[cogl] Update the SDL winsys



commit bdcbb8af4db9a94614b848da49ccc1f65cda285d
Author: Neil Roberts <neil linux intel com>
Date:   Wed Dec 14 12:09:53 2011 +0000

    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 <robert linux intel com>

 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 2589e78..c25647e 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 5e5ae04..5f65383 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);
 
@@ -103,6 +106,9 @@ static CoglWinsysVtableGetter _cogl_winsys_vtable_getters[] =
 #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 e621b49..94d4de9 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 bb8908b..c71f402 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 <http://www.gnu.org/licenses/>.
  *
  *
+ * Authors:
+ *   Neil Roberts <neil linux intel com>
  */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
-#include "cogl.h"
+#include <SDL.h>
 
-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
+{
+  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)
 {
-  return NULL;
+  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 9ce91eb..d05c9d0 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



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]