[RFC mesa 3/4] wayland: Add new take_buffer and commit for wayland-egl

John Kåre Alsaker john.kare.alsaker at gmail.com
Sat Mar 2 17:26:13 PST 2013


---
 src/egl/drivers/dri2/platform_wayland.c        | 106 ++++++++++++++++++-------
 src/egl/wayland/wayland-egl/wayland-egl-priv.h |   2 +
 src/egl/wayland/wayland-egl/wayland-egl.c      |  22 +++++
 3 files changed, 102 insertions(+), 28 deletions(-)

diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index 56f5d3c..8797491 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -98,6 +98,12 @@ static struct wl_buffer_listener wl_buffer_listener = {
    wl_buffer_release
 };
 
+static struct wl_buffer *
+take_buffer(struct dri2_egl_surface *dri2_surf);
+
+static EGLBoolean
+commit_surface(struct dri2_egl_display *, struct dri2_egl_surface *dri2_surf);
+
 static void
 resize_callback(struct wl_egl_window *wl_win, void *data)
 {
@@ -108,6 +114,22 @@ resize_callback(struct wl_egl_window *wl_win, void *data)
    (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
 }
 
+static struct wl_buffer *
+take_buffer_callback(struct wl_egl_window *wl_win, void *data)
+{
+   return take_buffer(data);
+}
+
+static int
+commit_callback(struct wl_egl_window *wl_win, void *data)
+{
+   struct dri2_egl_surface *dri2_surf = data;
+   struct dri2_egl_display *dri2_dpy =
+      dri2_egl_display(dri2_surf->base.Resource.Display);
+
+   return commit_surface(dri2_dpy, dri2_surf) ? 0 : -1;
+}
+
 /**
  * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
  */
@@ -143,6 +165,8 @@ dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
 
       dri2_surf->wl_win->private = dri2_surf;
       dri2_surf->wl_win->resize_callback = resize_callback;
+      dri2_surf->wl_win->take_buffer_callback = take_buffer_callback;
+      dri2_surf->wl_win->commit_callback = commit_callback;
 
       dri2_surf->base.Width =  -1;
       dri2_surf->base.Height = -1;
@@ -221,6 +245,8 @@ dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
    if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
       dri2_surf->wl_win->private = NULL;
       dri2_surf->wl_win->resize_callback = NULL;
+      dri2_surf->wl_win->take_buffer_callback = NULL;
+      dri2_surf->wl_win->commit_callback = NULL;
    }
 
    free(surf);
@@ -438,16 +464,13 @@ static const struct wl_callback_listener frame_listener = {
 	wayland_frame_callback
 };
 
-/**
- * Called via eglSwapBuffers(), drv->API.SwapBuffers().
- */
-static EGLBoolean
-dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
+static struct wl_buffer *
+take_buffer(struct dri2_egl_surface *dri2_surf)
 {
-   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
-   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
    __DRIbuffer buffer;
-   int i, ret;
+   struct dri2_egl_display *dri2_dpy =
+      dri2_egl_display(dri2_surf->base.Resource.Display);
+   int i;
 
    for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
       if (dri2_surf->color_buffers[i].age > 0)
@@ -456,8 +479,7 @@ dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
    /* Make sure we have a back buffer in case we're swapping without ever
     * rendering. */
    if (get_back_bo(dri2_surf, &buffer) < 0) {
-      _eglError(EGL_BAD_ALLOC, "dri2_swap_buffers");
-      return EGL_FALSE;
+      return NULL;
    }
 
    dri2_surf->back->age = 1;
@@ -465,31 +487,30 @@ dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
    dri2_surf->back = NULL;
 
    if (dri2_surf->current->wl_buffer == NULL) {
-      dri2_surf->current->wl_buffer =
+      struct wl_buffer *result =
          wl_drm_create_buffer(dri2_dpy->wl_drm,
                               dri2_surf->current->dri_buffer->name,
                               dri2_surf->base.Width,
                               dri2_surf->base.Height,
                               dri2_surf->current->dri_buffer->pitch,
                               dri2_surf->format);
-      wl_proxy_set_queue((struct wl_proxy *) dri2_surf->current->wl_buffer,
-                         dri2_dpy->wl_queue);
-      wl_buffer_add_listener(dri2_surf->current->wl_buffer,
-                             &wl_buffer_listener, dri2_surf);
+      /* TODO: Handle the case where dri2_surf->current->wl_buffer is NULL */
+      wl_proxy_set_queue((struct wl_proxy *) result, dri2_dpy->wl_queue);
+      wl_buffer_add_listener(result, &wl_buffer_listener, dri2_surf);
+
+      dri2_surf->current->wl_buffer = result;
    }
 
-   wl_surface_attach(dri2_surf->wl_win->surface,
-                     dri2_surf->current->wl_buffer,
-                     dri2_surf->dx, dri2_surf->dy);
+   (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
+   (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
 
-   dri2_surf->wl_win->attached_width  = dri2_surf->base.Width;
-   dri2_surf->wl_win->attached_height = dri2_surf->base.Height;
-   /* reset resize growing parameters */
-   dri2_surf->dx = 0;
-   dri2_surf->dy = 0;
+   return dri2_surf->current->wl_buffer;
+}
 
-   wl_surface_damage(dri2_surf->wl_win->surface, 0, 0,
-                     dri2_surf->base.Width, dri2_surf->base.Height);
+static EGLBoolean
+commit_surface(struct dri2_egl_display *dri2_dpy, struct dri2_egl_surface *dri2_surf)
+{
+   int ret;
 
    dri2_surf->frame_callback = wl_surface_frame(dri2_surf->wl_win->surface);
    wl_callback_add_listener(dri2_surf->frame_callback,
@@ -499,9 +520,6 @@ dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
 
    wl_surface_commit(dri2_surf->wl_win->surface);
 
-   (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
-   (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
-
    ret = 0;
 
    while (dri2_surf->frame_callback && ret != -1)
@@ -512,6 +530,38 @@ dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
    return EGL_TRUE;
 }
 
+/**
+ * Called via eglSwapBuffers(), drv->API.SwapBuffers().
+ */
+static EGLBoolean
+dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
+   struct wl_buffer *wl_buffer;
+
+   wl_buffer = take_buffer(dri2_surf);
+
+   if (!wl_buffer) {
+      _eglError(EGL_BAD_ALLOC, "dri2_swap_buffers");
+      return EGL_FALSE;
+   }
+
+   wl_surface_attach(dri2_surf->wl_win->surface, wl_buffer,
+                     dri2_surf->dx, dri2_surf->dy);
+
+   dri2_surf->wl_win->attached_width  = dri2_surf->base.Width;
+   dri2_surf->wl_win->attached_height = dri2_surf->base.Height;
+   /* reset resize growing parameters */
+   dri2_surf->dx = 0;
+   dri2_surf->dy = 0;
+
+   wl_surface_damage(dri2_surf->wl_win->surface, 0, 0,
+                     dri2_surf->base.Width, dri2_surf->base.Height);
+
+   return commit_surface(dri2_dpy, dri2_surf);
+}
+
 static EGLint
 dri2_query_buffer_age(_EGLDriver *drv,
                       _EGLDisplay *disp, _EGLSurface *surface)
diff --git a/src/egl/wayland/wayland-egl/wayland-egl-priv.h b/src/egl/wayland/wayland-egl/wayland-egl-priv.h
index da25be9..901d2c7 100644
--- a/src/egl/wayland/wayland-egl/wayland-egl-priv.h
+++ b/src/egl/wayland/wayland-egl/wayland-egl-priv.h
@@ -27,6 +27,8 @@ struct wl_egl_window {
 
 	void *private;
 	void (*resize_callback)(struct wl_egl_window *, void *);
+	struct wl_buffer *(*take_buffer_callback)(struct wl_egl_window *, void *);
+	int (*commit_callback)(struct wl_egl_window *, void *);
 };
 
 #ifdef  __cplusplus
diff --git a/src/egl/wayland/wayland-egl/wayland-egl.c b/src/egl/wayland/wayland-egl/wayland-egl.c
index 8bd49cf..57b8262 100644
--- a/src/egl/wayland/wayland-egl/wayland-egl.c
+++ b/src/egl/wayland/wayland-egl/wayland-egl.c
@@ -31,6 +31,8 @@ wl_egl_window_create(struct wl_surface *surface,
 	egl_window->surface = surface;
 	egl_window->private = NULL;
 	egl_window->resize_callback = NULL;
+	egl_window->take_buffer_callback = NULL;
+	egl_window->commit_callback = NULL;
 	wl_egl_window_resize(egl_window, width, height, 0, 0);
 	egl_window->attached_width  = 0;
 	egl_window->attached_height = 0;
@@ -53,3 +55,23 @@ wl_egl_window_get_attached_size(struct wl_egl_window *egl_window,
 	if (height)
 		*height = egl_window->attached_height;
 }
+
+WL_EGL_EXPORT struct wl_buffer *
+wl_egl_window_take_buffer(struct wl_egl_window *egl_window)
+{
+	if (egl_window->take_buffer_callback)
+		return egl_window->take_buffer_callback(egl_window,
+							egl_window->private);
+	else
+		return NULL;
+}
+
+WL_EGL_EXPORT int
+wl_egl_window_commit(struct wl_egl_window *egl_window)
+{
+	if (egl_window->commit_callback)
+		return egl_window->commit_callback(egl_window,
+						   egl_window->private);
+	else
+		return -1;
+}
-- 
1.8.1.4



More information about the wayland-devel mailing list