From 97243ad9ac3fd47f6e1a5df2ec9a755a2082e550 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Wed, 4 May 2011 11:10:54 +0100 Subject: [PATCH] Adds cogl_onscreen_show/hide functions This adds Cogl API to show and hide onscreen framebuffers. We don't want to go too far down the road of abstracting window system APIs with Cogl since that would be out of its scope but the previous idea that we would automatically map framebuffers on allocation except for those made from foreign windows wasn't good enough. The problem is that we don't want to make Clutter always create stages from foreign windows but with the automatic map semantics then Clutter doesn't get an opportunity to select for all the events it requires before mapping. This meant that we wouldn't be delivered a mouse enter event for windows mapped underneath the cursor which would break Clutters handling of button press events. --- cogl/cogl-framebuffer.c | 31 ++++++++++++++++++ cogl/cogl-framebuffer.h | 52 +++++++++++++++++++++++++++++++ cogl/winsys/cogl-winsys-egl.c | 21 +++++++++++-- cogl/winsys/cogl-winsys-glx.c | 17 ++++++++-- cogl/winsys/cogl-winsys-private.h | 4 +++ examples/hello.c | 2 ++ 6 files changed, 123 insertions(+), 4 deletions(-) diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c index 9712fe747..071b9ec88 100644 --- a/cogl/cogl-framebuffer.c +++ b/cogl/cogl-framebuffer.c @@ -1690,3 +1690,34 @@ cogl_onscreen_set_swap_throttled (CoglOnscreen *onscreen, winsys->onscreen_update_swap_throttled (onscreen); } } + +void +cogl_onscreen_show (CoglOnscreen *onscreen) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + const CoglWinsysVtable *winsys; + + if (!framebuffer->allocated) + { + if (!cogl_framebuffer_allocate (framebuffer, NULL)) + return; + } + + winsys = _cogl_framebuffer_get_winsys (framebuffer); + if (winsys->onscreen_set_visibility) + winsys->onscreen_set_visibility (onscreen, TRUE); +} + +void +cogl_onscreen_hide (CoglOnscreen *onscreen) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + + if (framebuffer->allocated) + { + const CoglWinsysVtable *winsys = + _cogl_framebuffer_get_winsys (framebuffer); + if (winsys->onscreen_set_visibility) + winsys->onscreen_set_visibility (onscreen, FALSE); + } +} diff --git a/cogl/cogl-framebuffer.h b/cogl/cogl-framebuffer.h index 120382fc3..3f4ecb8a5 100644 --- a/cogl/cogl-framebuffer.h +++ b/cogl/cogl-framebuffer.h @@ -106,6 +106,58 @@ void cogl_onscreen_set_swap_throttled (CoglOnscreen *onscreen, gboolean throttled); +/** + * cogl_onscreen_show: + * @onscreen: The onscreen framebuffer to make visible + * + * This requests to make @onscreen visible to the user. + * + * Actually the precise semantics of this function depend on the + * window system currently in use, and if you don't have a + * multi-windowining system this function may in-fact do nothing. + * + * This function will implicitly allocate the given @onscreen + * framebuffer before showing it if it hasn't already been allocated. + * + * Since Cogl doesn't explicitly track the visibility status of + * onscreen framebuffers it wont try to avoid redundant window system + * requests e.g. to show an already visible window. This also means + * that it's acceptable to alternatively use native APIs to show and + * hide windows without confusing Cogl. + * + * Since: 2.0 + * Stability: Unstable + */ +#define cogl_onscreen_show cogl_onscreen_show_EXP +void +cogl_onscreen_show (CoglOnscreen *onscreen); + +/** + * cogl_onscreen_hide: + * @onscreen: The onscreen framebuffer to make invisible + * + * This requests to make @onscreen invisible to the user. + * + * Actually the precise semantics of this function depend on the + * window system currently in use, and if you don't have a + * multi-windowining system this function may in-fact do nothing. + * + * This function does not implicitly allocate the given @onscreen + * framebuffer before hiding it. + * + * Since Cogl doesn't explicitly track the visibility status of + * onscreen framebuffers it wont try to avoid redundant window system + * requests e.g. to show an already visible window. This also means + * that it's acceptable to alternatively use native APIs to show and + * hide windows without confusing Cogl. + * + * Since: 2.0 + * Stability: Unstable + */ +#define cogl_onscreen_hide cogl_onscreen_hide_EXP +void +cogl_onscreen_hide (CoglOnscreen *onscreen); + #define cogl_get_draw_framebuffer cogl_get_draw_framebuffer_EXP CoglFramebuffer * cogl_get_draw_framebuffer (void); diff --git a/cogl/winsys/cogl-winsys-egl.c b/cogl/winsys/cogl-winsys-egl.c index 61b733ecf..0ffd48b40 100644 --- a/cogl/winsys/cogl-winsys-egl.c +++ b/cogl/winsys/cogl-winsys-egl.c @@ -971,8 +971,6 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen, XFree (xvisinfo); - XMapWindow (xlib_renderer->xdpy, xwin); - XSync (xlib_renderer->xdpy, False); xerror = _cogl_renderer_xlib_untrap_errors (display->renderer, &state); if (xerror) @@ -1127,6 +1125,22 @@ _cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen, g_warning ("Error reported by eglSwapBuffersRegion"); } +#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT +static void +_cogl_winsys_onscreen_set_visibility (CoglOnscreen *onscreen, + gboolean visibility) +{ + CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context; + CoglRendererXlib *xlib_renderer = context->display->renderer->winsys; + CoglOnscreenXlib *xlib_onscreen = onscreen->winsys; + + if (visibility) + XMapWindow (xlib_renderer->xdpy, xlib_onscreen->xwin); + else + XUnmapWindow (xlib_renderer->xdpy, xlib_onscreen->xwin); +} +#endif + static guint32 _cogl_winsys_get_vsync_counter (void) { @@ -1229,6 +1243,9 @@ static CoglWinsysVtable _cogl_winsys_vtable = .onscreen_bind = _cogl_winsys_onscreen_bind, .onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers, .onscreen_swap_region = _cogl_winsys_onscreen_swap_region, +#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT + .onscreen_set_visibility = _cogl_winsys_onscreen_set_visibility, +#endif .onscreen_update_swap_throttled = _cogl_winsys_onscreen_update_swap_throttled, .onscreen_x11_get_window_xid = diff --git a/cogl/winsys/cogl-winsys-glx.c b/cogl/winsys/cogl-winsys-glx.c index 1f115f2fe..47a207f2b 100644 --- a/cogl/winsys/cogl-winsys-glx.c +++ b/cogl/winsys/cogl-winsys-glx.c @@ -806,8 +806,6 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen, XFree (xvisinfo); - XMapWindow (xlib_renderer->xdpy, xwin); - XSync (xlib_renderer->xdpy, False); xerror = _cogl_renderer_xlib_untrap_errors (display->renderer, &state); if (xerror) @@ -1324,6 +1322,20 @@ _cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen) _cogl_winsys_onscreen_bind (onscreen); } +static void +_cogl_winsys_onscreen_set_visibility (CoglOnscreen *onscreen, + gboolean visibility) +{ + CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context; + CoglRendererXlib *xlib_renderer = context->display->renderer->winsys; + CoglOnscreenXlib *xlib_onscreen = onscreen->winsys; + + if (visibility) + XMapWindow (xlib_renderer->xdpy, xlib_onscreen->xwin); + else + XUnmapWindow (xlib_renderer->xdpy, xlib_onscreen->xwin); +} + /* XXX: This is a particularly hacky _cogl_winsys interface... */ static XVisualInfo * _cogl_winsys_xlib_get_visual_info (void) @@ -1904,6 +1916,7 @@ static CoglWinsysVtable _cogl_winsys_vtable = _cogl_winsys_onscreen_add_swap_buffers_callback, .onscreen_remove_swap_buffers_callback = _cogl_winsys_onscreen_remove_swap_buffers_callback, + .onscreen_set_visibility = _cogl_winsys_onscreen_set_visibility, .get_vsync_counter = _cogl_winsys_get_vsync_counter, /* X11 tfp support... */ diff --git a/cogl/winsys/cogl-winsys-private.h b/cogl/winsys/cogl-winsys-private.h index e09fde99b..1e1fec042 100644 --- a/cogl/winsys/cogl-winsys-private.h +++ b/cogl/winsys/cogl-winsys-private.h @@ -122,6 +122,10 @@ typedef struct _CoglWinsysVtable (*onscreen_remove_swap_buffers_callback) (CoglOnscreen *onscreen, unsigned int id); + void + (*onscreen_set_visibility) (CoglOnscreen *onscreen, + gboolean visibility); + guint32 (*get_vsync_counter) (void); diff --git a/examples/hello.c b/examples/hello.c index ace664fb5..62076ad0f 100644 --- a/examples/hello.c +++ b/examples/hello.c @@ -34,6 +34,8 @@ main (int argc, char **argv) return 1; } + cogl_onscreen_show (onscreen); + cogl_push_framebuffer (fb); triangle = cogl_primitive_new_p2c4 (COGL_VERTICES_MODE_TRIANGLES,