From 4197bada4208f08e7a4a3fc684f858aa8ea53b09 Mon Sep 17 00:00:00 2001 From: nobled Date: Fri, 28 Jan 2011 16:49:07 +0000 Subject: [PATCH 01/16] fix ClutterContainer docs --- clutter/clutter-container.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clutter/clutter-container.h b/clutter/clutter-container.h index 2b5534dbe..b9cee5eda 100644 --- a/clutter/clutter-container.h +++ b/clutter/clutter-container.h @@ -80,8 +80,8 @@ typedef struct _ClutterContainerIface ClutterContainerIface; * @destroy_child_meta: virtual function that gets called when a child is * removed; it shuld release all resources held by the record * @get_child_meta: return the record for a container child - * @actor_added: class handler for #ClutterContainer::actor_added - * @actor_removed: class handler for #ClutterContainer::actor_removed + * @actor_added: class handler for #ClutterContainer::actor-added + * @actor_removed: class handler for #ClutterContainer::actor-removed * @child_notify: class handler for #ClutterContainer::child-notify * * Base interface for container actors. The @add, @remove and @foreach From 2a45ea6839eedc6f914d6192b02d6c0a78bfb212 Mon Sep 17 00:00:00 2001 From: nobled Date: Fri, 28 Jan 2011 16:50:06 +0000 Subject: [PATCH 02/16] wayland: fix connecting to default socket Fixes a mistake in commit "wayland: Update to current api" (e7f62bc936995c5d998f7c8dc4b2b1b7254ea97d) --- clutter/wayland/clutter-backend-wayland.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clutter/wayland/clutter-backend-wayland.c b/clutter/wayland/clutter-backend-wayland.c index ee8dac350..19eba1fd4 100644 --- a/clutter/wayland/clutter-backend-wayland.c +++ b/clutter/wayland/clutter-backend-wayland.c @@ -190,7 +190,7 @@ clutter_backend_wayland_post_parse (ClutterBackend *backend, g_atexit (clutter_backend_at_exit); /* TODO: expose environment variable/commandline option for this... */ - backend_wayland->wayland_display = wl_display_connect ("\0wayland"); + backend_wayland->wayland_display = wl_display_connect (NULL); if (!backend_wayland->wayland_display) { g_set_error (error, CLUTTER_INIT_ERROR, From 0886452dc241d18a1c6d4d787b06e61ea75a2b57 Mon Sep 17 00:00:00 2001 From: nobled Date: Fri, 28 Jan 2011 17:29:48 +0000 Subject: [PATCH 03/16] wayland: update to new api Adapt to changes from this Wayland commit: "Update surface.attach and change surface.map to surface.map_toplevel" (82da52b15b49da3f3c7b4bd85d334ddfaa375ebc) --- clutter/wayland/clutter-backend-wayland.c | 4 +--- clutter/wayland/clutter-stage-wayland.c | 10 ++++------ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/clutter/wayland/clutter-backend-wayland.c b/clutter/wayland/clutter-backend-wayland.c index 19eba1fd4..a08abdc21 100644 --- a/clutter/wayland/clutter-backend-wayland.c +++ b/clutter/wayland/clutter-backend-wayland.c @@ -111,7 +111,7 @@ static void handle_configure (void *data, struct wl_shell *shell, uint32_t timestamp, uint32_t edges, struct wl_surface *surface, - int32_t x, int32_t y, int32_t width, int32_t height) + int32_t width, int32_t height) { ClutterStageWayland *stage_wayland; @@ -123,8 +123,6 @@ handle_configure (void *data, struct wl_shell *shell, clutter_actor_queue_relayout (CLUTTER_ACTOR (stage_wayland->wrapper)); } - stage_wayland->pending_allocation.x = x; - stage_wayland->pending_allocation.y = y; stage_wayland->pending_allocation.width = width; stage_wayland->pending_allocation.height = height; stage_wayland->allocation = stage_wayland->pending_allocation; diff --git a/clutter/wayland/clutter-stage-wayland.c b/clutter/wayland/clutter-stage-wayland.c index 19c4b530b..dac3b63a6 100644 --- a/clutter/wayland/clutter-stage-wayland.c +++ b/clutter/wayland/clutter-stage-wayland.c @@ -361,12 +361,10 @@ wayland_swap_buffers (ClutterStageWayland *stage_wayland) stage_wayland->back_buffer = buffer; wl_surface_attach (stage_wayland->wayland_surface, - stage_wayland->front_buffer->wayland_buffer); - wl_surface_map (stage_wayland->wayland_surface, - stage_wayland->allocation.x, - stage_wayland->allocation.y, - stage_wayland->allocation.width, - stage_wayland->allocation.height); + stage_wayland->front_buffer->wayland_buffer, + /* 0,0 here is "relative to the old buffer," not absolute */ + 0, 0); + wl_surface_map_toplevel (stage_wayland->wayland_surface); stage_wayland->pending_swaps++; wl_display_frame_callback (backend_wayland->wayland_display, From 9dcb9453ede3ff435ddaf492123a25ad128630e3 Mon Sep 17 00:00:00 2001 From: nobled Date: Sun, 30 Jan 2011 22:06:23 +0000 Subject: [PATCH 04/16] wayland: use EGL_NO_SURFACE --- clutter/wayland/clutter-backend-wayland.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clutter/wayland/clutter-backend-wayland.c b/clutter/wayland/clutter-backend-wayland.c index a08abdc21..2ad0fbdfe 100644 --- a/clutter/wayland/clutter-backend-wayland.c +++ b/clutter/wayland/clutter-backend-wayland.c @@ -310,8 +310,8 @@ try_create_context (ClutterBackend *backend, } if (!eglMakeCurrent (backend_wayland->edpy, - NULL, - NULL, + EGL_NO_SURFACE, + EGL_NO_SURFACE, backend_wayland->egl_context)) { g_set_error (error, CLUTTER_INIT_ERROR, From 542717e45b7279e220e033069a6712693eafa49d Mon Sep 17 00:00:00 2001 From: nobled Date: Sun, 30 Jan 2011 22:18:55 +0000 Subject: [PATCH 05/16] wayland: fix GLES context creation It was unconditionally binding the desktop-GL API and requesting the wrong API version in the case of GLES1. --- clutter/wayland/clutter-backend-wayland.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/clutter/wayland/clutter-backend-wayland.c b/clutter/wayland/clutter-backend-wayland.c index 2ad0fbdfe..1ba958a61 100644 --- a/clutter/wayland/clutter-backend-wayland.c +++ b/clutter/wayland/clutter-backend-wayland.c @@ -275,6 +275,12 @@ clutter_backend_wayland_post_parse (ClutterBackend *backend, return TRUE; } +#if defined(HAVE_COGL_GLES2) +#define _COGL_GLES_VERSION 2 +#elif defined(HAVE_COGL_GLES) +#define _COGL_GLES_VERSION 1 +#endif + static gboolean try_create_context (ClutterBackend *backend, int retry_cookie, @@ -283,16 +289,19 @@ try_create_context (ClutterBackend *backend, { ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); const char *error_message; - +#if defined(HAVE_COGL_GL) eglBindAPI (EGL_OPENGL_API); +#else + eglBindAPI (EGL_OPENGL_ES_API); +#endif if (backend_wayland->egl_context == EGL_NO_CONTEXT) { -#if defined (HAVE_COGL_GLES2) - static const EGLint attribs[] = - { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; -#else +#if defined(HAVE_COGL_GL) static const EGLint *attribs = NULL; +#else + static const EGLint attribs[] = + { EGL_CONTEXT_CLIENT_VERSION, _COGL_GLES_VERSION, EGL_NONE }; #endif backend_wayland->egl_context = From ffd7197dd6679e539b2ede0bdd401f57461113d5 Mon Sep 17 00:00:00 2001 From: nobled Date: Sun, 30 Jan 2011 22:22:10 +0000 Subject: [PATCH 06/16] wayland: check for API-specific surfaceless extension It's a whole different extension name for each GL api. --- clutter/wayland/clutter-backend-wayland.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/clutter/wayland/clutter-backend-wayland.c b/clutter/wayland/clutter-backend-wayland.c index 1ba958a61..dd26b4aa4 100644 --- a/clutter/wayland/clutter-backend-wayland.c +++ b/clutter/wayland/clutter-backend-wayland.c @@ -341,6 +341,14 @@ fail: } } +#if defined(HAVE_COGL_GL) +#define _COGL_SURFACELESS_EXTENSION "EGL_KHR_surfaceless_opengl" +#elif defined(HAVE_COGL_GLES) +#define _COGL_SURFACELESS_EXTENSION "EGL_KHR_surfaceless_gles1" +#elif defined(HAVE_COGL_GLES2) +#define _COGL_SURFACELESS_EXTENSION "EGL_KHR_surfaceless_gles2" +#endif + static gboolean clutter_backend_wayland_create_context (ClutterBackend *backend, GError **error) @@ -357,12 +365,12 @@ clutter_backend_wayland_create_context (ClutterBackend *backend, egl_extensions = eglQueryString (backend_wayland->edpy, EGL_EXTENSIONS); - if (!_cogl_check_extension ("EGL_KHR_surfaceless_opengl", egl_extensions)) + if (!_cogl_check_extension (_COGL_SURFACELESS_EXTENSION, egl_extensions)) { g_set_error (error, CLUTTER_INIT_ERROR, CLUTTER_INIT_ERROR_BACKEND, "Wayland clients require the " - "EGL_KHR_surfaceless_opengl extension"); + _COGL_SURFACELESS_EXTENSION " extension"); return FALSE; } From 7e4a8fd907d728d4daa7bd0c124a22e86659fc7b Mon Sep 17 00:00:00 2001 From: nobled Date: Sun, 30 Jan 2011 22:43:50 +0000 Subject: [PATCH 07/16] wayland: don't require the surfaceless extensions Just create a one-pixel dummy surface for eglMakeCurrent(). --- clutter/wayland/clutter-backend-wayland.c | 62 ++++++++++++++++++----- clutter/wayland/clutter-backend-wayland.h | 1 + 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/clutter/wayland/clutter-backend-wayland.c b/clutter/wayland/clutter-backend-wayland.c index dd26b4aa4..2fede4c1e 100644 --- a/clutter/wayland/clutter-backend-wayland.c +++ b/clutter/wayland/clutter-backend-wayland.c @@ -275,6 +275,31 @@ clutter_backend_wayland_post_parse (ClutterBackend *backend, return TRUE; } +static gboolean +make_dummy_surface (ClutterBackendWayland *backend_wayland) +{ + static const EGLint attrs[] = { + EGL_WIDTH, 1, + EGL_HEIGHT, 1, + EGL_NONE }; + EGLint num_configs; + + eglGetConfigs(backend_wayland->edpy, + &backend_wayland->egl_config, 1, &num_configs); + if (num_configs < 1) + return FALSE; + + backend_wayland->egl_surface = + eglCreatePbufferSurface(backend_wayland->edpy, + backend_wayland->egl_config, + attrs); + + if (backend_wayland->egl_surface == EGL_NO_SURFACE) + return FALSE; + + return TRUE; +} + #if defined(HAVE_COGL_GLES2) #define _COGL_GLES_VERSION 2 #elif defined(HAVE_COGL_GLES) @@ -289,11 +314,6 @@ try_create_context (ClutterBackend *backend, { ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); const char *error_message; -#if defined(HAVE_COGL_GL) - eglBindAPI (EGL_OPENGL_API); -#else - eglBindAPI (EGL_OPENGL_ES_API); -#endif if (backend_wayland->egl_context == EGL_NO_CONTEXT) { @@ -306,7 +326,7 @@ try_create_context (ClutterBackend *backend, backend_wayland->egl_context = eglCreateContext (backend_wayland->edpy, - NULL, + backend_wayland->egl_config, EGL_NO_CONTEXT, attribs); if (backend_wayland->egl_context == EGL_NO_CONTEXT) @@ -319,13 +339,13 @@ try_create_context (ClutterBackend *backend, } if (!eglMakeCurrent (backend_wayland->edpy, - EGL_NO_SURFACE, - EGL_NO_SURFACE, + backend_wayland->egl_surface, + backend_wayland->egl_surface, backend_wayland->egl_context)) { g_set_error (error, CLUTTER_INIT_ERROR, CLUTTER_INIT_ERROR_BACKEND, - "Unable to MakeCurrent with NULL drawables"); + "Unable to MakeCurrent"); return FALSE; } @@ -363,15 +383,29 @@ clutter_backend_wayland_create_context (ClutterBackend *backend, if (backend_wayland->egl_context != EGL_NO_CONTEXT) return TRUE; +#if defined(HAVE_COGL_GL) + eglBindAPI (EGL_OPENGL_API); +#else + eglBindAPI (EGL_OPENGL_ES_API); +#endif egl_extensions = eglQueryString (backend_wayland->edpy, EGL_EXTENSIONS); if (!_cogl_check_extension (_COGL_SURFACELESS_EXTENSION, egl_extensions)) { - g_set_error (error, CLUTTER_INIT_ERROR, - CLUTTER_INIT_ERROR_BACKEND, - "Wayland clients require the " - _COGL_SURFACELESS_EXTENSION " extension"); - return FALSE; + g_debug("Could not find the " _COGL_SURFACELESS_EXTENSION + " extension; falling back to binding a dummy surface"); + if (!make_dummy_surface(backend_wayland)) + { + g_set_error (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_BACKEND, + "Could not create dummy surface"); + return FALSE; + } + } + else + { + backend_wayland->egl_config = NULL; + backend_wayland->egl_surface = EGL_NO_SURFACE; } retry_cookie = 0; diff --git a/clutter/wayland/clutter-backend-wayland.h b/clutter/wayland/clutter-backend-wayland.h index d243cee9c..1d3f3d49e 100644 --- a/clutter/wayland/clutter-backend-wayland.h +++ b/clutter/wayland/clutter-backend-wayland.h @@ -57,6 +57,7 @@ struct _ClutterBackendWayland EGLDisplay edpy; EGLContext egl_context; EGLConfig egl_config; + EGLSurface egl_surface; gint egl_version_major; gint egl_version_minor; From f6a6a44fe7e7561558a375b780ba17b0dfa1e842 Mon Sep 17 00:00:00 2001 From: nobled Date: Mon, 31 Jan 2011 02:14:17 +0000 Subject: [PATCH 08/16] wayland: clean up buffer creation code The height was being set from the ClutterGeometry in some parts and from the stage in others. And since both callers of this function pass &stage_wayland->allocation as the geometry anyway, the stage argument isn't really even needed. --- clutter/wayland/clutter-stage-wayland.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/clutter/wayland/clutter-stage-wayland.c b/clutter/wayland/clutter-stage-wayland.c index dac3b63a6..6011b9d40 100644 --- a/clutter/wayland/clutter-stage-wayland.c +++ b/clutter/wayland/clutter-stage-wayland.c @@ -60,8 +60,7 @@ G_DEFINE_TYPE_WITH_CODE (ClutterStageWayland, clutter_stage_window_iface_init)); static ClutterStageWaylandWaylandBuffer * -wayland_create_buffer (ClutterStageWayland *stage_wayland, - ClutterGeometry *geom) +wayland_create_buffer (ClutterGeometry *geom) { ClutterBackend *backend = clutter_get_default_backend (); ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); @@ -104,8 +103,8 @@ wayland_create_buffer (ClutterStageWayland *stage_wayland, buffer->wayland_buffer = wl_drm_create_buffer (backend_wayland->wayland_drm, name, - stage_wayland->allocation.width, - stage_wayland->allocation.height, + geom->width, + geom->height, stride, visual); rect.x = geom->x; @@ -171,7 +170,7 @@ clutter_stage_wayland_realize (ClutterStageWindow *stage_window) wl_surface_set_user_data (stage_wayland->wayland_surface, stage_wayland); stage_wayland->pick_buffer = - wayland_create_buffer (stage_wayland, &stage_wayland->allocation); + wayland_create_buffer (&stage_wayland->allocation); return TRUE; } @@ -502,7 +501,7 @@ _clutter_stage_wayland_redraw (ClutterStageWayland *stage_wayland, if (!stage_wayland->back_buffer) stage_wayland->back_buffer = - wayland_create_buffer (stage_wayland, &stage_wayland->allocation); + wayland_create_buffer (&stage_wayland->allocation); cogl_set_framebuffer (stage_wayland->back_buffer->offscreen); _clutter_stage_maybe_setup_viewport (stage_wayland->wrapper); From 2ff5cf5aa0178e921203a220e64645ae2f705de2 Mon Sep 17 00:00:00 2001 From: nobled Date: Mon, 31 Jan 2011 02:27:23 +0000 Subject: [PATCH 09/16] wayland: fix pixel format This matches to the Wayland premultiplied_argb_visual the rest of the code is using. The format needs to differ based on endianness, though... --- clutter/wayland/clutter-stage-wayland.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clutter/wayland/clutter-stage-wayland.c b/clutter/wayland/clutter-stage-wayland.c index 6011b9d40..958feeca4 100644 --- a/clutter/wayland/clutter-stage-wayland.c +++ b/clutter/wayland/clutter-stage-wayland.c @@ -93,7 +93,7 @@ wayland_create_buffer (ClutterGeometry *geom) geom->height, 0, 0, - COGL_PIXEL_FORMAT_ARGB_8888); + COGL_PIXEL_FORMAT_ARGB_8888_PRE); buffer->offscreen = cogl_offscreen_new_to_texture (buffer->tex); backend_wayland->export_drm_image (edpy, buffer->drm_image, From 15cd4705dbd51025e452810a873e2010bee494b9 Mon Sep 17 00:00:00 2001 From: nobled Date: Mon, 31 Jan 2011 02:45:01 +0000 Subject: [PATCH 10/16] wayland: really fix buffer format selection Wayland visuals refer to a pixel's bytes in order from most significant to least significant, while the one-byte-per-component Cogl formats refer to the order of increasing memory addresses, so converting between the two depends on the system's endianness. --- clutter/wayland/clutter-stage-wayland.c | 31 ++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/clutter/wayland/clutter-stage-wayland.c b/clutter/wayland/clutter-stage-wayland.c index 958feeca4..1843fc81c 100644 --- a/clutter/wayland/clutter-stage-wayland.c +++ b/clutter/wayland/clutter-stage-wayland.c @@ -59,6 +59,32 @@ G_DEFINE_TYPE_WITH_CODE (ClutterStageWayland, G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW, clutter_stage_window_iface_init)); +#if G_BYTE_ORDER == G_BIG_ENDIAN +#define VISUAL_ARGB_PRE COGL_PIXEL_FORMAT_ARGB_8888_PRE +#define VISUAL_ARGB COGL_PIXEL_FORMAT_ARGB_8888 +#define VISUAL_RGB COGL_PIXEL_FORMAT_RGB_888 +#elif G_BYTE_ORDER == G_LITTLE_ENDIAN +#define VISUAL_ARGB_PRE COGL_PIXEL_FORMAT_BGRA_8888_PRE +#define VISUAL_ARGB COGL_PIXEL_FORMAT_BGRA_8888 +#define VISUAL_RGB COGL_PIXEL_FORMAT_BGR_888 +#endif + +static struct wl_visual * +get_visual (struct wl_display *display, CoglPixelFormat format) +{ + switch (format) + { + case VISUAL_ARGB_PRE: + return wl_display_get_premultiplied_argb_visual (display); + case VISUAL_ARGB: + return wl_display_get_argb_visual (display); + case VISUAL_RGB: + return wl_display_get_rgb_visual (display); + default: + return NULL; + } +} + static ClutterStageWaylandWaylandBuffer * wayland_create_buffer (ClutterGeometry *geom) { @@ -93,13 +119,12 @@ wayland_create_buffer (ClutterGeometry *geom) geom->height, 0, 0, - COGL_PIXEL_FORMAT_ARGB_8888_PRE); + VISUAL_ARGB_PRE); buffer->offscreen = cogl_offscreen_new_to_texture (buffer->tex); backend_wayland->export_drm_image (edpy, buffer->drm_image, &name, NULL, &stride); - visual = - wl_display_get_premultiplied_argb_visual (backend_wayland->wayland_display); + visual = get_visual (backend_wayland->wayland_display, VISUAL_ARGB_PRE); buffer->wayland_buffer = wl_drm_create_buffer (backend_wayland->wayland_drm, name, From d4ccef786b4cf5b1885f51c2aa2fca43095f1a75 Mon Sep 17 00:00:00 2001 From: nobled Date: Mon, 31 Jan 2011 03:07:37 +0000 Subject: [PATCH 11/16] wayland: make buffer handling generic Separate the code specific to DRM buffers into its own functions/subclass to prepare for adding SHM buffers. --- clutter/wayland/clutter-stage-wayland.c | 56 ++++++++++++++++++------- clutter/wayland/clutter-stage-wayland.h | 12 +++++- 2 files changed, 50 insertions(+), 18 deletions(-) diff --git a/clutter/wayland/clutter-stage-wayland.c b/clutter/wayland/clutter-stage-wayland.c index 1843fc81c..521bea2e5 100644 --- a/clutter/wayland/clutter-stage-wayland.c +++ b/clutter/wayland/clutter-stage-wayland.c @@ -86,12 +86,13 @@ get_visual (struct wl_display *display, CoglPixelFormat format) } static ClutterStageWaylandWaylandBuffer * -wayland_create_buffer (ClutterGeometry *geom) +wayland_create_drm_buffer (ClutterBackendWayland *backend_wayland, + ClutterGeometry *geom) { - ClutterBackend *backend = clutter_get_default_backend (); - ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); EGLDisplay edpy = clutter_wayland_get_egl_display (); - ClutterStageWaylandWaylandBuffer *buffer; + struct wl_visual *visual; + EGLint name, stride; + ClutterStageWaylandWaylandBufferDRM *buffer; EGLint image_attribs[] = { EGL_WIDTH, 0, EGL_HEIGHT, 0, @@ -99,12 +100,10 @@ wayland_create_buffer (ClutterGeometry *geom) EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SCANOUT_MESA, EGL_NONE }; - struct wl_visual *visual; - EGLint name; - EGLint stride; - cairo_rectangle_int_t rect; - buffer = g_slice_new (ClutterStageWaylandWaylandBuffer); + buffer = g_slice_new (ClutterStageWaylandWaylandBufferDRM); + + buffer->buffer.type = BUFFER_TYPE_DRM; image_attribs[1] = geom->width; image_attribs[3] = geom->height; @@ -113,25 +112,39 @@ wayland_create_buffer (ClutterGeometry *geom) glBindTexture (GL_TEXTURE_2D, buffer->texture); backend_wayland->image_target_texture_2d (GL_TEXTURE_2D, buffer->drm_image); - buffer->tex = cogl_texture_new_from_foreign (buffer->texture, + buffer->buffer.tex = cogl_texture_new_from_foreign (buffer->texture, GL_TEXTURE_2D, geom->width, geom->height, 0, 0, VISUAL_ARGB_PRE); - buffer->offscreen = cogl_offscreen_new_to_texture (buffer->tex); backend_wayland->export_drm_image (edpy, buffer->drm_image, &name, NULL, &stride); visual = get_visual (backend_wayland->wayland_display, VISUAL_ARGB_PRE); - buffer->wayland_buffer = + buffer->buffer.wayland_buffer = wl_drm_create_buffer (backend_wayland->wayland_drm, name, geom->width, geom->height, stride, visual); + return &buffer->buffer; +} + +static ClutterStageWaylandWaylandBuffer * +wayland_create_buffer (ClutterGeometry *geom) +{ + ClutterBackend *backend = clutter_get_default_backend (); + ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); + ClutterStageWaylandWaylandBuffer *buffer; + cairo_rectangle_int_t rect; + + buffer = wayland_create_drm_buffer (backend_wayland, geom); + + buffer->offscreen = cogl_offscreen_new_to_texture (buffer->tex); + rect.x = geom->x; rect.y = geom->y; rect.width = geom->width; @@ -142,18 +155,29 @@ wayland_create_buffer (ClutterGeometry *geom) } static void -wayland_free_buffer (ClutterStageWaylandWaylandBuffer *buffer) +wayland_free_drm_buffer (ClutterStageWaylandWaylandBuffer *generic_buffer) { ClutterBackend *backend = clutter_get_default_backend (); ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); EGLDisplay edpy = clutter_wayland_get_egl_display (); + ClutterStageWaylandWaylandBufferDRM *buffer; + buffer = (ClutterStageWaylandWaylandBufferDRM *)generic_buffer; + + glDeleteTextures (1, &buffer->texture); + backend_wayland->destroy_image (edpy, buffer->drm_image); + g_slice_free (ClutterStageWaylandWaylandBufferDRM, buffer); +} + +static void +wayland_free_buffer (ClutterStageWaylandWaylandBuffer *buffer) +{ cogl_handle_unref (buffer->tex); wl_buffer_destroy (buffer->wayland_buffer); cogl_handle_unref (buffer->offscreen); - glDeleteTextures (1, &buffer->texture); - backend_wayland->destroy_image (edpy, buffer->drm_image); - g_slice_free (ClutterStageWaylandWaylandBuffer, buffer); + + if (buffer->type == BUFFER_TYPE_DRM) + wayland_free_drm_buffer(buffer); } static void diff --git a/clutter/wayland/clutter-stage-wayland.h b/clutter/wayland/clutter-stage-wayland.h index 2c44f38fa..ebf1ecb8c 100644 --- a/clutter/wayland/clutter-stage-wayland.h +++ b/clutter/wayland/clutter-stage-wayland.h @@ -51,16 +51,24 @@ typedef struct _ClutterStageWayland ClutterStageWayland; typedef struct _ClutterStageWaylandClass ClutterStageWaylandClass; +#define BUFFER_TYPE_DRM 1 + typedef struct _ClutterStageWaylandWaylandBuffer { - EGLImageKHR drm_image; - GLuint texture; CoglHandle offscreen; struct wl_buffer *wayland_buffer; cairo_region_t *dirty_region; CoglHandle tex; + guint8 type; } ClutterStageWaylandWaylandBuffer; +typedef struct _ClutterStageWaylandWaylandBufferDRM +{ + ClutterStageWaylandWaylandBuffer buffer; + EGLImageKHR drm_image; + GLuint texture; +} ClutterStageWaylandWaylandBufferDRM; + struct _ClutterStageWayland { GObject parent_instance; From d84f31ef3a9ad56463b34af74a4a5f68ef0621a4 Mon Sep 17 00:00:00 2001 From: nobled Date: Mon, 31 Jan 2011 04:22:50 +0000 Subject: [PATCH 12/16] wayland: add shm buffer code It's not enabled to do anything yet. --- clutter/wayland/clutter-backend-wayland.c | 4 ++ clutter/wayland/clutter-backend-wayland.h | 1 + clutter/wayland/clutter-stage-wayland.c | 62 +++++++++++++++++++++++ clutter/wayland/clutter-stage-wayland.h | 8 +++ 4 files changed, 75 insertions(+) diff --git a/clutter/wayland/clutter-backend-wayland.c b/clutter/wayland/clutter-backend-wayland.c index 2fede4c1e..662a0caed 100644 --- a/clutter/wayland/clutter-backend-wayland.c +++ b/clutter/wayland/clutter-backend-wayland.c @@ -175,6 +175,10 @@ display_handle_global (struct wl_display *display, wl_drm_add_listener (backend_wayland->wayland_drm, &drm_listener, backend_wayland); } + else if (strcmp (interface, "shm") == 0) + { + backend_wayland->wayland_shm = wl_shm_create (display, id); + } } static gboolean diff --git a/clutter/wayland/clutter-backend-wayland.h b/clutter/wayland/clutter-backend-wayland.h index 1d3f3d49e..b9174b8d2 100644 --- a/clutter/wayland/clutter-backend-wayland.h +++ b/clutter/wayland/clutter-backend-wayland.h @@ -67,6 +67,7 @@ struct _ClutterBackendWayland struct wl_compositor *wayland_compositor; struct wl_shell *wayland_shell; struct wl_drm *wayland_drm; + struct wl_shm *wayland_shm; char *device_name; int authenticated; struct wl_output *wayland_output; diff --git a/clutter/wayland/clutter-stage-wayland.c b/clutter/wayland/clutter-stage-wayland.c index 521bea2e5..d51634169 100644 --- a/clutter/wayland/clutter-stage-wayland.c +++ b/clutter/wayland/clutter-stage-wayland.c @@ -28,7 +28,12 @@ #include "config.h" #endif +#include +#include +#include #include +#include +#include #include #include #include @@ -84,6 +89,50 @@ get_visual (struct wl_display *display, CoglPixelFormat format) return NULL; } } +static ClutterStageWaylandWaylandBuffer * +wayland_create_shm_buffer (ClutterBackendWayland *backend_wayland, + ClutterGeometry *geom) +{ + ClutterStageWaylandWaylandBufferSHM *buffer; + struct wl_visual *visual; + CoglTextureFlags flags = COGL_TEXTURE_NONE; /* XXX: tweak flags? */ + CoglPixelFormat format = VISUAL_ARGB_PRE; + unsigned int stride; + int fd; + gchar tmp[] = "/tmp/clutter-wayland-shm-XXXXXX"; + + buffer = g_slice_new (ClutterStageWaylandWaylandBufferSHM); + + buffer->buffer.type = BUFFER_TYPE_SHM; + + /* XXX: can we query Cogl for what the stride should + be for a given format and width? */ + stride = geom->width; + buffer->size = stride * geom->height; + + fd = g_mkstemp_full(tmp, O_RDWR, 0600); + ftruncate(fd, buffer->size); + buffer->data = mmap(NULL, buffer->size, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0); + + g_unlink(tmp); + + buffer->buffer.tex = cogl_texture_new_from_data ((unsigned int)geom->width, + (unsigned int)geom->height, + flags, format, + COGL_PIXEL_FORMAT_ANY, + stride, buffer->data); + + visual = get_visual (backend_wayland->wayland_display, format); + buffer->buffer.wayland_buffer = + wl_shm_create_buffer (backend_wayland->wayland_shm, + fd, + geom->width, + geom->height, + stride, visual); + close(fd); + return &buffer->buffer; +} static ClutterStageWaylandWaylandBuffer * wayland_create_drm_buffer (ClutterBackendWayland *backend_wayland, @@ -154,6 +203,17 @@ wayland_create_buffer (ClutterGeometry *geom) return buffer; } +static void +wayland_free_shm_buffer (ClutterStageWaylandWaylandBuffer *generic_buffer) +{ + ClutterStageWaylandWaylandBufferSHM *buffer; + + buffer = (ClutterStageWaylandWaylandBufferSHM *)generic_buffer; + + munmap(buffer->data, buffer->size); + g_slice_free (ClutterStageWaylandWaylandBufferSHM, buffer); +} + static void wayland_free_drm_buffer (ClutterStageWaylandWaylandBuffer *generic_buffer) { @@ -178,6 +238,8 @@ wayland_free_buffer (ClutterStageWaylandWaylandBuffer *buffer) if (buffer->type == BUFFER_TYPE_DRM) wayland_free_drm_buffer(buffer); + else if (buffer->type == BUFFER_TYPE_SHM) + wayland_free_shm_buffer(buffer); } static void diff --git a/clutter/wayland/clutter-stage-wayland.h b/clutter/wayland/clutter-stage-wayland.h index ebf1ecb8c..be7b915a6 100644 --- a/clutter/wayland/clutter-stage-wayland.h +++ b/clutter/wayland/clutter-stage-wayland.h @@ -52,6 +52,7 @@ typedef struct _ClutterStageWayland ClutterStageWayland; typedef struct _ClutterStageWaylandClass ClutterStageWaylandClass; #define BUFFER_TYPE_DRM 1 +#define BUFFER_TYPE_SHM 2 typedef struct _ClutterStageWaylandWaylandBuffer { @@ -69,6 +70,13 @@ typedef struct _ClutterStageWaylandWaylandBufferDRM GLuint texture; } ClutterStageWaylandWaylandBufferDRM; +typedef struct _ClutterStageWaylandWaylandBufferSHM +{ + ClutterStageWaylandWaylandBuffer buffer; + guint8 *data; + size_t size; +} ClutterStageWaylandWaylandBufferSHM; + struct _ClutterStageWayland { GObject parent_instance; From e855bc45a266ab72ac1545fadf506d0ae0128c50 Mon Sep 17 00:00:00 2001 From: nobled Date: Mon, 31 Jan 2011 05:05:28 +0000 Subject: [PATCH 13/16] wayland: fall back to shm buffers if drm fails --- clutter/wayland/clutter-backend-wayland.c | 74 ++++++++++++++--------- clutter/wayland/clutter-backend-wayland.h | 1 + clutter/wayland/clutter-stage-wayland.c | 8 ++- 3 files changed, 54 insertions(+), 29 deletions(-) diff --git a/clutter/wayland/clutter-backend-wayland.c b/clutter/wayland/clutter-backend-wayland.c index 662a0caed..1763c1359 100644 --- a/clutter/wayland/clutter-backend-wayland.c +++ b/clutter/wayland/clutter-backend-wayland.c @@ -182,37 +182,10 @@ display_handle_global (struct wl_display *display, } static gboolean -clutter_backend_wayland_post_parse (ClutterBackend *backend, - GError **error) +try_enable_drm (ClutterBackendWayland *backend_wayland, GError **error) { - ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); - EGLBoolean status; drm_magic_t magic; - g_atexit (clutter_backend_at_exit); - - /* TODO: expose environment variable/commandline option for this... */ - backend_wayland->wayland_display = wl_display_connect (NULL); - if (!backend_wayland->wayland_display) - { - g_set_error (error, CLUTTER_INIT_ERROR, - CLUTTER_INIT_ERROR_BACKEND, - "Failed to open Wayland display socket"); - return FALSE; - } - - backend_wayland->wayland_source = - _clutter_event_source_wayland_new (backend_wayland->wayland_display); - g_source_attach (backend_wayland->wayland_source, NULL); - - /* Set up listener so we'll catch all events. */ - wl_display_add_global_listener (backend_wayland->wayland_display, - display_handle_global, - backend_wayland); - - /* Process connection events. */ - wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_READABLE); - backend_wayland->drm_fd = open (backend_wayland->device_name, O_RDWR); if (backend_wayland->drm_fd < 0) { @@ -261,6 +234,51 @@ clutter_backend_wayland_post_parse (ClutterBackend *backend, backend_wayland->edpy = backend_wayland->get_drm_display (backend_wayland->drm_fd); + return TRUE; +}; + +static gboolean +clutter_backend_wayland_post_parse (ClutterBackend *backend, + GError **error) +{ + ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); + EGLBoolean status; + + g_atexit (clutter_backend_at_exit); + + /* TODO: expose environment variable/commandline option for this... */ + backend_wayland->wayland_display = wl_display_connect (NULL); + if (!backend_wayland->wayland_display) + { + g_set_error (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_BACKEND, + "Failed to open Wayland display socket"); + return FALSE; + } + + backend_wayland->wayland_source = + _clutter_event_source_wayland_new (backend_wayland->wayland_display); + g_source_attach (backend_wayland->wayland_source, NULL); + + /* Set up listener so we'll catch all events. */ + wl_display_add_global_listener (backend_wayland->wayland_display, + display_handle_global, + backend_wayland); + + /* Process connection events. */ + wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_READABLE); + + backend_wayland->drm_enabled = try_enable_drm(backend_wayland, error); + + if (!backend_wayland->drm_enabled) { + if (backend_wayland->wayland_shm == NULL) + return FALSE; + + g_debug("Could not enable DRM buffers, falling back to SHM buffers"); + g_clear_error(error); + backend_wayland->edpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); + } + status = eglInitialize (backend_wayland->edpy, &backend_wayland->egl_version_major, &backend_wayland->egl_version_minor); diff --git a/clutter/wayland/clutter-backend-wayland.h b/clutter/wayland/clutter-backend-wayland.h index b9174b8d2..c36ecab84 100644 --- a/clutter/wayland/clutter-backend-wayland.h +++ b/clutter/wayland/clutter-backend-wayland.h @@ -73,6 +73,7 @@ struct _ClutterBackendWayland struct wl_output *wayland_output; ClutterGeometry screen_allocation; int drm_fd; + gboolean drm_enabled; PFNEGLGETDRMDISPLAYMESA get_drm_display; PFNEGLCREATEDRMIMAGEMESA create_drm_image; diff --git a/clutter/wayland/clutter-stage-wayland.c b/clutter/wayland/clutter-stage-wayland.c index d51634169..e9ef0be1b 100644 --- a/clutter/wayland/clutter-stage-wayland.c +++ b/clutter/wayland/clutter-stage-wayland.c @@ -190,7 +190,13 @@ wayland_create_buffer (ClutterGeometry *geom) ClutterStageWaylandWaylandBuffer *buffer; cairo_rectangle_int_t rect; - buffer = wayland_create_drm_buffer (backend_wayland, geom); + if (backend_wayland->drm_enabled && + backend_wayland->wayland_drm != NULL) + buffer = wayland_create_drm_buffer (backend_wayland, geom); + else if (backend_wayland->wayland_shm != NULL) + buffer = wayland_create_shm_buffer (backend_wayland, geom); + else + return NULL; buffer->offscreen = cogl_offscreen_new_to_texture (buffer->tex); From 20b1350614cab53c2ded828cdffc96db3c083ddd Mon Sep 17 00:00:00 2001 From: nobled Date: Tue, 8 Feb 2011 15:45:39 +0000 Subject: [PATCH 14/16] wayland: check for egl extensions explicitly eglGetProcAddress() returns non-null function pointers whether or not they're actually supported by the driver, since it can be used before any driver gets loaded. So we have to check if the extensions are advertised first, which requires having an initialized display, so we split the display creation code into its own function. The exception to extension-checking is EGL_MESA_drm_display, since by definition it's needed before any display is even created. --- clutter/wayland/clutter-backend-wayland.c | 115 +++++++++++++++------- 1 file changed, 78 insertions(+), 37 deletions(-) diff --git a/clutter/wayland/clutter-backend-wayland.c b/clutter/wayland/clutter-backend-wayland.c index 1763c1359..c96a24597 100644 --- a/clutter/wayland/clutter-backend-wayland.c +++ b/clutter/wayland/clutter-backend-wayland.c @@ -181,12 +181,43 @@ display_handle_global (struct wl_display *display, } } +static gboolean +try_get_display (ClutterBackendWayland *backend_wayland, GError **error) +{ + EGLDisplay edpy = EGL_NO_DISPLAY; + int drm_fd; + + drm_fd = open (backend_wayland->device_name, O_RDWR); + + backend_wayland->get_drm_display = + (PFNEGLGETDRMDISPLAYMESA) eglGetProcAddress ("eglGetDRMDisplayMESA"); + + if (backend_wayland->get_drm_display != NULL && drm_fd >= 0) + edpy = backend_wayland->get_drm_display (drm_fd); + + if (edpy == EGL_NO_DISPLAY) + edpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); + + if (edpy == EGL_NO_DISPLAY) + { + g_set_error (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_BACKEND, + "Failed to open EGLDisplay"); + return FALSE; + } + + backend_wayland->edpy = edpy; + backend_wayland->drm_fd = drm_fd; + + return TRUE; +} + static gboolean try_enable_drm (ClutterBackendWayland *backend_wayland, GError **error) { drm_magic_t magic; + const gchar *exts, *glexts; - backend_wayland->drm_fd = open (backend_wayland->device_name, O_RDWR); if (backend_wayland->drm_fd < 0) { g_set_error (error, CLUTTER_INIT_ERROR, @@ -195,6 +226,39 @@ try_enable_drm (ClutterBackendWayland *backend_wayland, GError **error) return FALSE; } + glexts = glGetString(GL_EXTENSIONS); + exts = eglQueryString (backend_wayland->edpy, EGL_EXTENSIONS); + + if (!_cogl_check_extension ("EGL_KHR_image_base", exts) || + !_cogl_check_extension ("EGL_MESA_drm_image", exts) || + !_cogl_check_extension ("GL_OES_EGL_image", glexts)) + { + g_set_error (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_BACKEND, + "Missing EGL extensions"); + return FALSE; + } + + backend_wayland->create_drm_image = + (PFNEGLCREATEDRMIMAGEMESA) eglGetProcAddress ("eglCreateDRMImageMESA"); + backend_wayland->destroy_image = + (PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress ("eglDestroyImageKHR"); + backend_wayland->export_drm_image = + (PFNEGLEXPORTDRMIMAGEMESA) eglGetProcAddress ("eglExportDRMImageMESA"); + backend_wayland->image_target_texture_2d = + (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) eglGetProcAddress ("glEGLImageTargetTexture2DOES"); + + if (backend_wayland->create_drm_image == NULL || + backend_wayland->destroy_image == NULL || + backend_wayland->export_drm_image == NULL || + backend_wayland->image_target_texture_2d == NULL) + { + g_set_error (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_BACKEND, + "Missing EGL extensions"); + return FALSE; + } + if (drmGetMagic (backend_wayland->drm_fd, &magic)) { g_set_error (error, CLUTTER_INIT_ERROR, @@ -208,32 +272,6 @@ try_enable_drm (ClutterBackendWayland *backend_wayland, GError **error) while (!backend_wayland->authenticated) wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_READABLE); - backend_wayland->get_drm_display = - (PFNEGLGETDRMDISPLAYMESA) eglGetProcAddress ("eglGetDRMDisplayMESA"); - backend_wayland->create_drm_image = - (PFNEGLCREATEDRMIMAGEMESA) eglGetProcAddress ("eglCreateDRMImageMESA"); - backend_wayland->destroy_image = - (PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress ("eglDestroyImageKHR"); - backend_wayland->export_drm_image = - (PFNEGLEXPORTDRMIMAGEMESA) eglGetProcAddress ("eglExportDRMImageMESA"); - backend_wayland->image_target_texture_2d = - (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) eglGetProcAddress ("glEGLImageTargetTexture2DOES"); - - if (backend_wayland->get_drm_display == NULL || - backend_wayland->create_drm_image == NULL || - backend_wayland->destroy_image == NULL || - backend_wayland->export_drm_image == NULL || - backend_wayland->image_target_texture_2d == NULL) - { - g_set_error (error, CLUTTER_INIT_ERROR, - CLUTTER_INIT_ERROR_BACKEND, - "Missing EGL extensions"); - return FALSE; - } - - backend_wayland->edpy = - backend_wayland->get_drm_display (backend_wayland->drm_fd); - return TRUE; }; @@ -268,16 +306,8 @@ clutter_backend_wayland_post_parse (ClutterBackend *backend, /* Process connection events. */ wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_READABLE); - backend_wayland->drm_enabled = try_enable_drm(backend_wayland, error); - - if (!backend_wayland->drm_enabled) { - if (backend_wayland->wayland_shm == NULL) - return FALSE; - - g_debug("Could not enable DRM buffers, falling back to SHM buffers"); - g_clear_error(error); - backend_wayland->edpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); - } + if (!try_get_display(backend_wayland, error)) + return FALSE; status = eglInitialize (backend_wayland->edpy, &backend_wayland->egl_version_major, @@ -294,6 +324,16 @@ clutter_backend_wayland_post_parse (ClutterBackend *backend, backend_wayland->egl_version_major, backend_wayland->egl_version_minor); + backend_wayland->drm_enabled = try_enable_drm(backend_wayland, error); + + if (!backend_wayland->drm_enabled) { + if (backend_wayland->wayland_shm == NULL) + return FALSE; + + g_debug("Could not enable DRM buffers, falling back to SHM buffers"); + g_clear_error(error); + } + return TRUE; } @@ -612,6 +652,7 @@ _clutter_backend_wayland_class_init (ClutterBackendWaylandClass *klass) static void _clutter_backend_wayland_init (ClutterBackendWayland *backend_wayland) { + backend_wayland->edpy = EGL_NO_DISPLAY; backend_wayland->egl_context = EGL_NO_CONTEXT; backend_wayland->drm_fd = -1; From c1a27d481ba7579a59b720a6b9b7a4be46294110 Mon Sep 17 00:00:00 2001 From: nobled Date: Tue, 8 Feb 2011 15:53:08 +0000 Subject: [PATCH 15/16] wayland: set renderable type on dummy surface Make sure it's compatible with the API that's in use. --- clutter/wayland/clutter-backend-wayland.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/clutter/wayland/clutter-backend-wayland.c b/clutter/wayland/clutter-backend-wayland.c index c96a24597..794cecad2 100644 --- a/clutter/wayland/clutter-backend-wayland.c +++ b/clutter/wayland/clutter-backend-wayland.c @@ -337,12 +337,23 @@ clutter_backend_wayland_post_parse (ClutterBackend *backend, return TRUE; } +#if defined(HAVE_COGL_GL) +#define _COGL_RENDERABLE_BIT EGL_OPENGL_BIT +#elif defined(HAVE_COGL_GLES2) +#define _COGL_GLES_VERSION 2 +#define _COGL_RENDERABLE_BIT EGL_OPENGL_ES2_BIT +#elif defined(HAVE_COGL_GLES) +#define _COGL_GLES_VERSION 1 +#define _COGL_RENDERABLE_BIT EGL_OPENGL_ES_BIT +#endif + static gboolean make_dummy_surface (ClutterBackendWayland *backend_wayland) { static const EGLint attrs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, + EGL_RENDERABLE_TYPE, _COGL_RENDERABLE_BIT, EGL_NONE }; EGLint num_configs; @@ -362,12 +373,6 @@ make_dummy_surface (ClutterBackendWayland *backend_wayland) return TRUE; } -#if defined(HAVE_COGL_GLES2) -#define _COGL_GLES_VERSION 2 -#elif defined(HAVE_COGL_GLES) -#define _COGL_GLES_VERSION 1 -#endif - static gboolean try_create_context (ClutterBackend *backend, int retry_cookie, From 734a236a97a06d823ed9387640c390a5081c71ff Mon Sep 17 00:00:00 2001 From: nobled Date: Tue, 8 Feb 2011 15:55:18 +0000 Subject: [PATCH 16/16] wayland: fix shm buffers We need to *write* to the shared memory, not read from it. cogl_texture_from_data() is read-only, it doesn't keep the data in sync with the texture. Instead, we have to call cogl_texture_get_data() ourselves to sync manually. --- clutter/wayland/clutter-stage-wayland.c | 44 ++++++++++++++++++------- clutter/wayland/clutter-stage-wayland.h | 4 ++- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/clutter/wayland/clutter-stage-wayland.c b/clutter/wayland/clutter-stage-wayland.c index e9ef0be1b..c691dde23 100644 --- a/clutter/wayland/clutter-stage-wayland.c +++ b/clutter/wayland/clutter-stage-wayland.c @@ -95,9 +95,9 @@ wayland_create_shm_buffer (ClutterBackendWayland *backend_wayland, { ClutterStageWaylandWaylandBufferSHM *buffer; struct wl_visual *visual; + CoglHandle tex; CoglTextureFlags flags = COGL_TEXTURE_NONE; /* XXX: tweak flags? */ CoglPixelFormat format = VISUAL_ARGB_PRE; - unsigned int stride; int fd; gchar tmp[] = "/tmp/clutter-wayland-shm-XXXXXX"; @@ -105,10 +105,13 @@ wayland_create_shm_buffer (ClutterBackendWayland *backend_wayland, buffer->buffer.type = BUFFER_TYPE_SHM; - /* XXX: can we query Cogl for what the stride should - be for a given format and width? */ - stride = geom->width; - buffer->size = stride * geom->height; + tex = cogl_texture_new_with_size ((unsigned int)geom->width, + (unsigned int)geom->height, + flags, format); + buffer->format = format; + buffer->stride = cogl_texture_get_rowstride(tex); + buffer->size = cogl_texture_get_data(tex, format, buffer->stride, NULL); + buffer->buffer.tex = tex; fd = g_mkstemp_full(tmp, O_RDWR, 0600); ftruncate(fd, buffer->size); @@ -117,19 +120,14 @@ wayland_create_shm_buffer (ClutterBackendWayland *backend_wayland, g_unlink(tmp); - buffer->buffer.tex = cogl_texture_new_from_data ((unsigned int)geom->width, - (unsigned int)geom->height, - flags, format, - COGL_PIXEL_FORMAT_ANY, - stride, buffer->data); - visual = get_visual (backend_wayland->wayland_display, format); + buffer->buffer.wayland_buffer = wl_shm_create_buffer (backend_wayland->wayland_shm, fd, geom->width, geom->height, - stride, visual); + buffer->stride, visual); close(fd); return &buffer->buffer; } @@ -465,6 +463,26 @@ wayland_frame_callback (void *data, uint32_t _time) stage_wayland->pending_swaps--; } +static void +wayland_damage_buffer(ClutterStageWaylandWaylandBuffer *generic_buffer) +{ + ClutterStageWaylandWaylandBufferSHM *buffer; + int size; + + if (generic_buffer->type != BUFFER_TYPE_SHM) + return; + + buffer = (ClutterStageWaylandWaylandBufferSHM *)generic_buffer; + + size = cogl_texture_get_data(buffer->buffer.tex, buffer->format, + buffer->stride, NULL); + g_assert(size == (int)buffer->size); + + (void) cogl_texture_get_data(buffer->buffer.tex, buffer->format, + buffer->stride, buffer->data); + +} + static void wayland_swap_buffers (ClutterStageWayland *stage_wayland) { @@ -476,6 +494,8 @@ wayland_swap_buffers (ClutterStageWayland *stage_wayland) stage_wayland->front_buffer = stage_wayland->back_buffer; stage_wayland->back_buffer = buffer; + wayland_damage_buffer(stage_wayland->front_buffer); + wl_surface_attach (stage_wayland->wayland_surface, stage_wayland->front_buffer->wayland_buffer, /* 0,0 here is "relative to the old buffer," not absolute */ diff --git a/clutter/wayland/clutter-stage-wayland.h b/clutter/wayland/clutter-stage-wayland.h index be7b915a6..156a75e8c 100644 --- a/clutter/wayland/clutter-stage-wayland.h +++ b/clutter/wayland/clutter-stage-wayland.h @@ -60,7 +60,7 @@ typedef struct _ClutterStageWaylandWaylandBuffer struct wl_buffer *wayland_buffer; cairo_region_t *dirty_region; CoglHandle tex; - guint8 type; + guint type; } ClutterStageWaylandWaylandBuffer; typedef struct _ClutterStageWaylandWaylandBufferDRM @@ -73,8 +73,10 @@ typedef struct _ClutterStageWaylandWaylandBufferDRM typedef struct _ClutterStageWaylandWaylandBufferSHM { ClutterStageWaylandWaylandBuffer buffer; + CoglPixelFormat format; guint8 *data; size_t size; + unsigned int stride; } ClutterStageWaylandWaylandBufferSHM; struct _ClutterStageWayland