Support window resizing in the SDL 2 winsys

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.

Reviewed-by: Robert Bragg <robert@linux.intel.com>

(cherry picked from commit 0dea9aeb897faf029828379b120970477df3c7d5)
This commit is contained in:
Neil Roberts 2012-06-27 15:49:38 +01:00 committed by Robert Bragg
parent 11126a1b7e
commit 9f107ab3fb
2 changed files with 111 additions and 2 deletions

View File

@ -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,
@ -259,6 +265,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)
{
@ -278,12 +325,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);
}
@ -347,15 +405,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)
{
@ -366,6 +431,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;
@ -407,6 +474,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)
{
@ -439,6 +542,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;
}

View File

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