diff mbox

[5/9] gl: Use the dispatch table for calling ARB/EXT functions

Message ID 1311602713-6182-5-git-send-email-alexandros.frantzis@linaro.org
State Accepted
Headers show

Commit Message

alexandros.frantzis@linaro.org July 25, 2011, 2:05 p.m. UTC
From: Alexandros Frantzis <alexandros.frantzis@linaro.org>

Use the dispatch table for calling GL functions that can have multiple name
variants. Also, always use the core variant names for GL constants.
---
 src/cairo-gl-composite.c |   12 ++-
 src/cairo-gl-device.c    |   52 +++++-----
 src/cairo-gl-gradient.c  |   14 ++-
 src/cairo-gl-private.h   |    2 +-
 src/cairo-gl-shaders.c   |  256 +++++++++++++++++++++++++++-------------------
 src/cairo-gl-surface.c   |    4 +-
 6 files changed, 195 insertions(+), 145 deletions(-)
diff mbox

Patch

diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index 97407bb..109e99b 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -960,7 +960,7 @@  _cairo_gl_composite_begin (cairo_gl_composite_t *setup,
     _cairo_gl_context_set_destination (ctx, setup->dst);
 
     if (_cairo_gl_context_is_flushed (ctx)) {
-        glBindBufferARB (GL_ARRAY_BUFFER_ARB, ctx->vbo);
+        ctx->dispatch.BindBuffer (GL_ARRAY_BUFFER, ctx->vbo);
 
         glVertexPointer (2, GL_FLOAT, vertex_size, NULL);
         glEnableClientState (GL_VERTEX_ARRAY);
@@ -1034,7 +1034,7 @@  _cairo_gl_composite_flush (cairo_gl_context_t *ctx)
 
     count = ctx->vb_offset / ctx->vertex_size;
 
-    glUnmapBufferARB (GL_ARRAY_BUFFER_ARB);
+    ctx->dispatch.UnmapBuffer (GL_ARRAY_BUFFER);
     ctx->vb = NULL;
     ctx->vb_offset = 0;
 
@@ -1058,13 +1058,15 @@  static void
 _cairo_gl_composite_prepare_buffer (cairo_gl_context_t *ctx,
                                     unsigned int n_vertices)
 {
+    cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
+
     if (ctx->vb_offset + n_vertices * ctx->vertex_size > CAIRO_GL_VBO_SIZE)
 	_cairo_gl_composite_flush (ctx);
 
     if (ctx->vb == NULL) {
-	glBufferDataARB (GL_ARRAY_BUFFER_ARB, CAIRO_GL_VBO_SIZE,
-			 NULL, GL_STREAM_DRAW_ARB);
-	ctx->vb = glMapBufferARB (GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+	dispatch->BufferData (GL_ARRAY_BUFFER, CAIRO_GL_VBO_SIZE,
+			      NULL, GL_STREAM_DRAW);
+	ctx->vb = dispatch->MapBuffer (GL_ARRAY_BUFFER, GL_WRITE_ONLY);
     }
 }
 
diff --git a/src/cairo-gl-device.c b/src/cairo-gl-device.c
index c39489c..a6aec42 100644
--- a/src/cairo-gl-device.c
+++ b/src/cairo-gl-device.c
@@ -85,7 +85,7 @@  _gl_flush (void *device)
     ctx->pre_shader = NULL;
     _cairo_gl_set_shader (ctx, NULL);
 
-    glBindBufferARB (GL_ARRAY_BUFFER_ARB, 0);
+    ctx->dispatch.BindBuffer (GL_ARRAY_BUFFER, 0);
 
     glDisableClientState (GL_VERTEX_ARRAY);
 
@@ -152,6 +152,7 @@  cairo_status_t
 _cairo_gl_context_init (cairo_gl_context_t *ctx)
 {
     cairo_status_t status;
+    cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
     int n;
 
     _cairo_device_init (&ctx->base, &_cairo_gl_device_backend);
@@ -193,7 +194,7 @@  _cairo_gl_context_init (cairo_gl_context_t *ctx)
     }
 
     if (! GLEW_ARB_texture_non_power_of_two)
-	ctx->tex_target = GL_TEXTURE_RECTANGLE_EXT;
+	ctx->tex_target = GL_TEXTURE_RECTANGLE;
     else
 	ctx->tex_target = GL_TEXTURE_2D;
 
@@ -218,8 +219,8 @@  _cairo_gl_context_init (cairo_gl_context_t *ctx)
 		  GL_RGBA, GL_UNSIGNED_BYTE, NULL);
 
     /* PBO for any sort of texture upload */
-    glGenBuffersARB (1, &ctx->texture_load_pbo);
-    glGenBuffersARB (1, &ctx->vbo);
+    dispatch->GenBuffers (1, &ctx->texture_load_pbo);
+    dispatch->GenBuffers (1, &ctx->vbo);
 
     ctx->max_framebuffer_size = 0;
     glGetIntegerv (GL_MAX_RENDERBUFFER_SIZE, &ctx->max_framebuffer_size);
@@ -254,6 +255,7 @@  _cairo_gl_ensure_framebuffer (cairo_gl_context_t *ctx,
                               cairo_gl_surface_t *surface)
 {
     GLenum status;
+    cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
 
     if (likely (surface->fb))
         return;
@@ -261,25 +263,25 @@  _cairo_gl_ensure_framebuffer (cairo_gl_context_t *ctx,
     /* Create a framebuffer object wrapping the texture so that we can render
      * to it.
      */
-    glGenFramebuffersEXT (1, &surface->fb);
-    glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, surface->fb);
-    glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT,
-			       GL_COLOR_ATTACHMENT0_EXT,
-			       ctx->tex_target,
-			       surface->tex,
-			       0);
-
-    status = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT);
-    if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+    dispatch->GenFramebuffers (1, &surface->fb);
+    dispatch->BindFramebuffer (GL_FRAMEBUFFER, surface->fb);
+    dispatch->FramebufferTexture2D (GL_FRAMEBUFFER,
+				    GL_COLOR_ATTACHMENT0,
+				    ctx->tex_target,
+				    surface->tex,
+				    0);
+
+    status = dispatch->CheckFramebufferStatus (GL_FRAMEBUFFER);
+    if (status != GL_FRAMEBUFFER_COMPLETE) {
 	const char *str;
 	switch (status) {
-	//case GL_FRAMEBUFFER_UNDEFINED_EXT: str= "undefined"; break;
-	case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: str= "incomplete attachment"; break;
-	case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: str= "incomplete/missing attachment"; break;
-	case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: str= "incomplete draw buffer"; break;
-	case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: str= "incomplete read buffer"; break;
-	case GL_FRAMEBUFFER_UNSUPPORTED_EXT: str= "unsupported"; break;
-	case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT: str= "incomplete multiple"; break;
+	//case GL_FRAMEBUFFER_UNDEFINED: str= "undefined"; break;
+	case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: str= "incomplete attachment"; break;
+	case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: str= "incomplete/missing attachment"; break;
+	case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: str= "incomplete draw buffer"; break;
+	case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: str= "incomplete read buffer"; break;
+	case GL_FRAMEBUFFER_UNSUPPORTED: str= "unsupported"; break;
+	case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: str= "incomplete multiple"; break;
 	default: str = "unknown error"; break;
 	}
 
@@ -302,12 +304,12 @@  _cairo_gl_context_set_destination (cairo_gl_context_t *ctx,
 
     if (_cairo_gl_surface_is_texture (surface)) {
         _cairo_gl_ensure_framebuffer (ctx, surface);
-        glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, surface->fb);
-        glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);
-        glReadBuffer (GL_COLOR_ATTACHMENT0_EXT);
+        ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb);
+        glDrawBuffer (GL_COLOR_ATTACHMENT0);
+        glReadBuffer (GL_COLOR_ATTACHMENT0);
     } else {
         ctx->make_current (ctx, surface);
-        glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
+        ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, 0);
         glDrawBuffer (GL_BACK_LEFT);
         glReadBuffer (GL_BACK_LEFT);
     }
diff --git a/src/cairo-gl-gradient.c b/src/cairo-gl-gradient.c
index 94c220b..a48e156 100644
--- a/src/cairo-gl-gradient.c
+++ b/src/cairo-gl-gradient.c
@@ -195,6 +195,7 @@  _cairo_gl_gradient_create (cairo_gl_context_t           *ctx,
     cairo_status_t status;
     int tex_width;
     void *data;
+    cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
 
     if ((unsigned int) ctx->max_texture_size / 2 <= n_stops)
         return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -221,16 +222,17 @@  _cairo_gl_gradient_create (cairo_gl_context_t           *ctx,
     gradient->stops = gradient->stops_embedded;
     memcpy (gradient->stops_embedded, stops, n_stops * sizeof (cairo_gradient_stop_t));
 
-    glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, ctx->texture_load_pbo);
-    glBufferDataARB (GL_PIXEL_UNPACK_BUFFER_ARB, tex_width * sizeof (uint32_t), 0, GL_STREAM_DRAW);
-    data = glMapBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY);
+    dispatch->BindBuffer (GL_PIXEL_UNPACK_BUFFER, ctx->texture_load_pbo);
+    dispatch->BufferData (GL_PIXEL_UNPACK_BUFFER,
+			  tex_width * sizeof (uint32_t), 0, GL_STREAM_DRAW);
+    data = dispatch->MapBuffer (GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
 
     status = _cairo_gl_gradient_render (ctx, n_stops, stops, data, tex_width);
 
-    glUnmapBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB);
+    dispatch->UnmapBuffer (GL_PIXEL_UNPACK_BUFFER);
 
     if (unlikely (status)) {
-        glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, 0);
+        dispatch->BindBuffer (GL_PIXEL_UNPACK_BUFFER, 0);
         free (gradient);
         return status;
     }
@@ -241,7 +243,7 @@  _cairo_gl_gradient_create (cairo_gl_context_t           *ctx,
     glTexImage1D (GL_TEXTURE_1D, 0, GL_RGBA8, tex_width, 0,
                   GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
 
-    glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, 0);
+    dispatch->BindBuffer (GL_PIXEL_UNPACK_BUFFER, 0);
 
     /* we ignore errors here and just return an uncached gradient */
     if (likely (! _cairo_cache_insert (&ctx->gradients, &gradient->cache_entry)))
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index c0a2d2d..c9851ff 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -332,7 +332,7 @@  _cairo_gl_device_has_glsl (cairo_device_t *device)
 static cairo_always_inline cairo_bool_t
 _cairo_gl_device_requires_power_of_two_textures (cairo_device_t *device)
 {
-    return ((cairo_gl_context_t *) device)->tex_target == GL_TEXTURE_RECTANGLE_EXT;
+    return ((cairo_gl_context_t *) device)->tex_target == GL_TEXTURE_RECTANGLE;
 }
 
 static cairo_always_inline cairo_status_t cairo_warn
diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c
index abb4dd2..06e3c62 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -3,6 +3,7 @@ 
  * Copyright © 2009 T. Zachary Laine
  * Copyright © 2010 Eric Anholt
  * Copyright © 2010 Red Hat, Inc
+ * Copyright © 2010 Linaro Limited
  *
  * This library is free software; you can redistribute it and/or
  * modify it either under the terms of the GNU Lesser General Public
@@ -35,6 +36,7 @@ 
  *	Benjamin Otte <otte@gnome.org>
  *	Eric Anholt <eric@anholt.net>
  *	T. Zachary Laine <whatwasthataddress@gmail.com>
+ *	Alexandros Frantzis <alexandros.frantzis@linaro.org>
  */
 
 #include "cairoint.h"
@@ -44,53 +46,61 @@ 
 
 typedef struct cairo_gl_shader_impl {
     void
-    (*compile_shader) (GLuint *shader, GLenum type, const char *text);
+    (*compile_shader) (cairo_gl_context_t *ctx, GLuint *shader, GLenum type,
+		       const char *text);
 
     void
-    (*link_shader) (GLuint *program, GLuint vert, GLuint frag);
+    (*link_shader) (cairo_gl_context_t *ctx, GLuint *program, GLuint vert, GLuint frag);
 
     void
-    (*destroy_shader) (GLuint shader);
+    (*destroy_shader) (cairo_gl_context_t *ctx, GLuint shader);
 
     void
-    (*destroy_program) (GLuint program);
+    (*destroy_program) (cairo_gl_context_t *ctx, GLuint program);
 
     void
-    (*bind_float) (cairo_gl_shader_t *shader,
+    (*bind_float) (cairo_gl_context_t *ctx,
+		   cairo_gl_shader_t *shader,
 		   const char *name,
 		   float value);
 
     void
-    (*bind_vec2) (cairo_gl_shader_t *shader,
+    (*bind_vec2) (cairo_gl_context_t *ctx,
+		  cairo_gl_shader_t *shader,
 		  const char *name,
 		  float value0,
 		  float value1);
 
     void
-    (*bind_vec3) (cairo_gl_shader_t *shader,
+    (*bind_vec3) (cairo_gl_context_t *ctx,
+		  cairo_gl_shader_t *shader,
 		  const char *name,
 		  float value0,
 		  float value1,
 		  float value2);
 
     void
-    (*bind_vec4) (cairo_gl_shader_t *shader,
+    (*bind_vec4) (cairo_gl_context_t *ctx,
+		  cairo_gl_shader_t *shader,
 		  const char *name,
 		  float value0, float value1,
 		  float value2, float value3);
 
     void
-    (*bind_matrix) (cairo_gl_shader_t *shader,
+    (*bind_matrix) (cairo_gl_context_t *ctx,
+		    cairo_gl_shader_t *shader,
 		    const char *name,
 		    cairo_matrix_t* m);
 
     void
-    (*bind_texture) (cairo_gl_shader_t *shader,
+    (*bind_texture) (cairo_gl_context_t *ctx,
+		     cairo_gl_shader_t *shader,
 		     const char *name,
 		     cairo_gl_tex_t tex_unit);
 
     void
-    (*use) (cairo_gl_shader_t *shader);
+    (*use) (cairo_gl_context_t *ctx,
+	    cairo_gl_shader_t *shader);
 } shader_impl_t;
 
 static cairo_status_t
@@ -103,24 +113,26 @@  _cairo_gl_shader_compile (cairo_gl_context_t *ctx,
 /* ARB_shader_objects / ARB_vertex_shader / ARB_fragment_shader extensions
    API. */
 static void
-compile_shader_arb (GLuint *shader, GLenum type, const char *text)
+compile_shader_arb (cairo_gl_context_t *ctx, GLuint *shader,
+		    GLenum type, const char *text)
 {
     const char* strings[1] = { text };
     GLint gl_status;
+    cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
 
-    *shader = glCreateShaderObjectARB (type);
-    glShaderSourceARB (*shader, 1, strings, 0);
-    glCompileShaderARB (*shader);
-    glGetObjectParameterivARB (*shader, GL_OBJECT_COMPILE_STATUS_ARB, &gl_status);
+    *shader = dispatch->CreateShader (type);
+    dispatch->ShaderSource (*shader, 1, strings, 0);
+    dispatch->CompileShader (*shader);
+    dispatch->GetShaderiv (*shader, GL_COMPILE_STATUS, &gl_status);
     if (gl_status == GL_FALSE) {
         GLint log_size;
-        glGetObjectParameterivARB (*shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &log_size);
+        dispatch->GetShaderiv (*shader, GL_INFO_LOG_LENGTH, &log_size);
         if (0 < log_size) {
             char *log = _cairo_malloc (log_size);
             GLint chars;
 
             log[log_size - 1] = '\0';
-            glGetInfoLogARB (*shader, log_size, &chars, log);
+            dispatch->GetShaderInfoLog (*shader, log_size, &chars, log);
             printf ("OpenGL shader compilation failed.  Shader:\n"
                     "%s\n"
                     "OpenGL compilation log:\n"
@@ -137,24 +149,25 @@  compile_shader_arb (GLuint *shader, GLenum type, const char *text)
 }
 
 static void
-link_shader_arb (GLuint *program, GLuint vert, GLuint frag)
+link_shader_arb (cairo_gl_context_t *ctx, GLuint *program, GLuint vert, GLuint frag)
 {
     GLint gl_status;
+    cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
 
-    *program = glCreateProgramObjectARB ();
-    glAttachObjectARB (*program, vert);
-    glAttachObjectARB (*program, frag);
-    glLinkProgramARB (*program);
-    glGetObjectParameterivARB (*program, GL_OBJECT_LINK_STATUS_ARB, &gl_status);
+    *program = dispatch->CreateProgram ();
+    dispatch->AttachShader (*program, vert);
+    dispatch->AttachShader (*program, frag);
+    dispatch->LinkProgram (*program);
+    dispatch->GetProgramiv (*program, GL_LINK_STATUS, &gl_status);
     if (gl_status == GL_FALSE) {
         GLint log_size;
-        glGetObjectParameterivARB (*program, GL_OBJECT_INFO_LOG_LENGTH_ARB, &log_size);
+        dispatch->GetProgramiv (*program, GL_INFO_LOG_LENGTH, &log_size);
         if (0 < log_size) {
             char *log = _cairo_malloc (log_size);
             GLint chars;
 
             log[log_size - 1] = '\0';
-            glGetInfoLogARB (*program, log_size, &chars, log);
+            dispatch->GetProgramInfoLog (*program, log_size, &chars, log);
             printf ("OpenGL shader link failed:\n%s\n", log);
 
             free (log);
@@ -167,117 +180,131 @@  link_shader_arb (GLuint *program, GLuint vert, GLuint frag)
 }
 
 static void
-destroy_shader_arb (GLuint shader)
+destroy_shader_arb (cairo_gl_context_t *ctx, GLuint shader)
 {
-  glDeleteObjectARB (shader);
+    ctx->dispatch.DeleteShader (shader);
 }
 
 static void
-destroy_program_arb (GLuint shader)
+destroy_program_arb (cairo_gl_context_t *ctx, GLuint shader)
 {
-  glDeleteObjectARB (shader);
+    ctx->dispatch.DeleteProgram (shader);
 }
 
 static void
-bind_float_arb (cairo_gl_shader_t *shader,
+bind_float_arb (cairo_gl_context_t *ctx,
+		cairo_gl_shader_t *shader,
 		const char *name,
 		float value)
 {
-    GLint location = glGetUniformLocationARB (shader->program, name);
+    cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
+    GLint location = dispatch->GetUniformLocation (shader->program, name);
     assert (location != -1);
-    glUniform1fARB (location, value);
+    dispatch->Uniform1f (location, value);
 }
 
 static void
-bind_vec2_arb (cairo_gl_shader_t *shader,
+bind_vec2_arb (cairo_gl_context_t *ctx,
+	       cairo_gl_shader_t *shader,
 	       const char *name,
 	       float value0,
 	       float value1)
 {
-    GLint location = glGetUniformLocationARB (shader->program, name);
+    cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
+    GLint location = dispatch->GetUniformLocation (shader->program, name);
     assert (location != -1);
-    glUniform2fARB (location, value0, value1);
+    dispatch->Uniform2f (location, value0, value1);
 }
 
 static void
-bind_vec3_arb (cairo_gl_shader_t *shader,
+bind_vec3_arb (cairo_gl_context_t *ctx,
+	       cairo_gl_shader_t *shader,
 	       const char *name,
 	       float value0,
 	       float value1,
 	       float value2)
 {
-    GLint location = glGetUniformLocationARB (shader->program, name);
+    cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
+    GLint location = dispatch->GetUniformLocation (shader->program, name);
     assert (location != -1);
-    glUniform3fARB (location, value0, value1, value2);
+    dispatch->Uniform3f (location, value0, value1, value2);
 }
 
 static void
-bind_vec4_arb (cairo_gl_shader_t *shader,
+bind_vec4_arb (cairo_gl_context_t *ctx,
+	       cairo_gl_shader_t *shader,
 	       const char *name,
 	       float value0,
 	       float value1,
 	       float value2,
 	       float value3)
 {
-    GLint location = glGetUniformLocationARB (shader->program, name);
+    cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
+    GLint location = dispatch->GetUniformLocation (shader->program, name);
     assert (location != -1);
-    glUniform4fARB (location, value0, value1, value2, value3);
+    dispatch->Uniform4f (location, value0, value1, value2, value3);
 }
 
 static void
-bind_matrix_arb (cairo_gl_shader_t *shader,
+bind_matrix_arb (cairo_gl_context_t *ctx,
+		 cairo_gl_shader_t *shader,
 		 const char *name,
 		 cairo_matrix_t* m)
 {
-    GLint location = glGetUniformLocationARB (shader->program, name);
-    float gl_m[9] = {
+    cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
+    GLint location = dispatch->GetUniformLocation (shader->program, name);
+    float gl_m[16] = {
         m->xx, m->xy, m->x0,
         m->yx, m->yy, m->y0,
         0,     0,     1
     };
     assert (location != -1);
-    glUniformMatrix3fvARB (location, 1, GL_TRUE, gl_m);
+    dispatch->UniformMatrix3fv (location, 1, GL_TRUE, gl_m);
 }
 
 static void
-bind_texture_arb (cairo_gl_shader_t *shader,
+bind_texture_arb (cairo_gl_context_t *ctx,
+		  cairo_gl_shader_t *shader,
 		  const char *name,
 		  cairo_gl_tex_t tex_unit)
 {
-    GLint location = glGetUniformLocationARB (shader->program, name);
+    cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
+    GLint location = dispatch->GetUniformLocation (shader->program, name);
     assert (location != -1);
-    glUniform1iARB (location, tex_unit);
+    dispatch->Uniform1i (location, tex_unit);
 }
 
 static void
-use_program_arb (cairo_gl_shader_t *shader)
+use_program_arb (cairo_gl_context_t *ctx, cairo_gl_shader_t *shader)
 {
     if (shader)
-	glUseProgramObjectARB (shader->program);
+	ctx->dispatch.UseProgram (shader->program);
     else
-	glUseProgramObjectARB (0);
+	ctx->dispatch.UseProgram (0);
 }
 
 /* OpenGL Core 2.0 API. */
 static void
-compile_shader_core_2_0 (GLuint *shader, GLenum type, const char *text)
+compile_shader_core_2_0 (cairo_gl_context_t *ctx, GLuint *shader,
+			 GLenum type, const char *text)
 {
     const char* strings[1] = { text };
     GLint gl_status;
+    cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
 
-    *shader = glCreateShader (type);
-    glShaderSource (*shader, 1, strings, 0);
-    glCompileShader (*shader);
-    glGetShaderiv (*shader, GL_COMPILE_STATUS, &gl_status);
+    *shader = dispatch->CreateShader (type);
+    dispatch->ShaderSource (*shader, 1, strings, 0);
+    dispatch->CompileShader (*shader);
+    dispatch->GetShaderiv (*shader, GL_COMPILE_STATUS, &gl_status);
     if (gl_status == GL_FALSE) {
         GLint log_size;
-        glGetShaderiv (*shader, GL_INFO_LOG_LENGTH, &log_size);
+        dispatch->GetShaderiv (*shader, GL_INFO_LOG_LENGTH, &log_size);
         if (0 < log_size) {
             char *log = _cairo_malloc (log_size);
             GLint chars;
 
             log[log_size - 1] = '\0';
-            glGetShaderInfoLog (*shader, log_size, &chars, log);
+            dispatch->GetShaderInfoLog (*shader, log_size, &chars, log);
             printf ("OpenGL shader compilation failed.  Shader:\n"
                     "%s\n"
                     "OpenGL compilation log:\n"
@@ -294,24 +321,26 @@  compile_shader_core_2_0 (GLuint *shader, GLenum type, const char *text)
 }
 
 static void
-link_shader_core_2_0 (GLuint *program, GLuint vert, GLuint frag)
+link_shader_core_2_0 (cairo_gl_context_t *ctx, GLuint *program,
+		      GLuint vert, GLuint frag)
 {
     GLint gl_status;
+    cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
 
-    *program = glCreateProgram ();
-    glAttachShader (*program, vert);
-    glAttachShader (*program, frag);
-    glLinkProgram (*program);
-    glGetProgramiv (*program, GL_LINK_STATUS, &gl_status);
+    *program = dispatch->CreateProgram ();
+    dispatch->AttachShader (*program, vert);
+    dispatch->AttachShader (*program, frag);
+    dispatch->LinkProgram (*program);
+    dispatch->GetProgramiv (*program, GL_LINK_STATUS, &gl_status);
     if (gl_status == GL_FALSE) {
         GLint log_size;
-        glGetProgramiv (*program, GL_INFO_LOG_LENGTH, &log_size);
+        dispatch->GetProgramiv (*program, GL_INFO_LOG_LENGTH, &log_size);
         if (0 < log_size) {
             char *log = _cairo_malloc (log_size);
             GLint chars;
 
             log[log_size - 1] = '\0';
-            glGetProgramInfoLog (*program, log_size, &chars, log);
+            dispatch->GetProgramInfoLog (*program, log_size, &chars, log);
             printf ("OpenGL shader link failed:\n%s\n", log);
 
             free (log);
@@ -324,91 +353,106 @@  link_shader_core_2_0 (GLuint *program, GLuint vert, GLuint frag)
 }
 
 static void
-destroy_shader_core_2_0 (GLuint shader)
+destroy_shader_core_2_0 (cairo_gl_context_t *ctx, GLuint shader)
 {
-  glDeleteShader (shader);
+    ctx->dispatch.DeleteShader (shader);
 }
 
 static void
-destroy_program_core_2_0 (GLuint shader)
+destroy_program_core_2_0 (cairo_gl_context_t *ctx, GLuint shader)
 {
-    glDeleteProgram (shader);
+    ctx->dispatch.DeleteProgram (shader);
 }
 
 static void
-bind_float_core_2_0 (cairo_gl_shader_t *shader,
+bind_float_core_2_0 (cairo_gl_context_t *ctx,
+		     cairo_gl_shader_t *shader,
 		     const char *name,
 		     float value)
 {
-    GLint location = glGetUniformLocation (shader->program, name);
+    cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
+    GLint location = dispatch->GetUniformLocation (shader->program, name);
     assert (location != -1);
-    glUniform1f (location, value);
+    dispatch->Uniform1f (location, value);
 }
 
 static void
-bind_vec2_core_2_0 (cairo_gl_shader_t *shader,
+bind_vec2_core_2_0 (cairo_gl_context_t *ctx,
+		    cairo_gl_shader_t *shader,
 		    const char *name,
 		    float value0,
 		    float value1)
 {
-    GLint location = glGetUniformLocation (shader->program, name);
+    cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
+    GLint location = dispatch->GetUniformLocation (shader->program, name);
     assert (location != -1);
-    glUniform2f (location, value0, value1);
+    dispatch->Uniform2f (location, value0, value1);
 }
 
 static void
-bind_vec3_core_2_0 (cairo_gl_shader_t *shader,
+bind_vec3_core_2_0 (cairo_gl_context_t *ctx,
+		    cairo_gl_shader_t *shader,
 		    const char *name,
 		    float value0,
 		    float value1,
 		    float value2)
 {
-    GLint location = glGetUniformLocation (shader->program, name);
+    cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
+    GLint location = dispatch->GetUniformLocation (shader->program, name);
     assert (location != -1);
-    glUniform3f (location, value0, value1, value2);
+    dispatch->Uniform3f (location, value0, value1, value2);
 }
 
 static void
-bind_vec4_core_2_0 (cairo_gl_shader_t *shader,
+bind_vec4_core_2_0 (cairo_gl_context_t *ctx,
+		    cairo_gl_shader_t *shader,
 		    const char *name,
 		    float value0,
 		    float value1,
 		    float value2,
 		    float value3)
 {
-    GLint location = glGetUniformLocation (shader->program, name);
+    cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
+    GLint location = dispatch->GetUniformLocation (shader->program, name);
     assert (location != -1);
-    glUniform4f (location, value0, value1, value2, value3);
+    dispatch->Uniform4f (location, value0, value1, value2, value3);
 }
 
 static void
-bind_matrix_core_2_0 (cairo_gl_shader_t *shader, const char *name, cairo_matrix_t* m)
+bind_matrix_core_2_0 (cairo_gl_context_t *ctx,
+		      cairo_gl_shader_t *shader,
+		      const char *name,
+		      cairo_matrix_t* m)
 {
-    GLint location = glGetUniformLocation (shader->program, name);
+    cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
+    GLint location = dispatch->GetUniformLocation (shader->program, name);
     float gl_m[16] = {
         m->xx, m->xy, m->x0,
         m->yx, m->yy, m->y0,
         0,     0,     1
     };
     assert (location != -1);
-    glUniformMatrix3fv (location, 1, GL_TRUE, gl_m);
+    dispatch->UniformMatrix3fv (location, 1, GL_TRUE, gl_m);
 }
 
 static void
-bind_texture_core_2_0 (cairo_gl_shader_t *shader, const char *name, cairo_gl_tex_t tex_unit)
+bind_texture_core_2_0 (cairo_gl_context_t *ctx, cairo_gl_shader_t *shader,
+		       const char *name, cairo_gl_tex_t tex_unit)
 {
-    GLint location = glGetUniformLocation (shader->program, name);
+    cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
+    GLint location = dispatch->GetUniformLocation (shader->program, name);
     assert (location != -1);
-    glUniform1i (location, tex_unit);
+    dispatch->Uniform1i (location, tex_unit);
 }
 
 static void
-use_program_core_2_0 (cairo_gl_shader_t *shader)
+use_program_core_2_0 (cairo_gl_context_t *ctx,
+		      cairo_gl_shader_t *shader)
 {
     if (shader)
-	glUseProgram (shader->program);
+	ctx->dispatch.UseProgram (shader->program);
     else
-	glUseProgram (0);
+	ctx->dispatch.UseProgram (0);
 }
 
 static const cairo_gl_shader_impl_t shader_impl_core_2_0 = {
@@ -540,7 +584,7 @@  _cairo_gl_context_fini_shaders (cairo_gl_context_t *ctx)
 
     for (i = 0; i <= CAIRO_GL_VAR_TYPE_MAX; i++) {
 	if (ctx->vertex_shaders[i])
-	    ctx->shader_impl->destroy_shader (ctx->vertex_shaders[i]);
+	    ctx->shader_impl->destroy_shader (ctx, ctx->vertex_shaders[i]);
     }
 
     _cairo_cache_fini (&ctx->shaders);
@@ -551,10 +595,10 @@  _cairo_gl_shader_fini (cairo_gl_context_t *ctx,
 		       cairo_gl_shader_t *shader)
 {
     if (shader->fragment_shader)
-        ctx->shader_impl->destroy_shader (shader->fragment_shader);
+        ctx->shader_impl->destroy_shader (ctx, shader->fragment_shader);
 
     if (shader->program)
-        ctx->shader_impl->destroy_program (shader->program);
+        ctx->shader_impl->destroy_program (ctx, shader->program);
 }
 
 static const char *operand_names[] = { "source", "mask", "dest" };
@@ -664,7 +708,7 @@  cairo_gl_shader_emit_color (cairo_output_stream_t *stream,
                             cairo_gl_tex_t name)
 {
     const char *namestr = operand_names[name];
-    const char *rectstr = (tex_target == GL_TEXTURE_RECTANGLE_EXT ? "Rect" : "");
+    const char *rectstr = (tex_target == GL_TEXTURE_RECTANGLE ? "Rect" : "");
 
     switch (type) {
     case CAIRO_GL_OPERAND_COUNT:
@@ -828,17 +872,17 @@  _cairo_gl_shader_compile (cairo_gl_context_t *ctx,
         if (unlikely (status))
             goto FAILURE;
 
-	ctx->shader_impl->compile_shader (&ctx->vertex_shaders[vertex_shader],
+	ctx->shader_impl->compile_shader (ctx, &ctx->vertex_shaders[vertex_shader],
 					  GL_VERTEX_SHADER,
 					  source);
         free (source);
     }
 
-    ctx->shader_impl->compile_shader (&shader->fragment_shader,
+    ctx->shader_impl->compile_shader (ctx, &shader->fragment_shader,
 				      GL_FRAGMENT_SHADER,
 				      fragment_text);
 
-    ctx->shader_impl->link_shader (&shader->program,
+    ctx->shader_impl->link_shader (ctx, &shader->program,
 				   ctx->vertex_shaders[vertex_shader],
 				   shader->fragment_shader);
 
@@ -857,7 +901,7 @@  _cairo_gl_shader_bind_float (cairo_gl_context_t *ctx,
 			     const char *name,
 			     float value)
 {
-    ctx->shader_impl->bind_float (ctx->current_shader, name, value);
+    ctx->shader_impl->bind_float (ctx, ctx->current_shader, name, value);
 }
 
 void
@@ -866,7 +910,7 @@  _cairo_gl_shader_bind_vec2 (cairo_gl_context_t *ctx,
 			    float value0,
 			    float value1)
 {
-    ctx->shader_impl->bind_vec2 (ctx->current_shader, name, value0, value1);
+    ctx->shader_impl->bind_vec2 (ctx, ctx->current_shader, name, value0, value1);
 }
 
 void
@@ -876,7 +920,7 @@  _cairo_gl_shader_bind_vec3 (cairo_gl_context_t *ctx,
 			    float value1,
 			    float value2)
 {
-    ctx->shader_impl->bind_vec3 (ctx->current_shader, name, value0, value1, value2);
+    ctx->shader_impl->bind_vec3 (ctx, ctx->current_shader, name, value0, value1, value2);
 }
 
 void
@@ -885,21 +929,21 @@  _cairo_gl_shader_bind_vec4 (cairo_gl_context_t *ctx,
 			    float value0, float value1,
 			    float value2, float value3)
 {
-    ctx->shader_impl->bind_vec4 (ctx->current_shader, name, value0, value1, value2, value3);
+    ctx->shader_impl->bind_vec4 (ctx, ctx->current_shader, name, value0, value1, value2, value3);
 }
 
 void
 _cairo_gl_shader_bind_matrix (cairo_gl_context_t *ctx,
 			      const char *name, cairo_matrix_t* m)
 {
-    ctx->shader_impl->bind_matrix (ctx->current_shader, name, m);
+    ctx->shader_impl->bind_matrix (ctx, ctx->current_shader, name, m);
 }
 
 void
 _cairo_gl_shader_bind_texture (cairo_gl_context_t *ctx,
 			       const char *name, GLuint tex_unit)
 {
-    ctx->shader_impl->bind_texture (ctx->current_shader, name, tex_unit);
+    ctx->shader_impl->bind_texture (ctx, ctx->current_shader, name, tex_unit);
 }
 
 void
@@ -912,7 +956,7 @@  _cairo_gl_set_shader (cairo_gl_context_t *ctx,
     if (ctx->current_shader == shader)
         return;
 
-    ctx->shader_impl->use (shader);
+    ctx->shader_impl->use (ctx, shader);
 
     ctx->current_shader = shader;
 }
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 9b4b2ac..61a0e9d 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -785,9 +785,9 @@  _cairo_gl_surface_finish (void *abstract_surface)
 	ctx->current_target = NULL;
 
     if (surface->depth)
-        glDeleteFramebuffersEXT (1, &surface->depth);
+        ctx->dispatch.DeleteFramebuffers (1, &surface->depth);
     if (surface->fb)
-        glDeleteFramebuffersEXT (1, &surface->fb);
+        ctx->dispatch.DeleteFramebuffers (1, &surface->fb);
     if (surface->owns_tex)
 	glDeleteTextures (1, &surface->tex);