[cairo-commit] 12 commits - boilerplate/cairo-boilerplate-gl.c src/cairo-array.c src/cairo-gl-device.c src/cairo-gl-glyphs.c src/cairo-gl.h src/cairo-gl-private.h src/cairo-gl-surface.c src/Makefile.sources

Benjamin Otte company at kemper.freedesktop.org
Wed May 5 04:20:44 PDT 2010


 boilerplate/cairo-boilerplate-gl.c |   17 --
 src/Makefile.sources               |    6 
 src/cairo-array.c                  |    2 
 src/cairo-gl-device.c              |  205 ++++++++++++++++++++++++
 src/cairo-gl-glyphs.c              |   21 +-
 src/cairo-gl-private.h             |   12 +
 src/cairo-gl-surface.c             |  312 +++++++++----------------------------
 src/cairo-gl.h                     |    3 
 8 files changed, 316 insertions(+), 262 deletions(-)

New commits:
commit 9c594d8b405eba09b07c0a438f5311f5c5e40313
Author: Benjamin Otte <otte at redhat.com>
Date:   Wed May 5 12:28:59 2010 +0200

    gl: Get rid of ctx variable
    
    The code used renderer->ctx and ctx interchangably, that was confusing.

diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index c6aacdf..2690bd6 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -2786,7 +2786,6 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t	 op,
 					cairo_region_t		*clip_region)
 {
     cairo_gl_surface_t *dst = abstract_dst;
-    cairo_gl_context_t *ctx = (cairo_gl_context_t *) dst->base.device;
     cairo_gl_surface_span_renderer_t *renderer;
     cairo_status_t status;
     cairo_surface_attributes_t *src_attributes;
@@ -2819,17 +2818,18 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t	 op,
 	return _cairo_span_renderer_create_in_error (status);
     }
 
-    status = _cairo_gl_operand_init (ctx, &renderer->setup.src, src, dst,
+    status = _cairo_gl_operand_init (renderer->ctx,
+                                     &renderer->setup.src, src, dst,
 				     rects->source.x, rects->source.y,
 				     extents->x, extents->y,
 				     extents->width, extents->height);
     if (unlikely (status)) {
-        _cairo_gl_context_release (ctx);
+        _cairo_gl_context_release (renderer->ctx);
 	free (renderer);
 	return _cairo_span_renderer_create_in_error (status);
     }
 
-    _cairo_gl_set_destination (ctx, dst);
+    _cairo_gl_set_destination (renderer->ctx, dst);
 
     status = _cairo_gl_get_program (renderer->ctx,
 				    renderer->setup.src.source,
@@ -2853,8 +2853,8 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t	 op,
 	/* Set up the mask to source from the incoming vertex color. */
 	glActiveTexture (GL_TEXTURE1);
 	/* Have to have a dummy texture bound in order to use the combiner unit. */
-	glBindTexture (ctx->tex_target, renderer->ctx->dummy_tex);
-	glEnable (ctx->tex_target);
+	glBindTexture (renderer->ctx->tex_target, renderer->ctx->dummy_tex);
+	glEnable (renderer->ctx->tex_target);
 	glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
 	glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
 	glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
commit a354f1f92a17378f42d0b703482ae2b8168c7f68
Author: Benjamin Otte <otte at redhat.com>
Date:   Wed May 5 12:28:24 2010 +0200

    gl: Another case of proper device acquiring
    
    This patch isn't strictly necessary, but it cleans up the code.

diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 5576a99..c6aacdf 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -536,20 +536,23 @@ _cairo_gl_surface_create_similar (void		 *abstract_surface,
 				  int		  height)
 {
     cairo_surface_t *surface = abstract_surface;
-    cairo_gl_context_t *ctx = (cairo_gl_context_t *) surface->device;
+    cairo_gl_context_t *ctx;
     cairo_status_t status;
 
+    status = _cairo_gl_context_acquire (surface->device, &ctx);
+    if (unlikely (status))
+	return _cairo_surface_create_in_error (status);
+
     if (width > ctx->max_framebuffer_size ||
 	height > ctx->max_framebuffer_size)
     {
-	return NULL;
+	surface = NULL;
+        goto RELEASE;
     }
 
-    status = _cairo_gl_context_acquire (surface->device, &ctx);
-    if (unlikely (status))
-	return _cairo_surface_create_in_error (status);
-
     surface = _cairo_gl_surface_create_scratch (ctx, content, width, height);
+
+RELEASE:
     _cairo_gl_context_release (ctx);
 
     return surface;
commit 36210ee51444979271f7ba1cc0ac452cd30df0af
Author: Benjamin Otte <otte at redhat.com>
Date:   Wed May 5 12:24:43 2010 +0200

    gl: Get rid of another cast to cairo_gl_context_t

diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 5dedcbd..5576a99 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -419,19 +419,19 @@ cairo_gl_surface_create (cairo_device_t		*abstract_device,
 			 int			 width,
 			 int			 height)
 {
-    cairo_gl_context_t *ctx = (cairo_gl_context_t *) abstract_device;
+    cairo_gl_context_t *ctx;
     cairo_gl_surface_t *surface;
     cairo_status_t status;
 
     if (! CAIRO_CONTENT_VALID (content))
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT));
 
-    if (ctx == NULL) {
+    if (abstract_device == NULL) {
 	return cairo_image_surface_create (_cairo_format_from_content (content),
 					   width, height);
     }
 
-    if (ctx->base.backend->type != CAIRO_DEVICE_TYPE_GL)
+    if (abstract_device->backend->type != CAIRO_DEVICE_TYPE_GL)
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
 
     status = _cairo_gl_context_acquire (abstract_device, &ctx);
commit 58b03691d379979b50d74740748b8b8523e0cd0d
Author: Benjamin Otte <otte at redhat.com>
Date:   Wed May 5 12:21:23 2010 +0200

    gl: Introduce _cairo_gl_device_has_glsl() function
    
    The function takes a cairo_device_t argument as it can be called on an
    unacquired device.
    
    This is the first patch in a process to try to rid cairo-gl-surface.c of
    casts from cairo_device_t to cairo_gl_context_t. As its members should
    usually only be accessed when the device is locked, the only way the
    cairo_gl_context_t should be acquired is using
    _cairo_gl_context_acquire().

diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index cf0cbd6..604d060 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -316,7 +316,7 @@ _cairo_gl_glyphs_set_shader (cairo_gl_context_t *ctx,
     if (setup->in == in)
 	return;
 
-    if (ctx->using_glsl) {
+    if (_cairo_gl_device_has_glsl (&ctx->base)) {
 	cairo_status_t status;
 
 	status = _cairo_gl_get_program (ctx,
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 75a9348..c0d9c62 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -224,6 +224,12 @@ _cairo_gl_operand_init (cairo_gl_context_t *ctx,
 			int dst_x, int dst_y,
 			int width, int height);
 
+static cairo_always_inline cairo_bool_t
+_cairo_gl_device_has_glsl (cairo_device_t *device)
+{
+    return ((cairo_gl_context_t *) device)->using_glsl;
+}
+
 static cairo_always_inline cairo_status_t cairo_warn
 _cairo_gl_context_acquire (cairo_device_t *device,
 			   cairo_gl_context_t **ctx)
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index d9eb3fd..5dedcbd 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -637,7 +637,7 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
 	GLuint tex;
 	GLfloat vertices[8], texcoords[8];
 
-	if (ctx->using_glsl) {
+	if (_cairo_gl_device_has_glsl (&ctx->base)) {
 	    cairo_gl_shader_program_t *program;
 
 	    status = _cairo_gl_get_program (ctx,
@@ -710,7 +710,7 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
 	glDisableClientState (GL_VERTEX_ARRAY);
 	glDisableClientState (GL_TEXTURE_COORD_ARRAY);
 
-	if (ctx->using_glsl)
+	if (_cairo_gl_device_has_glsl (&ctx->base))
 	    _cairo_gl_use_program (NULL);
 	glDeleteTextures (1, &tex);
 	glDisable (ctx->tex_target);
@@ -1268,7 +1268,7 @@ _cairo_gl_gradient_operand_init(cairo_gl_context_t *ctx,
 	}
     }
 
-    if (!ctx->using_glsl)
+    if (! _cairo_gl_device_has_glsl (&ctx->base))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
@@ -2487,9 +2487,8 @@ _cairo_gl_surface_fill_rectangles (void			   *abstract_surface,
 				   int			    num_rects)
 {
     cairo_gl_surface_t *surface = abstract_surface;
-    cairo_gl_context_t *ctx = (cairo_gl_context_t *) surface->base.device;
 
-    if (ctx->using_glsl) {
+    if (_cairo_gl_device_has_glsl (surface->base.device)) {
 	return _cairo_gl_surface_fill_rectangles_glsl(abstract_surface,
 						      op,
 						      color,
commit 5223b654230d3074d0bc31eb74c415e50eced365
Author: Benjamin Otte <otte at redhat.com>
Date:   Wed May 5 12:07:49 2010 +0200

    gl: Get rid of cairo_gl_surface_glfinish() from public API
    
    This is now done explicitly in the boilerplate code. It was not a useful
    public API to begin with.

diff --git a/boilerplate/cairo-boilerplate-gl.c b/boilerplate/cairo-boilerplate-gl.c
index 37030af..5957da4 100644
--- a/boilerplate/cairo-boilerplate-gl.c
+++ b/boilerplate/cairo-boilerplate-gl.c
@@ -234,7 +234,12 @@ _cairo_boilerplate_gl_synchronize (void *closure)
 {
     gl_target_closure_t *gltc = closure;
 
-    cairo_gl_surface_glfinish (gltc->surface);
+    if (cairo_device_acquire (gltc->device))
+        return;
+
+    glFinish ();
+
+    cairo_device_release (gltc->device);
 }
 
 #if CAIRO_HAS_EGL_FUNCTIONS
@@ -312,14 +317,6 @@ _cairo_boilerplate_egl_create_surface (const char		 *name,
 
     return surface;
 }
-
-static void
-_cairo_boilerplate_egl_synchronize (void *closure)
-{
-    egl_target_closure_t *gltc = closure;
-
-    cairo_gl_surface_glfinish (gltc->surface);
-}
 #endif
 
 static const cairo_boilerplate_target_t targets[] = {
@@ -370,7 +367,7 @@ static const cairo_boilerplate_target_t targets[] = {
 	_cairo_boilerplate_get_image_surface,
 	cairo_surface_write_to_png,
 	_cairo_boilerplate_egl_cleanup,
-	_cairo_boilerplate_egl_synchronize,
+	_cairo_boilerplate_gl_synchronize,
 	TRUE, FALSE, FALSE
     },
 #endif
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 1a0cbd4..d9eb3fd 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -2944,12 +2944,3 @@ const cairo_surface_backend_t _cairo_gl_surface_backend = {
     _cairo_gl_surface_show_glyphs, /* show_glyphs */
     NULL  /* snapshot */
 };
-
-/** Call glFinish(), used for accurate performance testing. */
-cairo_status_t
-cairo_gl_surface_glfinish (cairo_surface_t *surface)
-{
-    glFinish ();
-
-    return CAIRO_STATUS_SUCCESS;
-}
diff --git a/src/cairo-gl.h b/src/cairo-gl.h
index c1416d1..7dc1fbd 100644
--- a/src/cairo-gl.h
+++ b/src/cairo-gl.h
@@ -57,9 +57,6 @@ cairo_gl_surface_get_height (cairo_surface_t *abstract_surface);
 cairo_public void
 cairo_gl_surface_swapbuffers (cairo_surface_t *surface);
 
-cairo_public cairo_status_t
-cairo_gl_surface_glfinish (cairo_surface_t *surface);
-
 #if CAIRO_HAS_GLX_FUNCTIONS
 #include <GL/glx.h>
 
commit e071fa2c4f62b5ead39c6c6401f39360ea4dee1f
Author: Benjamin Otte <otte at redhat.com>
Date:   Wed May 5 12:03:13 2010 +0200

    gl: Remove unused member variable

diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 00e95d8..75a9348 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -125,7 +125,6 @@ typedef struct _cairo_gl_context {
     GLenum tex_target;
     cairo_bool_t using_glsl;
 
-    cairo_bool_t using_shaders;
     cairo_gl_shader_program_t fill_rectangles_shader;
     cairo_gl_shader_program_t shaders[CAIRO_GL_SHADER_SOURCE_COUNT]
 					[CAIRO_GL_SHADER_MASK_COUNT]
commit 90c64f60d853f1a6ea5febd362ef3528cc9d914b
Author: Benjamin Otte <otte at redhat.com>
Date:   Wed May 5 12:01:59 2010 +0200

    gl: Move device-specific code into cairo-gl-device.c

diff --git a/src/Makefile.sources b/src/Makefile.sources
index e92ec8b..a40404b 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -313,7 +313,11 @@ cairo_beos_headers = cairo-beos.h
 
 cairo_gl_headers = cairo-gl.h
 cairo_gl_private = cairo-gl-private.h
-cairo_gl_sources = cairo-gl-surface.c cairo-gl-glyphs.c cairo-gl-shaders.c
+cairo_gl_sources = cairo-gl-device.c \
+		   cairo-gl-glyphs.c \
+		   cairo-gl-shaders.c \
+		   cairo-gl-surface.c
+
 cairo_glx_sources += cairo-glx-context.c
 cairo_egl_sources += cairo-egl-context.c
 
diff --git a/src/cairo-gl-device.c b/src/cairo-gl-device.c
new file mode 100644
index 0000000..3d121e9
--- /dev/null
+++ b/src/cairo-gl-device.c
@@ -0,0 +1,205 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2009 Eric Anholt
+ * Copyright © 2009 Chris Wilson
+ * Copyright © 2005 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Contributor(s):
+ *	Carl Worth <cworth at cworth.org>
+ */
+
+#include "cairoint.h"
+
+#include "cairo-error-private.h"
+#include "cairo-gl-private.h"
+
+static void
+_gl_lock (void *device)
+{
+    cairo_gl_context_t *ctx = (cairo_gl_context_t *) device;
+
+    ctx->acquire (ctx);
+}
+
+static void
+_gl_unlock (void *device)
+{
+    cairo_gl_context_t *ctx = (cairo_gl_context_t *) device;
+
+    ctx->release (ctx);
+    ctx->current_target = NULL;
+}
+
+static void
+_gl_destroy (void *device)
+{
+    cairo_gl_context_t *ctx = device;
+    cairo_scaled_font_t *scaled_font, *next_scaled_font;
+    int n;
+
+    ctx->acquire (ctx);
+
+    cairo_list_foreach_entry_safe (scaled_font,
+				   next_scaled_font,
+				   cairo_scaled_font_t,
+				   &ctx->fonts,
+				   link)
+    {
+	_cairo_scaled_font_revoke_ownership (scaled_font);
+    }
+
+    for (n = 0; n < ARRAY_LENGTH (ctx->glyph_cache); n++)
+	_cairo_gl_glyph_cache_fini (ctx, &ctx->glyph_cache[n]);
+
+    ctx->destroy (ctx);
+
+    free (ctx);
+}
+
+static const cairo_device_backend_t _cairo_gl_device_backend = {
+    CAIRO_DEVICE_TYPE_GL,
+
+    _gl_lock,
+    _gl_unlock,
+
+    NULL, /* flush */
+    NULL, /* finish */
+    _gl_destroy,
+};
+
+cairo_status_t
+_cairo_gl_context_init (cairo_gl_context_t *ctx)
+{
+    int n;
+
+    _cairo_device_init (&ctx->base, &_cairo_gl_device_backend);
+
+    memset (ctx->glyph_cache, 0, sizeof (ctx->glyph_cache));
+    cairo_list_init (&ctx->fonts);
+
+    if (glewInit () != GLEW_OK)
+	return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); /* XXX */
+
+    if (! GLEW_EXT_framebuffer_object ||
+	! GLEW_ARB_texture_env_combine ||
+	! GLEW_EXT_bgra)
+    {
+	fprintf (stderr,
+		 "Required GL extensions not available:\n");
+	if (! GLEW_EXT_framebuffer_object)
+	    fprintf (stderr, "    GL_EXT_framebuffer_object\n");
+	if (! GLEW_ARB_texture_env_combine)
+	    fprintf (stderr, "    GL_ARB_texture_env_combine\n");
+	/* EXT_bgra is used in two places:
+	 * - draw_image to upload common pixman formats without hand-swizzling.
+	 * - get_image to download common pixman formats without hand-swizzling.
+	 */
+	if (! GLEW_EXT_bgra)
+	    fprintf (stderr, "    GL_EXT_bgra\n");
+
+	return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); /* XXX */
+    }
+
+    if (! GLEW_ARB_texture_non_power_of_two &&
+	! GLEW_ARB_texture_rectangle ) {
+	fprintf (stderr,
+		 "Required GL extensions not available:\n");
+	fprintf (stderr, "    GL_ARB_texture_non_power_of_two, GL_ARB_texture_rectangle\n");
+    }
+
+    if (!GLEW_ARB_texture_non_power_of_two)
+	ctx->tex_target = GL_TEXTURE_RECTANGLE_EXT;
+    else
+	ctx->tex_target = GL_TEXTURE_2D;
+
+
+    if (GLEW_VERSION_2_0 ||
+	(GLEW_ARB_fragment_shader &&
+	 GLEW_ARB_vertex_shader &&
+	 GLEW_ARB_shader_objects))
+    {
+	ctx->using_glsl = TRUE;
+    }
+
+    init_shader_program (&ctx->fill_rectangles_shader);
+
+    /* Set up the dummy texture for tex_env_combine with constant color. */
+    glGenTextures (1, &ctx->dummy_tex);
+    glBindTexture (ctx->tex_target, ctx->dummy_tex);
+    glTexImage2D (ctx->tex_target, 0, GL_RGBA, 1, 1, 0,
+		  GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+
+    /* PBO for any sort of texture upload */
+    glGenBuffersARB (1, &ctx->texture_load_pbo);
+    glGenBuffersARB (1, &ctx->vbo);
+
+    ctx->max_framebuffer_size = 0;
+    glGetIntegerv (GL_MAX_RENDERBUFFER_SIZE, &ctx->max_framebuffer_size);
+    ctx->max_texture_size = 0;
+    glGetIntegerv (GL_MAX_TEXTURE_SIZE, &ctx->max_texture_size);
+
+    for (n = 0; n < ARRAY_LENGTH (ctx->glyph_cache); n++)
+	_cairo_gl_glyph_cache_init (&ctx->glyph_cache[n]);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+void
+_cairo_gl_set_destination (cairo_gl_context_t *ctx,
+                           cairo_gl_surface_t *surface)
+{
+    if (ctx->current_target != surface) {
+	ctx->current_target = surface;
+
+	if (surface->fb) {
+	    glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, surface->fb);
+	    glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);
+	    glReadBuffer (GL_COLOR_ATTACHMENT0_EXT);
+	} else {
+	    ctx->make_current (ctx, surface);
+	    glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
+	    glDrawBuffer (GL_BACK_LEFT);
+	    glReadBuffer (GL_BACK_LEFT);
+	}
+    }
+
+    glViewport (0, 0, surface->width, surface->height);
+
+    glMatrixMode (GL_PROJECTION);
+    glLoadIdentity ();
+    if (surface->fb)
+	glOrtho (0, surface->width, 0, surface->height, -1.0, 1.0);
+    else
+	glOrtho (0, surface->width, surface->height, 0, -1.0, 1.0);
+
+    glMatrixMode (GL_MODELVIEW);
+    glLoadIdentity ();
+}
+
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 0fde030..1a0cbd4 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -67,137 +67,6 @@ static cairo_bool_t _cairo_surface_is_gl (cairo_surface_t *surface)
     return surface->backend == &_cairo_gl_surface_backend;
 }
 
-static void
-_gl_lock (void *device)
-{
-    cairo_gl_context_t *ctx = (cairo_gl_context_t *) device;
-
-    ctx->acquire (ctx);
-}
-
-static void
-_gl_unlock (void *device)
-{
-    cairo_gl_context_t *ctx = (cairo_gl_context_t *) device;
-
-    ctx->release (ctx);
-    ctx->current_target = NULL;
-}
-
-static void
-_gl_destroy (void *device)
-{
-    cairo_gl_context_t *ctx = device;
-    cairo_scaled_font_t *scaled_font, *next_scaled_font;
-    int n;
-
-    ctx->acquire (ctx);
-
-    cairo_list_foreach_entry_safe (scaled_font,
-				   next_scaled_font,
-				   cairo_scaled_font_t,
-				   &ctx->fonts,
-				   link)
-    {
-	_cairo_scaled_font_revoke_ownership (scaled_font);
-    }
-
-    for (n = 0; n < ARRAY_LENGTH (ctx->glyph_cache); n++)
-	_cairo_gl_glyph_cache_fini (ctx, &ctx->glyph_cache[n]);
-
-    ctx->destroy (ctx);
-
-    free (ctx);
-}
-
-static const cairo_device_backend_t _cairo_gl_device_backend = {
-    CAIRO_DEVICE_TYPE_GL,
-
-    _gl_lock,
-    _gl_unlock,
-
-    NULL, /* flush */
-    NULL, /* finish */
-    _gl_destroy,
-};
-
-cairo_status_t
-_cairo_gl_context_init (cairo_gl_context_t *ctx)
-{
-    int n;
-
-    _cairo_device_init (&ctx->base, &_cairo_gl_device_backend);
-
-    memset (ctx->glyph_cache, 0, sizeof (ctx->glyph_cache));
-    cairo_list_init (&ctx->fonts);
-
-    if (glewInit () != GLEW_OK)
-	return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); /* XXX */
-
-    if (! GLEW_EXT_framebuffer_object ||
-	! GLEW_ARB_texture_env_combine ||
-	! GLEW_EXT_bgra)
-    {
-	fprintf (stderr,
-		 "Required GL extensions not available:\n");
-	if (! GLEW_EXT_framebuffer_object)
-	    fprintf (stderr, "    GL_EXT_framebuffer_object\n");
-	if (! GLEW_ARB_texture_env_combine)
-	    fprintf (stderr, "    GL_ARB_texture_env_combine\n");
-	/* EXT_bgra is used in two places:
-	 * - draw_image to upload common pixman formats without hand-swizzling.
-	 * - get_image to download common pixman formats without hand-swizzling.
-	 */
-	if (! GLEW_EXT_bgra)
-	    fprintf (stderr, "    GL_EXT_bgra\n");
-
-	return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); /* XXX */
-    }
-
-    if (! GLEW_ARB_texture_non_power_of_two &&
-	! GLEW_ARB_texture_rectangle ) {
-	fprintf (stderr,
-		 "Required GL extensions not available:\n");
-	fprintf (stderr, "    GL_ARB_texture_non_power_of_two, GL_ARB_texture_rectangle\n");
-    }
-
-    if (!GLEW_ARB_texture_non_power_of_two)
-	ctx->tex_target = GL_TEXTURE_RECTANGLE_EXT;
-    else
-	ctx->tex_target = GL_TEXTURE_2D;
-
-
-    if (GLEW_VERSION_2_0 ||
-	(GLEW_ARB_fragment_shader &&
-	 GLEW_ARB_vertex_shader &&
-	 GLEW_ARB_shader_objects))
-    {
-	ctx->using_glsl = TRUE;
-    }
-
-    init_shader_program (&ctx->fill_rectangles_shader);
-
-    /* Set up the dummy texture for tex_env_combine with constant color. */
-    glGenTextures (1, &ctx->dummy_tex);
-    glBindTexture (ctx->tex_target, ctx->dummy_tex);
-    glTexImage2D (ctx->tex_target, 0, GL_RGBA, 1, 1, 0,
-		  GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-
-    /* PBO for any sort of texture upload */
-    glGenBuffersARB (1, &ctx->texture_load_pbo);
-    glGenBuffersARB (1, &ctx->vbo);
-
-    ctx->max_framebuffer_size = 0;
-    glGetIntegerv (GL_MAX_RENDERBUFFER_SIZE, &ctx->max_framebuffer_size);
-    ctx->max_texture_size = 0;
-    glGetIntegerv (GL_MAX_TEXTURE_SIZE, &ctx->max_texture_size);
-
-    for (n = 0; n < ARRAY_LENGTH (ctx->glyph_cache); n++)
-	_cairo_gl_glyph_cache_init (&ctx->glyph_cache[n]);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
 cairo_bool_t
 _cairo_gl_get_image_format_and_type (pixman_format_code_t pixman_format,
 				     GLenum *internal_format, GLenum *format,
@@ -319,37 +188,6 @@ _cairo_gl_get_image_format_and_type (pixman_format_code_t pixman_format,
     }
 }
 
-void
-_cairo_gl_set_destination (cairo_gl_context_t *ctx, cairo_gl_surface_t *surface)
-{
-    if (ctx->current_target != surface) {
-	ctx->current_target = surface;
-
-	if (surface->fb) {
-	    glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, surface->fb);
-	    glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);
-	    glReadBuffer (GL_COLOR_ATTACHMENT0_EXT);
-	} else {
-	    ctx->make_current (ctx, surface);
-	    glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
-	    glDrawBuffer (GL_BACK_LEFT);
-	    glReadBuffer (GL_BACK_LEFT);
-	}
-    }
-
-    glViewport (0, 0, surface->width, surface->height);
-
-    glMatrixMode (GL_PROJECTION);
-    glLoadIdentity ();
-    if (surface->fb)
-	glOrtho (0, surface->width, 0, surface->height, -1.0, 1.0);
-    else
-	glOrtho (0, surface->width, surface->height, 0, -1.0, 1.0);
-
-    glMatrixMode (GL_MODELVIEW);
-    glLoadIdentity ();
-}
-
 cairo_bool_t
 _cairo_gl_operator_is_supported (cairo_operator_t op)
 {
commit 0ff5a18fd5623b57c7493e6b67a6b1c75af82fb3
Author: Benjamin Otte <otte at redhat.com>
Date:   Wed May 5 11:52:40 2010 +0200

    gl: Make _gl_set_destination() take the context as an argument
    
    Keeping with the API introduced for Xlib, functions that require an
    acquired context take this context as the first argument.

diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index 0b6fb28..cf0cbd6 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -494,7 +494,7 @@ _render_glyphs (cairo_gl_surface_t	*dst,
 	return status;
     }
 
-    _cairo_gl_set_destination (dst);
+    _cairo_gl_set_destination (ctx, dst);
 
     _cairo_scaled_font_freeze_cache (scaled_font);
     if (! _cairo_gl_surface_owns_font (dst, scaled_font)) {
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 11abb4b..00e95d8 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -246,7 +246,7 @@ _cairo_gl_context_release (cairo_gl_context_t *ctx)
 }
 
 cairo_private void
-_cairo_gl_set_destination (cairo_gl_surface_t *surface);
+_cairo_gl_set_destination (cairo_gl_context_t *ctx, cairo_gl_surface_t *surface);
 
 cairo_private cairo_bool_t
 _cairo_gl_operator_is_supported (cairo_operator_t op);
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index f640e6b..0fde030 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -320,10 +320,8 @@ _cairo_gl_get_image_format_and_type (pixman_format_code_t pixman_format,
 }
 
 void
-_cairo_gl_set_destination (cairo_gl_surface_t *surface)
+_cairo_gl_set_destination (cairo_gl_context_t *ctx, cairo_gl_surface_t *surface)
 {
-    cairo_gl_context_t *ctx = (cairo_gl_context_t *) surface->base.device;
-
     if (ctx->current_target != surface) {
 	ctx->current_target = surface;
 
@@ -564,7 +562,7 @@ _cairo_gl_surface_clear (cairo_gl_surface_t *surface)
     if (unlikely (status))
 	return status;
 
-    _cairo_gl_set_destination (surface);
+    _cairo_gl_set_destination (ctx, surface);
     if (surface->base.content == CAIRO_CONTENT_COLOR)
 	glClearColor (0.0, 0.0, 0.0, 1.0);
     else
@@ -819,7 +817,7 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
 	    glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 	}
 
-	_cairo_gl_set_destination (dst);
+	_cairo_gl_set_destination (ctx, dst);
 
 	glGenTextures (1, &tex);
 	glActiveTexture (GL_TEXTURE0);
@@ -939,7 +937,7 @@ _cairo_gl_surface_get_image (cairo_gl_surface_t      *surface,
     status = _cairo_gl_context_acquire (surface->base.device, &ctx);
     if (unlikely (status))
         return status;
-    _cairo_gl_set_destination (surface);
+    _cairo_gl_set_destination (ctx, surface);
 
     glPixelStorei (GL_PACK_ALIGNMENT, 1);
     glPixelStorei (GL_PACK_ROW_LENGTH, image->stride / cpp);
@@ -2028,7 +2026,7 @@ _cairo_gl_surface_composite_component_alpha (cairo_operator_t op,
 	status = CAIRO_STATUS_SUCCESS;
     }
 
-    _cairo_gl_set_destination (dst);
+    _cairo_gl_set_destination (ctx, dst);
 
     if (clip_region != NULL) {
 	int num_rectangles;
@@ -2249,7 +2247,7 @@ _cairo_gl_surface_composite (cairo_operator_t		  op,
 	status = CAIRO_STATUS_SUCCESS;
     }
 
-    _cairo_gl_set_destination (dst);
+    _cairo_gl_set_destination (ctx, dst);
     _cairo_gl_set_operator (dst, op, FALSE);
 
     _cairo_gl_use_program (setup.shader);
@@ -2486,7 +2484,7 @@ _cairo_gl_surface_fill_rectangles_fixed (void			 *abstract_surface,
     if (unlikely (status))
 	return status;
 
-    _cairo_gl_set_destination (surface);
+    _cairo_gl_set_destination (ctx, surface);
     _cairo_gl_set_operator (surface, op, FALSE);
 
     if (num_rects > N_STACK_RECTS) {
@@ -2603,7 +2601,7 @@ _cairo_gl_surface_fill_rectangles_glsl (void                  *abstract_surface,
 
     _cairo_gl_use_program (&ctx->fill_rectangles_shader);
 
-    _cairo_gl_set_destination (surface);
+    _cairo_gl_set_destination (ctx, surface);
     _cairo_gl_set_operator (surface, op, FALSE);
 
     status = bind_vec4_to_shader (ctx->fill_rectangles_shader.program,
@@ -2991,7 +2989,7 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t	 op,
 	return _cairo_span_renderer_create_in_error (status);
     }
 
-    _cairo_gl_set_destination (dst);
+    _cairo_gl_set_destination (ctx, dst);
 
     status = _cairo_gl_get_program (renderer->ctx,
 				    renderer->setup.src.source,
commit e8c5b6b1c2099fc6a49d0a082f5e884d3fbd89df
Author: Benjamin Otte <otte at redhat.com>
Date:   Wed May 5 10:05:30 2010 +0200

    Fix typo in docs

diff --git a/src/cairo-array.c b/src/cairo-array.c
index f2d2fb8..942c9b9 100644
--- a/src/cairo-array.c
+++ b/src/cairo-array.c
@@ -261,7 +261,7 @@ _cairo_array_append (cairo_array_t	*array,
 }
 
 /**
- * _cairo_array_append:
+ * _cairo_array_append_multiple:
  * @array: a #cairo_array_t
  *
  * Append one or more items onto the array by growing the array by
commit 53508e6e3047b4dac6d69d5d3ff2208178998fd4
Author: Benjamin Otte <otte at redhat.com>
Date:   Tue May 4 19:28:45 2010 +0200

    gl: Acquire the context before destroying it.

diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 0214aec..f640e6b 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -91,7 +91,7 @@ _gl_destroy (void *device)
     cairo_scaled_font_t *scaled_font, *next_scaled_font;
     int n;
 
-    ctx->destroy (ctx);
+    ctx->acquire (ctx);
 
     cairo_list_foreach_entry_safe (scaled_font,
 				   next_scaled_font,
@@ -105,6 +105,8 @@ _gl_destroy (void *device)
     for (n = 0; n < ARRAY_LENGTH (ctx->glyph_cache); n++)
 	_cairo_gl_glyph_cache_fini (ctx, &ctx->glyph_cache[n]);
 
+    ctx->destroy (ctx);
+
     free (ctx);
 }
 
commit c46aec489722bf09cd10c52d70bb4975eb1546d9
Author: Benjamin Otte <otte at redhat.com>
Date:   Tue May 4 19:28:22 2010 +0200

    gl: acquire/release context during surface_finish()

diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index f961f10..0214aec 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -964,7 +964,12 @@ static cairo_status_t
 _cairo_gl_surface_finish (void *abstract_surface)
 {
     cairo_gl_surface_t *surface = abstract_surface;
-    cairo_gl_context_t *ctx = (cairo_gl_context_t *) surface->base.device;
+    cairo_status_t status;
+    cairo_gl_context_t *ctx;
+
+    status = _cairo_gl_context_acquire (surface->base.device, &ctx);
+    if (unlikely (status))
+        return status;
 
     glDeleteFramebuffersEXT (1, &surface->fb);
     glDeleteTextures (1, &surface->tex);
@@ -972,6 +977,8 @@ _cairo_gl_surface_finish (void *abstract_surface)
     if (ctx->current_target == surface)
 	ctx->current_target = NULL;
 
+    _cairo_gl_context_release (ctx);
+
     return CAIRO_STATUS_SUCCESS;
 }
 
commit 88801aabb34328746a53d3d59d036dada7ced756
Author: Benjamin Otte <otte at redhat.com>
Date:   Tue May 4 19:23:08 2010 +0200

    gl: Acquire context when initing/destroying gl operands

diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index b5baec6..0b6fb28 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -480,17 +480,19 @@ _render_glyphs (cairo_gl_surface_t	*dst,
 
     memset (&composite_setup, 0, sizeof(composite_setup));
 
-    status = _cairo_gl_operand_init (&composite_setup.src, source, dst,
+    status = _cairo_gl_context_acquire (dst->base.device, &ctx);
+    if (unlikely (status))
+	return status;
+
+    status = _cairo_gl_operand_init (ctx, &composite_setup.src, source, dst,
 				     glyph_extents->x, glyph_extents->y,
 				     dst_x, dst_y,
 				     glyph_extents->width,
 				     glyph_extents->height);
-    if (unlikely (status))
-	return status;
-
-    status = _cairo_gl_context_acquire (dst->base.device, &ctx);
-    if (unlikely (status))
+    if (unlikely (status)) {
+        _cairo_gl_context_release (ctx);
 	return status;
+    }
 
     _cairo_gl_set_destination (dst);
 
@@ -639,10 +641,11 @@ _render_glyphs (cairo_gl_surface_t	*dst,
     _cairo_gl_use_program (NULL);
 
     glBindBufferARB (GL_ARRAY_BUFFER_ARB, 0);
-    _cairo_gl_context_release (ctx);
 
     _cairo_gl_operand_destroy (&composite_setup.src);
 
+    _cairo_gl_context_release (ctx);
+
     *remaining_glyphs = num_glyphs - i;
     return status;
 }
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 9490072..11abb4b 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -217,7 +217,8 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
 			      int dst_x, int dst_y);
 
 cairo_private cairo_int_status_t
-_cairo_gl_operand_init (cairo_gl_composite_operand_t *operand,
+_cairo_gl_operand_init (cairo_gl_context_t *ctx,
+                        cairo_gl_composite_operand_t *operand,
 			const cairo_pattern_t *pattern,
 			cairo_gl_surface_t *dst,
 			int src_x, int src_y,
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index db837aa..f961f10 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -1294,7 +1294,8 @@ _cairo_gl_create_gradient_texture (const cairo_gl_context_t *ctx,
  * from dest to src coords.
  */
 static cairo_status_t
-_cairo_gl_pattern_texture_setup (cairo_gl_composite_operand_t *operand,
+_cairo_gl_pattern_texture_setup (cairo_gl_context_t *ctx,
+                                 cairo_gl_composite_operand_t *operand,
 				 const cairo_pattern_t *src,
 				 cairo_gl_surface_t *dst,
 				 int src_x, int src_y,
@@ -1305,7 +1306,6 @@ _cairo_gl_pattern_texture_setup (cairo_gl_composite_operand_t *operand,
     cairo_matrix_t m;
     cairo_gl_surface_t *surface;
     cairo_surface_attributes_t *attributes;
-    cairo_gl_context_t *ctx = (cairo_gl_context_t *) dst->base.device;
     attributes = &operand->operand.texture.attributes;
 
     status = _cairo_pattern_acquire_surface (src, &dst->base,
@@ -1386,10 +1386,10 @@ _cairo_gl_solid_operand_init (cairo_gl_composite_operand_t *operand,
 }
 
 static cairo_status_t
-_cairo_gl_gradient_operand_init(cairo_gl_composite_operand_t *operand,
+_cairo_gl_gradient_operand_init(cairo_gl_context_t *ctx,
+                                cairo_gl_composite_operand_t *operand,
 				cairo_gl_surface_t *dst)
 {
-    const cairo_gl_context_t *ctx = (cairo_gl_context_t *) dst->base.device;
     cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *)operand->pattern;
 
     /* Fast path for gradients with less than 2 color stops.
@@ -1505,7 +1505,8 @@ _cairo_gl_gradient_operand_init(cairo_gl_composite_operand_t *operand,
 }
 
 cairo_int_status_t
-_cairo_gl_operand_init (cairo_gl_composite_operand_t *operand,
+_cairo_gl_operand_init (cairo_gl_context_t *ctx,
+                       cairo_gl_composite_operand_t *operand,
 		       const cairo_pattern_t *pattern,
 		       cairo_gl_surface_t *dst,
 		       int src_x, int src_y,
@@ -1522,7 +1523,7 @@ _cairo_gl_operand_init (cairo_gl_composite_operand_t *operand,
 		                             &((cairo_solid_pattern_t *) pattern)->color);
     case CAIRO_PATTERN_TYPE_LINEAR:
     case CAIRO_PATTERN_TYPE_RADIAL:
-	status = _cairo_gl_gradient_operand_init (operand, dst);
+	status = _cairo_gl_gradient_operand_init (ctx, operand, dst);
 	if (!_cairo_status_is_error (status))
 	    return status;
 
@@ -1531,7 +1532,7 @@ _cairo_gl_operand_init (cairo_gl_composite_operand_t *operand,
     default:
     case CAIRO_PATTERN_TYPE_SURFACE:
 	operand->type = OPERAND_TEXTURE;
-	return _cairo_gl_pattern_texture_setup (operand,
+	return _cairo_gl_pattern_texture_setup (ctx, operand,
 						pattern, dst,
 						src_x, src_y,
 						dst_x, dst_y,
@@ -1972,31 +1973,31 @@ _cairo_gl_surface_composite_component_alpha (cairo_operator_t op,
 
     memset (&setup, 0, sizeof (setup));
 
-    status = _cairo_gl_operand_init (&setup.src, src, dst,
+    status = _cairo_gl_context_acquire (dst->base.device, &ctx);
+    if (unlikely (status))
+	return status;
+
+    status = _cairo_gl_operand_init (ctx, &setup.src, src, dst,
 				     src_x, src_y,
 				     dst_x, dst_y,
 				     width, height);
-    if (unlikely (status))
+    if (unlikely (status)) {
+        _cairo_gl_context_release (ctx);
 	return status;
+    }
     src_attributes = &setup.src.operand.texture.attributes;
 
-    status = _cairo_gl_operand_init (&setup.mask, mask, dst,
+    status = _cairo_gl_operand_init (ctx, &setup.mask, mask, dst,
 				     mask_x, mask_y,
 				     dst_x, dst_y,
 				     width, height);
     if (unlikely (status)) {
+        _cairo_gl_context_release (ctx);
 	_cairo_gl_operand_destroy (&setup.src);
 	return status;
     }
     mask_attributes = &setup.mask.operand.texture.attributes;
 
-    status = _cairo_gl_context_acquire (dst->base.device, &ctx);
-    if (unlikely (status)) {
-	_cairo_gl_operand_destroy (&setup.src);
-	_cairo_gl_operand_destroy (&setup.mask);
-	return status;
-    }
-
     status = _cairo_gl_get_program (ctx,
 				    setup.src.source,
 				    setup.mask.mask,
@@ -2029,7 +2030,7 @@ _cairo_gl_surface_composite_component_alpha (cairo_operator_t op,
 					 4*3*sizeof (vertices[0]));
 	    if (unlikely (vertices == NULL)) {
 		status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-		goto CONTEXT_RELEASE;
+		goto CLEANUP;
 	    }
 
 	    texcoord_src = vertices + num_rectangles * 4;
@@ -2135,13 +2136,13 @@ _cairo_gl_surface_composite_component_alpha (cairo_operator_t op,
     while ((err = glGetError ()))
 	fprintf (stderr, "GL error 0x%08x\n", (int) err);
 
-  CONTEXT_RELEASE:
-    _cairo_gl_context_release (ctx);
-
+  CLEANUP:
     _cairo_gl_operand_destroy (&setup.src);
     if (mask != NULL)
 	_cairo_gl_operand_destroy (&setup.mask);
 
+    _cairo_gl_context_release (ctx);
+
     if (vertices != vertices_stack)
 	free (vertices);
 
@@ -2199,21 +2200,28 @@ _cairo_gl_surface_composite (cairo_operator_t		  op,
 
     memset (&setup, 0, sizeof (setup));
 
-    status = _cairo_gl_operand_init (&setup.src, src, dst,
+    status = _cairo_gl_context_acquire (dst->base.device, &ctx);
+    if (unlikely (status))
+	return status;
+
+    status = _cairo_gl_operand_init (ctx, &setup.src, src, dst,
 				     src_x, src_y,
 				     dst_x, dst_y,
 				     width, height);
-    if (unlikely (status))
+    if (unlikely (status)) {
+        _cairo_gl_context_release (ctx);
 	return status;
+    }
     src_attributes = &setup.src.operand.texture.attributes;
 
     if (mask != NULL) {
-	status = _cairo_gl_operand_init (&setup.mask, mask, dst,
+	status = _cairo_gl_operand_init (ctx, &setup.mask, mask, dst,
 					 mask_x, mask_y,
 					 dst_x, dst_y,
 					 width, height);
 	if (unlikely (status)) {
 	    _cairo_gl_operand_destroy (&setup.src);
+            _cairo_gl_context_release (ctx);
 	    return status;
 	}
 	mask_attributes = &setup.mask.operand.texture.attributes;
@@ -2221,10 +2229,6 @@ _cairo_gl_surface_composite (cairo_operator_t		  op,
 	setup.mask.mask = CAIRO_GL_SHADER_MASK_NONE;
     }
 
-    status = _cairo_gl_context_acquire (dst->base.device, &ctx);
-    if (unlikely (status))
-	goto CLEANUP_SHADER;
-
     status = _cairo_gl_get_program (ctx,
 				    setup.src.source,
 				    setup.mask.mask,
@@ -2288,7 +2292,7 @@ _cairo_gl_surface_composite (cairo_operator_t		  op,
 					 4*3*sizeof (vertices[0]));
 	    if (unlikely (vertices == NULL)) {
 		status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-		goto CONTEXT_RELEASE;
+		goto CLEANUP_SHADER;
 	    }
 
 	    texcoord_src = vertices + num_rectangles * 4;
@@ -2382,14 +2386,13 @@ _cairo_gl_surface_composite (cairo_operator_t		  op,
     while ((err = glGetError ()))
 	fprintf (stderr, "GL error 0x%08x\n", (int) err);
 
-  CONTEXT_RELEASE:
-    _cairo_gl_context_release (ctx);
-
   CLEANUP_SHADER:
     _cairo_gl_operand_destroy (&setup.src);
     if (mask != NULL)
 	_cairo_gl_operand_destroy (&setup.mask);
 
+    _cairo_gl_context_release (ctx);
+
     if (vertices != vertices_stack)
 	free (vertices);
 
@@ -2963,21 +2966,22 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t	 op,
     renderer->dst = dst;
     renderer->clip = clip_region;
 
-    status = _cairo_gl_operand_init (&renderer->setup.src, src, dst,
-				     rects->source.x, rects->source.y,
-				     extents->x, extents->y,
-				     extents->width, extents->height);
+    status = _cairo_gl_context_acquire (dst->base.device, &renderer->ctx);
     if (unlikely (status)) {
 	free (renderer);
 	return _cairo_span_renderer_create_in_error (status);
     }
 
-    status = _cairo_gl_context_acquire (dst->base.device, &renderer->ctx);
+    status = _cairo_gl_operand_init (ctx, &renderer->setup.src, src, dst,
+				     rects->source.x, rects->source.y,
+				     extents->x, extents->y,
+				     extents->width, extents->height);
     if (unlikely (status)) {
-	_cairo_gl_operand_destroy (&renderer->setup.src);
+        _cairo_gl_context_release (ctx);
 	free (renderer);
 	return _cairo_span_renderer_create_in_error (status);
     }
+
     _cairo_gl_set_destination (dst);
 
     status = _cairo_gl_get_program (renderer->ctx,


More information about the cairo-commit mailing list