[clutter/wip/cogl-winsys-egl: 14/37] Adds renderer, display, onscreen-template and swap-chain stubs



commit 20d146b962affa686662693917cfe15ac4d5b0d0
Author: Robert Bragg <robert linux intel com>
Date:   Fri Feb 25 17:06:50 2011 +0000

    Adds renderer,display,onscreen-template and swap-chain stubs
    
    As part of the process of splitting Cogl out as a standalone graphics
    API we need to introduce some API concepts that will allow us to
    initialize a new CoglContext when Clutter isn't there to handle that for
    us...
    
    The new objects roughly in the order that they are (optionally) involved
    in constructing a context are: CoglRenderer, CoglOnscreenTemplate,
    CoglSwapChain and CoglDisplay.
    
    Conceptually a CoglRenderer represents a means for rendering.  Cogl
    supports rendering via OpenGL or OpenGL ES 1/2.0 and those APIs are
    accessed through a number of different windowing APIs such as GLX, EGL,
    SDL or WGL and more. Potentially in the future Cogl could render using
    D3D or even by using libdrm and directly banging the hardware. All these
    choices are wrapped up in the configuration of a CoglRenderer.
    
    Conceptually a CoglDisplay represents a display pipeline for a renderer.
    Although Cogl doesn't aim to provide a detailed abstraction of display
    hardware, on some platforms we can give control over multiple display
    planes (On TV platforms for instance video content may be on one plane
    and 3D would be on another so a CoglDisplay lets you select the plane
    up-front.)
    
    Another aspect of CoglDisplay is that it lets us negotiate a display
    pipeline that best supports the type of CoglOnscreen framebuffers we are
    planning to create. For instance if you want transparent CoglOnscreen
    framebuffers then we have to be sure the display pipeline wont discard
    the alpha component of your framebuffers. Or if you want to use
    double/tripple buffering that requires support from the display
    pipeline.
    
    CoglOnscreenTemplate and CoglSwapChain are how we describe our default
    CoglOnscreen framebuffer configuration which can affect the
    configuration of the display pipeline.
    
    The default/simple way we expect most CoglContexts to be constructed
    will be via something like:
    
     if (!cogl_context_new (NULL, &error))
       g_error ("Failed to construct a CoglContext: %s", error->message);
    
    Where that NULL is for an optional "display" parameter and NULL says to
    Cogl "please just try to do something sensible".
    
    If you want some more control though you can manually construct a
    CoglDisplay something like:
    
     display = cogl_display_new (NULL, NULL);
     cogl_display_cex100_set_plane (display, plane);
     if (!cogl_display_setup (display, &error))
       g_error ("Failed to setup a CoglDisplay: %s", error->message);
    
    And in a similar fashion to cogl_context_new() you can optionally pass
    a NULL "renderer" and/or a NULL "onscreen template" so Cogl will try to
    just do something sensible.
    
    If you need to change the CoglOnscreen defaults you can provide a
    template something like:
      chain = cogl_swap_chain_new ();
      cogl_swap_chain_set_has_alpha (chain, TRUE);
      cogl_swap_chain_set_length (chain, 3);
    
      onscreen_template = cogl_onscreen_template_new (chain);
      cogl_onscreen_template_set_pixel_format (onscreen_template,
                                               COGL_PIXEL_FORMAT_RGB565);
    
      display = cogl_display_new (NULL, onscreen_template);
      if (!cogl_display_setup (display, &error))
        g_error ("Failed to setup a CoglDisplay: %s", error->message);

 clutter/clutter-backend-private.h                  |    5 +
 clutter/clutter-backend.c                          |    1 +
 clutter/clutter-stage.c                            |   12 -
 clutter/cogl/cogl/Makefile.am                      |   60 +-
 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                   |  146 ++-
 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-private.h           |   43 +
 clutter/cogl/cogl/cogl-display-xlib-private.h      |   35 +
 clutter/cogl/cogl/cogl-display.c                   |  111 ++
 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               |  236 ++++-
 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-onscreen-template-private.h |   37 +
 clutter/cogl/cogl/cogl-onscreen-template.c         |   62 +
 clutter/cogl/cogl/cogl-onscreen-template.h         |   48 +
 clutter/cogl/cogl/cogl-private.h                   |    6 +
 clutter/cogl/cogl/cogl-renderer-glx-private.h      |   61 +
 clutter/cogl/cogl/cogl-renderer-private.h          |   43 +
 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                  |  129 ++
 clutter/cogl/cogl/cogl-renderer.h                  |  158 +++
 clutter/cogl/cogl/cogl-swap-chain-private.h        |   37 +
 clutter/cogl/cogl/cogl-swap-chain.c                |   66 +
 clutter/cogl/cogl/cogl-swap-chain.h                |   46 +
 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                    |  376 ++-----
 clutter/glx/clutter-stage-glx.h                    |    5 +-
 clutter/x11/clutter-backend-x11.c                  |    4 +-
 clutter/x11/clutter-stage-x11.c                    |   14 +-
 configure.ac                                       |    2 +
 63 files changed, 4228 insertions(+), 1641 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 cdb342f..c4d2f50 100644
--- a/clutter/cogl/cogl/Makefile.am
+++ b/clutter/cogl/cogl/Makefile.am
@@ -78,11 +78,16 @@ 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)
 
 cogl_experimental_h = \
+	$(srcdir)/cogl-renderer.h 		\
+	$(srcdir)/cogl-swap-chain.h 		\
+	$(srcdir)/cogl-onscreen-template.h 	\
+	$(srcdir)/cogl-display.h 		\
 	$(srcdir)/cogl-context.h 		\
 	$(srcdir)/cogl2-path.h 			\
 	$(srcdir)/cogl2-clip-state.h		\
@@ -110,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
@@ -161,6 +164,18 @@ cogl_sources_c = \
 	$(srcdir)/cogl-handle.h 			\
 	$(srcdir)/cogl-context-private.h		\
 	$(srcdir)/cogl-context.c			\
+	$(srcdir)/cogl-renderer-private.h		\
+	$(srcdir)/cogl-renderer.h			\
+	$(srcdir)/cogl-renderer.c			\
+	$(srcdir)/cogl-swap-chain-private.h		\
+	$(srcdir)/cogl-swap-chain.h			\
+	$(srcdir)/cogl-swap-chain.c			\
+	$(srcdir)/cogl-onscreen-template-private.h 	\
+	$(srcdir)/cogl-onscreen-template.h 		\
+	$(srcdir)/cogl-onscreen-template.c 		\
+	$(srcdir)/cogl-display-private.h		\
+	$(srcdir)/cogl-display.h			\
+	$(srcdir)/cogl-display.c			\
 	$(srcdir)/cogl-internal.h			\
 	$(srcdir)/cogl.c				\
 	$(srcdir)/cogl-object-private.h			\
@@ -279,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 += \
@@ -309,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 00f4eaf..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)
@@ -86,30 +83,24 @@ _cogl_init_feature_overrides (CoglContext *ctx)
                             COGL_FEATURE_TEXTURE_NPOT_REPEAT);
 }
 
-/* FIXME: We don't report a GError here should we? With non NULL
- * displays then there should basically be no risk of error I think,
- * but NULL just says "please do the right thing" and we could hit any
- * number of problems that should be reported back to the caller!
- *
- * Also is it acceptable for construction to report an error
- * or should there be a separate cogl_context_check_status()
- * API of some kind?
+/* For reference: There was some deliberation over whether to have a
+ * constructor that could throw an exception but looking at standard
+ * practices with several high level OO languages including python, C++,
+ * C# Java and Ruby they all support exceptions in constructors and the
+ * general consensus appears to be that throwing an exception is neater
+ * than successfully constructing with an internal error status that
+ * would then have to be explicitly checked via some form of ::is_ok()
+ * method.
  */
 CoglContext *
-cogl_context_new (CoglDisplay *display)
+cogl_context_new (CoglDisplay *display,
+                  GError **error)
 {
   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)
@@ -134,23 +125,59 @@ 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;
 
+  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);
+
+  if (!cogl_display_setup (display, error))
+    {
+      cogl_object_unref (display);
+      g_free (context);
+      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 ();
@@ -161,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);
@@ -244,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;
@@ -334,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 ();
 
@@ -411,44 +441,38 @@ _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);
 }
 
 CoglContext *
 _cogl_context_get_default (void)
 {
+  GError *error = NULL;
   /* Create if doesn't exist yet */
   if (_context == NULL)
-    _context = cogl_context_new (NULL);
+    {
+      _context = cogl_context_new (NULL, &error);
+      if (!_context)
+        {
+          g_warning ("Failed to create default context: %s",
+                     error->message);
+          g_error_free (error);
+        }
+    }
 
   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-private.h b/clutter/cogl/cogl/cogl-display-private.h
new file mode 100644
index 0000000..1bda21d
--- /dev/null
+++ b/clutter/cogl/cogl/cogl-display-private.h
@@ -0,0 +1,43 @@
+/*
+ * 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_PRIVATE_H
+#define __COGL_DISPLAY_PRIVATE_H
+
+#include "cogl-object-private.h"
+#include "cogl-renderer.h"
+#include "cogl-onscreen-template.h"
+
+struct _CoglDisplay
+{
+  CoglObject _parent;
+
+  gboolean setup;
+  CoglRenderer *renderer;
+  CoglOnscreenTemplate *onscreen_template;
+
+  void *winsys;
+};
+
+#endif /* __COGL_DISPLAY_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
new file mode 100644
index 0000000..a09de18
--- /dev/null
+++ b/clutter/cogl/cogl/cogl-display.c
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ *
+ * Authors:
+ *   Robert Bragg <robert linux intel com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "cogl.h"
+#include "cogl-object.h"
+
+#include "cogl-display-private.h"
+#include "cogl-winsys-private.h"
+
+static void _cogl_display_free (CoglDisplay *display);
+
+COGL_OBJECT_DEFINE (Display, display);
+
+GQuark
+cogl_display_error_quark (void)
+{
+  return g_quark_from_static_string ("cogl-display-error-quark");
+}
+
+static void
+_cogl_display_free (CoglDisplay *display)
+{
+  if (display->renderer)
+    {
+      cogl_object_unref (display->renderer);
+      display->renderer = NULL;
+    }
+
+  if (display->onscreen_template)
+    {
+      cogl_object_unref (display->onscreen_template);
+      display->onscreen_template = NULL;
+    }
+
+  g_slice_free (CoglDisplay, display);
+}
+
+CoglDisplay *
+cogl_display_new (CoglRenderer *renderer,
+                  CoglOnscreenTemplate *onscreen_template)
+{
+  CoglDisplay *display = g_slice_new0 (CoglDisplay);
+  GError *error = NULL;
+
+  display->renderer = renderer;
+  if (renderer)
+    cogl_object_ref (renderer);
+  else
+    display->renderer = cogl_renderer_new ();
+
+  if (!cogl_renderer_connect (display->renderer, &error))
+    {
+      g_warning ("Failed to connect renderer: %s\n", error->message);
+      g_error_free (error);
+      g_object_unref (display->renderer);
+      g_slice_free (CoglDisplay, display);
+      return NULL;
+    }
+
+  display->onscreen_template = onscreen_template;
+  if (onscreen_template)
+    cogl_object_ref (onscreen_template);
+
+  display->setup = FALSE;
+
+  return _cogl_display_object_new (display);
+}
+
+gboolean
+cogl_display_setup (CoglDisplay *display,
+                    GError **error)
+{
+  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 3e3cc07..00ce4fb 100644
--- a/clutter/cogl/cogl/cogl-display.h
+++ b/clutter/cogl/cogl/cogl-display.h
@@ -31,7 +31,8 @@
 #ifndef __COGL_DISPLAY_H__
 #define __COGL_DISPLAY_H__
 
-#include <cogl/cogl-display.h>
+#include <cogl/cogl-renderer.h>
+#include <cogl/cogl-onscreen-template.h>
 
 G_BEGIN_DECLS
 
@@ -71,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 62cbc15..3078e51 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),
@@ -897,6 +903,9 @@ _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
@@ -941,16 +950,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
@@ -968,15 +995,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));
 
@@ -1054,11 +1107,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;
 
@@ -1082,9 +1138,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
@@ -1177,15 +1250,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,
@@ -1259,15 +1336,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
@@ -1277,21 +1359,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;
@@ -1447,6 +1537,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;
@@ -1479,3 +1571,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-onscreen-template-private.h b/clutter/cogl/cogl/cogl-onscreen-template-private.h
new file mode 100644
index 0000000..0f8d253
--- /dev/null
+++ b/clutter/cogl/cogl/cogl-onscreen-template-private.h
@@ -0,0 +1,37 @@
+/*
+ * 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_ONSCREEN_TEMPLATE_PRIVATE_H
+#define __COGL_ONSCREEN_TEMPLATE_PRIVATE_H
+
+#include "cogl-object-private.h"
+#include "cogl-swap-chain.h"
+
+struct _CoglOnscreenTemplate
+{
+  CoglObject _parent;
+
+  CoglSwapChain *swap_chain;
+};
+
+#endif /* __COGL_ONSCREEN_TEMPLATE_PRIVATE_H */
diff --git a/clutter/cogl/cogl/cogl-onscreen-template.c b/clutter/cogl/cogl/cogl-onscreen-template.c
new file mode 100644
index 0000000..ff400e4
--- /dev/null
+++ b/clutter/cogl/cogl/cogl-onscreen-template.c
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ *
+ * Authors:
+ *   Robert Bragg <robert linux intel com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "cogl.h"
+#include "cogl-object.h"
+
+#include "cogl-onscreen-template-private.h"
+
+static void _cogl_onscreen_template_free (CoglOnscreenTemplate *onscreen_template);
+
+COGL_OBJECT_DEFINE (OnscreenTemplate, onscreen_template);
+
+GQuark
+cogl_onscreen_template_error_quark (void)
+{
+  return g_quark_from_static_string ("cogl-onscreen-template-error-quark");
+}
+
+static void
+_cogl_onscreen_template_free (CoglOnscreenTemplate *onscreen_template)
+{
+  g_slice_free (CoglOnscreenTemplate, onscreen_template);
+}
+
+CoglOnscreenTemplate *
+cogl_onscreen_template_new (CoglSwapChain *swap_chain)
+{
+  CoglOnscreenTemplate *onscreen_template = g_slice_new0 (CoglOnscreenTemplate);
+
+  onscreen_template->swap_chain = swap_chain;
+  if (swap_chain)
+    cogl_object_ref (swap_chain);
+
+  return _cogl_onscreen_template_object_new (onscreen_template);
+}
diff --git a/clutter/cogl/cogl/cogl-onscreen-template.h b/clutter/cogl/cogl/cogl-onscreen-template.h
new file mode 100644
index 0000000..4769f9f
--- /dev/null
+++ b/clutter/cogl/cogl/cogl-onscreen-template.h
@@ -0,0 +1,48 @@
+/*
+ * 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>
+ *
+ */
+
+#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
+#error "Only <cogl/cogl.h> can be included directly."
+#endif
+
+#ifndef __COGL_ONSCREEN_TEMPLATE_H__
+#define __COGL_ONSCREEN_TEMPLATE_H__
+
+#include <cogl/cogl-swap-chain.h>
+
+G_BEGIN_DECLS
+
+typedef struct _CoglOnscreenTemplate	      CoglOnscreenTemplate;
+
+#define COGL_ONSCREEN_TEMPLATE(OBJECT) ((CoglOnscreenTemplate *)OBJECT)
+
+#define cogl_onscreen_template_new cogl_onscreen_template_new_EXP
+CoglOnscreenTemplate *
+cogl_onscreen_template_new (CoglSwapChain *swap_chain);
+
+G_END_DECLS
+
+#endif /* __COGL_ONSCREEN_TEMPLATE_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-private.h b/clutter/cogl/cogl/cogl-renderer-private.h
new file mode 100644
index 0000000..8668270
--- /dev/null
+++ b/clutter/cogl/cogl/cogl-renderer-private.h
@@ -0,0 +1,43 @@
+/*
+ * 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_PRIVATE_H
+#define __COGL_RENDERER_PRIVATE_H
+
+#include "cogl-object-private.h"
+
+#ifdef COGL_HAS_XLIB_SUPPORT
+#include <X11/Xlib.h>
+#endif
+
+struct _CoglRenderer
+{
+  CoglObject _parent;
+  gboolean connected;
+#ifdef COGL_HAS_XLIB_SUPPORT
+  Display *foreign_xdpy;
+#endif
+  void *winsys;
+};
+
+#endif /* __COGL_RENDERER_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 e14fdae..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_WINSYS_XLIB_H
-#define __COGL_WINSYS_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_WINSYS_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
new file mode 100644
index 0000000..2dffb2f
--- /dev/null
+++ b/clutter/cogl/cogl/cogl-renderer.c
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ *
+ * 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.h"
+#include "cogl-renderer-private.h"
+#include "cogl-display-private.h"
+#include "cogl-winsys-private.h"
+
+static void _cogl_renderer_free (CoglRenderer *renderer);
+
+COGL_OBJECT_DEFINE (Renderer, renderer);
+
+GQuark
+cogl_renderer_error_quark (void)
+{
+  return g_quark_from_static_string ("cogl-renderer-error-quark");
+}
+
+static void
+_cogl_renderer_free (CoglRenderer *renderer)
+{
+#ifdef COGL_HAS_FULL_WINSYS
+  _cogl_winsys_renderer_disconnect (renderer);
+#endif
+  g_free (renderer);
+}
+
+CoglRenderer *
+cogl_renderer_new (void)
+{
+  CoglRenderer *renderer = g_new0 (CoglRenderer, 1);
+
+  renderer->connected = FALSE;
+
+  return _cogl_renderer_object_new (renderer);
+}
+
+#if COGL_HAS_XLIB_SUPPORT
+void
+cogl_renderer_xlib_set_foreign_display (CoglRenderer *renderer,
+                                        Display *xdisplay)
+{
+  g_return_if_fail (cogl_is_renderer (renderer));
+
+  /* NB: Renderers are considered immutable once connected */
+  g_return_if_fail (!renderer->connected);
+
+  renderer->foreign_xdpy = xdisplay;
+}
+
+Display *
+cogl_renderer_xlib_get_foreign_display (CoglRenderer *renderer)
+{
+  g_return_val_if_fail (cogl_is_renderer (renderer), NULL);
+
+  return renderer->foreign_xdpy;
+}
+#endif /* COGL_HAS_XLIB_SUPPORT */
+
+gboolean
+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;
+}
+
+/* Final connection API */
+
+gboolean
+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-renderer.h b/clutter/cogl/cogl/cogl-renderer.h
new file mode 100644
index 0000000..6844299
--- /dev/null
+++ b/clutter/cogl/cogl/cogl-renderer.h
@@ -0,0 +1,158 @@
+/*
+ * 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, 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_RENDERER_H__
+#define __COGL_RENDERER_H__
+
+#include <glib.h>
+
+#include <cogl/cogl-types.h>
+#include <cogl/cogl-onscreen-template.h>
+
+#ifdef COGL_HAS_XLIB
+#include <X11/Xlib.h>
+#endif
+
+G_BEGIN_DECLS
+
+/**
+ * SECTION:cogl-renderer
+ * @short_description:
+ *
+ */
+
+#define cogl_renderer_error_quark cogl_renderer_error_quark_EXP
+
+#define COGL_RENDERER_ERROR cogl_renderer_error_quark ()
+GQuark
+cogl_renderer_error_quark (void);
+
+typedef struct _CoglRenderer CoglRenderer;
+
+#define cogl_is_renderer cogl_is_renderer_EXP
+gboolean
+cogl_is_renderer (void *object);
+
+#define cogl_renderer_new cogl_renderer_new_EXP
+CoglRenderer *
+cogl_renderer_new (void);
+
+/* optional configuration APIs */
+
+#ifdef COGL_HAS_XLIB
+
+#define cogl_renderer_xlib_handle_event cogl_renderer_xlib_handle_event_EXP
+/*
+ * cogl_renderer_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_renderer_xlib_handle_event (CoglRenderer *renderer,
+                                 XEvent *xevent);
+
+#define cogl_renderer_xlib_get_foreign_display \
+  cogl_renderer_xlib_get_foreign_display_EXP
+/*
+ * cogl_renderer_xlib_get_foreign_display:
+ *
+ * Return value: the foreign Xlib display that will be used by any Xlib based
+ * winsys backend. The display needs to be set with
+ * cogl_renderer_xlib_set_foreign_display() before this function is called.
+ */
+Display *
+cogl_renderer_xlib_get_foreign_display (CoglRenderer *renderer);
+
+#define cogl_renderer_xlib_set_foreign_display \
+  cogl_renderer_xlib_set_foreign_display_EXP
+/*
+ * cogl_renderer_xlib_set_foreign_display:
+ *
+ * Sets a foreign Xlib display that Cogl will use for and Xlib based winsys
+ * backend.
+ */
+void
+cogl_renderer_xlib_set_foreign_display (CoglRenderer *renderer,
+                                        Display *display);
+
+#define cogl_renderer_xlib_get_display cogl_renderer_xlib_get_display_EXP
+Display *
+cogl_renderer_xlib_get_display (CoglRenderer *renderer);
+
+#define cogl_renderer_xlib_add_filter cogl_renderer_xlib_add_filter_EXP
+/*
+ * _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_renderer_xlib_add_filter (CoglRenderer *renderer,
+                               CoglXlibFilterFunc func,
+                               void *data);
+
+#define cogl_renderer_xlib_remove_filter cogl_renderer_xlib_remove_filter_EXP
+/*
+ * _cogl_xlib_remove_filter:
+ *
+ * Removes a callback that was previously added with
+ * _cogl_xlib_add_filter().
+ */
+void
+cogl_renderer_xlib_remove_filter (CoglRenderer *renderer,
+                                  CoglXlibFilterFunc func,
+                                  void *data);
+#endif /* COGL_HAS_XLIB */
+
+#define cogl_renderer_check_onscreen_template \
+  cogl_renderer_check_onscreen_template_EXP
+gboolean
+cogl_renderer_check_onscreen_template (CoglRenderer *renderer,
+                                       CoglOnscreenTemplate *onscreen_template,
+                                       GError **error);
+
+/* Final connection API */
+
+#define cogl_renderer_connect cogl_renderer_connect_EXP
+gboolean
+cogl_renderer_connect (CoglRenderer *renderer, GError **error);
+
+G_END_DECLS
+
+#endif /* __COGL_RENDERER_H__ */
+
diff --git a/clutter/cogl/cogl/cogl-swap-chain-private.h b/clutter/cogl/cogl/cogl-swap-chain-private.h
new file mode 100644
index 0000000..5edadeb
--- /dev/null
+++ b/clutter/cogl/cogl/cogl-swap-chain-private.h
@@ -0,0 +1,37 @@
+/*
+ * 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_SWAP_CHAIN_PRIVATE_H
+#define __COGL_SWAP_CHAIN_PRIVATE_H
+
+#include "cogl-object-private.h"
+
+struct _CoglSwapChain
+{
+  CoglObject _parent;
+
+  gboolean has_alpha;
+
+};
+
+#endif /* __COGL_SWAP_CHAIN_PRIVATE_H */
diff --git a/clutter/cogl/cogl/cogl-swap-chain.c b/clutter/cogl/cogl/cogl-swap-chain.c
new file mode 100644
index 0000000..9622e9e
--- /dev/null
+++ b/clutter/cogl/cogl/cogl-swap-chain.c
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ *
+ * Authors:
+ *   Robert Bragg <robert linux intel com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "cogl.h"
+#include "cogl-object.h"
+
+#include "cogl-swap-chain-private.h"
+
+static void _cogl_swap_chain_free (CoglSwapChain *swap_chain);
+
+COGL_OBJECT_DEFINE (SwapChain, swap_chain);
+
+GQuark
+cogl_swap_chain_error_quark (void)
+{
+  return g_quark_from_static_string ("cogl-swap-chain-error-quark");
+}
+
+static void
+_cogl_swap_chain_free (CoglSwapChain *swap_chain)
+{
+  g_slice_free (CoglSwapChain, swap_chain);
+}
+
+CoglSwapChain *
+cogl_swap_chain_new (void)
+{
+  CoglSwapChain *swap_chain = g_slice_new0 (CoglSwapChain);
+
+  return _cogl_swap_chain_object_new (swap_chain);
+}
+
+void
+cogl_swap_chain_set_has_alpha (CoglSwapChain *swap_chain,
+                               gboolean has_alpha)
+{
+  swap_chain->has_alpha = has_alpha;
+}
+
diff --git a/clutter/cogl/cogl/cogl-swap-chain.h b/clutter/cogl/cogl/cogl-swap-chain.h
new file mode 100644
index 0000000..7791e23
--- /dev/null
+++ b/clutter/cogl/cogl/cogl-swap-chain.h
@@ -0,0 +1,46 @@
+/*
+ * 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_SWAP_CHAIN_H__
+#define __COGL_SWAP_CHAIN_H__
+
+G_BEGIN_DECLS
+
+typedef struct _CoglSwapChain CoglSwapChain;
+
+#define cogl_swap_chain_new cogl_swap_chain_new_EXP
+CoglSwapChain *
+cogl_swap_chain_new (void);
+
+#define cogl_swap_chain_set_has_alpha cogl_swap_chain_set_has_alpha_EXP
+void
+cogl_swap_chain_set_has_alpha (CoglSwapChain *swap_chain,
+                               gboolean has_alpha);
+
+G_END_DECLS
+
+#endif /* __COGL_SWAP_CHAIN_H__ */
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..a4c720e 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 exagerated 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 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 ();
+
+  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..17f5bcd 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,167 +447,61 @@ 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 ();
+      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;
 
-      /* 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...
-       */
+      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]);
 
-      /* 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_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;
 
@@ -685,52 +524,3 @@ clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
 
   /* 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 3891670..590d2c0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -445,6 +445,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]