[Cogl] [PATCH 1/3] Support window resizing in the SDL 2 winsys

Neil Roberts neil at linux.intel.com
Tue Nov 20 10:53:07 PST 2012


The SDL2 winsys will now set the SDL_WINDOW_RESIZABLE flag on the
window before creating it if the resizable property is set on the
onscreen. Note that there doesn't appear to be a way in SDL to change
the flag later so unlike the other winsyses it will only take affect
if it is set before allocating the framebuffer.

The winsys now registers a callback for SDL events so that it can
report window size changes back to the application.
---
 cogl/winsys/cogl-winsys-sdl2.c | 109 ++++++++++++++++++++++++++++++++++++++++-
 examples/cogl-sdl2-hello.c     |   4 ++
 2 files changed, 111 insertions(+), 2 deletions(-)

diff --git a/cogl/winsys/cogl-winsys-sdl2.c b/cogl/winsys/cogl-winsys-sdl2.c
index 4c0583b..3ae0962 100644
--- a/cogl/winsys/cogl-winsys-sdl2.c
+++ b/cogl/winsys/cogl-winsys-sdl2.c
@@ -53,13 +53,19 @@ typedef struct _CoglDisplaySdl2
 {
   SDL_Window *dummy_window;
   SDL_GLContext *context;
+  CoglBool pending_resize_notify;
 } CoglDisplaySdl2;
 
 typedef struct _CoglOnscreenSdl2
 {
   SDL_Window *window;
+  CoglBool pending_resize_notify;
 } CoglOnscreenSdl2;
 
+/* The key used to store a pointer to the CoglOnscreen in an
+ * SDL_Window */
+#define COGL_SDL_WINDOW_DATA_KEY "cogl-onscreen"
+
 static CoglFuncPtr
 _cogl_winsys_renderer_get_proc_address (CoglRenderer *renderer,
                                         const char *name,
@@ -258,6 +264,47 @@ error:
   return FALSE;
 }
 
+static CoglFilterReturn
+sdl_event_filter_cb (SDL_Event *event, void *data)
+{
+  if (event->type == SDL_WINDOWEVENT &&
+      event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
+    {
+      CoglContext *context = data;
+      CoglDisplay *display = context->display;
+      CoglDisplaySdl2 *sdl_display = display->winsys;
+      float width = event->window.data1;
+      float height = event->window.data2;
+      CoglFramebuffer *framebuffer;
+      CoglOnscreenSdl2 *sdl_onscreen;
+      SDL_Window *window;
+
+      window = SDL_GetWindowFromID (event->window.windowID);
+
+      if (window == NULL)
+        return COGL_FILTER_CONTINUE;
+
+      framebuffer = SDL_GetWindowData (window, COGL_SDL_WINDOW_DATA_KEY);
+
+      if (framebuffer == NULL || framebuffer->context != context)
+        return COGL_FILTER_CONTINUE;
+
+      _cogl_framebuffer_winsys_update_size (framebuffer, width, height);
+
+      sdl_onscreen = COGL_ONSCREEN (framebuffer)->winsys;
+
+      /* We only want to notify that a resize happened when the
+         application calls cogl_context_dispatch so instead of immediately
+         notifying we'll set a flag to remember to notify later */
+      sdl_display->pending_resize_notify = TRUE;
+      sdl_onscreen->pending_resize_notify = TRUE;
+
+      return COGL_FILTER_CONTINUE;
+    }
+
+  return COGL_FILTER_CONTINUE;
+}
+
 static CoglBool
 _cogl_winsys_context_init (CoglContext *context, CoglError **error)
 {
@@ -277,12 +324,23 @@ _cogl_winsys_context_init (CoglContext *context, CoglError **error)
                     COGL_WINSYS_FEATURE_SWAP_REGION_THROTTLE,
                     TRUE);
 
+  _cogl_renderer_add_native_filter (renderer,
+                                    (CoglNativeFilterFunc) sdl_event_filter_cb,
+                                    context);
+
   return TRUE;
 }
 
 static void
 _cogl_winsys_context_deinit (CoglContext *context)
 {
+  CoglRenderer *renderer = context->display->renderer;
+
+  _cogl_renderer_remove_native_filter (renderer,
+                                       (CoglNativeFilterFunc)
+                                       sdl_event_filter_cb,
+                                       context);
+
   g_free (context->winsys);
 }
 
@@ -346,15 +404,22 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
   CoglOnscreenSdl2 *sdl_onscreen;
   SDL_Window *window;
   int width, height;
+  SDL_WindowFlags flags;
 
   width = cogl_framebuffer_get_width (framebuffer);
   height = cogl_framebuffer_get_height (framebuffer);
 
+  flags = SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN;
+
+  /* The resizable property on SDL window apparently can only be set
+   * on creation */
+  if (onscreen->resizable)
+    flags |= SDL_WINDOW_RESIZABLE;
+
   window = SDL_CreateWindow ("" /* title */,
                              0, 0, /* x/y */
                              width, height,
-                             SDL_WINDOW_OPENGL |
-                             SDL_WINDOW_HIDDEN);
+                             flags);
 
   if (window == NULL)
     {
@@ -365,6 +430,8 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
       return FALSE;
     }
 
+  SDL_SetWindowData (window, COGL_SDL_WINDOW_DATA_KEY, onscreen);
+
   onscreen->winsys = g_slice_new (CoglOnscreenSdl2);
   sdl_onscreen = onscreen->winsys;
   sdl_onscreen->window = window;
@@ -406,6 +473,42 @@ _cogl_winsys_onscreen_set_visibility (CoglOnscreen *onscreen,
     SDL_HideWindow (sdl_onscreen->window);
 }
 
+static void
+flush_pending_notifications_cb (void *data,
+                                void *user_data)
+{
+  CoglFramebuffer *framebuffer = data;
+
+  if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
+    {
+      CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
+      CoglOnscreenSdl2 *sdl_onscreen = onscreen->winsys;
+
+      if (sdl_onscreen->pending_resize_notify)
+        {
+          _cogl_onscreen_notify_resize (onscreen);
+          sdl_onscreen->pending_resize_notify = FALSE;
+        }
+    }
+}
+
+static void
+_cogl_winsys_poll_dispatch (CoglContext *context,
+                            const CoglPollFD *poll_fds,
+                            int n_poll_fds)
+{
+  CoglDisplay *display = context->display;
+  CoglDisplaySdl2 *sdl_display = display->winsys;
+
+  if (sdl_display->pending_resize_notify)
+    {
+      g_list_foreach (context->framebuffers,
+                      flush_pending_notifications_cb,
+                      NULL);
+      sdl_display->pending_resize_notify = FALSE;
+    }
+}
+
 const CoglWinsysVtable *
 _cogl_winsys_sdl_get_vtable (void)
 {
@@ -438,6 +541,8 @@ _cogl_winsys_sdl_get_vtable (void)
         _cogl_winsys_onscreen_update_swap_throttled;
       vtable.onscreen_set_visibility = _cogl_winsys_onscreen_set_visibility;
 
+      vtable.poll_dispatch = _cogl_winsys_poll_dispatch;
+
       vtable_inited = TRUE;
     }
 
diff --git a/examples/cogl-sdl2-hello.c b/examples/cogl-sdl2-hello.c
index 972e7e1..0370460 100644
--- a/examples/cogl-sdl2-hello.c
+++ b/examples/cogl-sdl2-hello.c
@@ -99,6 +99,10 @@ main (int argc, char **argv)
   data.center_y = 0.0f;
   data.quit = FALSE;
 
+  /* In SDL2, setting resizable only works before allocating the
+   * onscreen */
+  cogl_onscreen_set_resizable (onscreen, TRUE);
+
   cogl_onscreen_show (onscreen);
 
   data.triangle = cogl_primitive_new_p2c4 (ctx, COGL_VERTICES_MODE_TRIANGLES,
-- 
1.7.11.3.g3c3efa5



More information about the Cogl mailing list