From 59a04cd0e63bfc1e9d40da163b1694925fdb40b1 Mon Sep 17 00:00:00 2001 From: Chris Cummins Date: Thu, 25 Apr 2013 18:30:42 +0100 Subject: [PATCH] wayland: implement foreign surfaces for CoglOnscreen This adds support for optionally providing a foreign Wayland surface to a CoglOnscreen before allocation. Setting a foreign surface prevents Cogl from creating a toplevel Wayland shell surface for the OnScreen. Reviewed-by: Robert Bragg (cherry picked from commit e447d9878f3bcfe5fe336d367238383b02879223) --- cogl/cogl-onscreen-private.h | 4 ++ cogl/cogl-onscreen.h | 19 +++++++++ cogl/winsys/cogl-winsys-egl-wayland.c | 60 ++++++++++++++++++--------- 3 files changed, 63 insertions(+), 20 deletions(-) diff --git a/cogl/cogl-onscreen-private.h b/cogl/cogl-onscreen-private.h index 925fa60c5..7fc601939 100644 --- a/cogl/cogl-onscreen-private.h +++ b/cogl/cogl-onscreen-private.h @@ -86,6 +86,10 @@ struct _CoglOnscreen HWND foreign_hwnd; #endif +#ifdef COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT + struct wl_surface *foreign_surface; +#endif + CoglBool swap_throttled; CoglFrameCallbackList frame_closures; diff --git a/cogl/cogl-onscreen.h b/cogl/cogl-onscreen.h index 4430dd22d..cf2f85d96 100644 --- a/cogl/cogl-onscreen.h +++ b/cogl/cogl-onscreen.h @@ -187,6 +187,25 @@ cogl_wayland_onscreen_get_surface (CoglOnscreen *onscreen); struct wl_shell_surface * cogl_wayland_onscreen_get_shell_surface (CoglOnscreen *onscreen); +/** + * cogl_wayland_onscreen_set_foreign_surface: + * @onscreen: An unallocated framebuffer. + * @surface A Wayland surface to associate with the @onscreen. + * + * Allows you to explicitly notify Cogl of an existing Wayland surface to use, + * which prevents Cogl from allocating a surface and shell surface for the + * @onscreen. An allocated surface will not be destroyed when the @onscreen is + * freed. + * + * This function must be called before @onscreen is allocated. + * + * Since: 1.16 + * Stability: unstable + */ +void +cogl_wayland_onscreen_set_foreign_surface (CoglOnscreen *onscreen, + struct wl_surface *surface); + /** * cogl_wayland_onscreen_resize: * @onscreen: A #CoglOnscreen framebuffer diff --git a/cogl/winsys/cogl-winsys-egl-wayland.c b/cogl/winsys/cogl-winsys-egl-wayland.c index 144456481..e605b517c 100644 --- a/cogl/winsys/cogl-winsys-egl-wayland.c +++ b/cogl/winsys/cogl-winsys-egl-wayland.c @@ -324,8 +324,12 @@ _cogl_winsys_egl_onscreen_init (CoglOnscreen *onscreen, wayland_onscreen = g_slice_new0 (CoglOnscreenWayland); egl_onscreen->platform = wayland_onscreen; - wayland_onscreen->wayland_surface = - wl_compositor_create_surface (wayland_renderer->wayland_compositor); + if (onscreen->foreign_surface) + wayland_onscreen->wayland_surface = onscreen->foreign_surface; + else + wayland_onscreen->wayland_surface = + wl_compositor_create_surface (wayland_renderer->wayland_compositor); + if (!wayland_onscreen->wayland_surface) { _cogl_set_error (error, COGL_WINSYS_ERROR, @@ -334,10 +338,6 @@ _cogl_winsys_egl_onscreen_init (CoglOnscreen *onscreen, return FALSE; } - wayland_onscreen->wayland_shell_surface = - wl_shell_get_shell_surface (wayland_renderer->wayland_shell, - wayland_onscreen->wayland_surface); - wayland_onscreen->wayland_egl_native_window = wl_egl_window_create (wayland_onscreen->wayland_surface, cogl_framebuffer_get_width (framebuffer), @@ -358,7 +358,13 @@ _cogl_winsys_egl_onscreen_init (CoglOnscreen *onscreen, wayland_onscreen->wayland_egl_native_window, NULL); - wl_shell_surface_set_toplevel (wayland_onscreen->wayland_shell_surface); + if (!onscreen->foreign_surface) + { + wayland_onscreen->wayland_shell_surface = + wl_shell_get_shell_surface (wayland_renderer->wayland_shell, + wayland_onscreen->wayland_surface); + wl_shell_surface_set_toplevel (wayland_onscreen->wayland_shell_surface); + } return TRUE; } @@ -375,22 +381,24 @@ _cogl_winsys_egl_onscreen_deinit (CoglOnscreen *onscreen) wayland_onscreen->wayland_egl_native_window = NULL; } - /* NB: The wayland protocol docs explicitly state that - * "wl_shell_surface_destroy() must be called before destroying the - * wl_surface object." ... */ - if (wayland_onscreen->wayland_shell_surface) + if (!onscreen->foreign_surface) { - wl_shell_surface_destroy (wayland_onscreen->wayland_shell_surface); - wayland_onscreen->wayland_shell_surface = NULL; - } + /* NB: The wayland protocol docs explicitly state that + * "wl_shell_surface_destroy() must be called before destroying + * the wl_surface object." ... */ + if (wayland_onscreen->wayland_shell_surface) + { + wl_shell_surface_destroy (wayland_onscreen->wayland_shell_surface); + wayland_onscreen->wayland_shell_surface = NULL; + } - if (wayland_onscreen->wayland_surface) - { - wl_surface_destroy (wayland_onscreen->wayland_surface); - wayland_onscreen->wayland_surface = NULL; + if (wayland_onscreen->wayland_surface) + { + wl_surface_destroy (wayland_onscreen->wayland_surface); + wayland_onscreen->wayland_surface = NULL; + } } - g_slice_free (CoglOnscreenWayland, wayland_onscreen); } @@ -524,7 +532,7 @@ cogl_wayland_onscreen_get_surface (CoglOnscreen *onscreen) CoglFramebuffer *fb; fb = COGL_FRAMEBUFFER (onscreen); - if (fb->allocated) + if (fb->allocated && !onscreen->foreign_surface) { CoglOnscreenEGL *egl_onscreen = onscreen->winsys; CoglOnscreenWayland *wayland_onscreen = egl_onscreen->platform; @@ -550,6 +558,18 @@ cogl_wayland_onscreen_get_shell_surface (CoglOnscreen *onscreen) return NULL; } +void +cogl_wayland_onscreen_set_foreign_surface (CoglOnscreen *onscreen, + struct wl_surface *surface) +{ + CoglFramebuffer *fb; + + fb = COGL_FRAMEBUFFER (onscreen); + _COGL_RETURN_IF_FAIL (!fb->allocated); + + onscreen->foreign_surface = surface; +} + void cogl_wayland_onscreen_resize (CoglOnscreen *onscreen, int width,