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 <robert@linux.intel.com>

(cherry picked from commit e447d9878f3bcfe5fe336d367238383b02879223)
This commit is contained in:
Chris Cummins 2013-04-25 18:30:42 +01:00 committed by Robert Bragg
parent 4327b7a364
commit 59a04cd0e6
3 changed files with 63 additions and 20 deletions

View File

@ -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;

View File

@ -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

View File

@ -324,8 +324,12 @@ _cogl_winsys_egl_onscreen_init (CoglOnscreen *onscreen,
wayland_onscreen = g_slice_new0 (CoglOnscreenWayland);
egl_onscreen->platform = wayland_onscreen;
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);
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,9 +381,11 @@ _cogl_winsys_egl_onscreen_deinit (CoglOnscreen *onscreen)
wayland_onscreen->wayland_egl_native_window = NULL;
}
if (!onscreen->foreign_surface)
{
/* NB: The wayland protocol docs explicitly state that
* "wl_shell_surface_destroy() must be called before destroying the
* wl_surface object." ... */
* "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);
@ -389,7 +397,7 @@ _cogl_winsys_egl_onscreen_deinit (CoglOnscreen *onscreen)
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,