From bdcbb8af4db9a94614b848da49ccc1f65cda285d Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Wed, 14 Dec 2011 12:09:53 +0000 Subject: [PATCH] Update the SDL winsys The SDL winsys was missing a few minor features, such as the implementation. This patch adds that in. Reviewed-by: Robert Bragg --- cogl/Makefile.am | 4 + cogl/cogl-renderer.c | 6 + cogl/cogl-renderer.h | 4 +- cogl/winsys/cogl-winsys-sdl.c | 261 +++++++++++++++++++++++++++++++++- configure.ac | 19 +++ 5 files changed, 287 insertions(+), 7 deletions(-) diff --git a/cogl/Makefile.am b/cogl/Makefile.am index 2589e784b..c25647e07 100644 --- a/cogl/Makefile.am +++ b/cogl/Makefile.am @@ -410,6 +410,10 @@ cogl_sources_c += \ $(srcdir)/winsys/cogl-winsys-egl-feature-functions.h \ $(srcdir)/winsys/cogl-winsys-egl-private.h endif +if SUPPORT_SDL +cogl_sources_c += \ + $(srcdir)/winsys/cogl-winsys-sdl.c +endif EXTRA_DIST += stb_image.c diff --git a/cogl/cogl-renderer.c b/cogl/cogl-renderer.c index 5e5ae044e..5f65383f5 100644 --- a/cogl/cogl-renderer.c +++ b/cogl/cogl-renderer.c @@ -74,6 +74,9 @@ extern const CoglWinsysVtable *_cogl_winsys_glx_get_vtable (void); #ifdef COGL_HAS_WGL_SUPPORT extern const CoglWinsysVtable *_cogl_winsys_wgl_get_vtable (void); #endif +#ifdef COGL_HAS_SDL_SUPPORT +extern const CoglWinsysVtable *_cogl_winsys_sdl_get_vtable (void); +#endif typedef const CoglWinsysVtable *(*CoglWinsysVtableGetter) (void); @@ -102,6 +105,9 @@ static CoglWinsysVtableGetter _cogl_winsys_vtable_getters[] = #endif #ifdef COGL_HAS_WGL_SUPPORT _cogl_winsys_wgl_get_vtable, +#endif +#ifdef COGL_HAS_SDL_SUPPORT + _cogl_winsys_sdl_get_vtable, #endif _cogl_winsys_stub_get_vtable, }; diff --git a/cogl/cogl-renderer.h b/cogl/cogl-renderer.h index e621b4927..94d4de9d6 100644 --- a/cogl/cogl-renderer.h +++ b/cogl/cogl-renderer.h @@ -71,6 +71,7 @@ cogl_renderer_new (void); * @COGL_WINSYS_ID_EGL_KMS: Use EGL with the KMS platform * @COGL_WINSYS_ID_EGL_ANDROID: Use EGL with the Android platform * @COGL_WINSYS_ID_WGL: Use the Microsoft Windows WGL binding API + * @COGL_WINSYS_ID_SDL: Use the SDL window system * * Identifies specific window system backends that Cogl supports. * @@ -88,7 +89,8 @@ typedef enum COGL_WINSYS_ID_EGL_WAYLAND, COGL_WINSYS_ID_EGL_KMS, COGL_WINSYS_ID_EGL_ANDROID, - COGL_WINSYS_ID_WGL + COGL_WINSYS_ID_WGL, + COGL_WINSYS_ID_SDL } CoglWinsysID; /** diff --git a/cogl/winsys/cogl-winsys-sdl.c b/cogl/winsys/cogl-winsys-sdl.c index bb8908b21..c71f402f9 100644 --- a/cogl/winsys/cogl-winsys-sdl.c +++ b/cogl/winsys/cogl-winsys-sdl.c @@ -3,7 +3,7 @@ * * An object oriented GL/GLES Abstraction/Utility Layer * - * Copyright (C) 2007,2008,2009 Intel Corporation. + * Copyright (C) 2011 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,18 +19,267 @@ * License along with this library. If not, see . * * + * Authors: + * Neil Roberts */ #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include "cogl.h" +#include -CoglFuncPtr -_cogl_winsys_get_proc_address (CoglRenderer *renderer, - const char *name) +#include "cogl-renderer-private.h" +#include "cogl-display-private.h" +#include "cogl-framebuffer-private.h" +#include "cogl-swap-chain-private.h" +#include "cogl-onscreen-template-private.h" +#include "cogl-context-private.h" +#include "cogl-onscreen-private.h" + +typedef struct _CoglRendererSdl { - return NULL; + int stub; +} CoglRendererSdl; + +typedef struct _CoglDisplaySdl +{ + SDL_Surface *surface; + gboolean has_onscreen; +} CoglDisplaySdl; + +static CoglFuncPtr +_cogl_winsys_renderer_get_proc_address (CoglRenderer *renderer, + const char *name) +{ + return SDL_GL_GetProcAddress (name); } +static void +_cogl_winsys_renderer_disconnect (CoglRenderer *renderer) +{ + SDL_Quit (); + + g_slice_free (CoglRendererSdl, renderer->winsys); +} + +static gboolean +_cogl_winsys_renderer_connect (CoglRenderer *renderer, + GError **error) +{ + if (renderer->driver != COGL_DRIVER_GL) + { + g_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_INIT, + "The SDL winsys only supports the GL driver"); + return FALSE; + } + + if (SDL_Init (SDL_INIT_VIDEO) == -1) + { + g_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_INIT, + "SDL_Init failed: %s", + SDL_GetError ()); + return FALSE; + } + + renderer->winsys = g_slice_new0 (CoglRendererSdl); + + return TRUE; +} + +static void +_cogl_winsys_display_destroy (CoglDisplay *display) +{ + CoglDisplaySdl *sdl_display = display->winsys; + + _COGL_RETURN_IF_FAIL (sdl_display != NULL); + + /* No need to destroy the surface - it is freed by SDL_Quit */ + + g_slice_free (CoglDisplaySdl, display->winsys); + display->winsys = NULL; +} + +static void +set_gl_attribs_from_framebuffer_config (CoglFramebufferConfig *config) +{ + SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 1); + SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 1); + SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 1); + SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 1); + + SDL_GL_SetAttribute (SDL_GL_STENCIL_SIZE, + config->need_stencil ? 1 : 0); + + SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, + config->swap_chain->length > 1 ? 1 : 0); + + SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, + config->swap_chain->has_alpha ? 1 : 0); +} + +static gboolean +_cogl_winsys_display_setup (CoglDisplay *display, + GError **error) +{ + CoglDisplaySdl *sdl_display; + + _COGL_RETURN_VAL_IF_FAIL (display->winsys == NULL, FALSE); + + sdl_display = g_slice_new0 (CoglDisplaySdl); + display->winsys = sdl_display; + + set_gl_attribs_from_framebuffer_config (&display->onscreen_template->config); + + /* There's no way to know what size the application will need until + it creates the first onscreen but we need to set the video mode + now so that we can get a GL context. We'll have to just guess at + a size an resize it later */ + sdl_display->surface = SDL_SetVideoMode (640, 480, 0, SDL_OPENGL); + + if (sdl_display->surface == NULL) + { + g_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_INIT, + "SDL_SetVideoMode failed: %s", + SDL_GetError ()); + goto error; + } + + return TRUE; + +error: + _cogl_winsys_display_destroy (display); + return FALSE; +} + +static gboolean +_cogl_winsys_context_init (CoglContext *context, GError **error) +{ + return _cogl_context_update_features (context, error); +} + +static void +_cogl_winsys_context_deinit (CoglContext *context) +{ +} + +static void +_cogl_winsys_onscreen_bind (CoglOnscreen *onscreen) +{ +} + +static void +_cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen) +{ + CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context; + CoglDisplay *display = context->display; + CoglDisplaySdl *sdl_display = display->winsys; + + sdl_display->has_onscreen = FALSE; +} + +static gboolean +_cogl_winsys_onscreen_init (CoglOnscreen *onscreen, + GError **error) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + CoglContext *context = framebuffer->context; + CoglDisplay *display = context->display; + CoglDisplaySdl *sdl_display = display->winsys; + int width, height; + + if (sdl_display->has_onscreen) + { + g_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_CREATE_ONSCREEN, + "SDL winsys only supports a single onscreen window"); + return FALSE; + } + + width = cogl_framebuffer_get_width (framebuffer); + height = cogl_framebuffer_get_height (framebuffer); + + /* Try to update the video size using the onscreen size */ + if (width != sdl_display->surface->w || + height != sdl_display->surface->h) + { + sdl_display->surface = SDL_SetVideoMode (width, height, 0, SDL_OPENGL); + + if (sdl_display->surface == NULL) + { + g_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_CREATE_ONSCREEN, + "SDL_SetVideoMode failed: %s", + SDL_GetError ()); + return FALSE; + } + } + + _cogl_framebuffer_winsys_update_size (framebuffer, + sdl_display->surface->w, + sdl_display->surface->h); + + sdl_display->has_onscreen = TRUE; + + return TRUE; +} + +static void +_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen) +{ + SDL_GL_SwapBuffers (); +} + +static void +_cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen) +{ + /* SDL doesn't appear to provide a way to set this */ +} + +static void +_cogl_winsys_onscreen_set_visibility (CoglOnscreen *onscreen, + gboolean visibility) +{ + /* SDL doesn't appear to provide a way to set this */ +} + +const CoglWinsysVtable * +_cogl_winsys_sdl_get_vtable (void) +{ + static gboolean vtable_inited = FALSE; + static CoglWinsysVtable vtable; + + /* It would be nice if we could use C99 struct initializers here + like the GLX backend does. However this code is more likely to be + compiled using Visual Studio which (still!) doesn't support them + so we initialize it in code instead */ + + if (!vtable_inited) + { + memset (&vtable, 0, sizeof (vtable)); + + vtable.id = COGL_WINSYS_ID_SDL; + vtable.name = "SDL"; + vtable.renderer_get_proc_address = _cogl_winsys_renderer_get_proc_address; + vtable.renderer_connect = _cogl_winsys_renderer_connect; + vtable.renderer_disconnect = _cogl_winsys_renderer_disconnect; + vtable.display_setup = _cogl_winsys_display_setup; + vtable.display_destroy = _cogl_winsys_display_destroy; + vtable.context_init = _cogl_winsys_context_init; + vtable.context_deinit = _cogl_winsys_context_deinit; + vtable.onscreen_init = _cogl_winsys_onscreen_init; + vtable.onscreen_deinit = _cogl_winsys_onscreen_deinit; + vtable.onscreen_bind = _cogl_winsys_onscreen_bind; + vtable.onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers; + vtable.onscreen_update_swap_throttled = + _cogl_winsys_onscreen_update_swap_throttled; + vtable.onscreen_set_visibility = _cogl_winsys_onscreen_set_visibility; + + vtable_inited = TRUE; + } + + return &vtable; +} diff --git a/configure.ac b/configure.ac index 9ce91ebb6..d05c9d0a2 100644 --- a/configure.ac +++ b/configure.ac @@ -876,6 +876,25 @@ AS_IF([test "x$NEED_EGL" = "xyes"], AM_CONDITIONAL(SUPPORT_EGL, [test "x$SUPPORT_EGL" = "xyes"]) +AC_ARG_ENABLE( + [sdl], + [AC_HELP_STRING([--enable-sdl=@<:@no/yes@:>@], [Enable support SDL @<:@default=no@:>@])], + [], + [enable_sdl=no]) +AS_IF([test "x$enable_sdl" = "xyes"], + [ + PKG_CHECK_EXISTS([sdl], + [], + [AC_MSG_ERROR([SDL support requested but SDL not found])]) + + SUPPORT_SDL=yes + GL_WINSYS_APIS="$GL_WINSYS_APIS sdl" + COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES sdl" + + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_SDL_SUPPORT" + ], + [SUPPORT_SDL=no]) +AM_CONDITIONAL(SUPPORT_SDL, [test "x$SUPPORT_SDL" = "xyes"]) dnl ======================================================== dnl Check X11 dependencies if required