[clutter: 15/19] Moves all GLX code down from Clutter to Cogl



commit d6f110a4d26eb5e49e762bcbf51d36af894adcc9
Author: Robert Bragg <robert linux intel com>
Date:   Fri Nov 5 12:28:33 2010 +0000

    Moves all GLX code down from Clutter to Cogl
    
    This migrates all the GLX window system code down from the Clutter
    backend code into a Cogl winsys. Moving OpenGL window system binding
    code down from Clutter into Cogl is the biggest blocker to having Cogl
    become a standalone 3D graphics library, so this is an important step in
    that direction.

 clutter/clutter-backend-private.h                  |    5 +
 clutter/clutter-backend.c                          |    1 +
 clutter/clutter-stage.c                            |   12 -
 clutter/cogl/cogl/Makefile.am                      |   44 +-
 clutter/cogl/cogl/cogl-clutter.c                   |   14 +
 clutter/cogl/cogl/cogl-clutter.h                   |   10 +
 clutter/cogl/cogl/cogl-context-private.h           |   34 +-
 clutter/cogl/cogl/cogl-context.c                   |  104 +-
 clutter/cogl/cogl/cogl-context.h                   |    7 +-
 clutter/cogl/cogl/cogl-debug.h                     |    1 +
 clutter/cogl/cogl/cogl-display-glx-private.h       |   57 +
 clutter/cogl/cogl/cogl-display-xlib-private.h      |   35 +
 clutter/cogl/cogl/cogl-display.c                   |    5 +
 clutter/cogl/cogl/cogl-display.h                   |   12 +-
 clutter/cogl/cogl/cogl-feature-private.c           |    5 +-
 clutter/cogl/cogl/cogl-feature-private.h           |   20 +-
 clutter/cogl/cogl/cogl-framebuffer-private.h       |   39 +-
 clutter/cogl/cogl/cogl-framebuffer.c               |  235 ++++-
 clutter/cogl/cogl/cogl-framebuffer.h               |  109 ++
 clutter/cogl/cogl/cogl-internal.h                  |  102 +--
 clutter/cogl/cogl/cogl-journal-private.h           |    1 +
 clutter/cogl/cogl/cogl-private.h                   |    6 +
 clutter/cogl/cogl/cogl-renderer-glx-private.h      |   61 +
 clutter/cogl/cogl/cogl-renderer-x11-private.h      |   32 +
 ...-winsys-xlib.h => cogl-renderer-xlib-private.h} |   50 +-
 clutter/cogl/cogl/cogl-renderer-xlib.c             |  288 +++++
 clutter/cogl/cogl/cogl-renderer.c                  |   23 +
 clutter/cogl/cogl/cogl-types.h                     |   87 ++-
 clutter/cogl/cogl/cogl-util.c                      |    1 -
 clutter/cogl/cogl/cogl-xlib-private.h              |   82 ++
 .../{winsys/cogl-winsys-xlib.c => cogl-xlib.c}     |  104 ++-
 clutter/cogl/cogl/cogl-xlib.h                      |   84 ++
 clutter/cogl/cogl/cogl.c                           |   10 +-
 clutter/cogl/cogl/cogl.h                           |   52 +-
 .../cogl/cogl/driver/gl/cogl-context-driver-gl.h   |   53 +
 clutter/cogl/cogl/driver/gl/cogl-gl.c              |   40 +-
 .../cogl/driver/gles/cogl-context-driver-gles.h    |   52 +
 clutter/cogl/cogl/driver/gles/cogl-gles.c          |   46 +-
 clutter/cogl/cogl/winsys/cogl-context-winsys.c     |  152 ---
 clutter/cogl/cogl/winsys/cogl-context-winsys.h     |  118 --
 clutter/cogl/cogl/winsys/cogl-texture-pixmap-x11.c |  111 +-
 .../cogl/winsys/cogl-winsys-feature-functions.h    |   45 -
 .../winsys/cogl-winsys-glx-feature-functions.h     |  105 ++
 clutter/cogl/cogl/winsys/cogl-winsys-glx.c         | 1262 +++++++++++++++++++-
 clutter/cogl/cogl/winsys/cogl-winsys-private.h     |   88 ++
 clutter/cogl/cogl/winsys/cogl-winsys-stub.c        |  114 ++
 clutter/cogl/cogl/winsys/cogl-winsys.c             |   36 +
 clutter/glx/clutter-backend-glx.c                  |  654 ++---------
 clutter/glx/clutter-backend-glx.h                  |   49 +-
 clutter/glx/clutter-stage-glx.c                    |  385 ++-----
 clutter/glx/clutter-stage-glx.h                    |    5 +-
 clutter/x11/clutter-backend-x11.c                  |    4 +-
 clutter/x11/clutter-stage-x11.c                    |   14 +-
 configure.ac                                       |    2 +
 54 files changed, 3436 insertions(+), 1631 deletions(-)
---
diff --git a/clutter/clutter-backend-private.h b/clutter/clutter-backend-private.h
index cc88903..3374bbc 100644
--- a/clutter/clutter-backend-private.h
+++ b/clutter/clutter-backend-private.h
@@ -37,6 +37,11 @@ struct _ClutterBackend
 {
   /*< private >*/
   GObject                parent_instance;
+
+  CoglRenderer          *cogl_renderer;
+  CoglDisplay           *cogl_display;
+  CoglContext           *cogl_context;
+
   ClutterBackendPrivate *priv;
 };
 
diff --git a/clutter/clutter-backend.c b/clutter/clutter-backend.c
index 93328be..6763247 100644
--- a/clutter/clutter-backend.c
+++ b/clutter/clutter-backend.c
@@ -53,6 +53,7 @@
 #include "clutter-version.h"
 
 #include <cogl/cogl.h>
+#include <cogl/cogl-internal.h>
 
 G_DEFINE_ABSTRACT_TYPE (ClutterBackend, clutter_backend, G_TYPE_OBJECT);
 
diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c
index 723b3a7..43ffd27 100644
--- a/clutter/clutter-stage.c
+++ b/clutter/clutter-stage.c
@@ -672,7 +672,6 @@ clutter_stage_realize (ClutterActor *self)
   if (is_realized)
     {
       ClutterBackend *backend = clutter_get_default_backend ();
-      GError *error = NULL;
 
       /* We want to select the context without calling
          clutter_backend_ensure_context so that it doesn't call any
@@ -680,17 +679,6 @@ clutter_stage_realize (ClutterActor *self)
          before we get a chance to check whether the GL version is
          valid */
       _clutter_backend_ensure_context_internal (backend, CLUTTER_STAGE (self));
-
-      /* Make sure Cogl can support the driver */
-      if (!_cogl_check_driver_valid (&error))
-        {
-          g_critical ("The GL driver is not supported: %s",
-                      error->message);
-          g_clear_error (&error);
-          CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
-        }
-      else
-        CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
     }
   else
     CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
diff --git a/clutter/cogl/cogl/Makefile.am b/clutter/cogl/cogl/Makefile.am
index 80b5ae5..c4d2f50 100644
--- a/clutter/cogl/cogl/Makefile.am
+++ b/clutter/cogl/cogl/Makefile.am
@@ -78,6 +78,7 @@ cogl_public_h = \
 	$(srcdir)/cogl-attribute.h 		\
 	$(srcdir)/cogl-primitive.h 		\
 	$(srcdir)/cogl-clip-state.h		\
+	$(srcdir)/cogl-framebuffer.h		\
 	$(srcdir)/cogl-clutter.h       		\
 	$(srcdir)/cogl.h			\
 	$(NULL)
@@ -114,10 +115,8 @@ endif # COGL_DRIVER_GLES
 
 # winsys sources, common to all backends
 cogl_winsys_common_sources = \
-	$(srcdir)/winsys/cogl-winsys-private.h			\
-	$(srcdir)/winsys/cogl-context-winsys.h          	\
-	$(srcdir)/winsys/cogl-context-winsys.c          	\
-	$(srcdir)/winsys/cogl-winsys-feature-functions.h	\
+	$(srcdir)/winsys/cogl-winsys-private.h \
+	$(srcdir)/winsys/cogl-winsys.c \
 	$(NULL)
 
 # tesselator sources
@@ -295,29 +294,39 @@ cogl_sources_c = \
 
 if SUPPORT_XLIB
 cogl_experimental_h += \
-       $(srcdir)/winsys/cogl-texture-pixmap-x11.h
+       $(srcdir)/winsys/cogl-texture-pixmap-x11.h \
+       $(srcdir)/cogl-xlib.h
 
 cogl_sources_c += \
-       $(srcdir)/winsys/cogl-winsys-xlib.h \
-       $(srcdir)/winsys/cogl-winsys-xlib.c \
-       $(srcdir)/winsys/cogl-texture-pixmap-x11.c \
-       $(srcdir)/winsys/cogl-texture-pixmap-x11-private.h
+	$(srcdir)/cogl-renderer-x11-private.h \
+	$(srcdir)/cogl-renderer-xlib-private.h \
+	$(srcdir)/cogl-renderer-xlib.c \
+	$(srcdir)/cogl-display-xlib-private.h \
+	$(srcdir)/cogl-xlib.c \
+	$(srcdir)/winsys/cogl-texture-pixmap-x11.c \
+	$(srcdir)/winsys/cogl-texture-pixmap-x11-private.h
 endif
 if SUPPORT_GLX
 cogl_sources_c += \
-       $(srcdir)/winsys/cogl-winsys-glx.c
+	$(srcdir)/cogl-renderer-glx-private.h \
+	$(srcdir)/cogl-display-glx-private.h \
+	$(srcdir)/winsys/cogl-winsys-glx-feature-functions.h \
+	$(srcdir)/winsys/cogl-winsys-glx.c
 endif
 if SUPPORT_EGL_PLATFORM_POWERVR_X11
 cogl_sources_c += \
-       $(srcdir)/winsys/cogl-winsys-egl.c
+	$(srcdir)/winsys/cogl-winsys-egl.c \
+	$(srcdir)/winsys/cogl-winsys-stub.c
 endif
 if SUPPORT_EGL_PLATFORM_POWERVR_NULL
 cogl_sources_c += \
-       $(srcdir)/winsys/cogl-winsys-egl.c
+       $(srcdir)/winsys/cogl-winsys-egl.c \
+       $(srcdir)/winsys/cogl-winsys-stub.c
 endif
 if SUPPORT_EGL_PLATFORM_POWERVR_GDL
 cogl_sources_c += \
-       $(srcdir)/winsys/cogl-winsys-egl.c
+       $(srcdir)/winsys/cogl-winsys-egl.c \
+       $(srcdir)/winsys/cogl-winsys-stub.c
 endif
 if SUPPORT_EGL_PLATFORM_FRUITY
 cogl_sources_c += \
@@ -325,15 +334,18 @@ cogl_sources_c += \
 endif
 if SUPPORT_EGL_PLATFORM_DRM_SURFACELESS
 cogl_sources_c += \
-       $(srcdir)/winsys/cogl-winsys-egl.c
+       $(srcdir)/winsys/cogl-winsys-egl.c \
+       $(srcdir)/winsys/cogl-winsys-stub.c
 endif
 if SUPPORT_WIN32
 cogl_sources_c += \
-       $(srcdir)/winsys/cogl-winsys-win32.c
+       $(srcdir)/winsys/cogl-winsys-win32.c \
+       $(srcdir)/winsys/cogl-winsys-stub.c
 endif
 if SUPPORT_OSX
 cogl_sources_c += \
-       $(srcdir)/winsys/cogl-winsys-osx.c
+       $(srcdir)/winsys/cogl-winsys-osx.c \
+       $(srcdir)/winsys/cogl-winsys-stub.c
 endif
 
 EXTRA_DIST += stb_image.c
diff --git a/clutter/cogl/cogl/cogl-clutter.c b/clutter/cogl/cogl/cogl-clutter.c
index 07f827a..facdeb3 100644
--- a/clutter/cogl/cogl/cogl-clutter.c
+++ b/clutter/cogl/cogl/cogl-clutter.c
@@ -43,6 +43,12 @@ cogl_clutter_check_extension (const char *name, const char *ext)
   return _cogl_check_extension (name, ext);
 }
 
+gboolean
+cogl_clutter_winsys_has_feature (CoglWinsysFeature feature)
+{
+  return _cogl_winsys_has_feature (feature);
+}
+
 void
 cogl_onscreen_clutter_backend_set_size (int width, int height)
 {
@@ -57,3 +63,11 @@ cogl_onscreen_clutter_backend_set_size (int width, int height)
 
   _cogl_framebuffer_winsys_update_size (framebuffer, width, height);
 }
+
+#ifdef COGL_HAS_XLIB_SUPPORT
+XVisualInfo *
+cogl_clutter_winsys_xlib_get_visual_info (void)
+{
+  return _cogl_winsys_xlib_get_visual_info ();
+}
+#endif
diff --git a/clutter/cogl/cogl/cogl-clutter.h b/clutter/cogl/cogl/cogl-clutter.h
index 023d14f..a121671 100644
--- a/clutter/cogl/cogl/cogl-clutter.h
+++ b/clutter/cogl/cogl/cogl-clutter.h
@@ -38,10 +38,20 @@ G_BEGIN_DECLS
 gboolean
 cogl_clutter_check_extension (const char *name, const char *ext);
 
+#define cogl_clutter_winsys_has_feature cogl_clutter_winsys_has_feature_CLUTTER
+gboolean
+cogl_clutter_winsys_has_feature (CoglWinsysFeature feature);
+
 #define cogl_onscreen_clutter_backend_set_size cogl_onscreen_clutter_backend_set_size_CLUTTER
 void
 cogl_onscreen_clutter_backend_set_size (int width, int height);
 
+#ifdef COGL_HAS_XLIB
+#define cogl_clutter_winsys_xlib_get_visual_info cogl_clutter_winsys_xlib_get_visual_info_CLUTTER
+XVisualInfo *
+cogl_clutter_winsys_xlib_get_visual_info (void);
+#endif
+
 G_END_DECLS
 
 #endif /* __COGL_CLUTTER_H__ */
diff --git a/clutter/cogl/cogl/cogl-context-private.h b/clutter/cogl/cogl/cogl-context-private.h
index 83a9ebd..ba54de7 100644
--- a/clutter/cogl/cogl/cogl-context-private.h
+++ b/clutter/cogl/cogl/cogl-context-private.h
@@ -26,6 +26,11 @@
 
 #include "cogl-internal.h"
 #include "cogl-context.h"
+#include "cogl-winsys-private.h"
+
+#ifdef COGL_HAS_XLIB_SUPPORT
+#include "cogl-xlib-private.h"
+#endif
 
 #if HAVE_COGL_GL
 #include "cogl-context-driver-gl.h"
@@ -35,7 +40,7 @@
 #include "cogl-context-driver-gles.h"
 #endif
 
-#include "cogl-context-winsys.h"
+#include "cogl-display-private.h"
 #include "cogl-primitives.h"
 #include "cogl-clip-stack.h"
 #include "cogl-matrix-stack.h"
@@ -55,9 +60,10 @@ struct _CoglContext
 {
   CoglObject _parent;
 
+  CoglDisplay *display;
+
   /* Features cache */
-  CoglFeatureFlags        feature_flags;
-  CoglFeatureFlagsPrivate feature_flags_private;
+  CoglFeatureFlags feature_flags;
 
   CoglHandle        default_pipeline;
   CoglHandle        default_layer_0;
@@ -70,8 +76,6 @@ struct _CoglContext
   gboolean          enable_backface_culling;
   CoglFrontWinding  flushed_front_winding;
 
-  gboolean          indirect;
-
   /* A few handy matrix constants */
   CoglMatrix        identity_matrix;
   CoglMatrix        y_flip_matrix;
@@ -237,8 +241,26 @@ struct _CoglContext
   GByteArray       *buffer_map_fallback_array;
   gboolean          buffer_map_fallback_in_use;
 
+  CoglWinsysRectangleState rectangle_state;
+
+  /* FIXME: remove these when we remove the last xlib based clutter
+   * backend. they should be tracked as part of the renderer but e.g.
+   * the eglx backend doesn't yet have a corresponding Cogl winsys
+   * and so we wont have a renderer in that case. */
+#ifdef COGL_HAS_XLIB_SUPPORT
+  int damage_base;
+  /* List of callback functions that will be given every Xlib event */
+  GSList *event_filters;
+  /* Current top of the XError trap state stack. The actual memory for
+     these is expected to be allocated on the stack by the caller */
+  CoglXlibTrapState *trap_state;
+#endif
+
   CoglContextDriver drv;
-  CoglContextWinsys winsys;
+
+  CoglBitmask winsys_features;
+  void *winsys;
+  gboolean stub_winsys;
 };
 
 CoglContext *
diff --git a/clutter/cogl/cogl/cogl-context.c b/clutter/cogl/cogl/cogl-context.c
index ed950c3..a543baa 100644
--- a/clutter/cogl/cogl/cogl-context.c
+++ b/clutter/cogl/cogl/cogl-context.c
@@ -28,6 +28,8 @@
 #include "cogl.h"
 #include "cogl-object.h"
 #include "cogl-internal.h"
+#include "cogl-private.h"
+#include "cogl-winsys-private.h"
 #include "cogl-profile.h"
 #include "cogl-util.h"
 #include "cogl-context-private.h"
@@ -56,13 +58,8 @@ COGL_OBJECT_DEFINE (Context, context);
 
 extern void
 _cogl_create_context_driver (CoglContext *context);
-extern void
-_cogl_create_context_winsys (CoglContext *context);
-extern void
-_cogl_destroy_context_winsys (CoglContext *context);
 
 static CoglContext *_context = NULL;
-static gboolean gl_is_indirect = FALSE;
 
 static void
 _cogl_init_feature_overrides (CoglContext *ctx)
@@ -102,15 +99,8 @@ cogl_context_new (CoglDisplay *display,
   CoglContext *context;
   GLubyte default_texture_data[] = { 0xff, 0xff, 0xff, 0x0 };
   unsigned long enable_flags = 0;
-  CoglHandle window_buffer;
   int i;
 
-  /* A NULL display means "please just do something sensible"
-   * and since we haven't implemented anything for CoglDisplay
-   * yet that's the only kind of context construction we allow
-   * for now. */
-  g_return_val_if_fail (display == NULL, NULL);
-
 #ifdef CLUTTER_ENABLE_PROFILE
   /* We need to be absolutely sure that uprof has been initialized
    * before calling _cogl_uprof_init. uprof_init (NULL, NULL)
@@ -135,18 +125,21 @@ cogl_context_new (CoglDisplay *display,
    * context which it can access via _COGL_GET_CONTEXT() including
    * code used to construct a CoglContext. Until all of that code
    * has been updated to take an explicit context argument we have
-   * to immediatly make our pointer the default context.
+   * to immediately make our pointer the default context.
    */
   _context = context;
 
   /* Init default values */
-  _context->feature_flags = 0;
-  _context->feature_flags_private = 0;
+  context->feature_flags = 0;
 
   context->texture_types = NULL;
   context->buffer_types = NULL;
 
-    if (!display)
+  context->rectangle_state = COGL_WINSYS_RECTANGLE_STATE_UNKNOWN;
+
+  _cogl_bitmask_init (&context->winsys_features);
+
+  if (!display)
     display = cogl_display_new (NULL, NULL);
   else
     cogl_object_ref (display);
@@ -158,12 +151,33 @@ cogl_context_new (CoglDisplay *display,
       return NULL;
     }
 
+  context->display = display;
+
+#ifdef COGL_HAS_FULL_WINSYS
+  if (!_cogl_winsys_context_init (context, error))
+    {
+      cogl_object_unref (display);
+      g_free (context);
+      return NULL;
+    }
+#else
+  /* In this case Clutter is still responsible for creating a GL
+   * context. */
+  context->stub_winsys = TRUE;
+  if (!_cogl_gl_check_version (error))
+    {
+      g_free (context);
+      return NULL;
+    }
+  _cogl_gl_update_features (context);
+#ifdef COGL_HAS_XLIB_SUPPORT
+  _cogl_xlib_query_damage_extension ();
+#endif
+#endif
+
   /* Initialise the driver specific state */
-  _cogl_gl_context_init (context);
   _cogl_init_feature_overrides (context);
 
-  _cogl_create_context_winsys (context);
-
   _cogl_pipeline_init_default_pipeline ();
   _cogl_pipeline_init_default_layers ();
   _cogl_pipeline_init_state_hash_functions ();
@@ -174,8 +188,6 @@ cogl_context_new (CoglDisplay *display,
   context->enable_backface_culling = FALSE;
   context->flushed_front_winding = COGL_FRONT_WINDING_COUNTER_CLOCKWISE;
 
-  context->indirect = gl_is_indirect;
-
   cogl_matrix_init_identity (&context->identity_matrix);
   cogl_matrix_init_identity (&context->y_flip_matrix);
   cogl_matrix_scale (&context->y_flip_matrix, 1, -1, 1);
@@ -257,13 +269,18 @@ cogl_context_new (CoglDisplay *display,
 
   context->framebuffer_stack = _cogl_create_framebuffer_stack ();
 
-  _context->current_clip_stack_valid = FALSE;
+  /* XXX: In this case the Clutter backend is still responsible for
+   * the OpenGL binding API and for creating onscreen framebuffers and
+   * so we have to add a dummy framebuffer to represent the backend
+   * owned window... */
+  if (context->stub_winsys)
+    {
+      CoglOnscreen *window = _cogl_onscreen_new ();
+      cogl_set_framebuffer (COGL_FRAMEBUFFER (window));
+      cogl_object_unref (COGL_FRAMEBUFFER (window));
+    }
 
-  window_buffer = _cogl_onscreen_new ();
-  cogl_set_framebuffer (window_buffer);
-  /* XXX: the deprecated _cogl_set_draw_buffer API expects to
-   * find the window buffer here... */
-  context->window_buffer = window_buffer;
+  _context->current_clip_stack_valid = FALSE;
 
   context->dirty_bound_framebuffer = TRUE;
   context->dirty_gl_viewport = TRUE;
@@ -347,7 +364,7 @@ cogl_context_new (CoglDisplay *display,
 static void
 _cogl_context_free (CoglContext *context)
 {
-  _cogl_destroy_context_winsys (context);
+  _cogl_winsys_context_deinit (context);
 
   _cogl_destroy_texture_units ();
 
@@ -424,6 +441,8 @@ _cogl_context_free (CoglContext *context)
 
   g_byte_array_free (context->buffer_map_fallback_array, TRUE);
 
+  _cogl_bitmask_destroy (&context->winsys_features);
+
   cogl_object_unref (context->display);
 
   g_free (context);
@@ -448,31 +467,12 @@ _cogl_context_get_default (void)
   return _context;
 }
 
-/**
- * _cogl_set_indirect_context:
- * @indirect: TRUE if GL context is indirect
- *
- * Advises COGL that the GL context is indirect (commands are sent
- * over a socket). COGL uses this information to try to avoid
- * round-trips in its use of GL, for example.
- *
- * This function cannot be called "on the fly," only before COGL
- * initializes.
- */
 void
-_cogl_set_indirect_context (gboolean indirect)
+cogl_set_default_context (CoglContext *context)
 {
-  /* we get called multiple times if someone creates
-   * more than the default stage
-   */
-  if (_context != NULL)
-    {
-      if (indirect != _context->indirect)
-        g_warning ("Right now all stages will be treated as "
-                   "either direct or indirect, ignoring attempt "
-                   "to change to indirect=%d", indirect);
-      return;
-    }
+  cogl_object_ref (context);
 
-  gl_is_indirect = indirect;
+  if (_context)
+    cogl_object_unref (_context);
+  _context = context;
 }
diff --git a/clutter/cogl/cogl/cogl-context.h b/clutter/cogl/cogl/cogl-context.h
index d8cab2a..9394fbf 100644
--- a/clutter/cogl/cogl/cogl-context.h
+++ b/clutter/cogl/cogl/cogl-context.h
@@ -54,7 +54,12 @@ typedef struct _CoglContext	      CoglContext;
 #define cogl_context_new cogl_context_new_EXP
 
 CoglContext *
-cogl_context_new (CoglDisplay *display);
+cogl_context_new (CoglDisplay *display,
+                  GError **error);
+
+#define cogl_set_default_context cogl_set_default_context_EXP
+void
+cogl_set_default_context (CoglContext *context);
 
 G_END_DECLS
 
diff --git a/clutter/cogl/cogl/cogl-debug.h b/clutter/cogl/cogl/cogl-debug.h
index 0cd039f..87f280d 100644
--- a/clutter/cogl/cogl/cogl-debug.h
+++ b/clutter/cogl/cogl/cogl-debug.h
@@ -63,6 +63,7 @@ typedef enum {
   COGL_DEBUG_DISABLE_PROGRAM_CACHES,
   COGL_DEBUG_DISABLE_FAST_READ_PIXEL,
   COGL_DEBUG_CLIPPING,
+  COGL_DEBUG_WINSYS,
 
   COGL_DEBUG_N_FLAGS
 } CoglDebugFlags;
diff --git a/clutter/cogl/cogl/cogl-display-glx-private.h b/clutter/cogl/cogl/cogl-display-glx-private.h
new file mode 100644
index 0000000..279b653
--- /dev/null
+++ b/clutter/cogl/cogl/cogl-display-glx-private.h
@@ -0,0 +1,57 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *
+ */
+
+#ifndef __COGL_DISPLAY_GLX_PRIVATE_H
+#define __COGL_DISPLAY_GLX_PRIVATE_H
+
+#include "cogl-object-private.h"
+#include "cogl-display-xlib-private.h"
+
+typedef struct _CoglGLXCachedConfig
+{
+  /* This will be -1 if there is no cached config in this slot */
+  int depth;
+  gboolean found;
+  GLXFBConfig fb_config;
+  gboolean can_mipmap;
+} CoglGLXCachedConfig;
+
+#define COGL_GLX_N_CACHED_CONFIGS 3
+
+typedef struct _CoglDisplayGLX
+{
+  CoglDisplayXlib _parent;
+
+  CoglGLXCachedConfig glx_cached_configs[COGL_GLX_N_CACHED_CONFIGS];
+
+  gboolean found_fbconfig;
+  gboolean fbconfig_has_rgba_visual;
+  GLXFBConfig fbconfig;
+
+  /* Single context for all wins */
+  GLXContext glx_context;
+  GLXWindow dummy_glxwin;
+} CoglDisplayGLX;
+
+#endif /* __COGL_DISPLAY_GLX_PRIVATE_H */
diff --git a/clutter/cogl/cogl/cogl-display-xlib-private.h b/clutter/cogl/cogl/cogl-display-xlib-private.h
new file mode 100644
index 0000000..6e28388
--- /dev/null
+++ b/clutter/cogl/cogl/cogl-display-xlib-private.h
@@ -0,0 +1,35 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *
+ */
+
+#ifndef __COGL_DISPLAY_XLIB_PRIVATE_H
+#define __COGL_DISPLAY_XLIB_PRIVATE_H
+
+#include <X11/Xlib.h>
+
+typedef struct _CoglDisplayXlib
+{
+  Window dummy_xwin;
+} CoglDisplayXlib;
+
+#endif /* __COGL_DISPLAY_XLIB_PRIVATE_H */
diff --git a/clutter/cogl/cogl/cogl-display.c b/clutter/cogl/cogl/cogl-display.c
index ebaaafa..a09de18 100644
--- a/clutter/cogl/cogl/cogl-display.c
+++ b/clutter/cogl/cogl/cogl-display.c
@@ -100,6 +100,11 @@ cogl_display_setup (CoglDisplay *display,
   if (display->setup)
     return TRUE;
 
+#ifdef COGL_HAS_FULL_WINSYS
+  if (!_cogl_winsys_display_setup (display, error))
+    return FALSE;
+#endif
+
   display->setup = TRUE;
 
   return TRUE;
diff --git a/clutter/cogl/cogl/cogl-display.h b/clutter/cogl/cogl/cogl-display.h
index 5dec9db..00ce4fb 100644
--- a/clutter/cogl/cogl/cogl-display.h
+++ b/clutter/cogl/cogl/cogl-display.h
@@ -31,6 +31,9 @@
 #ifndef __COGL_DISPLAY_H__
 #define __COGL_DISPLAY_H__
 
+#include <cogl/cogl-renderer.h>
+#include <cogl/cogl-onscreen-template.h>
+
 G_BEGIN_DECLS
 
 /**
@@ -69,8 +72,15 @@ typedef struct _CoglDisplay	      CoglDisplay;
 
 #define COGL_DISPLAY(OBJECT) ((CoglDisplay *)OBJECT)
 
+#define cogl_display_new cogl_display_new_EXP
 CoglDisplay *
-cogl_display_new (CoglDisplay *display);
+cogl_display_new (CoglRenderer *renderer,
+                  CoglOnscreenTemplate *onscreen_template);
+
+#define cogl_display_setup cogl_display_setup_EXP
+gboolean
+cogl_display_setup (CoglDisplay *display,
+                    GError **error);
 
 G_END_DECLS
 
diff --git a/clutter/cogl/cogl/cogl-feature-private.c b/clutter/cogl/cogl/cogl-feature-private.c
index deff9fc..d3904b4 100644
--- a/clutter/cogl/cogl/cogl-feature-private.c
+++ b/clutter/cogl/cogl/cogl-feature-private.c
@@ -37,7 +37,8 @@ _cogl_feature_check (const char *driver_prefix,
                      const CoglFeatureData *data,
                      unsigned int gl_major,
                      unsigned int gl_minor,
-                     const char *extensions_string)
+                     const char *extensions_string,
+                     void *function_table)
 
 {
   const char *suffix = NULL;
@@ -123,7 +124,7 @@ _cogl_feature_check (const char *driver_prefix,
         break;
 
       /* Set the function pointer in the context */
-      *(void **) ((guint8 *) ctx +
+      *(void **) ((guint8 *) function_table +
                   data->functions[func_num].pointer_offset) = func;
     }
 
diff --git a/clutter/cogl/cogl/cogl-feature-private.h b/clutter/cogl/cogl/cogl-feature-private.h
index 133d588..5d0101e 100644
--- a/clutter/cogl/cogl/cogl-feature-private.h
+++ b/clutter/cogl/cogl/cogl-feature-private.h
@@ -26,6 +26,8 @@
 
 #include <glib.h>
 
+#include "cogl-internal.h"
+
 #define COGL_CHECK_GL_VERSION(driver_major, driver_minor, \
                               target_major, target_minor) \
   ((driver_major) > (target_major) || \
@@ -59,17 +61,21 @@ struct _CoglFeatureData
   const char *extension_names;
   /* A set of feature flags to enable if the extension is available */
   CoglFeatureFlags feature_flags;
-  /* A set of private feature flags to enable if the extension is available
-   * and for internal use only */
-  CoglFeatureFlagsPrivate feature_flags_private;
+  /* FIXME: This is now unused */
+  int padding_feature_flags_private;
+  /* An optional corresponding winsys feature. */
+  CoglWinsysFeature winsys_feature;
   /* A list of functions required for this feature. Terminated with a
      NULL name */
   const CoglFeatureFunction *functions;
 };
 
-gboolean _cogl_feature_check (const char *driver_prefix,
-                              const CoglFeatureData *data,
-                              unsigned int gl_major, unsigned int gl_minor,
-                              const char *extensions_string);
+gboolean
+_cogl_feature_check (const char *driver_prefix,
+                     const CoglFeatureData *data,
+                     unsigned int gl_major,
+                     unsigned int gl_minor,
+                     const char *extensions_string,
+                     void *function_table);
 
 #endif /* __COGL_FEATURE_PRIVATE_H */
diff --git a/clutter/cogl/cogl/cogl-framebuffer-private.h b/clutter/cogl/cogl/cogl-framebuffer-private.h
index afc8fe1..ee6f3ff 100644
--- a/clutter/cogl/cogl/cogl-framebuffer-private.h
+++ b/clutter/cogl/cogl/cogl-framebuffer-private.h
@@ -24,11 +24,20 @@
 #ifndef __COGL_FRAMEBUFFER_PRIVATE_H
 #define __COGL_FRAMEBUFFER_PRIVATE_H
 
-#include "cogl-handle.h"
+#include "cogl-object-private.h"
 #include "cogl-matrix-stack.h"
 #include "cogl-clip-state-private.h"
 #include "cogl-journal-private.h"
 
+#ifdef COGL_HAS_XLIB_SUPPORT
+#include <X11/Xlib.h>
+#endif
+
+#ifdef COGL_HAS_GLX_SUPPORT
+#include <GL/glx.h>
+#include <GL/glxext.h>
+#endif
+
 typedef enum _CoglFramebufferType {
   COGL_FRAMEBUFFER_TYPE_ONSCREEN,
   COGL_FRAMEBUFFER_TYPE_OFFSCREEN
@@ -37,12 +46,14 @@ typedef enum _CoglFramebufferType {
 struct _CoglFramebuffer
 {
   CoglObject          _parent;
+  CoglContext        *context;
   CoglFramebufferType  type;
   int                 width;
   int                 height;
   /* Format of the pixels in the framebuffer (including the expected
      premult state) */
   CoglPixelFormat     format;
+  gboolean            allocated;
 
   CoglMatrixStack    *modelview_stack;
   CoglMatrixStack    *projection_stack;
@@ -85,8 +96,6 @@ struct _CoglFramebuffer
   gboolean            clear_clip_dirty;
 };
 
-#define COGL_FRAMEBUFFER(X) ((CoglFramebuffer *)(X))
-
 typedef struct _CoglOffscreen
 {
   CoglFramebuffer  _parent;
@@ -103,12 +112,18 @@ typedef enum
 
 #define COGL_OFFSCREEN(X) ((CoglOffscreen *)(X))
 
-typedef struct _CoglOnscreen
+struct _CoglOnscreen
 {
   CoglFramebuffer  _parent;
-} CoglOnscreen;
 
-#define COGL_ONSCREEN(X) ((CoglOnscreen *)(X))
+#ifdef COGL_HAS_X11_SUPPORT
+  guint32 foreign_xid;
+#endif
+
+  gboolean swap_throttled;
+
+  void *winsys;
+};
 
 void
 _cogl_framebuffer_state_init (void);
@@ -233,7 +248,11 @@ typedef enum _CoglFramebufferFlushFlags
   COGL_FRAMEBUFFER_FLUSH_SKIP_MODELVIEW =     1L<<0,
   /* Similarly this flag implies you are going to flush the clip state
      yourself */
-  COGL_FRAMEBUFFER_FLUSH_SKIP_CLIP_STATE =    1L<<1
+  COGL_FRAMEBUFFER_FLUSH_SKIP_CLIP_STATE =    1L<<1,
+  /* When using this all that will be updated is the glBindFramebuffer
+   * state and corresponding winsys state to make the framebuffer
+   * current if it is a CoglOnscreen framebuffer. */
+  COGL_FRAMEBUFFER_FLUSH_BIND_ONLY =          1L<<2
 } CoglFramebufferFlushFlags;
 
 void
@@ -241,9 +260,6 @@ _cogl_framebuffer_flush_state (CoglFramebuffer *draw_buffer,
                                CoglFramebuffer *read_buffer,
                                CoglFramebufferFlushFlags flags);
 
-CoglHandle
-_cogl_onscreen_new (void);
-
 CoglFramebuffer *
 _cogl_get_read_framebuffer (void);
 
@@ -339,5 +355,8 @@ _cogl_blit_framebuffer (unsigned int src_x,
                         unsigned int width,
                         unsigned int height);
 
+CoglOnscreen *
+_cogl_onscreen_new (void);
+
 #endif /* __COGL_FRAMEBUFFER_PRIVATE_H */
 
diff --git a/clutter/cogl/cogl/cogl-framebuffer.c b/clutter/cogl/cogl/cogl-framebuffer.c
index a145994..e67e27b 100644
--- a/clutter/cogl/cogl/cogl-framebuffer.c
+++ b/clutter/cogl/cogl/cogl-framebuffer.c
@@ -36,6 +36,7 @@
 #include "cogl-framebuffer-private.h"
 #include "cogl-clip-stack.h"
 #include "cogl-journal-private.h"
+#include "cogl-winsys-private.h"
 
 #ifndef HAVE_COGL_GLES2
 
@@ -291,6 +292,8 @@ _cogl_framebuffer_clear4f (CoglFramebuffer *framebuffer,
   int scissor_x1;
   int scissor_y1;
 
+  g_return_if_fail (framebuffer->allocated);
+
   _cogl_clip_stack_get_bounds (clip_stack,
                                &scissor_x0, &scissor_y0,
                                &scissor_x1, &scissor_y1);
@@ -451,6 +454,8 @@ _cogl_framebuffer_clear (CoglFramebuffer *framebuffer,
                          unsigned long buffers,
                          const CoglColor *color)
 {
+  g_return_if_fail (framebuffer->allocated);
+
   _cogl_framebuffer_clear4f (framebuffer, buffers,
                              cogl_color_get_red_float (color),
                              cogl_color_get_green_float (color),
@@ -811,8 +816,6 @@ _cogl_offscreen_new_to_texture_full (CoglHandle texhandle,
   CoglFramebufferTryFBOData data;
   gboolean            fbo_created;
 
-  _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
-
   if (!cogl_features_available (COGL_FEATURE_OFFSCREEN))
     return COGL_INVALID_HANDLE;
 
@@ -887,8 +890,11 @@ _cogl_offscreen_new_to_texture_full (CoglHandle texhandle,
   if (fbo_created)
     {
       CoglOffscreen *ret;
+      CoglFramebuffer *fb = COGL_FRAMEBUFFER (offscreen);
 
-      _cogl_framebuffer_init (COGL_FRAMEBUFFER (offscreen),
+      _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
+
+      _cogl_framebuffer_init (fb,
                               ctx,
                               COGL_FRAMEBUFFER_TYPE_OFFSCREEN,
                               cogl_texture_get_format (texhandle),
@@ -901,6 +907,8 @@ _cogl_offscreen_new_to_texture_full (CoglHandle texhandle,
       ret = _cogl_offscreen_object_new (offscreen);
       _cogl_texture_associate_framebuffer (texhandle, COGL_FRAMEBUFFER (ret));
 
+      fb->allocated = TRUE;
+
       return ret;
     }
   else
@@ -946,16 +954,34 @@ _cogl_offscreen_free (CoglOffscreen *offscreen)
   g_free (offscreen);
 }
 
-CoglHandle
+/* XXX: While we still have backend in Clutter we need a dummy object
+ * to represent the CoglOnscreen framebuffer that the backend
+ * creates... */
+CoglOnscreen *
 _cogl_onscreen_new (void)
 {
-  CoglOnscreen *onscreen;
+  CoglOnscreen *onscreen = g_new0 (CoglOnscreen, 1);
 
   _COGL_GET_CONTEXT (ctx, NULL);
 
-  /* XXX: Until we have full winsys support in Cogl then we can't fully
-   * implement CoglOnscreen framebuffers, since we can't, e.g. keep track of
-   * the window size. */
+  _cogl_framebuffer_init (COGL_FRAMEBUFFER (onscreen),
+                          ctx,
+                          COGL_FRAMEBUFFER_TYPE_ONSCREEN,
+                          COGL_PIXEL_FORMAT_RGBA_8888_PRE,
+                          0xdeadbeef, /* width */
+                          0xdeadbeef); /* height */
+
+  COGL_FRAMEBUFFER (onscreen)->allocated = TRUE;
+
+  /* XXX: Note we don't initialize onscreen->winsys in this case. */
+
+  return _cogl_onscreen_object_new (onscreen);
+}
+
+CoglOnscreen *
+cogl_onscreen_new (CoglContext *ctx, int width, int height)
+{
+  CoglOnscreen *onscreen;
 
   /* FIXME: We are assuming onscreen buffers will always be
      premultiplied so we'll set the premult flag on the bitmap
@@ -973,15 +999,41 @@ _cogl_onscreen_new (void)
                           ctx,
                           COGL_FRAMEBUFFER_TYPE_ONSCREEN,
                           COGL_PIXEL_FORMAT_RGBA_8888_PRE,
-                          0xdeadbeef, /* width */
-                          0xdeadbeef); /* height */
+                          width, /* width */
+                          height); /* height */
+
+  onscreen->swap_throttled = TRUE;
 
   return _cogl_onscreen_object_new (onscreen);
 }
 
+gboolean
+cogl_framebuffer_allocate (CoglFramebuffer *framebuffer,
+                           GError **error)
+{
+  CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
+
+  if (framebuffer->allocated)
+    return TRUE;
+
+  /* XXX: with the current cogl_offscreen_new_to_texture() API the
+   * framebuffer is implicitly allocated before returning. */
+  g_return_val_if_fail (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN,
+                        TRUE);
+
+  if (!_cogl_winsys_onscreen_init (onscreen, error))
+    return FALSE;
+
+  framebuffer->allocated = TRUE;
+
+  return TRUE;
+}
+
 static void
 _cogl_onscreen_free (CoglOnscreen *onscreen)
 {
+  _cogl_winsys_onscreen_deinit (onscreen);
+
   /* Chain up to parent */
   _cogl_framebuffer_free (COGL_FRAMEBUFFER (onscreen));
 
@@ -1059,11 +1111,14 @@ static void
 _cogl_set_framebuffers_real (CoglFramebuffer *draw_buffer,
                              CoglFramebuffer *read_buffer)
 {
-  CoglContext *ctx = draw_buffer->context;
   CoglFramebufferStackEntry *entry;
+  GSList *l;
 
-  g_return_if_fail (context != NULL);
-  g_return_if_fail (draw_buffer->context == read_buffer->context);
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+  g_return_if_fail (ctx != NULL);
+  g_return_if_fail (draw_buffer && read_buffer ?
+                    draw_buffer->context == read_buffer->context : TRUE);
 
   entry = ctx->framebuffer_stack->data;
 
@@ -1087,9 +1142,26 @@ _cogl_set_framebuffers_real (CoglFramebuffer *draw_buffer,
    * projection matrix stacks and clip state so we need to dirty
    * them to ensure they get flushed for the next batch of geometry
    * we flush */
-  _cogl_matrix_stack_dirty (draw_buffer->modelview_stack);
-  _cogl_matrix_stack_dirty (draw_buffer->projection_stack);
+  if (draw_buffer)
+    {
+      _cogl_matrix_stack_dirty (draw_buffer->modelview_stack);
+      _cogl_matrix_stack_dirty (draw_buffer->projection_stack);
+    }
+
   _cogl_clip_stack_dirty ();
+
+  /* XXX:
+   * To support the deprecated cogl_set_draw_buffer API we keep track
+   * of the last onscreen framebuffer that was pushed so that it can
+   * be restored if the COGL_WINDOW_BUFFER enum is used. */
+  ctx->window_buffer = NULL;
+  for (l = ctx->framebuffer_stack; l; l = l->next)
+    {
+      entry = l->data;
+      if (entry->draw_buffer &&
+          entry->draw_buffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
+        ctx->window_buffer = entry->draw_buffer;
+    }
 }
 
 static void
@@ -1182,15 +1254,19 @@ _cogl_push_framebuffers (CoglFramebuffer *draw_buffer,
   g_return_if_fail (_cogl_is_framebuffer (read_buffer));
 
   ctx = draw_buffer->context;
-  g_return_if_fail (context != NULL);
+  g_return_if_fail (ctx != NULL);
   g_return_if_fail (draw_buffer->context == read_buffer->context);
 
-  g_return_if_fail (context->framebuffer_stack != NULL);
+  g_return_if_fail (ctx->framebuffer_stack != NULL);
 
   /* Copy the top of the stack so that when we call cogl_set_framebuffer
      it will still know what the old framebuffer was */
-  old_draw_buffer = cogl_object_ref (cogl_get_draw_framebuffer ());
-  old_read_buffer = cogl_object_ref (_cogl_get_read_framebuffer ());
+  old_draw_buffer = cogl_get_draw_framebuffer ();
+  if (old_draw_buffer)
+    cogl_object_ref (old_draw_buffer);
+  old_read_buffer = _cogl_get_read_framebuffer ();
+  if (old_read_buffer)
+    cogl_object_ref (old_read_buffer);
   ctx->framebuffer_stack =
     g_slist_prepend (ctx->framebuffer_stack,
                      create_stack_entry (old_draw_buffer,
@@ -1264,15 +1340,20 @@ cogl_pop_draw_buffer (void)
 }
 
 static void
-bind_gl_framebuffer (GLenum target, CoglFramebuffer *framebuffer)
+bind_gl_framebuffer (CoglContext *ctx,
+                     GLenum target,
+                     CoglFramebuffer *framebuffer)
 {
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
   if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN)
     GE (glBindFramebuffer (target,
                            COGL_OFFSCREEN (framebuffer)->fbo_handle));
   else
-    GE (glBindFramebuffer (target, 0));
+    {
+#ifdef COGL_HAS_FULL_WINSYS
+      _cogl_winsys_onscreen_bind (COGL_ONSCREEN (framebuffer));
+#endif
+      GE (glBindFramebuffer (target, 0));
+    }
 }
 
 void
@@ -1282,21 +1363,29 @@ _cogl_framebuffer_flush_state (CoglFramebuffer *draw_buffer,
 {
   CoglContext *ctx = draw_buffer->context;
 
-  if (cogl_features_available (COGL_FEATURE_OFFSCREEN) &&
-      ctx->dirty_bound_framebuffer)
+  if (ctx->dirty_bound_framebuffer)
     {
-      if (!cogl_features_available (COGL_FEATURE_OFFSCREEN_BLIT) ||
-          draw_buffer == read_buffer)
-        bind_gl_framebuffer (GL_FRAMEBUFFER, draw_buffer);
+      if (draw_buffer == read_buffer)
+        bind_gl_framebuffer (ctx, GL_FRAMEBUFFER, draw_buffer);
       else
         {
-          bind_gl_framebuffer (GL_DRAW_FRAMEBUFFER, draw_buffer);
-          bind_gl_framebuffer (GL_READ_FRAMEBUFFER, read_buffer);
+          /* NB: Currently we only take advantage of binding separate
+           * read/write buffers for offscreen framebuffer blit
+           * purposes.  */
+          g_return_if_fail (cogl_features_available (COGL_FEATURE_OFFSCREEN_BLIT));
+          g_return_if_fail (draw_buffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN);
+          g_return_if_fail (read_buffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN);
+
+          bind_gl_framebuffer (ctx, GL_DRAW_FRAMEBUFFER, draw_buffer);
+          bind_gl_framebuffer (ctx, GL_READ_FRAMEBUFFER, read_buffer);
         }
-
-      ctx->dirty_bound_framebuffer = FALSE;
     }
 
+  ctx->dirty_bound_framebuffer = FALSE;
+
+  if (flags & COGL_FRAMEBUFFER_FLUSH_BIND_ONLY)
+    return;
+
   if (ctx->dirty_gl_viewport)
     {
       float gl_viewport_y;
@@ -1452,6 +1541,8 @@ _cogl_blit_framebuffer (unsigned int src_x,
   CoglFramebuffer *read_buffer;
   CoglContext *ctx;
 
+  /* FIXME: this function should take explit src and dst framebuffer
+   * arguments. */
   draw_buffer = cogl_get_draw_framebuffer ();
   read_buffer = _cogl_get_read_framebuffer ();
   ctx = draw_buffer->context;
@@ -1484,3 +1575,83 @@ _cogl_blit_framebuffer (unsigned int src_x,
                      GL_COLOR_BUFFER_BIT,
                      GL_NEAREST);
 }
+
+void
+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));
+}
+
+void
+cogl_framebuffer_swap_region (CoglFramebuffer *framebuffer,
+                              int *rectangles,
+                              int n_rectangles)
+{
+  /* 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);
+}
+
+#ifdef COGL_HAS_X11_SUPPORT
+void
+cogl_onscreen_x11_set_foreign_window_xid (CoglOnscreen *onscreen,
+                                          guint32 xid)
+{
+  onscreen->foreign_xid = xid;
+}
+
+guint32
+cogl_onscreen_x11_get_window_xid (CoglOnscreen *onscreen)
+{
+  return _cogl_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;
+  XFree (visinfo);
+  return id;
+}
+#endif /* COGL_HAS_X11_SUPPORT */
+
+unsigned int
+cogl_framebuffer_add_swap_buffers_callback (CoglFramebuffer *framebuffer,
+                                            CoglSwapBuffersNotify callback,
+                                            void *user_data)
+{
+  CoglOnscreen *onscreen = COGL_ONSCREEN (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);
+}
+
+void
+cogl_framebuffer_remove_swap_buffers_callback (CoglFramebuffer *framebuffer,
+                                               unsigned int id)
+{
+  CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
+
+  _cogl_winsys_onscreen_remove_swap_buffers_callback (onscreen, id);
+}
+
+void
+cogl_onscreen_set_swap_throttled (CoglOnscreen *onscreen,
+                                  gboolean throttled)
+{
+  onscreen->swap_throttled = throttled;
+  if (COGL_FRAMEBUFFER (onscreen)->allocated)
+    _cogl_winsys_onscreen_update_swap_throttled (onscreen);
+}
diff --git a/clutter/cogl/cogl/cogl-framebuffer.h b/clutter/cogl/cogl/cogl-framebuffer.h
new file mode 100644
index 0000000..1e0a300
--- /dev/null
+++ b/clutter/cogl/cogl/cogl-framebuffer.h
@@ -0,0 +1,109 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *
+ *
+ * Authors:
+ *   Robert Bragg <robert linux intel com>
+ */
+
+#ifndef __COGL_FRAMEBUFFER_H
+#define __COGL_FRAMEBUFFER_H
+
+#include <glib.h>
+
+
+G_BEGIN_DECLS
+
+#ifdef COGL_ENABLE_EXPERIMENTAL_API
+#define cogl_onscreen_new cogl_onscreen_new_EXP
+
+#define COGL_FRAMEBUFFER(X) ((CoglFramebuffer *)(X))
+
+#define cogl_framebuffer_allocate cogl_framebuffer_allocate_EXP
+gboolean
+cogl_framebuffer_allocate (CoglFramebuffer *framebuffer,
+                           GError **error);
+
+#define cogl_framebuffer_swap_buffers cogl_framebuffer_swap_buffers_EXP
+void
+cogl_framebuffer_swap_buffers (CoglFramebuffer *framebuffer);
+
+#define cogl_framebuffer_swap_region cogl_framebuffer_swap_region_EXP
+void
+cogl_framebuffer_swap_region (CoglFramebuffer *framebuffer,
+                              int *rectangles,
+                              int n_rectangles);
+
+
+typedef void (*CoglSwapBuffersNotify) (CoglFramebuffer *framebuffer,
+                                       void *user_data);
+
+#define cogl_framebuffer_add_swap_buffers_callback \
+  cogl_framebuffer_add_swap_buffers_callback_EXP
+unsigned int
+cogl_framebuffer_add_swap_buffers_callback (CoglFramebuffer *framebuffer,
+                                            CoglSwapBuffersNotify callback,
+                                            void *user_data);
+
+#define cogl_framebuffer_remove_swap_buffers_callback \
+  cogl_framebuffer_remove_swap_buffers_callback_EXP
+void
+cogl_framebuffer_remove_swap_buffers_callback (CoglFramebuffer *framebuffer,
+                                               unsigned int id);
+
+
+typedef struct _CoglOnscreen CoglOnscreen;
+#define COGL_ONSCREEN(X) ((CoglOnscreen *)(X))
+
+CoglOnscreen *
+cogl_onscreen_new (CoglContext *context, int width, int height);
+
+#ifdef COGL_HAS_X11
+#define cogl_onscreen_x11_set_foreign_window_xid \
+  cogl_onscreen_x11_set_foreign_window_xid_EXP
+void
+cogl_onscreen_x11_set_foreign_window_xid (CoglOnscreen *onscreen,
+                                          guint32 xid);
+
+#define cogl_onscreen_x11_get_window_xid cogl_onscreen_x11_get_window_xid_EXP
+guint32
+cogl_onscreen_x11_get_window_xid (CoglOnscreen *onscreen);
+
+#define cogl_onscreen_x11_get_visual_xid cogl_onscreen_x11_get_visual_xid_EXP
+guint32
+cogl_onscreen_x11_get_visual_xid (CoglOnscreen *onscreen);
+#endif /* COGL_HAS_X11 */
+
+void
+cogl_onscreen_set_swap_throttled (CoglOnscreen *onscreen,
+                                  gboolean throttled);
+
+#define cogl_get_draw_framebuffer cogl_get_draw_framebuffer_EXP
+CoglFramebuffer *
+cogl_get_draw_framebuffer (void);
+
+#endif /* COGL_ENABLE_EXPERIMENTAL_API */
+
+G_END_DECLS
+
+#endif /* __COGL_FRAMEBUFFER_H */
+
diff --git a/clutter/cogl/cogl/cogl-internal.h b/clutter/cogl/cogl/cogl-internal.h
index 09f5cbc..eba62bf 100644
--- a/clutter/cogl/cogl/cogl-internal.h
+++ b/clutter/cogl/cogl/cogl-internal.h
@@ -29,7 +29,7 @@
 #include "cogl-bitmask.h"
 
 #ifdef COGL_HAS_XLIB_SUPPORT
-#include <X11/Xlib.h>
+#include <X11/Xutil.h>
 #endif
 
 typedef enum
@@ -119,99 +119,17 @@ _cogl_transform_point (const CoglMatrix *matrix_mv,
                        float *x,
                        float *y);
 
-#ifdef COGL_HAS_XLIB_SUPPORT
-
-/*
- * CoglX11FilterReturn:
- * @COGL_XLIB_FILTER_CONTINUE: The event was not handled, continues the
- *                            processing
- * @COGL_XLIB_FILTER_REMOVE: Remove the event, stops the processing
- *
- * Return values for the #CoglX11FilterFunc function.
- */
-typedef enum _CoglXlibFilterReturn {
-  COGL_XLIB_FILTER_CONTINUE,
-  COGL_XLIB_FILTER_REMOVE
-} CoglXlibFilterReturn;
-
-/*
- * CoglXlibFilterFunc:
- *
- * A callback function that can be registered with
- * _cogl_xlib_add_filter. The function should return
- * %COGL_XLIB_FILTER_REMOVE if it wants to prevent further processing
- * or %COGL_XLIB_FILTER_CONTINUE otherwise.
- */
-typedef CoglXlibFilterReturn (* CoglXlibFilterFunc) (XEvent *xevent,
-                                                     gpointer data);
-
-/*
- * cogl_xlib_handle_event:
- * @xevent: pointer to XEvent structure
- *
- * This function processes a single X event; it can be used to hook
- * into external X event retrieval (for example that done by Clutter
- * or GDK).
- *
- * Return value: #CoglXlibFilterReturn. %COGL_XLIB_FILTER_REMOVE
- * indicates that Cogl has internally handled the event and the
- * caller should do no further processing. %COGL_XLIB_FILTER_CONTINUE
- * indicates that Cogl is either not interested in the event,
- * or has used the event to update internal state without taking
- * any exclusive action.
- */
-CoglXlibFilterReturn
-_cogl_xlib_handle_event (XEvent *xevent);
-
-/*
- * _cogl_xlib_get_display:
- *
- * Return value: the Xlib display that will be used by the Xlib winsys
- * backend. The display needs to be set with _cogl_xlib_set_display()
- * before this function is called.
- */
-Display *
-_cogl_xlib_get_display (void);
+#define COGL_DRIVER_ERROR (_cogl_driver_error_quark ())
 
-/*
- * cogl_xlib_set_display:
- *
- * Sets the Xlib display that Cogl will use for the Xlib winsys
- * backend. This function should eventually go away when Cogl gains a
- * more complete winsys abstraction.
- */
-void
-_cogl_xlib_set_display (Display *display);
-
-/*
- * _cogl_xlib_add_filter:
- *
- * Adds a callback function that will receive all X11 events. The
- * function can stop further processing of the event by return
- * %COGL_XLIB_FILTER_REMOVE.
- */
-void
-_cogl_xlib_add_filter (CoglXlibFilterFunc func,
-                       gpointer data);
-
-/*
- * _cogl_xlib_remove_filter:
- *
- * Removes a callback that was previously added with
- * _cogl_xlib_add_filter().
- */
-void
-_cogl_xlib_remove_filter (CoglXlibFilterFunc func,
-                          gpointer data);
-
-#endif /* COGL_HAS_XLIB_SUPPORT */
-
-typedef enum _CoglFeatureFlagsPrivate
-{
-  COGL_FEATURE_PRIVATE_PLACE_HOLDER = (1 << 0)
-} CoglFeatureFlagsPrivate;
+typedef enum { /*< prefix=COGL_DRIVER_ERROR >*/
+  COGL_DRIVER_ERROR_UNKNOWN_VERSION,
+  COGL_DRIVER_ERROR_INVALID_VERSION
+} CoglDriverError;
 
 gboolean
-_cogl_features_available_private (CoglFeatureFlagsPrivate features);
+_cogl_check_extension (const char *name, const char *ext);
+
+GQuark
+_cogl_driver_error_quark (void);
 
 #endif /* __COGL_INTERNAL_H */
diff --git a/clutter/cogl/cogl/cogl-journal-private.h b/clutter/cogl/cogl/cogl-journal-private.h
index 44a4af8..7212dca 100644
--- a/clutter/cogl/cogl/cogl-journal-private.h
+++ b/clutter/cogl/cogl/cogl-journal-private.h
@@ -24,6 +24,7 @@
 #ifndef __COGL_JOURNAL_PRIVATE_H
 #define __COGL_JOURNAL_PRIVATE_H
 
+#include "cogl.h"
 #include "cogl-handle.h"
 #include "cogl-clip-stack.h"
 
diff --git a/clutter/cogl/cogl/cogl-private.h b/clutter/cogl/cogl/cogl-private.h
index 4407b42..bd09f4e 100644
--- a/clutter/cogl/cogl/cogl-private.h
+++ b/clutter/cogl/cogl/cogl-private.h
@@ -27,6 +27,12 @@
 G_BEGIN_DECLS
 
 gboolean
+_cogl_gl_check_version (GError **error);
+
+void
+_cogl_gl_update_features (CoglContext *context);
+
+gboolean
 _cogl_check_extension (const char *name, const char *ext);
 
 void
diff --git a/clutter/cogl/cogl/cogl-renderer-glx-private.h b/clutter/cogl/cogl/cogl-renderer-glx-private.h
new file mode 100644
index 0000000..aaebc9e
--- /dev/null
+++ b/clutter/cogl/cogl/cogl-renderer-glx-private.h
@@ -0,0 +1,61 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *
+ */
+
+#ifndef __COGL_RENDERER_GLX_PRIVATE_H
+#define __COGL_RENDERER_GLX_PRIVATE_H
+
+#include "cogl-object-private.h"
+#include "cogl-renderer-xlib-private.h"
+
+typedef struct _CoglRendererGLX
+{
+  CoglRendererXlib _parent;
+
+  int glx_major;
+  int glx_minor;
+
+  int glx_error_base;
+  int glx_event_base;
+
+  gboolean is_direct;
+
+  /* Vblank stuff */
+  int dri_fd;
+
+  /* Function pointers for GLX specific extensions */
+#define COGL_WINSYS_FEATURE_BEGIN(a, b, c, d, e, f)
+
+#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args) \
+  ret (APIENTRY * pf_ ## name) args;
+
+#define COGL_WINSYS_FEATURE_END()
+
+#include "cogl-winsys-glx-feature-functions.h"
+
+#undef COGL_WINSYS_FEATURE_BEGIN
+#undef COGL_WINSYS_FEATURE_FUNCTION
+#undef COGL_WINSYS_FEATURE_END
+} CoglRendererGLX;
+
+#endif /* __COGL_RENDERER_GLX_PRIVATE_H */
diff --git a/clutter/cogl/cogl/cogl-renderer-x11-private.h b/clutter/cogl/cogl/cogl-renderer-x11-private.h
new file mode 100644
index 0000000..5ec56cc
--- /dev/null
+++ b/clutter/cogl/cogl/cogl-renderer-x11-private.h
@@ -0,0 +1,32 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ */
+
+#ifndef __COGL_RENDERER_X11_PRIVATE_H
+#define __COGL_RENDERER_X11_PRIVATE_H
+
+typedef struct _CoglRendererX11
+{
+  int damage_base;
+} CoglRendererX11;
+
+#endif /* __COGL_RENDERER_X11_PRIVATE_H */
diff --git a/clutter/cogl/cogl/winsys/cogl-winsys-xlib.h b/clutter/cogl/cogl/cogl-renderer-xlib-private.h
similarity index 53%
rename from clutter/cogl/cogl/winsys/cogl-winsys-xlib.h
rename to clutter/cogl/cogl/cogl-renderer-xlib-private.h
index 62a2162..13f9464 100644
--- a/clutter/cogl/cogl/winsys/cogl-winsys-xlib.h
+++ b/clutter/cogl/cogl/cogl-renderer-xlib-private.h
@@ -3,7 +3,7 @@
  *
  * An object oriented GL/GLES Abstraction/Utility Layer
  *
- * Copyright (C) 2010 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
@@ -15,30 +15,40 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
  *
  *
  */
 
-#ifndef __COGL_XLIB_H
-#define __COGL_XLIB_H
+#ifndef __COGL_RENDERER_XLIB_PRIVATE_H
+#define __COGL_RENDERER_XLIB_PRIVATE_H
 
-#include "cogl.h"
-#include "cogl-context-winsys.h"
+#include "cogl-object-private.h"
+#include "cogl-xlib-private.h"
+#include "cogl-renderer-x11-private.h"
 
-#include <X11/Xlib.h>
+typedef struct _CoglRendererXlib
+{
+  CoglRendererX11 _parent;
 
-typedef struct _CoglXlibFilterClosure CoglXlibFilterClosure;
+  Display *xdpy;
 
-struct _CoglXlibFilterClosure
-{
-  CoglXlibFilterFunc func;
-  gpointer data;
-};
+  /* List of callback functions that will be given every Xlib event */
+  GSList *event_filters;
+  /* Current top of the XError trap state stack. The actual memory for
+     these is expected to be allocated on the stack by the caller */
+  CoglXlibTrapState *trap_state;
+} CoglRendererXlib;
+
+gboolean
+_cogl_renderer_xlib_connect (CoglRenderer *renderer, GError **error);
+
+void
+_cogl_renderer_xlib_disconnect (CoglRenderer *renderer);
 
 /*
- * _cogl_xlib_trap_errors:
+ * cogl_renderer_xlib_trap_errors:
  * @state: A temporary place to store data for the trap.
  *
  * Traps every X error until _cogl_xlib_untrap_errors() called. You
@@ -50,10 +60,11 @@ struct _CoglXlibFilterClosure
  * pointers in reverse order.
  */
 void
-_cogl_xlib_trap_errors (CoglXlibTrapState *state);
+_cogl_renderer_xlib_trap_errors (CoglRenderer *renderer,
+                                 CoglXlibTrapState *state);
 
 /*
- * _cogl_xlib_untrap_errors:
+ * cogl_renderer_xlib_untrap_errors:
  * @state: The state that was passed to _cogl_xlib_trap_errors().
  *
  * Removes the X error trap and returns the current status.
@@ -61,6 +72,7 @@ _cogl_xlib_trap_errors (CoglXlibTrapState *state);
  * Return value: the trapped error code, or 0 for success
  */
 int
-_cogl_xlib_untrap_errors (CoglXlibTrapState *state);
+_cogl_renderer_xlib_untrap_errors (CoglRenderer *renderer,
+                                   CoglXlibTrapState *state);
 
-#endif /* __COGL_XLIB_H */
+#endif /* __COGL_RENDERER_XLIB_PRIVATE_H */
diff --git a/clutter/cogl/cogl/cogl-renderer-xlib.c b/clutter/cogl/cogl/cogl-renderer-xlib.c
new file mode 100644
index 0000000..bd2cc2b
--- /dev/null
+++ b/clutter/cogl/cogl/cogl-renderer-xlib.c
@@ -0,0 +1,288 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2008,2009,2010 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *   Robert Bragg <robert linux intel com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "cogl.h"
+#include "cogl-internal.h"
+#include "cogl-object.h"
+
+#include "cogl-renderer-private.h"
+#include "cogl-renderer-xlib-private.h"
+#include "cogl-renderer-x11-private.h"
+#include "cogl-winsys-private.h"
+
+#include <X11/Xlib.h>
+#include <X11/extensions/Xdamage.h>
+
+static char *_cogl_x11_display_name = NULL;
+static GList *_cogl_xlib_renderers = NULL;
+
+CoglXlibFilterReturn
+cogl_renderer_xlib_handle_event (CoglRenderer *renderer,
+                                 XEvent *xevent)
+{
+  CoglRendererXlib *xlib_renderer = renderer->winsys;
+  GSList *l;
+
+  g_return_val_if_fail (xlib_renderer->xdpy != NULL, COGL_XLIB_FILTER_CONTINUE);
+
+  /* XXX: should this be a more graceful check? */
+  g_return_val_if_fail (xlib_renderer != NULL, COGL_XLIB_FILTER_CONTINUE);
+
+  /* Pass the event on to all of the registered filters in turn */
+  for (l = xlib_renderer->event_filters; l; l = l->next)
+    {
+      CoglXlibFilterClosure *closure = l->data;
+
+      if (closure->func (xevent, closure->data) == COGL_XLIB_FILTER_REMOVE)
+        return COGL_XLIB_FILTER_REMOVE;
+    }
+
+  switch (xevent->type)
+    {
+      /* TODO... */
+    default:
+      break;
+    }
+
+  return COGL_XLIB_FILTER_CONTINUE;
+}
+
+void
+cogl_renderer_xlib_add_filter (CoglRenderer *renderer,
+                               CoglXlibFilterFunc func,
+                               void *data)
+{
+  CoglRendererXlib *xlib_renderer;
+  CoglXlibFilterClosure *closure;
+
+  xlib_renderer = renderer->winsys;
+
+  closure = g_slice_new (CoglXlibFilterClosure);
+  closure->func = func;
+  closure->data = data;
+
+  xlib_renderer->event_filters =
+    g_slist_prepend (xlib_renderer->event_filters, closure);
+}
+
+void
+cogl_renderer_xlib_remove_filter (CoglRenderer *renderer,
+                                  CoglXlibFilterFunc func,
+                                  void *data)
+{
+  CoglRendererXlib *xlib_renderer;
+  GSList *l, *prev = NULL;
+
+  xlib_renderer = renderer->winsys;
+
+  for (l = xlib_renderer->event_filters; l; prev = l, l = l->next)
+    {
+      CoglXlibFilterClosure *closure = l->data;
+
+      if (closure->func == func && closure->data == data)
+        {
+          g_slice_free (CoglXlibFilterClosure, closure);
+          if (prev)
+            prev->next = g_slist_delete_link (prev->next, l);
+          else
+            xlib_renderer->event_filters =
+              g_slist_delete_link (xlib_renderer->event_filters, l);
+          break;
+        }
+    }
+}
+
+static void
+register_xlib_renderer (CoglRenderer *renderer)
+{
+  GList *l;
+
+  for (l = _cogl_xlib_renderers; l; l = l->next)
+    if (l->data == renderer)
+      return;
+
+  _cogl_xlib_renderers = g_list_prepend (_cogl_xlib_renderers, renderer);
+}
+
+static void
+unregister_xlib_renderer (CoglRenderer *renderer)
+{
+  _cogl_xlib_renderers = g_list_remove (_cogl_xlib_renderers, renderer);
+}
+
+static CoglRenderer *
+get_renderer_for_xdisplay (Display *xdpy)
+{
+  GList *l;
+
+  for (l = _cogl_xlib_renderers; l; l = l->next)
+    {
+      CoglRenderer *renderer = l->data;
+      CoglRendererXlib *xlib_renderer = renderer->winsys;
+
+      if (xlib_renderer->xdpy == xdpy)
+        return renderer;
+    }
+
+  return NULL;
+}
+
+static int
+error_handler (Display *xdpy,
+               XErrorEvent *error)
+{
+  CoglRenderer *renderer;
+  CoglRendererXlib *xlib_renderer;
+
+  renderer = get_renderer_for_xdisplay (xdpy);
+
+  xlib_renderer = renderer->winsys;
+  g_assert (xlib_renderer->trap_state);
+
+  xlib_renderer->trap_state->trapped_error_code = error->error_code;
+
+  return 0;
+}
+
+void
+_cogl_renderer_xlib_trap_errors (CoglRenderer *renderer,
+                                 CoglXlibTrapState *state)
+{
+  CoglRendererXlib *xlib_renderer;
+
+  xlib_renderer = renderer->winsys;
+
+  state->trapped_error_code = 0;
+  state->old_error_handler = XSetErrorHandler (error_handler);
+
+  state->old_state = xlib_renderer->trap_state;
+  xlib_renderer->trap_state = state;
+}
+
+int
+_cogl_renderer_xlib_untrap_errors (CoglRenderer *renderer,
+                                   CoglXlibTrapState *state)
+{
+  CoglRendererXlib *xlib_renderer;
+
+  xlib_renderer = renderer->winsys;
+  g_assert (state == xlib_renderer->trap_state);
+
+  XSetErrorHandler (state->old_error_handler);
+
+  xlib_renderer->trap_state = state->old_state;
+
+  return state->trapped_error_code;
+}
+
+static Display *
+assert_xlib_display (CoglRenderer *renderer, GError **error)
+{
+  Display *xdpy = cogl_renderer_xlib_get_foreign_display (renderer);
+  CoglRendererXlib *xlib_renderer = renderer->winsys;
+
+  /* A foreign display may have already been set... */
+  if (xdpy)
+    {
+      xlib_renderer->xdpy = xdpy;
+      return xdpy;
+    }
+
+  xdpy = XOpenDisplay (_cogl_x11_display_name);
+  if (xdpy == NULL)
+    {
+      g_set_error (error,
+                   COGL_RENDERER_ERROR,
+                   COGL_RENDERER_ERROR_XLIB_DISPLAY_OPEN,
+                   "Failed to open X Display %s", _cogl_x11_display_name);
+      return NULL;
+    }
+
+  xlib_renderer->xdpy = xdpy;
+  return xdpy;
+}
+
+gboolean
+_cogl_renderer_xlib_connect (CoglRenderer *renderer, GError **error)
+{
+  CoglRendererXlib *xlib_renderer = renderer->winsys;
+  CoglRendererX11 *x11_renderer = renderer->winsys;
+  int damage_error;
+
+  if (!assert_xlib_display (renderer, error))
+    return FALSE;
+
+  /* Check whether damage events are supported on this display */
+  if (!XDamageQueryExtension (xlib_renderer->xdpy,
+                              &x11_renderer->damage_base,
+                              &damage_error))
+    x11_renderer->damage_base = -1;
+
+  xlib_renderer->event_filters = NULL;
+
+  xlib_renderer->trap_state = NULL;
+
+  register_xlib_renderer (renderer);
+
+  return TRUE;
+}
+
+static void
+free_xlib_filter_closure (void *data, void *user_data)
+{
+  g_slice_free (CoglXlibFilterClosure, data);
+}
+
+void
+_cogl_renderer_xlib_disconnect (CoglRenderer *renderer)
+{
+  CoglRendererXlib *xlib_renderer = renderer->winsys;
+
+  g_slist_foreach (xlib_renderer->event_filters,
+                   free_xlib_filter_closure, NULL);
+  g_slist_free (xlib_renderer->event_filters);
+
+  if (!renderer->foreign_xdpy)
+    XCloseDisplay (xlib_renderer->xdpy);
+
+  unregister_xlib_renderer (renderer);
+}
+
+Display *
+cogl_renderer_xlib_get_display (CoglRenderer *renderer)
+{
+  CoglRendererXlib *xlib_renderer;
+
+  g_return_val_if_fail (cogl_is_renderer (renderer), NULL);
+
+  xlib_renderer = renderer->winsys;
+
+  return xlib_renderer->xdpy;
+}
diff --git a/clutter/cogl/cogl/cogl-renderer.c b/clutter/cogl/cogl/cogl-renderer.c
index 9eddc9b..2dffb2f 100644
--- a/clutter/cogl/cogl/cogl-renderer.c
+++ b/clutter/cogl/cogl/cogl-renderer.c
@@ -50,6 +50,9 @@ cogl_renderer_error_quark (void)
 static void
 _cogl_renderer_free (CoglRenderer *renderer)
 {
+#ifdef COGL_HAS_FULL_WINSYS
+  _cogl_winsys_renderer_disconnect (renderer);
+#endif
   g_free (renderer);
 }
 
@@ -90,6 +93,21 @@ cogl_renderer_check_onscreen_template (CoglRenderer *renderer,
                                        CoglOnscreenTemplate *onscreen_template,
                                        GError **error)
 {
+#ifdef COGL_HAS_FULL_WINSYS
+  CoglDisplay *display;
+
+  if (!_cogl_winsys_renderer_connect (renderer, error))
+    return FALSE;
+
+  display = cogl_display_new (renderer, onscreen_template);
+  if (!cogl_display_setup (display, error))
+    {
+      cogl_object_unref (display);
+      return FALSE;
+    }
+
+  cogl_object_unref (display);
+#endif
   return TRUE;
 }
 
@@ -101,6 +119,11 @@ cogl_renderer_connect (CoglRenderer *renderer, GError **error)
   if (renderer->connected)
     return TRUE;
 
+#ifdef COGL_HAS_FULL_WINSYS
+  if (!_cogl_winsys_renderer_connect (renderer, error))
+    return FALSE;
+#endif
+
   renderer->connected = TRUE;
   return TRUE;
 }
diff --git a/clutter/cogl/cogl/cogl-types.h b/clutter/cogl/cogl/cogl-types.h
index 6b5ff03..1a1aac4 100644
--- a/clutter/cogl/cogl/cogl-types.h
+++ b/clutter/cogl/cogl/cogl-types.h
@@ -30,6 +30,11 @@
 
 #include <glib-object.h>
 
+#include <cogl/cogl-defines.h>
+#ifdef COGL_HAS_XLIB
+#include <X11/Xlib.h>
+#endif
+
 G_BEGIN_DECLS
 
 /* Some structures are meant to be opaque but they have public
@@ -284,7 +289,8 @@ typedef enum
   COGL_FEATURE_TEXTURE_3D             = (1 << 19),
   COGL_FEATURE_SHADERS_ARBFP          = (1 << 20),
   COGL_FEATURE_MAP_BUFFER_FOR_READ    = (1 << 21),
-  COGL_FEATURE_MAP_BUFFER_FOR_WRITE   = (1 << 22)
+  COGL_FEATURE_MAP_BUFFER_FOR_WRITE   = (1 << 22),
+  COGL_FEATURE_ONSCREEN_MULTIPLE      = (1 << 23)
 } CoglFeatureFlags;
 
 /**
@@ -582,11 +588,84 @@ typedef enum
   COGL_DEPTH_TEST_FUNCTION_GEQUAL   = 0x0206,
   COGL_DEPTH_TEST_FUNCTION_ALWAYS   = 0x0207
 } CoglDepthTestFunction;
-/* XXX: Note these types are only referenced by experimental API so
- * although they aren't explicitly guarded they are implicitly
- * experimental too. */
 /* NB: The above definitions are taken from gl.h equivalents */
 
+typedef enum { /*< prefix=COGL_RENDERER_ERROR >*/
+  COGL_RENDERER_ERROR_NOT_FOUND,
+  COGL_RENDERER_ERROR_XLIB_DISPLAY_OPEN
+} CoglRendererError;
+
+/*
+ * CoglXlibFilterReturn:
+ * @COGL_XLIB_FILTER_CONTINUE: The event was not handled, continues the
+ *                            processing
+ * @COGL_XLIB_FILTER_REMOVE: Remove the event, stops the processing
+ *
+ * Return values for the #CoglXlibFilterFunc function.
+ *
+ * Stability: Unstable
+ */
+typedef enum _CoglXlibFilterReturn { /*< prefix=COGL_XLIB_FILTER >*/
+  COGL_XLIB_FILTER_CONTINUE,
+  COGL_XLIB_FILTER_REMOVE
+} CoglXlibFilterReturn;
+
+typedef enum _CoglWinsysFeature
+{
+  COGL_WINSYS_FEATURE_NONE,
+
+  /* Available if the window system can support multiple onscreen
+   * framebuffers at the same time. */
+  COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN,
+
+  /* Available if onscreen framebuffer swaps can be automatically
+   * throttled to the vblank frequency. */
+  COGL_WINSYS_FEATURE_SWAP_THROTTLE,
+
+  /* Available if its possible to query a counter that
+   * increments at each vblank. */
+  COGL_WINSYS_FEATURE_VBLANK_COUNTER,
+
+  /* Available if its possible to wait until the next vertical
+   * blank period */
+  COGL_WINSYS_FEATURE_VBLANK_WAIT,
+
+  /* Available if the window system supports mapping native
+   * pixmaps to textures. */
+  COGL_WINSYS_FEATURE_TEXTURE_FROM_PIXMAP,
+
+  /* Available if the window system supports reporting an event
+   * for swap buffer completions. */
+  COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT,
+
+  /* Available if it's possible to swap a list of sub rectangles
+   * from the back buffer to the front buffer */
+  COGL_WINSYS_FEATURE_SWAP_REGION,
+
+  /* Available if swap_region requests can be automatically throttled
+   * to the vblank frequency. */
+  COGL_WINSYS_FEATURE_SWAP_REGION_THROTTLE
+} CoglWinsysFeature;
+
+/* XXX: Note these enum types are only referenced by experimental API
+ * so although they aren't explicitly guarded they are implicitly
+ * experimental too. */
+
+#ifdef COGL_HAS_XLIB
+
+/*
+ * CoglXlibFilterFunc:
+ *
+ * A callback function that can be registered with
+ * _cogl_xlib_add_filter. The function should return
+ * %COGL_XLIB_FILTER_REMOVE if it wants to prevent further processing
+ * or %COGL_XLIB_FILTER_CONTINUE otherwise.
+ */
+typedef CoglXlibFilterReturn (* CoglXlibFilterFunc) (XEvent *xevent,
+                                                     void *data);
+
+#endif /* COGL_HAS_XLIB */
+
 G_END_DECLS
 
 #endif /* __COGL_TYPES_H__ */
diff --git a/clutter/cogl/cogl/cogl-util.c b/clutter/cogl/cogl/cogl-util.c
index d38049a..ddee76a 100644
--- a/clutter/cogl/cogl/cogl-util.c
+++ b/clutter/cogl/cogl/cogl-util.c
@@ -37,7 +37,6 @@
 #include "cogl-shader.h"
 #include "cogl-texture.h"
 #include "cogl-types.h"
-#include "cogl-handle.h"
 #include "cogl-util.h"
 
 /*
diff --git a/clutter/cogl/cogl/cogl-xlib-private.h b/clutter/cogl/cogl/cogl-xlib-private.h
new file mode 100644
index 0000000..39bfeba
--- /dev/null
+++ b/clutter/cogl/cogl/cogl-xlib-private.h
@@ -0,0 +1,82 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2010,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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ */
+
+#ifndef __COGL_XLIB_PRIVATE_H
+#define __COGL_XLIB_PRIVATE_H
+
+#include "cogl/cogl.h"
+
+#include <X11/Xlib.h>
+
+typedef struct _CoglXlibTrapState CoglXlibTrapState;
+
+struct _CoglXlibTrapState
+{
+  /* These values are intended to be internal to
+   * _cogl_xlib_{un,}trap_errors but they need to be in the header so
+   * that the struct can be allocated on the stack */
+  int (* old_error_handler) (Display *, XErrorEvent *);
+  int trapped_error_code;
+  CoglXlibTrapState *old_state;
+};
+
+typedef struct _CoglXlibFilterClosure
+{
+  CoglXlibFilterFunc func;
+  void *data;
+} CoglXlibFilterClosure;
+
+void
+_cogl_xlib_query_damage_extension (void);
+
+int
+_cogl_xlib_get_damage_base (void);
+
+void
+_cogl_xlib_trap_errors (CoglXlibTrapState *state);
+
+int
+_cogl_xlib_untrap_errors (CoglXlibTrapState *state);
+
+/*
+ * _cogl_xlib_add_filter:
+ *
+ * Adds a callback function that will receive all X11 events. The
+ * function can stop further processing of the event by return
+ * %COGL_XLIB_FILTER_REMOVE.
+ */
+void
+_cogl_xlib_add_filter (CoglXlibFilterFunc func,
+                       void *data);
+
+/*
+ * _cogl_xlib_remove_filter:
+ *
+ * Removes a callback that was previously added with
+ * _cogl_xlib_add_filter().
+ */
+void
+_cogl_xlib_remove_filter (CoglXlibFilterFunc func,
+                          void *data);
+
+#endif /* __COGL_XLIB_PRIVATE_H */
diff --git a/clutter/cogl/cogl/winsys/cogl-winsys-xlib.c b/clutter/cogl/cogl/cogl-xlib.c
similarity index 56%
rename from clutter/cogl/cogl/winsys/cogl-winsys-xlib.c
rename to clutter/cogl/cogl/cogl-xlib.c
index 636b9fb..ce7fb15 100644
--- a/clutter/cogl/cogl/winsys/cogl-winsys-xlib.c
+++ b/clutter/cogl/cogl/cogl-xlib.c
@@ -3,7 +3,7 @@
  *
  * An object oriented GL/GLES Abstraction/Utility Layer
  *
- * Copyright (C) 2010 Intel Corporation.
+ * Copyright (C) 2010,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
@@ -34,24 +34,36 @@
 #include <cogl-handle.h>
 #include <cogl-context-private.h>
 #include <cogl-framebuffer-private.h>
+#include <cogl-display-private.h>
+#include <cogl-renderer-private.h>
+#include <cogl-renderer-xlib-private.h>
 
 #include <X11/Xlib.h>
+#include <X11/extensions/Xdamage.h>
 
 #include "cogl-xlib.h"
 
+/* FIXME: when we remove the last X11 based Clutter backend then we
+ * will get rid of these functions and instead rely on the equivalent
+ * _cogl_renderer_xlib API
+ */
+
 /* This can't be in the Cogl context because it can be set before
    context is created */
 static Display *_cogl_xlib_display = NULL;
 
 CoglXlibFilterReturn
-_cogl_xlib_handle_event (XEvent *xevent)
+cogl_xlib_handle_event (XEvent *xevent)
 {
   GSList *l;
 
   _COGL_GET_CONTEXT (ctx, COGL_XLIB_FILTER_CONTINUE);
 
+  if (!ctx->stub_winsys)
+    return cogl_renderer_xlib_handle_event (ctx->display->renderer, xevent);
+
   /* Pass the event on to all of the registered filters in turn */
-  for (l = ctx->winsys.event_filters; l; l = l->next)
+  for (l = ctx->event_filters; l; l = l->next)
     {
       CoglXlibFilterClosure *closure = l->data;
 
@@ -70,10 +82,13 @@ _cogl_xlib_handle_event (XEvent *xevent)
 }
 
 Display *
-_cogl_xlib_get_display (void)
+cogl_xlib_get_display (void)
 {
   _COGL_GET_CONTEXT (ctx, NULL);
 
+  if (!ctx->stub_winsys)
+    return cogl_renderer_xlib_get_display (ctx->display->renderer);
+
   /* _cogl_xlib_set_display should be called before this function */
   g_assert (_cogl_xlib_display != NULL);
 
@@ -81,7 +96,7 @@ _cogl_xlib_get_display (void)
 }
 
 void
-_cogl_xlib_set_display (Display *display)
+cogl_xlib_set_display (Display *display)
 {
   /* This can only be called once before the Cogl context is created */
   g_assert (_cogl_xlib_display == NULL);
@@ -91,29 +106,43 @@ _cogl_xlib_set_display (Display *display)
 
 void
 _cogl_xlib_add_filter (CoglXlibFilterFunc func,
-                       gpointer data)
+                       void *data)
 {
   CoglXlibFilterClosure *closure;
 
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
+  if (!ctx->stub_winsys)
+    {
+      cogl_renderer_xlib_add_filter (ctx->display->renderer,
+                                     func, data);
+      return;
+    }
+
   closure = g_slice_new (CoglXlibFilterClosure);
   closure->func = func;
   closure->data = data;
 
-  ctx->winsys.event_filters =
-    g_slist_prepend (ctx->winsys.event_filters, closure);
+  ctx->event_filters =
+    g_slist_prepend (ctx->event_filters, closure);
 }
 
 void
 _cogl_xlib_remove_filter (CoglXlibFilterFunc func,
-                          gpointer data)
+                          void *data)
 {
   GSList *l, *prev = NULL;
 
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
-  for (l = ctx->winsys.event_filters; l; prev = l, l = l->next)
+  if (!ctx->stub_winsys)
+    {
+      cogl_renderer_xlib_remove_filter (ctx->display->renderer,
+                                        func, data);
+      return;
+    }
+
+  for (l = ctx->event_filters; l; prev = l, l = l->next)
     {
       CoglXlibFilterClosure *closure = l->data;
 
@@ -123,8 +152,8 @@ _cogl_xlib_remove_filter (CoglXlibFilterFunc func,
           if (prev)
             prev->next = g_slist_delete_link (prev->next, l);
           else
-            ctx->winsys.event_filters =
-              g_slist_delete_link (ctx->winsys.event_filters, l);
+            ctx->event_filters =
+              g_slist_delete_link (ctx->event_filters, l);
           break;
         }
     }
@@ -136,9 +165,9 @@ error_handler (Display     *xdpy,
 {
   _COGL_GET_CONTEXT (ctxt, 0);
 
-  g_assert (ctxt->winsys.trap_state);
+  g_assert (ctxt->trap_state);
 
-  ctxt->winsys.trap_state->trapped_error_code = error->error_code;
+  ctxt->trap_state->trapped_error_code = error->error_code;
 
   return 0;
 }
@@ -148,11 +177,17 @@ _cogl_xlib_trap_errors (CoglXlibTrapState *state)
 {
   _COGL_GET_CONTEXT (ctxt, NO_RETVAL);
 
+  if (!ctxt->stub_winsys)
+    {
+      _cogl_renderer_xlib_trap_errors (ctxt->display->renderer, state);
+      return;
+    }
+
   state->trapped_error_code = 0;
   state->old_error_handler = XSetErrorHandler (error_handler);
 
-  state->old_state = ctxt->winsys.trap_state;
-  ctxt->winsys.trap_state = state;
+  state->old_state = ctxt->trap_state;
+  ctxt->trap_state = state;
 }
 
 int
@@ -160,11 +195,44 @@ _cogl_xlib_untrap_errors (CoglXlibTrapState *state)
 {
   _COGL_GET_CONTEXT (ctxt, 0);
 
-  g_assert (state == ctxt->winsys.trap_state);
+  if (!ctxt->stub_winsys)
+    {
+      return _cogl_renderer_xlib_untrap_errors (ctxt->display->renderer, state);
+    }
+
+  g_assert (state == ctxt->trap_state);
 
   XSetErrorHandler (state->old_error_handler);
 
-  ctxt->winsys.trap_state = state->old_state;
+  ctxt->trap_state = state->old_state;
 
   return state->trapped_error_code;
 }
+
+void
+_cogl_xlib_query_damage_extension (void)
+{
+  int damage_error;
+
+  _COGL_GET_CONTEXT (ctxt, NO_RETVAL);
+
+  /* Check whether damage events are supported on this display */
+  if (!XDamageQueryExtension (cogl_xlib_get_display (),
+                              &ctxt->damage_base,
+                              &damage_error))
+    ctxt->damage_base = -1;
+}
+
+int
+_cogl_xlib_get_damage_base (void)
+{
+  _COGL_GET_CONTEXT (ctxt, -1);
+
+  if (!ctxt->stub_winsys)
+    {
+      CoglRendererX11 *x11_renderer = ctxt->display->renderer->winsys;
+      return x11_renderer->damage_base;
+    }
+  else
+    return ctxt->damage_base;
+}
diff --git a/clutter/cogl/cogl/cogl-xlib.h b/clutter/cogl/cogl/cogl-xlib.h
new file mode 100644
index 0000000..c776ece
--- /dev/null
+++ b/clutter/cogl/cogl/cogl-xlib.h
@@ -0,0 +1,84 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
+#error "Only <cogl/cogl.h> can be included directly."
+#endif
+
+#ifndef __COGL_XLIB_H__
+#define __COGL_XLIB_H__
+
+#include <cogl/cogl-types.h>
+
+#include <X11/Xlib.h>
+
+G_BEGIN_DECLS
+
+/*
+ * cogl_xlib_get_display:
+ *
+ * Return value: the Xlib display that will be used by the Xlib winsys
+ * backend. The display needs to be set with _cogl_xlib_set_display()
+ * before this function is called.
+ *
+ * Stability: Unstable
+ */
+#define cogl_xlib_get_display cogl_xlib_get_display_EXP
+Display *
+cogl_xlib_get_display (void);
+
+/*
+ * cogl_xlib_set_display:
+ *
+ * Sets the Xlib display that Cogl will use for the Xlib winsys
+ * backend. This function should eventually go away when Cogl gains a
+ * more complete winsys abstraction.
+ *
+ * Stability: Unstable
+ */
+#define cogl_xlib_set_display cogl_xlib_set_display_EXP
+void
+cogl_xlib_set_display (Display *display);
+
+/*
+ * cogl_xlib_handle_event:
+ * @xevent: pointer to XEvent structure
+ *
+ * This function processes a single X event; it can be used to hook
+ * into external X event retrieval (for example that done by Clutter
+ * or GDK).
+ *
+ * Return value: #CoglXlibFilterReturn. %COGL_XLIB_FILTER_REMOVE
+ * indicates that Cogl has internally handled the event and the
+ * caller should do no further processing. %COGL_XLIB_FILTER_CONTINUE
+ * indicates that Cogl is either not interested in the event,
+ * or has used the event to update internal state without taking
+ * any exclusive action.
+ *
+ * Stability: Unstable
+ */
+#define cogl_xlib_handle_event cogl_xlib_handle_event_EXP
+CoglXlibFilterReturn
+cogl_xlib_handle_event (XEvent *xevent);
+
+#endif /* __COGL_XLIB_H__ */
diff --git a/clutter/cogl/cogl/cogl.c b/clutter/cogl/cogl/cogl.c
index aa483c9..49882d9 100644
--- a/clutter/cogl/cogl/cogl.c
+++ b/clutter/cogl/cogl/cogl.c
@@ -38,7 +38,7 @@
 #include "cogl-context-private.h"
 #include "cogl-pipeline-private.h"
 #include "cogl-pipeline-opengl-private.h"
-#include "cogl-winsys.h"
+#include "cogl-winsys-private.h"
 #include "cogl-framebuffer-private.h"
 #include "cogl-matrix-private.h"
 #include "cogl-journal-private.h"
@@ -394,14 +394,6 @@ cogl_features_available (CoglFeatureFlags features)
   return (ctx->feature_flags & features) == features;
 }
 
-gboolean
-_cogl_features_available_private (CoglFeatureFlagsPrivate features)
-{
-  _COGL_GET_CONTEXT (ctx, 0);
-
-  return (ctx->feature_flags_private & features) == features;
-}
-
 /* XXX: This function should either be replaced with one returning
  * integers, or removed/deprecated and make the
  * _cogl_framebuffer_get_viewport* functions public.
diff --git a/clutter/cogl/cogl/cogl.h b/clutter/cogl/cogl/cogl.h
index fffc12c..cbd2d0c 100644
--- a/clutter/cogl/cogl/cogl.h
+++ b/clutter/cogl/cogl/cogl.h
@@ -67,7 +67,12 @@
 
 #include <cogl/cogl-deprecated.h>
 
+typedef struct _CoglFramebuffer CoglFramebuffer;
+
 #if defined (COGL_ENABLE_EXPERIMENTAL_API)
+#include <cogl/cogl-swap-chain.h>
+#include <cogl/cogl-renderer.h>
+#include <cogl/cogl-display.h>
 #include <cogl/cogl-context.h>
 #include <cogl/cogl-buffer.h>
 #include <cogl/cogl-pixel-array.h>
@@ -79,6 +84,13 @@
 #include <cogl/cogl-attribute.h>
 #include <cogl/cogl-primitive.h>
 #include <cogl/cogl-pipeline.h>
+#include <cogl/cogl-framebuffer.h>
+#ifdef COGL_HAS_XLIB
+#include <cogl/cogl-xlib.h>
+#endif
+/* XXX: This will definitly go away once all the Clutter winsys
+ * code has been migrated down into Cogl! */
+#include <cogl/cogl-clutter.h>
 #endif
 
 G_BEGIN_DECLS
@@ -90,8 +102,6 @@ G_BEGIN_DECLS
  * General utility functions for COGL.
  */
 
-typedef struct _CoglFramebuffer CoglFramebuffer;
-
 /**
  * cogl_get_option_group:
  *
@@ -1245,44 +1255,6 @@ cogl_begin_gl (void);
 void
 cogl_end_gl (void);
 
-/*
- * Internal API available only to Clutter.
- *
- * These are typically only to deal with the poor seperation of
- * responsabilities that currently exists between Clutter and Cogl.
- * Eventually a lot of the backend code currently in Clutter will
- * move down into Cogl and these functions will be removed.
- */
-
-void
-_cogl_destroy_context (void);
-
-/*< private >*/
-#define COGL_DRIVER_ERROR (_cogl_driver_error_quark ())
-
-typedef enum { /*< prefix=COGL_DRIVER_ERROR >*/
-  COGL_DRIVER_ERROR_UNKNOWN_VERSION,
-  COGL_DRIVER_ERROR_INVALID_VERSION
-} CoglDriverError;
-
-gboolean
-_cogl_check_extension (const char *name, const char *ext);
-
-void
-_cogl_set_indirect_context  (gboolean indirect);
-
-gboolean
-_cogl_check_driver_valid (GError **error);
-
-GQuark
-_cogl_driver_error_quark (void);
-
-#ifdef COGL_ENABLE_EXPERIMENTAL_API
-#define cogl_get_draw_framebuffer cogl_get_draw_framebuffer_EXP
-CoglFramebuffer *
-cogl_get_draw_framebuffer (void);
-#endif
-
 G_END_DECLS
 
 #undef __COGL_H_INSIDE__
diff --git a/clutter/cogl/cogl/driver/gl/cogl-context-driver-gl.h b/clutter/cogl/cogl/driver/gl/cogl-context-driver-gl.h
new file mode 100644
index 0000000..2d8e521
--- /dev/null
+++ b/clutter/cogl/cogl/driver/gl/cogl-context-driver-gl.h
@@ -0,0 +1,53 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2007,2008,2009 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ */
+
+#ifndef __COGL_CONTEXT_DRIVER_H
+#define __COGL_CONTEXT_DRIVER_H
+
+#include "cogl.h"
+
+#ifndef APIENTRY
+#define APIENTRY
+#endif
+
+#define COGL_FEATURE_BEGIN(a, b, c, d, e, f, g)
+
+#define COGL_FEATURE_FUNCTION(ret, name, args) \
+  ret (APIENTRY * pf_ ## name) args;
+
+#define COGL_FEATURE_END()
+
+typedef struct _CoglContextDriver
+{
+  /* This defines a list of function pointers */
+#include "cogl-feature-functions-gl.h"
+
+  GLint gl_max_program_temoraries_arb;
+} CoglContextDriver;
+
+#undef COGL_FEATURE_BEGIN
+#undef COGL_FEATURE_FUNCTION
+#undef COGL_FEATURE_END
+
+#endif /* __COGL_CONTEXT_DRIVER_H */
+
diff --git a/clutter/cogl/cogl/driver/gl/cogl-gl.c b/clutter/cogl/cogl/driver/gl/cogl-gl.c
index b26f230..b5a3bee 100644
--- a/clutter/cogl/cogl/driver/gl/cogl-gl.c
+++ b/clutter/cogl/cogl/driver/gl/cogl-gl.c
@@ -29,6 +29,7 @@
 
 #include "cogl.h"
 
+#include "cogl-private.h"
 #include "cogl-internal.h"
 #include "cogl-context-private.h"
 #include "cogl-feature-private.h"
@@ -95,7 +96,7 @@ _cogl_get_gl_version (int *major_out, int *minor_out)
 }
 
 gboolean
-_cogl_check_driver_valid (GError **error)
+_cogl_gl_check_version (GError **error)
 {
   int major, minor;
   const char *gl_extensions;
@@ -161,8 +162,8 @@ _cogl_check_driver_valid (GError **error)
                            namespaces, extension_names,                 \
                            feature_flags, feature_flags_private)        \
   { min_gl_major, min_gl_minor, namespaces,                             \
-      extension_names, feature_flags, feature_flags_private,             \
-      cogl_feature_ ## name ## _funcs },
+    extension_names, feature_flags, feature_flags_private, 0,           \
+    cogl_feature_ ## name ## _funcs },
 #undef COGL_FEATURE_FUNCTION
 #define COGL_FEATURE_FUNCTION(ret, name, args)
 #undef COGL_FEATURE_END
@@ -182,23 +183,35 @@ static const CoglFeatureData cogl_feature_data[] =
 #define COGL_FEATURE_END()
 
 static void
-initialize_context_driver (CoglContext *context)
+initialize_function_table (CoglContext *context)
 {
   #include "cogl-feature-functions-gl.h"
 }
 
+/* Query the GL extensions and lookup the corresponding function
+ * pointers. Theoretically the list of extensions can change for
+ * different GL contexts so it is the winsys backend's responsiblity
+ * to know when to re-query the GL extensions. */
 void
-_cogl_gl_context_init (CoglContext *context)
+_cogl_gl_update_features (CoglContext *context)
 {
   CoglFeatureFlags flags = 0;
-  CoglFeatureFlagsPrivate  flags_private = 0;
   const char *gl_extensions;
   int max_clip_planes = 0;
   int num_stencil_bits = 0;
   int gl_major = 0, gl_minor = 0;
   int i;
 
-  initialize_context_driver (context);
+  COGL_NOTE (WINSYS,
+             "Checking features\n"
+             "  GL_VENDOR: %s\n"
+             "  GL_RENDERER: %s\n"
+             "  GL_VERSION: %s\n"
+             "  GL_EXTENSIONS: %s",
+             glGetString (GL_VENDOR),
+             glGetString (GL_RENDERER),
+             glGetString (GL_VERSION),
+             glGetString (GL_EXTENSIONS));
 
   _cogl_get_gl_version (&gl_major, &gl_minor);
 
@@ -235,16 +248,15 @@ _cogl_gl_context_init (CoglContext *context)
   if (max_clip_planes >= 4)
     flags |= COGL_FEATURE_FOUR_CLIP_PLANES;
 
+  initialize_function_table (context);
+
   for (i = 0; i < G_N_ELEMENTS (cogl_feature_data); i++)
     if (_cogl_feature_check ("GL", cogl_feature_data + i,
                              gl_major, gl_minor,
-                             gl_extensions))
-      {
-        flags |= cogl_feature_data[i].feature_flags;
-        flags_private |= cogl_feature_data[i].feature_flags_private;
-      }
+                             gl_extensions,
+                             context))
+      flags |= cogl_feature_data[i].feature_flags;
 
   /* Cache features */
-  context->feature_flags = flags;
-  context->feature_flags_private = flags_private;
+  context->feature_flags |= flags;
 }
diff --git a/clutter/cogl/cogl/driver/gles/cogl-context-driver-gles.h b/clutter/cogl/cogl/driver/gles/cogl-context-driver-gles.h
new file mode 100644
index 0000000..ca3b1d4
--- /dev/null
+++ b/clutter/cogl/cogl/driver/gles/cogl-context-driver-gles.h
@@ -0,0 +1,52 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2007,2008,2009 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ */
+
+#ifndef __COGL_CONTEXT_DRIVER_H
+#define __COGL_CONTEXT_DRIVER_H
+
+#include "cogl.h"
+
+#ifndef APIENTRY
+#define APIENTRY
+#endif
+
+#define COGL_FEATURE_BEGIN(a, b, c, d, e, f, g)
+
+#define COGL_FEATURE_FUNCTION(ret, name, args) \
+  ret (APIENTRY * pf_ ## name) args;
+
+#define COGL_FEATURE_END()
+
+typedef struct _CoglContextDriver
+{
+  /* This defines a list of function pointers */
+#include "cogl-feature-functions-gles.h"
+
+} CoglContextDriver;
+
+#undef COGL_FEATURE_BEGIN
+#undef COGL_FEATURE_FUNCTION
+#undef COGL_FEATURE_END
+
+#endif /* __COGL_CONTEXT_DRIVER_H */
+
diff --git a/clutter/cogl/cogl/driver/gles/cogl-gles.c b/clutter/cogl/cogl/driver/gles/cogl-gles.c
index 304e537..f137925 100644
--- a/clutter/cogl/cogl/driver/gles/cogl-gles.c
+++ b/clutter/cogl/cogl/driver/gles/cogl-gles.c
@@ -33,7 +33,7 @@
 #include "cogl-feature-private.h"
 
 gboolean
-_cogl_check_driver_valid (GError **error)
+_cogl_gl_check_version (GError **error)
 {
   /* The GLES backend doesn't have any particular version requirements */
   return TRUE;
@@ -58,8 +58,8 @@ _cogl_check_driver_valid (GError **error)
                            namespaces, extension_names,                 \
                            feature_flags, feature_flags_private)        \
   { min_gl_major, min_gl_minor, namespaces,                             \
-      extension_names, feature_flags, feature_flags_private,            \
-      cogl_feature_ ## name ## _funcs },
+    extension_names, feature_flags, feature_flags_private, 0,           \
+    cogl_feature_ ## name ## _funcs },
 #undef COGL_FEATURE_FUNCTION
 #define COGL_FEATURE_FUNCTION(ret, name, args)
 #undef COGL_FEATURE_END
@@ -74,36 +74,44 @@ static const CoglFeatureData cogl_feature_data[] =
 #define COGL_FEATURE_BEGIN(a, b, c, d, e, f, g)
 #undef COGL_FEATURE_FUNCTION
 #define COGL_FEATURE_FUNCTION(ret, name, args) \
-  _context->drv.pf_ ## name = NULL;
+  context->drv.pf_ ## name = NULL;
 #undef COGL_FEATURE_END
 #define COGL_FEATURE_END()
 
 static void
-initialize_context_driver (CoglContext *context)
+initialize_function_table (CoglContext *context)
 {
   #include "cogl-feature-functions-gles.h"
 }
 
+/* Query the GL extensions and lookup the corresponding function
+ * pointers. Theoretically the list of extensions can change for
+ * different GL contexts so it is the winsys backend's responsiblity
+ * to know when to re-query the GL extensions. */
 void
-_cogl_gl_context_init (CoglContext *context)
+_cogl_gl_update_features (CoglContext *context)
 {
   CoglFeatureFlags flags = 0;
+  const char *gl_extensions;
 #ifndef HAVE_COGL_GLES2
   int max_clip_planes = 0;
 #endif
   int num_stencil_bits = 0;
-  const char *gl_extensions;
   int i;
 
-  initialize_context_driver (context);
+  COGL_NOTE (WINSYS,
+             "Checking features\n"
+             "  GL_VENDOR: %s\n"
+             "  GL_RENDERER: %s\n"
+             "  GL_VERSION: %s\n"
+             "  GL_EXTENSIONS: %s",
+             glGetString (GL_VENDOR),
+             glGetString (GL_RENDERER),
+             glGetString (GL_VERSION),
+             glGetString (GL_EXTENSIONS));
 
   gl_extensions = (const char*) glGetString (GL_EXTENSIONS);
 
-  for (i = 0; i < G_N_ELEMENTS (cogl_feature_data); i++)
-    if (_cogl_feature_check ("GL", cogl_feature_data + i,
-                             0, 0,
-                             gl_extensions))
-        flags |= cogl_feature_data[i].feature_flags;
 
   GE( glGetIntegerv (GL_STENCIL_BITS, &num_stencil_bits) );
   /* We need at least three stencil bits to combine clips */
@@ -128,7 +136,15 @@ _cogl_gl_context_init (CoglContext *context)
   /* Both GLES 1.1 and GLES 2.0 support point sprites in core */
   flags |= COGL_FEATURE_POINT_SPRITE;
 
+  initialize_function_table (context);
+
+  for (i = 0; i < G_N_ELEMENTS (cogl_feature_data); i++)
+    if (_cogl_feature_check ("GL", cogl_feature_data + i,
+                             0, 0,
+                             gl_extensions,
+                             context))
+      flags |= cogl_feature_data[i].feature_flags;
+
   /* Cache features */
-  context->feature_flags = flags;
+  context->feature_flags |= flags;
 }
-
diff --git a/clutter/cogl/cogl/winsys/cogl-texture-pixmap-x11.c b/clutter/cogl/cogl/winsys/cogl-texture-pixmap-x11.c
index 98ecf31..9f8ec69 100644
--- a/clutter/cogl/cogl/winsys/cogl-texture-pixmap-x11.c
+++ b/clutter/cogl/cogl/winsys/cogl-texture-pixmap-x11.c
@@ -42,7 +42,11 @@
 #include "cogl-texture-rectangle-private.h"
 #include "cogl-context-private.h"
 #include "cogl-handle.h"
-#include "cogl-winsys-xlib.h"
+#if COGL_HAS_GLX_SUPPORT
+#include "cogl-display-glx-private.h"
+#include "cogl-renderer-private.h"
+#include "cogl-renderer-glx-private.h"
+#endif
 #include "cogl-pipeline-opengl-private.h"
 
 #include <X11/Xlib.h>
@@ -55,9 +59,6 @@
 #include <string.h>
 #include <math.h>
 
-#define glXBindTexImage ctx->winsys.pf_glXBindTexImage
-#define glXReleaseTexImage ctx->winsys.pf_glXReleaseTexImage
-
 static void _cogl_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap);
 
 COGL_TEXTURE_DEFINE (TexturePixmapX11, texture_pixmap_x11);
@@ -112,7 +113,7 @@ process_damage_event (CoglTexturePixmapX11 *tex_pixmap,
 
   _COGL_GET_CONTEXT (ctxt, NO_RETVAL);
 
-  display = _cogl_xlib_get_display ();
+  display = cogl_xlib_get_display ();
 
   COGL_NOTE (TEXTURE_PIXMAP, "Damage event received for %p", tex_pixmap);
 
@@ -206,10 +207,12 @@ static CoglXlibFilterReturn
 _cogl_texture_pixmap_x11_filter (XEvent *event, gpointer data)
 {
   CoglTexturePixmapX11 *tex_pixmap = data;
+  int damage_base;
 
   _COGL_GET_CONTEXT (ctxt, COGL_XLIB_FILTER_CONTINUE);
 
-  if (event->type == ctxt->winsys.damage_base + XDamageNotify)
+  damage_base = _cogl_xlib_get_damage_base ();
+  if (event->type == damage_base + XDamageNotify)
     {
       XDamageNotifyEvent *damage_event = (XDamageNotifyEvent *) event;
 
@@ -228,26 +231,28 @@ get_fbconfig_for_depth (unsigned int depth,
                         gboolean *can_mipmap_ret)
 {
   GLXFBConfig *fbconfigs;
-  int          n_elements, i;
-  Display     *dpy;
-  int          db, stencil, alpha, mipmap, rgba, value;
-  int          spare_cache_slot = 0;
-  gboolean     found = FALSE;
+  int n_elements, i;
+  Display *dpy;
+  int db, stencil, alpha, mipmap, rgba, value;
+  int spare_cache_slot = 0;
+  gboolean found = FALSE;
+  CoglDisplayGLX *glx_display;
 
   _COGL_GET_CONTEXT (ctxt, FALSE);
+  glx_display = ctxt->display->winsys;
 
   /* Check if we've already got a cached config for this depth */
-  for (i = 0; i < COGL_WINSYS_N_CACHED_CONFIGS; i++)
-    if (ctxt->winsys.glx_cached_configs[i].depth == -1)
+  for (i = 0; i < COGL_GLX_N_CACHED_CONFIGS; i++)
+    if (glx_display->glx_cached_configs[i].depth == -1)
       spare_cache_slot = i;
-    else if (ctxt->winsys.glx_cached_configs[i].depth == depth)
+    else if (glx_display->glx_cached_configs[i].depth == depth)
       {
-        *fbconfig_ret = ctxt->winsys.glx_cached_configs[i].fb_config;
-        *can_mipmap_ret = ctxt->winsys.glx_cached_configs[i].can_mipmap;
-        return ctxt->winsys.glx_cached_configs[i].found;
+        *fbconfig_ret = glx_display->glx_cached_configs[i].fb_config;
+        *can_mipmap_ret = glx_display->glx_cached_configs[i].can_mipmap;
+        return glx_display->glx_cached_configs[i].found;
       }
 
-  dpy = _cogl_xlib_get_display ();
+  dpy = cogl_xlib_get_display ();
 
   fbconfigs = glXGetFBConfigs (dpy, DefaultScreen (dpy),
                                &n_elements);
@@ -349,10 +354,10 @@ get_fbconfig_for_depth (unsigned int depth,
   if (n_elements)
     XFree (fbconfigs);
 
-  ctxt->winsys.glx_cached_configs[spare_cache_slot].depth = depth;
-  ctxt->winsys.glx_cached_configs[spare_cache_slot].found = found;
-  ctxt->winsys.glx_cached_configs[spare_cache_slot].fb_config = *fbconfig_ret;
-  ctxt->winsys.glx_cached_configs[spare_cache_slot].can_mipmap = mipmap;
+  glx_display->glx_cached_configs[spare_cache_slot].depth = depth;
+  glx_display->glx_cached_configs[spare_cache_slot].found = found;
+  glx_display->glx_cached_configs[spare_cache_slot].fb_config = *fbconfig_ret;
+  glx_display->glx_cached_configs[spare_cache_slot].can_mipmap = mipmap;
 
   return found;
 }
@@ -362,7 +367,7 @@ should_use_rectangle (void)
 {
   _COGL_GET_CONTEXT (ctxt, FALSE);
 
-  if (ctxt->winsys.rectangle_state == COGL_WINSYS_RECTANGLE_STATE_UNKNOWN)
+  if (ctxt->rectangle_state == COGL_WINSYS_RECTANGLE_STATE_UNKNOWN)
     {
       if (cogl_features_available (COGL_FEATURE_TEXTURE_RECTANGLE))
         {
@@ -378,7 +383,7 @@ should_use_rectangle (void)
              the env var is set to 'allow' or not set and NPOTs textures
              are not available */
 
-          ctxt->winsys.rectangle_state =
+          ctxt->rectangle_state =
             cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) ?
             COGL_WINSYS_RECTANGLE_STATE_DISABLE :
             COGL_WINSYS_RECTANGLE_STATE_ENABLE;
@@ -389,10 +394,10 @@ should_use_rectangle (void)
               (rect_env = g_getenv ("CLUTTER_PIXMAP_TEXTURE_RECTANGLE")))
             {
               if (g_ascii_strcasecmp (rect_env, "force") == 0)
-                ctxt->winsys.rectangle_state =
+                ctxt->rectangle_state =
                   COGL_WINSYS_RECTANGLE_STATE_ENABLE;
               else if (g_ascii_strcasecmp (rect_env, "disable") == 0)
-                ctxt->winsys.rectangle_state =
+                ctxt->rectangle_state =
                   COGL_WINSYS_RECTANGLE_STATE_DISABLE;
               else if (g_ascii_strcasecmp (rect_env, "allow"))
                 g_warning ("Unknown value for COGL_PIXMAP_TEXTURE_RECTANGLE, "
@@ -400,10 +405,10 @@ should_use_rectangle (void)
             }
         }
       else
-        ctxt->winsys.rectangle_state = COGL_WINSYS_RECTANGLE_STATE_DISABLE;
+        ctxt->rectangle_state = COGL_WINSYS_RECTANGLE_STATE_DISABLE;
     }
 
-  return ctxt->winsys.rectangle_state == COGL_WINSYS_RECTANGLE_STATE_ENABLE;
+  return ctxt->rectangle_state == COGL_WINSYS_RECTANGLE_STATE_ENABLE;
 }
 
 static void
@@ -425,11 +430,10 @@ try_create_glx_pixmap (CoglTexturePixmapX11 *tex_pixmap,
   tex_pixmap->pixmap_bound = FALSE;
   tex_pixmap->glx_pixmap = None;
 
-  if ((ctxt->winsys.feature_flags &
-       COGL_WINSYS_FEATURE_TEXTURE_FROM_PIXMAP) == 0)
+  if (!_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_TEXTURE_FROM_PIXMAP))
     return;
 
-  dpy = _cogl_xlib_get_display ();
+  dpy = cogl_xlib_get_display ();
 
   if (!get_fbconfig_for_depth (tex_pixmap->depth, &fb_config,
                                &tex_pixmap->glx_can_mipmap))
@@ -507,7 +511,7 @@ set_damage_object_internal (CoglTexturePixmapX11 *tex_pixmap,
 
       if (tex_pixmap->damage_owned)
         {
-          XDamageDestroy (_cogl_xlib_get_display (), tex_pixmap->damage);
+          XDamageDestroy (cogl_xlib_get_display (), tex_pixmap->damage);
           tex_pixmap->damage_owned = FALSE;
         }
     }
@@ -524,12 +528,13 @@ cogl_texture_pixmap_x11_new (guint32 pixmap,
                              gboolean automatic_updates)
 {
   CoglTexturePixmapX11 *tex_pixmap = g_new (CoglTexturePixmapX11, 1);
-  Display *display = _cogl_xlib_get_display ();
+  Display *display = cogl_xlib_get_display ();
   Window pixmap_root_window;
   int pixmap_x, pixmap_y;
   unsigned int pixmap_border_width;
   CoglTexture *tex = COGL_TEXTURE (tex_pixmap);
   XWindowAttributes window_attributes;
+  int damage_base;
 
   _COGL_GET_CONTEXT (ctxt, COGL_INVALID_HANDLE);
 
@@ -565,7 +570,8 @@ cogl_texture_pixmap_x11_new (guint32 pixmap,
   /* If automatic updates are requested and the Xlib connection
      supports damage events then we'll register a damage object on the
      pixmap */
-  if (automatic_updates && ctxt->winsys.damage_base >= 0)
+  damage_base = _cogl_xlib_get_damage_base ();
+  if (automatic_updates && damage_base >= 0)
     {
       Damage damage = XDamageCreate (display,
                                      pixmap,
@@ -601,7 +607,7 @@ try_alloc_shm (CoglTexturePixmapX11 *tex_pixmap)
   XImage *dummy_image;
   Display *display;
 
-  display = _cogl_xlib_get_display ();
+  display = cogl_xlib_get_display ();
 
   if (!XShmQueryExtension (display))
     return;
@@ -709,13 +715,15 @@ cogl_texture_pixmap_x11_set_damage_object (CoglHandle handle,
                                                                   report_level)
 {
   CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (handle);
+  int damage_base;
 
   _COGL_GET_CONTEXT (ctxt, NO_RETVAL);
 
   if (!cogl_is_texture_pixmap_x11 (tex_pixmap))
     return;
 
-  if (ctxt->winsys.damage_base >= 0)
+  damage_base = _cogl_xlib_get_damage_base ();
+  if (damage_base >= 0)
     set_damage_object_internal (tex_pixmap, damage, report_level);
 }
 
@@ -728,7 +736,7 @@ _cogl_texture_pixmap_x11_update_image_texture (CoglTexturePixmapX11 *tex_pixmap)
   int src_x, src_y;
   int x, y, width, height;
 
-  display = _cogl_xlib_get_display ();
+  display = cogl_xlib_get_display ();
 
   /* If the damage region is empty then there's nothing to do */
   if (tex_pixmap->damage_rect.x2 == tex_pixmap->damage_rect.x1)
@@ -889,12 +897,15 @@ _cogl_texture_pixmap_x11_free_glx_pixmap (CoglTexturePixmapX11 *tex_pixmap)
   if (tex_pixmap->glx_pixmap)
     {
       CoglXlibTrapState trap_state;
+      CoglRendererGLX *glx_renderer;
 
       _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+      glx_renderer = ctx->display->renderer->winsys;
 
       if (tex_pixmap->pixmap_bound)
-        glXReleaseTexImage (_cogl_xlib_get_display (), tex_pixmap->glx_pixmap,
-                            GLX_FRONT_LEFT_EXT);
+        glx_renderer->pf_glXReleaseTexImage (cogl_xlib_get_display (),
+                                             tex_pixmap->glx_pixmap,
+                                             GLX_FRONT_LEFT_EXT);
 
       /* FIXME - we need to trap errors and synchronize here because
        * of ordering issues between the XPixmap destruction and the
@@ -913,8 +924,8 @@ _cogl_texture_pixmap_x11_free_glx_pixmap (CoglTexturePixmapX11 *tex_pixmap)
        *   http://bugzilla.clutter-project.org/show_bug.cgi?id=2324
        */
       _cogl_xlib_trap_errors (&trap_state);
-      glXDestroyPixmap (_cogl_xlib_get_display (), tex_pixmap->glx_pixmap);
-      XSync (_cogl_xlib_get_display (), False);
+      glXDestroyPixmap (cogl_xlib_get_display (), tex_pixmap->glx_pixmap);
+      XSync (cogl_xlib_get_display (), False);
       _cogl_xlib_untrap_errors (&trap_state);
 
       tex_pixmap->glx_pixmap = None;
@@ -927,8 +938,10 @@ _cogl_texture_pixmap_x11_update_glx_texture (CoglTexturePixmapX11 *tex_pixmap,
                                              gboolean needs_mipmap)
 {
   gboolean ret = TRUE;
+  CoglRendererGLX *glx_renderer;
 
   _COGL_GET_CONTEXT (ctx, FALSE);
+  glx_renderer = ctx->display->renderer->winsys;
 
   /* If we don't have a GLX pixmap then fallback */
   if (tex_pixmap->glx_pixmap == None)
@@ -1031,14 +1044,14 @@ _cogl_texture_pixmap_x11_update_glx_texture (CoglTexturePixmapX11 *tex_pixmap,
           GE( _cogl_bind_gl_texture_transient (gl_target, gl_handle, FALSE) );
 
           if (tex_pixmap->pixmap_bound)
-            glXReleaseTexImage (_cogl_xlib_get_display (),
-                                tex_pixmap->glx_pixmap,
-                                GLX_FRONT_LEFT_EXT);
+            glx_renderer->pf_glXReleaseTexImage (cogl_xlib_get_display (),
+                                                 tex_pixmap->glx_pixmap,
+                                                 GLX_FRONT_LEFT_EXT);
 
-          glXBindTexImage (_cogl_xlib_get_display (),
-                           tex_pixmap->glx_pixmap,
-                           GLX_FRONT_LEFT_EXT,
-                           NULL);
+          glx_renderer->pf_glXBindTexImage (cogl_xlib_get_display (),
+                                            tex_pixmap->glx_pixmap,
+                                            GLX_FRONT_LEFT_EXT,
+                                            NULL);
 
           /* According to the recommended usage in the spec for
              GLX_EXT_texture_pixmap we should release the texture after
@@ -1373,7 +1386,7 @@ _cogl_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap)
 
   if (tex_pixmap->shm_info.shmid != -1)
     {
-      XShmDetach (_cogl_xlib_get_display (), &tex_pixmap->shm_info);
+      XShmDetach (cogl_xlib_get_display (), &tex_pixmap->shm_info);
       shmdt (tex_pixmap->shm_info.shmaddr);
       shmctl (tex_pixmap->shm_info.shmid, IPC_RMID, 0);
     }
diff --git a/clutter/cogl/cogl/winsys/cogl-winsys-glx-feature-functions.h b/clutter/cogl/cogl/winsys/cogl-winsys-glx-feature-functions.h
new file mode 100644
index 0000000..50df562
--- /dev/null
+++ b/clutter/cogl/cogl/winsys/cogl-winsys-glx-feature-functions.h
@@ -0,0 +1,105 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2010 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *
+ */
+
+/* This can be included multiple times with different definitions for
+ * the COGL_WINSYS_FEATURE_* functions.
+ */
+
+/* Macro prototypes:
+ * COGL_WINSYS_FEATURE_BEGIN (name, namespaces, extension_names,
+ *                            implied_public_feature_flags,
+ *                            implied_private_feature_flags,
+ *                            implied_winsys_feature)
+ * COGL_WINSYS_FEATURE_FUNCTION (return_type, function_name,
+ *                               (arguments))
+ * ...
+ * COGL_WINSYS_FEATURE_END ()
+ *
+ * Note: You can list multiple namespace and extension names if the
+ * corresponding _FEATURE_FUNCTIONS have the same semantics accross
+ * the different extension variants.
+ *
+ * XXX: NB: Don't add a trailing semicolon when using these macros
+ */
+
+COGL_WINSYS_FEATURE_BEGIN (texture_from_pixmap,
+                           "EXT\0",
+                           "texture_from_pixmap\0",
+                           0,
+                           0,
+                           COGL_WINSYS_FEATURE_TEXTURE_FROM_PIXMAP)
+COGL_WINSYS_FEATURE_FUNCTION (void, glXBindTexImage,
+                              (Display *display,
+                               GLXDrawable drawable,
+                               int buffer,
+                               int *attribList))
+COGL_WINSYS_FEATURE_FUNCTION (void, glXReleaseTexImage,
+                              (Display *display,
+                               GLXDrawable drawable,
+                               int buffer))
+COGL_WINSYS_FEATURE_END ()
+
+COGL_WINSYS_FEATURE_BEGIN (video_sync,
+                           "SGI\0",
+                           "video_sync\0",
+                           0,
+                           0,
+                           COGL_WINSYS_FEATURE_VBLANK_COUNTER)
+COGL_WINSYS_FEATURE_FUNCTION (int, glXGetVideoSync,
+                              (unsigned int *count))
+COGL_WINSYS_FEATURE_FUNCTION (int, glXWaitVideoSync,
+                              (int divisor,
+                               int remainder,
+                               unsigned int *count))
+COGL_WINSYS_FEATURE_END ()
+
+COGL_WINSYS_FEATURE_BEGIN (swap_control,
+                           "SGI\0",
+                           "swap_control\0",
+                           0,
+                           0,
+                           COGL_WINSYS_FEATURE_SWAP_THROTTLE)
+COGL_WINSYS_FEATURE_FUNCTION (int, glXSwapInterval,
+                              (int interval))
+COGL_WINSYS_FEATURE_END ()
+
+COGL_WINSYS_FEATURE_BEGIN (copy_sub_buffer,
+                           "MESA\0",
+                           "copy_sub_buffer\0",
+                           0,
+                           0,
+                           0)
+COGL_WINSYS_FEATURE_FUNCTION (void, glXCopySubBuffer,
+                              (Display *dpy,
+                               GLXDrawable drawable,
+                               int x, int y, int width, int height))
+COGL_WINSYS_FEATURE_END ()
+
+COGL_WINSYS_FEATURE_BEGIN (swap_event,
+                           "INTEL\0",
+                           "swap_event\0",
+                           0,
+                           0,
+                           COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT)
+COGL_WINSYS_FEATURE_END ()
diff --git a/clutter/cogl/cogl/winsys/cogl-winsys-glx.c b/clutter/cogl/cogl/winsys/cogl-winsys-glx.c
index c0f6d5c..2a81d3a 100644
--- a/clutter/cogl/cogl/winsys/cogl-winsys-glx.c
+++ b/clutter/cogl/cogl/winsys/cogl-winsys-glx.c
@@ -3,7 +3,7 @@
  *
  * An object oriented GL/GLES Abstraction/Utility Layer
  *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
+ * Copyright (C) 2007,2008,2009,2010,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
@@ -16,9 +16,12 @@
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  *
+ * Authors:
+ *   Robert Bragg <robert linux intel com>
  */
 
 #ifdef HAVE_CONFIG_H
@@ -27,19 +30,102 @@
 
 #include "cogl.h"
 
-#ifdef HAVE_CLUTTER_GLX
+#include "cogl-winsys-private.h"
+#include "cogl-feature-private.h"
+#include "cogl-context-private.h"
+#include "cogl-framebuffer.h"
+#include "cogl-swap-chain-private.h"
+#include "cogl-renderer-private.h"
+#include "cogl-renderer-glx-private.h"
+#include "cogl-onscreen-template-private.h"
+#include "cogl-display-xlib-private.h"
+#include "cogl-display-glx-private.h"
+#include "cogl-private.h"
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <glib/gi18n-lib.h>
+
 #include <dlfcn.h>
 #include <GL/glx.h>
+#include <X11/Xlib.h>
 
 typedef CoglFuncPtr (*GLXGetProcAddressProc) (const GLubyte *procName);
+
+#ifdef HAVE_DRM
+#include <drm.h>
+#include <sys/ioctl.h>
+#include <errno.h>
 #endif
 
+typedef struct _CoglContextGLX
+{
+  GLXDrawable current_drawable;
+} CoglContextGLX;
+
+typedef struct _CoglOnscreenXlib
+{
+  Window xwin;
+  gboolean is_foreign_xwin;
+} CoglOnscreenXlib;
+
+typedef struct _CoglOnscreenGLX
+{
+  CoglOnscreenXlib _parent;
+  GLXDrawable glxwin;
+  guint32 last_swap_vsync_counter;
+  GList *swap_callbacks;
+} CoglOnscreenGLX;
+
+typedef struct _CoglSwapBuffersNotifyEntry
+{
+  CoglSwapBuffersNotify callback;
+  void *user_data;
+  unsigned int id;
+} CoglSwapBuffersNotifyEntry;
+
+
+/* Define a set of arrays containing the functions required from GL
+   for each winsys feature */
+#define COGL_WINSYS_FEATURE_BEGIN(name, namespaces, extension_names,    \
+                                  feature_flags, feature_flags_private, \
+                                  winsys_feature)                       \
+  static const CoglFeatureFunction                                      \
+  cogl_glx_feature_ ## name ## _funcs[] = {
+#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args)                   \
+  { G_STRINGIFY (name), G_STRUCT_OFFSET (CoglRendererGLX, pf_ ## name) },
+#define COGL_WINSYS_FEATURE_END()               \
+  { NULL, 0 },                                  \
+    };
+#include "cogl-winsys-glx-feature-functions.h"
+
+/* Define an array of features */
+#undef COGL_WINSYS_FEATURE_BEGIN
+#define COGL_WINSYS_FEATURE_BEGIN(name, namespaces, extension_names,    \
+                                  feature_flags, feature_flags_private, \
+                                  winsys_feature)                       \
+  { 255, 255, namespaces, extension_names,                              \
+      feature_flags, feature_flags_private,                             \
+      winsys_feature, \
+      cogl_glx_feature_ ## name ## _funcs },
+#undef COGL_WINSYS_FEATURE_FUNCTION
+#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args)
+#undef COGL_WINSYS_FEATURE_END
+#define COGL_WINSYS_FEATURE_END()
+
+static const CoglFeatureData winsys_feature_data[] =
+  {
+#include "cogl-winsys-glx-feature-functions.h"
+  };
 
 CoglFuncPtr
 _cogl_winsys_get_proc_address (const char *name)
 {
   static GLXGetProcAddressProc get_proc_func = NULL;
-  static void                 *dlhand = NULL;
+  static void *dlhand = NULL;
 
   if (get_proc_func == NULL && dlhand == NULL)
     {
@@ -76,3 +162,1171 @@ _cogl_winsys_get_proc_address (const char *name)
   return NULL;
 }
 
+#undef COGL_WINSYS_FEATURE_BEGIN
+#define COGL_WINSYS_FEATURE_BEGIN(a, b, c, d, e, f)
+#undef COGL_WINSYS_FEATURE_FUNCTION
+#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args) \
+  glx_renderer->pf_ ## name = NULL;
+#undef COGL_WINSYS_FEATURE_END
+#define COGL_WINSYS_FEATURE_END()
+
+static void
+initialize_function_table (CoglRenderer *renderer)
+{
+  CoglRendererGLX *glx_renderer = renderer->winsys;
+
+#include "cogl-winsys-glx-feature-functions.h"
+}
+
+static CoglOnscreen *
+find_onscreen_for_xid (CoglContext *context, guint32 xid)
+{
+  GList *l;
+
+  for (l = context->framebuffers; l; l = l->next)
+    {
+      CoglFramebuffer *framebuffer = l->data;
+      CoglOnscreenXlib *xlib_onscreen;
+
+      if (!framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
+        continue;
+
+      /* Does the GLXEvent have the GLXDrawable or the X Window? */
+      xlib_onscreen = COGL_ONSCREEN (framebuffer)->winsys;
+      if (xlib_onscreen->xwin == (Window)xid)
+        return COGL_ONSCREEN (framebuffer);
+    }
+
+  return NULL;
+}
+
+static void
+notify_swap_buffers (CoglContext *context, GLXDrawable drawable)
+{
+  CoglOnscreen *onscreen = find_onscreen_for_xid (context, (guint32)drawable);
+  CoglOnscreenGLX *glx_onscreen;
+  GList *l;
+
+  if (!onscreen)
+    return;
+
+  glx_onscreen = onscreen->winsys;
+
+  for (l = glx_onscreen->swap_callbacks; l; l = l->next)
+    {
+      CoglSwapBuffersNotifyEntry *entry = l->data;
+      entry->callback (COGL_FRAMEBUFFER (onscreen), entry->user_data);
+    }
+}
+
+static CoglXlibFilterReturn
+glx_event_filter_cb (XEvent *xevent, void *data)
+{
+  CoglContext *context = data;
+  CoglRendererGLX *glx_renderer = context->display->renderer->winsys;
+
+  if (xevent->type == ConfigureNotify)
+    {
+      CoglOnscreen *onscreen =
+        find_onscreen_for_xid (context, xevent->xconfigure.window);
+
+      if (onscreen)
+        {
+          CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
+
+          _cogl_framebuffer_winsys_update_size (framebuffer,
+                                                xevent->xconfigure.width,
+                                                xevent->xconfigure.height);
+        }
+    }
+  else if (xevent->type ==
+           (glx_renderer->glx_event_base + GLX_BufferSwapComplete))
+    {
+      GLXBufferSwapComplete *swap_event = (GLXBufferSwapComplete *)xevent;
+      notify_swap_buffers (context, swap_event->drawable);
+      return COGL_XLIB_FILTER_REMOVE;
+    }
+
+  return COGL_XLIB_FILTER_CONTINUE;
+}
+
+gboolean
+_cogl_winsys_renderer_connect (CoglRenderer *renderer,
+                               GError **error)
+{
+  CoglRendererGLX *glx_renderer;
+  CoglRendererXlib *xlib_renderer;
+
+  renderer->winsys = g_slice_new0 (CoglRendererGLX);
+
+  glx_renderer = renderer->winsys;
+  xlib_renderer = renderer->winsys;
+
+  if (!_cogl_renderer_xlib_connect (renderer, error))
+    goto error;
+
+  if (!glXQueryExtension (xlib_renderer->xdpy,
+                          &glx_renderer->glx_error_base,
+                          &glx_renderer->glx_event_base))
+    {
+      g_set_error (error, COGL_WINSYS_ERROR,
+                   COGL_WINSYS_ERROR_INIT,
+                   "XServer appears to lack required GLX support");
+      goto error;
+    }
+
+  /* XXX: Note: For a long time Mesa exported a hybrid GLX, exporting
+   * extensions specified to require GLX 1.3, but still reporting 1.2
+   * via glXQueryVersion. */
+  if (!glXQueryVersion (xlib_renderer->xdpy,
+                        &glx_renderer->glx_major,
+                        &glx_renderer->glx_minor)
+      || !(glx_renderer->glx_major == 1 && glx_renderer->glx_minor >= 2))
+    {
+      g_set_error (error, COGL_WINSYS_ERROR,
+                   COGL_WINSYS_ERROR_INIT,
+                   "XServer appears to lack required GLX 1.2 support");
+      goto error;
+    }
+
+  glx_renderer->dri_fd = -1;
+
+  return TRUE;
+
+error:
+  _cogl_winsys_renderer_disconnect (renderer);
+  return FALSE;
+}
+
+void
+_cogl_winsys_renderer_disconnect (CoglRenderer *renderer)
+{
+  _cogl_renderer_xlib_disconnect (renderer);
+
+  g_slice_free (CoglRendererGLX, renderer->winsys);
+}
+
+void
+update_winsys_features (CoglContext *context)
+{
+  CoglDisplayGLX *glx_display = context->display->winsys;
+  CoglRendererXlib *xlib_renderer = context->display->renderer->winsys;
+  CoglRendererGLX *glx_renderer = context->display->renderer->winsys;
+  const char *glx_extensions;
+  int i;
+
+  g_return_if_fail (glx_display->glx_context);
+
+  _cogl_gl_update_features (context);
+
+  _cogl_bitmask_init (&context->winsys_features);
+
+  glx_extensions =
+    glXQueryExtensionsString (xlib_renderer->xdpy,
+                              DefaultScreen (xlib_renderer->xdpy));
+
+  COGL_NOTE (WINSYS, "  GLX Extensions: %s", glx_extensions);
+
+  context->feature_flags |= COGL_FEATURE_ONSCREEN_MULTIPLE;
+  _cogl_bitmask_set (&context->winsys_features,
+                     COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN,
+                     TRUE);
+
+  initialize_function_table (context->display->renderer);
+
+  for (i = 0; i < G_N_ELEMENTS (winsys_feature_data); i++)
+    if (_cogl_feature_check ("GLX", winsys_feature_data + i, 0, 0,
+                             glx_extensions,
+                             glx_renderer))
+      {
+        context->feature_flags |= winsys_feature_data[i].feature_flags;
+        if (winsys_feature_data[i].winsys_feature)
+          _cogl_bitmask_set (&context->winsys_features,
+                             winsys_feature_data[i].winsys_feature,
+                             TRUE);
+      }
+
+  /* Note: the GLX_SGI_video_sync spec explicitly states this extension
+   * only works for direct contexts. */
+  if (!glx_renderer->is_direct)
+    {
+      glx_renderer->pf_glXGetVideoSync = NULL;
+      glx_renderer->pf_glXWaitVideoSync = NULL;
+    }
+
+  if (glx_renderer->pf_glXWaitVideoSync)
+    _cogl_bitmask_set (&context->winsys_features,
+                       COGL_WINSYS_FEATURE_VBLANK_WAIT,
+                       TRUE);
+
+#ifdef HAVE_DRM
+  /* drm is really an extreme fallback -rumoured to work with Via
+   * chipsets... */
+  if (!glx_renderer->pf_glXWaitVideoSync)
+    {
+      if (glx_renderer->dri_fd < 0)
+        glx_renderer->dri_fd = open("/dev/dri/card0", O_RDWR);
+      if (glx_renderer->dri_fd >= 0)
+        _cogl_bitmask_set (&context->winsys_features,
+                           COGL_WINSYS_FEATURE_VBLANK_WAIT,
+                           TRUE);
+    }
+#endif
+
+  if (glx_renderer->pf_glXCopySubBuffer || context->drv.pf_glBlitFramebuffer)
+    _cogl_bitmask_set (&context->winsys_features,
+                       COGL_WINSYS_FEATURE_SWAP_REGION, TRUE);
+
+  /* Note: glXCopySubBuffer and glBlitFramebuffer won't be throttled
+   * by the SwapInterval so we have to throttle swap_region requests
+   * manually... */
+  if (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_REGION) &&
+      _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_WAIT))
+    _cogl_bitmask_set (&context->winsys_features,
+                       COGL_WINSYS_FEATURE_SWAP_REGION_THROTTLE, TRUE);
+}
+
+/* It seems the GLX spec never defined an invalid GLXFBConfig that
+ * we could overload as an indication of error, so we have to return
+ * an explicit boolean status. */
+static gboolean
+find_fbconfig (CoglDisplay *display,
+               gboolean with_alpha,
+               GLXFBConfig *config_ret,
+               GError **error)
+{
+  CoglRendererXlib *xlib_renderer = display->renderer->winsys;
+  GLXFBConfig *configs = NULL;
+  int n_configs, i;
+  static const int attributes[] = {
+    GLX_DRAWABLE_TYPE,    GLX_WINDOW_BIT,
+    GLX_RENDER_TYPE,      GLX_RGBA_BIT,
+    GLX_DOUBLEBUFFER,     GL_TRUE,
+    GLX_RED_SIZE,         1,
+    GLX_GREEN_SIZE,       1,
+    GLX_BLUE_SIZE,        1,
+    GLX_ALPHA_SIZE,       1,
+    GLX_DEPTH_SIZE,       1,
+    GLX_STENCIL_SIZE,     1,
+    None
+  };
+  gboolean ret = TRUE;
+  int xscreen_num = DefaultScreen (xlib_renderer->xdpy);
+
+  configs = glXChooseFBConfig (xlib_renderer->xdpy,
+                               xscreen_num,
+                               attributes,
+                               &n_configs);
+  if (!configs || n_configs == 0)
+    {
+      g_set_error (error, COGL_WINSYS_ERROR,
+                   COGL_WINSYS_ERROR_CREATE_CONTEXT,
+                   "Failed to find any compatible fbconfigs");
+      ret = FALSE;
+      goto done;
+    }
+
+  if (with_alpha)
+    {
+      for (i = 0; i < n_configs; i++)
+        {
+          XVisualInfo *vinfo;
+
+          vinfo = glXGetVisualFromFBConfig (xlib_renderer->xdpy, configs[i]);
+          if (vinfo == NULL)
+            continue;
+
+          if (vinfo->depth == 32 &&
+              (vinfo->red_mask | vinfo->green_mask | vinfo->blue_mask)
+              != 0xffffffff)
+            {
+              COGL_NOTE (WINSYS, "Found an ARGB FBConfig [index:%d]", i);
+              *config_ret = configs[i];
+              goto done;
+            }
+        }
+
+      /* If we make it here then we didn't find an RGBA config so
+         we'll fall back to using an RGB config */
+      g_set_error (error, COGL_WINSYS_ERROR,
+                   COGL_WINSYS_ERROR_CREATE_CONTEXT,
+                   "Unable to find fbconfig with rgba visual");
+      ret = FALSE;
+      goto done;
+    }
+  else
+    {
+      COGL_NOTE (WINSYS, "Using the first available FBConfig");
+      *config_ret = configs[0];
+    }
+
+done:
+  XFree (configs);
+  return ret;
+}
+
+static gboolean
+create_context (CoglDisplay *display, GError **error)
+{
+  CoglDisplayGLX *glx_display = display->winsys;
+  CoglDisplayXlib *xlib_display = display->winsys;
+  CoglRendererXlib *xlib_renderer = display->renderer->winsys;
+  CoglRendererGLX *glx_renderer = display->renderer->winsys;
+  gboolean support_transparent_windows;
+  GLXFBConfig config;
+  GError *fbconfig_error = NULL;
+  XSetWindowAttributes attrs;
+  XVisualInfo *xvisinfo;
+  GLXDrawable dummy_drawable;
+  CoglXlibTrapState old_state;
+
+  g_return_val_if_fail (glx_display->glx_context == NULL, TRUE);
+
+  if (display->onscreen_template &&
+      display->onscreen_template->swap_chain &&
+      display->onscreen_template->swap_chain->has_alpha)
+    support_transparent_windows = TRUE;
+  else
+    support_transparent_windows = FALSE;
+
+  glx_display->found_fbconfig =
+    find_fbconfig (display, support_transparent_windows, &config,
+                   &fbconfig_error);
+  if (!glx_display->found_fbconfig)
+    {
+      g_set_error (error, COGL_WINSYS_ERROR,
+                   COGL_WINSYS_ERROR_CREATE_CONTEXT,
+                   "Unable to find suitable fbconfig for the GLX context: %s",
+                   fbconfig_error->message);
+      g_error_free (fbconfig_error);
+      return FALSE;
+    }
+
+  glx_display->fbconfig = config;
+  glx_display->fbconfig_has_rgba_visual = support_transparent_windows;
+
+  COGL_NOTE (WINSYS, "Creating GLX Context (display: %p)",
+             xlib_renderer->xdpy);
+
+  glx_display->glx_context = glXCreateNewContext (xlib_renderer->xdpy,
+                                                  config,
+                                                  GLX_RGBA_TYPE,
+                                                  NULL,
+                                                  True);
+  if (glx_display->glx_context == NULL)
+    {
+      g_set_error (error, COGL_WINSYS_ERROR,
+                   COGL_WINSYS_ERROR_CREATE_CONTEXT,
+                   "Unable to create suitable GL context");
+      return FALSE;
+    }
+
+  glx_renderer->is_direct =
+    glXIsDirect (xlib_renderer->xdpy, glx_display->glx_context);
+
+  COGL_NOTE (WINSYS, "Setting %s context",
+             glx_renderer->is_direct ? "direct" : "indirect");
+
+  /* XXX: GLX doesn't let us make a context current without a window
+   * so we create a dummy window that we can use while no CoglOnscreen
+   * framebuffer is in use.
+   */
+
+  xvisinfo = glXGetVisualFromFBConfig (xlib_renderer->xdpy, config);
+  if (xvisinfo == NULL)
+    {
+      g_set_error (error, COGL_WINSYS_ERROR,
+                   COGL_WINSYS_ERROR_CREATE_CONTEXT,
+                   "Unable to retrieve the X11 visual");
+      return FALSE;
+    }
+
+  _cogl_renderer_xlib_trap_errors (display->renderer, &old_state);
+
+  attrs.override_redirect = True;
+  attrs.colormap = XCreateColormap (xlib_renderer->xdpy,
+                                    DefaultRootWindow (xlib_renderer->xdpy),
+                                    xvisinfo->visual,
+                                    AllocNone);
+  attrs.border_pixel = 0;
+
+  xlib_display->dummy_xwin =
+    XCreateWindow (xlib_renderer->xdpy,
+                   DefaultRootWindow (xlib_renderer->xdpy),
+                   -100, -100, 1, 1,
+                   0,
+                   xvisinfo->depth,
+                   CopyFromParent,
+                   xvisinfo->visual,
+                   CWOverrideRedirect | CWColormap | CWBorderPixel,
+                   &attrs);
+
+  /* Try and create a GLXWindow to use with extensions dependent on
+   * GLX versions >= 1.3 that don't accept regular X Windows as GLX
+   * drawables. */
+  if (glx_renderer->glx_major == 1 && glx_renderer->glx_minor >= 3)
+    {
+      glx_display->dummy_glxwin = glXCreateWindow (xlib_renderer->xdpy,
+                                                   config,
+                                                   xlib_display->dummy_xwin,
+                                                   NULL);
+    }
+
+  if (glx_display->dummy_glxwin)
+    dummy_drawable = glx_display->dummy_glxwin;
+  else
+    dummy_drawable = xlib_display->dummy_xwin;
+
+  COGL_NOTE (WINSYS, "Selecting dummy 0x%x for the GLX context",
+             (unsigned int) dummy_drawable);
+
+  glXMakeContextCurrent (xlib_renderer->xdpy,
+                         dummy_drawable,
+                         dummy_drawable,
+                         glx_display->glx_context);
+
+  XFree (xvisinfo);
+
+  if (_cogl_renderer_xlib_untrap_errors (display->renderer, &old_state))
+    {
+      g_set_error (error, COGL_WINSYS_ERROR,
+                   COGL_WINSYS_ERROR_CREATE_CONTEXT,
+                   "Unable to select the newly created GLX context");
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+gboolean
+_cogl_winsys_display_setup (CoglDisplay *display,
+                            GError **error)
+{
+  CoglDisplayGLX *glx_display;
+  CoglDisplayXlib *xlib_display;
+  int i;
+
+  g_return_val_if_fail (display->winsys == NULL, FALSE);
+
+  glx_display = g_slice_new0 (CoglDisplayGLX);
+  display->winsys = glx_display;
+
+  xlib_display = display->winsys;
+
+  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
+_cogl_winsys_display_destroy (CoglDisplay *display)
+{
+  CoglDisplayGLX *glx_display = display->winsys;
+  CoglDisplayXlib *xlib_display = display->winsys;
+  CoglRendererXlib *xlib_renderer = display->renderer->winsys;
+
+  g_return_if_fail (glx_display != NULL);
+
+  if (glx_display->glx_context)
+    {
+      glXMakeContextCurrent (xlib_renderer->xdpy, None, None, NULL);
+      glXDestroyContext (xlib_renderer->xdpy, glx_display->glx_context);
+      glx_display->glx_context = NULL;
+    }
+
+  if (glx_display->dummy_glxwin)
+    {
+      glXDestroyWindow (xlib_renderer->xdpy, glx_display->dummy_glxwin);
+      glx_display->dummy_glxwin = None;
+    }
+
+  if (xlib_display->dummy_xwin)
+    {
+      XDestroyWindow (xlib_renderer->xdpy, xlib_display->dummy_xwin);
+      xlib_display->dummy_xwin = None;
+    }
+
+  g_slice_free (CoglDisplayGLX, display->winsys);
+  display->winsys = NULL;
+}
+
+gboolean
+_cogl_winsys_context_init (CoglContext *context, GError **error)
+{
+  context->winsys = g_new0 (CoglContextGLX, 1);
+
+  cogl_renderer_xlib_add_filter (context->display->renderer,
+                                 glx_event_filter_cb,
+                                 context);
+  update_winsys_features (context);
+
+  return TRUE;
+}
+
+void
+_cogl_winsys_context_deinit (CoglContext *context)
+{
+  cogl_renderer_xlib_remove_filter (context->display->renderer,
+                                    glx_event_filter_cb,
+                                    context);
+  g_free (context->winsys);
+}
+
+gboolean
+_cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
+                            GError **error)
+{
+  CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
+  CoglContext *context = framebuffer->context;
+  CoglDisplay *display = context->display;
+  CoglDisplayGLX *glx_display = display->winsys;
+  CoglRendererXlib *xlib_renderer = display->renderer->winsys;
+  CoglRendererGLX *glx_renderer = display->renderer->winsys;
+  Window xwin;
+  CoglOnscreenXlib *xlib_onscreen;
+  CoglOnscreenGLX *glx_onscreen;
+
+  g_return_val_if_fail (glx_display->glx_context, FALSE);
+
+  /* FIXME: We need to explicitly Select for ConfigureNotify events.
+   * For foreign windows we need to be careful not to mess up any
+   * existing event mask.
+   * We need to document that for windows we create then toolkits
+   * must be careful not to clear event mask bits that we select.
+   */
+
+  /* XXX: Note we ignore the user's original width/height when
+   * given a foreign X window. */
+  if (onscreen->foreign_xid)
+    {
+      Status status;
+      CoglXlibTrapState state;
+      XWindowAttributes attr;
+      int xerror;
+
+      xwin = onscreen->foreign_xid;
+
+      _cogl_renderer_xlib_trap_errors (display->renderer, &state);
+
+      status = XGetWindowAttributes (xlib_renderer->xdpy, xwin, &attr);
+      XSync (xlib_renderer->xdpy, False);
+      xerror = _cogl_renderer_xlib_untrap_errors (display->renderer, &state);
+      if (status == 0 || xerror)
+        {
+          char message[1000];
+          XGetErrorText (xlib_renderer->xdpy, xerror, message, sizeof(message));
+          g_set_error (error, COGL_WINSYS_ERROR,
+                       COGL_WINSYS_ERROR_CREATE_ONSCREEN,
+                       "Unable to query geometry of foreign xid 0x%08lX: %s",
+                       xwin, message);
+          return FALSE;
+        }
+
+      _cogl_framebuffer_winsys_update_size (framebuffer,
+                                            attr.width, attr.height);
+    }
+  else
+    {
+      int width;
+      int height;
+      CoglXlibTrapState state;
+      XVisualInfo *xvisinfo;
+      XSetWindowAttributes xattr;
+      unsigned long mask;
+      int xerror;
+
+      width = _cogl_framebuffer_get_width (framebuffer);
+      height = _cogl_framebuffer_get_height (framebuffer);
+
+      _cogl_renderer_xlib_trap_errors (display->renderer, &state);
+
+      xvisinfo = glXGetVisualFromFBConfig (xlib_renderer->xdpy,
+                                           glx_display->fbconfig);
+      if (xvisinfo == NULL)
+        {
+          g_set_error (error, COGL_WINSYS_ERROR,
+                       COGL_WINSYS_ERROR_CREATE_ONSCREEN,
+                       "Unable to retrieve the X11 visual of context's "
+                       "fbconfig");
+          return FALSE;
+        }
+
+      /* window attributes */
+      xattr.background_pixel = WhitePixel (xlib_renderer->xdpy,
+                                           DefaultScreen (xlib_renderer->xdpy));
+      xattr.border_pixel = 0;
+      /* XXX: is this an X resource that we are leakingâ?½... */
+      xattr.colormap = XCreateColormap (xlib_renderer->xdpy,
+                                        DefaultRootWindow (xlib_renderer->xdpy),
+                                        xvisinfo->visual,
+                                        AllocNone);
+      mask = CWBorderPixel | CWColormap;
+
+      xwin = XCreateWindow (xlib_renderer->xdpy,
+                            DefaultRootWindow (xlib_renderer->xdpy),
+                            0, 0,
+                            width, height,
+                            0,
+                            xvisinfo->depth,
+                            InputOutput,
+                            xvisinfo->visual,
+                            mask, &xattr);
+
+      XFree (xvisinfo);
+
+      XSync (xlib_renderer->xdpy, False);
+      xerror = _cogl_renderer_xlib_untrap_errors (display->renderer, &state);
+      if (xerror)
+        {
+          char message[1000];
+          XGetErrorText (xlib_renderer->xdpy, xerror,
+                         message, sizeof (message));
+          g_set_error (error, COGL_WINSYS_ERROR,
+                       COGL_WINSYS_ERROR_CREATE_ONSCREEN,
+                       "X error while creating Window for CoglOnscreen: %s",
+                       message);
+          return FALSE;
+        }
+    }
+
+  onscreen->winsys = g_slice_new0 (CoglOnscreenGLX);
+  xlib_onscreen = onscreen->winsys;
+  glx_onscreen = onscreen->winsys;
+
+  xlib_onscreen->xwin = xwin;
+  xlib_onscreen->is_foreign_xwin = onscreen->foreign_xid ? TRUE : FALSE;
+
+  /* Try and create a GLXWindow to use with extensions dependent on
+   * GLX versions >= 1.3 that don't accept regular X Windows as GLX
+   * drawables. */
+  if (glx_renderer->glx_major == 1 && glx_renderer->glx_minor >= 3)
+    {
+      glx_onscreen->glxwin =
+        glXCreateWindow (xlib_renderer->xdpy,
+                         glx_display->fbconfig,
+                         xlib_onscreen->xwin,
+                         NULL);
+    }
+
+#ifdef GLX_INTEL_swap_event
+  if (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT))
+    {
+      GLXDrawable drawable =
+        glx_onscreen->glxwin ? glx_onscreen->glxwin : xlib_onscreen->xwin;
+
+      /* similarly to above, we unconditionally select this event
+       * because we rely on it to advance the master clock, and
+       * drive redraw/relayout, animations and event handling.
+       */
+      glXSelectEvent (xlib_renderer->xdpy,
+                      drawable,
+                      GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK);
+    }
+#endif /* GLX_INTEL_swap_event */
+
+  return TRUE;
+}
+
+void
+_cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
+{
+  CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
+  CoglContext *context = framebuffer->context;
+  CoglRendererXlib *xlib_renderer = context->display->renderer->winsys;
+  CoglXlibTrapState old_state;
+  CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
+  CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
+
+  _cogl_xlib_trap_errors (&old_state);
+
+  if (glx_onscreen->glxwin != None)
+    {
+      glXDestroyWindow (xlib_renderer->xdpy, glx_onscreen->glxwin);
+      glx_onscreen->glxwin = None;
+    }
+
+  if (!xlib_onscreen->is_foreign_xwin && xlib_onscreen->xwin != None)
+    {
+      XDestroyWindow (xlib_renderer->xdpy, xlib_onscreen->xwin);
+      xlib_onscreen->xwin = None;
+    }
+  else
+    xlib_onscreen->xwin = None;
+
+  XSync (xlib_renderer->xdpy, False);
+
+  _cogl_xlib_untrap_errors (&old_state);
+}
+
+void
+_cogl_winsys_onscreen_bind (CoglOnscreen *onscreen)
+{
+  CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
+  CoglContextGLX *glx_context = context->winsys;
+  CoglDisplayXlib *xlib_display = context->display->winsys;
+  CoglDisplayGLX *glx_display = context->display->winsys;
+  CoglRendererXlib *xlib_renderer = context->display->renderer->winsys;
+  CoglRendererGLX *glx_renderer = context->display->renderer->winsys;
+  CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
+  CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
+  CoglXlibTrapState old_state;
+  GLXDrawable drawable;
+
+  if (G_UNLIKELY (!onscreen))
+    {
+      drawable =
+        glx_display->dummy_glxwin ?
+        glx_display->dummy_glxwin : xlib_display->dummy_xwin;
+
+      if (glx_context->current_drawable == drawable)
+        return;
+
+      _cogl_xlib_trap_errors (&old_state);
+
+      glXMakeContextCurrent (xlib_renderer->xdpy,
+                             drawable, drawable,
+                             glx_display->glx_context);
+    }
+  else
+    {
+      drawable =
+        glx_onscreen->glxwin ? glx_onscreen->glxwin : xlib_onscreen->xwin;
+
+      if (glx_context->current_drawable == drawable)
+        return;
+
+      _cogl_xlib_trap_errors (&old_state);
+
+      COGL_NOTE (WINSYS,
+                 "MakeContextCurrent dpy: %p, window: 0x%x (%s), context: %p",
+                 xlib_renderer->xdpy,
+                 (unsigned int) drawable,
+                 xlib_onscreen->is_foreign_xwin ? "foreign" : "native",
+                 glx_display->glx_context);
+
+      glXMakeContextCurrent (xlib_renderer->xdpy,
+                             drawable,
+                             drawable,
+                             glx_display->glx_context);
+
+      /* In case we are using GLX_SGI_swap_control for vblank syncing
+       * we need call glXSwapIntervalSGI here to make sure that it
+       * affects the current drawable.
+       *
+       * Note: we explicitly set to 0 when we aren't using the swap
+       * interval to synchronize since some drivers have a default
+       * swap interval of 1. Sadly some drivers even ignore requests
+       * to disable the swap interval.
+       *
+       * NB: glXSwapIntervalSGI applies to the context not the
+       * drawable which is why we can't just do this once when the
+       * framebuffer is allocated.
+       *
+       * FIXME: We should check for GLX_EXT_swap_control which allows
+       * per framebuffer swap intervals. GLX_MESA_swap_control also
+       * allows per-framebuffer swap intervals but the semantics tend
+       * to be more muddled since Mesa drivers tend to expose both the
+       * MESA and SGI extensions which should technically be mutually
+       * exclusive.
+       */
+      if (glx_renderer->pf_glXSwapInterval)
+        {
+          if (onscreen->swap_throttled)
+            glx_renderer->pf_glXSwapInterval (1);
+          else
+            glx_renderer->pf_glXSwapInterval (0);
+        }
+    }
+
+  XSync (xlib_renderer->xdpy, False);
+
+  /* FIXME: We should be reporting a GError here
+   */
+  if (_cogl_xlib_untrap_errors (&old_state))
+    {
+      g_warning ("X Error received while making drawable 0x%08lX current",
+                 drawable);
+      return;
+    }
+
+  glx_context->current_drawable = drawable;
+}
+
+#ifdef HAVE_DRM
+static int
+drm_wait_vblank (int fd, drm_wait_vblank_t *vbl)
+{
+    int ret, rc;
+
+    do
+      {
+        ret = ioctl (fd, DRM_IOCTL_WAIT_VBLANK, vbl);
+        vbl->request.type &= ~_DRM_VBLANK_RELATIVE;
+        rc = errno;
+      }
+    while (ret && rc == EINTR);
+
+    return rc;
+}
+#endif /* HAVE_DRM */
+
+void
+_cogl_winsys_wait_for_vblank (void)
+{
+  CoglDisplayGLX *glx_display;
+  CoglRendererGLX *glx_renderer;
+
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+  glx_display = ctx->display->winsys;
+  glx_renderer = ctx->display->renderer->winsys;
+
+  if (glx_renderer->pf_glXGetVideoSync)
+    {
+      guint32 current_count;
+
+      glx_renderer->pf_glXGetVideoSync (&current_count);
+      glx_renderer->pf_glXWaitVideoSync (2,
+                                         (current_count + 1) % 2,
+                                         &current_count);
+    }
+#ifdef HAVE_DRM
+  else
+    {
+      drm_wait_vblank_t blank;
+
+      COGL_NOTE (WINSYS, "Waiting for vblank (drm)");
+      blank.request.type = _DRM_VBLANK_RELATIVE;
+      blank.request.sequence = 1;
+      blank.request.signal = 0;
+      drm_wait_vblank (glx_renderer->dri_fd, &blank);
+    }
+#endif /* HAVE_DRM */
+}
+
+void
+_cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
+                                   int *rectangles,
+                                   int n_rectangles)
+{
+  CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
+  CoglContext *context = framebuffer->context;
+  CoglRendererXlib *xlib_renderer = context->display->renderer->winsys;
+  CoglRendererGLX *glx_renderer = context->display->renderer->winsys;
+  CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
+  CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
+  GLXDrawable drawable =
+    glx_onscreen->glxwin ? glx_onscreen->glxwin : xlib_onscreen->xwin;
+  guint32 end_frame_vsync_counter;
+  gboolean have_counter;
+  gboolean can_wait;
+
+  _cogl_framebuffer_flush_state (framebuffer,
+                                 framebuffer,
+                                 COGL_FRAMEBUFFER_FLUSH_BIND_ONLY);
+
+  if (onscreen->swap_throttled)
+    {
+      have_counter =
+        _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_COUNTER);
+      can_wait = _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_WAIT);
+    }
+  else
+    {
+      have_counter = FALSE;
+      can_wait = FALSE;
+    }
+
+  /* We need to ensure that all the rendering is done, otherwise
+   * redraw operations that are slower than the framerate can
+   * queue up in the pipeline during a heavy animation, causing a
+   * larger and larger backlog of rendering visible as lag to the
+   * user.
+   *
+   * For an exaggerated example consider rendering at 60fps (so 16ms
+   * per frame) and you have a really slow frame that takes 160ms to
+   * render, even though painting the scene and issuing the commands
+   * to the GPU takes no time at all. If all we did was use the
+   * video_sync extension to throttle the painting done by the CPU
+   * then every 16ms we would have another frame queued up even though
+   * the GPU has only rendered one tenth of the current frame. By the
+   * time the GPU would get to the 2nd frame there would be 9 frames
+   * waiting to be rendered.
+   *
+   * The problem is that we don't currently have a good way to throttle
+   * the GPU, only the CPU so we have to resort to synchronizing the
+   * GPU with the CPU to throttle it.
+   *
+   * Note: since calling glFinish() and synchronizing the CPU with
+   * the GPU is far from ideal, we hope that this is only a short
+   * term solution.
+   * - One idea is to using sync objects to track render
+   *   completion so we can throttle the backlog (ideally with an
+   *   additional extension that lets us get notifications in our
+   *   mainloop instead of having to busy wait for the
+   *   completion.)
+   * - Another option is to support clipped redraws by reusing the
+   *   contents of old back buffers such that we can flip instead
+   *   of using a blit and then we can use GLX_INTEL_swap_events
+   *   to throttle. For this though we would still probably want an
+   *   additional extension so we can report the limited region of
+   *   the window damage to X/compositors.
+   */
+  glFinish ();
+
+  if (have_counter && can_wait)
+    {
+      end_frame_vsync_counter = _cogl_winsys_get_vsync_counter ();
+
+      /* If we have the GLX_SGI_video_sync extension then we can
+       * be a bit smarter about how we throttle blits by avoiding
+       * any waits if we can see that the video sync count has
+       * already progressed. */
+      if (glx_onscreen->last_swap_vsync_counter == end_frame_vsync_counter)
+        _cogl_winsys_wait_for_vblank ();
+    }
+  else if (can_wait)
+    _cogl_winsys_wait_for_vblank ();
+
+  if (glx_renderer->pf_glXCopySubBuffer)
+    {
+      Display *xdpy = xlib_renderer->xdpy;
+      int i;
+      for (i = 0; i < n_rectangles; i++)
+        {
+          int *rect = &rectangles[4 * i];
+          glx_renderer->pf_glXCopySubBuffer (xdpy, drawable,
+                                             rect[0], rect[1], rect[2], rect[3]);
+        }
+    }
+  else if (context->drv.pf_glBlitFramebuffer)
+    {
+      int i;
+      /* XXX: checkout how this state interacts with the code to use
+       * glBlitFramebuffer in Neil's texture atlasing branch */
+      glDrawBuffer (GL_FRONT);
+      for (i = 0; i < n_rectangles; i++)
+        {
+          int *rect = &rectangles[4 * i];
+          int x2 = rect[0] + rect[2];
+          int y2 = rect[1] + rect[3];
+          context->drv.pf_glBlitFramebuffer (rect[0], rect[1], x2, y2,
+                                             rect[0], rect[1], x2, y2,
+                                             GL_COLOR_BUFFER_BIT, GL_NEAREST);
+        }
+      glDrawBuffer (GL_BACK);
+    }
+
+  /* NB: unlike glXSwapBuffers, glXCopySubBuffer and
+   * glBlitFramebuffer don't issue an implicit glFlush() so we
+   * have to flush ourselves if we want the request to complete in
+   * a finite amount of time since otherwise the driver can batch
+   * the command indefinitely. */
+  glFlush ();
+
+  /* NB: It's important we save the counter we read before acting on
+   * the swap request since if we are mixing and matching different
+   * swap methods between frames we don't want to read the timer e.g.
+   * after calling glFinish() some times and not for others.
+   *
+   * In other words; this way we consistently save the time at the end
+   * of the applications frame such that the counter isn't muddled by
+   * the varying costs of different swap methods.
+   */
+  if (have_counter)
+    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
+_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
+{
+  CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
+  CoglContext *context = framebuffer->context;
+  CoglRendererXlib *xlib_renderer = context->display->renderer->winsys;
+  CoglRendererGLX *glx_renderer = context->display->renderer->winsys;
+  CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
+  CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
+  gboolean have_counter;
+  GLXDrawable drawable;
+
+  /* XXX: theoretically this shouldn't be necessary but at least with
+   * the Intel drivers we have see that if we don't call
+   * glXMakeContextCurrent for the drawable we are swapping then
+   * we get a BadDrawable error from the X server. */
+  _cogl_framebuffer_flush_state (framebuffer,
+                                 framebuffer,
+                                 COGL_FRAMEBUFFER_FLUSH_BIND_ONLY);
+
+  drawable = glx_onscreen->glxwin ? glx_onscreen->glxwin : xlib_onscreen->xwin;
+
+  if (onscreen->swap_throttled)
+    {
+      guint32 end_frame_vsync_counter;
+
+      have_counter =
+        _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_COUNTER);
+
+      /* If the swap_region API is also being used then we need to track
+       * the vsync counter for each swap request so we can manually
+       * throttle swap_region requests. */
+      if (have_counter)
+        end_frame_vsync_counter = _cogl_winsys_get_vsync_counter ();
+
+      if (!glx_renderer->pf_glXSwapInterval)
+        {
+          gboolean can_wait =
+            _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_WAIT);
+
+          /* If we are going to wait for VBLANK manually, we not only
+           * need to flush out pending drawing to the GPU before we
+           * sleep, we need to wait for it to finish. Otherwise, we
+           * may end up with the situation:
+           *
+           *        - We finish drawing      - GPU drawing continues
+           *        - We go to sleep         - GPU drawing continues
+           * VBLANK - We call glXSwapBuffers - GPU drawing continues
+           *                                 - GPU drawing continues
+           *                                 - Swap buffers happens
+           *
+           * Producing a tear. Calling glFinish() first will cause us
+           * to properly wait for the next VBLANK before we swap. This
+           * obviously does not happen when we use _GLX_SWAP and let
+           * the driver do the right thing
+           */
+          glFinish ();
+
+          if (have_counter && can_wait)
+            {
+              if (glx_onscreen->last_swap_vsync_counter ==
+                  end_frame_vsync_counter)
+                _cogl_winsys_wait_for_vblank ();
+            }
+          else if (can_wait)
+            _cogl_winsys_wait_for_vblank ();
+        }
+    }
+  else
+    have_counter = FALSE;
+
+  glXSwapBuffers (xlib_renderer->xdpy, drawable);
+
+  if (have_counter)
+    glx_onscreen->last_swap_vsync_counter = _cogl_winsys_get_vsync_counter ();
+}
+
+guint32
+_cogl_winsys_onscreen_x11_get_window_xid (CoglOnscreen *onscreen)
+{
+  CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
+  return xlib_onscreen->xwin;
+}
+
+unsigned int
+_cogl_winsys_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen,
+                                                 CoglSwapBuffersNotify callback,
+                                                 void *user_data)
+{
+  CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
+  CoglSwapBuffersNotifyEntry *entry = g_slice_new0 (CoglSwapBuffersNotifyEntry);
+  static int next_swap_buffers_callback_id = 0;
+
+  entry->callback = callback;
+  entry->user_data = user_data;
+  entry->id = next_swap_buffers_callback_id++;
+
+  glx_onscreen->swap_callbacks =
+    g_list_prepend (glx_onscreen->swap_callbacks, entry);
+
+  return entry->id;
+}
+
+void
+_cogl_winsys_onscreen_remove_swap_buffers_callback (CoglOnscreen *onscreen,
+                                                    unsigned int id)
+{
+  CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
+  GList *l;
+
+  for (l = glx_onscreen->swap_callbacks; l; l = l->next)
+    {
+      CoglSwapBuffersNotifyEntry *entry = l->data;
+      if (entry->id == id)
+        {
+          g_slice_free (CoglSwapBuffersNotifyEntry, entry);
+          glx_onscreen->swap_callbacks =
+            g_list_delete_link (glx_onscreen->swap_callbacks, l);
+          return;
+        }
+    }
+}
+
+void
+_cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen)
+{
+  CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
+  CoglContextGLX *glx_context = context->winsys;
+  CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
+  CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
+  GLXDrawable drawable =
+    glx_onscreen->glxwin ? glx_onscreen->glxwin : xlib_onscreen->xwin;
+
+  if (glx_context->current_drawable != drawable)
+    return;
+
+  glx_context->current_drawable = 0;
+  _cogl_winsys_onscreen_bind (onscreen);
+}
+
+/* FIXME: we should distinguish renderer and context features */
+gboolean
+_cogl_winsys_has_feature (CoglWinsysFeature feature)
+{
+  _COGL_GET_CONTEXT (ctx, FALSE);
+
+  return _cogl_bitmask_get (&ctx->winsys_features, feature);
+}
+
+/* XXX: This is a particularly hacky _cogl_winsys interface... */
+XVisualInfo *
+_cogl_winsys_xlib_get_visual_info (void)
+{
+  CoglDisplayXlib *xlib_display;
+  CoglDisplayGLX *glx_display;
+  CoglRendererXlib *xlib_renderer;
+
+  _COGL_GET_CONTEXT (ctx, NULL);
+
+  g_return_val_if_fail (ctx->display->winsys, FALSE);
+
+  xlib_display = ctx->display->winsys;
+  glx_display = ctx->display->winsys;
+  xlib_renderer = ctx->display->renderer->winsys;
+
+  if (!glx_display->found_fbconfig)
+    return NULL;
+
+  return glXGetVisualFromFBConfig (xlib_renderer->xdpy, glx_display->fbconfig);
+}
diff --git a/clutter/cogl/cogl/winsys/cogl-winsys-private.h b/clutter/cogl/cogl/winsys/cogl-winsys-private.h
index 4cf326e..8d56bea 100644
--- a/clutter/cogl/cogl/winsys/cogl-winsys-private.h
+++ b/clutter/cogl/cogl/winsys/cogl-winsys-private.h
@@ -24,7 +24,95 @@
 #ifndef __COGL_WINSYS_PRIVATE_H
 #define __COGL_WINSYS_PRIVATE_H
 
+#include "cogl-framebuffer-private.h"
+
+#ifdef COGL_HAS_XLIB_SUPPORT
+#include <X11/Xutil.h>
+#endif
+
+GQuark
+_cogl_winsys_error_quark (void);
+
+#define COGL_WINSYS_ERROR (_cogl_winsys_error_quark ())
+
+typedef enum { /*< prefix=COGL_WINSYS_ERROR >*/
+  COGL_WINSYS_ERROR_INIT,
+  COGL_WINSYS_ERROR_CREATE_CONTEXT,
+  COGL_WINSYS_ERROR_CREATE_ONSCREEN,
+} CoglWinsysError;
+
+typedef enum
+{
+  COGL_WINSYS_RECTANGLE_STATE_UNKNOWN,
+  COGL_WINSYS_RECTANGLE_STATE_DISABLE,
+  COGL_WINSYS_RECTANGLE_STATE_ENABLE
+} CoglWinsysRectangleState;
+
 CoglFuncPtr
 _cogl_winsys_get_proc_address (const char *name);
 
+gboolean
+_cogl_winsys_renderer_connect (CoglRenderer *renderer,
+                               GError **error);
+
+void
+_cogl_winsys_renderer_disconnect (CoglRenderer *renderer);
+
+gboolean
+_cogl_winsys_display_setup (CoglDisplay *display,
+                            GError **error);
+
+void
+_cogl_winsys_display_destroy (CoglDisplay *display);
+
+gboolean
+_cogl_winsys_context_init (CoglContext *context, GError **error);
+
+void
+_cogl_winsys_context_deinit (CoglContext *context);
+
+gboolean
+_cogl_winsys_has_feature (CoglWinsysFeature feature);
+
+#ifdef COGL_HAS_XLIB_SUPPORT
+XVisualInfo *
+_cogl_winsys_xlib_get_visual_info (void);
+#endif
+
+gboolean
+_cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
+                            GError **error);
+
+void
+_cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen);
+
+void
+_cogl_winsys_onscreen_bind (CoglOnscreen *onscreen);
+
+void
+_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen);
+
+void
+_cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
+                                   int *rectangles,
+                                   int n_rectangles);
+
+void
+_cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen);
+
+guint32
+_cogl_winsys_onscreen_x11_get_window_xid (CoglOnscreen *onscreen);
+
+guint32
+_cogl_winsys_get_vsync_counter (void);
+
+unsigned int
+_cogl_winsys_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen,
+                                                 CoglSwapBuffersNotify callback,
+                                                 void *user_data);
+
+void
+_cogl_winsys_onscreen_remove_swap_buffers_callback (CoglOnscreen *onscreen,
+                                                    unsigned int id);
+
 #endif /* __COGL_WINSYS_PRIVATE_H */
diff --git a/clutter/cogl/cogl/winsys/cogl-winsys-stub.c b/clutter/cogl/cogl/winsys/cogl-winsys-stub.c
new file mode 100644
index 0000000..6648150
--- /dev/null
+++ b/clutter/cogl/cogl/winsys/cogl-winsys-stub.c
@@ -0,0 +1,114 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2010 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "cogl-framebuffer-private.h"
+
+/* This provides a stub winsys implementation for when Clutter still handles
+ * creating an OpenGL context. This is useful so we don't have to guard all
+ * calls into the winsys layer with #ifdef COGL_HAS_FULL_WINSYS
+ */
+
+
+void
+_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
+{
+
+}
+
+void
+_cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
+                                   int *rectangles,
+                                   int n_rectangles)
+{
+
+}
+
+void
+_cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen)
+{
+
+}
+
+unsigned int
+_cogl_winsys_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen,
+                                                 CoglSwapBuffersNotify callback,
+                                                 void *user_data)
+{
+  g_assert (0);
+  return 0;
+}
+
+void
+_cogl_winsys_onscreen_remove_swap_buffers_callback (CoglOnscreen *onscreen,
+                                                    unsigned int id)
+{
+  g_assert (0);
+}
+
+#ifdef COGL_HAS_XLIB_SUPPORT
+XVisualInfo *
+_cogl_winsys_xlib_get_visual_info (void)
+{
+  g_assert (0);
+  return NULL;
+}
+#endif
+
+gboolean
+_cogl_winsys_has_feature (CoglWinsysFeature feature)
+{
+  g_assert (0);
+  return FALSE;
+}
+
+#ifdef COGL_HAS_X11_SUPPORT
+guint32
+_cogl_winsys_onscreen_x11_get_window_xid (CoglOnscreen *onscreen)
+{
+  g_assert (0);
+  return 0;
+}
+#endif
+
+gboolean
+_cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
+                            GError **error)
+{
+  return TRUE;
+}
+
+void
+_cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
+{
+
+}
+
+void
+_cogl_winsys_context_deinit (CoglContext *context)
+{
+
+}
diff --git a/clutter/cogl/cogl/winsys/cogl-winsys.c b/clutter/cogl/cogl/winsys/cogl-winsys.c
new file mode 100644
index 0000000..e59063a
--- /dev/null
+++ b/clutter/cogl/cogl/winsys/cogl-winsys.c
@@ -0,0 +1,36 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "cogl.h"
+
+GQuark
+_cogl_winsys_error_quark (void)
+{
+  return g_quark_from_static_string ("cogl-winsys-error-quark");
+}
+
diff --git a/clutter/glx/clutter-backend-glx.c b/clutter/glx/clutter-backend-glx.c
index 684ad29..38c90ba 100644
--- a/clutter/glx/clutter-backend-glx.c
+++ b/clutter/glx/clutter-backend-glx.c
@@ -49,6 +49,7 @@
 #include "clutter-stage-private.h"
 
 #include "cogl/cogl.h"
+#include "cogl/cogl-internal.h"
 
 #define clutter_backend_glx_get_type    _clutter_backend_glx_get_type
 
@@ -57,12 +58,15 @@ G_DEFINE_TYPE (ClutterBackendGLX, clutter_backend_glx, CLUTTER_TYPE_BACKEND_X11)
 /* singleton object */
 static ClutterBackendGLX *backend_singleton = NULL;
 
-static gchar    *clutter_vblank_name = NULL;
+static gchar *clutter_vblank = NULL;
 
 G_CONST_RETURN gchar*
-_clutter_backend_glx_get_vblank_method (void)
+_clutter_backend_glx_get_vblank (void)
 {
-  return clutter_vblank_name;
+  if (clutter_vblank && strcmp (clutter_vblank, "0") == 0)
+    return "none";
+  else
+    return clutter_vblank;
 }
 
 static gboolean
@@ -76,7 +80,7 @@ clutter_backend_glx_pre_parse (ClutterBackend  *backend,
   env_string = g_getenv ("CLUTTER_VBLANK");
   if (env_string)
     {
-      clutter_vblank_name = g_strdup (env_string);
+      clutter_vblank = g_strdup (env_string);
       env_string = NULL;
     }
 
@@ -87,42 +91,12 @@ static gboolean
 clutter_backend_glx_post_parse (ClutterBackend  *backend,
                                 GError         **error)
 {
-  ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
-  ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
   ClutterBackendClass *parent_class =
     CLUTTER_BACKEND_CLASS (clutter_backend_glx_parent_class);
-  int glx_major, glx_minor;
 
   if (!parent_class->post_parse (backend, error))
     return FALSE;
 
-  if (!glXQueryExtension (backend_x11->xdpy,
-                          &backend_glx->error_base,
-                          &backend_glx->event_base))
-    {
-      g_set_error_literal (error, CLUTTER_INIT_ERROR,
-                           CLUTTER_INIT_ERROR_BACKEND,
-                           "XServer appears to lack the required GLX support");
-
-      return FALSE;
-    }
-
-  /* XXX: Technically we should require >= GLX 1.3 support but for a long
-   * time Mesa has exported a hybrid GLX, exporting extensions specified
-   * to require GLX 1.3, but still reporting 1.2 via glXQueryVersion. */
-  glx_major = 1;
-  glx_minor = 2;
-  if (!glXQueryVersion (backend_x11->xdpy, &glx_major, &glx_minor) ||
-      !(glx_major == 1 && glx_minor >= 2))
-    {
-      g_set_error (error, CLUTTER_INIT_ERROR,
-                   CLUTTER_INIT_ERROR_BACKEND,
-                   "XServer appears to lack the required GLX "
-                   "1.2 support (%d.%d reported)",
-                   glx_major, glx_minor);
-      return FALSE;
-    }
-
   return TRUE;
 }
 
@@ -130,8 +104,9 @@ static const GOptionEntry entries[] =
 {
   { "vblank", 0,
     0,
-    G_OPTION_ARG_STRING, &clutter_vblank_name,
-    N_("VBlank method to be used (none, dri or glx)"), "METHOD"
+    G_OPTION_ARG_STRING, &clutter_vblank,
+    N_("Set to 'none' or '0' to disable throttling "
+       "framerate to vblank"), "OPTION"
   },
   { NULL }
 };
@@ -160,32 +135,20 @@ clutter_backend_glx_finalize (GObject *gobject)
 static void
 clutter_backend_glx_dispose (GObject *gobject)
 {
-  ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (gobject);
-  ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (gobject);
+  ClutterBackend *backend = CLUTTER_BACKEND (gobject);
 
   /* Unrealize all shaders, since the GL context is going away */
+  /* XXX: Why isn't this done in
+   * clutter-backend.c:clutter_backend_dispose ?
+   */
   _clutter_shader_release_all ();
 
-  if (backend_glx->gl_context)
-    {
-      glXMakeContextCurrent (backend_x11->xdpy, None, None, NULL);
-      glXDestroyContext (backend_x11->xdpy, backend_glx->gl_context);
-      backend_glx->gl_context = NULL;
-    }
-
-  if (backend_glx->dummy_glxwin)
-    {
-      glXDestroyWindow (backend_x11->xdpy, backend_glx->dummy_glxwin);
-      backend_glx->dummy_glxwin = None;
-    }
-
-  if (backend_glx->dummy_xwin)
-    {
-      XDestroyWindow (backend_x11->xdpy, backend_glx->dummy_xwin);
-      backend_glx->dummy_xwin = None;
-    }
-
+  /* We chain up before disposing our CoglContext so that we will
+   * destroy all of the stages first. Otherwise the actors may try to
+   * make Cogl calls during destruction which would cause a crash */
   G_OBJECT_CLASS (clutter_backend_glx_parent_class)->dispose (gobject);
+
+  cogl_object_unref (backend->cogl_context);
 }
 
 static GObject *
@@ -212,197 +175,46 @@ clutter_backend_glx_constructor (GType                  gtype,
   return g_object_ref (backend_singleton);
 }
 
-static gboolean
-check_vblank_env (const char *name)
-{
-  if (clutter_vblank_name && !g_ascii_strcasecmp (clutter_vblank_name, name))
-    return TRUE;
-
-  return FALSE;
-}
-
 static ClutterFeatureFlags
 clutter_backend_glx_get_features (ClutterBackend *backend)
 {
   ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
   ClutterBackendClass *parent_class;
-  const gchar *glx_extensions = NULL;
-  const gchar *gl_extensions = NULL;
   ClutterFeatureFlags flags;
-  gboolean use_dri = FALSE;
 
   parent_class = CLUTTER_BACKEND_CLASS (clutter_backend_glx_parent_class);
 
   flags = parent_class->get_features (backend);
-  flags |= CLUTTER_FEATURE_STAGE_MULTIPLE;
-
-  /* this will make sure that the GL context exists */
-  g_assert (backend_glx->gl_context != NULL);
-  g_assert (glXGetCurrentDrawable () != None);
 
-  CLUTTER_NOTE (BACKEND,
-                "Checking features\n"
-                "  GL_VENDOR: %s\n"
-                "  GL_RENDERER: %s\n"
-                "  GL_VERSION: %s\n"
-                "  GL_EXTENSIONS: %s",
-                glGetString (GL_VENDOR),
-                glGetString (GL_RENDERER),
-                glGetString (GL_VERSION),
-                glGetString (GL_EXTENSIONS));
-
-  glx_extensions =
-    glXQueryExtensionsString (clutter_x11_get_default_display (),
-                              clutter_x11_get_default_screen ());
-
-  CLUTTER_NOTE (BACKEND, "  GLX Extensions: %s", glx_extensions);
-
-  gl_extensions = (const gchar *)glGetString (GL_EXTENSIONS);
-
-  /* When using glBlitFramebuffer or glXCopySubBufferMESA for sub stage
-   * redraws, we cannot rely on glXSwapIntervalSGI to throttle the blits
-   * so we need to resort to manually synchronizing with the vblank so we
-   * always check for the video_sync extension...
-   */
-  if (_cogl_check_extension ("GLX_SGI_video_sync", glx_extensions) &&
-      /* Note: the GLX_SGI_video_sync spec explicitly states this extension
-       * only works for direct contexts. */
-      glXIsDirect (clutter_x11_get_default_display (),
-                   backend_glx->gl_context))
+  if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN))
     {
-      backend_glx->get_video_sync =
-        (GetVideoSyncProc) cogl_get_proc_address ("glXGetVideoSyncSGI");
-
-      backend_glx->wait_video_sync =
-        (WaitVideoSyncProc) cogl_get_proc_address ("glXWaitVideoSyncSGI");
+      CLUTTER_NOTE (BACKEND, "Cogl supports multiple onscreen framebuffers");
+      flags |= CLUTTER_FEATURE_STAGE_MULTIPLE;
     }
-
-  use_dri = check_vblank_env ("dri");
-
-  /* First check for explicit disabling or it set elsewhere (eg NVIDIA) */
-  if (check_vblank_env ("none"))
+  else
     {
-      CLUTTER_NOTE (BACKEND, "vblank sync: disabled at user request");
-      goto vblank_setup_done;
+      CLUTTER_NOTE (BACKEND, "Cogl only supports one onscreen framebuffer");
+      flags |= CLUTTER_FEATURE_STAGE_STATIC;
     }
 
-  if (g_getenv ("__GL_SYNC_TO_VBLANK") != NULL)
+  if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_THROTTLE))
     {
-      backend_glx->vblank_type = CLUTTER_VBLANK_GLX_SWAP;
+      CLUTTER_NOTE (BACKEND, "Cogl supports swap buffers throttling");
       flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;
-
-      CLUTTER_NOTE (BACKEND, "Using __GL_SYNC_TO_VBLANK hint");
-      goto vblank_setup_done;
-    }
-
-  /* We try two GL vblank syncing mechanisms.
-   * glXSwapIntervalSGI is tried first, then glXGetVideoSyncSGI.
-   *
-   * glXSwapIntervalSGI is known to work with Mesa and in particular
-   * the Intel drivers. glXGetVideoSyncSGI has serious problems with
-   * Intel drivers causing terrible frame rate so it only tried as a
-   * fallback.
-   *
-   * How well glXGetVideoSyncSGI works with other driver (ATI etc) needs
-   * to be investigated. glXGetVideoSyncSGI on ATI at least seems to have
-   * no effect.
-   */
-  if (!use_dri &&
-      _cogl_check_extension ("GLX_SGI_swap_control", glx_extensions))
-    {
-      backend_glx->swap_interval =
-        (SwapIntervalProc) cogl_get_proc_address ("glXSwapIntervalSGI");
-
-      CLUTTER_NOTE (BACKEND, "attempting glXSwapIntervalSGI vblank setup");
-
-      if (backend_glx->swap_interval != NULL &&
-          backend_glx->swap_interval (1) == 0)
-        {
-          backend_glx->vblank_type = CLUTTER_VBLANK_GLX_SWAP;
-          flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;
-
-          CLUTTER_NOTE (BACKEND, "glXSwapIntervalSGI setup success");
-
-#ifdef GLX_INTEL_swap_event
-          /* GLX_INTEL_swap_event allows us to avoid blocking the CPU
-           * while we wait for glXSwapBuffers to complete, and instead
-           * we get an X event notifying us of completion...
-           */
-          if (!(clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_SWAP_EVENTS) &&
-              _cogl_check_extension ("GLX_INTEL_swap_event", glx_extensions))
-            {
-              flags |= CLUTTER_FEATURE_SWAP_EVENTS;
-            }
-#endif /* GLX_INTEL_swap_event */
-
-          goto vblank_setup_done;
-        }
-
-      CLUTTER_NOTE (BACKEND, "glXSwapIntervalSGI vblank setup failed");
-    }
-
-  if (!use_dri &&
-      !(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK) &&
-      _cogl_check_extension ("GLX_SGI_video_sync", glx_extensions))
-    {
-      CLUTTER_NOTE (BACKEND, "attempting glXGetVideoSyncSGI vblank setup");
-
-      if ((backend_glx->get_video_sync != NULL) &&
-          (backend_glx->wait_video_sync != NULL))
-        {
-          CLUTTER_NOTE (BACKEND, "glXGetVideoSyncSGI vblank setup success");
-
-          backend_glx->vblank_type = CLUTTER_VBLANK_GLX;
-          flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;
-
-          goto vblank_setup_done;
-        }
-
-      CLUTTER_NOTE (BACKEND, "glXGetVideoSyncSGI vblank setup failed");
     }
+  else
+    CLUTTER_NOTE (BACKEND, "Cogl doesn't support swap buffers throttling");
 
-#ifdef __linux__
-  /*
-   * DRI is really an extreme fallback -rumoured to work with Via chipsets
-   */
-  if (!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK))
+  if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT))
     {
-      CLUTTER_NOTE (BACKEND, "attempting DRI vblank setup");
-
-      backend_glx->dri_fd = open("/dev/dri/card0", O_RDWR);
-      if (backend_glx->dri_fd >= 0)
-        {
-          CLUTTER_NOTE (BACKEND, "DRI vblank setup success");
-
-          backend_glx->vblank_type = CLUTTER_VBLANK_DRI;
-          flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;
-
-          goto vblank_setup_done;
-        }
-
-      CLUTTER_NOTE (BACKEND, "DRI vblank setup failed");
+      CLUTTER_NOTE (BACKEND, "Cogl supports swap buffers complete events");
+      flags |= CLUTTER_FEATURE_SWAP_EVENTS;
     }
-#endif /* __linux__ */
-
-  CLUTTER_NOTE (BACKEND, "no use-able vblank mechanism found");
 
-vblank_setup_done:
-
-  if (_cogl_check_extension ("GLX_MESA_copy_sub_buffer", glx_extensions))
+  if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_REGION))
     {
-      backend_glx->copy_sub_buffer =
-        (CopySubBufferProc) cogl_get_proc_address ("glXCopySubBufferMESA");
+      CLUTTER_NOTE (BACKEND, "Cogl supports swapping buffer regions");
       backend_glx->can_blit_sub_buffer = TRUE;
-      backend_glx->blit_sub_buffer_is_synchronized = TRUE;
-    }
-  else if (_cogl_check_extension ("GL_EXT_framebuffer_blit", gl_extensions))
-    {
-      CLUTTER_NOTE (BACKEND,
-                    "Using glBlitFramebuffer fallback for sub_buffer copies");
-      backend_glx->blit_framebuffer =
-        (BlitFramebufferProc) cogl_get_proc_address ("glBlitFramebuffer");
-      backend_glx->can_blit_sub_buffer = TRUE;
-      backend_glx->blit_sub_buffer_is_synchronized = FALSE;
     }
 
   CLUTTER_NOTE (BACKEND, "backend features checked");
@@ -410,375 +222,77 @@ vblank_setup_done:
   return flags;
 }
 
-/* It seems the GLX spec never defined an invalid GLXFBConfig that
- * we could overload as an indication of error, so we have to return
- * an explicit boolean status. */
-gboolean
-_clutter_backend_glx_get_fbconfig (ClutterBackendGLX *backend_glx,
-                                   GLXFBConfig       *config)
-{
-  ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend_glx);
-  GLXFBConfig *configs = NULL;
-  gboolean use_argb = clutter_x11_get_use_argb_visual ();
-  int n_configs, i;
-  static const int attributes[] = {
-    GLX_DRAWABLE_TYPE,    GLX_WINDOW_BIT,
-    GLX_RENDER_TYPE,      GLX_RGBA_BIT,
-    GLX_DOUBLEBUFFER,     GL_TRUE,
-    GLX_RED_SIZE,         1,
-    GLX_GREEN_SIZE,       1,
-    GLX_BLUE_SIZE,        1,
-    GLX_ALPHA_SIZE,       1,
-    GLX_DEPTH_SIZE,       1,
-    GLX_STENCIL_SIZE,     1,
-    None
-  };
-
-  if (backend_x11->xdpy == NULL || backend_x11->xscreen == NULL)
-    return FALSE;
-
-  /* If we don't already have a cached config then try to get one */
-  if (!backend_glx->found_fbconfig)
-    {
-      CLUTTER_NOTE (BACKEND,
-                    "Retrieving GL fbconfig, dpy: %p, xscreen; %p (%d)",
-                    backend_x11->xdpy,
-                    backend_x11->xscreen,
-                    backend_x11->xscreen_num);
-
-      configs = glXChooseFBConfig (backend_x11->xdpy,
-                                   backend_x11->xscreen_num,
-                                   attributes,
-                                   &n_configs);
-      if (configs)
-        {
-          if (use_argb)
-            {
-              for (i = 0; i < n_configs; i++)
-                {
-                  XVisualInfo *vinfo;
-
-                  vinfo = glXGetVisualFromFBConfig (backend_x11->xdpy,
-                                                    configs[i]);
-                  if (vinfo == NULL)
-                    continue;
-
-                  if (vinfo->depth == 32 &&
-                      (vinfo->red_mask   == 0xff0000 &&
-                       vinfo->green_mask == 0x00ff00 &&
-                       vinfo->blue_mask  == 0x0000ff))
-                    {
-                      CLUTTER_NOTE (BACKEND,
-                                    "Found an ARGB FBConfig [index:%d]",
-                                    i);
-
-                      backend_glx->found_fbconfig = TRUE;
-                      backend_glx->fbconfig = configs[i];
-
-                      goto out;
-                    }
-                }
-
-              /* If we make it here then we didn't find an RGBA config so
-                 we'll fall back to using an RGB config */
-              CLUTTER_NOTE (BACKEND, "ARGB visual requested, but none found");
-            }
-
-          if (n_configs >= 1)
-            {
-              CLUTTER_NOTE (BACKEND, "Using the first available FBConfig");
-              backend_glx->found_fbconfig = TRUE;
-              backend_glx->fbconfig = configs[0];
-            }
-
-        out:
-          XFree (configs);
-        }
-    }
-
-  if (G_LIKELY (backend_glx->found_fbconfig))
-    {
-      *config = backend_glx->fbconfig;
-
-      return TRUE;
-    }
-
-  return FALSE;
-}
-
-void
-_clutter_backend_glx_blit_sub_buffer (ClutterBackendGLX *backend_glx,
-                                      GLXDrawable        drawable,
-                                      int                x,
-                                      int                y,
-                                      int                width,
-                                      int                height)
-{
-  ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend_glx);
-
-  if (backend_glx->copy_sub_buffer)
-    {
-      backend_glx->copy_sub_buffer (backend_x11->xdpy, drawable,
-                                    x, y, width, height);
-    }
-  else if (backend_glx->blit_framebuffer)
-    {
-      glDrawBuffer (GL_FRONT);
-      backend_glx->blit_framebuffer (x, y, x + width, y + height,
-                                     x, y, x + width, y + height,
-                                     GL_COLOR_BUFFER_BIT, GL_NEAREST);
-      glDrawBuffer (GL_BACK);
-    }
-
-  /* NB: unlike glXSwapBuffers, glXCopySubBuffer and
-   * glBlitFramebuffer don't issue an implicit glFlush() so we
-   * have to flush ourselves if we want the request to complete in
-   * finite amount of time since otherwise the driver can batch
-   * the command indefinitely. */
-  glFlush();
-}
-
 static XVisualInfo *
 clutter_backend_glx_get_visual_info (ClutterBackendX11 *backend_x11)
 {
-  ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend_x11);
-  GLXFBConfig config;
-
-  if (!_clutter_backend_glx_get_fbconfig (backend_glx, &config))
-    return NULL;
-
-  return glXGetVisualFromFBConfig (backend_x11->xdpy, config);
+  return cogl_clutter_winsys_xlib_get_visual_info ();
 }
 
 static gboolean
 clutter_backend_glx_create_context (ClutterBackend  *backend,
                                     GError         **error)
 {
-  ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
   ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
-  GLXFBConfig config;
-  gboolean is_direct;
-  Window root_xwin;
-  XSetWindowAttributes attrs;
-  XVisualInfo *xvisinfo;
-  Display *xdisplay;
-  int major;
-  int minor;
-  GLXDrawable dummy_drawable;
-
-  if (backend_glx->gl_context != NULL)
-    return TRUE;
-
-  xdisplay = clutter_x11_get_default_display ();
-  root_xwin = clutter_x11_get_root_window ();
-
-  if (!_clutter_backend_glx_get_fbconfig (backend_glx, &config))
-    {
-      g_set_error_literal (error, CLUTTER_INIT_ERROR,
-                           CLUTTER_INIT_ERROR_BACKEND,
-                           "Unable to find suitable fbconfig for the GLX context");
-      return FALSE;
-    }
+  CoglSwapChain *swap_chain = NULL;
+  CoglOnscreenTemplate *onscreen_template = NULL;
 
-  CLUTTER_NOTE (BACKEND, "Creating GLX Context (display: %p)", xdisplay);
+  if (backend->cogl_context)
+    return TRUE;
 
-  backend_glx->gl_context = glXCreateNewContext (xdisplay,
-                                                 config,
-                                                 GLX_RGBA_TYPE,
-                                                 NULL,
-                                                 True);
-  if (backend_glx->gl_context == NULL)
-    {
-      g_set_error_literal (error, CLUTTER_INIT_ERROR,
-                           CLUTTER_INIT_ERROR_BACKEND,
-                           "Unable to create suitable GL context");
-      return FALSE;
-    }
+  backend->cogl_renderer = cogl_renderer_new ();
+  cogl_renderer_xlib_set_foreign_display (backend->cogl_renderer,
+                                          backend_x11->xdpy);
+  if (!cogl_renderer_connect (backend->cogl_renderer, error))
+    goto error;
 
-  is_direct = glXIsDirect (xdisplay, backend_glx->gl_context);
-
-  CLUTTER_NOTE (GL, "Setting %s context",
-                is_direct ? "direct"
-                          : "indirect");
-  _cogl_set_indirect_context (!is_direct);
-
-  /* COGL assumes that there is always a GL context selected; in order
-   * to make sure that a GLX context exists and is made current, we use
-   * a dummy, offscreen override-redirect window to which we can always
-   * fall back if no stage is available
-   *
-   * XXX - we need to do this dance because GLX does not allow creating
-   * a context and querying it for basic information (even the function
-   * pointers) unless it's made current to a real Drawable. it should be
-   * possible to avoid this in future releases of Mesa and X11, but right
-   * now this is the best solution available.
-   */
-  xvisinfo = glXGetVisualFromFBConfig (xdisplay, config);
-  if (xvisinfo == NULL)
-    {
-      g_set_error_literal (error, CLUTTER_INIT_ERROR,
-                           CLUTTER_INIT_ERROR_BACKEND,
-                           "Unable to retrieve the X11 visual");
-      return FALSE;
-    }
+  swap_chain = cogl_swap_chain_new ();
+  cogl_swap_chain_set_has_alpha (swap_chain,
+                                 clutter_x11_get_use_argb_visual ());
 
-  clutter_x11_trap_x_errors ();
-
-  attrs.override_redirect = True;
-  attrs.colormap = XCreateColormap (xdisplay,
-                                    root_xwin,
-                                    xvisinfo->visual,
-                                    AllocNone);
-  attrs.border_pixel = 0;
-
-  backend_glx->dummy_xwin = XCreateWindow (xdisplay, root_xwin,
-                                           -100, -100, 1, 1,
-                                           0,
-                                           xvisinfo->depth,
-                                           CopyFromParent,
-                                           xvisinfo->visual,
-                                           CWOverrideRedirect | CWColormap | CWBorderPixel,
-                                           &attrs);
-
-  /* Try and create a GLXWindow to use with extensions dependent on
-   * GLX versions >= 1.3 that don't accept regular X Windows as GLX
-   * drawables. */
-  if (glXQueryVersion (backend_x11->xdpy, &major, &minor) &&
-      major == 1 && minor >= 3)
-    {
-      backend_glx->dummy_glxwin = glXCreateWindow (backend_x11->xdpy,
-                                                   config,
-                                                   backend_glx->dummy_xwin,
-                                                   NULL);
-    }
+  onscreen_template = cogl_onscreen_template_new (swap_chain);
+  cogl_object_unref (swap_chain);
 
-  if (backend_glx->dummy_glxwin)
-    dummy_drawable = backend_glx->dummy_glxwin;
-  else
-    dummy_drawable = backend_glx->dummy_xwin;
+  if (!cogl_renderer_check_onscreen_template (backend->cogl_renderer,
+                                              onscreen_template,
+                                              error))
+    goto error;
 
-  CLUTTER_NOTE (BACKEND, "Selecting dummy 0x%x for the GLX context",
-                (unsigned int) dummy_drawable);
+  backend->cogl_display = cogl_display_new (backend->cogl_renderer,
+                                            onscreen_template);
+  cogl_object_unref (backend->cogl_renderer);
+  cogl_object_unref (onscreen_template);
 
-  glXMakeContextCurrent (xdisplay,
-                         dummy_drawable,
-                         dummy_drawable,
-                         backend_glx->gl_context);
+  if (!cogl_display_setup (backend->cogl_display, error))
+    goto error;
 
-  XFree (xvisinfo);
+  backend->cogl_context = cogl_context_new (backend->cogl_display, error);
+  if (!backend->cogl_context)
+    goto error;
 
-  if (clutter_x11_untrap_x_errors ())
-    {
-      g_set_error_literal (error, CLUTTER_INIT_ERROR,
-                           CLUTTER_INIT_ERROR_BACKEND,
-                           "Unable to select the newly created GLX context");
-      return FALSE;
-    }
+  /* XXX: eventually this should go away but a lot of Cogl code still
+   * depends on a global default context. */
+  cogl_set_default_context (backend->cogl_context);
 
   return TRUE;
-}
 
-/* TODO: remove this interface in favour of
- * _clutter_stage_window_make_current () */
-static void
-clutter_backend_glx_ensure_context (ClutterBackend *backend,
-                                    ClutterStage   *stage)
-{
-  ClutterStageWindow *impl;
-
-  /* if there is no stage, the stage is being destroyed or it has no
-   * implementation attached to it then we clear the GL context
-   */
-  if (stage == NULL ||
-      CLUTTER_ACTOR_IN_DESTRUCTION (stage) ||
-      ((impl = _clutter_stage_get_window (stage)) == NULL))
+error:
+  if (backend->cogl_display)
     {
-      ClutterBackendX11 *backend_x11;
+      cogl_object_unref (backend->cogl_display);
+      backend->cogl_display = NULL;
+    }
 
-      backend_x11 = CLUTTER_BACKEND_X11 (backend);
-      CLUTTER_NOTE (MULTISTAGE, "Clearing all context");
+  if (onscreen_template)
+    cogl_object_unref (onscreen_template);
+  if (swap_chain)
+    cogl_object_unref (swap_chain);
 
-      glXMakeContextCurrent (backend_x11->xdpy, None, None, NULL);
-    }
-  else
+  if (backend->cogl_renderer)
     {
-      ClutterBackendGLX *backend_glx;
-      ClutterBackendX11 *backend_x11;
-      ClutterStageGLX   *stage_glx;
-      ClutterStageX11   *stage_x11;
-      GLXDrawable        drawable;
-
-      g_assert (impl != NULL);
-
-      stage_glx = CLUTTER_STAGE_GLX (impl);
-      stage_x11 = CLUTTER_STAGE_X11 (impl);
-      backend_glx = CLUTTER_BACKEND_GLX (backend);
-      backend_x11 = CLUTTER_BACKEND_X11 (backend);
-
-      drawable = stage_glx->glxwin ? stage_glx->glxwin : stage_x11->xwin;
-
-      CLUTTER_NOTE (BACKEND,
-                    "Setting context for stage of type %s, window: 0x%x",
-                    G_OBJECT_TYPE_NAME (impl),
-                    (unsigned int) drawable);
-
-      /* no GL context to set */
-      if (backend_glx->gl_context == NULL)
-        return;
-
-      clutter_x11_trap_x_errors ();
-
-      /* we might get here inside the final dispose cycle, so we
-       * need to handle this gracefully
-       */
-      if (drawable == None)
-        {
-          GLXDrawable dummy_drawable;
-
-          CLUTTER_NOTE (BACKEND,
-                        "Received a stale stage, clearing all context");
-
-          if (backend_glx->dummy_glxwin)
-            dummy_drawable = backend_glx->dummy_glxwin;
-          else
-            dummy_drawable = backend_glx->dummy_xwin;
-
-          if (dummy_drawable == None)
-            glXMakeContextCurrent (backend_x11->xdpy, None, None, NULL);
-          else
-            {
-              glXMakeContextCurrent (backend_x11->xdpy,
-                                     dummy_drawable,
-                                     dummy_drawable,
-                                     backend_glx->gl_context);
-            }
-        }
-      else
-        {
-          CLUTTER_NOTE (BACKEND,
-                        "MakeContextCurrent dpy: %p, window: 0x%x (%s), context: %p",
-                        backend_x11->xdpy,
-                        (unsigned int) drawable,
-                        stage_x11->is_foreign_xwin ? "foreign" : "native",
-                        backend_glx->gl_context);
-
-          glXMakeContextCurrent (backend_x11->xdpy,
-                                 drawable,
-                                 drawable,
-                                 backend_glx->gl_context);
-          /*
-           * In case we are using GLX_SGI_swap_control for vblank syncing we need call
-           * glXSwapIntervalSGI here to make sure that it affects the current drawable.
-           */
-          if (backend_glx->vblank_type == CLUTTER_VBLANK_GLX_SWAP && backend_glx->swap_interval != NULL)
-            backend_glx->swap_interval (1);
-        }
-
-      if (clutter_x11_untrap_x_errors ())
-        g_critical ("Unable to make the stage window 0x%x the current "
-                    "GLX drawable",
-                    (unsigned int) drawable);
+      cogl_object_unref (backend->cogl_renderer);
+      backend->cogl_renderer = NULL;
     }
+  return FALSE;
 }
 
 static ClutterStageWindow *
@@ -813,6 +327,16 @@ clutter_backend_glx_create_stage (ClutterBackend  *backend,
 }
 
 static void
+clutter_backend_glx_ensure_context (ClutterBackend *backend,
+                                    ClutterStage   *stage)
+{
+  ClutterStageGLX *stage_glx =
+    CLUTTER_STAGE_GLX (_clutter_stage_get_window (stage));
+
+  cogl_set_framebuffer (COGL_FRAMEBUFFER (stage_glx->onscreen));
+}
+
+static void
 clutter_backend_glx_class_init (ClutterBackendGLXClass *klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
diff --git a/clutter/glx/clutter-backend-glx.h b/clutter/glx/clutter-backend-glx.h
index 195b19a..a1d6eae 100644
--- a/clutter/glx/clutter-backend-glx.h
+++ b/clutter/glx/clutter-backend-glx.h
@@ -47,30 +47,11 @@ typedef struct _ClutterBackendGLXClass  ClutterBackendGLXClass;
 
 typedef enum ClutterGLXVBlankType {
   CLUTTER_VBLANK_NONE = 0,
-  CLUTTER_VBLANK_GLX_SWAP,
-  CLUTTER_VBLANK_GLX,
-  CLUTTER_VBLANK_DRI
+  CLUTTER_VBLANK_AUTOMATIC_THROTTLE,
+  CLUTTER_VBLANK_VBLANK_COUNTER,
+  CLUTTER_VBLANK_MANUAL_WAIT
 } ClutterGLXVBlankType;
 
-typedef int (*GetVideoSyncProc)  (unsigned int *count);
-typedef int (*WaitVideoSyncProc) (int           divisor,
-                                  int           remainder,
-                                  unsigned int *count);
-typedef int (*SwapIntervalProc)  (int           interval);
-typedef void (*CopySubBufferProc)(Display *dpy,
-                                  GLXDrawable drawable,
-                                  int x, int y, int width, int height);
-typedef void (*BlitFramebufferProc) (GLint      srcX0,
-                                     GLint      srcY0,
-                                     GLint      srcX1,
-                                     GLint      srcY1,
-                                     GLint      dstX0,
-                                     GLint      dstY0,
-                                     GLint      dstX1,
-                                     GLint      dstY1,
-                                     GLbitfield mask,
-                                     GLenum     filter);
-
 struct _ClutterBackendGLX
 {
   ClutterBackendX11 parent_instance;
@@ -78,25 +59,13 @@ struct _ClutterBackendGLX
   int                    error_base;
   int                    event_base;
 
-  /* Single context for all wins */
-  gboolean               found_fbconfig;
-  GLXFBConfig            fbconfig;
-  GLXContext             gl_context;
-  Window                 dummy_xwin;
-  GLXWindow              dummy_glxwin;
+  CoglContext           *cogl_context;
 
   /* Vblank stuff */
-  GetVideoSyncProc       get_video_sync;
-  WaitVideoSyncProc      wait_video_sync;
-  SwapIntervalProc       swap_interval;
-  gint                   dri_fd;
   ClutterGLXVBlankType   vblank_type;
   unsigned int           last_video_sync_count;
 
   gboolean               can_blit_sub_buffer;
-  CopySubBufferProc      copy_sub_buffer;
-  BlitFramebufferProc    blit_framebuffer;
-  gboolean               blit_sub_buffer_is_synchronized;
 
   /* props */
   Atom atom_WM_STATE;
@@ -110,14 +79,8 @@ struct _ClutterBackendGLXClass
 
 GType _clutter_backend_glx_get_type (void) G_GNUC_CONST;
 
-gboolean
-_clutter_backend_glx_get_fbconfig (ClutterBackendGLX *backend_x11,
-                                   GLXFBConfig       *config);
-
-void
-_clutter_backend_glx_blit_sub_buffer (ClutterBackendGLX *backend_glx,
-                                      GLXDrawable drawable,
-                                      int x, int y, int width, int height);
+G_CONST_RETURN gchar*
+_clutter_backend_glx_get_vblank (void);
 
 G_END_DECLS
 
diff --git a/clutter/glx/clutter-stage-glx.c b/clutter/glx/clutter-stage-glx.c
index 76d11f6..60e0002 100644
--- a/clutter/glx/clutter-stage-glx.c
+++ b/clutter/glx/clutter-stage-glx.c
@@ -53,10 +53,8 @@
 #endif
 
 static void clutter_stage_window_iface_init     (ClutterStageWindowIface     *iface);
-static void clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface);
 
 static ClutterStageWindowIface *clutter_stage_window_parent_iface = NULL;
-static ClutterEventTranslatorIface *clutter_event_translator_parent_iface = NULL;
 
 #define clutter_stage_glx_get_type      _clutter_stage_glx_get_type
 
@@ -64,33 +62,37 @@ G_DEFINE_TYPE_WITH_CODE (ClutterStageGLX,
                          clutter_stage_glx,
                          CLUTTER_TYPE_STAGE_X11,
                          G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
-                                                clutter_stage_window_iface_init)
-                         G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_EVENT_TRANSLATOR,
-                                                clutter_event_translator_iface_init));
+                                                clutter_stage_window_iface_init));
 
 static void
 clutter_stage_glx_unrealize (ClutterStageWindow *stage_window)
 {
-  ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
   ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window);
-  ClutterBackendX11 *backend_x11 = stage_x11->backend;
 
   /* Note unrealize should free up any backend stage related resources */
   CLUTTER_NOTE (BACKEND, "Unrealizing GLX stage [%p]", stage_glx);
 
-  clutter_x11_trap_x_errors ();
-
-  if (stage_glx->glxwin != None)
-    {
-      glXDestroyWindow (backend_x11->xdpy, stage_glx->glxwin);
-      stage_glx->glxwin = None;
-    }
-
-  _clutter_stage_x11_destroy_window_untrapped (stage_x11);
+  cogl_object_unref (stage_glx->onscreen);
+  stage_glx->onscreen = NULL;
+}
 
-  XSync (backend_x11->xdpy, False);
+static void
+handle_swap_complete_cb (CoglFramebuffer *framebuffer,
+                         void *user_data)
+{
+  ClutterStageGLX *stage_glx = user_data;
 
-  clutter_x11_untrap_x_errors ();
+  /* Early versions of the swap_event implementation in Mesa
+   * deliver BufferSwapComplete event when not selected for,
+   * so if we get a swap event we aren't expecting, just ignore it.
+   *
+   * https://bugs.freedesktop.org/show_bug.cgi?id=27962
+   *
+   * FIXME: This issue can be hidden inside Cogl so we shouldn't
+   * need to care about this bug here.
+   */
+  if (stage_glx->pending_swaps > 0)
+    stage_glx->pending_swaps--;
 }
 
 static gboolean
@@ -98,56 +100,53 @@ clutter_stage_glx_realize (ClutterStageWindow *stage_window)
 {
   ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
   ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window);
-  ClutterBackendX11 *backend_x11;
+  ClutterBackend *backend;
   ClutterBackendGLX *backend_glx;
+  CoglFramebuffer *framebuffer;
+  GError *error = NULL;
+  gfloat width;
+  gfloat height;
+  const char *clutter_vblank;
 
   CLUTTER_NOTE (ACTOR, "Realizing stage '%s' [%p]",
                 G_OBJECT_TYPE_NAME (stage_window),
                 stage_window);
 
-  if (!_clutter_stage_x11_create_window (stage_x11))
-    return FALSE;
+  backend = CLUTTER_BACKEND (stage_x11->backend);
+  backend_glx = CLUTTER_BACKEND_GLX (stage_x11->backend);
 
-  backend_x11 = stage_x11->backend;
-  backend_glx = CLUTTER_BACKEND_GLX (backend_x11);
+  clutter_actor_get_size (CLUTTER_ACTOR (stage_x11->wrapper), &width, &height);
 
-  if (stage_glx->glxwin == None)
-    {
-      int major;
-      int minor;
-      GLXFBConfig config;
+  stage_glx->onscreen = cogl_onscreen_new (backend->cogl_context,
+                                           width, height);
+  if (stage_x11->xwin != None)
+    cogl_onscreen_x11_set_foreign_window_xid (stage_glx->onscreen,
+                                              stage_x11->xwin);
 
-      /* Try and create a GLXWindow to use with extensions dependent on
-       * GLX versions >= 1.3 that don't accept regular X Windows as GLX
-       * drawables.
-       */
-      if (glXQueryVersion (backend_x11->xdpy, &major, &minor) &&
-          major == 1 && minor >= 3 &&
-          _clutter_backend_glx_get_fbconfig (backend_glx, &config))
-        {
-          stage_glx->glxwin = glXCreateWindow (backend_x11->xdpy,
-                                               config,
-                                               stage_x11->xwin,
-                                               NULL);
-        }
-    }
+  clutter_vblank = _clutter_backend_glx_get_vblank ();
+  if (clutter_vblank && strcmp (clutter_vblank, "none") == 0)
+    cogl_onscreen_set_swap_throttled (stage_glx->onscreen, FALSE);
 
-#ifdef GLX_INTEL_swap_event
-  if (clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS))
+  framebuffer = COGL_FRAMEBUFFER (stage_glx->onscreen);
+  if (!cogl_framebuffer_allocate (framebuffer, &error))
     {
-      GLXDrawable drawable = stage_glx->glxwin
-                           ? stage_glx->glxwin
-                           : stage_x11->xwin;
+      g_warning ("Failed to allocate stage: %s", error->message);
+      g_error_free (error);
+      cogl_object_unref (stage_glx->onscreen);
+      stage_glx->onscreen = NULL;
+      return FALSE;
+    }
 
-      /* we unconditionally select this event because we rely on it to
-       * advance the master clock, and drive redraw/relayout, animations
-       * and event handling.
-       */
-      glXSelectEvent (backend_x11->xdpy,
-                      drawable,
-                      GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK);
+  if (stage_x11->xwin == None)
+    stage_x11->xwin = cogl_onscreen_x11_get_window_xid (stage_glx->onscreen);
+
+  if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT))
+    {
+      stage_glx->swap_callback_id =
+        cogl_framebuffer_add_swap_buffers_callback (framebuffer,
+                                                    handle_swap_complete_cb,
+                                                    stage_glx);
     }
-#endif /* GLX_INTEL_swap_event */
 
   /* chain up to the StageX11 implementation */
   return clutter_stage_window_parent_iface->realize (stage_window);
@@ -311,65 +310,12 @@ clutter_stage_glx_add_redraw_clip (ClutterStageWindow *stage_window,
   stage_glx->initialized_redraw_clip = TRUE;
 }
 
-#ifdef HAVE_DRM
-static int
-drm_wait_vblank(int fd, drm_wait_vblank_t *vbl)
-{
-    int ret, rc;
-
-    do
-      {
-        ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl);
-        vbl->request.type &= ~_DRM_VBLANK_RELATIVE;
-        rc = errno;
-      }
-    while (ret && rc == EINTR);
-
-    return rc;
-}
-#endif /* HAVE_DRM */
-
-static void
-wait_for_vblank (ClutterBackendGLX *backend_glx)
-{
-  if (backend_glx->vblank_type == CLUTTER_VBLANK_NONE)
-    return;
-
-  if (backend_glx->wait_video_sync)
-    {
-      unsigned int retraceCount;
-
-      CLUTTER_NOTE (BACKEND, "Waiting for vblank (wait_video_sync)");
-      backend_glx->get_video_sync (&retraceCount);
-      backend_glx->wait_video_sync (2,
-                                    (retraceCount + 1) % 2,
-                                    &retraceCount);
-    }
-  else
-    {
-#ifdef HAVE_DRM
-      drm_wait_vblank_t blank;
-
-      CLUTTER_NOTE (BACKEND, "Waiting for vblank (drm)");
-      blank.request.type     = _DRM_VBLANK_RELATIVE;
-      blank.request.sequence = 1;
-      blank.request.signal   = 0;
-      drm_wait_vblank (backend_glx->dri_fd, &blank);
-#else
-      CLUTTER_NOTE (BACKEND, "No vblank mechanism found");
-#endif /* HAVE_DRM */
-    }
-}
-
 static void
 clutter_stage_glx_redraw (ClutterStageWindow *stage_window)
 {
-  ClutterBackendX11 *backend_x11;
   ClutterBackendGLX *backend_glx;
   ClutterStageX11 *stage_x11;
   ClutterStageGLX *stage_glx;
-  GLXDrawable drawable;
-  unsigned int video_sync_count;
   gboolean may_use_clipped_redraw;
   gboolean use_clipped_redraw;
 
@@ -395,8 +341,7 @@ clutter_stage_glx_redraw (ClutterStageWindow *stage_window)
 
   stage_glx = CLUTTER_STAGE_GLX (stage_window);
 
-  backend_x11 = stage_x11->backend;
-  backend_glx = CLUTTER_BACKEND_GLX (backend_x11);
+  backend_glx = CLUTTER_BACKEND_GLX (stage_x11->backend);
 
   CLUTTER_TIMER_START (_clutter_uprof_context, painting_timer);
 
@@ -502,173 +447,75 @@ clutter_stage_glx_redraw (ClutterStageWindow *stage_window)
       cogl_object_unref (vbo);
     }
 
-  cogl_flush ();
   CLUTTER_TIMER_STOP (_clutter_uprof_context, painting_timer);
 
-  drawable = stage_glx->glxwin
-           ? stage_glx->glxwin
-           : stage_x11->xwin;
-
-  /* If we might ever use _clutter_backend_glx_blit_sub_buffer then we
-   * always need to keep track of the video_sync_count so that we can
-   * throttle blits.
-   *
-   * Note: we get the count *before* we issue any glXCopySubBuffer or
-   * blit_sub_buffer request in case the count would go up before
-   * returning control to us.
-   */
-  if (backend_glx->can_blit_sub_buffer && backend_glx->get_video_sync)
-    backend_glx->get_video_sync (&video_sync_count);
-
   /* push on the screen */
   if (use_clipped_redraw)
     {
       ClutterGeometry *clip = &stage_glx->bounding_redraw_clip;
-      ClutterGeometry copy_area;
+      int copy_area[4];
       ClutterActor *actor;
 
-      CLUTTER_NOTE (BACKEND,
-                    "_glx_blit_sub_buffer (window: 0x%lx, "
-                                          "x: %d, y: %d, "
-                                          "width: %d, height: %d)",
-                    (unsigned long) drawable,
-                    stage_glx->bounding_redraw_clip.x,
-                    stage_glx->bounding_redraw_clip.y,
-                    stage_glx->bounding_redraw_clip.width,
-                    stage_glx->bounding_redraw_clip.height);
-
       /* XXX: It seems there will be a race here in that the stage
-       * window may be resized before glXCopySubBufferMESA is handled
-       * and so we may copy the wrong region. I can't really see how
-       * we can handle this with the current state of X but at least
-       * in this case a full redraw should be queued by the resize
-       * anyway so it should only exhibit temporary artefacts.
+       * window may be resized before the cogl_framebuffer_swap_region
+       * is handled and so we may copy the wrong region. I can't
+       * really see how we can handle this with the current state of X
+       * but at least in this case a full redraw should be queued by
+       * the resize anyway so it should only exhibit temporary
+       * artefacts.
        */
+
       actor = CLUTTER_ACTOR (stage_x11->wrapper);
-      copy_area.y = clutter_actor_get_height (actor)
-                  - clip->y
-                  - clip->height;
-      copy_area.x = clip->x;
-      copy_area.width = clip->width;
-      copy_area.height = clip->height;
-
-      /* We need to ensure that all the rendering is done, otherwise
-       * redraw operations that are slower than the framerate can
-       * queue up in the pipeline during a heavy animation, causing a
-       * larger and larger backlog of rendering visible as lag to the
-       * user.
-       *
-       * Note: since calling glFinish() and sycnrhonizing the CPU with
-       * the GPU is far from ideal, we hope that this is only a short
-       * term solution.
-       * - One idea is to using sync objects to track render
-       *   completion so we can throttle the backlog (ideally with an
-       *   additional extension that lets us get notifications in our
-       *   mainloop instead of having to busy wait for the
-       *   completion.)
-       * - Another option is to support clipped redraws by reusing the
-       *   contents of old back buffers such that we can flip instead
-       *   of using a blit and then we can use GLX_INTEL_swap_events
-       *   to throttle. For this though we would still probably want an
-       *   additional extension so we can report the limited region of
-       *   the window damage to X/compositors.
-       */
-      glFinish ();
 
-      /* glXCopySubBufferMESA and glBlitFramebuffer are not integrated
-       * with the glXSwapIntervalSGI mechanism which we usually use to
-       * throttle the Clutter framerate to the vertical refresh and so
-       * we have to manually wait for the vblank period...
-       */
+      copy_area[0] = clip->x;
+      copy_area[1] = clutter_actor_get_height (actor) - clip->y - clip->height;
+      copy_area[2] = clip->width;
+      copy_area[3] = clip->height;
 
-      /* Here 'is_synchronized' only means that the blit won't cause a
-       * tear, ie it won't prevent multiple blits per retrace if they
-       * can all be performed in the blanking period. If that's the
-       * case then we still want to use the vblank sync menchanism but
-       * we only need it to throttle redraws.
-       */
-      if (!backend_glx->blit_sub_buffer_is_synchronized)
-        {
-          /* XXX: note that glXCopySubBuffer, at least for Intel, is
-           * synchronized with the vblank but glBlitFramebuffer may
-           * not be so we use the same scheme we do when calling
-           * glXSwapBuffers without the swap_control extension and
-           * call glFinish () before waiting for the vblank period.
-           *
-           * See where we call glXSwapBuffers for more details.
-           */
-          wait_for_vblank (backend_glx);
-        }
-      else if (backend_glx->get_video_sync)
-        {
-          /* If we have the GLX_SGI_video_sync extension then we can
-           * be a bit smarter about how we throttle blits by avoiding
-           * any waits if we can see that the video sync count has
-           * already progressed. */
-          if (backend_glx->last_video_sync_count == video_sync_count)
-            wait_for_vblank (backend_glx);
-        }
-      else
-        wait_for_vblank (backend_glx);
+      CLUTTER_NOTE (BACKEND,
+                    "cogl_framebuffer_swap_region (onscreen: %p, "
+                                                  "x: %d, y: %d, "
+                                                  "width: %d, height: %d)",
+                    stage_glx->onscreen,
+                    copy_area[0], copy_area[1], copy_area[2], copy_area[3]);
 
       CLUTTER_TIMER_START (_clutter_uprof_context, blit_sub_buffer_timer);
-      _clutter_backend_glx_blit_sub_buffer (backend_glx,
-                                            drawable,
-                                            copy_area.x,
-                                            copy_area.y,
-                                            copy_area.width,
-                                            copy_area.height);
+
+      cogl_framebuffer_swap_region (COGL_FRAMEBUFFER (stage_glx->onscreen),
+                                    copy_area, 1);
+
       CLUTTER_TIMER_STOP (_clutter_uprof_context, blit_sub_buffer_timer);
     }
   else
     {
-      CLUTTER_NOTE (BACKEND, "glXSwapBuffers (display: %p, window: 0x%lx)",
-                    backend_x11->xdpy,
-                    (unsigned long) drawable);
+      CLUTTER_NOTE (BACKEND, "cogl_framebuffer_swap_buffers (onscreen: %p)",
+                    stage_glx->onscreen);
 
-      /* If we have GLX swap buffer events then glXSwapBuffers will return
-       * immediately and we need to track that there is a swap in
-       * progress... */
+      /* If we have swap buffer events then
+       * cogl_framebuffer_swap_buffers will return immediately and we
+       * need to track that there is a swap in progress... */
       if (clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS))
         stage_glx->pending_swaps++;
 
-      if (backend_glx->vblank_type != CLUTTER_VBLANK_GLX_SWAP &&
-          backend_glx->vblank_type != CLUTTER_VBLANK_NONE)
-        {
-          /* If we are going to wait for VBLANK manually, we not only
-           * need to flush out pending drawing to the GPU before we
-           * sleep, we need to wait for it to finish. Otherwise, we
-           * may end up with the situation:
-           *
-           *        - We finish drawing      - GPU drawing continues
-           *        - We go to sleep         - GPU drawing continues
-           * VBLANK - We call glXSwapBuffers - GPU drawing continues
-           *                                 - GPU drawing continues
-           *                                 - Swap buffers happens
-           *
-           * Producing a tear. Calling glFinish() first will cause us
-           * to properly wait for the next VBLANK before we swap. This
-           * obviously does not happen when we use _GLX_SWAP and let
-           * the driver do the right thing
-           */
-          glFinish ();
-
-          wait_for_vblank (backend_glx);
-        }
-
       CLUTTER_TIMER_START (_clutter_uprof_context, swapbuffers_timer);
-      glXSwapBuffers (backend_x11->xdpy, drawable);
+      cogl_framebuffer_swap_buffers (COGL_FRAMEBUFFER (stage_glx->onscreen));
       CLUTTER_TIMER_STOP (_clutter_uprof_context, swapbuffers_timer);
     }
 
-  backend_glx->last_video_sync_count = video_sync_count;
-
   /* reset the redraw clipping for the next paint... */
   stage_glx->initialized_redraw_clip = FALSE;
 
   stage_glx->frame_count++;
 }
 
+static CoglFramebuffer *
+clutter_stage_glx_get_active_framebuffer (ClutterStageWindow *stage_window)
+{
+  ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window);
+
+  return COGL_FRAMEBUFFER (stage_glx->onscreen);
+}
+
 static void
 clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
 {
@@ -682,55 +529,7 @@ clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
   iface->has_redraw_clips = clutter_stage_glx_has_redraw_clips;
   iface->ignoring_redraw_clips = clutter_stage_glx_ignoring_redraw_clips;
   iface->redraw = clutter_stage_glx_redraw;
+  iface->get_active_framebuffer = clutter_stage_glx_get_active_framebuffer;
 
   /* the rest is inherited from ClutterStageX11 */
 }
-
-static ClutterTranslateReturn
-clutter_stage_glx_translate_event (ClutterEventTranslator *translator,
-                                   gpointer                native,
-                                   ClutterEvent           *event)
-{
-#ifdef GLX_INTEL_swap_event
-  ClutterBackendGLX *backend_glx;
-  XEvent *xevent = native;
-
-  backend_glx = CLUTTER_BACKEND_GLX (clutter_get_default_backend ());
-
-  if (xevent->type == (backend_glx->event_base + GLX_BufferSwapComplete))
-    {
-      ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (translator);
-      ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (translator);
-      GLXBufferSwapComplete *swap_complete_event;
-
-      swap_complete_event = (GLXBufferSwapComplete *) xevent;
-
-      if (stage_x11->xwin == swap_complete_event->drawable)
-        {
-	  /* Early versions of the swap_event implementation in Mesa
-	   * deliver BufferSwapComplete event when not selected for,
-	   * so if we get a swap event we aren't expecting, just ignore it.
-	   *
-	   * https://bugs.freedesktop.org/show_bug.cgi?id=27962
-	   */
-          if (stage_glx->pending_swaps > 0)
-            stage_glx->pending_swaps--;
-
-          return CLUTTER_TRANSLATE_REMOVE;
-        }
-    }
-#endif
-
-  /* chain up to the common X11 implementation */
-  return clutter_event_translator_parent_iface->translate_event (translator,
-                                                                 native,
-                                                                 event);
-}
-
-static void
-clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface)
-{
-  clutter_event_translator_parent_iface = g_type_interface_peek_parent (iface);
-
-  iface->translate_event = clutter_stage_glx_translate_event;
-}
diff --git a/clutter/glx/clutter-stage-glx.h b/clutter/glx/clutter-stage-glx.h
index 9baa0f3..43e8d16 100644
--- a/clutter/glx/clutter-stage-glx.h
+++ b/clutter/glx/clutter-stage-glx.h
@@ -50,8 +50,9 @@ struct _ClutterStageGLX
 
   gint pending_swaps;
 
-  GLXPixmap glxpixmap;
-  GLXWindow glxwin;
+  CoglOnscreen *onscreen;
+
+  unsigned int swap_callback_id;
 
   /* We only enable clipped redraws after 2 frames, since we've seen
    * a lot of drivers can struggle to get going and may output some
diff --git a/clutter/x11/clutter-backend-x11.c b/clutter/x11/clutter-backend-x11.c
index c029500..4b04123 100644
--- a/clutter/x11/clutter-backend-x11.c
+++ b/clutter/x11/clutter-backend-x11.c
@@ -134,7 +134,7 @@ cogl_xlib_filter (XEvent       *xevent,
   ClutterX11FilterReturn retval;
   CoglXlibFilterReturn ret;
 
-  ret = _cogl_xlib_handle_event (xevent);
+  ret = cogl_xlib_handle_event (xevent);
   switch (ret)
     {
     case COGL_XLIB_FILTER_REMOVE:
@@ -390,7 +390,7 @@ _clutter_backend_x11_post_parse (ClutterBackend  *backend,
 
       /* Cogl needs to know the Xlib display connection for
          CoglTexturePixmapX11 */
-      _cogl_xlib_set_display (backend_x11->xdpy);
+      cogl_xlib_set_display (backend_x11->xdpy);
 
       /* add event filter for Cogl events */
       clutter_x11_add_filter (cogl_xlib_filter, NULL);
diff --git a/clutter/x11/clutter-stage-x11.c b/clutter/x11/clutter-stage-x11.c
index a587c31..5421742 100644
--- a/clutter/x11/clutter-stage-x11.c
+++ b/clutter/x11/clutter-stage-x11.c
@@ -379,6 +379,13 @@ clutter_stage_x11_realize (ClutterStageWindow *stage_window)
   ClutterDeviceManager *device_manager;
   int event_flags;
 
+  if (clutter_stages_by_xid == NULL)
+    clutter_stages_by_xid = g_hash_table_new (NULL, NULL);
+
+  g_hash_table_insert (clutter_stages_by_xid,
+                       GINT_TO_POINTER (stage_x11->xwin),
+                       stage_x11);
+
   set_wm_pid (stage_x11);
   set_wm_title (stage_x11);
   set_cursor_visible (stage_x11);
@@ -1436,13 +1443,6 @@ _clutter_stage_x11_create_window (ClutterStageX11 *stage_x11)
 
   XFree (xvisinfo);
 
-  if (clutter_stages_by_xid == NULL)
-    clutter_stages_by_xid = g_hash_table_new (NULL, NULL);
-
-  g_hash_table_insert (clutter_stages_by_xid,
-                       GINT_TO_POINTER (stage_x11->xwin),
-                       stage_x11);
-
   return TRUE;
 }
 
diff --git a/configure.ac b/configure.ac
index 40f88ec..6642412 100644
--- a/configure.ac
+++ b/configure.ac
@@ -447,6 +447,8 @@ AS_IF([test "x$SUPPORT_GLX" = "x1"],
       [
         AC_DEFINE([COGL_HAS_GLX_SUPPORT], [1], [Cogl supports OpenGL using the GLX API])
 
+        AC_DEFINE([COGL_HAS_FULL_WINSYS], [1], [Cogl can create its own OpenGL context])
+
         AC_DEFINE([HAVE_CLUTTER_GLX], [1], [Have the GLX backend])
 
         AC_CHECK_HEADERS([GL/glx.h],



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