[clutter] Add a vtable of indirection to the winsys code



commit 75e6d734c1b831e11831270d1777b84b689dca6a
Author: Robert Bragg <robert linux intel com>
Date:   Fri Feb 25 11:29:08 2011 +0000

    Add a vtable of indirection to the winsys code
    
    So that we can dynamically select what winsys backend to use at runtime
    we need to have some indirection to how code accesses the winsys instead
    of simply calling _cogl_winsys* functions that would collide if we
    wanted to compile more than one backend into Cogl.

 clutter/cogl/cogl/cogl-clutter.c                   |    8 +-
 clutter/cogl/cogl/cogl-context-private.h           |    3 +
 clutter/cogl/cogl/cogl-context.c                   |   19 ++-
 clutter/cogl/cogl/cogl-display.c                   |   14 ++-
 clutter/cogl/cogl/cogl-framebuffer.c               |   71 ++++++--
 clutter/cogl/cogl/cogl-renderer-private.h          |    2 +
 clutter/cogl/cogl/cogl-renderer.c                  |   76 +++++++-
 clutter/cogl/cogl/cogl.c                           |    9 +
 clutter/cogl/cogl/winsys/cogl-texture-pixmap-x11.c |   42 ++++-
 clutter/cogl/cogl/winsys/cogl-winsys-egl.c         |  162 +++++++++--------
 clutter/cogl/cogl/winsys/cogl-winsys-glx.c         |  194 +++++++++++++-------
 clutter/cogl/cogl/winsys/cogl-winsys-private.h     |  122 ++++++------
 12 files changed, 482 insertions(+), 240 deletions(-)
---
diff --git a/clutter/cogl/cogl/cogl-clutter.c b/clutter/cogl/cogl/cogl-clutter.c
index facdeb3..49821ac 100644
--- a/clutter/cogl/cogl/cogl-clutter.c
+++ b/clutter/cogl/cogl/cogl-clutter.c
@@ -68,6 +68,12 @@ cogl_onscreen_clutter_backend_set_size (int width, int height)
 XVisualInfo *
 cogl_clutter_winsys_xlib_get_visual_info (void)
 {
-  return _cogl_winsys_xlib_get_visual_info ();
+  const CoglWinsysVtable *winsys;
+
+  _COGL_GET_CONTEXT (ctx, NULL);
+
+  winsys = _cogl_context_get_winsys (ctx);
+
+  return winsys->xlib_get_visual_info ();
 }
 #endif
diff --git a/clutter/cogl/cogl/cogl-context-private.h b/clutter/cogl/cogl/cogl-context-private.h
index 9093b44..2f1642c 100644
--- a/clutter/cogl/cogl/cogl-context-private.h
+++ b/clutter/cogl/cogl/cogl-context-private.h
@@ -268,6 +268,9 @@ struct _CoglContext
 CoglContext *
 _cogl_context_get_default ();
 
+const CoglWinsysVtable *
+_cogl_context_get_winsys (CoglContext *context);
+
 /* Obtains the context and returns retval if NULL */
 #define _COGL_GET_CONTEXT(ctxvar, retval) \
 CoglContext *ctxvar = _cogl_context_get_default (); \
diff --git a/clutter/cogl/cogl/cogl-context.c b/clutter/cogl/cogl/cogl-context.c
index e1b18f6..d8dc5c6 100644
--- a/clutter/cogl/cogl/cogl-context.c
+++ b/clutter/cogl/cogl/cogl-context.c
@@ -33,6 +33,8 @@
 #include "cogl-profile.h"
 #include "cogl-util.h"
 #include "cogl-context-private.h"
+#include "cogl-display-private.h"
+#include "cogl-renderer-private.h"
 #include "cogl-journal-private.h"
 #include "cogl-texture-private.h"
 #include "cogl-pipeline-private.h"
@@ -83,6 +85,12 @@ _cogl_init_feature_overrides (CoglContext *ctx)
                             COGL_FEATURE_TEXTURE_NPOT_REPEAT);
 }
 
+const CoglWinsysVtable *
+_cogl_context_get_winsys (CoglContext *context)
+{
+  return context->display->renderer->winsys_vtable;
+}
+
 /* For reference: There was some deliberation over whether to have a
  * constructor that could throw an exception but looking at standard
  * practices with several high level OO languages including python, C++,
@@ -99,6 +107,7 @@ cogl_context_new (CoglDisplay *display,
   CoglContext *context;
   GLubyte default_texture_data[] = { 0xff, 0xff, 0xff, 0x0 };
   unsigned long enable_flags = 0;
+  const CoglWinsysVtable *winsys;
   int i;
 
 #ifdef CLUTTER_ENABLE_PROFILE
@@ -155,7 +164,8 @@ cogl_context_new (CoglDisplay *display,
 
 #ifdef COGL_HAS_FULL_WINSYS
   context->stub_winsys = FALSE;
-  if (!_cogl_winsys_context_init (context, error))
+  winsys = _cogl_context_get_winsys (context);
+  if (!winsys->context_init (context, error))
     {
       cogl_object_unref (display);
       g_free (context);
@@ -365,7 +375,9 @@ cogl_context_new (CoglDisplay *display,
 static void
 _cogl_context_free (CoglContext *context)
 {
-  _cogl_winsys_context_deinit (context);
+  const CoglWinsysVtable *winsys = _cogl_context_get_winsys (context);
+
+  winsys->context_deinit (context);
 
   _cogl_destroy_texture_units ();
 
@@ -480,7 +492,8 @@ cogl_set_default_context (CoglContext *context)
 EGLDisplay
 cogl_context_egl_get_egl_display (CoglContext *context)
 {
-  return _cogl_winsys_context_egl_get_egl_display (context);
+  const CoglWinsysVtable *winsys = _cogl_context_get_winsys (context);
+  return winsys->context_egl_get_egl_display (context);
 }
 #endif
 
diff --git a/clutter/cogl/cogl/cogl-display.c b/clutter/cogl/cogl/cogl-display.c
index a09de18..bb792b7 100644
--- a/clutter/cogl/cogl/cogl-display.c
+++ b/clutter/cogl/cogl/cogl-display.c
@@ -32,6 +32,7 @@
 #include "cogl-object.h"
 
 #include "cogl-display-private.h"
+#include "cogl-renderer-private.h"
 #include "cogl-winsys-private.h"
 
 static void _cogl_display_free (CoglDisplay *display);
@@ -93,15 +94,26 @@ cogl_display_new (CoglRenderer *renderer,
   return _cogl_display_object_new (display);
 }
 
+static const CoglWinsysVtable *
+_cogl_display_get_winsys (CoglDisplay *display)
+{
+  return display->renderer->winsys_vtable;
+}
+
 gboolean
 cogl_display_setup (CoglDisplay *display,
                     GError **error)
 {
+#ifdef COGL_HAS_FULL_WINSYS
+  const CoglWinsysVtable *winsys;
+#endif
+
   if (display->setup)
     return TRUE;
 
 #ifdef COGL_HAS_FULL_WINSYS
-  if (!_cogl_winsys_display_setup (display, error))
+  winsys = _cogl_display_get_winsys (display);
+  if (!winsys->display_setup (display, error))
     return FALSE;
 #endif
 
diff --git a/clutter/cogl/cogl/cogl-framebuffer.c b/clutter/cogl/cogl/cogl-framebuffer.c
index 8f0769d..9712fe7 100644
--- a/clutter/cogl/cogl/cogl-framebuffer.c
+++ b/clutter/cogl/cogl/cogl-framebuffer.c
@@ -29,6 +29,8 @@
 #include "cogl-debug.h"
 #include "cogl-internal.h"
 #include "cogl-context-private.h"
+#include "cogl-display-private.h"
+#include "cogl-renderer-private.h"
 #include "cogl-handle.h"
 #include "cogl-object-private.h"
 #include "cogl-util.h"
@@ -231,6 +233,12 @@ _cogl_framebuffer_free (CoglFramebuffer *framebuffer)
   cogl_object_unref (ctx);
 }
 
+static const CoglWinsysVtable *
+_cogl_framebuffer_get_winsys (CoglFramebuffer *framebuffer)
+{
+  return framebuffer->context->display->renderer->winsys_vtable;
+}
+
 /* This version of cogl_clear can be used internally as an alternative
  * to avoid flushing the journal or the framebuffer state. This is
  * needed when doing operations that may be called whiling flushing
@@ -1012,6 +1020,7 @@ cogl_framebuffer_allocate (CoglFramebuffer *framebuffer,
                            GError **error)
 {
   CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
+  const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer);
 
   if (framebuffer->allocated)
     return TRUE;
@@ -1021,7 +1030,7 @@ cogl_framebuffer_allocate (CoglFramebuffer *framebuffer,
   g_return_val_if_fail (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN,
                         TRUE);
 
-  if (!_cogl_winsys_onscreen_init (onscreen, error))
+  if (!winsys->onscreen_init (onscreen, error))
     return FALSE;
 
   framebuffer->allocated = TRUE;
@@ -1032,10 +1041,14 @@ cogl_framebuffer_allocate (CoglFramebuffer *framebuffer,
 static void
 _cogl_onscreen_free (CoglOnscreen *onscreen)
 {
-  _cogl_winsys_onscreen_deinit (onscreen);
+  CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
+  const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer);
+
+  winsys->onscreen_deinit (onscreen);
+  g_return_if_fail (onscreen->winsys == NULL);
 
   /* Chain up to parent */
-  _cogl_framebuffer_free (COGL_FRAMEBUFFER (onscreen));
+  _cogl_framebuffer_free (framebuffer);
 
   g_free (onscreen);
 }
@@ -1350,7 +1363,9 @@ bind_gl_framebuffer (CoglContext *ctx,
   else
     {
 #ifdef COGL_HAS_FULL_WINSYS
-      _cogl_winsys_onscreen_bind (COGL_ONSCREEN (framebuffer));
+      const CoglWinsysVtable *winsys =
+        _cogl_framebuffer_get_winsys (framebuffer);
+      winsys->onscreen_bind (COGL_ONSCREEN (framebuffer));
 #endif
       GE (glBindFramebuffer (target, 0));
     }
@@ -1582,7 +1597,11 @@ cogl_framebuffer_swap_buffers (CoglFramebuffer *framebuffer)
   /* FIXME: we shouldn't need to flush *all* journals here! */
   cogl_flush ();
   if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
-    _cogl_winsys_onscreen_swap_buffers (COGL_ONSCREEN (framebuffer));
+    {
+      const CoglWinsysVtable *winsys =
+        _cogl_framebuffer_get_winsys (framebuffer);
+      winsys->onscreen_swap_buffers (COGL_ONSCREEN (framebuffer));
+    }
 }
 
 void
@@ -1593,9 +1612,13 @@ cogl_framebuffer_swap_region (CoglFramebuffer *framebuffer,
   /* FIXME: we shouldn't need to flush *all* journals here! */
   cogl_flush ();
   if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
-    _cogl_winsys_onscreen_swap_region (COGL_ONSCREEN (framebuffer),
-                                       rectangles,
-                                       n_rectangles);
+    {
+      const CoglWinsysVtable *winsys =
+        _cogl_framebuffer_get_winsys (framebuffer);
+      winsys->onscreen_swap_region (COGL_ONSCREEN (framebuffer),
+                                    rectangles,
+                                    n_rectangles);
+    }
 }
 
 #ifdef COGL_HAS_X11_SUPPORT
@@ -1609,15 +1632,20 @@ cogl_onscreen_x11_set_foreign_window_xid (CoglOnscreen *onscreen,
 guint32
 cogl_onscreen_x11_get_window_xid (CoglOnscreen *onscreen)
 {
-  return _cogl_winsys_onscreen_x11_get_window_xid (onscreen);
+  CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
+  const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer);
+
+  return winsys->onscreen_x11_get_window_xid (onscreen);
 }
 
 guint32
 cogl_onscreen_x11_get_visual_xid (CoglOnscreen *onscreen)
 {
-  guint32 id;
-  XVisualInfo *visinfo = _cogl_winsys_xlib_get_visual_info ();
-  id = (guint32)visinfo->visualid;
+  CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
+  const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer);
+  XVisualInfo *visinfo = winsys->xlib_get_visual_info ();
+  guint32 id = (guint32)visinfo->visualid;
+
   XFree (visinfo);
   return id;
 }
@@ -1629,13 +1657,14 @@ cogl_framebuffer_add_swap_buffers_callback (CoglFramebuffer *framebuffer,
                                             void *user_data)
 {
   CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
+  const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer);
 
   /* Should this just be cogl_onscreen API instead? */
   g_return_val_if_fail (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN, 0);
 
-  return _cogl_winsys_onscreen_add_swap_buffers_callback (onscreen,
-                                                          callback,
-                                                          user_data);
+  return winsys->onscreen_add_swap_buffers_callback (onscreen,
+                                                     callback,
+                                                     user_data);
 }
 
 void
@@ -1643,15 +1672,21 @@ cogl_framebuffer_remove_swap_buffers_callback (CoglFramebuffer *framebuffer,
                                                unsigned int id)
 {
   CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
+  const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer);
 
-  _cogl_winsys_onscreen_remove_swap_buffers_callback (onscreen, id);
+  winsys->onscreen_remove_swap_buffers_callback (onscreen, id);
 }
 
 void
 cogl_onscreen_set_swap_throttled (CoglOnscreen *onscreen,
                                   gboolean throttled)
 {
+  CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   onscreen->swap_throttled = throttled;
-  if (COGL_FRAMEBUFFER (onscreen)->allocated)
-    _cogl_winsys_onscreen_update_swap_throttled (onscreen);
+  if (framebuffer->allocated)
+    {
+      const CoglWinsysVtable *winsys =
+        _cogl_framebuffer_get_winsys (framebuffer);
+      winsys->onscreen_update_swap_throttled (onscreen);
+    }
 }
diff --git a/clutter/cogl/cogl/cogl-renderer-private.h b/clutter/cogl/cogl/cogl-renderer-private.h
index 6600825..8b9ebe7 100644
--- a/clutter/cogl/cogl/cogl-renderer-private.h
+++ b/clutter/cogl/cogl/cogl-renderer-private.h
@@ -25,6 +25,7 @@
 #define __COGL_RENDERER_PRIVATE_H
 
 #include "cogl-object-private.h"
+#include "cogl-winsys-private.h"
 
 #ifdef COGL_HAS_XLIB_SUPPORT
 #include <X11/Xlib.h>
@@ -34,6 +35,7 @@ struct _CoglRenderer
 {
   CoglObject _parent;
   gboolean connected;
+  const CoglWinsysVtable *winsys_vtable;
 #ifdef COGL_HAS_XLIB_SUPPORT
   Display *foreign_xdpy;
 #endif
diff --git a/clutter/cogl/cogl/cogl-renderer.c b/clutter/cogl/cogl/cogl-renderer.c
index 548c2f0..613b163 100644
--- a/clutter/cogl/cogl/cogl-renderer.c
+++ b/clutter/cogl/cogl/cogl-renderer.c
@@ -37,6 +37,29 @@
 #include "cogl-display-private.h"
 #include "cogl-winsys-private.h"
 
+#ifdef COGL_HAS_FULL_WINSYS
+
+#ifdef COGL_HAS_GLX_SUPPORT
+extern const CoglWinsysVtable *_cogl_winsys_glx_get_vtable (void);
+#endif
+#ifdef COGL_HAS_EGL_SUPPORT
+extern const CoglWinsysVtable *_cogl_winsys_egl_get_vtable (void);
+#endif
+
+typedef const CoglWinsysVtable *(*CoglWinsysVtableGetter) (void);
+
+static CoglWinsysVtableGetter _cogl_winsys_vtable_getters[] =
+{
+#ifdef COGL_HAS_GLX_SUPPORT
+  _cogl_winsys_glx_get_vtable,
+#endif
+#ifdef COGL_HAS_EGL_SUPPORT
+  _cogl_winsys_egl_get_vtable
+#endif
+};
+
+#endif /* COGL_HAS_FULL_WINSYS */
+
 static void _cogl_renderer_free (CoglRenderer *renderer);
 
 COGL_OBJECT_DEFINE (Renderer, renderer);
@@ -53,6 +76,12 @@ cogl_renderer_error_quark (void)
   return g_quark_from_static_string ("cogl-renderer-error-quark");
 }
 
+static const CoglWinsysVtable *
+_cogl_renderer_get_winsys (CoglRenderer *renderer)
+{
+  return renderer->winsys_vtable;
+}
+
 static void
 native_filter_closure_free (CoglNativeFilterClosure *closure)
 {
@@ -63,7 +92,8 @@ static void
 _cogl_renderer_free (CoglRenderer *renderer)
 {
 #ifdef COGL_HAS_FULL_WINSYS
-  _cogl_winsys_renderer_disconnect (renderer);
+  const CoglWinsysVtable *winsys = _cogl_renderer_get_winsys (renderer);
+  winsys->renderer_disconnect (renderer);
 #endif
 
   g_slist_foreach (renderer->event_filters,
@@ -114,8 +144,9 @@ cogl_renderer_check_onscreen_template (CoglRenderer *renderer,
 {
 #ifdef COGL_HAS_FULL_WINSYS
   CoglDisplay *display;
+  const CoglWinsysVtable *winsys = _cogl_renderer_get_winsys (renderer);
 
-  if (!_cogl_winsys_renderer_connect (renderer, error))
+  if (!winsys->renderer_connect (renderer, error))
     return FALSE;
 
   display = cogl_display_new (renderer, onscreen_template);
@@ -135,16 +166,51 @@ cogl_renderer_check_onscreen_template (CoglRenderer *renderer,
 gboolean
 cogl_renderer_connect (CoglRenderer *renderer, GError **error)
 {
+#ifdef COGL_HAS_FULL_WINSYS
+  int i;
+#endif
+  GString *error_message;
+
   if (renderer->connected)
     return TRUE;
 
 #ifdef COGL_HAS_FULL_WINSYS
-  if (!_cogl_winsys_renderer_connect (renderer, error))
-    return FALSE;
-#endif
+  error_message = g_string_new ("");
+  for (i = 0; i < G_N_ELEMENTS (_cogl_winsys_vtable_getters); i++)
+    {
+      const CoglWinsysVtable *winsys = _cogl_winsys_vtable_getters[i]();
+      GError *tmp_error = NULL;
+      if (!winsys->renderer_connect (renderer, &tmp_error))
+        {
+          g_string_append_c (error_message, '\n');
+          g_string_append (error_message, tmp_error->message);
+          g_error_free (tmp_error);
+        }
+      else
+        {
+          renderer->winsys_vtable = winsys;
+          renderer->connected = TRUE;
+          g_string_free (error_message, TRUE);
+          return TRUE;
+        }
+    }
 
+  if (!renderer->connected)
+    {
+      renderer->winsys_vtable = NULL;
+      g_set_error (error, COGL_WINSYS_ERROR,
+                   COGL_WINSYS_ERROR_INIT,
+                   "Failed to connected to any renderer: %s",
+                   error_message->str);
+      g_string_free (error_message, TRUE);
+      return FALSE;
+    }
+
+  return TRUE;
+#else
   renderer->connected = TRUE;
   return TRUE;
+#endif
 }
 
 CoglFilterReturn
diff --git a/clutter/cogl/cogl/cogl.c b/clutter/cogl/cogl/cogl.c
index 4dbe4ae..69ed652 100644
--- a/clutter/cogl/cogl/cogl.c
+++ b/clutter/cogl/cogl/cogl.c
@@ -93,8 +93,17 @@ cogl_get_proc_address (const char* name)
 {
   void *address;
   static GModule *module = NULL;
+#ifdef COGL_HAS_FULL_WINSYS
+  const CoglWinsysVtable *winsys;
 
+  _COGL_GET_CONTEXT (ctx, NULL);
+
+  winsys = _cogl_context_get_winsys (ctx);
+
+  address = winsys->get_proc_address (name);
+#else
   address = _cogl_winsys_get_proc_address (name);
+#endif
   if (address)
     return address;
 
diff --git a/clutter/cogl/cogl/winsys/cogl-texture-pixmap-x11.c b/clutter/cogl/cogl/winsys/cogl-texture-pixmap-x11.c
index c59d760..01657d1 100644
--- a/clutter/cogl/cogl/winsys/cogl-texture-pixmap-x11.c
+++ b/clutter/cogl/cogl/winsys/cogl-texture-pixmap-x11.c
@@ -42,6 +42,8 @@
 #include "cogl-texture-2d-private.h"
 #include "cogl-texture-rectangle-private.h"
 #include "cogl-context-private.h"
+#include "cogl-display-private.h"
+#include "cogl-renderer-private.h"
 #include "cogl-handle.h"
 #include "cogl-winsys-private.h"
 #include "cogl-pipeline-opengl-private.h"
@@ -101,12 +103,23 @@ cogl_damage_rectangle_is_whole (const CoglDamageRectangle *damage_rect,
           && damage_rect->x2 == width && damage_rect->y2 == height);
 }
 
+static const CoglWinsysVtable *
+_cogl_texture_pixmap_x11_get_winsys (CoglTexturePixmapX11 *tex_pixmap)
+{
+  /* FIXME: A CoglContext should be reachable from a CoglTexture
+   * pointer */
+  _COGL_GET_CONTEXT (ctx, NULL);
+
+  return ctx->display->renderer->winsys_vtable;
+}
+
 static void
 process_damage_event (CoglTexturePixmapX11 *tex_pixmap,
                       XDamageNotifyEvent *damage_event)
 {
   Display *display;
   enum { DO_NOTHING, NEEDS_SUBTRACT, NEED_BOUNDING_BOX } handle_mode;
+  const CoglWinsysVtable *winsys;
 
   _COGL_GET_CONTEXT (ctxt, NO_RETVAL);
 
@@ -195,7 +208,8 @@ process_damage_event (CoglTexturePixmapX11 *tex_pixmap,
   /* If we're using the texture from pixmap extension then there's no
      point in getting the region and we can just mark that the texture
      needs updating */
-  _cogl_winsys_texture_pixmap_x11_damage_notify (tex_pixmap);
+  winsys = _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
+  winsys->texture_pixmap_x11_damage_notify (tex_pixmap);
 }
 
 static CoglFilterReturn
@@ -254,6 +268,7 @@ cogl_texture_pixmap_x11_new (guint32 pixmap,
   CoglTexture *tex = COGL_TEXTURE (tex_pixmap);
   XWindowAttributes window_attributes;
   int damage_base;
+  const CoglWinsysVtable *winsys;
 
   _COGL_GET_CONTEXT (ctxt, COGL_INVALID_HANDLE);
 
@@ -307,7 +322,9 @@ cogl_texture_pixmap_x11_new (guint32 pixmap,
   tex_pixmap->damage_rect.y1 = 0;
   tex_pixmap->damage_rect.y2 = tex_pixmap->height;
 
-  _cogl_winsys_texture_pixmap_x11_create (tex_pixmap);
+  winsys = _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
+  if (winsys->texture_pixmap_x11_create)
+    winsys->texture_pixmap_x11_create (tex_pixmap);
 
   return _cogl_texture_pixmap_x11_handle_new (tex_pixmap);
 }
@@ -390,6 +407,7 @@ cogl_texture_pixmap_x11_update_area (CoglHandle handle,
                                      int height)
 {
   CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (handle);
+  const CoglWinsysVtable *winsys;
 
   if (!cogl_is_texture_pixmap_x11 (handle))
     return;
@@ -398,7 +416,8 @@ cogl_texture_pixmap_x11_update_area (CoglHandle handle,
      texture because we can't determine which will be needed until we
      actually render something */
 
-  _cogl_winsys_texture_pixmap_x11_damage_notify (tex_pixmap);
+  winsys = _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
+  winsys->texture_pixmap_x11_damage_notify (tex_pixmap);
 
   cogl_damage_rectangle_union (&tex_pixmap->damage_rect,
                                x, y, width, height);
@@ -617,7 +636,10 @@ _cogl_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
 {
   if (tex_pixmap->winsys)
     {
-      if (_cogl_winsys_texture_pixmap_x11_update (tex_pixmap, needs_mipmap))
+      const CoglWinsysVtable *winsys =
+        _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
+
+      if (winsys->texture_pixmap_x11_update (tex_pixmap, needs_mipmap))
         {
           _cogl_texture_pixmap_x11_set_use_winsys_texture (tex_pixmap, TRUE);
           return;
@@ -649,7 +671,11 @@ _cogl_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap)
   for (i = 0; i < 2; i++)
     {
       if (tex_pixmap->use_winsys_texture)
-        tex = _cogl_winsys_texture_pixmap_x11_get_texture (tex_pixmap);
+        {
+          const CoglWinsysVtable *winsys =
+            _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
+          tex = winsys->texture_pixmap_x11_get_texture (tex_pixmap);
+        }
       else
         tex = tex_pixmap->tex;
 
@@ -912,7 +938,11 @@ _cogl_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap)
     cogl_handle_unref (tex_pixmap->tex);
 
   if (tex_pixmap->winsys)
-    _cogl_winsys_texture_pixmap_x11_free (tex_pixmap);
+    {
+      const CoglWinsysVtable *winsys =
+        _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
+      winsys->texture_pixmap_x11_free (tex_pixmap);
+    }
 
   /* Chain up */
   _cogl_texture_free (COGL_TEXTURE (tex_pixmap));
diff --git a/clutter/cogl/cogl/winsys/cogl-winsys-egl.c b/clutter/cogl/cogl/winsys/cogl-winsys-egl.c
index 44583af..46f5842 100644
--- a/clutter/cogl/cogl/winsys/cogl-winsys-egl.c
+++ b/clutter/cogl/cogl/winsys/cogl-winsys-egl.c
@@ -168,7 +168,7 @@ static const CoglFeatureData winsys_feature_data[] =
 #include "cogl-winsys-egl-feature-functions.h"
   };
 
-CoglFuncPtr
+static CoglFuncPtr
 _cogl_winsys_get_proc_address (const char *name)
 {
   return (CoglFuncPtr) eglGetProcAddress (name);
@@ -237,7 +237,21 @@ event_filter_cb (void *event, void *data)
 }
 #endif /* COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT */
 
-gboolean
+static void
+_cogl_winsys_renderer_disconnect (CoglRenderer *renderer)
+{
+  CoglRendererEGL *egl_renderer = renderer->winsys;
+
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+  _cogl_renderer_xlib_disconnect (renderer);
+#endif
+
+  eglTerminate (egl_renderer->edpy);
+
+  g_slice_free (CoglRendererEGL, egl_renderer);
+}
+
+static gboolean
 _cogl_winsys_renderer_connect (CoglRenderer *renderer,
                                GError **error)
 {
@@ -285,21 +299,7 @@ error:
   return FALSE;
 }
 
-void
-_cogl_winsys_renderer_disconnect (CoglRenderer *renderer)
-{
-  CoglRendererEGL *egl_renderer = renderer->winsys;
-
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
-  _cogl_renderer_xlib_disconnect (renderer);
-#endif
-
-  eglTerminate (egl_renderer->edpy);
-
-  g_slice_free (CoglRendererEGL, egl_renderer);
-}
-
-void
+static void
 update_winsys_features (CoglContext *context)
 {
   CoglDisplayEGL *egl_display = context->display->winsys;
@@ -675,7 +675,20 @@ create_context (CoglDisplay *display, GError **error)
   return status;
 }
 
-gboolean
+static void
+_cogl_winsys_display_destroy (CoglDisplay *display)
+{
+  CoglDisplayEGL *egl_display = display->winsys;
+
+  g_return_if_fail (egl_display != NULL);
+
+  cleanup_context (display);
+
+  g_slice_free (CoglDisplayEGL, display->winsys);
+  display->winsys = NULL;
+}
+
+static gboolean
 _cogl_winsys_display_setup (CoglDisplay *display,
                             GError **error)
 {
@@ -698,20 +711,7 @@ error:
   return FALSE;
 }
 
-void
-_cogl_winsys_display_destroy (CoglDisplay *display)
-{
-  CoglDisplayEGL *egl_display = display->winsys;
-
-  g_return_if_fail (egl_display != NULL);
-
-  cleanup_context (display);
-
-  g_slice_free (CoglDisplayEGL, display->winsys);
-  display->winsys = NULL;
-}
-
-gboolean
+static gboolean
 _cogl_winsys_context_init (CoglContext *context, GError **error)
 {
   context->winsys = g_new0 (CoglContextEGL, 1);
@@ -726,7 +726,7 @@ _cogl_winsys_context_init (CoglContext *context, GError **error)
   return TRUE;
 }
 
-void
+static void
 _cogl_winsys_context_deinit (CoglContext *context)
 {
 #ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
@@ -737,7 +737,7 @@ _cogl_winsys_context_deinit (CoglContext *context)
   g_free (context->winsys);
 }
 
-gboolean
+static gboolean
 _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
                             GError **error)
 {
@@ -896,7 +896,7 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
   return TRUE;
 }
 
-void
+static void
 _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
 {
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
@@ -941,7 +941,7 @@ _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
 #endif
 }
 
-void
+static void
 _cogl_winsys_onscreen_bind (CoglOnscreen *onscreen)
 {
   CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
@@ -982,7 +982,7 @@ _cogl_winsys_onscreen_bind (CoglOnscreen *onscreen)
     eglSwapInterval (egl_renderer->edpy, 0);
 }
 
-void
+static void
 _cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
                                    int *rectangles,
                                    int n_rectangles)
@@ -998,14 +998,14 @@ _cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
     g_warning ("Error reported by eglSwapBuffersRegion");
 }
 
-guint32
+static guint32
 _cogl_winsys_get_vsync_counter (void)
 {
   /* Unsupported feature */
   return 0;
 }
 
-void
+static void
 _cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
 {
   CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
@@ -1015,14 +1015,14 @@ _cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
   eglSwapBuffers (egl_renderer->edpy, egl_onscreen->egl_surface);
 }
 
-guint32
+static guint32
 _cogl_winsys_onscreen_x11_get_window_xid (CoglOnscreen *onscreen)
 {
   CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
   return xlib_onscreen->xwin;
 }
 
-unsigned int
+static unsigned int
 _cogl_winsys_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen,
                                                  CoglSwapBuffersNotify callback,
                                                  void *user_data)
@@ -1031,14 +1031,14 @@ _cogl_winsys_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen,
   return 0;
 }
 
-void
+static void
 _cogl_winsys_onscreen_remove_swap_buffers_callback (CoglOnscreen *onscreen,
                                                     unsigned int id)
 {
   /* Unsupported feature */
 }
 
-void
+static void
 _cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen)
 {
   CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
@@ -1054,7 +1054,7 @@ _cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen)
 
 #ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
 /* XXX: This is a particularly hacky _cogl_winsys interface... */
-XVisualInfo *
+static XVisualInfo *
 _cogl_winsys_xlib_get_visual_info (void)
 {
   CoglDisplayEGL *egl_display;
@@ -1072,7 +1072,7 @@ _cogl_winsys_xlib_get_visual_info (void)
 }
 #endif
 
-EGLDisplay
+static EGLDisplay
 _cogl_winsys_context_egl_get_egl_display (CoglContext *context)
 {
   CoglRendererEGL *egl_renderer = context->display->renderer->winsys;
@@ -1080,37 +1080,47 @@ _cogl_winsys_context_egl_get_egl_display (CoglContext *context)
   return egl_renderer->edpy;
 }
 
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
-gboolean
-_cogl_winsys_texture_pixmap_x11_create (CoglTexturePixmapX11 *tex_pixmap)
-{
-  /* Unsupported feature */
-  tex_pixmap->winsys = NULL;
-  return FALSE;
-}
-
-void
-_cogl_winsys_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap)
-{
-  /* Unsupported feature */
-}
-
-gboolean
-_cogl_winsys_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
-                                        gboolean needs_mipmap)
-{
-  /* Unsupported feature */
-}
-
-void
-_cogl_winsys_texture_pixmap_x11_damage_notify (CoglTexturePixmapX11 *tex_pixmap)
-{
-  /* Unsupported feature */
-}
+static CoglWinsysVtable _cogl_winsys_vtable =
+  {
+    .get_proc_address = _cogl_winsys_get_proc_address,
+    .renderer_connect = _cogl_winsys_renderer_connect,
+    .renderer_disconnect = _cogl_winsys_renderer_disconnect,
+    .display_setup = _cogl_winsys_display_setup,
+    .display_destroy = _cogl_winsys_display_destroy,
+    .context_init = _cogl_winsys_context_init,
+    .context_deinit = _cogl_winsys_context_deinit,
+    .context_egl_get_egl_display =
+      _cogl_winsys_context_egl_get_egl_display,
+#ifdef COGL_HAS_XLIB_SUPPORT
+    .xlib_get_visual_info = _cogl_winsys_xlib_get_visual_info,
+#endif
+    .onscreen_init = _cogl_winsys_onscreen_init,
+    .onscreen_deinit = _cogl_winsys_onscreen_deinit,
+    .onscreen_bind = _cogl_winsys_onscreen_bind,
+    .onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers,
+    .onscreen_swap_region = _cogl_winsys_onscreen_swap_region,
+    .onscreen_update_swap_throttled =
+      _cogl_winsys_onscreen_update_swap_throttled,
+    .onscreen_x11_get_window_xid =
+      _cogl_winsys_onscreen_x11_get_window_xid,
+    .onscreen_add_swap_buffers_callback =
+      _cogl_winsys_onscreen_add_swap_buffers_callback,
+    .onscreen_remove_swap_buffers_callback =
+      _cogl_winsys_onscreen_remove_swap_buffers_callback,
+    .get_vsync_counter = _cogl_winsys_get_vsync_counter
+  };
 
-CoglHandle
-_cogl_winsys_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap)
+/* XXX: we use a function because no doubt someone will complain
+ * about using c99 member initializers because they aren't portable
+ * to windows. We want to avoid having to rigidly follow the real
+ * order of members since some members are #ifdefd and we'd have
+ * to mirror the #ifdefing to add padding etc. For any winsys that
+ * can assume the platform has a sane compiler then we can just use
+ * c99 initializers for insane platforms they can initialize
+ * the members by name in a function.
+ */
+const CoglWinsysVtable *
+_cogl_winsys_egl_get_vtable (void)
 {
-  /* Unsupported feature */
+  return &_cogl_winsys_vtable;
 }
-#endif
diff --git a/clutter/cogl/cogl/winsys/cogl-winsys-glx.c b/clutter/cogl/cogl/winsys/cogl-winsys-glx.c
index 7668a5f..26ad6e6 100644
--- a/clutter/cogl/cogl/winsys/cogl-winsys-glx.c
+++ b/clutter/cogl/cogl/winsys/cogl-winsys-glx.c
@@ -277,7 +277,15 @@ glx_event_filter_cb (void *native_event, void *data)
   return COGL_FILTER_CONTINUE;
 }
 
-gboolean
+static void
+_cogl_winsys_renderer_disconnect (CoglRenderer *renderer)
+{
+  _cogl_renderer_xlib_disconnect (renderer);
+
+  g_slice_free (CoglRendererGLX, renderer->winsys);
+}
+
+static gboolean
 _cogl_winsys_renderer_connect (CoglRenderer *renderer,
                                GError **error)
 {
@@ -325,15 +333,7 @@ error:
   return FALSE;
 }
 
-void
-_cogl_winsys_renderer_disconnect (CoglRenderer *renderer)
-{
-  _cogl_renderer_xlib_disconnect (renderer);
-
-  g_slice_free (CoglRendererGLX, renderer->winsys);
-}
-
-void
+static void
 update_winsys_features (CoglContext *context)
 {
   CoglDisplayGLX *glx_display = context->display->winsys;
@@ -625,32 +625,7 @@ create_context (CoglDisplay *display, GError **error)
   return TRUE;
 }
 
-gboolean
-_cogl_winsys_display_setup (CoglDisplay *display,
-                            GError **error)
-{
-  CoglDisplayGLX *glx_display;
-  int i;
-
-  g_return_val_if_fail (display->winsys == NULL, FALSE);
-
-  glx_display = g_slice_new0 (CoglDisplayGLX);
-  display->winsys = glx_display;
-
-  if (!create_context (display, error))
-    goto error;
-
-  for (i = 0; i < COGL_GLX_N_CACHED_CONFIGS; i++)
-    glx_display->glx_cached_configs[i].depth = -1;
-
-  return TRUE;
-
-error:
-  _cogl_winsys_display_destroy (display);
-  return FALSE;
-}
-
-void
+static void
 _cogl_winsys_display_destroy (CoglDisplay *display)
 {
   CoglDisplayGLX *glx_display = display->winsys;
@@ -682,7 +657,32 @@ _cogl_winsys_display_destroy (CoglDisplay *display)
   display->winsys = NULL;
 }
 
-gboolean
+static gboolean
+_cogl_winsys_display_setup (CoglDisplay *display,
+                            GError **error)
+{
+  CoglDisplayGLX *glx_display;
+  int i;
+
+  g_return_val_if_fail (display->winsys == NULL, FALSE);
+
+  glx_display = g_slice_new0 (CoglDisplayGLX);
+  display->winsys = glx_display;
+
+  if (!create_context (display, error))
+    goto error;
+
+  for (i = 0; i < COGL_GLX_N_CACHED_CONFIGS; i++)
+    glx_display->glx_cached_configs[i].depth = -1;
+
+  return TRUE;
+
+error:
+  _cogl_winsys_display_destroy (display);
+  return FALSE;
+}
+
+static gboolean
 _cogl_winsys_context_init (CoglContext *context, GError **error)
 {
   context->winsys = g_new0 (CoglContextGLX, 1);
@@ -695,7 +695,7 @@ _cogl_winsys_context_init (CoglContext *context, GError **error)
   return TRUE;
 }
 
-void
+static void
 _cogl_winsys_context_deinit (CoglContext *context)
 {
   cogl_renderer_remove_native_filter (context->display->renderer,
@@ -704,7 +704,7 @@ _cogl_winsys_context_deinit (CoglContext *context)
   g_free (context->winsys);
 }
 
-gboolean
+static gboolean
 _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
                             GError **error)
 {
@@ -859,7 +859,7 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
   return TRUE;
 }
 
-void
+static void
 _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
 {
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
@@ -890,7 +890,7 @@ _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
   _cogl_xlib_untrap_errors (&old_state);
 }
 
-void
+static void
 _cogl_winsys_onscreen_bind (CoglOnscreen *onscreen)
 {
   CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
@@ -1002,7 +1002,7 @@ drm_wait_vblank (int fd, drm_wait_vblank_t *vbl)
 }
 #endif /* HAVE_DRM */
 
-void
+static void
 _cogl_winsys_wait_for_vblank (void)
 {
   CoglRendererGLX *glx_renderer;
@@ -1034,7 +1034,22 @@ _cogl_winsys_wait_for_vblank (void)
 #endif /* HAVE_DRM */
 }
 
-void
+static guint32
+_cogl_winsys_get_vsync_counter (void)
+{
+  guint32 video_sync_count;
+  CoglRendererGLX *glx_renderer;
+
+  _COGL_GET_CONTEXT (ctx, 0);
+
+  glx_renderer = ctx->display->renderer->winsys;
+
+  glx_renderer->pf_glXGetVideoSync (&video_sync_count);
+
+  return video_sync_count;
+}
+
+static void
 _cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
                                    int *rectangles,
                                    int n_rectangles)
@@ -1167,22 +1182,7 @@ _cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
     glx_onscreen->last_swap_vsync_counter = end_frame_vsync_counter;
 }
 
-guint32
-_cogl_winsys_get_vsync_counter (void)
-{
-  guint32 video_sync_count;
-  CoglRendererGLX *glx_renderer;
-
-  _COGL_GET_CONTEXT (ctx, 0);
-
-  glx_renderer = ctx->display->renderer->winsys;
-
-  glx_renderer->pf_glXGetVideoSync (&video_sync_count);
-
-  return video_sync_count;
-}
-
-void
+static void
 _cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
 {
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
@@ -1259,14 +1259,14 @@ _cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
     glx_onscreen->last_swap_vsync_counter = _cogl_winsys_get_vsync_counter ();
 }
 
-guint32
+static guint32
 _cogl_winsys_onscreen_x11_get_window_xid (CoglOnscreen *onscreen)
 {
   CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
   return xlib_onscreen->xwin;
 }
 
-unsigned int
+static unsigned int
 _cogl_winsys_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen,
                                                  CoglSwapBuffersNotify callback,
                                                  void *user_data)
@@ -1285,7 +1285,7 @@ _cogl_winsys_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen,
   return entry->id;
 }
 
-void
+static void
 _cogl_winsys_onscreen_remove_swap_buffers_callback (CoglOnscreen *onscreen,
                                                     unsigned int id)
 {
@@ -1305,7 +1305,7 @@ _cogl_winsys_onscreen_remove_swap_buffers_callback (CoglOnscreen *onscreen,
     }
 }
 
-void
+static void
 _cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen)
 {
   CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
@@ -1323,7 +1323,7 @@ _cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen)
 }
 
 /* XXX: This is a particularly hacky _cogl_winsys interface... */
-XVisualInfo *
+static XVisualInfo *
 _cogl_winsys_xlib_get_visual_info (void)
 {
   CoglDisplayGLX *glx_display;
@@ -1616,7 +1616,7 @@ try_create_glx_pixmap (CoglContext *context,
   return TRUE;
 }
 
-gboolean
+static gboolean
 _cogl_winsys_texture_pixmap_x11_create (CoglTexturePixmapX11 *tex_pixmap)
 {
   CoglTexturePixmapGLX *glx_tex_pixmap;
@@ -1697,7 +1697,7 @@ free_glx_pixmap (CoglContext *context,
   glx_tex_pixmap->pixmap_bound = FALSE;
 }
 
-void
+static void
 _cogl_winsys_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap)
 {
   CoglTexturePixmapGLX *glx_tex_pixmap;
@@ -1720,7 +1720,7 @@ _cogl_winsys_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap)
   g_free (glx_tex_pixmap);
 }
 
-gboolean
+static gboolean
 _cogl_winsys_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
                                         gboolean needs_mipmap)
 {
@@ -1861,7 +1861,7 @@ _cogl_winsys_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
   return TRUE;
 }
 
-void
+static void
 _cogl_winsys_texture_pixmap_x11_damage_notify (CoglTexturePixmapX11 *tex_pixmap)
 {
   CoglTexturePixmapGLX *glx_tex_pixmap = tex_pixmap->winsys;
@@ -1869,10 +1869,66 @@ _cogl_winsys_texture_pixmap_x11_damage_notify (CoglTexturePixmapX11 *tex_pixmap)
   glx_tex_pixmap->bind_tex_image_queued = TRUE;
 }
 
-CoglHandle
+static CoglHandle
 _cogl_winsys_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap)
 {
   CoglTexturePixmapGLX *glx_tex_pixmap = tex_pixmap->winsys;
 
   return glx_tex_pixmap->glx_tex;
 }
+
+
+static CoglWinsysVtable _cogl_winsys_vtable =
+  {
+    .get_proc_address = _cogl_winsys_get_proc_address,
+    .renderer_connect = _cogl_winsys_renderer_connect,
+    .renderer_disconnect = _cogl_winsys_renderer_disconnect,
+    .display_setup = _cogl_winsys_display_setup,
+    .display_destroy = _cogl_winsys_display_destroy,
+    .context_init = _cogl_winsys_context_init,
+    .context_deinit = _cogl_winsys_context_deinit,
+    .xlib_get_visual_info = _cogl_winsys_xlib_get_visual_info,
+    .onscreen_init = _cogl_winsys_onscreen_init,
+    .onscreen_deinit = _cogl_winsys_onscreen_deinit,
+    .onscreen_bind = _cogl_winsys_onscreen_bind,
+    .onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers,
+    .onscreen_swap_region = _cogl_winsys_onscreen_swap_region,
+    .onscreen_update_swap_throttled =
+      _cogl_winsys_onscreen_update_swap_throttled,
+    .onscreen_x11_get_window_xid =
+      _cogl_winsys_onscreen_x11_get_window_xid,
+    .onscreen_add_swap_buffers_callback =
+      _cogl_winsys_onscreen_add_swap_buffers_callback,
+    .onscreen_remove_swap_buffers_callback =
+      _cogl_winsys_onscreen_remove_swap_buffers_callback,
+    .get_vsync_counter = _cogl_winsys_get_vsync_counter,
+
+    /* X11 tfp support... */
+    /* XXX: instead of having a rather monolithic winsys vtable we could
+     * perhaps look for a way to separate these... */
+    .texture_pixmap_x11_create =
+      _cogl_winsys_texture_pixmap_x11_create,
+    .texture_pixmap_x11_free =
+      _cogl_winsys_texture_pixmap_x11_free,
+    .texture_pixmap_x11_update =
+      _cogl_winsys_texture_pixmap_x11_update,
+    .texture_pixmap_x11_damage_notify =
+      _cogl_winsys_texture_pixmap_x11_damage_notify,
+    .texture_pixmap_x11_get_texture =
+      _cogl_winsys_texture_pixmap_x11_get_texture,
+  };
+
+/* XXX: we use a function because no doubt someone will complain
+ * about using c99 member initializers because they aren't portable
+ * to windows. We want to avoid having to rigidly follow the real
+ * order of members since some members are #ifdefd and we'd have
+ * to mirror the #ifdefing to add padding etc. For any winsys that
+ * can assume the platform has a sane compiler then we can just use
+ * c99 initializers for insane platforms they can initialize
+ * the members by name in a function.
+ */
+const CoglWinsysVtable *
+_cogl_winsys_glx_get_vtable (void)
+{
+  return &_cogl_winsys_vtable;
+}
diff --git a/clutter/cogl/cogl/winsys/cogl-winsys-private.h b/clutter/cogl/cogl/winsys/cogl-winsys-private.h
index 150f2dc..a610848 100644
--- a/clutter/cogl/cogl/winsys/cogl-winsys-private.h
+++ b/clutter/cogl/cogl/winsys/cogl-winsys-private.h
@@ -31,6 +31,7 @@
 
 #ifdef COGL_HAS_XLIB_SUPPORT
 #include <X11/Xutil.h>
+#include "cogl-texture-pixmap-x11-private.h"
 #endif
 
 GQuark
@@ -51,95 +52,94 @@ typedef enum
   COGL_WINSYS_RECTANGLE_STATE_ENABLE
 } CoglWinsysRectangleState;
 
-CoglFuncPtr
-_cogl_winsys_get_proc_address (const char *name);
+typedef struct _CoglWinsysVtable
+{
+  CoglFuncPtr
+  (*get_proc_address) (const char *name);
 
-gboolean
-_cogl_winsys_renderer_connect (CoglRenderer *renderer,
-                               GError **error);
+  gboolean
+  (*renderer_connect) (CoglRenderer *renderer, GError **error);
 
-void
-_cogl_winsys_renderer_disconnect (CoglRenderer *renderer);
+  void
+  (*renderer_disconnect) (CoglRenderer *renderer);
 
-gboolean
-_cogl_winsys_display_setup (CoglDisplay *display,
-                            GError **error);
+  gboolean
+  (*display_setup) (CoglDisplay *display, GError **error);
 
-void
-_cogl_winsys_display_destroy (CoglDisplay *display);
+  void
+  (*display_destroy) (CoglDisplay *display);
 
-gboolean
-_cogl_winsys_context_init (CoglContext *context, GError **error);
+  gboolean
+  (*context_init) (CoglContext *context, GError **error);
 
-void
-_cogl_winsys_context_deinit (CoglContext *context);
+  void
+  (*context_deinit) (CoglContext *context);
 
 #ifdef COGL_HAS_EGL_SUPPORT
-EGLDisplay
-_cogl_winsys_context_egl_get_egl_display (CoglContext *context);
+  EGLDisplay
+  (*context_egl_get_egl_display) (CoglContext *context);
 #endif
 
-gboolean
-_cogl_winsys_has_feature (CoglWinsysFeature feature);
+  gboolean
+  (*has_feature) (CoglWinsysFeature feature);
 
 #ifdef COGL_HAS_XLIB_SUPPORT
-XVisualInfo *
-_cogl_winsys_xlib_get_visual_info (void);
+  XVisualInfo *
+  (*xlib_get_visual_info) (void);
 #endif
 
-gboolean
-_cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
-                            GError **error);
+  gboolean
+  (*onscreen_init) (CoglOnscreen *onscreen, GError **error);
 
-void
-_cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen);
+  void
+  (*onscreen_deinit) (CoglOnscreen *onscreen);
 
-void
-_cogl_winsys_onscreen_bind (CoglOnscreen *onscreen);
+  void
+  (*onscreen_bind) (CoglOnscreen *onscreen);
 
-void
-_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen);
+  void
+  (*onscreen_swap_buffers) (CoglOnscreen *onscreen);
 
-void
-_cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
-                                   int *rectangles,
-                                   int n_rectangles);
+  void
+  (*onscreen_swap_region) (CoglOnscreen *onscreen,
+                           int *rectangles,
+                           int n_rectangles);
 
-void
-_cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen);
+  void
+  (*onscreen_update_swap_throttled) (CoglOnscreen *onscreen);
 
-guint32
-_cogl_winsys_onscreen_x11_get_window_xid (CoglOnscreen *onscreen);
+  guint32
+  (*onscreen_x11_get_window_xid) (CoglOnscreen *onscreen);
 
-guint32
-_cogl_winsys_get_vsync_counter (void);
+  unsigned int
+  (*onscreen_add_swap_buffers_callback) (CoglOnscreen *onscreen,
+                                         CoglSwapBuffersNotify callback,
+                                         void *user_data);
 
-unsigned int
-_cogl_winsys_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen,
-                                                 CoglSwapBuffersNotify callback,
-                                                 void *user_data);
+  void
+  (*onscreen_remove_swap_buffers_callback) (CoglOnscreen *onscreen,
+                                            unsigned int id);
 
-void
-_cogl_winsys_onscreen_remove_swap_buffers_callback (CoglOnscreen *onscreen,
-                                                    unsigned int id);
+  guint32
+  (*get_vsync_counter) (void);
 
 #ifdef COGL_HAS_XLIB_SUPPORT
-gboolean
-_cogl_winsys_texture_pixmap_x11_create (CoglTexturePixmapX11 *tex_pixmap);
+  gboolean
+  (*texture_pixmap_x11_create) (CoglTexturePixmapX11 *tex_pixmap);
+  void
+  (*texture_pixmap_x11_free) (CoglTexturePixmapX11 *tex_pixmap);
 
-void
-_cogl_winsys_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap);
+  gboolean
+  (*texture_pixmap_x11_update) (CoglTexturePixmapX11 *tex_pixmap,
+                                gboolean needs_mipmap);
 
-gboolean
-_cogl_winsys_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
-                                        gboolean needs_mipmap);
+  void
+  (*texture_pixmap_x11_damage_notify) (CoglTexturePixmapX11 *tex_pixmap);
 
-void
-_cogl_winsys_texture_pixmap_x11_damage_notify (
-                                            CoglTexturePixmapX11 *tex_pixmap);
-
-CoglHandle
-_cogl_winsys_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap);
+  CoglHandle
+  (*texture_pixmap_x11_get_texture) (CoglTexturePixmapX11 *tex_pixmap);
 #endif
 
+} CoglWinsysVtable;
+
 #endif /* __COGL_WINSYS_PRIVATE_H */



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