[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