[cogl: 5/5] Dynamically load the GL or GLES library



commit b2e735ff7f4094056765ff6adb5c74fd51d11e4a
Author: Neil Roberts <neil linux intel com>
Date:   Thu Jul 7 20:44:56 2011 +0100

    Dynamically load the GL or GLES library
    
    The GL or GLES library is now dynamically loaded by the CoglRenderer
    so that it can choose between GL, GLES1 and GLES2 at runtime. The
    library is loaded by the renderer because it needs to be done before
    calling eglInitialize. There is a new environment variable called
    COGL_DRIVER to choose between gl, gles1 or gles2.
    
    The #ifdefs for HAVE_COGL_GL, HAVE_COGL_GLES and HAVE_COGL_GLES2 have
    been changed so that they don't assume the ifdefs are mutually
    exclusive. They haven't been removed entirely so that it's possible to
    compile the GLES backends without the the enums from the GL headers.
    
    When using GLX the winsys additionally dynamically loads libGL because
    that also contains the GLX API. It can't be linked in directly because
    that would probably conflict with the GLES API if the EGL is
    selected. When compiling with EGL support the library links directly
    to libEGL because it doesn't contain any GL API so it shouldn't have
    any conflicts.
    
    When building for WGL or OSX Cogl still directly links against the GL
    API so there is a #define in config.h so that Cogl won't try to dlopen
    the library.
    
    Cogl-pango previously had a #ifdef to detect when the GL backend is
    used so that it can sneakily pass GL_QUADS to
    cogl_vertex_buffer_draw. This is now changed so that it queries the
    CoglContext for the backend. However to get this to work Cogl now
    needs to export the _cogl_context_get_default symbol and cogl-pango
    needs some extra -I flags to so that it can include
    cogl-context-private.h

 cogl-pango/Makefile.am                      |    2 +
 cogl-pango/cogl-pango-display-list.c        |   45 +++--
 cogl/Makefile.am                            |   12 +-
 cogl/cogl-attribute.c                       |  278 +++++++++++++--------------
 cogl/cogl-blend-string.c                    |   43 ++--
 cogl/cogl-buffer.c                          |   18 +--
 cogl/cogl-clip-stack.c                      |   41 +++--
 cogl/cogl-context-private.h                 |   16 ++-
 cogl/cogl-context.c                         |   84 +++++++--
 cogl/cogl-display-private.h                 |    1 +
 cogl/cogl-display.c                         |    3 +
 cogl/cogl-ext-functions.h                   |   13 --
 cogl/cogl-feature-private.c                 |   17 +-
 cogl/cogl-feature-private.h                 |    5 +-
 cogl/cogl-framebuffer.c                     |   10 +-
 cogl/cogl-glx-renderer-private.h            |   51 +++++
 cogl/cogl-internal.h                        |   11 +-
 cogl/cogl-journal.c                         |   60 +++---
 cogl/cogl-matrix-stack.c                    |  106 +++++-----
 cogl/cogl-pipeline-fragend-arbfp.c          |   45 +++--
 cogl/cogl-pipeline-fragend-fixed.c          |   32 ++--
 cogl/cogl-pipeline-fragend-glsl.c           |   24 ++-
 cogl/cogl-pipeline-opengl.c                 |  284 ++++++++++++++-------------
 cogl/cogl-pipeline-private.h                |  131 +++++++------
 cogl/cogl-pipeline-progend-glsl.c           |   98 ++++++----
 cogl/cogl-pipeline-vertend-fixed.c          |    5 +
 cogl/cogl-pipeline-vertend-glsl.c           |   52 +++---
 cogl/cogl-pipeline.c                        |  232 ++++++++++++++--------
 cogl/cogl-private.h                         |   10 +-
 cogl/cogl-program.c                         |   20 +--
 cogl/cogl-renderer-private.h                |    9 +
 cogl/cogl-renderer.c                        |   80 ++++++++
 cogl/cogl-shader-boilerplate.h              |   27 +--
 cogl/cogl-shader-private.h                  |    2 -
 cogl/cogl-shader.c                          |   89 ++++-----
 cogl/cogl-texture-2d.c                      |   55 +++---
 cogl/cogl-texture-3d.c                      |    4 +-
 cogl/cogl-texture-rectangle.c               |   51 +++---
 cogl/cogl-texture.c                         |   86 ++++----
 cogl/cogl.c                                 |   38 ++--
 cogl/driver/gl/cogl-gl.c                    |    8 +-
 cogl/driver/gles/cogl-gles.c                |   42 ++---
 cogl/driver/gles/cogl-texture-driver-gles.c |    5 +-
 cogl/winsys/cogl-winsys-egl.c               |   37 ++--
 cogl/winsys/cogl-winsys-glx.c               |  277 ++++++++++++++++++--------
 cogl/winsys/cogl-winsys-stub.c              |    4 +-
 cogl/winsys/cogl-winsys-wgl.c               |    7 +-
 configure.ac                                |   90 ++++++---
 48 files changed, 1553 insertions(+), 1107 deletions(-)
---
diff --git a/cogl-pango/Makefile.am b/cogl-pango/Makefile.am
index b57e147..afd96d6 100644
--- a/cogl-pango/Makefile.am
+++ b/cogl-pango/Makefile.am
@@ -40,6 +40,8 @@ INCLUDES = \
 	-DG_DISABLE_SINGLE_INCLUDES	\
 	-DCLUTTER_COMPILATION		\
 	-DG_LOG_DOMAIN=\"CoglPango\"	\
+	-I$(top_srcdir)/cogl		\
+	-I$(top_srcdir)/cogl/winsys	\
 	-I$(top_srcdir)			\
 	-I$(top_builddir)
 
diff --git a/cogl-pango/cogl-pango-display-list.c b/cogl-pango/cogl-pango-display-list.c
index a79cf0f..8440006 100644
--- a/cogl-pango/cogl-pango-display-list.c
+++ b/cogl-pango/cogl-pango-display-list.c
@@ -30,6 +30,7 @@
 #include <string.h>
 
 #include "cogl-pango-display-list.h"
+#include "cogl/cogl-context-private.h"
 
 typedef enum
 {
@@ -265,6 +266,8 @@ emit_rectangles_through_journal (CoglPangoDisplayListNode *node)
 static void
 emit_vertex_buffer_geometry (CoglPangoDisplayListNode *node)
 {
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
   /* It's expensive to go through the Cogl journal for large runs
    * of text in part because the journal transforms the quads in software
    * to avoid changing the modelview matrix. So for larger runs of text
@@ -293,29 +296,27 @@ emit_vertex_buffer_geometry (CoglPangoDisplayListNode *node)
       node->d.texture.vertex_buffer = vb;
     }
 
-
 #ifdef CLUTTER_COGL_HAS_GL
-
-  cogl_vertex_buffer_draw (node->d.texture.vertex_buffer,
-                           GL_QUADS,
-                           0, node->d.texture.verts->len);
-
-#else /* CLUTTER_COGL_HAS_GL */
-  {
-    /* GLES doesn't support GL_QUADS so instead we use a VBO with
-       indexed vertices to generate GL_TRIANGLES from the quads */
-
-    int n_indices = node->d.texture.verts->len / 4 * 6;
-    CoglHandle indices_vbo
-      = cogl_vertex_buffer_indices_get_for_quads (n_indices);
-
-    cogl_vertex_buffer_draw_elements (node->d.texture.vertex_buffer,
-                                      COGL_VERTICES_MODE_TRIANGLES,
-                                      indices_vbo,
-                                      0, node->d.texture.verts->len - 1,
-                                      0, n_indices);
-  }
-#endif /* CLUTTER_COGL_HAS_GL */
+  if (ctx->driver == COGL_DRIVER_GL)
+    cogl_vertex_buffer_draw (node->d.texture.vertex_buffer,
+                             GL_QUADS,
+                             0, node->d.texture.verts->len);
+  else
+#endif
+    {
+      /* GLES doesn't support GL_QUADS so instead we use a VBO with
+         indexed vertices to generate GL_TRIANGLES from the quads */
+
+      int n_indices = node->d.texture.verts->len / 4 * 6;
+      CoglHandle indices_vbo
+        = cogl_vertex_buffer_indices_get_for_quads (n_indices);
+
+      cogl_vertex_buffer_draw_elements (node->d.texture.vertex_buffer,
+                                        COGL_VERTICES_MODE_TRIANGLES,
+                                        indices_vbo,
+                                        0, node->d.texture.verts->len - 1,
+                                        0, n_indices);
+    }
 }
 
 static void
diff --git a/cogl/Makefile.am b/cogl/Makefile.am
index 7e7469c..9d22264 100644
--- a/cogl/Makefile.am
+++ b/cogl/Makefile.am
@@ -28,6 +28,9 @@ AM_CPPFLAGS = \
 	-DG_DISABLE_DEPRECATED		\
 	-DG_LOG_DOMAIN=\"Cogl\" 	\
 	-DCLUTTER_COMPILATION		\
+	-DCOGL_GL_LIBNAME=\"$(COGL_GL_LIBNAME)\" \
+	-DCOGL_GLES1_LIBNAME=\"$(COGL_GLES1_LIBNAME)\" \
+	-DCOGL_GLES2_LIBNAME=\"$(COGL_GLES2_LIBNAME)\" \
 	$(NULL)
 
 AM_CFLAGS = $(COGL_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) $(MAINTAINER_CFLAGS)
@@ -102,20 +105,19 @@ cogl_experimental_h = \
 # driver sources
 cogl_driver_sources =
 
-if COGL_DRIVER_GL
+if COGL_DRIVER_GL_SUPPORTED
 cogl_driver_sources += \
 	$(srcdir)/driver/gl/cogl-gl.c			\
 	$(srcdir)/driver/gl/cogl-texture-driver-gl.c	\
 	$(NULL)
 endif
 
-if COGL_DRIVER_GLES
+if COGL_DRIVER_GLES_SUPPORTED
 cogl_driver_sources += \
 	$(srcdir)/driver/gles/cogl-gles.c			\
 	$(srcdir)/driver/gles/cogl-texture-driver-gles.c	\
 	$(NULL)
-
-endif # COGL_DRIVER_GLES
+endif
 
 # winsys sources, common to all backends
 cogl_winsys_common_sources = \
@@ -387,7 +389,7 @@ libcogl_la_LDFLAGS = \
 	-no-undefined \
 	-version-info @COGL_LT_CURRENT@:@COGL_LT_REVISION@:@COGL_LT_AGE@ \
 	-export-dynamic \
-	-export-symbols-regex "^(cogl|_cogl_debug_flags|_cogl_atlas_new|_cogl_atlas_add_reorganize_callback|_cogl_atlas_reserve_space|_cogl_callback|_cogl_util_get_eye_planes_for_screen_poly|_cogl_atlas_texture_remove_reorganize_callback|_cogl_atlas_texture_add_reorganize_callback|_cogl_texture_foreach_sub_texture_in_region|_cogl_atlas_texture_new_with_size|_cogl_profile_trace_message).*"
+	-export-symbols-regex "^(cogl|_cogl_debug_flags|_cogl_atlas_new|_cogl_atlas_add_reorganize_callback|_cogl_atlas_reserve_space|_cogl_callback|_cogl_util_get_eye_planes_for_screen_poly|_cogl_atlas_texture_remove_reorganize_callback|_cogl_atlas_texture_add_reorganize_callback|_cogl_texture_foreach_sub_texture_in_region|_cogl_atlas_texture_new_with_size|_cogl_profile_trace_message|_cogl_context_get_default).*"
 
 libcogl_la_SOURCES = $(cogl_sources_c)
 nodist_libcogl_la_SOURCES = $(BUILT_SOURCES)
diff --git a/cogl/cogl-attribute.c b/cogl/cogl-attribute.c
index 5970b79..b6e9957 100644
--- a/cogl/cogl-attribute.c
+++ b/cogl/cogl-attribute.c
@@ -47,26 +47,11 @@
 #include <string.h>
 #include <stdio.h>
 
-#if ! defined (HAVE_COGL_GL)
-
-/* GLES doesn't have glDrawRangeElements, so we simply pretend it does
- * but that it makes no use of the start, end constraints: */
-#define glDrawRangeElements(mode, start, end, count, type, indices) \
-  glDrawElements (mode, count, type, indices)
-
 /* This isn't defined in the GLES headers */
 #ifndef GL_UNSIGNED_INT
 #define GL_UNSIGNED_INT 0x1405
 #endif
 
-#ifdef HAVE_COGL_GLES2
-
-#define MAY_HAVE_PROGRAMABLE_GL
-
-#endif /* HAVE_COGL_GLES2 */
-
-#endif
-
 static void _cogl_attribute_free (CoglAttribute *attribute);
 
 COGL_OBJECT_DEFINE (Attribute, attribute);
@@ -412,23 +397,24 @@ toggle_enabled_cb (int bit_num, void *user_data)
 
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
-#ifdef HAVE_COGL_GLES2
-
-  if (enabled)
-    GE( ctx, glEnableVertexAttribArray (bit_num) );
-  else
-    GE( ctx, glDisableVertexAttribArray (bit_num) );
-
-#else /* HAVE_COGL_GLES2 */
-
-  GE( ctx, glClientActiveTexture (GL_TEXTURE0 + bit_num) );
-
-  if (enabled)
-    GE( ctx, glEnableClientState (GL_TEXTURE_COORD_ARRAY) );
+  if (ctx->driver == COGL_DRIVER_GLES2)
+    {
+      if (enabled)
+        GE( ctx, glEnableVertexAttribArray (bit_num) );
+      else
+        GE( ctx, glDisableVertexAttribArray (bit_num) );
+    }
+#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
   else
-    GE( ctx, glDisableClientState (GL_TEXTURE_COORD_ARRAY) );
+    {
+      GE( ctx, glClientActiveTexture (GL_TEXTURE0 + bit_num) );
 
-#endif /* HAVE_COGL_GLES2 */
+      if (enabled)
+        GE( ctx, glEnableClientState (GL_TEXTURE_COORD_ARRAY) );
+      else
+        GE( ctx, glDisableClientState (GL_TEXTURE_COORD_ARRAY) );
+    }
+#endif
 }
 
 static void
@@ -460,9 +446,7 @@ enable_gl_state (CoglDrawFlags flags,
 {
   CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
   int i;
-#ifdef MAY_HAVE_PROGRAMABLE_GL
   GLuint generic_index = 0;
-#endif
   unsigned long enable_flags = 0;
   gboolean skip_gl_color = FALSE;
   CoglPipeline *source;
@@ -591,134 +575,144 @@ enable_gl_state (CoglDrawFlags flags,
         {
         case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
 #ifdef HAVE_COGL_GLES2
-
-          attrib_location =
-            _cogl_pipeline_progend_glsl_get_color_attribute (source);
-          if (attrib_location != -1)
+          if (ctx->driver == COGL_DRIVER_GLES2)
             {
-              GE( ctx,
-                  glVertexAttribPointer (attrib_location,
-                                         attribute->n_components,
-                                         attribute->type,
-                                         TRUE, /* normalize */
-                                         attribute->stride,
-                                         base + attribute->offset) );
-
-              _cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE);
+              attrib_location =
+                _cogl_pipeline_progend_glsl_get_color_attribute (source);
+              if (attrib_location != -1)
+                {
+                  GE( ctx,
+                      glVertexAttribPointer (attrib_location,
+                                             attribute->n_components,
+                                             attribute->type,
+                                             TRUE, /* normalize */
+                                             attribute->stride,
+                                             base + attribute->offset) );
+
+                  _cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE);
+                }
             }
-
-#else
-
-          enable_flags |= COGL_ENABLE_COLOR_ARRAY;
-          /* GE (ctx, glEnableClientState (GL_COLOR_ARRAY)); */
-          GE (ctx, glColorPointer (attribute->n_components,
-                                   attribute->type,
-                                   attribute->stride,
-                                   base + attribute->offset));
-
+          else
 #endif
+            {
+              enable_flags |= COGL_ENABLE_COLOR_ARRAY;
+              /* GE (ctx, glEnableClientState (GL_COLOR_ARRAY)); */
+              GE (ctx, glColorPointer (attribute->n_components,
+                                       attribute->type,
+                                       attribute->stride,
+                                       base + attribute->offset));
+
+            }
 
           break;
         case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY:
 #ifdef HAVE_COGL_GLES2
-
-          attrib_location =
-            _cogl_pipeline_progend_glsl_get_normal_attribute (source);
-          if (attrib_location != -1)
+          if (ctx->driver == COGL_DRIVER_GLES2)
             {
-              GE( ctx,
-                  glVertexAttribPointer (attrib_location,
-                                         attribute->n_components,
-                                         attribute->type,
-                                         TRUE, /* normalize */
-                                         attribute->stride,
-                                         base + attribute->offset) );
-              _cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE);
+              attrib_location =
+                _cogl_pipeline_progend_glsl_get_normal_attribute (source);
+              if (attrib_location != -1)
+                {
+                  GE( ctx,
+                      glVertexAttribPointer (attrib_location,
+                                             attribute->n_components,
+                                             attribute->type,
+                                             TRUE, /* normalize */
+                                             attribute->stride,
+                                             base + attribute->offset) );
+                  _cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE);
+                }
             }
-
-#else
-
-          /* FIXME: go through cogl cache to enable normal array */
-          GE (ctx, glEnableClientState (GL_NORMAL_ARRAY));
-          GE (ctx, glNormalPointer (attribute->type,
-                                    attribute->stride,
-                                    base + attribute->offset));
-
 #endif
+#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
+          if (ctx->driver != COGL_DRIVER_GLES2)
+            {
+              /* FIXME: go through cogl cache to enable normal array */
+              GE (ctx, glEnableClientState (GL_NORMAL_ARRAY));
+              GE (ctx, glNormalPointer (attribute->type,
+                                        attribute->stride,
+                                        base + attribute->offset));
 
+            }
+#endif
           break;
         case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY:
 #ifdef HAVE_COGL_GLES2
-
-          attrib_location = _cogl_pipeline_progend_glsl_get_tex_coord_attribute
-                                             (source, attribute->texture_unit);
-          if (attrib_location != -1)
+          if (ctx->driver == COGL_DRIVER_GLES2)
             {
-              GE( ctx,
-                  glVertexAttribPointer (attrib_location,
-                                         attribute->n_components,
-                                         attribute->type,
-                                         FALSE, /* normalize */
-                                         attribute->stride,
-                                         base + attribute->offset) );
-              _cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE);
+              attrib_location =
+                _cogl_pipeline_progend_glsl_get_tex_coord_attribute
+                (source, attribute->texture_unit);
+              if (attrib_location != -1)
+                {
+                  GE( ctx,
+                      glVertexAttribPointer (attrib_location,
+                                             attribute->n_components,
+                                             attribute->type,
+                                             FALSE, /* normalize */
+                                             attribute->stride,
+                                             base + attribute->offset) );
+                  _cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE);
+                }
             }
-#else
-
-          GE (ctx, glClientActiveTexture (GL_TEXTURE0 +
-                                          attribute->texture_unit));
-          GE (ctx, glTexCoordPointer (attribute->n_components,
-                                      attribute->type,
-                                      attribute->stride,
-                                      base + attribute->offset));
-          _cogl_bitmask_set (&ctx->temp_bitmask,
-                             attribute->texture_unit, TRUE);
-
+          else
 #endif
+            {
+              GE (ctx, glClientActiveTexture (GL_TEXTURE0 +
+                                              attribute->texture_unit));
+              GE (ctx, glTexCoordPointer (attribute->n_components,
+                                          attribute->type,
+                                          attribute->stride,
+                                          base + attribute->offset));
+              _cogl_bitmask_set (&ctx->temp_bitmask,
+                                 attribute->texture_unit, TRUE);
+
+            }
           break;
         case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY:
 #ifdef HAVE_COGL_GLES2
-
-          attrib_location =
-            _cogl_pipeline_progend_glsl_get_position_attribute (source);
-          if (attrib_location != -1)
+          if (ctx->driver == COGL_DRIVER_GLES2)
             {
-              GE( ctx,
-                  glVertexAttribPointer (attrib_location,
-                                         attribute->n_components,
-                                         attribute->type,
-                                         FALSE, /* normalize */
-                                         attribute->stride,
-                                         base + attribute->offset) );
-              _cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE);
+              attrib_location =
+                _cogl_pipeline_progend_glsl_get_position_attribute (source);
+              if (attrib_location != -1)
+                {
+                  GE( ctx,
+                      glVertexAttribPointer (attrib_location,
+                                             attribute->n_components,
+                                             attribute->type,
+                                             FALSE, /* normalize */
+                                             attribute->stride,
+                                             base + attribute->offset) );
+                  _cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE);
+                }
             }
-
-#else
-
-          enable_flags |= COGL_ENABLE_VERTEX_ARRAY;
-          /* GE (ctx, glEnableClientState (GL_VERTEX_ARRAY)); */
-          GE (ctx, glVertexPointer (attribute->n_components,
-                                    attribute->type,
-                                    attribute->stride,
-                                    base + attribute->offset));
-
+          else
 #endif
+            {
+              enable_flags |= COGL_ENABLE_VERTEX_ARRAY;
+              /* GE (ctx, glEnableClientState (GL_VERTEX_ARRAY)); */
+              GE (ctx, glVertexPointer (attribute->n_components,
+                                        attribute->type,
+                                        attribute->stride,
+                                        base + attribute->offset));
+
+            }
           break;
         case COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY:
-          {
-#ifdef MAY_HAVE_PROGRAMABLE_GL
-            /* FIXME: go through cogl cache to enable generic array. */
-            /* FIXME: this is going to end up just using the builtins
-               on GLES 2 */
-            GE (ctx, glEnableVertexAttribArray (generic_index++));
-            GE (ctx, glVertexAttribPointer (generic_index,
-                                            attribute->n_components,
-                                            attribute->type,
-                                            attribute->normalized,
-                                            attribute->stride,
-                                            base + attribute->offset));
-#endif
-          }
+          if (ctx->driver != COGL_DRIVER_GLES1)
+            {
+              /* FIXME: go through cogl cache to enable generic array. */
+              /* FIXME: this is going to end up just using the builtins
+                 on GLES 2 */
+              GE (ctx, glEnableVertexAttribArray (generic_index++));
+              GE (ctx, glVertexAttribPointer (generic_index,
+                                              attribute->n_components,
+                                              attribute->type,
+                                              attribute->normalized,
+                                              attribute->stride,
+                                              base + attribute->offset));
+            }
           break;
         default:
           g_warning ("Unrecognised attribute type 0x%08x", attribute->type);
@@ -752,9 +746,7 @@ disable_gl_state (CoglAttribute **attributes,
                   int n_attributes,
                   CoglPipeline *source)
 {
-#ifdef MAY_HAVE_PROGRAMABLE_GL
   GLuint generic_index = 0;
-#endif
   int i;
 
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
@@ -773,8 +765,9 @@ disable_gl_state (CoglAttribute **attributes,
           break;
         case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY:
           /* FIXME: go through cogl cache to enable normal array */
-#ifndef HAVE_COGL_GLES2
-          GE (ctx, glDisableClientState (GL_NORMAL_ARRAY));
+#if defined(HAVE_COGL_GLES) || defined(HAVE_COGL_GL)
+          if (ctx->driver != COGL_DRIVER_GLES2)
+            GE (ctx, glDisableClientState (GL_NORMAL_ARRAY));
 #endif
           break;
         case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY:
@@ -788,10 +781,9 @@ disable_gl_state (CoglAttribute **attributes,
           /* GE (ctx, glDisableClientState (GL_VERTEX_ARRAY)); */
           break;
         case COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY:
-#ifdef MAY_HAVE_PROGRAMABLE_GL
-          /* FIXME: go through cogl cache to enable generic array */
-          GE (ctx, glDisableVertexAttribArray (generic_index++));
-#endif
+          if (ctx->driver != COGL_DRIVER_GLES1)
+            /* FIXME: go through cogl cache to enable generic array */
+            GE (ctx, glDisableVertexAttribArray (generic_index++));
           break;
         default:
           g_warning ("Unrecognised attribute type 0x%08x", attribute->type);
diff --git a/cogl/cogl-blend-string.c b/cogl/cogl-blend-string.c
index aaba5cf..1eb2a80 100644
--- a/cogl/cogl-blend-string.c
+++ b/cogl/cogl-blend-string.c
@@ -214,32 +214,33 @@ validate_blend_statements (CoglBlendStringStatement *statements,
   const char *error_string;
   CoglBlendStringError detail = COGL_BLEND_STRING_ERROR_INVALID_ERROR;
 
-#ifdef HAVE_COGL_GL
   _COGL_GET_CONTEXT (ctx, 0);
-#endif
 
-#ifdef HAVE_COGL_GL
-  if (n_statements == 2)
+  if (ctx->driver == COGL_DRIVER_GL)
+    {
+      if (n_statements == 2)
+        {
+          /* glBlendEquationSeperate is GL 2.0 only */
+          if (!ctx->glBlendEquationSeparate &&
+              statements[0].function->type != statements[1].function->type)
+            {
+              error_string = "Separate blend functions for the RGB an A "
+                "channels isn't supported by the driver";
+              detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR;
+              goto error;
+            }
+        }
+    }
+  else if (ctx->driver == COGL_DRIVER_GLES1)
     {
-      /* glBlendEquationSeperate is GL 2.0 only */
-      if (!ctx->glBlendEquationSeparate &&
-          statements[0].function->type != statements[1].function->type)
+      if (n_statements != 1)
         {
           error_string = "Separate blend functions for the RGB an A "
-                         "channels isn't supported by the driver";
+            "channels isn't supported by the GLES 1";
           detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR;
           goto error;
         }
     }
-#elif defined(HAVE_COGL_GLES)
-  if (n_statements != 1)
-    {
-      error_string = "Separate blend functions for the RGB an A "
-                     "channels isn't supported by the GLES 1";
-      detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR;
-      goto error;
-    }
-#endif
 
   for (i = 0; i < n_statements; i++)
     for (j = 0; j < statements[i].function->argc; j++)
@@ -261,15 +262,15 @@ validate_blend_statements (CoglBlendStringStatement *statements,
             goto error;
           }
 
-#ifdef HAVE_COGL_GLES
-        if (arg->factor.is_color &&
-            arg->factor.source.info->type == COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT)
+        if (ctx->driver == COGL_DRIVER_GLES1 &&
+            arg->factor.is_color &&
+            (arg->factor.source.info->type ==
+             COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT))
           {
             error_string = "GLES Doesn't support constant blend factors";
             detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR;
             goto error;
           }
-#endif
       }
 
   return TRUE;
diff --git a/cogl/cogl-buffer.c b/cogl/cogl-buffer.c
index 207b170..7a6c77a 100644
--- a/cogl/cogl-buffer.c
+++ b/cogl/cogl-buffer.c
@@ -316,33 +316,25 @@ _cogl_buffer_access_to_gl_enum (CoglBufferAccess access)
     return GL_READ_ONLY;
 }
 
-/* OpenGL ES 1.1 and 2 only know about STATIC_DRAW and DYNAMIC_DRAW */
-#if defined (COGL_HAS_GLES)
-GLenum
-_cogl_buffer_hints_to_gl_enum (CoglBufferUsageHint usage_hint,
-                               CoglBufferUpdateHint update_hint)
-{
-  /* usage hint is always TEXTURE for now */
-  if (update_hint == COGL_BUFFER_UPDATE_HINT_STATIC)
-      return GL_STATIC_DRAW;
-  return GL_DYNAMIC_DRAW;
-}
-#else
 GLenum
 _cogl_buffer_hints_to_gl_enum (CoglBufferUsageHint  usage_hint,
                                CoglBufferUpdateHint update_hint)
 {
+  _COGL_GET_CONTEXT (ctx, 0);
+
   /* usage hint is always TEXTURE for now */
   if (update_hint == COGL_BUFFER_UPDATE_HINT_STATIC)
     return GL_STATIC_DRAW;
   if (update_hint == COGL_BUFFER_UPDATE_HINT_DYNAMIC)
     return GL_DYNAMIC_DRAW;
+  /* OpenGL ES 1.1 and 2 only know about STATIC_DRAW and DYNAMIC_DRAW */
+#ifdef HAVE_COGL_GL
   if (update_hint == COGL_BUFFER_UPDATE_HINT_STREAM)
     return GL_STREAM_DRAW;
+#endif
 
   return GL_STATIC_DRAW;
 }
-#endif
 
 void *
 _cogl_buffer_bind (CoglBuffer *buffer, CoglBufferBindTarget target)
diff --git a/cogl/cogl-clip-stack.c b/cogl/cogl-clip-stack.c
index c599cfd..7663bb4 100644
--- a/cogl/cogl-clip-stack.c
+++ b/cogl/cogl-clip-stack.c
@@ -71,11 +71,8 @@ set_clip_plane (GLint plane_num,
 		const float *vertex_a,
 		const float *vertex_b)
 {
-#if defined (HAVE_COGL_GLES2) || defined (HAVE_COGL_GLES)
-  GLfloat plane[4];
-#else
-  GLdouble plane[4];
-#endif
+  GLfloat planef[4];
+  double planed[4];
   GLfloat angle;
   CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
   CoglMatrixStack *modelview_stack =
@@ -110,17 +107,29 @@ set_clip_plane (GLint plane_num,
 
   _cogl_matrix_stack_flush_to_gl (modelview_stack, COGL_MATRIX_MODELVIEW);
 
-  plane[0] = 0;
-  plane[1] = -1.0;
-  plane[2] = 0;
-  plane[3] = vertex_a[1];
-#if defined (HAVE_COGL_GLES2)
-  g_assert_not_reached ();
-#elif defined (HAVE_COGL_GLES)
-  GE( ctx, glClipPlanef (plane_num, plane) );
-#else
-  GE( ctx, glClipPlane (plane_num, plane) );
-#endif
+  planef[0] = 0;
+  planef[1] = -1.0;
+  planef[2] = 0;
+  planef[3] = vertex_a[1];
+
+  switch (ctx->driver)
+    {
+    default:
+      g_assert_not_reached ();
+      break;
+
+    case COGL_DRIVER_GLES1:
+      GE( ctx, glClipPlanef (plane_num, planef) );
+      break;
+
+    case COGL_DRIVER_GL:
+      planed[0] = planef[0];
+      planed[1] = planef[1];
+      planed[2] = planef[2];
+      planed[3] = planef[3];
+      GE( ctx, glClipPlane (plane_num, planed) );
+      break;
+    }
 
   _cogl_matrix_stack_pop (modelview_stack);
 }
diff --git a/cogl/cogl-context-private.h b/cogl/cogl-context-private.h
index 87b0d6c..8ffcba1 100644
--- a/cogl/cogl-context-private.h
+++ b/cogl/cogl-context-private.h
@@ -56,6 +56,8 @@ struct _CoglContext
 
   CoglDisplay *display;
 
+  CoglDriver driver;
+
   /* vtable for the texture driver functions */
   const CoglTextureDriver *texture_driver;
 
@@ -86,10 +88,8 @@ struct _CoglContext
      API. We keep track of the matrix stack that Cogl is trying to
      flush so we can flush it later after the program is generated. A
      reference is taken on the stacks. */
-#ifdef HAVE_COGL_GLES2
   CoglMatrixStack  *flushed_modelview_stack;
   CoglMatrixStack  *flushed_projection_stack;
-#endif /* HAVE_COGL_GLES2 */
 
   GArray           *texture_units;
   int               active_texture_unit;
@@ -287,6 +287,18 @@ _cogl_context_get_default ();
 const CoglWinsysVtable *
 _cogl_context_get_winsys (CoglContext *context);
 
+/* Check whether the current GL context is supported by Cogl */
+gboolean
+_cogl_context_check_gl_version (CoglContext *context,
+                                GError **error);
+
+/* 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_context_update_features (CoglContext *context);
+
 /* Obtains the context and returns retval if NULL */
 #define _COGL_GET_CONTEXT(ctxvar, retval) \
 CoglContext *ctxvar = _cogl_context_get_default (); \
diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c
index 7a70797..0981e0d 100644
--- a/cogl/cogl-context.c
+++ b/cogl/cogl-context.c
@@ -54,8 +54,12 @@
 #define GL_POINT_SPRITE 0x8861
 #endif
 
+#ifdef HAVE_COGL_GL
 extern const CoglTextureDriver _cogl_texture_driver_gl;
+#endif
+#if defined (HAVE_COGL_GLES) || defined (HAVE_COGL_GLES2)
 extern const CoglTextureDriver _cogl_texture_driver_gles;
+#endif
 
 static void _cogl_context_free (CoglContext *context);
 
@@ -168,6 +172,11 @@ cogl_context_new (CoglDisplay *display,
 
   context->display = display;
 
+  /* This is duplicated data, but it's much more convenient to have
+     the driver attached to the context and the value is accessed a
+     lot throughout Cogl */
+  context->driver = display->renderer->driver;
+
   winsys = _cogl_context_get_winsys (context);
   if (!winsys->context_init (context, error))
     {
@@ -176,12 +185,25 @@ cogl_context_new (CoglDisplay *display,
       return NULL;
     }
 
+  switch (context->driver)
+    {
 #ifdef HAVE_COGL_GL
-  context->texture_driver = &_cogl_texture_driver_gl;
-#else
-  context->texture_driver = &_cogl_texture_driver_gles;
+    case COGL_DRIVER_GL:
+      context->texture_driver = &_cogl_texture_driver_gl;
+      break;
+#endif
+
+#if defined (HAVE_COGL_GLES) || defined (HAVE_COGL_GLES2)
+    case COGL_DRIVER_GLES1:
+    case COGL_DRIVER_GLES2:
+      context->texture_driver = &_cogl_texture_driver_gles;
+      break;
 #endif
 
+    default:
+      g_assert_not_reached ();
+    }
+
   /* Initialise the driver specific state */
   _cogl_init_feature_overrides (context);
 
@@ -308,14 +330,15 @@ cogl_context_new (CoglDisplay *display,
   context->texture_download_pipeline = COGL_INVALID_HANDLE;
   context->blit_texture_pipeline = COGL_INVALID_HANDLE;
 
-#ifndef HAVE_COGL_GLES2
-  /* The default for GL_ALPHA_TEST is to always pass which is equivalent to
-   * the test being disabled therefore we assume that for all drivers there
-   * will be no performance impact if we always leave the test enabled which
-   * makes things a bit simpler for us. Under GLES2 the alpha test is
-   * implemented in the fragment shader so there is no enable for it
-   */
-  GE (context, glEnable (GL_ALPHA_TEST));
+#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
+  if (context->driver != COGL_DRIVER_GLES2)
+    /* The default for GL_ALPHA_TEST is to always pass which is equivalent to
+     * the test being disabled therefore we assume that for all drivers there
+     * will be no performance impact if we always leave the test enabled which
+     * makes things a bit simpler for us. Under GLES2 the alpha test is
+     * implemented in the fragment shader so there is no enable for it
+     */
+    GE (context, glEnable (GL_ALPHA_TEST));
 #endif
 
 #ifdef HAVE_COGL_GLES2
@@ -361,10 +384,9 @@ cogl_context_new (CoglDisplay *display,
      each pipeline to track whether any layers have point sprite
      coords enabled. We don't need to do this for GLES2 because point
      sprites are handled using a builtin varying in the shader. */
-#ifndef HAVE_COGL_GLES2
-  if (cogl_features_available (COGL_FEATURE_POINT_SPRITE))
+  if (_context->driver != COGL_DRIVER_GLES2 &&
+      cogl_features_available (COGL_FEATURE_POINT_SPRITE))
     GE (context, glEnable (GL_POINT_SPRITE));
-#endif
 
   return _cogl_context_object_new (context);
 }
@@ -499,3 +521,37 @@ cogl_context_egl_get_egl_display (CoglContext *context)
 }
 #endif
 
+gboolean
+_cogl_context_check_gl_version (CoglContext *context,
+                                GError **error)
+{
+#ifdef HAVE_COGL_GL
+  if (context->driver == COGL_DRIVER_GL)
+    return _cogl_gl_check_gl_version (context, error);
+#endif
+
+#if defined(HAVE_COGL_GLES) || defined(HAVE_COGL_GLES2)
+  return _cogl_gles_check_gl_version (context, error);
+#endif
+
+  g_assert_not_reached ();
+}
+
+void
+_cogl_context_update_features (CoglContext *context)
+{
+#ifdef HAVE_COGL_GL
+  if (context->driver == COGL_DRIVER_GL)
+    {
+      _cogl_gl_update_features (context);
+      return;
+    }
+#endif
+
+#if defined(HAVE_COGL_GLES) || defined(HAVE_COGL_GLES2)
+  _cogl_gles_update_features (context);
+  return;
+#endif
+
+  g_assert_not_reached ();
+}
diff --git a/cogl/cogl-display-private.h b/cogl/cogl-display-private.h
index 2411855..2db5d55 100644
--- a/cogl/cogl-display-private.h
+++ b/cogl/cogl-display-private.h
@@ -29,6 +29,7 @@
 #include "cogl-display.h"
 #include "cogl-renderer.h"
 #include "cogl-onscreen-template.h"
+#include "cogl-internal.h"
 #if COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT
 #include <wayland-server.h>
 #endif
diff --git a/cogl/cogl-display.c b/cogl/cogl-display.c
index a0e37a2..db0d7cd 100644
--- a/cogl/cogl-display.c
+++ b/cogl/cogl-display.c
@@ -28,9 +28,12 @@
 #include "config.h"
 #endif
 
+#include <string.h>
+
 #include "cogl.h"
 #include "cogl-private.h"
 #include "cogl-object.h"
+#include "cogl-internal.h"
 
 #include "cogl-display-private.h"
 #include "cogl-renderer-private.h"
diff --git a/cogl/cogl-ext-functions.h b/cogl/cogl-ext-functions.h
index 2a85687..45dc669 100644
--- a/cogl/cogl-ext-functions.h
+++ b/cogl/cogl-ext-functions.h
@@ -563,19 +563,6 @@ COGL_EXT_FUNCTION (GLboolean, glUnmapBuffer,
                    (GLenum		 target))
 COGL_EXT_END ()
 
-COGL_EXT_BEGIN (draw_range_elements, 1, 2,
-                0, /* not in either GLES */
-                "\0",
-                "\0")
-COGL_EXT_FUNCTION (void, glDrawRangeElements,
-                   (GLenum                mode,
-                    GLuint                start,
-                    GLuint                end,
-                    GLsizei               count,
-                    GLenum                type,
-                    const GLvoid         *indices))
-COGL_EXT_END ()
-
 COGL_EXT_BEGIN (blending, 1, 2,
                 COGL_EXT_IN_GLES2,
                 "\0",
diff --git a/cogl/cogl-feature-private.c b/cogl/cogl-feature-private.c
index 27c806c..053bd02 100644
--- a/cogl/cogl-feature-private.c
+++ b/cogl/cogl-feature-private.c
@@ -38,7 +38,7 @@ _cogl_feature_check (const CoglWinsysVtable *winsys,
                      const CoglFeatureData *data,
                      int gl_major,
                      int gl_minor,
-                     CoglExtGlesAvailability gles_version,
+                     CoglDriver driver,
                      const char *extensions_string,
                      void *function_table)
 
@@ -48,9 +48,13 @@ _cogl_feature_check (const CoglWinsysVtable *winsys,
 
   /* First check whether the functions should be directly provided by
      GL */
-  if (COGL_CHECK_GL_VERSION (gl_major, gl_minor,
-                             data->min_gl_major, data->min_gl_minor) ||
-      (gles_version & data->gles_availability))
+  if ((driver == COGL_DRIVER_GL &&
+       COGL_CHECK_GL_VERSION (gl_major, gl_minor,
+                              data->min_gl_major, data->min_gl_minor)) ||
+      (driver == COGL_DRIVER_GLES1 &&
+       (data->gles_availability & COGL_EXT_IN_GLES)) ||
+      (driver == COGL_DRIVER_GLES2 &&
+       (data->gles_availability & COGL_EXT_IN_GLES2)))
     suffix = "";
   else
     {
@@ -180,15 +184,14 @@ void
 _cogl_feature_check_ext_functions (CoglContext *context,
                                    int gl_major,
                                    int gl_minor,
-                                   const char *gl_extensions,
-                                   CoglExtGlesAvailability gles_version)
+                                   const char *gl_extensions)
 {
   int i;
 
   for (i = 0; i < G_N_ELEMENTS (cogl_feature_ext_functions_data); i++)
     _cogl_feature_check (_cogl_context_get_winsys (context),
                          "GL", cogl_feature_ext_functions_data + i,
-                         gl_major, gl_minor, gles_version,
+                         gl_major, gl_minor, context->driver,
                          gl_extensions,
                          context);
 }
diff --git a/cogl/cogl-feature-private.h b/cogl/cogl-feature-private.h
index b90897b..1cf3eed 100644
--- a/cogl/cogl-feature-private.h
+++ b/cogl/cogl-feature-private.h
@@ -86,7 +86,7 @@ _cogl_feature_check (const CoglWinsysVtable *winsys,
                      const CoglFeatureData *data,
                      int gl_major,
                      int gl_minor,
-                     CoglExtGlesAvailability gles_version,
+                     CoglDriver driver,
                      const char *extensions_string,
                      void *function_table);
 
@@ -94,7 +94,6 @@ void
 _cogl_feature_check_ext_functions (CoglContext *context,
                                    int gl_major,
                                    int gl_minor,
-                                   const char *gl_extensions,
-                                   CoglExtGlesAvailability gles_version);
+                                   const char *gl_extensions);
 
 #endif /* __COGL_FEATURE_PRIVATE_H */
diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c
index d5b4ad4..7cf6048 100644
--- a/cogl/cogl-framebuffer.c
+++ b/cogl/cogl-framebuffer.c
@@ -615,8 +615,9 @@ _cogl_framebuffer_init_bits (CoglFramebuffer *framebuffer)
     return;
 
 #ifdef HAVE_COGL_GL
-  if (cogl_features_available (COGL_FEATURE_OFFSCREEN)
-      && framebuffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN)
+  if (ctx->driver == COGL_DRIVER_GL &&
+      cogl_features_available (COGL_FEATURE_OFFSCREEN) &&
+      framebuffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN)
     {
       GLenum attachment, pname;
 
@@ -812,6 +813,8 @@ _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;
 
@@ -866,7 +869,8 @@ _cogl_offscreen_new_to_texture_full (CoglHandle texhandle,
       if ((have_working_flags &&
            try_creating_fbo (offscreen, flags, &data)) ||
 #ifdef HAVE_COGL_GL
-          try_creating_fbo (offscreen, flags = _TRY_DEPTH_STENCIL, &data) ||
+          (ctx->driver == COGL_DRIVER_GL &&
+           try_creating_fbo (offscreen, flags = _TRY_DEPTH_STENCIL, &data)) ||
 #endif
           try_creating_fbo (offscreen, flags = _TRY_DEPTH | _TRY_STENCIL,
                             &data) ||
diff --git a/cogl/cogl-glx-renderer-private.h b/cogl/cogl-glx-renderer-private.h
index 37dc452..1016235 100644
--- a/cogl/cogl-glx-renderer-private.h
+++ b/cogl/cogl-glx-renderer-private.h
@@ -25,6 +25,7 @@
 #ifndef __COGL_RENDERER_GLX_PRIVATE_H
 #define __COGL_RENDERER_GLX_PRIVATE_H
 
+#include <gmodule.h>
 #include "cogl-object-private.h"
 #include "cogl-xlib-renderer-private.h"
 
@@ -43,6 +44,56 @@ typedef struct _CoglGLXRenderer
   /* Vblank stuff */
   int dri_fd;
 
+  /* GModule pointing to libGL which we use to get glX functions out of */
+  GModule *libgl_module;
+
+  /* Function pointers for core GLX functionality. We can't just link
+     against these directly because we need to conditionally load
+     libGL when we are using GLX so that it won't conflict with a GLES
+     library if we are using EGL + GLES */
+  void
+  (* glXDestroyContext) (Display *dpy, GLXContext ctx);
+  void
+  (* glXSwapBuffers) (Display *dpy, GLXDrawable drawable);
+  Bool
+  (* glXQueryExtension) (Display *dpy, int *errorb, int *event);
+  const char *
+  (* glXQueryExtensionsString) (Display *dpy, int screen);
+  Bool
+  (* glXQueryVersion) (Display *dpy, int *maj, int *min);
+  Bool
+  (* glXIsDirect) (Display *dpy, GLXContext ctx);
+  int
+  (* glXGetFBConfigAttrib) (Display *dpy, GLXFBConfig config,
+                            int attribute, int *value);
+  GLXWindow
+  (* glXCreateWindow) (Display *dpy, GLXFBConfig config,
+                       Window win, const int *attribList);
+  void
+  (* glXDestroyWindow) (Display *dpy, GLXWindow window);
+  GLXPixmap
+  (* glXCreatePixmap) (Display *dpy, GLXFBConfig config,
+                       Pixmap pixmap, const int *attribList);
+  void
+  (* glXDestroyPixmap) (Display *dpy, GLXPixmap pixmap);
+  GLXContext
+  (* glXCreateNewContext) (Display *dpy, GLXFBConfig config,
+                           int renderType, GLXContext shareList,
+                           Bool direct);
+  Bool
+  (* glXMakeContextCurrent) (Display *dpy, GLXDrawable draw,
+                             GLXDrawable read, GLXContext ctx);
+  void
+  (* glXSelectEvent) (Display *dpy, GLXDrawable drawable,
+                      unsigned long mask);
+  GLXFBConfig *
+  (* glXGetFBConfigs) (Display *dpy, int screen, int *nelements);
+  GLXFBConfig *
+  (* glXChooseFBConfig) (Display *dpy, int screen,
+                         const int *attrib_list, int *nelements);
+  XVisualInfo *
+  (* glXGetVisualFromFBConfig) (Display *dpy, GLXFBConfig config);
+
   /* Function pointers for GLX specific extensions */
 #define COGL_WINSYS_FEATURE_BEGIN(a, b, c, d, e, f)
 
diff --git a/cogl/cogl-internal.h b/cogl/cogl-internal.h
index 71e5766..022ea32 100644
--- a/cogl/cogl-internal.h
+++ b/cogl/cogl-internal.h
@@ -123,11 +123,20 @@ _cogl_transform_point (const CoglMatrix *matrix_mv,
 
 typedef enum { /*< prefix=COGL_DRIVER_ERROR >*/
   COGL_DRIVER_ERROR_UNKNOWN_VERSION,
-  COGL_DRIVER_ERROR_INVALID_VERSION
+  COGL_DRIVER_ERROR_INVALID_VERSION,
+  COGL_DRIVER_ERROR_NO_SUITABLE_DRIVER_FOUND,
+  COGL_DRIVER_ERROR_FAILED_TO_LOAD_LIBRARY
 } CoglDriverError;
 
 typedef enum
 {
+  COGL_DRIVER_GL,
+  COGL_DRIVER_GLES1,
+  COGL_DRIVER_GLES2
+} CoglDriver;
+
+typedef enum
+{
   COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE = 1L<<0,
 } CoglPrivateFeatureFlags;
 
diff --git a/cogl/cogl-journal.c b/cogl/cogl-journal.c
index 755584b..9f073d3 100644
--- a/cogl/cogl-journal.c
+++ b/cogl/cogl-journal.c
@@ -102,10 +102,10 @@ typedef struct _CoglJournalFlushState
   gsize                stride;
   size_t               array_offset;
   GLuint               current_vertex;
-#ifndef HAVE_COGL_GL
+
   CoglIndices         *indices;
   gsize                indices_type_size;
-#endif
+
   CoglMatrixStack     *modelview_stack;
   CoglMatrixStack     *projection_stack;
 
@@ -301,35 +301,38 @@ _cogl_journal_flush_modelview_and_entries (CoglJournalEntry *batch_start,
     draw_flags |= COGL_DRAW_COLOR_ATTRIBUTE_IS_OPAQUE;
 
 #ifdef HAVE_COGL_GL
-
-  /* XXX: it's rather evil that we sneak in the GL_QUADS enum here... */
-  _cogl_draw_attributes (GL_QUADS,
-                         state->current_vertex, batch_len * 4,
-                         attributes,
-                         state->attributes->len,
-                         draw_flags);
-
-#else /* HAVE_COGL_GL */
-  if (batch_len > 1)
+  if (ctx->driver == COGL_DRIVER_GL)
     {
-      _cogl_draw_indexed_attributes (COGL_VERTICES_MODE_TRIANGLES,
-                                     state->current_vertex * 6 / 4,
-                                     batch_len * 6,
-                                     state->indices,
-                                     attributes,
-                                     state->attributes->len,
-                                     draw_flags);
-
-    }
-  else
-    {
-      _cogl_draw_attributes (COGL_VERTICES_MODE_TRIANGLE_FAN,
-                             state->current_vertex, 4,
+      /* XXX: it's rather evil that we sneak in the GL_QUADS enum here... */
+      _cogl_draw_attributes (GL_QUADS,
+                             state->current_vertex, batch_len * 4,
                              attributes,
                              state->attributes->len,
                              draw_flags);
     }
-#endif
+  else
+#endif /* HAVE_COGL_GL */
+    {
+      if (batch_len > 1)
+        {
+          _cogl_draw_indexed_attributes (COGL_VERTICES_MODE_TRIANGLES,
+                                         state->current_vertex * 6 / 4,
+                                         batch_len * 6,
+                                         state->indices,
+                                         attributes,
+                                         state->attributes->len,
+                                         draw_flags);
+
+        }
+      else
+        {
+          _cogl_draw_attributes (COGL_VERTICES_MODE_TRIANGLE_FAN,
+                                 state->current_vertex, 4,
+                                 attributes,
+                                 state->attributes->len,
+                                 draw_flags);
+        }
+    }
 
   /* DEBUGGING CODE XXX: This path will cause all rectangles to be
    * drawn with a coloured outline. Each batch will be rendered with
@@ -619,9 +622,8 @@ _cogl_journal_flush_vbo_offsets_and_entries (CoglJournalEntry *batch_start,
                         4,
                         COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
 
-#ifndef HAVE_COGL_GL
-  state->indices = cogl_get_rectangle_indices (batch_len);
-#endif
+  if (ctx->driver != COGL_DRIVER_GL)
+    state->indices = cogl_get_rectangle_indices (batch_len);
 
   /* We only create new Attributes when the stride within the
    * AttributeBuffer changes. (due to a change in the number of pipeline
diff --git a/cogl/cogl-matrix-stack.c b/cogl/cogl-matrix-stack.c
index d761b53..09aa002 100644
--- a/cogl/cogl-matrix-stack.c
+++ b/cogl/cogl-matrix-stack.c
@@ -393,7 +393,7 @@ _cogl_matrix_stack_set (CoglMatrixStack  *stack,
   stack->age++;
 }
 
-#ifndef HAVE_COGL_GLES2
+#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
 
 static void
 flush_to_fixed_api_gl (gboolean is_identity,
@@ -417,7 +417,7 @@ flush_to_fixed_api_gl (gboolean is_identity,
     }
 }
 
-#endif /* HAVE_COGL_GLES2 */
+#endif
 
 void
 _cogl_matrix_stack_prepare_for_flush (CoglMatrixStack *stack,
@@ -462,72 +462,74 @@ _cogl_matrix_stack_flush_to_gl (CoglMatrixStack *stack,
 
   state = _cogl_matrix_stack_top (stack);
 
-#ifdef HAVE_COGL_GLES2
-
-  /* Under GLES2 we need to flush the matrices differently because
-     they are stored in uniforms attached to the program instead of
-     the global GL context state. At this point we can't be sure that
-     the right program will be generated so instead we'll just store a
-     reference to the matrix stack that is intended to be flushed and
-     update the uniform once the program is ready. */
-
-  switch (mode)
+  if (ctx->driver == COGL_DRIVER_GLES2)
     {
-    case COGL_MATRIX_MODELVIEW:
-      cogl_object_ref (stack);
-      if (ctx->flushed_modelview_stack)
-        cogl_object_unref (ctx->flushed_modelview_stack);
-      ctx->flushed_modelview_stack = stack;
-      break;
-
-    case COGL_MATRIX_PROJECTION:
-      cogl_object_ref (stack);
-      if (ctx->flushed_projection_stack)
-        cogl_object_unref (ctx->flushed_projection_stack);
-      ctx->flushed_projection_stack = stack;
-      break;
-
-    case COGL_MATRIX_TEXTURE:
-      /* This shouldn't happen because the texture matrices are
-         handled by the GLSL pipeline backend */
-      g_assert_not_reached ();
-      break;
-    }
-
-#else /* HAVE_COGL_GLES2 */
-
-  if (stack->flushed_state == state)
-    return;
-
-  if (ctx->flushed_matrix_mode != mode)
-    {
-      GLenum gl_mode = 0;
+      /* Under GLES2 we need to flush the matrices differently because
+         they are stored in uniforms attached to the program instead of
+         the global GL context state. At this point we can't be sure that
+         the right program will be generated so instead we'll just store a
+         reference to the matrix stack that is intended to be flushed and
+         update the uniform once the program is ready. */
 
       switch (mode)
         {
         case COGL_MATRIX_MODELVIEW:
-          gl_mode = GL_MODELVIEW;
+          cogl_object_ref (stack);
+          if (ctx->flushed_modelview_stack)
+            cogl_object_unref (ctx->flushed_modelview_stack);
+          ctx->flushed_modelview_stack = stack;
           break;
 
         case COGL_MATRIX_PROJECTION:
-          gl_mode = GL_PROJECTION;
+          cogl_object_ref (stack);
+          if (ctx->flushed_projection_stack)
+            cogl_object_unref (ctx->flushed_projection_stack);
+          ctx->flushed_projection_stack = stack;
           break;
 
         case COGL_MATRIX_TEXTURE:
-          gl_mode = GL_TEXTURE;
+          /* This shouldn't happen because the texture matrices are
+             handled by the GLSL pipeline backend */
+          g_assert_not_reached ();
           break;
         }
-
-      GE (ctx, glMatrixMode (gl_mode));
-      ctx->flushed_matrix_mode = mode;
     }
 
-  _cogl_matrix_stack_prepare_for_flush (stack,
-                                        mode,
-                                        flush_to_fixed_api_gl,
-                                        stack);
+#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
+  else
+    {
+      if (stack->flushed_state == state)
+        return;
+
+      if (ctx->flushed_matrix_mode != mode)
+        {
+          GLenum gl_mode = 0;
+
+          switch (mode)
+            {
+            case COGL_MATRIX_MODELVIEW:
+              gl_mode = GL_MODELVIEW;
+              break;
+
+            case COGL_MATRIX_PROJECTION:
+              gl_mode = GL_PROJECTION;
+              break;
 
-#endif /* HAVE_COGL_GLES2 */
+            case COGL_MATRIX_TEXTURE:
+              gl_mode = GL_TEXTURE;
+              break;
+            }
+
+          GE (ctx, glMatrixMode (gl_mode));
+          ctx->flushed_matrix_mode = mode;
+        }
+
+      _cogl_matrix_stack_prepare_for_flush (stack,
+                                            mode,
+                                            flush_to_fixed_api_gl,
+                                            stack);
+    }
+#endif
 
   stack->flushed_state = state;
 }
diff --git a/cogl/cogl-pipeline-fragend-arbfp.c b/cogl/cogl-pipeline-fragend-arbfp.c
index ef07357..3f24edb 100644
--- a/cogl/cogl-pipeline-fragend-arbfp.c
+++ b/cogl/cogl-pipeline-fragend-arbfp.c
@@ -225,9 +225,9 @@ _cogl_pipeline_fragend_arbfp_start (CoglPipeline *pipeline,
    */
   authority = _cogl_pipeline_find_equivalent_parent
     (pipeline,
-     COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN &
+     _cogl_pipeline_get_state_for_fragment_codegen (ctx) &
      ~COGL_PIPELINE_STATE_LAYERS,
-     COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN);
+     _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx));
   authority_priv = get_arbfp_priv (authority);
   if (authority_priv &&
       authority_priv->arbfp_program_state)
@@ -318,12 +318,18 @@ _cogl_pipeline_fragend_arbfp_start (CoglPipeline *pipeline,
 unsigned int
 _cogl_pipeline_fragend_arbfp_hash (const void *data)
 {
-  unsigned long fragment_state =
-    COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN;
-  unsigned long layer_fragment_state =
-    COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN;
+  unsigned int fragment_state;
+  unsigned int layer_fragment_state;
+
+  _COGL_GET_CONTEXT (ctx, 0);
+
+  fragment_state =
+    _cogl_pipeline_get_state_for_fragment_codegen (ctx);
+  layer_fragment_state =
+    _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx);
 
   return _cogl_pipeline_hash ((CoglPipeline *)data,
+
                               fragment_state, layer_fragment_state,
                               0);
 }
@@ -331,10 +337,15 @@ _cogl_pipeline_fragend_arbfp_hash (const void *data)
 gboolean
 _cogl_pipeline_fragend_arbfp_equal (const void *a, const void *b)
 {
-  unsigned long fragment_state =
-    COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN;
-  unsigned long layer_fragment_state =
-    COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN;
+  unsigned int fragment_state;
+  unsigned int layer_fragment_state;
+
+  _COGL_GET_CONTEXT (ctx, 0);
+
+  fragment_state =
+    _cogl_pipeline_get_state_for_fragment_codegen (ctx);
+  layer_fragment_state =
+    _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx);
 
   return _cogl_pipeline_equal ((CoglPipeline *)a, (CoglPipeline *)b,
                                fragment_state, layer_fragment_state,
@@ -344,12 +355,9 @@ _cogl_pipeline_fragend_arbfp_equal (const void *a, const void *b)
 static const char *
 gl_target_to_arbfp_string (GLenum gl_target)
 {
-#ifndef HAVE_COGL_GLES2
   if (gl_target == GL_TEXTURE_1D)
     return "1D";
-  else
-#endif
-    if (gl_target == GL_TEXTURE_2D)
+  else if (gl_target == GL_TEXTURE_2D)
     return "2D";
 #ifdef GL_ARB_texture_rectangle
   else if (gl_target == GL_TEXTURE_RECTANGLE_ARB)
@@ -1028,7 +1036,9 @@ _cogl_pipeline_fragend_arbfp_pipeline_pre_change_notify (
                                                    CoglPipelineState change,
                                                    const CoglColor *new_color)
 {
-  if ((change & COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN))
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+  if ((change & _cogl_pipeline_get_state_for_fragment_codegen (ctx)))
     dirty_arbfp_program_state (pipeline);
 }
 
@@ -1047,10 +1057,13 @@ _cogl_pipeline_fragend_arbfp_layer_pre_change_notify (
                                                 CoglPipelineLayerState change)
 {
   CoglPipelineFragendARBfpPrivate *priv = get_arbfp_priv (owner);
+
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
   if (!priv)
     return;
 
-  if ((change & COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN))
+  if ((change & _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx)))
     {
       dirty_arbfp_program_state (owner);
       return;
diff --git a/cogl/cogl-pipeline-fragend-fixed.c b/cogl/cogl-pipeline-fragend-fixed.c
index ebd2ec8..97fe043 100644
--- a/cogl/cogl-pipeline-fragend-fixed.c
+++ b/cogl/cogl-pipeline-fragend-fixed.c
@@ -92,9 +92,14 @@ _cogl_pipeline_fragend_fixed_start (CoglPipeline *pipeline,
 {
   CoglHandle user_program;
 
+  _COGL_GET_CONTEXT (ctx, FALSE);
+
   if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_FIXED)))
     return FALSE;
 
+  if (ctx->driver == COGL_DRIVER_GLES2)
+    return FALSE;
+
   /* If there is a user program with a fragment shader then the
      appropriate backend for that language should handle it. We can
      still use the fixed fragment backend if the program only contains
@@ -319,20 +324,19 @@ _cogl_pipeline_fragend_fixed_end (CoglPipeline *pipeline,
 
           GE (ctx, glFogfv (GL_FOG_COLOR, fogColor));
 
-#if HAVE_COGL_GLES
-          switch (fog_state->mode)
-            {
-            case COGL_FOG_MODE_LINEAR:
-              gl_mode = GL_LINEAR;
-              break;
-            case COGL_FOG_MODE_EXPONENTIAL:
-              gl_mode = GL_EXP;
-              break;
-            case COGL_FOG_MODE_EXPONENTIAL_SQUARED:
-              gl_mode = GL_EXP2;
-              break;
-            }
-#endif
+          if (ctx->driver == COGL_DRIVER_GLES1)
+            switch (fog_state->mode)
+              {
+              case COGL_FOG_MODE_LINEAR:
+                gl_mode = GL_LINEAR;
+                break;
+              case COGL_FOG_MODE_EXPONENTIAL:
+                gl_mode = GL_EXP;
+                break;
+              case COGL_FOG_MODE_EXPONENTIAL_SQUARED:
+                gl_mode = GL_EXP2;
+                break;
+              }
           /* TODO: support other modes for GLES2 */
 
           /* NB: GLES doesn't have glFogi */
diff --git a/cogl/cogl-pipeline-fragend-glsl.c b/cogl/cogl-pipeline-fragend-glsl.c
index a0787c4..32b355d 100644
--- a/cogl/cogl-pipeline-fragend-glsl.c
+++ b/cogl/cogl-pipeline-fragend-glsl.c
@@ -227,9 +227,9 @@ _cogl_pipeline_fragend_glsl_start (CoglPipeline *pipeline,
        */
       authority = _cogl_pipeline_find_equivalent_parent
         (pipeline,
-         COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN &
+         _cogl_pipeline_get_state_for_fragment_codegen (ctx) &
          ~COGL_PIPELINE_STATE_LAYERS,
-         COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN);
+         _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx));
 
       authority_priv = get_glsl_priv (authority);
       if (!authority_priv)
@@ -339,6 +339,8 @@ add_texture_lookup (GlslShaderState *glsl_shader_state,
   int unit_index = _cogl_pipeline_layer_get_unit_index (layer);
   const char *target_string, *tex_coord_swizzle;
 
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
   if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_TEXTURING)))
     {
       g_string_append (glsl_shader_state->source,
@@ -362,7 +364,7 @@ add_texture_lookup (GlslShaderState *glsl_shader_state,
       cogl_texture_get_gl_texture (texture, NULL, &gl_target);
       switch (gl_target)
         {
-#ifndef HAVE_COGL_GLES2
+#ifdef HAVE_COGL_GL
         case GL_TEXTURE_1D:
           target_string = "1D";
           tex_coord_swizzle = "s";
@@ -413,14 +415,13 @@ add_texture_lookup (GlslShaderState *glsl_shader_state,
      supports the gl_PointCoord variable, it requires GLSL 1.2 which
      would mean we would have to declare the GLSL version and check
      for it */
-#ifdef HAVE_COGL_GLES2
-  if (cogl_pipeline_get_layer_point_sprite_coords_enabled (pipeline,
+  if (ctx->driver == COGL_DRIVER_GLES2 &&
+      cogl_pipeline_get_layer_point_sprite_coords_enabled (pipeline,
                                                            layer->index))
     g_string_append_printf (glsl_shader_state->source,
                             "gl_PointCoord.%s",
                             tex_coord_swizzle);
   else
-#endif
     g_string_append_printf (glsl_shader_state->source,
                             "cogl_tex_coord_in[%d].%s",
                             unit_index, tex_coord_swizzle);
@@ -782,7 +783,8 @@ _cogl_pipeline_fragend_glsl_end (CoglPipeline *pipeline,
       COGL_COUNTER_INC (_cogl_uprof_context, fragend_glsl_compile_counter);
 
 #ifdef HAVE_COGL_GLES2
-      add_alpha_test_snippet (pipeline, glsl_shader_state);
+      if (ctx->driver == COGL_DRIVER_GLES2)
+        add_alpha_test_snippet (pipeline, glsl_shader_state);
 #endif
 
       g_string_append (glsl_shader_state->source, "}\n");
@@ -833,7 +835,9 @@ _cogl_pipeline_fragend_glsl_pre_change_notify (CoglPipeline *pipeline,
                                                CoglPipelineState change,
                                                const CoglColor *new_color)
 {
-  if ((change & COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN))
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+  if ((change & _cogl_pipeline_get_state_for_fragment_codegen (ctx)))
     dirty_glsl_shader_state (pipeline);
 }
 
@@ -853,11 +857,13 @@ _cogl_pipeline_fragend_glsl_layer_pre_change_notify (
 {
   CoglPipelineFragendGlslPrivate *priv;
 
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
   priv = get_glsl_priv (owner);
   if (!priv)
     return;
 
-  if ((change & COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN))
+  if ((change & _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx)))
     {
       dirty_glsl_shader_state (owner);
       return;
diff --git a/cogl/cogl-pipeline-opengl.c b/cogl/cogl-pipeline-opengl.c
index 836a801..1b15b55 100644
--- a/cogl/cogl-pipeline-opengl.c
+++ b/cogl/cogl-pipeline-opengl.c
@@ -240,12 +240,6 @@ _cogl_pipeline_texture_storage_change_notify (CoglHandle texture)
 static void
 set_glsl_program (GLuint gl_program)
 {
-#ifdef HAVE_COGL_GLES
-
-  g_return_if_reached ();
-
-#else /* HAVE_COGL_GLES */
-
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
   if (ctx->current_gl_program != gl_program)
@@ -263,8 +257,6 @@ set_glsl_program (GLuint gl_program)
           ctx->current_gl_program = 0;
         }
     }
-
-#endif /* HAVE_COGL_GLES */
 }
 
 void
@@ -415,7 +407,7 @@ _cogl_get_max_texture_image_units (void)
 }
 #endif
 
-#ifndef HAVE_COGL_GLES
+#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL)
 
 static gboolean
 blend_factor_uses_constant (GLenum blend_factor)
@@ -446,21 +438,20 @@ flush_depth_state (CoglDepthState *depth_state)
       ctx->depth_writing_enabled_cache = depth_state->write_enabled;
     }
 
-#ifndef COGL_HAS_GLES
-  if (ctx->depth_range_near_cache != depth_state->range_near ||
-      ctx->depth_range_far_cache != depth_state->range_far)
+  if (ctx->driver != COGL_DRIVER_GLES1 &&
+      (ctx->depth_range_near_cache != depth_state->range_near ||
+       ctx->depth_range_far_cache != depth_state->range_far))
     {
-#ifdef COGL_HAS_GLES2
-      GE (ctx, glDepthRangef (depth_state->range_near,
-                              depth_state->range_far));
-#else
-      GE (ctx, glDepthRange (depth_state->range_near,
-                             depth_state->range_far));
-#endif
+      if (ctx->driver == COGL_DRIVER_GLES2)
+        GE (ctx, glDepthRangef (depth_state->range_near,
+                                depth_state->range_far));
+      else
+        GE (ctx, glDepthRange (depth_state->range_near,
+                               depth_state->range_far));
+
       ctx->depth_range_near_cache = depth_state->range_near;
       ctx->depth_range_far_cache = depth_state->range_far;
     }
-#endif /* COGL_HAS_GLES */
 }
 
 static void
@@ -472,8 +463,8 @@ _cogl_pipeline_flush_color_blend_alpha_depth_state (
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
   /* On GLES2 we'll flush the color later */
-#ifndef HAVE_COGL_GLES2
-  if (!skip_gl_color)
+  if (ctx->driver != COGL_DRIVER_GLES2 &&
+      !skip_gl_color)
     {
       if ((pipelines_difference & COGL_PIPELINE_STATE_COLOR) ||
           /* Assume if we were previously told to skip the color, then
@@ -488,7 +479,6 @@ _cogl_pipeline_flush_color_blend_alpha_depth_state (
                                cogl_color_get_alpha_byte (&authority->color)));
         }
     }
-#endif
 
   if (pipelines_difference & COGL_PIPELINE_STATE_BLEND)
     {
@@ -497,97 +487,103 @@ _cogl_pipeline_flush_color_blend_alpha_depth_state (
       CoglPipelineBlendState *blend_state =
         &authority->big_state->blend_state;
 
-#if defined (HAVE_COGL_GLES2)
-      gboolean have_blend_equation_seperate = TRUE;
-      gboolean have_blend_func_separate = TRUE;
-#elif defined (HAVE_COGL_GL)
-      gboolean have_blend_equation_seperate = FALSE;
-      gboolean have_blend_func_separate = FALSE;
-      if (ctx->glBlendEquationSeparate) /* Only GL 2.0 + */
-        have_blend_equation_seperate = TRUE;
-      if (ctx->glBlendFuncSeparate) /* Only GL 1.4 + */
-        have_blend_func_separate = TRUE;
-#endif
-
-#ifndef HAVE_COGL_GLES /* GLES 1 only has glBlendFunc */
-      if (blend_factor_uses_constant (blend_state->blend_src_factor_rgb) ||
-          blend_factor_uses_constant (blend_state->blend_src_factor_alpha) ||
-          blend_factor_uses_constant (blend_state->blend_dst_factor_rgb) ||
-          blend_factor_uses_constant (blend_state->blend_dst_factor_alpha))
+      /* GLES 1 only has glBlendFunc */
+      if (ctx->driver == COGL_DRIVER_GLES1)
         {
-          float red =
-            cogl_color_get_red_float (&blend_state->blend_constant);
-          float green =
-            cogl_color_get_green_float (&blend_state->blend_constant);
-          float blue =
-            cogl_color_get_blue_float (&blend_state->blend_constant);
-          float alpha =
-            cogl_color_get_alpha_float (&blend_state->blend_constant);
+          GE (ctx, glBlendFunc (blend_state->blend_src_factor_rgb,
+                                blend_state->blend_dst_factor_rgb));
+        }
+#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL)
+      else
+        {
+          if (blend_factor_uses_constant (blend_state->blend_src_factor_rgb) ||
+              blend_factor_uses_constant (blend_state
+                                          ->blend_src_factor_alpha) ||
+              blend_factor_uses_constant (blend_state->blend_dst_factor_rgb) ||
+              blend_factor_uses_constant (blend_state->blend_dst_factor_alpha))
+            {
+              float red =
+                cogl_color_get_red_float (&blend_state->blend_constant);
+              float green =
+                cogl_color_get_green_float (&blend_state->blend_constant);
+              float blue =
+                cogl_color_get_blue_float (&blend_state->blend_constant);
+              float alpha =
+                cogl_color_get_alpha_float (&blend_state->blend_constant);
 
 
-          GE (ctx, glBlendColor (red, green, blue, alpha));
-        }
+              GE (ctx, glBlendColor (red, green, blue, alpha));
+            }
 
-      if (have_blend_equation_seperate &&
-          blend_state->blend_equation_rgb != blend_state->blend_equation_alpha)
-        GE (ctx, glBlendEquationSeparate (blend_state->blend_equation_rgb,
-                                          blend_state->blend_equation_alpha));
-      else
-        GE (ctx, glBlendEquation (blend_state->blend_equation_rgb));
-
-      if (have_blend_func_separate &&
-          (blend_state->blend_src_factor_rgb != blend_state->blend_src_factor_alpha ||
-           (blend_state->blend_src_factor_rgb !=
-            blend_state->blend_src_factor_alpha)))
-        GE (ctx, glBlendFuncSeparate (blend_state->blend_src_factor_rgb,
-                                      blend_state->blend_dst_factor_rgb,
-                                      blend_state->blend_src_factor_alpha,
-                                      blend_state->blend_dst_factor_alpha));
-      else
+          if (ctx->glBlendEquationSeparate &&
+              blend_state->blend_equation_rgb !=
+              blend_state->blend_equation_alpha)
+            GE (ctx,
+                glBlendEquationSeparate (blend_state->blend_equation_rgb,
+                                         blend_state->blend_equation_alpha));
+          else
+            GE (ctx, glBlendEquation (blend_state->blend_equation_rgb));
+
+          if (ctx->glBlendFuncSeparate &&
+              (blend_state->blend_src_factor_rgb !=
+               blend_state->blend_src_factor_alpha ||
+               (blend_state->blend_src_factor_rgb !=
+                blend_state->blend_src_factor_alpha)))
+            GE (ctx, glBlendFuncSeparate (blend_state->blend_src_factor_rgb,
+                                          blend_state->blend_dst_factor_rgb,
+                                          blend_state->blend_src_factor_alpha,
+                                          blend_state->blend_dst_factor_alpha));
+          else
+            GE (ctx, glBlendFunc (blend_state->blend_src_factor_rgb,
+                                  blend_state->blend_dst_factor_rgb));
+        }
 #endif
-        GE (ctx, glBlendFunc (blend_state->blend_src_factor_rgb,
-                              blend_state->blend_dst_factor_rgb));
     }
 
-#ifndef HAVE_COGL_GLES2
+#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
 
-  /* Under GLES2 the alpha function is implemented as part of the
-     fragment shader */
-  if (pipelines_difference & (COGL_PIPELINE_STATE_ALPHA_FUNC |
-                              COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE))
+  if (ctx->driver != COGL_DRIVER_GLES2)
     {
-      CoglPipeline *authority =
-        _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_ALPHA_FUNC);
-      CoglPipelineAlphaFuncState *alpha_state =
-        &authority->big_state->alpha_state;
-
-      /* NB: Currently the Cogl defines are compatible with the GL ones: */
-      GE (ctx, glAlphaFunc (alpha_state->alpha_func,
-                            alpha_state->alpha_func_reference));
-    }
+      /* Under GLES2 the alpha function is implemented as part of the
+         fragment shader */
+      if (pipelines_difference & (COGL_PIPELINE_STATE_ALPHA_FUNC |
+                                  COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE))
+        {
+          CoglPipeline *authority =
+            _cogl_pipeline_get_authority (pipeline,
+                                          COGL_PIPELINE_STATE_ALPHA_FUNC);
+          CoglPipelineAlphaFuncState *alpha_state =
+            &authority->big_state->alpha_state;
+
+          /* NB: Currently the Cogl defines are compatible with the GL ones: */
+          GE (ctx, glAlphaFunc (alpha_state->alpha_func,
+                                alpha_state->alpha_func_reference));
+        }
 
-  /* Under GLES2 the lighting parameters are implemented as uniforms
-     in the progend */
-  if (pipelines_difference & COGL_PIPELINE_STATE_LIGHTING)
-    {
-      CoglPipeline *authority =
-        _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LIGHTING);
-      CoglPipelineLightingState *lighting_state =
-        &authority->big_state->lighting_state;
-
-      GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT,
-                             lighting_state->ambient));
-      GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE,
-                             lighting_state->diffuse));
-      GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR,
-                             lighting_state->specular));
-      GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION,
-                             lighting_state->emission));
-      GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS,
-                             &lighting_state->shininess));
+      /* Under GLES2 the lighting parameters are implemented as uniforms
+         in the progend */
+      if (pipelines_difference & COGL_PIPELINE_STATE_LIGHTING)
+        {
+          CoglPipeline *authority =
+            _cogl_pipeline_get_authority (pipeline,
+                                          COGL_PIPELINE_STATE_LIGHTING);
+          CoglPipelineLightingState *lighting_state =
+            &authority->big_state->lighting_state;
+
+          GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT,
+                                 lighting_state->ambient));
+          GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE,
+                                 lighting_state->diffuse));
+          GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR,
+                                 lighting_state->specular));
+          GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION,
+                                 lighting_state->emission));
+          GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS,
+                                 &lighting_state->shininess));
+        }
     }
 
-#endif /* HAVE_COGL_GLES2 */
+#endif
 
   if (pipelines_difference & COGL_PIPELINE_STATE_DEPTH)
     {
@@ -635,45 +631,54 @@ get_max_activateable_texture_units (void)
       int i;
 
 #ifdef HAVE_COGL_GL
-      /* GL_MAX_TEXTURE_COORDS is provided for both GLSL and ARBfp. It
-         defines the number of texture coordinates that can be
-         uploaded (but doesn't necessarily relate to how many texture
-         images can be sampled) */
-      if (cogl_features_available (COGL_FEATURE_SHADERS_GLSL) ||
-          cogl_features_available (COGL_FEATURE_SHADERS_ARBFP))
-        /* Previously this code subtracted the value by one but there
-           was no explanation for why it did this and it doesn't seem
-           to make sense so it has been removed */
-        GE (ctx, glGetIntegerv (GL_MAX_TEXTURE_COORDS, values + n_values++));
-
-      /* GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS is defined for GLSL but
-         not ARBfp */
-      if (cogl_features_available (COGL_FEATURE_SHADERS_GLSL))
-        GE (ctx, glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
-                                values + n_values++));
+      if (ctx->driver == COGL_DRIVER_GL)
+        {
+          /* GL_MAX_TEXTURE_COORDS is provided for both GLSL and ARBfp. It
+             defines the number of texture coordinates that can be
+             uploaded (but doesn't necessarily relate to how many texture
+             images can be sampled) */
+          if (cogl_features_available (COGL_FEATURE_SHADERS_GLSL) ||
+              cogl_features_available (COGL_FEATURE_SHADERS_ARBFP))
+            /* Previously this code subtracted the value by one but there
+               was no explanation for why it did this and it doesn't seem
+               to make sense so it has been removed */
+            GE (ctx, glGetIntegerv (GL_MAX_TEXTURE_COORDS,
+                                    values + n_values++));
+
+          /* GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS is defined for GLSL but
+             not ARBfp */
+          if (cogl_features_available (COGL_FEATURE_SHADERS_GLSL))
+            GE (ctx, glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
+                                    values + n_values++));
+        }
 #endif /* HAVE_COGL_GL */
 
 #ifdef HAVE_COGL_GLES2
+      if (ctx->driver == COGL_DRIVER_GLES2)
+        {
+          GE (ctx, glGetIntegerv (GL_MAX_VERTEX_ATTRIBS, values + n_values));
+          /* Two of the vertex attribs need to be used for the position
+             and color */
+          values[n_values++] -= 2;
 
-      GE (ctx, glGetIntegerv (GL_MAX_VERTEX_ATTRIBS, values + n_values));
-      /* Two of the vertex attribs need to be used for the position
-         and color */
-      values[n_values++] -= 2;
-
-      GE (ctx, glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
-                              values + n_values++));
-
-#else /* HAVE_COGL_GLES2 */
+          GE (ctx, glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
+                                  values + n_values++));
+        }
+#endif
 
-      /* GL_MAX_TEXTURE_UNITS defines the number of units that are
-         usable from the fixed function pipeline, therefore it isn't
-         available in GLES2. These are also tied to the number of
-         texture coordinates that can be uploaded so it should be less
-         than that available from the shader extensions */
-      GE (ctx, glGetIntegerv (GL_MAX_TEXTURE_UNITS,
-                              values + n_values++));
+#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) /* not GLES2 */
+      if (ctx->driver != COGL_DRIVER_GLES2)
+        {
+          /* GL_MAX_TEXTURE_UNITS defines the number of units that are
+             usable from the fixed function pipeline, therefore it isn't
+             available in GLES2. These are also tied to the number of
+             texture coordinates that can be uploaded so it should be less
+             than that available from the shader extensions */
+          GE (ctx, glGetIntegerv (GL_MAX_TEXTURE_UNITS,
+                                  values + n_values++));
 
-#endif /* HAVE_COGL_GLES2 */
+        }
+#endif
 
       g_assert (n_values <= G_N_ELEMENTS (values) &&
                 n_values > 0);
@@ -786,8 +791,9 @@ flush_layers_common_gl_state_cb (CoglPipelineLayer *layer, void *user_data)
 
   /* Under GLES2 the fragment shader will use gl_PointCoord instead of
      replacing the texture coordinates */
-#ifndef HAVE_COGL_GLES2
-  if (layers_difference & COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS)
+#if defined (HAVE_COGL_GLES) || defined (HAVE_COGL_GL)
+  if (ctx->driver != COGL_DRIVER_GLES2 &&
+      (layers_difference & COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS))
     {
       CoglPipelineState change = COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS;
       CoglPipelineLayer *authority =
@@ -799,7 +805,7 @@ flush_layers_common_gl_state_cb (CoglPipelineLayer *layer, void *user_data)
       GE (ctx, glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE,
                           big_state->point_sprite_coords));
     }
-#endif /* HAVE_COGL_GLES2 */
+#endif
 
   cogl_handle_ref (layer);
   if (unit->layer != COGL_INVALID_HANDLE)
@@ -1299,7 +1305,7 @@ done:
      of the program object so they could be overridden by any
      attribute changes in another program */
 #ifdef HAVE_COGL_GLES2
-  if (!skip_gl_color)
+  if (ctx->driver == COGL_DRIVER_GLES2 && !skip_gl_color)
     {
       int attribute;
       CoglPipeline *authority =
diff --git a/cogl/cogl-pipeline-private.h b/cogl/cogl-pipeline-private.h
index 897ae35..ba0fabf 100644
--- a/cogl/cogl-pipeline-private.h
+++ b/cogl/cogl-pipeline-private.h
@@ -41,61 +41,100 @@
 typedef struct _CoglPipelineLayer     CoglPipelineLayer;
 #define COGL_PIPELINE_LAYER(OBJECT) ((CoglPipelineLayer *)OBJECT)
 
-#if defined (HAVE_COGL_GL)
+#ifdef HAVE_COGL_GL
 
-/* NB: pipeline->fragend is currently a 3bit unsigned int bitfield */
-#define COGL_PIPELINE_FRAGEND_ARBFP      0
-#define COGL_PIPELINE_FRAGEND_ARBFP_MASK (1L<<0)
-#define COGL_PIPELINE_FRAGEND_FIXED      1
-#define COGL_PIPELINE_FRAGEND_FIXED_MASK (1L<<1)
-#define COGL_PIPELINE_FRAGEND_GLSL       2
-#define COGL_PIPELINE_FRAGEND_GLSL_MASK  (1L<<2)
+#define COGL_PIPELINE_FRAGEND_ARBFP 0
+#define COGL_PIPELINE_FRAGEND_FIXED 1
+#define COGL_PIPELINE_FRAGEND_GLSL  2
+#define COGL_PIPELINE_N_FRAGENDS    3
 
-#define COGL_PIPELINE_N_FRAGENDS         3
+#else /* HAVE_COGL_GL */
 
-#elif defined (HAVE_COGL_GLES2)
+#ifdef HAVE_COGL_GLES2
 
-#define COGL_PIPELINE_FRAGEND_GLSL       0
-#define COGL_PIPELINE_FRAGEND_GLSL_MASK  (1L<<0)
+#define COGL_PIPELINE_FRAGEND_GLSL 0
+#ifdef HAVE_COGL_GLES
+#define COGL_PIPELINE_FRAGEND_FIXED 1
+#define COGL_PIPELINE_N_FRAGENDS    2
+#else
+#define COGL_PIPELINE_N_FRAGENDS    1
+#endif
 
-#define COGL_PIPELINE_N_FRAGENDS         1
+#else /* HAVE_COGL_GLES2 */
 
-#else /* HAVE_COGL_GLES */
+#ifdef HAVE_COGL_GLES
+#define COGL_PIPELINE_FRAGEND_FIXED 0
+#define COGL_PIPELINE_N_FRAGENDS    1
+#else
+#error No drivers defined
+#endif
 
-#define COGL_PIPELINE_FRAGEND_FIXED      0
-#define COGL_PIPELINE_FRAGEND_FIXED_MASK (1L<<0)
+#endif /* HAVE_COGL_GLES2 */
 
-#define COGL_PIPELINE_N_FRAGENDS         1
+#endif /* HAVE_COGL_GL */
 
+#ifdef COGL_PIPELINE_FRAGEND_ARBFP
+#define COGL_PIPELINE_FRAGEND_ARBFP_MASK \
+  (1 << COGL_PIPELINE_FRAGEND_ARBFP)
+#endif
+#ifdef COGL_PIPELINE_FRAGEND_FIXED
+#define COGL_PIPELINE_FRAGEND_FIXED_MASK \
+  (1 << COGL_PIPELINE_FRAGEND_FIXED)
+#endif
+#ifdef COGL_PIPELINE_FRAGEND_GLSL
+#define COGL_PIPELINE_FRAGEND_GLSL_MASK \
+  (1 << COGL_PIPELINE_FRAGEND_GLSL)
 #endif
 
 #define COGL_PIPELINE_FRAGEND_DEFAULT    0
 #define COGL_PIPELINE_FRAGEND_UNDEFINED  3
 
-#if defined (HAVE_COGL_GL)
+#ifdef HAVE_COGL_GL
 
-#define COGL_PIPELINE_VERTEND_FIXED      0
-#define COGL_PIPELINE_VERTEND_GLSL       1
+#define COGL_PIPELINE_VERTEND_FIXED 0
+#define COGL_PIPELINE_VERTEND_GLSL  1
+#define COGL_PIPELINE_N_VERTENDS    2
 
-#define COGL_PIPELINE_N_VERTENDS         2
+#else /* HAVE_COGL_GL */
 
-#elif defined (HAVE_COGL_GLES2)
+#ifdef HAVE_COGL_GLES2
 
-#define COGL_PIPELINE_VERTEND_GLSL       0
+#define COGL_PIPELINE_VERTEND_GLSL  0
+#ifdef HAVE_COGL_GLES
+#define COGL_PIPELINE_VERTEND_FIXED 1
+#define COGL_PIPELINE_N_VERTENDS    2
+#else
+#define COGL_PIPELINE_N_VERTENDS    1
+#endif
 
-#define COGL_PIPELINE_N_VERTENDS         1
+#else /* HAVE_COGL_GLES2 */
 
-#else /* HAVE_COGL_GLES */
+#ifdef HAVE_COGL_GLES
+#define COGL_PIPELINE_VERTEND_FIXED 0
+#define COGL_PIPELINE_N_VERTENDS    1
+#else
+#error No drivers defined
+#endif /* HAVE_COGL_GLES */
 
-#define COGL_PIPELINE_VERTEND_FIXED      0
+#endif /* HAVE_COGL_GLES2 */
 
-#define COGL_PIPELINE_N_VERTENDS         1
+#endif /* HAVE_COGL_GL */
 
+#ifdef COGL_PIPELINE_VERTEND_FIXED
+#define COGL_PIPELINE_VERTEND_FIXED_MASK \
+  (1 << COGL_PIPELINE_VERTEND_FIXED)
+#endif
+#ifdef COGL_PIPELINE_VERTEND_GLSL
+#define COGL_PIPELINE_VERTEND_GLSL_MASK \
+  (1 << COGL_PIPELINE_VERTEND_GLSL)
 #endif
 
 #define COGL_PIPELINE_VERTEND_DEFAULT    0
 #define COGL_PIPELINE_VERTEND_UNDEFINED  3
 
+#define COGL_PIPELINE_VERTEND_DEFAULT    0
+#define COGL_PIPELINE_VERTEND_UNDEFINED  3
+
 /* If we have either of the GLSL backends then we also need a GLSL
    progend to combine the shaders generated into a single
    program. Currently there is only one progend but if we ever add
@@ -187,23 +226,6 @@ typedef enum
    COGL_PIPELINE_LAYER_STATE_WRAP_MODES | \
    COGL_PIPELINE_LAYER_STATE_COMBINE)
 
-/* FIXME: Only texture target changes should really affect the
- * codegen, but this is difficult to detect */
-#ifdef HAVE_COGL_GLES2
-/* On GLES2 we need to use a different varying for the texture lookups
- * when point sprite coords are enabled */
-#define COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN \
-  (COGL_PIPELINE_LAYER_STATE_COMBINE | \
-   COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET | \
-   COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS | \
-   COGL_PIPELINE_LAYER_STATE_UNIT)
-#else
-#define COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN \
-  (COGL_PIPELINE_LAYER_STATE_COMBINE | \
-   COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET | \
-   COGL_PIPELINE_LAYER_STATE_UNIT)
-#endif
-
 #define COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN 0
 
 
@@ -491,19 +513,6 @@ typedef enum _CoglPipelineState
    COGL_PIPELINE_STATE_DEPTH | \
    COGL_PIPELINE_STATE_FOG)
 
-#ifdef HAVE_COGL_GLES2
-  /* Under GLES2 the alpha func becomes part of the fragment program
-     so we can't share programs there */
-#define COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN \
-  (COGL_PIPELINE_STATE_LAYERS | \
-   COGL_PIPELINE_STATE_ALPHA_FUNC | \
-   COGL_PIPELINE_STATE_USER_SHADER)
-#else
-#define COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN \
-  (COGL_PIPELINE_STATE_LAYERS | \
-   COGL_PIPELINE_STATE_USER_SHADER)
-#endif
-
 #define COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN \
   (COGL_PIPELINE_STATE_LAYERS | \
    COGL_PIPELINE_STATE_USER_SHADER)
@@ -546,7 +555,7 @@ typedef enum _CoglPipelineBlendEnable
 typedef struct
 {
   /* Determines how this pipeline is blended with other primitives */
-#ifndef HAVE_COGL_GLES
+#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL)
   GLenum    blend_equation_rgb;
   GLenum    blend_equation_alpha;
   GLint     blend_src_factor_alpha;
@@ -1240,5 +1249,11 @@ _cogl_pipeline_init_state_hash_functions (void);
 void
 _cogl_pipeline_init_layer_state_hash_functions (void);
 
+CoglPipelineLayerState
+_cogl_pipeline_get_layer_state_for_fragment_codegen (CoglContext *context);
+
+CoglPipelineState
+_cogl_pipeline_get_state_for_fragment_codegen (CoglContext *context);
+
 #endif /* __COGL_PIPELINE_PRIVATE_H */
 
diff --git a/cogl/cogl-pipeline-progend-glsl.c b/cogl/cogl-pipeline-progend-glsl.c
index 51be8d1..ae8e0af 100644
--- a/cogl/cogl-pipeline-progend-glsl.c
+++ b/cogl/cogl-pipeline-progend-glsl.c
@@ -301,8 +301,11 @@ destroy_glsl_priv (void *user_data)
   if (--priv->ref_count == 0)
     {
 #ifdef HAVE_COGL_GLES2
-      clear_attribute_cache (priv);
-      clear_flushed_matrix_stacks (priv);
+      if (ctx->driver == COGL_DRIVER_GLES2)
+        {
+          clear_attribute_cache (priv);
+          clear_flushed_matrix_stacks (priv);
+        }
 #endif
 
       if (priv->program)
@@ -411,17 +414,18 @@ get_uniform_cb (CoglPipeline *pipeline,
   unit_state->combine_constant_uniform = uniform_location;
 
 #ifdef HAVE_COGL_GLES2
+  if (ctx->driver == COGL_DRIVER_GLES2)
+    {
+      g_string_set_size (ctx->codegen_source_buffer, 0);
+      g_string_append_printf (ctx->codegen_source_buffer,
+                              "cogl_texture_matrix[%i]", state->unit);
 
-  g_string_set_size (ctx->codegen_source_buffer, 0);
-  g_string_append_printf (ctx->codegen_source_buffer,
-                          "cogl_texture_matrix[%i]", state->unit);
-
-  GE_RET( uniform_location,
-          ctx, glGetUniformLocation (state->gl_program,
-                                     ctx->codegen_source_buffer->str) );
-
-  unit_state->texture_matrix_uniform = uniform_location;
+      GE_RET( uniform_location,
+              ctx, glGetUniformLocation (state->gl_program,
+                                         ctx->codegen_source_buffer->str) );
 
+      unit_state->texture_matrix_uniform = uniform_location;
+    }
 #endif
 
   state->unit++;
@@ -454,7 +458,8 @@ update_constants_cb (CoglPipeline *pipeline,
 
 #ifdef HAVE_COGL_GLES2
 
-  if (unit_state->texture_matrix_uniform != -1 &&
+  if (ctx->driver == COGL_DRIVER_GLES2 &&
+      unit_state->texture_matrix_uniform != -1 &&
       (state->update_all || unit_state->dirty_texture_matrix))
     {
       const CoglMatrix *matrix;
@@ -529,9 +534,9 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline,
       authority = _cogl_pipeline_find_equivalent_parent
         (pipeline,
          (COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN |
-          COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN) &
+          _cogl_pipeline_get_state_for_fragment_codegen (ctx)) &
          ~COGL_PIPELINE_STATE_LAYERS,
-         COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN |
+         _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx) |
          COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN);
 
       priv = get_glsl_priv (authority);
@@ -591,7 +596,8 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline,
           /* Find the largest count of texture coordinate attributes
            * associated with each of the shaders so we can ensure a consistent
            * _cogl_tex_coord[] array declaration across all of the shaders.*/
-          if (user_program)
+          if (ctx->driver == COGL_DRIVER_GLES2 &&
+              user_program)
             for (l = user_program->attached_shaders; l; l = l->next)
               {
                 CoglShader *shader = l->data;
@@ -655,35 +661,40 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline,
                                &state);
 
 #ifdef HAVE_COGL_GLES2
-  if (program_changed)
+  if (ctx->driver == COGL_DRIVER_GLES2)
     {
-      int i;
+      if (program_changed)
+        {
+          int i;
 
-      clear_attribute_cache (priv);
-      clear_flushed_matrix_stacks (priv);
+          clear_attribute_cache (priv);
+          clear_flushed_matrix_stacks (priv);
 
-      for (i = 0; i < G_N_ELEMENTS (builtin_uniforms); i++)
-        GE_RET( priv->builtin_uniform_locations[i],
-                ctx, glGetUniformLocation (gl_program,
-                                           builtin_uniforms[i].uniform_name) );
+          for (i = 0; i < G_N_ELEMENTS (builtin_uniforms); i++)
+            GE_RET( priv->builtin_uniform_locations[i],
+                    ctx,
+                    glGetUniformLocation (gl_program,
+                                          builtin_uniforms[i].uniform_name) );
 
-      GE_RET( priv->modelview_uniform,
-              ctx, glGetUniformLocation (gl_program,
-                                         "cogl_modelview_matrix") );
+          GE_RET( priv->modelview_uniform,
+                  ctx, glGetUniformLocation (gl_program,
+                                             "cogl_modelview_matrix") );
 
-      GE_RET( priv->projection_uniform,
-              ctx, glGetUniformLocation (gl_program,
-                                         "cogl_projection_matrix") );
+          GE_RET( priv->projection_uniform,
+                  ctx, glGetUniformLocation (gl_program,
+                                             "cogl_projection_matrix") );
 
-      GE_RET( priv->mvp_uniform,
-              ctx, glGetUniformLocation (gl_program,
-                                         "cogl_modelview_projection_matrix") );
-    }
-  if (program_changed ||
-      priv->last_used_for_pipeline != pipeline)
-    priv->dirty_builtin_uniforms = ~(unsigned long) 0;
+          GE_RET( priv->mvp_uniform,
+                  ctx,
+                  glGetUniformLocation (gl_program,
+                                        "cogl_modelview_projection_matrix") );
+        }
+      if (program_changed ||
+          priv->last_used_for_pipeline != pipeline)
+        priv->dirty_builtin_uniforms = ~(unsigned long) 0;
 
-  update_builtin_uniforms (pipeline, gl_program, priv);
+      update_builtin_uniforms (pipeline, gl_program, priv);
+    }
 #endif
 
   if (user_program)
@@ -701,10 +712,12 @@ _cogl_pipeline_progend_glsl_pre_change_notify (CoglPipeline *pipeline,
                                                CoglPipelineState change,
                                                const CoglColor *new_color)
 {
-  if ((change & COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN))
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+  if ((change & _cogl_pipeline_get_state_for_fragment_codegen (ctx)))
     dirty_glsl_program_state (pipeline);
 #ifdef HAVE_COGL_GLES2
-  else
+  else if (ctx->driver == COGL_DRIVER_GLES2)
     {
       int i;
 
@@ -734,7 +747,9 @@ _cogl_pipeline_progend_glsl_layer_pre_change_notify (
                                                 CoglPipelineLayer *layer,
                                                 CoglPipelineLayerState change)
 {
-  if ((change & COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN))
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+  if ((change & _cogl_pipeline_get_state_for_fragment_codegen (ctx)))
     {
       dirty_glsl_program_state (owner);
       return;
@@ -850,6 +865,9 @@ _cogl_pipeline_progend_glsl_pre_paint (CoglPipeline *pipeline)
 
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
+  if (ctx->driver != COGL_DRIVER_GLES2)
+    return;
+
   /* We only need to update the matrices if we're using the the GLSL
      vertend, but this is a requirement on GLES2 anyway */
   g_return_if_fail (pipeline->vertend == COGL_PIPELINE_VERTEND_GLSL);
diff --git a/cogl/cogl-pipeline-vertend-fixed.c b/cogl/cogl-pipeline-vertend-fixed.c
index d6baf98..a3d3ae4 100644
--- a/cogl/cogl-pipeline-vertend-fixed.c
+++ b/cogl/cogl-pipeline-vertend-fixed.c
@@ -49,9 +49,14 @@ _cogl_pipeline_vertend_fixed_start (CoglPipeline *pipeline,
 {
   CoglProgram *user_program;
 
+  _COGL_GET_CONTEXT (ctx, FALSE);
+
   if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_FIXED)))
     return FALSE;
 
+  if (ctx->driver == COGL_DRIVER_GLES2)
+    return FALSE;
+
   /* If there is a user program with a vertex shader then the
      appropriate backend for that language should handle it. We can
      still use the fixed vertex backend if the program only contains
diff --git a/cogl/cogl-pipeline-vertend-glsl.c b/cogl/cogl-pipeline-vertend-glsl.c
index ac98c87..f13eceb 100644
--- a/cogl/cogl-pipeline-vertend-glsl.c
+++ b/cogl/cogl-pipeline-vertend-glsl.c
@@ -206,17 +206,13 @@ _cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline,
                    "main ()\n"
                    "{\n");
 
-#ifdef HAVE_COGL_GLES2
-
-  /* There is no builtin uniform for the pointsize on GLES2 so we need
-     to copy it from the custom uniform in the vertex shader */
-  g_string_append (priv->source,
-                   "  cogl_point_size_out = cogl_point_size_in;\n");
-
-#else /* HAVE_COGL_GLES2 */
-
+  if (ctx->driver == COGL_DRIVER_GLES2)
+    /* There is no builtin uniform for the pointsize on GLES2 so we need
+       to copy it from the custom uniform in the vertex shader */
+    g_string_append (priv->source,
+                     "  cogl_point_size_out = cogl_point_size_in;\n");
   /* On regular OpenGL we'll just flush the point size builtin */
-  if (pipelines_difference & COGL_PIPELINE_STATE_POINT_SIZE)
+  else if (pipelines_difference & COGL_PIPELINE_STATE_POINT_SIZE)
     {
       CoglPipeline *authority =
         _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_POINT_SIZE);
@@ -228,8 +224,6 @@ _cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline,
         }
     }
 
-#endif /* HAVE_COGL_GLES2 */
-
   return TRUE;
 }
 
@@ -241,32 +235,34 @@ _cogl_pipeline_vertend_glsl_add_layer (CoglPipeline *pipeline,
   CoglPipelineVertendPrivate *priv;
   int unit_index;
 
+  _COGL_GET_CONTEXT (ctx, FALSE);
+
   priv = get_glsl_priv (pipeline);
 
   unit_index = _cogl_pipeline_layer_get_unit_index (layer);
 
-#ifndef HAVE_COGL_GLES2
-
-  /* We are using the fixed function uniforms for the user matrices
-     and the only way to set them is with the fixed function API so we
-     still need to flush them here */
-  if (layers_difference & COGL_PIPELINE_LAYER_STATE_USER_MATRIX)
+  if (ctx->driver != COGL_DRIVER_GLES2)
     {
-      CoglPipelineLayerState state = COGL_PIPELINE_LAYER_STATE_USER_MATRIX;
-      CoglPipelineLayer *authority =
-        _cogl_pipeline_layer_get_authority (layer, state);
-      CoglTextureUnit *unit = _cogl_get_texture_unit (unit_index);
+      /* We are using the fixed function uniforms for the user matrices
+         and the only way to set them is with the fixed function API so we
+         still need to flush them here */
+      if (layers_difference & COGL_PIPELINE_LAYER_STATE_USER_MATRIX)
+        {
+          CoglPipelineLayerState state = COGL_PIPELINE_LAYER_STATE_USER_MATRIX;
+          CoglPipelineLayer *authority =
+            _cogl_pipeline_layer_get_authority (layer, state);
+          CoglTextureUnit *unit = _cogl_get_texture_unit (unit_index);
 
-      _cogl_matrix_stack_set (unit->matrix_stack,
-                              &authority->big_state->matrix);
+          _cogl_matrix_stack_set (unit->matrix_stack,
+                                  &authority->big_state->matrix);
 
-      _cogl_set_active_texture_unit (unit_index);
+          _cogl_set_active_texture_unit (unit_index);
 
-      _cogl_matrix_stack_flush_to_gl (unit->matrix_stack, COGL_MATRIX_TEXTURE);
+          _cogl_matrix_stack_flush_to_gl (unit->matrix_stack,
+                                          COGL_MATRIX_TEXTURE);
+        }
     }
 
-#endif /* HAVE_COGL_GLES2 */
-
   if (priv->source == NULL)
     return TRUE;
 
diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c
index ce08203..739036b 100644
--- a/cogl/cogl-pipeline.c
+++ b/cogl/cogl-pipeline.c
@@ -49,6 +49,10 @@
 #include <glib/gprintf.h>
 #include <string.h>
 
+#ifndef GL_FUNC_ADD
+#define GL_FUNC_ADD 0x8006
+#endif
+
 typedef gboolean (*CoglPipelineStateComparitor) (CoglPipeline *authority0,
                                                  CoglPipeline *authority1);
 
@@ -275,7 +279,7 @@ _cogl_pipeline_init_default_pipeline (void)
   alpha_state->alpha_func_reference = 0.0;
 
   /* Not the same as the GL default, but seems saner... */
-#ifndef HAVE_COGL_GLES
+#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL)
   blend_state->blend_equation_rgb = GL_FUNC_ADD;
   blend_state->blend_equation_alpha = GL_FUNC_ADD;
   blend_state->blend_src_factor_alpha = GL_ONE;
@@ -821,6 +825,8 @@ _cogl_pipeline_needs_blending_enabled (CoglPipeline    *pipeline,
   CoglPipelineBlendEnable enabled;
   unsigned long other_state;
 
+  _COGL_GET_CONTEXT (ctx, FALSE);
+
   if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_BLENDING)))
     return FALSE;
 
@@ -846,15 +852,18 @@ _cogl_pipeline_needs_blending_enabled (CoglPipeline    *pipeline,
    * functions...
    */
 
-#ifndef HAVE_COGL_GLES
-  /* GLES 1 can't change the function or have separate alpha factors */
-  if (blend_state->blend_equation_rgb != GL_FUNC_ADD ||
-      blend_state->blend_equation_alpha != GL_FUNC_ADD)
-    return TRUE;
+#if defined (HAVE_COGL_GLES2) || defined (HAVE_COGL_GL)
+  if (ctx->driver != COGL_DRIVER_GLES1)
+    {
+      /* GLES 1 can't change the function or have separate alpha factors */
+      if (blend_state->blend_equation_rgb != GL_FUNC_ADD ||
+          blend_state->blend_equation_alpha != GL_FUNC_ADD)
+        return TRUE;
 
-  if (blend_state->blend_src_factor_alpha != GL_ONE ||
-      blend_state->blend_dst_factor_alpha != GL_ONE_MINUS_SRC_ALPHA)
-    return TRUE;
+      if (blend_state->blend_src_factor_alpha != GL_ONE ||
+          blend_state->blend_dst_factor_alpha != GL_ONE_MINUS_SRC_ALPHA)
+        return TRUE;
+    }
 #endif
 
   if (blend_state->blend_src_factor_rgb != GL_ONE ||
@@ -3400,18 +3409,23 @@ _cogl_pipeline_blend_state_equal (CoglPipeline *authority0,
   CoglPipelineBlendState *blend_state0 = &authority0->big_state->blend_state;
   CoglPipelineBlendState *blend_state1 = &authority1->big_state->blend_state;
 
-#ifndef HAVE_COGL_GLES
-  if (blend_state0->blend_equation_rgb != blend_state1->blend_equation_rgb)
-    return FALSE;
-  if (blend_state0->blend_equation_alpha !=
-      blend_state1->blend_equation_alpha)
-    return FALSE;
-  if (blend_state0->blend_src_factor_alpha !=
-      blend_state1->blend_src_factor_alpha)
-    return FALSE;
-  if (blend_state0->blend_dst_factor_alpha !=
-      blend_state1->blend_dst_factor_alpha)
-    return FALSE;
+  _COGL_GET_CONTEXT (ctx, FALSE);
+
+#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL)
+  if (ctx->driver != COGL_DRIVER_GLES1)
+    {
+      if (blend_state0->blend_equation_rgb != blend_state1->blend_equation_rgb)
+        return FALSE;
+      if (blend_state0->blend_equation_alpha !=
+          blend_state1->blend_equation_alpha)
+        return FALSE;
+      if (blend_state0->blend_src_factor_alpha !=
+          blend_state1->blend_src_factor_alpha)
+        return FALSE;
+      if (blend_state0->blend_dst_factor_alpha !=
+          blend_state1->blend_dst_factor_alpha)
+        return FALSE;
+    }
 #endif
   if (blend_state0->blend_src_factor_rgb !=
       blend_state1->blend_src_factor_rgb)
@@ -3419,11 +3433,12 @@ _cogl_pipeline_blend_state_equal (CoglPipeline *authority0,
   if (blend_state0->blend_dst_factor_rgb !=
       blend_state1->blend_dst_factor_rgb)
     return FALSE;
-#ifndef HAVE_COGL_GLES
-  if (blend_state0->blend_src_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR ||
-      blend_state0->blend_src_factor_rgb == GL_CONSTANT_COLOR ||
-      blend_state0->blend_dst_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR ||
-      blend_state0->blend_dst_factor_rgb == GL_CONSTANT_COLOR)
+#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL)
+  if (ctx->driver != COGL_DRIVER_GLES1 &&
+      (blend_state0->blend_src_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR ||
+       blend_state0->blend_src_factor_rgb == GL_CONSTANT_COLOR ||
+       blend_state0->blend_dst_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR ||
+       blend_state0->blend_dst_factor_rgb == GL_CONSTANT_COLOR))
     {
       if (!cogl_color_equal (&blend_state0->blend_constant,
                              &blend_state1->blend_constant))
@@ -4411,7 +4426,7 @@ arg_to_gl_blend_factor (CoglBlendStringArgument *arg)
             return GL_DST_ALPHA;
         }
     }
-#ifndef HAVE_COGL_GLES
+#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL)
   else if (arg->factor.source.info->type ==
            COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT)
     {
@@ -4442,7 +4457,6 @@ setup_blend_state (CoglBlendStringStatement *statement,
                    GLint *blend_src_factor,
                    GLint *blend_dst_factor)
 {
-#ifndef HAVE_COGL_GLES
   switch (statement->function->type)
     {
     case COGL_BLEND_STRING_FUNCTION_ADD:
@@ -4453,7 +4467,6 @@ setup_blend_state (CoglBlendStringStatement *statement,
       g_warning ("Unsupported blend function given");
       *blend_equation = GL_FUNC_ADD;
     }
-#endif
 
   *blend_src_factor = arg_to_gl_blend_factor (&statement->args[0]);
   *blend_dst_factor = arg_to_gl_blend_factor (&statement->args[1]);
@@ -4473,6 +4486,8 @@ cogl_pipeline_set_blend (CoglPipeline *pipeline,
   int count;
   CoglPipelineBlendState *blend_state;
 
+  _COGL_GET_CONTEXT (ctx, FALSE);
+
   g_return_val_if_fail (cogl_is_pipeline (pipeline), FALSE);
 
   count =
@@ -4512,21 +4527,26 @@ cogl_pipeline_set_blend (CoglPipeline *pipeline,
   _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
 
   blend_state = &pipeline->big_state->blend_state;
-#ifndef HAVE_COGL_GLES
-  setup_blend_state (rgb,
-                     &blend_state->blend_equation_rgb,
-                     &blend_state->blend_src_factor_rgb,
-                     &blend_state->blend_dst_factor_rgb);
-  setup_blend_state (a,
-                     &blend_state->blend_equation_alpha,
-                     &blend_state->blend_src_factor_alpha,
-                     &blend_state->blend_dst_factor_alpha);
-#else
-  setup_blend_state (rgb,
-                     NULL,
-                     &blend_state->blend_src_factor_rgb,
-                     &blend_state->blend_dst_factor_rgb);
+#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES2)
+  if (ctx->driver != COGL_DRIVER_GLES1)
+    {
+      setup_blend_state (rgb,
+                         &blend_state->blend_equation_rgb,
+                         &blend_state->blend_src_factor_rgb,
+                         &blend_state->blend_dst_factor_rgb);
+      setup_blend_state (a,
+                         &blend_state->blend_equation_alpha,
+                         &blend_state->blend_src_factor_alpha,
+                         &blend_state->blend_dst_factor_alpha);
+    }
+  else
 #endif
+    {
+      setup_blend_state (rgb,
+                         NULL,
+                         &blend_state->blend_src_factor_rgb,
+                         &blend_state->blend_dst_factor_rgb);
+    }
 
   /* If we are the current authority see if we can revert to one of our
    * ancestors being the authority */
@@ -4560,33 +4580,40 @@ void
 cogl_pipeline_set_blend_constant (CoglPipeline *pipeline,
                                   const CoglColor *constant_color)
 {
-#ifndef HAVE_COGL_GLES
-  CoglPipelineState state = COGL_PIPELINE_STATE_BLEND;
-  CoglPipeline *authority;
-  CoglPipelineBlendState *blend_state;
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
   g_return_if_fail (cogl_is_pipeline (pipeline));
 
-  authority = _cogl_pipeline_get_authority (pipeline, state);
-
-  blend_state = &authority->big_state->blend_state;
-  if (cogl_color_equal (constant_color, &blend_state->blend_constant))
+  if (ctx->driver == COGL_DRIVER_GLES1)
     return;
 
-  /* - Flush journal primitives referencing the current state.
-   * - Make sure the pipeline has no dependants so it may be modified.
-   * - If the pipeline isn't currently an authority for the state being
-   *   changed, then initialize that state from the current authority.
-   */
-  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
+#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL)
+  {
+    CoglPipelineState state = COGL_PIPELINE_STATE_BLEND;
+    CoglPipeline *authority;
+    CoglPipelineBlendState *blend_state;
 
-  blend_state = &pipeline->big_state->blend_state;
-  blend_state->blend_constant = *constant_color;
+    authority = _cogl_pipeline_get_authority (pipeline, state);
 
-  _cogl_pipeline_update_authority (pipeline, authority, state,
-                                   _cogl_pipeline_blend_state_equal);
+    blend_state = &authority->big_state->blend_state;
+    if (cogl_color_equal (constant_color, &blend_state->blend_constant))
+      return;
 
-  handle_automatic_blend_enable (pipeline, state);
+    /* - Flush journal primitives referencing the current state.
+     * - Make sure the pipeline has no dependants so it may be modified.
+     * - If the pipeline isn't currently an authority for the state being
+     *   changed, then initialize that state from the current authority.
+     */
+    _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
+
+    blend_state = &pipeline->big_state->blend_state;
+    blend_state->blend_constant = *constant_color;
+
+    _cogl_pipeline_update_authority (pipeline, authority, state,
+                                     _cogl_pipeline_blend_state_equal);
+
+    handle_automatic_blend_enable (pipeline, state);
+  }
 #endif
 }
 
@@ -4677,6 +4704,8 @@ cogl_pipeline_set_depth_state (CoglPipeline *pipeline,
   CoglPipeline *authority;
   CoglDepthState *orig_state;
 
+  _COGL_GET_CONTEXT (ctx, FALSE);
+
   g_return_val_if_fail (cogl_is_pipeline (pipeline), FALSE);
   g_return_val_if_fail (depth_state->magic == COGL_DEPTH_STATE_MAGIC, FALSE);
 
@@ -4690,9 +4719,9 @@ cogl_pipeline_set_depth_state (CoglPipeline *pipeline,
       orig_state->range_far == depth_state->range_far)
     return TRUE;
 
-#ifdef COGL_HAS_GLES
-  if (depth_state->range_near != 0 ||
-      depth_state->range_far != 1)
+  if (ctx->driver == COGL_DRIVER_GLES1 &&
+      (depth_state->range_near != 0 ||
+       depth_state->range_far != 1))
     {
       g_set_error (error,
                    COGL_ERROR,
@@ -4700,7 +4729,6 @@ cogl_pipeline_set_depth_state (CoglPipeline *pipeline,
                    "glDepthRange not available on GLES 1");
       return FALSE;
     }
-#endif
 
   /* - Flush journal primitives referencing the current state.
    * - Make sure the pipeline has no dependants so it may be modified.
@@ -6070,33 +6098,38 @@ _cogl_pipeline_hash_blend_state (CoglPipeline *authority,
   CoglPipelineBlendState *blend_state = &authority->big_state->blend_state;
   unsigned int hash;
 
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
   if (!authority->real_blend_enable)
     return;
 
   hash = state->hash;
 
-#ifndef HAVE_COGL_GLES
-  hash =
-    _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_equation_rgb,
-                                   sizeof (blend_state->blend_equation_rgb));
-  hash =
-    _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_equation_alpha,
-                                   sizeof (blend_state->blend_equation_alpha));
-  hash =
-    _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_src_factor_alpha,
-                                   sizeof (blend_state->blend_src_factor_alpha));
-  hash =
-    _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_dst_factor_alpha,
-                                   sizeof (blend_state->blend_dst_factor_alpha));
-
-  if (blend_state->blend_src_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR ||
-      blend_state->blend_src_factor_rgb == GL_CONSTANT_COLOR ||
-      blend_state->blend_dst_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR ||
-      blend_state->blend_dst_factor_rgb == GL_CONSTANT_COLOR)
+#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL)
+  if (ctx->driver != COGL_DRIVER_GLES1)
     {
       hash =
-        _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_constant,
-                                       sizeof (blend_state->blend_constant));
+        _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_equation_rgb,
+                                       sizeof (blend_state->blend_equation_rgb));
+      hash =
+        _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_equation_alpha,
+                                       sizeof (blend_state->blend_equation_alpha));
+      hash =
+        _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_src_factor_alpha,
+                                       sizeof (blend_state->blend_src_factor_alpha));
+      hash =
+        _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_dst_factor_alpha,
+                                       sizeof (blend_state->blend_dst_factor_alpha));
+
+      if (blend_state->blend_src_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR ||
+          blend_state->blend_src_factor_rgb == GL_CONSTANT_COLOR ||
+          blend_state->blend_dst_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR ||
+          blend_state->blend_dst_factor_rgb == GL_CONSTANT_COLOR)
+        {
+          hash =
+            _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_constant,
+                                           sizeof (blend_state->blend_constant));
+        }
     }
 #endif
 
@@ -6698,3 +6731,30 @@ _cogl_pipeline_find_equivalent_parent (CoglPipeline *pipeline,
 
   return authority1;
 }
+
+CoglPipelineLayerState
+_cogl_pipeline_get_layer_state_for_fragment_codegen (CoglContext *context)
+{
+  CoglPipelineLayerState state =
+    (COGL_PIPELINE_LAYER_STATE_COMBINE |
+     COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET |
+     COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS |
+     COGL_PIPELINE_LAYER_STATE_UNIT);
+
+  if (context->driver == COGL_DRIVER_GLES2)
+    state |= COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS;
+
+  return state;
+}
+
+CoglPipelineState
+_cogl_pipeline_get_state_for_fragment_codegen (CoglContext *context)
+{
+  CoglPipelineState state = (COGL_PIPELINE_STATE_LAYERS |
+                             COGL_PIPELINE_STATE_USER_SHADER);
+
+  if (context->driver == COGL_DRIVER_GLES2)
+    state |= COGL_PIPELINE_STATE_ALPHA_FUNC;
+
+  return state;
+}
diff --git a/cogl/cogl-private.h b/cogl/cogl-private.h
index 8db76e1..465b267 100644
--- a/cogl/cogl-private.h
+++ b/cogl/cogl-private.h
@@ -27,12 +27,20 @@
 G_BEGIN_DECLS
 
 gboolean
-_cogl_gl_check_version (GError **error);
+_cogl_gl_check_gl_version (CoglContext *context,
+                           GError **error);
 
 void
 _cogl_gl_update_features (CoglContext *context);
 
 gboolean
+_cogl_gles_check_gl_version (CoglContext *context,
+                             GError **error);
+
+void
+_cogl_gles_update_features (CoglContext *context);
+
+gboolean
 _cogl_check_extension (const char *name, const char *ext);
 
 void
diff --git a/cogl/cogl-program.c b/cogl/cogl-program.c
index 8f00ead..044c284 100644
--- a/cogl/cogl-program.c
+++ b/cogl/cogl-program.c
@@ -106,13 +106,11 @@ cogl_program_attach_shader (CoglHandle program_handle,
   shader = _cogl_shader_pointer_from_handle (shader_handle);
 
   /* Only one shader is allowed if the type is ARBfp */
-#ifdef HAVE_COGL_GL
   if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
     g_return_if_fail (program->attached_shaders == NULL);
   else if (shader->language == COGL_SHADER_LANGUAGE_GLSL)
     g_return_if_fail (_cogl_program_get_language (program) ==
                       COGL_SHADER_LANGUAGE_GLSL);
-#endif
 
   program->attached_shaders
     = g_slist_prepend (program->attached_shaders,
@@ -366,8 +364,6 @@ cogl_program_uniform_matrix (int uniform_no,
                                    uniform_no, size, count, transpose, value);
 }
 
-#ifndef HAVE_COGL_GLES
-
 /* ARBfp local parameters can be referenced like:
  *
  * "program.local[5]"
@@ -478,8 +474,6 @@ _cogl_program_flush_uniform_glsl (GLint location,
     }
 }
 
-#endif /* HAVE_COGL_GLES */
-
 #ifdef HAVE_COGL_GL
 
 static void
@@ -506,17 +500,13 @@ _cogl_program_flush_uniforms (CoglProgram *program,
                               GLuint gl_program,
                               gboolean gl_program_changed)
 {
-#ifdef HAVE_COGL_GLES
-
-  g_return_if_reached ();
-
-#else /* HAVE_COGL_GLES */
-
   CoglProgramUniform *uniform;
   int i;
 
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
+  g_return_if_fail (ctx->driver != COGL_DRIVER_GLES1);
+
   for (i = 0; i < program->custom_uniforms->len; i++)
     {
       uniform = &g_array_index (program->custom_uniforms,
@@ -548,20 +538,18 @@ _cogl_program_flush_uniforms (CoglProgram *program,
                                                     &uniform->value);
                   break;
 
-#ifdef HAVE_COGL_GL
                 case COGL_SHADER_LANGUAGE_ARBFP:
+#ifdef HAVE_COGL_GL
                   _cogl_program_flush_uniform_arbfp (uniform->location,
                                                      &uniform->value);
-                  break;
 #endif
+                  break;
                 }
             }
 
           uniform->dirty = FALSE;
         }
     }
-
-#endif /* HAVE_COGL_GLES */
 }
 
 CoglShaderLanguage
diff --git a/cogl/cogl-renderer-private.h b/cogl/cogl-renderer-private.h
index a6110d3..dc279ba 100644
--- a/cogl/cogl-renderer-private.h
+++ b/cogl/cogl-renderer-private.h
@@ -24,8 +24,11 @@
 #ifndef __COGL_RENDERER_PRIVATE_H
 #define __COGL_RENDERER_PRIVATE_H
 
+#include <gmodule.h>
+
 #include "cogl-object-private.h"
 #include "cogl-winsys-private.h"
+#include "cogl-internal.h"
 
 #ifdef COGL_HAS_XLIB_SUPPORT
 #include <X11/Xlib.h>
@@ -44,6 +47,12 @@ struct _CoglRenderer
 #ifdef COGL_HAS_XLIB_SUPPORT
   Display *foreign_xdpy;
 #endif
+
+  CoglDriver driver;
+#ifndef HAVE_DIRECTLY_LINKED_GL_LIBRARY
+  GModule *libgl_module;
+#endif
+
 #if COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT
   struct wl_display *foreign_wayland_display;
   struct wl_compositor *foreign_wayland_compositor;
diff --git a/cogl/cogl-renderer.c b/cogl/cogl-renderer.c
index 026d4ab..8b76a77 100644
--- a/cogl/cogl-renderer.c
+++ b/cogl/cogl-renderer.c
@@ -100,6 +100,11 @@ _cogl_renderer_free (CoglRenderer *renderer)
   const CoglWinsysVtable *winsys = _cogl_renderer_get_winsys (renderer);
   winsys->renderer_disconnect (renderer);
 
+#ifndef HAVE_DIRECTLY_LINKED_GL_LIBRARY
+  if (renderer->libgl_module)
+    g_module_close (renderer->libgl_module);
+#endif
+
   g_slist_foreach (renderer->event_filters,
                    (GFunc) native_filter_closure_free,
                    NULL);
@@ -166,6 +171,75 @@ cogl_renderer_check_onscreen_template (CoglRenderer *renderer,
   return TRUE;
 }
 
+static gboolean
+_cogl_renderer_choose_driver (CoglRenderer *renderer,
+                              GError **error)
+{
+  const char *driver_name = g_getenv ("COGL_DRIVER");
+  const char *libgl_name;
+#ifndef HAVE_DIRECTLY_LINKED_GL_LIBRARY
+  char *libgl_module_path;
+#endif
+
+#ifdef HAVE_COGL_GL
+  if (driver_name == NULL || !strcmp (driver_name, "gl"))
+    {
+      renderer->driver = COGL_DRIVER_GL;
+      libgl_name = COGL_GL_LIBNAME;
+      goto found;
+    }
+#endif
+
+#ifdef HAVE_COGL_GLES2
+  if (driver_name == NULL || !strcmp (driver_name, "gles2"))
+    {
+      renderer->driver = COGL_DRIVER_GLES2;
+      libgl_name = COGL_GLES2_LIBNAME;
+      goto found;
+    }
+#endif
+
+#ifdef HAVE_COGL_GLES
+  if (driver_name == NULL || !strcmp (driver_name, "gles1"))
+    {
+      renderer->driver = COGL_DRIVER_GLES1;
+      libgl_name = COGL_GLES1_LIBNAME;
+      goto found;
+    }
+#endif
+
+  g_set_error (error,
+               COGL_DRIVER_ERROR,
+               COGL_DRIVER_ERROR_NO_SUITABLE_DRIVER_FOUND,
+               "No suitable driver found");
+  return FALSE;
+
+ found:
+
+#ifndef HAVE_DIRECTLY_LINKED_GL_LIBRARY
+
+  libgl_module_path = g_module_build_path (NULL, /* standard lib search path */
+                                           libgl_name);
+
+  renderer->libgl_module = g_module_open (libgl_module_path,
+                                          G_MODULE_BIND_LAZY);
+
+  g_free (libgl_module_path);
+
+  if (renderer->libgl_module == NULL)
+    {
+      g_set_error (error, COGL_DRIVER_ERROR,
+                   COGL_DRIVER_ERROR_FAILED_TO_LOAD_LIBRARY,
+                   "Failed to dynamically open the GL library \"%s\"",
+                   libgl_name);
+      return FALSE;
+    }
+
+#endif /* HAVE_DIRECTLY_LINKED_GL_LIBRARY */
+
+  return TRUE;
+}
+
 /* Final connection API */
 
 gboolean
@@ -177,6 +251,12 @@ cogl_renderer_connect (CoglRenderer *renderer, GError **error)
   if (renderer->connected)
     return TRUE;
 
+  /* The driver needs to be chosen before connecting the renderer
+     because eglInitialize requires the library containing the GL API
+     to be loaded before its called */
+  if (!_cogl_renderer_choose_driver (renderer, error))
+    return FALSE;
+
   error_message = g_string_new ("");
   for (i = 0; i < G_N_ELEMENTS (_cogl_winsys_vtable_getters); i++)
     {
diff --git a/cogl/cogl-shader-boilerplate.h b/cogl/cogl-shader-boilerplate.h
index 3a23de1..b46b7b4 100644
--- a/cogl/cogl-shader-boilerplate.h
+++ b/cogl/cogl-shader-boilerplate.h
@@ -29,10 +29,7 @@
 
 #include "cogl.h"
 
-
-#ifndef HAVE_COGL_GLES2
-
-#define _COGL_COMMON_SHADER_BOILERPLATE \
+#define _COGL_COMMON_SHADER_BOILERPLATE_GL \
   "#define COGL_VERSION 100\n" \
   "\n" \
   "#define cogl_modelview_matrix gl_ModelViewMatrix\n" \
@@ -41,8 +38,8 @@
   "#define cogl_texture_matrix gl_TextureMatrix\n" \
   "\n"
 
-#define _COGL_VERTEX_SHADER_BOILERPLATE \
-  _COGL_COMMON_SHADER_BOILERPLATE \
+#define _COGL_VERTEX_SHADER_BOILERPLATE_GL \
+  _COGL_COMMON_SHADER_BOILERPLATE_GL \
   "#define cogl_position_in gl_Vertex\n" \
   "#define cogl_color_in gl_Color\n" \
   "#define cogl_tex_coord_in  gl_MultiTexCoord0\n" \
@@ -61,8 +58,8 @@
   "#define cogl_color_out gl_FrontColor\n" \
   "#define cogl_tex_coord_out gl_TexCoord\n"
 
-#define _COGL_FRAGMENT_SHADER_BOILERPLATE \
-  _COGL_COMMON_SHADER_BOILERPLATE \
+#define _COGL_FRAGMENT_SHADER_BOILERPLATE_GL \
+  _COGL_COMMON_SHADER_BOILERPLATE_GL \
   "#define cogl_color_in gl_Color\n" \
   "#define cogl_tex_coord_in gl_TexCoord\n" \
   "\n" \
@@ -77,9 +74,7 @@
   "#define coglFragCoord   gl_FragCoord\n"
 #endif
 
-#else /* HAVE_COGL_GLES2 */
-
-#define _COGL_COMMON_SHADER_BOILERPLATE \
+#define _COGL_COMMON_SHADER_BOILERPLATE_GLES2 \
   "#define COGL_VERSION 100\n" \
   "\n" \
   "uniform mat4 cogl_modelview_matrix;\n" \
@@ -92,8 +87,8 @@
    if they are not actually used. The GLSL spec for GLES at least
    implies that this will happen for varyings but it doesn't
    explicitly so for attributes */
-#define _COGL_VERTEX_SHADER_BOILERPLATE \
-  _COGL_COMMON_SHADER_BOILERPLATE \
+#define _COGL_VERTEX_SHADER_BOILERPLATE_GLES2 \
+  _COGL_COMMON_SHADER_BOILERPLATE_GLES2 \
   "#define cogl_color_out _cogl_color\n" \
   "varying vec4 _cogl_color;\n" \
   "#define cogl_tex_coord_out _cogl_tex_coord\n" \
@@ -105,11 +100,11 @@
   "#define cogl_tex_coord_in cogl_tex_coord0_in;\n" \
   "attribute vec3 cogl_normal_in;\n"
 
-#define _COGL_FRAGMENT_SHADER_BOILERPLATE \
+#define _COGL_FRAGMENT_SHADER_BOILERPLATE_GLES2 \
   "#if __VERSION__ == 100\n" \
   "precision highp float;\n" \
   "#endif\n" \
-  _COGL_COMMON_SHADER_BOILERPLATE \
+  _COGL_COMMON_SHADER_BOILERPLATE_GLES2 \
   "\n" \
   "varying vec4 _cogl_color;\n" \
   "\n" \
@@ -121,7 +116,5 @@
   "\n" \
   "#define cogl_front_facing gl_FrontFacing\n"
 
-#endif /* HAVE_COGL_GLES2 */
-
 #endif /* __COGL_SHADER_BOILERPLATE_H */
 
diff --git a/cogl/cogl-shader-private.h b/cogl/cogl-shader-private.h
index 3b4b232..ee35816 100644
--- a/cogl/cogl-shader-private.h
+++ b/cogl/cogl-shader-private.h
@@ -31,9 +31,7 @@ typedef struct _CoglShader CoglShader;
 typedef enum
 {
   COGL_SHADER_LANGUAGE_GLSL,
-#ifdef HAVE_COGL_GL
   COGL_SHADER_LANGUAGE_ARBFP
-#endif
 } CoglShaderLanguage;
 
 struct _CoglShader
diff --git a/cogl/cogl-shader.c b/cogl/cogl-shader.c
index 996676b..4d662ab 100644
--- a/cogl/cogl-shader.c
+++ b/cogl/cogl-shader.c
@@ -41,11 +41,16 @@ static void _cogl_shader_free (CoglShader *shader);
 COGL_HANDLE_DEFINE (Shader, shader);
 COGL_OBJECT_DEFINE_DEPRECATED_REF_COUNTING (shader);
 
+#ifndef GL_FRAGMENT_SHADER
+#define GL_FRAGMENT_SHADER 0x8B30
+#endif
+#ifndef GL_VERTEX_SHADER
+#define GL_VERTEX_SHADER 0x8B31
+#endif
+
 static void
 _cogl_shader_free (CoglShader *shader)
 {
-#ifndef HAVE_COGL_GLES
-
   /* Frees shader resources but its handle is not
      released! Do that separately before this! */
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
@@ -61,8 +66,6 @@ _cogl_shader_free (CoglShader *shader)
     if (shader->gl_handle)
       GE (ctx, glDeleteShader (shader->gl_handle));
 
-#endif /* HAVE_COGL_GLES */
-
   g_slice_free (CoglShader, shader);
 }
 
@@ -98,8 +101,6 @@ cogl_create_shader (CoglShaderType type)
 static void
 delete_shader (CoglShader *shader)
 {
-#ifndef HAVE_COGL_GLES
-
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
 #ifdef HAVE_COGL_GL
@@ -116,8 +117,6 @@ delete_shader (CoglShader *shader)
     }
 
   shader->gl_handle = 0;
-
-#endif /* HAVE_COGL_GLES */
 }
 
 void
@@ -154,16 +153,15 @@ cogl_shader_source (CoglHandle   handle,
 void
 cogl_shader_compile (CoglHandle handle)
 {
-#ifdef HAVE_COGL_GL
   CoglShader *shader = handle;
-#endif
+
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
   if (!cogl_is_shader (handle))
     return;
 
-#ifdef HAVE_COGL_GL
-  _cogl_shader_compile_real (shader, 0 /* ignored */);
-#endif
+  if (ctx->driver == COGL_DRIVER_GL)
+    _cogl_shader_compile_real (shader, 0 /* ignored */);
 
   /* XXX: For GLES2 we don't actually compile anything until the
    * shader gets used so we have an opportunity to add some
@@ -183,43 +181,49 @@ _cogl_shader_set_source_with_boilerplate (GLuint shader_gl_handle,
                                           const char **strings_in,
                                           const GLint *lengths_in)
 {
-#ifndef HAVE_COGL_GLES
-
-  static const char vertex_boilerplate[] = _COGL_VERTEX_SHADER_BOILERPLATE;
-  static const char fragment_boilerplate[] = _COGL_FRAGMENT_SHADER_BOILERPLATE;
+  const char *vertex_boilerplate;
+  const char *fragment_boilerplate;
 
   const char **strings = g_alloca (sizeof (char *) * (count_in + 3));
   GLint *lengths = g_alloca (sizeof (GLint) * (count_in + 3));
   int count = 0;
-#ifdef HAVE_COGL_GLES2
   char *tex_coord_declarations = NULL;
-#endif
 
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
-#ifdef HAVE_COGL_GLES2
-  if (cogl_features_available (COGL_FEATURE_TEXTURE_3D))
+  if (ctx->driver == COGL_DRIVER_GLES2)
+    {
+      vertex_boilerplate = _COGL_VERTEX_SHADER_BOILERPLATE_GLES2;
+      fragment_boilerplate = _COGL_FRAGMENT_SHADER_BOILERPLATE_GLES2;
+    }
+  else
+    {
+      vertex_boilerplate = _COGL_VERTEX_SHADER_BOILERPLATE_GL;
+      fragment_boilerplate = _COGL_FRAGMENT_SHADER_BOILERPLATE_GL;
+    }
+
+  if (ctx->driver == COGL_DRIVER_GLES2 &&
+      cogl_features_available (COGL_FEATURE_TEXTURE_3D))
     {
       static const char texture_3d_extension[] =
         "#extension GL_OES_texture_3D : enable\n";
       strings[count] = texture_3d_extension;
       lengths[count++] = sizeof (texture_3d_extension) - 1;
     }
-#endif
 
   if (shader_gl_type == GL_VERTEX_SHADER)
     {
       strings[count] = vertex_boilerplate;
-      lengths[count++] = sizeof (vertex_boilerplate) - 1;
+      lengths[count++] = strlen (vertex_boilerplate);
     }
   else if (shader_gl_type == GL_FRAGMENT_SHADER)
     {
       strings[count] = fragment_boilerplate;
-      lengths[count++] = sizeof (fragment_boilerplate) - 1;
+      lengths[count++] = strlen (fragment_boilerplate);
     }
 
-#ifdef HAVE_COGL_GLES2
-  if (n_tex_coord_attribs)
+  if (ctx->driver == COGL_DRIVER_GLES2 &&
+      n_tex_coord_attribs)
     {
       GString *declarations = g_string_new (NULL);
 
@@ -245,7 +249,6 @@ _cogl_shader_set_source_with_boilerplate (GLuint shader_gl_handle,
       strings[count] = tex_coord_declarations;
       lengths[count++] = -1; /* null terminated */
     }
-#endif
 
   memcpy (strings + count, strings_in, sizeof (char *) * count_in);
   if (lengths_in)
@@ -282,19 +285,13 @@ _cogl_shader_set_source_with_boilerplate (GLuint shader_gl_handle,
   GE( ctx, glShaderSource (shader_gl_handle, count,
                            (const char **) strings, lengths) );
 
-#ifdef HAVE_COGL_GLES2
   g_free (tex_coord_declarations);
-#endif
-
-#endif /* HAVE_COGL_GLES */
 }
 
 void
 _cogl_shader_compile_real (CoglHandle handle,
                            int n_tex_coord_attribs)
 {
-#ifndef HAVE_COGL_GLES
-
   CoglShader *shader = handle;
 
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
@@ -343,7 +340,9 @@ _cogl_shader_compile_real (CoglHandle handle,
 
       if (shader->gl_handle
 #ifdef HAVE_COGL_GLES2
-          && shader->n_tex_coord_attribs >= n_tex_coord_attribs
+          &&
+          (ctx->driver != COGL_DRIVER_GLES2 ||
+           shader->n_tex_coord_attribs >= n_tex_coord_attribs)
 #endif
          )
         return;
@@ -389,19 +388,11 @@ _cogl_shader_compile_real (CoglHandle handle,
         }
 #endif
     }
-
-#endif /* HAVE_COGL_GLES */
 }
 
 char *
 cogl_shader_get_info_log (CoglHandle handle)
 {
-#ifdef HAVE_COGL_GLES
-
-  return NULL;
-
-#else /* HAVE_COGL_GLES */
-
   CoglShader *shader;
 
   _COGL_GET_CONTEXT (ctx, NULL);
@@ -443,8 +434,6 @@ cogl_shader_get_info_log (CoglHandle handle)
       buffer[len] = '\0';
       return g_strdup (buffer);
     }
-
-#endif /* HAVE_COGL_GLES */
 }
 
 CoglShaderType
@@ -467,12 +456,7 @@ cogl_shader_get_type (CoglHandle  handle)
 gboolean
 cogl_shader_is_compiled (CoglHandle handle)
 {
-#ifdef HAVE_COGL_GLES
-
-  return FALSE;
-
-#else /* HAVE_COGL_GLES */
-
+#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES2)
   GLint status;
   CoglShader *shader;
 
@@ -513,6 +497,7 @@ cogl_shader_is_compiled (CoglHandle handle)
       else
         return FALSE;
     }
-
-#endif /* HAVE_COGL_GLES */
+#else
+  return FALSE;
+#endif
 }
diff --git a/cogl/cogl-texture-2d.c b/cogl/cogl-texture-2d.c
index 8887204..71ff44a 100644
--- a/cogl/cogl-texture-2d.c
+++ b/cogl/cogl-texture-2d.c
@@ -430,37 +430,38 @@ cogl_texture_2d_new_from_foreign (CoglContext *ctx,
      (only level 0 we are interested in) */
 
 #if HAVE_COGL_GL
+  if (ctx->driver == COGL_DRIVER_GL)
+    {
+      GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_2D, 0,
+                                         GL_TEXTURE_COMPRESSED,
+                                         &gl_compressed) );
 
-  GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_2D, 0,
-                                     GL_TEXTURE_COMPRESSED,
-                                     &gl_compressed) );
-
-  {
-    GLint val;
-
-    GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_2D, 0,
-                                       GL_TEXTURE_INTERNAL_FORMAT,
-                                       &val) );
-
-    gl_int_format = val;
-  }
+      {
+        GLint val;
 
-  /* If we can query GL for the actual pixel format then we'll ignore
-     the passed in format and use that. */
-  if (!ctx->texture_driver->pixel_format_from_gl_internal (gl_int_format,
-                                                           &format))
-    return COGL_INVALID_HANDLE;
+        GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_2D, 0,
+                                           GL_TEXTURE_INTERNAL_FORMAT,
+                                           &val) );
 
-#else
-
-  /* Otherwise we'll assume we can derive the GL format from the
-     passed in format */
-  ctx->texture_driver->pixel_format_to_gl (format,
-                                           &gl_int_format,
-                                           NULL,
-                                           NULL);
+        gl_int_format = val;
+      }
 
+      /* If we can query GL for the actual pixel format then we'll ignore
+         the passed in format and use that. */
+      if (!ctx->texture_driver->pixel_format_from_gl_internal (gl_int_format,
+                                                               &format))
+        return COGL_INVALID_HANDLE;
+    }
+  else
 #endif
+    {
+      /* Otherwise we'll assume we can derive the GL format from the
+         passed in format */
+      ctx->texture_driver->pixel_format_to_gl (format,
+                                               &gl_int_format,
+                                               NULL,
+                                               NULL);
+    }
 
   /* Note: We always trust the given width and height without querying
    * the texture object because the user may be creating a Cogl
@@ -772,7 +773,7 @@ _cogl_texture_2d_pre_paint (CoglTexture *tex, CoglTexturePrePaintFlags flags)
          GL_GENERATE_MIPMAP and reuploading the first pixel */
       if (cogl_features_available (COGL_FEATURE_OFFSCREEN))
         ctx->texture_driver->gl_generate_mipmaps (GL_TEXTURE_2D);
-#ifndef HAVE_COGL_GLES2
+#if defined(HAVE_COGL_GLES) || defined(HAVE_COGL_GL)
       else
         {
           GE( ctx, glTexParameteri (GL_TEXTURE_2D,
diff --git a/cogl/cogl-texture-3d.c b/cogl/cogl-texture-3d.c
index 48e2e2d..a64c3d2 100644
--- a/cogl/cogl-texture-3d.c
+++ b/cogl/cogl-texture-3d.c
@@ -580,8 +580,8 @@ _cogl_texture_3d_pre_paint (CoglTexture *tex, CoglTexturePrePaintFlags flags)
          GL_GENERATE_MIPMAP and reuploading the first pixel */
       if (cogl_features_available (COGL_FEATURE_OFFSCREEN))
         ctx->texture_driver->gl_generate_mipmaps (GL_TEXTURE_3D);
-#ifndef HAVE_COGL_GLES2
-      else
+#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
+      else if (ctx->driver != COGL_DRIVER_GLES2)
         {
           GE( ctx, glTexParameteri (GL_TEXTURE_3D,
                                     GL_GENERATE_MIPMAP,
diff --git a/cogl/cogl-texture-rectangle.c b/cogl/cogl-texture-rectangle.c
index 88cf5bc..e98be8d 100644
--- a/cogl/cogl-texture-rectangle.c
+++ b/cogl/cogl-texture-rectangle.c
@@ -372,37 +372,36 @@ _cogl_texture_rectangle_new_from_foreign (GLuint gl_handle,
   /* Obtain texture parameters */
 
 #if HAVE_COGL_GL
+  if (ctx->driver == COGL_DRIVER_GL)
+    {
+      GLint val;
 
-  GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_RECTANGLE_ARB, 0,
-                                     GL_TEXTURE_COMPRESSED,
-                                     &gl_compressed) );
-
-  {
-    GLint val;
-
-    GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_RECTANGLE_ARB, 0,
-                                       GL_TEXTURE_INTERNAL_FORMAT,
-                                       &val) );
-
-    gl_int_format = val;
-  }
+      GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_RECTANGLE_ARB, 0,
+                                         GL_TEXTURE_COMPRESSED,
+                                         &gl_compressed) );
 
-  /* If we can query GL for the actual pixel format then we'll ignore
-     the passed in format and use that. */
-  if (!ctx->texture_driver->pixel_format_from_gl_internal (gl_int_format,
-                                                           &format))
-    return COGL_INVALID_HANDLE;
+      GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_RECTANGLE_ARB, 0,
+                                         GL_TEXTURE_INTERNAL_FORMAT,
+                                         &val) );
 
-#else
-
-  /* Otherwise we'll assume we can derive the GL format from the
-     passed in format */
-  ctx->texture_driver->pixel_format_to_gl (format,
-                                           &gl_int_format,
-                                           NULL,
-                                           NULL);
+      gl_int_format = val;
 
+      /* If we can query GL for the actual pixel format then we'll ignore
+         the passed in format and use that. */
+      if (!ctx->texture_driver->pixel_format_from_gl_internal (gl_int_format,
+                                                               &format))
+        return COGL_INVALID_HANDLE;
+    }
+  else
 #endif
+    {
+      /* Otherwise we'll assume we can derive the GL format from the
+         passed in format */
+      ctx->texture_driver->pixel_format_to_gl (format,
+                                               &gl_int_format,
+                                               NULL,
+                                               NULL);
+    }
 
   /* Note: We always trust the given width and height without querying
    * the texture object because the user may be creating a Cogl
diff --git a/cogl/cogl-texture.c b/cogl/cogl-texture.c
index ffd38b7..134e5f5 100644
--- a/cogl/cogl-texture.c
+++ b/cogl/cogl-texture.c
@@ -194,54 +194,54 @@ _cogl_texture_prepare_for_upload (CoglBitmap      *src_bmp,
      limited number of formats so we must convert using the Cogl
      bitmap code instead */
 
-#ifdef HAVE_COGL_GL
-
-  /* If the source format does not have the same premult flag as the
-     dst format then we need to copy and convert it */
-  if (_cogl_texture_needs_premult_conversion (src_format,
-                                              dst_format))
+  if (ctx->driver == COGL_DRIVER_GL)
     {
-      dst_bmp = _cogl_bitmap_copy (src_bmp);
-
-      if (!_cogl_bitmap_convert_premult_status (dst_bmp,
-                                                src_format ^
-                                                COGL_PREMULT_BIT))
+      /* If the source format does not have the same premult flag as the
+         dst format then we need to copy and convert it */
+      if (_cogl_texture_needs_premult_conversion (src_format,
+                                                  dst_format))
         {
-          cogl_object_unref (dst_bmp);
-          return NULL;
+          dst_bmp = _cogl_bitmap_copy (src_bmp);
+
+          if (!_cogl_bitmap_convert_premult_status (dst_bmp,
+                                                    src_format ^
+                                                    COGL_PREMULT_BIT))
+            {
+              cogl_object_unref (dst_bmp);
+              return NULL;
+            }
         }
+      else
+        dst_bmp = cogl_object_ref (src_bmp);
+
+      /* Use the source format from the src bitmap type and the internal
+         format from the dst format type so that GL can do the
+         conversion */
+      ctx->texture_driver->pixel_format_to_gl (src_format,
+                                               NULL, /* internal format */
+                                               out_glformat,
+                                               out_gltype);
+      ctx->texture_driver->pixel_format_to_gl (dst_format,
+                                               out_glintformat,
+                                               NULL,
+                                               NULL);
+
     }
   else
-    dst_bmp = cogl_object_ref (src_bmp);
+    {
+      CoglPixelFormat closest_format;
 
-  /* Use the source format from the src bitmap type and the internal
-     format from the dst format type so that GL can do the
-     conversion */
-  ctx->texture_driver->pixel_format_to_gl (src_format,
-                                           NULL, /* internal format */
-                                           out_glformat,
-                                           out_gltype);
-  ctx->texture_driver->pixel_format_to_gl (dst_format,
-                                           out_glintformat,
-                                           NULL,
-                                           NULL);
-
-#else /* HAVE_COGL_GL */
-  {
-    CoglPixelFormat closest_format;
-
-    closest_format = ctx->texture_driver->pixel_format_to_gl (dst_format,
-                                                              out_glintformat,
-                                                              out_glformat,
-                                                              out_gltype);
-
-    if (closest_format != src_format)
-      dst_bmp = _cogl_bitmap_convert_format_and_premult (src_bmp,
-                                                         closest_format);
-    else
-      dst_bmp = cogl_object_ref (src_bmp);
-  }
-#endif /* HAVE_COGL_GL */
+      closest_format = ctx->texture_driver->pixel_format_to_gl (dst_format,
+                                                                out_glintformat,
+                                                                out_glformat,
+                                                                out_gltype);
+
+      if (closest_format != src_format)
+        dst_bmp = _cogl_bitmap_convert_format_and_premult (src_bmp,
+                                                           closest_format);
+      else
+        dst_bmp = cogl_object_ref (src_bmp);
+    }
 
   if (dst_format_out)
     *dst_format_out = dst_format;
diff --git a/cogl/cogl.c b/cogl/cogl.c
index b77a623..7b2990e 100644
--- a/cogl/cogl.c
+++ b/cogl/cogl.c
@@ -164,15 +164,7 @@ toggle_flag (CoglContext *ctx,
   return FALSE;
 }
 
-#ifdef HAVE_COGL_GLES2
-
-/* Under GLES2 there are no builtin client flags so toggle_client_flag
-   should never be reached */
-
-#define toggle_client_flag(ctx, new_flags, flag, gl_flag) \
-  g_assert (((new_flags) & (flag)) == 0)
-
-#else /* HAVE_COGL_GLES2 */
+#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
 
 static gboolean
 toggle_client_flag (CoglContext *ctx,
@@ -180,6 +172,8 @@ toggle_client_flag (CoglContext *ctx,
 		    unsigned long flag,
 		    GLenum gl_flag)
 {
+  g_return_val_if_fail (ctx->driver != COGL_DRIVER_GLES2, FALSE);
+
   /* Toggles and caches a single client-side enable flag
    * on or off by comparing to current state
    */
@@ -201,7 +195,7 @@ toggle_client_flag (CoglContext *ctx,
   return FALSE;
 }
 
-#endif /* HAVE_COGL_GLES2 */
+#endif
 
 void
 _cogl_enable (unsigned long flags)
@@ -215,13 +209,18 @@ _cogl_enable (unsigned long flags)
                COGL_ENABLE_BACKFACE_CULLING,
                GL_CULL_FACE);
 
-  toggle_client_flag (ctx, flags,
-		      COGL_ENABLE_VERTEX_ARRAY,
-		      GL_VERTEX_ARRAY);
+#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
+  if (ctx->driver != COGL_DRIVER_GLES2)
+    {
+      toggle_client_flag (ctx, flags,
+                          COGL_ENABLE_VERTEX_ARRAY,
+                          GL_VERTEX_ARRAY);
 
-  toggle_client_flag (ctx, flags,
-		      COGL_ENABLE_COLOR_ARRAY,
-		      GL_COLOR_ARRAY);
+      toggle_client_flag (ctx, flags,
+                          COGL_ENABLE_COLOR_ARRAY,
+                          GL_COLOR_ARRAY);
+    }
+#endif
 }
 
 unsigned long
@@ -557,9 +556,9 @@ _cogl_read_pixels_with_rowstride (int x,
      GL_RGBA/GL_UNSIGNED_BYTE and convert if necessary. We also need
      to use this intermediate buffer if the rowstride has padding
      because GLES does not support setting GL_ROW_LENGTH */
-#ifndef COGL_HAS_GL
-  if (gl_format != GL_RGBA || gl_type != GL_UNSIGNED_BYTE ||
-      rowstride != 4 * width)
+  if (ctx->driver != COGL_DRIVER_GL &&
+      (gl_format != GL_RGBA || gl_type != GL_UNSIGNED_BYTE ||
+       rowstride != 4 * width))
     {
       CoglBitmap *tmp_bmp, *dst_bmp;
       guint8 *tmp_data = g_malloc (width * height * 4);
@@ -599,7 +598,6 @@ _cogl_read_pixels_with_rowstride (int x,
       cogl_object_unref (tmp_bmp);
     }
   else
-#endif
     {
       ctx->texture_driver->prep_gl_for_pixels_download (rowstride, bpp);
 
diff --git a/cogl/driver/gl/cogl-gl.c b/cogl/driver/gl/cogl-gl.c
index a701cb7..e2c1a3c 100644
--- a/cogl/driver/gl/cogl-gl.c
+++ b/cogl/driver/gl/cogl-gl.c
@@ -72,13 +72,12 @@ _cogl_get_gl_version (int *major_out, int *minor_out)
 }
 
 gboolean
-_cogl_gl_check_version (GError **error)
+_cogl_gl_check_gl_version (CoglContext *ctx,
+                           GError **error)
 {
   int major, minor;
   const char *gl_extensions;
 
-  _COGL_GET_CONTEXT (ctx, FALSE);
-
   if (!_cogl_get_gl_version (&major, &minor))
     {
       g_set_error (error,
@@ -166,8 +165,7 @@ _cogl_gl_update_features (CoglContext *context)
   _cogl_feature_check_ext_functions (context,
                                      gl_major,
                                      gl_minor,
-                                     gl_extensions,
-                                     0 /* gles_version */);
+                                     gl_extensions);
 
   if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 2, 0) ||
       _cogl_check_extension ("GL_ARB_texture_non_power_of_two", gl_extensions))
diff --git a/cogl/driver/gles/cogl-gles.c b/cogl/driver/gles/cogl-gles.c
index 0d97d2b..7035c69 100644
--- a/cogl/driver/gles/cogl-gles.c
+++ b/cogl/driver/gles/cogl-gles.c
@@ -33,7 +33,7 @@
 #include "cogl-feature-private.h"
 
 gboolean
-_cogl_gl_check_version (GError **error)
+_cogl_gles_check_gl_version (GError **error)
 {
   /* The GLES backend doesn't have any particular version requirements */
   return TRUE;
@@ -44,14 +44,11 @@ _cogl_gl_check_version (GError **error)
  * different GL contexts so it is the winsys backend's responsiblity
  * to know when to re-query the GL extensions. */
 void
-_cogl_gl_update_features (CoglContext *context)
+_cogl_gles_update_features (CoglContext *context)
 {
   CoglPrivateFeatureFlags private_flags = 0;
   CoglFeatureFlags flags = 0;
   const char *gl_extensions;
-#ifndef HAVE_COGL_GLES2
-  int max_clip_planes = 0;
-#endif
   int num_stencil_bits = 0;
 
   /* We have to special case getting the pointer to the glGetString
@@ -77,32 +74,31 @@ _cogl_gl_update_features (CoglContext *context)
   _cogl_feature_check_ext_functions (context,
                                      -1 /* GL major version */,
                                      -1 /* GL minor version */,
-                                     gl_extensions,
-#ifdef HAVE_COGL_GLES2
-                                     COGL_EXT_IN_GLES2
-#else
-                                     COGL_EXT_IN_GLES
-#endif
-                                     );
+                                     gl_extensions);
 
   GE( context, glGetIntegerv (GL_STENCIL_BITS, &num_stencil_bits) );
   /* We need at least three stencil bits to combine clips */
   if (num_stencil_bits > 2)
     flags |= COGL_FEATURE_STENCIL_BUFFER;
 
-#ifndef HAVE_COGL_GLES2
-  GE( context, glGetIntegerv (GL_MAX_CLIP_PLANES, &max_clip_planes) );
-  if (max_clip_planes >= 4)
-    flags |= COGL_FEATURE_FOUR_CLIP_PLANES;
+#ifdef HAVE_COGL_GLES
+  if (context->driver == COGL_DRIVER_GLES1)
+    {
+      int max_clip_planes;
+      GE( context, glGetIntegerv (GL_MAX_CLIP_PLANES, &max_clip_planes) );
+      if (max_clip_planes >= 4)
+        flags |= COGL_FEATURE_FOUR_CLIP_PLANES;
+    }
 #endif
 
-#ifdef HAVE_COGL_GLES2
-  flags |= COGL_FEATURE_SHADERS_GLSL | COGL_FEATURE_OFFSCREEN;
-  /* Note GLES 2 core doesn't support mipmaps for npot textures or
-   * repeat modes other than CLAMP_TO_EDGE. */
-  flags |= COGL_FEATURE_TEXTURE_NPOT_BASIC;
-  flags |= COGL_FEATURE_DEPTH_RANGE;
-#endif
+  if (context->driver == COGL_DRIVER_GLES2)
+    {
+      flags |= COGL_FEATURE_SHADERS_GLSL | COGL_FEATURE_OFFSCREEN;
+      /* Note GLES 2 core doesn't support mipmaps for npot textures or
+       * repeat modes other than CLAMP_TO_EDGE. */
+      flags |= COGL_FEATURE_TEXTURE_NPOT_BASIC;
+      flags |= COGL_FEATURE_DEPTH_RANGE;
+    }
 
   flags |= COGL_FEATURE_VBOS;
 
diff --git a/cogl/driver/gles/cogl-texture-driver-gles.c b/cogl/driver/gles/cogl-texture-driver-gles.c
index 0571848..5123993 100644
--- a/cogl/driver/gles/cogl-texture-driver-gles.c
+++ b/cogl/driver/gles/cogl-texture-driver-gles.c
@@ -499,11 +499,10 @@ _cogl_texture_driver_allows_foreign_gl_target (GLenum gl_target)
 static void
 _cogl_texture_driver_gl_generate_mipmaps (GLenum gl_target)
 {
-#ifdef HAVE_COGL_GLES2
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
-  GE( ctx, glGenerateMipmap (gl_target) );
-#endif
+  if (ctx->driver == COGL_DRIVER_GLES2)
+    GE( ctx, glGenerateMipmap (gl_target) );
 }
 
 static CoglPixelFormat
diff --git a/cogl/winsys/cogl-winsys-egl.c b/cogl/winsys/cogl-winsys-egl.c
index 5597cd1..9717906 100644
--- a/cogl/winsys/cogl-winsys-egl.c
+++ b/cogl/winsys/cogl-winsys-egl.c
@@ -353,7 +353,8 @@ check_egl_extensions (CoglRenderer *renderer)
   egl_renderer->private_features = 0;
   for (i = 0; i < G_N_ELEMENTS (winsys_feature_data); i++)
     if (_cogl_feature_check (winsys,
-                             "EGL", winsys_feature_data + i, 0, 0, 0,
+                             "EGL", winsys_feature_data + i, 0, 0,
+                             COGL_DRIVER_GL, /* the driver isn't used */
                              egl_extensions,
                              egl_renderer))
       {
@@ -514,7 +515,7 @@ update_winsys_features (CoglContext *context)
 
   check_egl_extensions (context->display->renderer);
 
-  _cogl_gl_update_features (context);
+  _cogl_context_update_features (context);
 
 #if defined (COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT) || \
     defined (COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT)
@@ -619,23 +620,17 @@ try_create_context (CoglDisplay *display,
 
     EGL_BUFFER_SIZE,     EGL_DONT_CARE,
 
-#if defined (HAVE_COGL_GL)
-    EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
-#elif defined (HAVE_COGL_GLES2)
-    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-#else
-    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
-#endif
+    EGL_RENDERABLE_TYPE, (display->renderer->driver == COGL_DRIVER_GL ?
+                          EGL_OPENGL_BIT :
+                          display->renderer->driver == COGL_DRIVER_GLES1 ?
+                          EGL_OPENGL_ES_BIT :
+                          EGL_OPENGL_ES2_BIT),
 
     EGL_SURFACE_TYPE,    EGL_WINDOW_BIT,
 
     EGL_NONE
   };
-#if defined (HAVE_COGL_GLES2)
-  EGLint attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
-#else
-  EGLint *attribs = NULL;
-#endif
+  EGLint attribs[3];
 
 #ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
   XVisualInfo *xvisinfo;
@@ -646,11 +641,19 @@ try_create_context (CoglDisplay *display,
 #endif
   const char *error_message;
 
+  if (display->renderer->driver == COGL_DRIVER_GLES2)
+    {
+      attribs[0] = EGL_CONTEXT_CLIENT_VERSION;
+      attribs[1] = 2;
+      attribs[2] = EGL_NONE;
+    }
+  else
+    attribs[0] = EGL_NONE;
+
   edpy = egl_renderer->edpy;
 
-#ifdef HAVE_COGL_GL
-  eglBindAPI (EGL_OPENGL_API);
-#endif
+  if (display->renderer->driver == COGL_DRIVER_GL)
+    eglBindAPI (EGL_OPENGL_API);
 
   /* Some GLES hardware can't support a stencil buffer: */
   if (retry_cookie == 1)
diff --git a/cogl/winsys/cogl-winsys-glx.c b/cogl/winsys/cogl-winsys-glx.c
index 80c3767..b4ee25e 100644
--- a/cogl/winsys/cogl-winsys-glx.c
+++ b/cogl/winsys/cogl-winsys-glx.c
@@ -265,17 +265,75 @@ glx_event_filter_cb (XEvent *xevent, void *data)
 static void
 _cogl_winsys_renderer_disconnect (CoglRenderer *renderer)
 {
+  CoglGLXRenderer *glx_renderer = renderer->winsys;
+
   _cogl_xlib_renderer_disconnect (renderer);
 
+  if (glx_renderer->libgl_module)
+    g_module_close (glx_renderer->libgl_module);
+
   g_slice_free (CoglGLXRenderer, renderer->winsys);
 }
 
 static gboolean
+resolve_core_glx_functions (CoglRenderer *renderer,
+                            GError **error)
+{
+  CoglGLXRenderer *glx_renderer;
+
+  glx_renderer = renderer->winsys;
+
+  if (!g_module_symbol (glx_renderer->libgl_module, "glXCreatePixmap",
+                        (void **) &glx_renderer->glXCreatePixmap) ||
+      !g_module_symbol (glx_renderer->libgl_module, "glXDestroyPixmap",
+                        (void **) &glx_renderer->glXDestroyPixmap) ||
+      !g_module_symbol (glx_renderer->libgl_module, "glXChooseFBConfig",
+                        (void **) &glx_renderer->glXChooseFBConfig) ||
+      !g_module_symbol (glx_renderer->libgl_module, "glXCreateNewContext",
+                        (void **) &glx_renderer->glXCreateNewContext) ||
+      !g_module_symbol (glx_renderer->libgl_module, "glXGetFBConfigAttrib",
+                        (void **) &glx_renderer->glXGetFBConfigAttrib) ||
+      !g_module_symbol (glx_renderer->libgl_module, "glXQueryVersion",
+                        (void **) &glx_renderer->glXQueryVersion) ||
+      !g_module_symbol (glx_renderer->libgl_module, "glXDestroyContext",
+                        (void **) &glx_renderer->glXDestroyContext) ||
+      !g_module_symbol (glx_renderer->libgl_module, "glXMakeContextCurrent",
+                        (void **) &glx_renderer->glXMakeContextCurrent) ||
+      !g_module_symbol (glx_renderer->libgl_module, "glXSwapBuffers",
+                        (void **) &glx_renderer->glXSwapBuffers) ||
+      !g_module_symbol (glx_renderer->libgl_module, "glXQueryExtension",
+                        (void **) &glx_renderer->glXQueryExtension) ||
+      !g_module_symbol (glx_renderer->libgl_module, "glXIsDirect",
+                        (void **) &glx_renderer->glXIsDirect) ||
+      !g_module_symbol (glx_renderer->libgl_module, "glXGetVisualFromFBConfig",
+                        (void **) &glx_renderer->glXGetVisualFromFBConfig) ||
+      !g_module_symbol (glx_renderer->libgl_module, "glXSelectEvent",
+                        (void **) &glx_renderer->glXSelectEvent) ||
+      !g_module_symbol (glx_renderer->libgl_module, "glXCreateWindow",
+                        (void **) &glx_renderer->glXCreateWindow) ||
+      !g_module_symbol (glx_renderer->libgl_module, "glXGetFBConfigs",
+                        (void **) &glx_renderer->glXGetFBConfigs) ||
+      !g_module_symbol (glx_renderer->libgl_module, "glXDestroyWindow",
+                        (void **) &glx_renderer->glXDestroyWindow) ||
+      !g_module_symbol (glx_renderer->libgl_module, "glXQueryExtensionsString",
+                        (void **) &glx_renderer->glXQueryExtensionsString))
+    {
+      g_set_error (error, COGL_WINSYS_ERROR,
+                   COGL_WINSYS_ERROR_INIT,
+                   "Failed to resolve required GLX symbol");
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static gboolean
 _cogl_winsys_renderer_connect (CoglRenderer *renderer,
                                GError **error)
 {
   CoglGLXRenderer *glx_renderer;
   CoglXlibRenderer *xlib_renderer;
+  char *libgl_module_path;
 
   renderer->winsys = g_slice_new0 (CoglGLXRenderer);
 
@@ -285,9 +343,28 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer,
   if (!_cogl_xlib_renderer_connect (renderer, error))
     goto error;
 
-  if (!glXQueryExtension (xlib_renderer->xdpy,
-                          &glx_renderer->glx_error_base,
-                          &glx_renderer->glx_event_base))
+  libgl_module_path = g_module_build_path (NULL, /* standard lib search path */
+                                           COGL_GL_LIBNAME);
+
+  glx_renderer->libgl_module = g_module_open (libgl_module_path,
+                                              G_MODULE_BIND_LAZY);
+
+  g_free (libgl_module_path);
+
+  if (glx_renderer->libgl_module == NULL)
+    {
+      g_set_error (error, COGL_WINSYS_ERROR,
+                   COGL_WINSYS_ERROR_INIT,
+                   "Failed to dynamically open the OpenGL library");
+      goto error;
+    }
+
+  if (!resolve_core_glx_functions (renderer, error))
+    goto error;
+
+  if (!glx_renderer->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,
@@ -298,9 +375,9 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer,
   /* 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)
+  if (!glx_renderer->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,
@@ -325,17 +402,19 @@ update_winsys_features (CoglContext *context)
   CoglXlibRenderer *xlib_renderer = context->display->renderer->winsys;
   CoglGLXRenderer *glx_renderer = context->display->renderer->winsys;
   const char *glx_extensions;
+  int default_screen;
   int i;
 
   g_return_if_fail (glx_display->glx_context);
 
-  _cogl_gl_update_features (context);
+  _cogl_context_update_features (context);
 
   memset (context->winsys_features, 0, sizeof (context->winsys_features));
 
+  default_screen = DefaultScreen (xlib_renderer->xdpy);
   glx_extensions =
-    glXQueryExtensionsString (xlib_renderer->xdpy,
-                              DefaultScreen (xlib_renderer->xdpy));
+    glx_renderer->glXQueryExtensionsString (xlib_renderer->xdpy,
+                                            default_screen);
 
   COGL_NOTE (WINSYS, "  GLX Extensions: %s", glx_extensions);
 
@@ -346,7 +425,8 @@ update_winsys_features (CoglContext *context)
 
   for (i = 0; i < G_N_ELEMENTS (winsys_feature_data); i++)
     if (_cogl_feature_check (_cogl_context_get_winsys (context),
-                             "GLX", winsys_feature_data + i, 0, 0, 0,
+                             "GLX", winsys_feature_data + i, 0, 0,
+                             COGL_DRIVER_GL, /* the driver isn't used */
                              glx_extensions,
                              glx_renderer))
       {
@@ -407,6 +487,7 @@ find_fbconfig (CoglDisplay *display,
                GError **error)
 {
   CoglXlibRenderer *xlib_renderer = display->renderer->winsys;
+  CoglGLXRenderer *glx_renderer = display->renderer->winsys;
   GLXFBConfig *configs = NULL;
   int n_configs, i;
   static const int attributes[] = {
@@ -424,10 +505,10 @@ find_fbconfig (CoglDisplay *display,
   gboolean ret = TRUE;
   int xscreen_num = DefaultScreen (xlib_renderer->xdpy);
 
-  configs = glXChooseFBConfig (xlib_renderer->xdpy,
-                               xscreen_num,
-                               attributes,
-                               &n_configs);
+  configs = glx_renderer->glXChooseFBConfig (xlib_renderer->xdpy,
+                                             xscreen_num,
+                                             attributes,
+                                             &n_configs);
   if (!configs || n_configs == 0)
     {
       g_set_error (error, COGL_WINSYS_ERROR,
@@ -443,7 +524,8 @@ find_fbconfig (CoglDisplay *display,
         {
           XVisualInfo *vinfo;
 
-          vinfo = glXGetVisualFromFBConfig (xlib_renderer->xdpy, configs[i]);
+          vinfo = glx_renderer->glXGetVisualFromFBConfig (xlib_renderer->xdpy,
+                                                          configs[i]);
           if (vinfo == NULL)
             continue;
 
@@ -519,11 +601,12 @@ create_context (CoglDisplay *display, GError **error)
   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);
+  glx_display->glx_context =
+    glx_renderer->glXCreateNewContext (xlib_renderer->xdpy,
+                                       config,
+                                       GLX_RGBA_TYPE,
+                                       NULL,
+                                       True);
   if (glx_display->glx_context == NULL)
     {
       g_set_error (error, COGL_WINSYS_ERROR,
@@ -533,7 +616,7 @@ create_context (CoglDisplay *display, GError **error)
     }
 
   glx_renderer->is_direct =
-    glXIsDirect (xlib_renderer->xdpy, glx_display->glx_context);
+    glx_renderer->glXIsDirect (xlib_renderer->xdpy, glx_display->glx_context);
 
   COGL_NOTE (WINSYS, "Setting %s context",
              glx_renderer->is_direct ? "direct" : "indirect");
@@ -543,7 +626,8 @@ create_context (CoglDisplay *display, GError **error)
    * framebuffer is in use.
    */
 
-  xvisinfo = glXGetVisualFromFBConfig (xlib_renderer->xdpy, config);
+  xvisinfo = glx_renderer->glXGetVisualFromFBConfig (xlib_renderer->xdpy,
+                                                     config);
   if (xvisinfo == NULL)
     {
       g_set_error (error, COGL_WINSYS_ERROR,
@@ -577,10 +661,11 @@ create_context (CoglDisplay *display, GError **error)
    * 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);
+      glx_display->dummy_glxwin =
+        glx_renderer->glXCreateWindow (xlib_renderer->xdpy,
+                                       config,
+                                       xlib_display->dummy_xwin,
+                                       NULL);
     }
 
   if (glx_display->dummy_glxwin)
@@ -591,10 +676,10 @@ create_context (CoglDisplay *display, GError **error)
   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);
+  glx_renderer->glXMakeContextCurrent (xlib_renderer->xdpy,
+                                       dummy_drawable,
+                                       dummy_drawable,
+                                       glx_display->glx_context);
 
   XFree (xvisinfo);
 
@@ -615,19 +700,23 @@ _cogl_winsys_display_destroy (CoglDisplay *display)
   CoglGLXDisplay *glx_display = display->winsys;
   CoglXlibDisplay *xlib_display = display->winsys;
   CoglXlibRenderer *xlib_renderer = display->renderer->winsys;
+  CoglGLXRenderer *glx_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_renderer->glXMakeContextCurrent (xlib_renderer->xdpy,
+                                           None, None, NULL);
+      glx_renderer->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_renderer->glXDestroyWindow (xlib_renderer->xdpy,
+                                      glx_display->dummy_glxwin);
       glx_display->dummy_glxwin = None;
     }
 
@@ -761,8 +850,8 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
 
       _cogl_xlib_renderer_trap_errors (display->renderer, &state);
 
-      xvisinfo = glXGetVisualFromFBConfig (xlib_renderer->xdpy,
-                                           glx_display->fbconfig);
+      xvisinfo = glx_renderer->glXGetVisualFromFBConfig (xlib_renderer->xdpy,
+                                                         glx_display->fbconfig);
       if (xvisinfo == NULL)
         {
           g_set_error (error, COGL_WINSYS_ERROR,
@@ -825,10 +914,10 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
   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);
+        glx_renderer->glXCreateWindow (xlib_renderer->xdpy,
+                                       glx_display->fbconfig,
+                                       xlib_onscreen->xwin,
+                                       NULL);
     }
 
 #ifdef GLX_INTEL_swap_event
@@ -841,9 +930,9 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
        * 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);
+      glx_renderer->glXSelectEvent (xlib_renderer->xdpy,
+                                    drawable,
+                                    GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK);
     }
 #endif /* GLX_INTEL_swap_event */
 
@@ -856,6 +945,7 @@ _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   CoglContext *context = framebuffer->context;
   CoglXlibRenderer *xlib_renderer = context->display->renderer->winsys;
+  CoglGLXRenderer *glx_renderer = context->display->renderer->winsys;
   CoglXlibTrapState old_state;
   CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
   CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
@@ -868,7 +958,8 @@ _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
 
   if (glx_onscreen->glxwin != None)
     {
-      glXDestroyWindow (xlib_renderer->xdpy, glx_onscreen->glxwin);
+      glx_renderer->glXDestroyWindow (xlib_renderer->xdpy,
+                                      glx_onscreen->glxwin);
       glx_onscreen->glxwin = None;
     }
 
@@ -913,9 +1004,9 @@ _cogl_winsys_onscreen_bind (CoglOnscreen *onscreen)
 
       _cogl_xlib_renderer_trap_errors (context->display->renderer, &old_state);
 
-      glXMakeContextCurrent (xlib_renderer->xdpy,
-                             drawable, drawable,
-                             glx_display->glx_context);
+      glx_renderer->glXMakeContextCurrent (xlib_renderer->xdpy,
+                                           drawable, drawable,
+                                           glx_display->glx_context);
     }
   else
     {
@@ -934,10 +1025,10 @@ _cogl_winsys_onscreen_bind (CoglOnscreen *onscreen)
                  xlib_onscreen->is_foreign_xwin ? "foreign" : "native",
                  glx_display->glx_context);
 
-      glXMakeContextCurrent (xlib_renderer->xdpy,
-                             drawable,
-                             drawable,
-                             glx_display->glx_context);
+      glx_renderer->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
@@ -1252,7 +1343,7 @@ _cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
   else
     have_counter = FALSE;
 
-  glXSwapBuffers (xlib_renderer->xdpy, drawable);
+  glx_renderer->glXSwapBuffers (xlib_renderer->xdpy, drawable);
 
   if (have_counter)
     glx_onscreen->last_swap_vsync_counter = _cogl_winsys_get_vsync_counter ();
@@ -1341,6 +1432,7 @@ _cogl_winsys_xlib_get_visual_info (void)
 {
   CoglGLXDisplay *glx_display;
   CoglXlibRenderer *xlib_renderer;
+  CoglGLXRenderer *glx_renderer;
 
   _COGL_GET_CONTEXT (ctx, NULL);
 
@@ -1348,11 +1440,13 @@ _cogl_winsys_xlib_get_visual_info (void)
 
   glx_display = ctx->display->winsys;
   xlib_renderer = ctx->display->renderer->winsys;
+  glx_renderer = ctx->display->renderer->winsys;
 
   if (!glx_display->found_fbconfig)
     return NULL;
 
-  return glXGetVisualFromFBConfig (xlib_renderer->xdpy, glx_display->fbconfig);
+  return glx_renderer->glXGetVisualFromFBConfig (xlib_renderer->xdpy,
+                                                 glx_display->fbconfig);
 }
 
 static gboolean
@@ -1362,6 +1456,7 @@ get_fbconfig_for_depth (CoglContext *context,
                         gboolean *can_mipmap_ret)
 {
   CoglXlibRenderer *xlib_renderer;
+  CoglGLXRenderer *glx_renderer;
   CoglGLXDisplay *glx_display;
   Display *dpy;
   GLXFBConfig *fbconfigs;
@@ -1371,6 +1466,7 @@ get_fbconfig_for_depth (CoglContext *context,
   gboolean found = FALSE;
 
   xlib_renderer = context->display->renderer->winsys;
+  glx_renderer = context->display->renderer->winsys;
   glx_display = context->display->winsys;
 
   /* Check if we've already got a cached config for this depth */
@@ -1386,7 +1482,8 @@ get_fbconfig_for_depth (CoglContext *context,
 
   dpy = xlib_renderer->xdpy;
 
-  fbconfigs = glXGetFBConfigs (dpy, DefaultScreen (dpy), &n_elements);
+  fbconfigs = glx_renderer->glXGetFBConfigs (dpy, DefaultScreen (dpy),
+                                             &n_elements);
 
   db = G_MAXSHORT;
   stencil = G_MAXSHORT;
@@ -1398,7 +1495,7 @@ get_fbconfig_for_depth (CoglContext *context,
       XVisualInfo *vi;
       int visual_depth;
 
-      vi = glXGetVisualFromFBConfig (dpy, fbconfigs[i]);
+      vi = glx_renderer->glXGetVisualFromFBConfig (dpy, fbconfigs[i]);
       if (vi == NULL)
         continue;
 
@@ -1409,24 +1506,24 @@ get_fbconfig_for_depth (CoglContext *context,
       if (visual_depth != depth)
         continue;
 
-      glXGetFBConfigAttrib (dpy,
-                            fbconfigs[i],
-                            GLX_ALPHA_SIZE,
-                            &alpha);
-      glXGetFBConfigAttrib (dpy,
-                            fbconfigs[i],
-                            GLX_BUFFER_SIZE,
-                            &value);
+      glx_renderer->glXGetFBConfigAttrib (dpy,
+                                          fbconfigs[i],
+                                          GLX_ALPHA_SIZE,
+                                          &alpha);
+      glx_renderer->glXGetFBConfigAttrib (dpy,
+                                          fbconfigs[i],
+                                          GLX_BUFFER_SIZE,
+                                          &value);
       if (value != depth && (value - alpha) != depth)
         continue;
 
       value = 0;
       if (depth == 32)
         {
-          glXGetFBConfigAttrib (dpy,
-                                fbconfigs[i],
-                                GLX_BIND_TO_TEXTURE_RGBA_EXT,
-                                &value);
+          glx_renderer->glXGetFBConfigAttrib (dpy,
+                                              fbconfigs[i],
+                                              GLX_BIND_TO_TEXTURE_RGBA_EXT,
+                                              &value);
           if (value)
             rgba = 1;
         }
@@ -1436,27 +1533,27 @@ get_fbconfig_for_depth (CoglContext *context,
           if (rgba)
             continue;
 
-          glXGetFBConfigAttrib (dpy,
-                                fbconfigs[i],
-                                GLX_BIND_TO_TEXTURE_RGB_EXT,
-                                &value);
+          glx_renderer->glXGetFBConfigAttrib (dpy,
+                                              fbconfigs[i],
+                                              GLX_BIND_TO_TEXTURE_RGB_EXT,
+                                              &value);
           if (!value)
             continue;
         }
 
-      glXGetFBConfigAttrib (dpy,
-                            fbconfigs[i],
-                            GLX_DOUBLEBUFFER,
-                            &value);
+      glx_renderer->glXGetFBConfigAttrib (dpy,
+                                          fbconfigs[i],
+                                          GLX_DOUBLEBUFFER,
+                                          &value);
       if (value > db)
         continue;
 
       db = value;
 
-      glXGetFBConfigAttrib (dpy,
-                            fbconfigs[i],
-                            GLX_STENCIL_SIZE,
-                            &value);
+      glx_renderer->glXGetFBConfigAttrib (dpy,
+                                          fbconfigs[i],
+                                          GLX_STENCIL_SIZE,
+                                          &value);
       if (value > stencil)
         continue;
 
@@ -1465,10 +1562,10 @@ get_fbconfig_for_depth (CoglContext *context,
       /* glGenerateMipmap is defined in the offscreen extension */
       if (cogl_features_available (COGL_FEATURE_OFFSCREEN))
         {
-          glXGetFBConfigAttrib (dpy,
-                                fbconfigs[i],
-                                GLX_BIND_TO_MIPMAP_TEXTURE_EXT,
-                                &value);
+          glx_renderer->glXGetFBConfigAttrib (dpy,
+                                              fbconfigs[i],
+                                              GLX_BIND_TO_MIPMAP_TEXTURE_EXT,
+                                              &value);
 
           if (value < mipmap)
             continue;
@@ -1548,6 +1645,7 @@ try_create_glx_pixmap (CoglContext *context,
   CoglTexturePixmapGLX *glx_tex_pixmap = tex_pixmap->winsys;
   CoglRenderer *renderer;
   CoglXlibRenderer *xlib_renderer;
+  CoglGLXRenderer *glx_renderer;
   Display *dpy;
   /* We have to initialize this *opaque* variable because gcc tries to
    * be too smart for its own good and warns that the variable may be
@@ -1560,6 +1658,7 @@ try_create_glx_pixmap (CoglContext *context,
 
   renderer = context->display->renderer;
   xlib_renderer = renderer->winsys;
+  glx_renderer = renderer->winsys;
   dpy = xlib_renderer->xdpy;
 
   if (!get_fbconfig_for_depth (context,
@@ -1606,10 +1705,11 @@ try_create_glx_pixmap (CoglContext *context,
 
   _cogl_xlib_renderer_trap_errors (renderer, &trap_state);
 
-  glx_tex_pixmap->glx_pixmap = glXCreatePixmap (dpy,
-                                                fb_config,
-                                                tex_pixmap->pixmap,
-                                                attribs);
+  glx_tex_pixmap->glx_pixmap =
+    glx_renderer->glXCreatePixmap (dpy,
+                                   fb_config,
+                                   tex_pixmap->pixmap,
+                                   attribs);
   glx_tex_pixmap->has_mipmap_space = mipmap;
 
   XSync (dpy, False);
@@ -1618,7 +1718,7 @@ try_create_glx_pixmap (CoglContext *context,
     {
       COGL_NOTE (TEXTURE_PIXMAP, "Failed to create pixmap for %p", tex_pixmap);
       _cogl_xlib_renderer_trap_errors (renderer, &trap_state);
-      glXDestroyPixmap (dpy, glx_tex_pixmap->glx_pixmap);
+      glx_renderer->glXDestroyPixmap (dpy, glx_tex_pixmap->glx_pixmap);
       XSync (dpy, False);
       _cogl_xlib_renderer_untrap_errors (renderer, &trap_state);
 
@@ -1702,7 +1802,8 @@ free_glx_pixmap (CoglContext *context,
    *   http://bugzilla.clutter-project.org/show_bug.cgi?id=2324
    */
   _cogl_xlib_renderer_trap_errors (renderer, &trap_state);
-  glXDestroyPixmap (xlib_renderer->xdpy, glx_tex_pixmap->glx_pixmap);
+  glx_renderer->glXDestroyPixmap (xlib_renderer->xdpy,
+                                  glx_tex_pixmap->glx_pixmap);
   XSync (xlib_renderer->xdpy, False);
   _cogl_xlib_renderer_untrap_errors (renderer, &trap_state);
 
diff --git a/cogl/winsys/cogl-winsys-stub.c b/cogl/winsys/cogl-winsys-stub.c
index 5db9918..f6a2b41 100644
--- a/cogl/winsys/cogl-winsys-stub.c
+++ b/cogl/winsys/cogl-winsys-stub.c
@@ -83,10 +83,10 @@ _cogl_winsys_context_init (CoglContext *context, GError **error)
 {
   context->winsys = &_cogl_winsys_stub_dummy_ptr;
 
-  if (!_cogl_gl_check_version (error))
+  if (!_cogl_context_check_gl_version (context, error))
     return FALSE;
 
-  _cogl_gl_update_features (context);
+  _cogl_context_update_features (context);
 
   memset (context->winsys_features, 0, sizeof (context->winsys_features));
 
diff --git a/cogl/winsys/cogl-winsys-wgl.c b/cogl/winsys/cogl-winsys-wgl.c
index fef7313..6596f74 100644
--- a/cogl/winsys/cogl-winsys-wgl.c
+++ b/cogl/winsys/cogl-winsys-wgl.c
@@ -513,6 +513,8 @@ get_wgl_extensions_string (HDC dc)
   const char * (APIENTRY *pf_wglGetExtensionsStringARB) (HDC);
   const char * (APIENTRY *pf_wglGetExtensionsStringEXT) (void);
 
+  _COGL_GET_CONTEXT (ctx, NULL);
+
   /* According to the docs for these two extensions, you are supposed
      to use wglGetProcAddress to detect their availability so
      presumably it will return NULL if they are not available */
@@ -550,7 +552,7 @@ update_winsys_features (CoglContext *context)
 
   g_return_if_fail (wgl_display->wgl_context);
 
-  _cogl_gl_update_features (context);
+  _cogl_context_update_features (context);
 
   memset (context->winsys_features, 0, sizeof (context->winsys_features));
 
@@ -567,7 +569,8 @@ update_winsys_features (CoglContext *context)
 
       for (i = 0; i < G_N_ELEMENTS (winsys_feature_data); i++)
         if (_cogl_feature_check (_cogl_context_get_winsys (context),
-                                 "WGL", winsys_feature_data + i, 0, 0, 0,
+                                 "WGL", winsys_feature_data + i, 0, 0,
+                                 COGL_DRIVER_GL,
                                  wgl_extensions,
                                  wgl_renderer))
           {
diff --git a/configure.ac b/configure.ac
index ea7dea5..cba739c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -356,9 +356,16 @@ dnl     ============================================================
 dnl         ========================================================
 dnl         Drivers first...
 dnl         ========================================================
-DRIVER_COUNT=0
 EGL_CHECKED=no
 
+dnl This gets set to yes if Cogl directly links to the GL library API
+dnl so it doesn't need to be dlopened. This currently happens on OSX
+dnl and WGL where it's not clear if window system API can be separated
+dnl from the GL API.
+GL_LIBRARY_DIRECTLY_LINKED=no
+
+enabled_drivers=""
+
 AC_ARG_ENABLE(
   [gles1],
   [AC_HELP_STRING([--enable-gles1=@<:@no/yes@:>@], [Enable support for OpenGL-ES 1.1 @<:@default=no@:>@])],
@@ -370,9 +377,7 @@ AS_IF([test "x$enable_gles1" = "xyes"],
         AS_IF([test "x$platform_win32" = "xyes"],
 	      [AC_MSG_ERROR([GLES 1 not available for win32])])
 
-        DRIVER_COUNT=$((DRIVER_COUNT + 1))
-        COGL_DRIVER=gles
-        glesversion=1.1
+        enabled_drivers="$enabled_drivers gles1"
 
         cogl_gl_headers="GLES/gl.h GLES/glext.h"
 
@@ -381,7 +386,8 @@ AS_IF([test "x$enable_gles1" = "xyes"],
         COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_GLES1"
 
         PKG_CHECK_EXISTS([glesv1_cm],
-          [COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES glesv1_cm"
+          [COGL_PKG_REQUIRES_GL="$COGL_PKG_REQUIRES_GL glesv1_cm"
+           COGL_GLES1_LIBNAME="GLESv1_CM"
            NEED_EGL=yes
           ],
           [
@@ -424,10 +430,10 @@ AS_IF([test "x$enable_gles1" = "xyes"],
             # bundles the GLES and EGL API together and -lGLESv1_CM
             # would be used for a standalone GLES API.
             AC_CHECK_LIB(GLES_CM, [eglInitialize],
-              [COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -lGLES_CM"],
+              [COGL_GLES1_LIBNAME="GLES_CM"],
               [
                 AC_CHECK_LIB(GLESv1_CM, [glFlush],
-                  [COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -lGLESv1_CM"
+                  [COGL_GLES1_LIBNAME="GLESv1_CM"
                    NEED_SEPARATE_EGL=yes
                   ],
                   [AC_MSG_ERROR([Unable to locate required GLES 1.x Common Profile library])])
@@ -448,9 +454,7 @@ AS_IF([test "x$enable_gles2" = "xyes"],
         AS_IF([test "x$platform_win32" = "xyes"],
 	      [AC_MSG_ERROR([GLES 2 not available for win32])])
 
-        DRIVER_COUNT=$((DRIVER_COUNT + 1))
-        COGL_DRIVER=gles
-        glesversion=2.0
+        enabled_drivers="$enabled_drivers gles2"
 
         cogl_gl_headers="GLES2/gl2.h GLES2/gl2ext.h"
         AC_DEFINE([HAVE_COGL_GLES2], 1, [Have GLES 2.0 for rendering])
@@ -458,7 +462,9 @@ AS_IF([test "x$enable_gles2" = "xyes"],
         COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_GLES2"
 
         PKG_CHECK_EXISTS([glesv2],
-          [COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES glesv2"],
+          [COGL_PKG_REQUIRES_GL="$COGL_PKG_REQUIRES_GL glesv2"
+           COGL_GLES2_LIBNAME="GLESv2"
+          ],
           [
             # We have to check the two headers independently as GLES2/gl2ext.h
             # needs to include GLES2/gl2.h to have the GL types defined (eg.
@@ -471,7 +477,7 @@ AS_IF([test "x$enable_gles2" = "xyes"],
                             [AC_MSG_ERROR([Unable to locate GLES2/gl2ext.h])],
                             [#include <GLES2/gl2.h>])
 
-            COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -lGLESv2"
+            COGL_GLES2_LIBNAME="GLESv2"
           ])
 
         NEED_EGL=yes
@@ -481,12 +487,11 @@ AC_ARG_ENABLE(
   [gl],
   [AC_HELP_STRING([--enable-gl=@<:@no/yes@:>@], [Enable support for OpenGL @<:@default=yes@:>@])],
   [],
-  [AS_IF([test $DRIVER_COUNT -gt 0], [enable_gl=no], [enable_gl=yes])]
+  [enable_gl=yes]
 )
 AS_IF([test "x$enable_gl" = "xyes"],
       [
-        DRIVER_COUNT=$((DRIVER_COUNT + 1))
-        COGL_DRIVER=gl
+        enabled_drivers="$enabled_drivers gl"
 
         PKG_CHECK_EXISTS([x11], [ALLOW_GLX=yes])
 
@@ -496,6 +501,10 @@ AS_IF([test "x$enable_gl" = "xyes"],
               [
                 cogl_gl_headers="OpenGL/gl.h"
                 COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -framework OpenGL"
+                dnl The GL API is being directly linked in so there is
+                dnl no need to dlopen it separately
+                GL_LIBRARY_DIRECTLY_LINKED=yes
+                COGL_GL_LIBNAME=""
               ],
 
               [test "x$platform_win32" = "xyes"],
@@ -503,15 +512,22 @@ AS_IF([test "x$enable_gl" = "xyes"],
 		COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -lopengl32 -lgdi32 -lwinmm"
 		COGL_EXTRA_CFLAGS="$COGL_EXTRA_CFLAGS -D_WIN32_WINNT=0x0500"
                 ALLOW_WGL=yes
+                dnl The GL API is being directly linked in so there is
+                dnl no need to dlopen it separately
+                GL_LIBRARY_DIRECTLY_LINKED=yes
+                COGL_GL_LIBNAME=""
 	      ],
 
 	      [
 		PKG_CHECK_EXISTS([gl],
-                  [COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES gl"],
+                  dnl We don't want to use COGL_PKG_REQUIRES here because we don't want to
+                  dnl directly link against libGL
+                  [COGL_PKG_REQUIRES_GL="$COGL_PKG_REQUIRES_GL gl"],
 		  [AC_CHECK_LIB(GL, [glGetString],
-				[COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -lGL"],
+				,
 				[AC_MSG_ERROR([Unable to locate required GL library])])
 		  ])
+                COGL_GL_LIBNAME="GL"
 	      ])
 
         AC_DEFINE([HAVE_COGL_GL], [1], [Have GL for rendering])
@@ -520,13 +536,18 @@ AS_IF([test "x$enable_gl" = "xyes"],
         COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS CLUTTER_COGL_HAS_GL"
       ])
 
-AS_IF([test $DRIVER_COUNT -gt 1],
-      [AC_MSG_ERROR(['The --enable-gl{es1,es2} options are currently mutually exclusive'])])
+AM_CONDITIONAL([COGL_DRIVER_GL_SUPPORTED], [test "x$enable_gl" = "xyes"])
+AM_CONDITIONAL([COGL_DRIVER_GLES_SUPPORTED],
+               [test "x$enable_gles1" = "xyes" || test "x$enable_gles2" = "xyes"])
 
-AC_SUBST([COGL_DRIVER])
+AC_SUBST([COGL_GL_LIBNAME])
+AC_SUBST([COGL_GLES1_LIBNAME])
+AC_SUBST([COGL_GLES2_LIBNAME])
 
-AM_CONDITIONAL([COGL_DRIVER_GL], [test "x$COGL_DRIVER" = "xgl"])
-AM_CONDITIONAL([COGL_DRIVER_GLES], [test "x$COGL_DRIVER" = "xgles"])
+if test "x$GL_LIBRARY_DIRECTLY_LINKED" = "xyes"; then
+   AC_DEFINE([HAVE_DIRECTLY_LINKED_GL_LIBRARY], [1],
+             [Defined if the GL library shouldn't be dlopened])
+fi
 
 dnl         ========================================================
 dnl         Check window system integration libraries...
@@ -541,7 +562,7 @@ AC_ARG_ENABLE(
 AS_IF([test "x$enable_glx" = "xyes"],
       [
         AS_IF([test "x$ALLOW_GLX" != "xyes"],
-              [AC_MSG_ERROR([GLX not supported with $COGL_DRIVER driver])])
+              [AC_MSG_ERROR([GLX not supported with this configuration])])
 
         NEED_XLIB=yes
         SUPPORT_GLX=yes
@@ -568,7 +589,7 @@ AC_ARG_ENABLE(
 AS_IF([test "x$enable_wgl" = "xyes"],
       [
         AS_IF([test "x$ALLOW_WGL" != "xyes"],
-              [AC_MSG_ERROR([WGL not supported with $COGL_DRIVER driver])])
+              [AC_MSG_ERROR([WGL not supported with this configuration])])
 
         SUPPORT_WGL=yes
         GL_WINSYS_APIS="$GL_WINSYS_APIS wgl"
@@ -691,7 +712,7 @@ AC_ARG_ENABLE(
   [xlib-egl-platform],
   [AC_HELP_STRING([--enable-xlib-egl-platform=@<:@no/yes@:>@], [Enable support for the Xlib egl platform @<:@default=auto@:>@])],
   [],
-  AS_IF([test "x$COGL_DRIVER" = "xgles" && test $EGL_PLATFORM_COUNT -eq 0],
+  AS_IF([test "x$enable_gles1" = "xyes" -o "x$enable_gles2" = "xyes" && test $EGL_PLATFORM_COUNT -eq 0],
         [enable_xlib_egl_platform=yes], [enable_xlib_egl_platform=no])
 )
 AS_IF([test "x$enable_xlib_egl_platform" = "xyes"],
@@ -823,7 +844,22 @@ AS_IF([test "x$have_glib" = "xno"], AC_MSG_ERROR([glib-2.0 is required]))
 COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES glib-2.0"
 AC_SUBST(COGL_PKG_REQUIRES)
 PKG_CHECK_MODULES(COGL_DEP, [$COGL_PKG_REQUIRES])
-
+if test -n "$COGL_PKG_REQUIRES_GL"; then
+  PKG_CHECK_MODULES(COGL_DEP_GL, [$COGL_PKG_REQUIRES_GL])
+
+  dnl Strip out the GL libraries from the GL pkg-config files so we can
+  dnl dynamically load them instead
+  gl_libs=""
+  for x in $COGL_DEP_GL_LIBS; do
+    AS_CASE([$x],
+            [-lGL], [],
+            [-lGLESv2], [],
+            [-lGLESv1_CM], [],
+            [*], [gl_libs="$gl_libs $x"])
+  done
+  COGL_DEP_CFLAGS="$COGL_DEP_CFLAGS $COGL_DEP_CFLAGS_GL"
+  COGL_DEP_LIBS="$COGL_DEP_LIBS $gl_libs"
+fi
 
 dnl ================================================================
 dnl Misc program dependencies.
@@ -920,7 +956,7 @@ echo "        Prefix: ${prefix}"
 echo ""
 # Features
 echo " â Features:"
-echo "        Driver: ${COGL_DRIVER} ${glesversion}"
+echo "        Drivers: ${enabled_drivers}"
 echo "        GL Window System APIs:${GL_WINSYS_APIS}"
 if test "x$SUPPORT_EGL" = "xyes"; then
 echo "        EGL Platforms:${EGL_PLATFORMS}"



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