diff --git a/clutter/clutter-container.h b/clutter/clutter-container.h index 34333695a..a2587a2e6 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 diff --git a/clutter/wayland/clutter-backend-wayland.c b/clutter/wayland/clutter-backend-wayland.c index ee8dac350..794cecad2 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; @@ -177,20 +175,117 @@ 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 +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; + + if (backend_wayland->drm_fd < 0) + { + g_set_error (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_BACKEND, + "Failed to open drm device"); + 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, + CLUTTER_INIT_ERROR_BACKEND, + "Failed to get drm magic"); + return FALSE; + } + + wl_drm_authenticate (backend_wayland->wayland_drm, magic); + wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_WRITABLE); + while (!backend_wayland->authenticated) + wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_READABLE); + + return TRUE; +}; + static gboolean clutter_backend_wayland_post_parse (ClutterBackend *backend, 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 ("\0wayland"); + backend_wayland->wayland_display = wl_display_connect (NULL); if (!backend_wayland->wayland_display) { g_set_error (error, CLUTTER_INIT_ERROR, @@ -211,53 +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_fd = open (backend_wayland->device_name, O_RDWR); - if (backend_wayland->drm_fd < 0) - { - g_set_error (error, CLUTTER_INIT_ERROR, - CLUTTER_INIT_ERROR_BACKEND, - "Failed to open drm device"); - return FALSE; - } - - if (drmGetMagic (backend_wayland->drm_fd, &magic)) - { - g_set_error (error, CLUTTER_INIT_ERROR, - CLUTTER_INIT_ERROR_BACKEND, - "Failed to get drm magic"); - return FALSE; - } - - wl_drm_authenticate (backend_wayland->wayland_drm, magic); - wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_WRITABLE); - 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); + if (!try_get_display(backend_wayland, error)) + return FALSE; status = eglInitialize (backend_wayland->edpy, &backend_wayland->egl_version_major, @@ -274,6 +324,52 @@ 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; +} + +#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; + + 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; } @@ -286,20 +382,18 @@ try_create_context (ClutterBackend *backend, ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); const char *error_message; - eglBindAPI (EGL_OPENGL_API); - 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 = eglCreateContext (backend_wayland->edpy, - NULL, + backend_wayland->egl_config, EGL_NO_CONTEXT, attribs); if (backend_wayland->egl_context == EGL_NO_CONTEXT) @@ -312,13 +406,13 @@ try_create_context (ClutterBackend *backend, } if (!eglMakeCurrent (backend_wayland->edpy, - NULL, - NULL, + 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; } @@ -334,6 +428,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) @@ -348,15 +450,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 ("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"); - 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; @@ -541,6 +657,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; diff --git a/clutter/wayland/clutter-backend-wayland.h b/clutter/wayland/clutter-backend-wayland.h index d243cee9c..c36ecab84 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; @@ -66,11 +67,13 @@ 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; 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 3bd478abb..d01047447 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 @@ -59,14 +64,82 @@ G_DEFINE_TYPE_WITH_CODE (ClutterStageWayland, G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW, clutter_stage_window_iface_init)); -static ClutterStageWaylandWaylandBuffer * -wayland_create_buffer (ClutterStageWayland *stage_wayland, - ClutterGeometry *geom) +#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_shm_buffer (ClutterBackendWayland *backend_wayland, + ClutterGeometry *geom) +{ + ClutterStageWaylandWaylandBufferSHM *buffer; + struct wl_visual *visual; + CoglHandle tex; + CoglTextureFlags flags = COGL_TEXTURE_NONE; /* XXX: tweak flags? */ + CoglPixelFormat format = VISUAL_ARGB_PRE; + int fd; + gchar tmp[] = "/tmp/clutter-wayland-shm-XXXXXX"; + + buffer = g_slice_new (ClutterStageWaylandWaylandBufferSHM); + + buffer->buffer.type = BUFFER_TYPE_SHM; + + 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); + buffer->data = mmap(NULL, buffer->size, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0); + + g_unlink(tmp); + + 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, + buffer->stride, visual); + close(fd); + return &buffer->buffer; +} + +static ClutterStageWaylandWaylandBuffer * +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, @@ -74,12 +147,10 @@ wayland_create_buffer (ClutterStageWayland *stage_wayland, 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; @@ -88,26 +159,45 @@ wayland_create_buffer (ClutterStageWayland *stage_wayland, 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, - COGL_PIXEL_FORMAT_ARGB_8888); - buffer->offscreen = cogl_offscreen_new_to_texture (buffer->tex); + VISUAL_ARGB_PRE); backend_wayland->export_drm_image (edpy, buffer->drm_image, &name, NULL, &stride); - visual = - wl_display_get_premultiplied_argb_visual (backend_wayland->wayland_display); - buffer->wayland_buffer = + visual = get_visual (backend_wayland->wayland_display, VISUAL_ARGB_PRE); + buffer->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); + 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; + + 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); + rect.x = geom->x; rect.y = geom->y; rect.width = geom->width; @@ -118,18 +208,42 @@ wayland_create_buffer (ClutterStageWayland *stage_wayland, } static void -wayland_free_buffer (ClutterStageWaylandWaylandBuffer *buffer) +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) { 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); + else if (buffer->type == BUFFER_TYPE_SHM) + wayland_free_shm_buffer(buffer); } static void @@ -171,7 +285,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; } @@ -349,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) { @@ -360,13 +494,13 @@ 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); - 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, @@ -506,7 +640,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); diff --git a/clutter/wayland/clutter-stage-wayland.h b/clutter/wayland/clutter-stage-wayland.h index 2c44f38fa..156a75e8c 100644 --- a/clutter/wayland/clutter-stage-wayland.h +++ b/clutter/wayland/clutter-stage-wayland.h @@ -51,16 +51,34 @@ typedef struct _ClutterStageWayland ClutterStageWayland; typedef struct _ClutterStageWaylandClass ClutterStageWaylandClass; +#define BUFFER_TYPE_DRM 1 +#define BUFFER_TYPE_SHM 2 + typedef struct _ClutterStageWaylandWaylandBuffer { - EGLImageKHR drm_image; - GLuint texture; CoglHandle offscreen; struct wl_buffer *wayland_buffer; cairo_region_t *dirty_region; CoglHandle tex; + guint type; } ClutterStageWaylandWaylandBuffer; +typedef struct _ClutterStageWaylandWaylandBufferDRM +{ + ClutterStageWaylandWaylandBuffer buffer; + EGLImageKHR drm_image; + GLuint texture; +} ClutterStageWaylandWaylandBufferDRM; + +typedef struct _ClutterStageWaylandWaylandBufferSHM +{ + ClutterStageWaylandWaylandBuffer buffer; + CoglPixelFormat format; + guint8 *data; + size_t size; + unsigned int stride; +} ClutterStageWaylandWaylandBufferSHM; + struct _ClutterStageWayland { GObject parent_instance;