[cairo-commit] 23 commits - src/cairo-gl-composite.c src/cairo-gl-device.c src/cairo-gl-glyphs.c src/cairo-gl-private.h src/cairo-gl-shaders.c src/cairo-gl-surface.c src/cairoint.h src/cairo-surface.c src/cairo-surface-private.h

Benjamin Otte company at kemper.freedesktop.org
Thu May 20 02:03:04 PDT 2010


 src/cairo-gl-composite.c    |  811 ++++++++++++++++++++++----------------------
 src/cairo-gl-device.c       |    4 
 src/cairo-gl-glyphs.c       |  125 ++----
 src/cairo-gl-private.h      |   75 +---
 src/cairo-gl-shaders.c      |   47 +-
 src/cairo-gl-surface.c      |  260 +++++---------
 src/cairo-surface-private.h |    1 
 src/cairo-surface.c         |   26 +
 src/cairoint.h              |    3 
 9 files changed, 633 insertions(+), 719 deletions(-)

New commits:
commit 4c7dd1be4526c85b47f1fe1d4663e7fbec0926b1
Author: Benjamin Otte <otte at redhat.com>
Date:   Wed May 19 22:03:18 2010 +0200

    gl: Move vertex array setup code into the texture setup code

diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index 76b6da0..0df0502 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -609,14 +609,19 @@ _cairo_gl_texture_set_attributes (cairo_gl_context_t         *ctx,
 static void
 _cairo_gl_operand_setup_texture (cairo_gl_context_t *ctx,
                                  cairo_gl_operand_t *operand,
-                                 GLuint              tex_unit)
+                                 GLuint              tex_unit,
+                                 unsigned int        vertex_offset)
 {
     switch (operand->type) {
     default:
     case CAIRO_GL_OPERAND_COUNT:
         ASSERT_NOT_REACHED;
     case CAIRO_GL_OPERAND_NONE:
+        break;
     case CAIRO_GL_OPERAND_SPANS:
+	glColorPointer (4, GL_UNSIGNED_BYTE, ctx->vertex_size,
+                        (void *) (uintptr_t) vertex_offset);
+	glEnableClientState (GL_COLOR_ARRAY);
         break;
     case CAIRO_GL_OPERAND_CONSTANT:
         if (ctx->current_shader == NULL) {
@@ -633,6 +638,11 @@ _cairo_gl_operand_setup_texture (cairo_gl_context_t *ctx,
         glBindTexture (ctx->tex_target, operand->texture.tex);
         glEnable (ctx->tex_target);
         _cairo_gl_texture_set_attributes (ctx, &operand->texture.attributes);
+
+	glClientActiveTexture (GL_TEXTURE0 + tex_unit);
+	glTexCoordPointer (2, GL_FLOAT, ctx->vertex_size,
+                           (void *) (uintptr_t) vertex_offset);
+	glEnableClientState (GL_TEXTURE_COORD_ARRAY);
         break;
     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
         glActiveTexture (GL_TEXTURE0 + tex_unit);
@@ -1108,37 +1118,20 @@ _cairo_gl_composite_begin (cairo_gl_context_t *ctx,
 
     _cairo_gl_composite_bind_to_shader (ctx, setup);
 
-    _cairo_gl_operand_setup_texture (ctx, &setup->src, 0);
-    _cairo_gl_operand_setup_texture (ctx, &setup->mask, 1);
-
     glBindBufferARB (GL_ARRAY_BUFFER_ARB, ctx->vbo);
 
     glVertexPointer (2, GL_FLOAT, ctx->vertex_size, NULL);
     glEnableClientState (GL_VERTEX_ARRAY);
 
+    _cairo_gl_operand_setup_texture (ctx, &setup->src, 0, dst_size);
+    _cairo_gl_operand_setup_texture (ctx, &setup->mask, 1, dst_size + src_size);
+
     _cairo_gl_set_src_operand (ctx, setup);
-    if (setup->src.type == CAIRO_GL_OPERAND_TEXTURE) {
-	glClientActiveTexture (GL_TEXTURE0);
-	glTexCoordPointer (2, GL_FLOAT, ctx->vertex_size,
-                           (void *) (uintptr_t) dst_size);
-	glEnableClientState (GL_TEXTURE_COORD_ARRAY);
-    }
     if (setup->has_component_alpha)
         _cairo_gl_set_component_alpha_mask_operand (ctx, setup);
     else
         _cairo_gl_set_mask_operand (ctx, setup);
 
-    if (setup->mask.type == CAIRO_GL_OPERAND_TEXTURE) {
-	glClientActiveTexture (GL_TEXTURE1);
-	glTexCoordPointer (2, GL_FLOAT, ctx->vertex_size,
-                           (void *) (uintptr_t) (dst_size + src_size));
-	glEnableClientState (GL_TEXTURE_COORD_ARRAY);
-    } else if (setup->mask.type == CAIRO_GL_OPERAND_SPANS) {
-	glColorPointer (4, GL_UNSIGNED_BYTE, ctx->vertex_size,
-                        (void *) (uintptr_t) (dst_size + src_size));
-	glEnableClientState (GL_COLOR_ARRAY);
-    }
-
     if (setup->clip_region)
 	glEnable (GL_SCISSOR_TEST);
 
commit d9d5976bdf333a5a7ea7707bc3076696f3c079d2
Author: Benjamin Otte <otte at redhat.com>
Date:   Wed May 19 21:54:32 2010 +0200

    gl: Add an assertion that a context cannot call _begin() twice
    
    Evert _begin() call must be followed by an _end() call to avoid any
    nastiness. Just like GL. :)

diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index 8e3d32e..76b6da0 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -1072,6 +1072,8 @@ _cairo_gl_composite_begin (cairo_gl_context_t *ctx,
     unsigned int dst_size, src_size, mask_size;
     cairo_status_t status;
 
+    assert (! _cairo_gl_context_is_in_progress (ctx));
+
     /* Do various magic for component alpha */
     if (setup->has_component_alpha) {
         status = _cairo_gl_composite_begin_component_alpha (ctx, setup);
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index b88751d..0cdbe73 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -221,6 +221,13 @@ _cairo_gl_context_create_in_error (cairo_status_t status)
 cairo_private cairo_status_t
 _cairo_gl_context_init (cairo_gl_context_t *ctx);
 
+static cairo_always_inline cairo_bool_t cairo_warn
+_cairo_gl_context_is_in_progress (cairo_gl_context_t *ctx)
+{
+    /* This variable gets set when _begin() is called */
+    return ctx->vertex_size != 0;
+}
+
 cairo_private void
 _cairo_gl_surface_init (cairo_device_t *device,
 			cairo_gl_surface_t *surface,
commit 5b8b1fe1cb692530b40db330c3040cd85a8b6bd7
Author: Benjamin Otte <otte at redhat.com>
Date:   Wed May 19 21:10:26 2010 +0200

    gl: Move vertex buffer handling from setup into context
    
    We can only emit one vertex buffer at a time anyway.

diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index adb63bb..8e3d32e 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -1097,7 +1097,7 @@ _cairo_gl_composite_begin (cairo_gl_context_t *ctx,
     src_size  = _cairo_gl_operand_get_vertex_size (setup->src.type);
     mask_size = _cairo_gl_operand_get_vertex_size (setup->mask.type);
 
-    setup->vertex_size = dst_size + src_size + mask_size;
+    ctx->vertex_size = dst_size + src_size + mask_size;
 
     _cairo_gl_context_set_destination (ctx, setup->dst);
     _cairo_gl_set_operator (setup->dst,
@@ -1111,13 +1111,13 @@ _cairo_gl_composite_begin (cairo_gl_context_t *ctx,
 
     glBindBufferARB (GL_ARRAY_BUFFER_ARB, ctx->vbo);
 
-    glVertexPointer (2, GL_FLOAT, setup->vertex_size, NULL);
+    glVertexPointer (2, GL_FLOAT, ctx->vertex_size, NULL);
     glEnableClientState (GL_VERTEX_ARRAY);
 
     _cairo_gl_set_src_operand (ctx, setup);
     if (setup->src.type == CAIRO_GL_OPERAND_TEXTURE) {
 	glClientActiveTexture (GL_TEXTURE0);
-	glTexCoordPointer (2, GL_FLOAT, setup->vertex_size,
+	glTexCoordPointer (2, GL_FLOAT, ctx->vertex_size,
                            (void *) (uintptr_t) dst_size);
 	glEnableClientState (GL_TEXTURE_COORD_ARRAY);
     }
@@ -1128,11 +1128,11 @@ _cairo_gl_composite_begin (cairo_gl_context_t *ctx,
 
     if (setup->mask.type == CAIRO_GL_OPERAND_TEXTURE) {
 	glClientActiveTexture (GL_TEXTURE1);
-	glTexCoordPointer (2, GL_FLOAT, setup->vertex_size,
+	glTexCoordPointer (2, GL_FLOAT, ctx->vertex_size,
                            (void *) (uintptr_t) (dst_size + src_size));
 	glEnableClientState (GL_TEXTURE_COORD_ARRAY);
     } else if (setup->mask.type == CAIRO_GL_OPERAND_SPANS) {
-	glColorPointer (4, GL_UNSIGNED_BYTE, setup->vertex_size,
+	glColorPointer (4, GL_UNSIGNED_BYTE, ctx->vertex_size,
                         (void *) (uintptr_t) (dst_size + src_size));
 	glEnableClientState (GL_COLOR_ARRAY);
     }
@@ -1147,7 +1147,7 @@ static inline void
 _cairo_gl_composite_draw (cairo_gl_context_t *ctx,
                           cairo_gl_composite_t *setup)
 {
-    unsigned int count = setup->vb_offset / setup->vertex_size;
+    unsigned int count = ctx->vb_offset / ctx->vertex_size;
 
     if (! setup->pre_shader) {
         glDrawArrays (GL_TRIANGLES, 0, count);
@@ -1172,7 +1172,7 @@ void
 _cairo_gl_composite_flush (cairo_gl_context_t *ctx,
                            cairo_gl_composite_t *setup)
 {
-    if (setup->vb_offset == 0)
+    if (ctx->vb_offset == 0)
         return;
 
     if (setup->clip_region) {
@@ -1191,7 +1191,8 @@ _cairo_gl_composite_flush (cairo_gl_context_t *ctx,
     }
 
     glUnmapBufferARB (GL_ARRAY_BUFFER_ARB);
-    setup->vb = NULL;
+    ctx->vb = NULL;
+    ctx->vb_offset = 0;
 }
 
 static void
@@ -1199,14 +1200,13 @@ _cairo_gl_composite_prepare_buffer (cairo_gl_context_t *ctx,
                                     cairo_gl_composite_t *setup,
                                     unsigned int n_vertices)
 {
-    if (setup->vb_offset + n_vertices * setup->vertex_size > CAIRO_GL_VBO_SIZE)
+    if (ctx->vb_offset + n_vertices * ctx->vertex_size > CAIRO_GL_VBO_SIZE)
 	_cairo_gl_composite_flush (ctx, setup);
 
-    if (setup->vb == NULL) {
+    if (ctx->vb == NULL) {
 	glBufferDataARB (GL_ARRAY_BUFFER_ARB, CAIRO_GL_VBO_SIZE,
 			 NULL, GL_STREAM_DRAW_ARB);
-	setup->vb = glMapBufferARB (GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
-	setup->vb_offset = 0;
+	ctx->vb = glMapBufferARB (GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
     }
 }
 
@@ -1258,7 +1258,7 @@ _cairo_gl_composite_emit_vertex (cairo_gl_context_t *ctx,
                                  GLfloat y,
                                  uint32_t color)
 {
-    GLfloat *vb = (GLfloat *) (void *) &setup->vb[setup->vb_offset];
+    GLfloat *vb = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset];
 
     *vb++ = x;
     *vb++ = y;
@@ -1266,7 +1266,7 @@ _cairo_gl_composite_emit_vertex (cairo_gl_context_t *ctx,
     _cairo_gl_operand_emit (&setup->src, &vb, x, y, color);
     _cairo_gl_operand_emit (&setup->mask, &vb, x, y, color);
 
-    setup->vb_offset += setup->vertex_size;
+    ctx->vb_offset += ctx->vertex_size;
 }
 
 void
@@ -1297,7 +1297,7 @@ _cairo_gl_composite_emit_glyph_vertex (cairo_gl_context_t *ctx,
                                        GLfloat glyph_x,
                                        GLfloat glyph_y)
 {
-    GLfloat *vb = (GLfloat *) (void *) &setup->vb[setup->vb_offset];
+    GLfloat *vb = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset];
 
     *vb++ = x;
     *vb++ = y;
@@ -1307,7 +1307,7 @@ _cairo_gl_composite_emit_glyph_vertex (cairo_gl_context_t *ctx,
     *vb++ = glyph_x;
     *vb++ = glyph_y;
 
-    setup->vb_offset += setup->vertex_size;
+    ctx->vb_offset += ctx->vertex_size;
 }
 
 void
@@ -1363,6 +1363,8 @@ _cairo_gl_composite_end (cairo_gl_context_t *ctx,
     glDisable (ctx->tex_target);
 
     setup->pre_shader = NULL;
+
+    ctx->vertex_size = 0;
 }
 
 void
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 0a66813..b88751d 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -145,6 +145,10 @@ typedef struct _cairo_gl_context {
     cairo_gl_surface_t *current_target;
     cairo_gl_shader_t *current_shader;
 
+    char *vb;
+    unsigned int vb_offset;
+    unsigned int vertex_size;
+
     void (*acquire) (void *ctx);
     void (*release) (void *ctx);
 
@@ -195,10 +199,6 @@ typedef struct _cairo_gl_composite {
     cairo_gl_operand_t src;
     cairo_gl_operand_t mask;
     cairo_gl_shader_t *pre_shader; /* for component alpha */
-
-    char *vb;
-    unsigned int vb_offset;
-    unsigned int vertex_size;
 } cairo_gl_composite_t;
 
 cairo_private extern const cairo_surface_backend_t _cairo_gl_surface_backend;
commit 0d5f2eab77f055b063538dcd345a1e0db480f3bc
Author: Benjamin Otte <otte at redhat.com>
Date:   Wed May 19 20:49:49 2010 +0200

    gl: Actuall do fall back to fixed function paths.
    
    Previously we were just returning UNSUPPORTED all the time. I guess that
    explains why my code got so slow...

diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index 12c6225..adb63bb 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -1086,7 +1086,9 @@ _cairo_gl_composite_begin (cairo_gl_context_t *ctx,
                                                                       : CAIRO_GL_SHADER_IN_NORMAL);
     if (unlikely (status)) {
         setup->pre_shader = NULL;
-	return status;
+        if (_cairo_status_is_error (status))
+	    return status;
+        /* fall back to fixed function here */
     }
 
     status = CAIRO_STATUS_SUCCESS;
commit bb7ca71c1af416ca084f03089f5fe762403635dd
Author: Benjamin Otte <otte at redhat.com>
Date:   Wed May 19 20:47:31 2010 +0200

    gl: Don't store the shader in the composite_t anymore
    
    Now that we have ctx->current_shader, there's no need to keep it in the
    composite setup code.

diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index 15fa838..12c6225 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -842,7 +842,7 @@ static void
 _cairo_gl_set_mask_operand (cairo_gl_context_t *ctx,
 			    cairo_gl_composite_t *setup)
 {
-    if (setup->shader)
+    if (ctx->current_shader)
         return;
 
     switch (setup->mask.type) {
@@ -1052,15 +1052,14 @@ _cairo_gl_composite_begin_component_alpha  (cairo_gl_context_t *ctx,
      */
     if (setup->op == CAIRO_OPERATOR_OVER) {
 	setup->op = CAIRO_OPERATOR_ADD;
-	status = _cairo_gl_get_shader (ctx,
-				       setup->src.type,
-				       setup->mask.type,
-				       CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA,
-				       &setup->pre_shader);
+	status = _cairo_gl_set_shader_by_type (ctx,
+                                               setup->src.type,
+                                               setup->mask.type,
+                                               CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA);
         if (unlikely (status))
             return status;
-        _cairo_gl_set_shader (ctx, setup->pre_shader);
         _cairo_gl_composite_bind_to_shader (ctx, setup);
+        setup->pre_shader = ctx->current_shader;
     }
 
     return CAIRO_STATUS_SUCCESS;
@@ -1080,12 +1079,11 @@ _cairo_gl_composite_begin (cairo_gl_context_t *ctx,
             return status;
     }
 
-    status = _cairo_gl_get_shader (ctx,
-				   setup->src.type,
-				   setup->mask.type,
-				   setup->has_component_alpha ? CAIRO_GL_SHADER_IN_CA_SOURCE
-				   : CAIRO_GL_SHADER_IN_NORMAL,
-				   &setup->shader);
+    status = _cairo_gl_set_shader_by_type (ctx,
+                                           setup->src.type,
+                                           setup->mask.type,
+                                           setup->has_component_alpha ? CAIRO_GL_SHADER_IN_CA_SOURCE
+                                                                      : CAIRO_GL_SHADER_IN_NORMAL);
     if (unlikely (status)) {
         setup->pre_shader = NULL;
 	return status;
@@ -1104,7 +1102,6 @@ _cairo_gl_composite_begin (cairo_gl_context_t *ctx,
                             setup->op,
                             setup->has_component_alpha);
 
-    _cairo_gl_set_shader (ctx, setup->shader);
     _cairo_gl_composite_bind_to_shader (ctx, setup);
 
     _cairo_gl_operand_setup_texture (ctx, &setup->src, 0);
@@ -1153,13 +1150,15 @@ _cairo_gl_composite_draw (cairo_gl_context_t *ctx,
     if (! setup->pre_shader) {
         glDrawArrays (GL_TRIANGLES, 0, count);
     } else {
+        cairo_gl_shader_t *prev_shader = ctx->current_shader;
+
         _cairo_gl_set_shader (ctx, setup->pre_shader);
         _cairo_gl_set_operator (setup->dst, CAIRO_OPERATOR_DEST_OUT, TRUE);
         _cairo_gl_set_src_alpha_operand (ctx, setup);
         _cairo_gl_set_component_alpha_mask_operand (ctx, setup);
         glDrawArrays (GL_TRIANGLES, 0, count);
 
-        _cairo_gl_set_shader (ctx, setup->shader);
+        _cairo_gl_set_shader (ctx, prev_shader);
         _cairo_gl_set_operator (setup->dst, setup->op, TRUE);
         _cairo_gl_set_src_operand (ctx, setup);
         _cairo_gl_set_component_alpha_mask_operand (ctx, setup);
@@ -1361,7 +1360,6 @@ _cairo_gl_composite_end (cairo_gl_context_t *ctx,
     glDisable (GL_TEXTURE_1D);
     glDisable (ctx->tex_target);
 
-    setup->shader = NULL;
     setup->pre_shader = NULL;
 }
 
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 6f191c9..0a66813 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -194,7 +194,6 @@ typedef struct _cairo_gl_composite {
 
     cairo_gl_operand_t src;
     cairo_gl_operand_t mask;
-    cairo_gl_shader_t *shader;
     cairo_gl_shader_t *pre_shader; /* for component alpha */
 
     char *vb;
@@ -397,11 +396,10 @@ _cairo_gl_shader_compile (cairo_gl_context_t *ctx,
 			  const char *fragment_text);
 
 cairo_private cairo_status_t
-_cairo_gl_get_shader (cairo_gl_context_t *ctx,
-		      cairo_gl_operand_type_t source,
-		      cairo_gl_operand_type_t mask,
-		      cairo_gl_shader_in_t in,
-		      cairo_gl_shader_t **out_program);
+_cairo_gl_set_shader_by_type (cairo_gl_context_t *ctx,
+                              cairo_gl_operand_type_t source,
+                              cairo_gl_operand_type_t mask,
+                              cairo_gl_shader_in_t in);
 
 cairo_private void
 _cairo_gl_shader_bind_float (cairo_gl_context_t *ctx,
diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c
index 246598c..d2c1973 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -925,17 +925,15 @@ _cairo_gl_set_shader (cairo_gl_context_t *ctx,
 }
 
 cairo_status_t
-_cairo_gl_get_shader (cairo_gl_context_t *ctx,
-		      cairo_gl_operand_type_t source,
-		      cairo_gl_operand_type_t mask,
-		      cairo_gl_shader_in_t in,
-		      cairo_gl_shader_t **out)
+_cairo_gl_set_shader_by_type (cairo_gl_context_t *ctx,
+                              cairo_gl_operand_type_t source,
+                              cairo_gl_operand_type_t mask,
+                              cairo_gl_shader_in_t in)
 {
     cairo_shader_cache_entry_t lookup, *entry;
     char *fs_source;
     cairo_status_t status;
 
-    *out = NULL;
     if (ctx->shader_impl == NULL)
 	return CAIRO_STATUS_SUCCESS;
 
@@ -949,7 +947,7 @@ _cairo_gl_get_shader (cairo_gl_context_t *ctx,
     entry = _cairo_cache_lookup (&ctx->shaders, &lookup.base);
     if (entry) {
         assert (entry->shader.program);
-	*out = &entry->shader;
+        _cairo_gl_set_shader (ctx, &entry->shader);
 	return CAIRO_STATUS_SUCCESS;
     }
 
@@ -992,6 +990,7 @@ _cairo_gl_get_shader (cairo_gl_context_t *ctx,
     }
 
     _cairo_gl_set_shader (ctx, &entry->shader);
+
     if (source != CAIRO_GL_OPERAND_CONSTANT) {
 	_cairo_gl_shader_bind_texture (ctx, "source_sampler", 0);
     }
@@ -1001,8 +1000,5 @@ _cairo_gl_get_shader (cairo_gl_context_t *ctx,
 	_cairo_gl_shader_bind_texture (ctx, "mask_sampler", 1);
     }
 
-    _cairo_gl_set_shader (ctx, NULL);
-
-    *out = &entry->shader;
     return CAIRO_STATUS_SUCCESS;
 }
commit 6c477b4a945a8f8b866bb2f5e125d4a0328d05f4
Author: Benjamin Otte <otte at redhat.com>
Date:   Wed May 19 20:10:19 2010 +0200

    gl: Move shader checking in the TexEnv setup code
    
    As the previously generic setup code only contains non-shader code now,
    we can check in advance that no shader is in use and do all the other
    stuff without checks.

diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index dd1c026..15fa838 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -685,6 +685,9 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
     cairo_surface_attributes_t *src_attributes;
     GLfloat constant_color[4] = {0.0, 0.0, 0.0, 0.0};
 
+    if (ctx->current_shader)
+        return;
+
     src_attributes = &setup->src.texture.attributes;
 
     switch (setup->src.type) {
@@ -693,27 +696,25 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
 						  setup->src.constant.color);
 	break;
     case CAIRO_GL_OPERAND_TEXTURE:
-	if (!setup->shader) {
-	    /* Set up the constant color we use to set color to 0 if needed. */
-	    glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant_color);
-	    /* Set up the combiner to just set color to the sampled texture. */
-	    glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
-	    glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
-	    glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
-
-	    /* Force the src color to 0 if the surface should be
-	     * alpha-only.  We may have a teximage with color bits if
-	     * the implementation doesn't support GL_ALPHA FBOs.
-	     */
-	    if (setup->src.texture.surface->base.content !=
-		CAIRO_CONTENT_ALPHA)
-		glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0);
-	    else
-		glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_CONSTANT);
-	    glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE0);
-	    glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
-	    glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
-	}
+        /* Set up the constant color we use to set color to 0 if needed. */
+        glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant_color);
+        /* Set up the combiner to just set color to the sampled texture. */
+        glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+        glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
+        glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
+
+        /* Force the src color to 0 if the surface should be
+         * alpha-only.  We may have a teximage with color bits if
+         * the implementation doesn't support GL_ALPHA FBOs.
+         */
+        if (setup->src.texture.surface->base.content !=
+            CAIRO_CONTENT_ALPHA)
+            glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0);
+        else
+            glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_CONSTANT);
+        glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE0);
+        glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+        glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
 	break;
 
     default:
@@ -738,6 +739,9 @@ _cairo_gl_set_src_alpha_operand (cairo_gl_context_t *ctx,
     GLfloat constant_color[4] = {0.0, 0.0, 0.0, 0.0};
     cairo_surface_attributes_t *src_attributes;
 
+    if (ctx->current_shader)
+        return;
+
     src_attributes = &setup->src.texture.attributes;
 
     switch (setup->src.type) {
@@ -750,17 +754,15 @@ _cairo_gl_set_src_alpha_operand (cairo_gl_context_t *ctx,
 						  constant_color);
 	break;
     case CAIRO_GL_OPERAND_TEXTURE:
-	if (!setup->shader) {
-	    /* Set up the combiner to just set color to the sampled texture. */
-	    glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
-	    glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
-	    glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
-
-	    glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0);
-	    glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE0);
-	    glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_ALPHA);
-	    glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
-	}
+        /* Set up the combiner to just set color to the sampled texture. */
+        glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+        glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
+        glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
+
+        glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0);
+        glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE0);
+        glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_ALPHA);
+        glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
 	break;
     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
@@ -783,50 +785,46 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
     cairo_surface_attributes_t *mask_attributes;
     GLfloat constant_color[4] = {0.0, 0.0, 0.0, 0.0};
 
+    if (ctx->current_shader)
+        return;
+
     mask_attributes = &setup->mask.texture.attributes;
 
-    if (!setup->shader) {
-	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);
+    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);
 
-	glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PREVIOUS);
-	glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PREVIOUS);
-	glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
-	glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
-    }
+    glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PREVIOUS);
+    glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PREVIOUS);
+    glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
+    glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
 
     switch (setup->mask.type) {
     case CAIRO_GL_OPERAND_CONSTANT:
-	/* Have to have a dummy texture bound in order to use the combiner unit. */
-	if (! setup->shader) {
-	    glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,
-			setup->mask.constant.color);
-
-	    glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_CONSTANT);
-	    glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_CONSTANT);
-	    glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
-	    glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
-	}
+        glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,
+                    setup->mask.constant.color);
+
+        glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_CONSTANT);
+        glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_CONSTANT);
+        glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+        glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
 	break;
     case CAIRO_GL_OPERAND_TEXTURE:
-	if (!setup->shader) {
-	    /* Set up the constant color we use to set color to 0 if needed. */
-	    glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant_color);
-
-	    /* Force the mask color to 0 if the surface should be
-	     * alpha-only.  We may have a teximage with color bits if
-	     * the implementation doesn't support GL_ALPHA FBOs.
-	     */
-	    if (setup->mask.texture.surface == NULL ||
-                setup->mask.texture.surface->base.content != CAIRO_CONTENT_ALPHA)
-		glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE1);
-	    else
-		glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_CONSTANT);
-	    glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE1);
-	    glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
-	    glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
-	}
+        /* Set up the constant color we use to set color to 0 if needed. */
+        glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant_color);
+
+        /* Force the mask color to 0 if the surface should be
+         * alpha-only.  We may have a teximage with color bits if
+         * the implementation doesn't support GL_ALPHA FBOs.
+         */
+        if (setup->mask.texture.surface == NULL ||
+            setup->mask.texture.surface->base.content != CAIRO_CONTENT_ALPHA)
+            glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE1);
+        else
+            glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_CONSTANT);
+        glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE1);
+        glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+        glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
 	break;
 
     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
@@ -844,6 +842,9 @@ static void
 _cairo_gl_set_mask_operand (cairo_gl_context_t *ctx,
 			    cairo_gl_composite_t *setup)
 {
+    if (setup->shader)
+        return;
+
     switch (setup->mask.type) {
     case CAIRO_GL_OPERAND_CONSTANT:
         _cairo_gl_set_tex_combine_constant_color (ctx, setup, 1,
@@ -851,43 +852,39 @@ _cairo_gl_set_mask_operand (cairo_gl_context_t *ctx,
         break;
 
     case CAIRO_GL_OPERAND_TEXTURE:
-        if (! setup->shader) {
-            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);
-
-            glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
-            glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
-            glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
-            glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
-
-            /* IN: dst.argb = src.argb * mask.aaaa */
-            glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE1);
-            glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE1);
-            glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_ALPHA);
-            glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
-        }
+        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);
+
+        glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
+        glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
+        glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+        glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
+
+        /* IN: dst.argb = src.argb * mask.aaaa */
+        glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE1);
+        glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE1);
+        glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_ALPHA);
+        glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
         break;
     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
     case CAIRO_GL_OPERAND_NONE:
         break;
     case CAIRO_GL_OPERAND_SPANS:
-        if (! setup->shader) {
-            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);
-
-            glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
-            glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
-            glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
-            glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
-
-            glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR);
-            glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PRIMARY_COLOR);
-            glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_ALPHA);
-            glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
-        }
+        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);
+
+        glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
+        glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
+        glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+        glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
+
+        glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR);
+        glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PRIMARY_COLOR);
+        glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_ALPHA);
+        glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
         break;
     case CAIRO_GL_OPERAND_COUNT:
     default:
@@ -1118,20 +1115,17 @@ _cairo_gl_composite_begin (cairo_gl_context_t *ctx,
     glVertexPointer (2, GL_FLOAT, setup->vertex_size, NULL);
     glEnableClientState (GL_VERTEX_ARRAY);
 
-    if (! setup->pre_shader)
-        _cairo_gl_set_src_operand (ctx, setup);
+    _cairo_gl_set_src_operand (ctx, setup);
     if (setup->src.type == CAIRO_GL_OPERAND_TEXTURE) {
 	glClientActiveTexture (GL_TEXTURE0);
 	glTexCoordPointer (2, GL_FLOAT, setup->vertex_size,
                            (void *) (uintptr_t) dst_size);
 	glEnableClientState (GL_TEXTURE_COORD_ARRAY);
     }
-    if (! setup->pre_shader) {
-        if (setup->has_component_alpha)
-            _cairo_gl_set_component_alpha_mask_operand (ctx, setup);
-        else
-            _cairo_gl_set_mask_operand (ctx, setup);
-    }
+    if (setup->has_component_alpha)
+        _cairo_gl_set_component_alpha_mask_operand (ctx, setup);
+    else
+        _cairo_gl_set_mask_operand (ctx, setup);
 
     if (setup->mask.type == CAIRO_GL_OPERAND_TEXTURE) {
 	glClientActiveTexture (GL_TEXTURE1);
commit 73262edd8201de8ab8a01e01f83af5b5d6470f9e
Author: Benjamin Otte <otte at redhat.com>
Date:   Wed May 19 19:25:03 2010 +0200

    gl: Move texture setup code into its own file
    
    This ensures textures don't need to be (re)set when doing component
    alpha and running 2 shaders.

diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index f06a0c4..dd1c026 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -43,56 +43,6 @@
 #include "cairo-error-private.h"
 #include "cairo-gl-private.h"
 
-static void
-_cairo_gl_set_texture_surface (int tex_unit, GLuint tex,
-			       cairo_surface_attributes_t *attributes,
-			       GLint tex_target)
-{
-
-    if (tex_target == GL_TEXTURE_RECTANGLE_EXT) {
-	assert (attributes->extend != CAIRO_EXTEND_REPEAT &&
-		attributes->extend != CAIRO_EXTEND_REFLECT);
-    }
-
-    glActiveTexture (GL_TEXTURE0 + tex_unit);
-    glBindTexture (tex_target, tex);
-    switch (attributes->extend) {
-    case CAIRO_EXTEND_NONE:
-	glTexParameteri (tex_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
-	glTexParameteri (tex_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
-	break;
-    case CAIRO_EXTEND_PAD:
-	glTexParameteri (tex_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-	glTexParameteri (tex_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-	break;
-    case CAIRO_EXTEND_REPEAT:
-	glTexParameteri (tex_target, GL_TEXTURE_WRAP_S, GL_REPEAT);
-	glTexParameteri (tex_target, GL_TEXTURE_WRAP_T, GL_REPEAT);
-	break;
-    case CAIRO_EXTEND_REFLECT:
-	glTexParameteri (tex_target, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
-	glTexParameteri (tex_target, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
-	break;
-    }
-    switch (attributes->filter) {
-    case CAIRO_FILTER_FAST:
-    case CAIRO_FILTER_NEAREST:
-	glTexParameteri (tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-	glTexParameteri (tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-	break;
-    case CAIRO_FILTER_GOOD:
-    case CAIRO_FILTER_BEST:
-    case CAIRO_FILTER_BILINEAR:
-	glTexParameteri (tex_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-	glTexParameteri (tex_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-	break;
-    default:
-    case CAIRO_FILTER_GAUSSIAN:
-	ASSERT_NOT_REACHED;
-    }
-    glEnable (tex_target);
-}
-
 static int
 _cairo_gl_gradient_sample_width (const cairo_gradient_pattern_t *gradient)
 {
@@ -611,16 +561,98 @@ _cairo_gl_composite_bind_to_shader (cairo_gl_context_t   *ctx,
 }
 
 static void
+_cairo_gl_texture_set_attributes (cairo_gl_context_t         *ctx,
+                                  cairo_surface_attributes_t *attributes)
+{
+    if (ctx->tex_target == GL_TEXTURE_RECTANGLE_EXT) {
+	assert (attributes->extend != CAIRO_EXTEND_REPEAT &&
+		attributes->extend != CAIRO_EXTEND_REFLECT);
+    }
+
+    switch (attributes->extend) {
+    case CAIRO_EXTEND_NONE:
+	glTexParameteri (ctx->tex_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+	glTexParameteri (ctx->tex_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+	break;
+    case CAIRO_EXTEND_PAD:
+	glTexParameteri (ctx->tex_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+	glTexParameteri (ctx->tex_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+	break;
+    case CAIRO_EXTEND_REPEAT:
+	glTexParameteri (ctx->tex_target, GL_TEXTURE_WRAP_S, GL_REPEAT);
+	glTexParameteri (ctx->tex_target, GL_TEXTURE_WRAP_T, GL_REPEAT);
+	break;
+    case CAIRO_EXTEND_REFLECT:
+	glTexParameteri (ctx->tex_target, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
+	glTexParameteri (ctx->tex_target, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
+	break;
+    }
+
+    switch (attributes->filter) {
+    case CAIRO_FILTER_FAST:
+    case CAIRO_FILTER_NEAREST:
+	glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	break;
+    case CAIRO_FILTER_GOOD:
+    case CAIRO_FILTER_BEST:
+    case CAIRO_FILTER_BILINEAR:
+	glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+	glTexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+	break;
+    default:
+    case CAIRO_FILTER_GAUSSIAN:
+	ASSERT_NOT_REACHED;
+    }
+}
+
+static void
+_cairo_gl_operand_setup_texture (cairo_gl_context_t *ctx,
+                                 cairo_gl_operand_t *operand,
+                                 GLuint              tex_unit)
+{
+    switch (operand->type) {
+    default:
+    case CAIRO_GL_OPERAND_COUNT:
+        ASSERT_NOT_REACHED;
+    case CAIRO_GL_OPERAND_NONE:
+    case CAIRO_GL_OPERAND_SPANS:
+        break;
+    case CAIRO_GL_OPERAND_CONSTANT:
+        if (ctx->current_shader == NULL) {
+            glActiveTexture (GL_TEXTURE0 + tex_unit);
+            /* Have to have a dummy texture bound in order to use the combiner unit. */
+            glBindTexture (ctx->tex_target, ctx->dummy_tex);
+            glEnable (ctx->tex_target);
+        } else {
+            glDisable (ctx->tex_target);
+        }
+        break;
+    case CAIRO_GL_OPERAND_TEXTURE:
+        glActiveTexture (GL_TEXTURE0 + tex_unit);
+        glBindTexture (ctx->tex_target, operand->texture.tex);
+        glEnable (ctx->tex_target);
+        _cairo_gl_texture_set_attributes (ctx, &operand->texture.attributes);
+        break;
+    case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
+        glActiveTexture (GL_TEXTURE0 + tex_unit);
+        glBindTexture (GL_TEXTURE_1D, operand->linear.tex);
+        glEnable (GL_TEXTURE_1D);
+        break;
+    case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
+        glActiveTexture (GL_TEXTURE0 + tex_unit);
+        glBindTexture (GL_TEXTURE_1D, operand->radial.tex);
+        glEnable (GL_TEXTURE_1D);
+        break;
+    }
+}
+
+static void
 _cairo_gl_set_tex_combine_constant_color (cairo_gl_context_t *ctx,
 					  cairo_gl_composite_t *setup,
 					  int tex_unit,
 					  GLfloat *color)
 {
-    glActiveTexture (GL_TEXTURE0 + tex_unit);
-    /* Have to have a dummy texture bound in order to use the combiner unit. */
-    glBindTexture (ctx->tex_target, ctx->dummy_tex);
-    glEnable (ctx->tex_target);
-
     glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
     if (tex_unit == 0) {
@@ -661,8 +693,6 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
 						  setup->src.constant.color);
 	break;
     case CAIRO_GL_OPERAND_TEXTURE:
-	_cairo_gl_set_texture_surface (0, setup->src.texture.tex,
-				       src_attributes, ctx->tex_target);
 	if (!setup->shader) {
 	    /* Set up the constant color we use to set color to 0 if needed. */
 	    glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant_color);
@@ -686,22 +716,13 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
 	}
 	break;
 
-    case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
-	glActiveTexture (GL_TEXTURE0);
-	glBindTexture (GL_TEXTURE_1D, setup->src.linear.tex);
-	glEnable (GL_TEXTURE_1D);
-	break;
-
-    case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
-	glActiveTexture (GL_TEXTURE0);
-	glBindTexture (GL_TEXTURE_1D, setup->src.linear.tex);
-	glEnable (GL_TEXTURE_1D);
-	break;
     default:
     case CAIRO_GL_OPERAND_COUNT:
         ASSERT_NOT_REACHED;
     case CAIRO_GL_OPERAND_NONE:
     case CAIRO_GL_OPERAND_SPANS:
+    case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
+    case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
         break;
     }
 }
@@ -729,8 +750,6 @@ _cairo_gl_set_src_alpha_operand (cairo_gl_context_t *ctx,
 						  constant_color);
 	break;
     case CAIRO_GL_OPERAND_TEXTURE:
-	_cairo_gl_set_texture_surface (0, setup->src.texture.tex,
-				       src_attributes, ctx->tex_target);
 	if (!setup->shader) {
 	    /* Set up the combiner to just set color to the sampled texture. */
 	    glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
@@ -754,28 +773,6 @@ _cairo_gl_set_src_alpha_operand (cairo_gl_context_t *ctx,
     }
 }
 
-static void
-_cairo_gl_set_linear_gradient_mask_operand (cairo_gl_context_t *ctx,
-                                            cairo_gl_composite_t *setup)
-{
-    assert(setup->shader);
-
-    glActiveTexture (GL_TEXTURE1);
-    glBindTexture (GL_TEXTURE_1D, setup->mask.linear.tex);
-    glEnable (GL_TEXTURE_1D);
-}
-
-static void
-_cairo_gl_set_radial_gradient_mask_operand (cairo_gl_context_t *ctx,
-                                            cairo_gl_composite_t *setup)
-{
-    assert(setup->shader);
-
-    glActiveTexture (GL_TEXTURE1);
-    glBindTexture (GL_TEXTURE_1D, setup->mask.radial.tex);
-    glEnable (GL_TEXTURE_1D);
-}
-
 /* This is like _cairo_gl_set_src_alpha_operand, for component alpha setup
  * of the mask part of IN to produce a "source alpha" value.
  */
@@ -803,10 +800,6 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
     case CAIRO_GL_OPERAND_CONSTANT:
 	/* Have to have a dummy texture bound in order to use the combiner unit. */
 	if (! setup->shader) {
-	    glBindTexture (ctx->tex_target, ctx->dummy_tex);
-	    glActiveTexture (GL_TEXTURE1);
-	    glEnable (ctx->tex_target);
-
 	    glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,
 			setup->mask.constant.color);
 
@@ -817,8 +810,6 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
 	}
 	break;
     case CAIRO_GL_OPERAND_TEXTURE:
-	_cairo_gl_set_texture_surface (1, setup->mask.texture.tex,
-				       mask_attributes, ctx->tex_target);
 	if (!setup->shader) {
 	    /* Set up the constant color we use to set color to 0 if needed. */
 	    glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant_color);
@@ -839,12 +830,7 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
 	break;
 
     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
-	_cairo_gl_set_linear_gradient_mask_operand (ctx, setup);
-	break;
-
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
-	_cairo_gl_set_radial_gradient_mask_operand (ctx, setup);
-	break;
     case CAIRO_GL_OPERAND_NONE:
     case CAIRO_GL_OPERAND_SPANS:
     case CAIRO_GL_OPERAND_COUNT:
@@ -865,10 +851,6 @@ _cairo_gl_set_mask_operand (cairo_gl_context_t *ctx,
         break;
 
     case CAIRO_GL_OPERAND_TEXTURE:
-        _cairo_gl_set_texture_surface (1, setup->mask.texture.tex,
-                                       &setup->mask.texture.attributes,
-                                       ctx->tex_target);
-
         if (! setup->shader) {
             glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
             glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
@@ -887,20 +869,11 @@ _cairo_gl_set_mask_operand (cairo_gl_context_t *ctx,
         }
         break;
     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
-        _cairo_gl_set_linear_gradient_mask_operand (ctx, setup);
-        break;
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
-        _cairo_gl_set_radial_gradient_mask_operand (ctx, setup);
-        break;
     case CAIRO_GL_OPERAND_NONE:
         break;
     case CAIRO_GL_OPERAND_SPANS:
         if (! setup->shader) {
-            /* 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, ctx->dummy_tex);
-            glEnable (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);
@@ -1137,6 +1110,9 @@ _cairo_gl_composite_begin (cairo_gl_context_t *ctx,
     _cairo_gl_set_shader (ctx, setup->shader);
     _cairo_gl_composite_bind_to_shader (ctx, setup);
 
+    _cairo_gl_operand_setup_texture (ctx, &setup->src, 0);
+    _cairo_gl_operand_setup_texture (ctx, &setup->mask, 1);
+
     glBindBufferARB (GL_ARRAY_BUFFER_ARB, ctx->vbo);
 
     glVertexPointer (2, GL_FLOAT, setup->vertex_size, NULL);
commit 970c879dd897019f90b0c8ff5a18781be4935c55
Author: Benjamin Otte <otte at redhat.com>
Date:   Wed May 19 18:34:00 2010 +0200

    gl: Binding variables only works for the current shader
    
    So make the code reflect that.

diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index 76ae6cd..f06a0c4 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -540,7 +540,6 @@ _cairo_gl_composite_set_clip_region (cairo_gl_context_t *ctx,
 
 static void
 _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
-                                  cairo_gl_shader_t  *shader,
                                   cairo_gl_operand_t *operand,
                                   const char         *name)
 {
@@ -561,7 +560,6 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
     case CAIRO_GL_OPERAND_CONSTANT:
         strcpy (custom_part, "_constant");
 	_cairo_gl_shader_bind_vec4 (ctx,
-				    shader,
                                     uniform_name,
                                     operand->constant.color[0],
                                     operand->constant.color[1],
@@ -570,31 +568,31 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
         break;
     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
         strcpy (custom_part, "_matrix");
-	_cairo_gl_shader_bind_matrix (ctx, shader,
+	_cairo_gl_shader_bind_matrix (ctx,
                                       uniform_name,
 				      &operand->linear.m);
         strcpy (custom_part, "_segment");
-	_cairo_gl_shader_bind_vec2   (ctx, shader,
+	_cairo_gl_shader_bind_vec2   (ctx,
                                       uniform_name,
 				      operand->linear.segment_x,
 				      operand->linear.segment_y);
         break;
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
         strcpy (custom_part, "_matrix");
-        _cairo_gl_shader_bind_matrix (ctx, shader,
+        _cairo_gl_shader_bind_matrix (ctx,
                                       uniform_name,
                                       &operand->radial.m);
         strcpy (custom_part, "_circle_1");
-        _cairo_gl_shader_bind_vec2   (ctx, shader,
+        _cairo_gl_shader_bind_vec2   (ctx,
                                       uniform_name,
                                       operand->radial.circle_1_x,
                                       operand->radial.circle_1_y);
         strcpy (custom_part, "_radius_0");
-        _cairo_gl_shader_bind_float  (ctx, shader,
+        _cairo_gl_shader_bind_float  (ctx,
                                       uniform_name,
                                       operand->radial.radius_0);
         strcpy (custom_part, "_radius_1");
-        _cairo_gl_shader_bind_float  (ctx, shader,
+        _cairo_gl_shader_bind_float  (ctx,
                                       uniform_name,
                                       operand->radial.radius_1);
         break;
@@ -603,14 +601,13 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
 
 static void
 _cairo_gl_composite_bind_to_shader (cairo_gl_context_t   *ctx,
-				    cairo_gl_composite_t *setup,
-                                    cairo_gl_shader_t    *shader)
+				    cairo_gl_composite_t *setup)
 {
-    if (shader == NULL)
+    if (ctx->current_shader == NULL)
         return;
 
-    _cairo_gl_operand_bind_to_shader (ctx, shader, &setup->src, "source");
-    _cairo_gl_operand_bind_to_shader (ctx, shader, &setup->mask, "mask");
+    _cairo_gl_operand_bind_to_shader (ctx, &setup->src, "source");
+    _cairo_gl_operand_bind_to_shader (ctx, &setup->mask, "mask");
 }
 
 static void
@@ -1093,7 +1090,7 @@ _cairo_gl_composite_begin_component_alpha  (cairo_gl_context_t *ctx,
         if (unlikely (status))
             return status;
         _cairo_gl_set_shader (ctx, setup->pre_shader);
-        _cairo_gl_composite_bind_to_shader (ctx, setup, setup->pre_shader);
+        _cairo_gl_composite_bind_to_shader (ctx, setup);
     }
 
     return CAIRO_STATUS_SUCCESS;
@@ -1138,7 +1135,7 @@ _cairo_gl_composite_begin (cairo_gl_context_t *ctx,
                             setup->has_component_alpha);
 
     _cairo_gl_set_shader (ctx, setup->shader);
-    _cairo_gl_composite_bind_to_shader (ctx, setup, setup->shader);
+    _cairo_gl_composite_bind_to_shader (ctx, setup);
 
     glBindBufferARB (GL_ARRAY_BUFFER_ARB, ctx->vbo);
 
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 19c34c3..6f191c9 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -405,19 +405,16 @@ _cairo_gl_get_shader (cairo_gl_context_t *ctx,
 
 cairo_private void
 _cairo_gl_shader_bind_float (cairo_gl_context_t *ctx,
-			     cairo_gl_shader_t *shader,
 			     const char *name,
 			     float value);
 
 cairo_private void
 _cairo_gl_shader_bind_vec2 (cairo_gl_context_t *ctx,
-			    cairo_gl_shader_t *shader,
 			    const char *name,
 			    float value0, float value1);
 
 cairo_private void
 _cairo_gl_shader_bind_vec3 (cairo_gl_context_t *ctx,
-			    cairo_gl_shader_t *shader,
 			    const char *name,
 			    float value0,
 			    float value1,
@@ -425,20 +422,17 @@ _cairo_gl_shader_bind_vec3 (cairo_gl_context_t *ctx,
 
 cairo_private void
 _cairo_gl_shader_bind_vec4 (cairo_gl_context_t *ctx,
-			    cairo_gl_shader_t *shader,
 			    const char *name,
 			    float value0, float value1,
 			    float value2, float value3);
 
 cairo_private void
 _cairo_gl_shader_bind_matrix (cairo_gl_context_t *ctx,
-			      cairo_gl_shader_t *shader,
 			      const char *name,
 			      cairo_matrix_t* m);
 
 cairo_private void
 _cairo_gl_shader_bind_texture (cairo_gl_context_t *ctx,
-			       cairo_gl_shader_t *shader,
 			       const char *name,
 			       GLuint tex_unit);
 
diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c
index ccd9780..246598c 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -861,58 +861,52 @@ _cairo_gl_shader_compile (cairo_gl_context_t *ctx,
 
 void
 _cairo_gl_shader_bind_float (cairo_gl_context_t *ctx,
-			     cairo_gl_shader_t *shader,
 			     const char *name,
 			     float value)
 {
-    ctx->shader_impl->bind_float (shader, name, value);
+    ctx->shader_impl->bind_float (ctx->current_shader, name, value);
 }
 
 void
 _cairo_gl_shader_bind_vec2 (cairo_gl_context_t *ctx,
-			    cairo_gl_shader_t *shader,
 			    const char *name,
 			    float value0,
 			    float value1)
 {
-    ctx->shader_impl->bind_vec2 (shader, name, value0, value1);
+    ctx->shader_impl->bind_vec2 (ctx->current_shader, name, value0, value1);
 }
 
 void
 _cairo_gl_shader_bind_vec3 (cairo_gl_context_t *ctx,
-			    cairo_gl_shader_t *shader,
 			    const char *name,
 			    float value0,
 			    float value1,
 			    float value2)
 {
-    ctx->shader_impl->bind_vec3 (shader, name, value0, value1, value2);
+    ctx->shader_impl->bind_vec3 (ctx->current_shader, name, value0, value1, value2);
 }
 
 void
 _cairo_gl_shader_bind_vec4 (cairo_gl_context_t *ctx,
-			    cairo_gl_shader_t *shader,
 			    const char *name,
 			    float value0, float value1,
 			    float value2, float value3)
 {
-    ctx->shader_impl->bind_vec4 (shader, name, value0, value1, value2, value3);
+    ctx->shader_impl->bind_vec4 (ctx->current_shader, name, value0, value1, value2, value3);
 }
 
 void
 _cairo_gl_shader_bind_matrix (cairo_gl_context_t *ctx,
-			      cairo_gl_shader_t *shader,
 			      const char *name, cairo_matrix_t* m)
 {
-    ctx->shader_impl->bind_matrix (shader, name, m);
+    ctx->shader_impl->bind_matrix (ctx->current_shader, name, m);
 }
 
 void
 _cairo_gl_shader_bind_texture (cairo_gl_context_t *ctx,
-			       cairo_gl_shader_t *shader,
 			       const char *name, GLuint tex_unit)
 {
-    ctx->shader_impl->bind_texture (shader, name, tex_unit);
+    ctx->shader_impl->bind_texture (ctx->current_shader, name, tex_unit);
 }
 
 void
@@ -999,12 +993,12 @@ _cairo_gl_get_shader (cairo_gl_context_t *ctx,
 
     _cairo_gl_set_shader (ctx, &entry->shader);
     if (source != CAIRO_GL_OPERAND_CONSTANT) {
-	_cairo_gl_shader_bind_texture (ctx, &entry->shader, "source_sampler", 0);
+	_cairo_gl_shader_bind_texture (ctx, "source_sampler", 0);
     }
     if (mask != CAIRO_GL_OPERAND_CONSTANT &&
 	mask != CAIRO_GL_OPERAND_SPANS &&
 	mask != CAIRO_GL_OPERAND_NONE) {
-	_cairo_gl_shader_bind_texture (ctx, &entry->shader, "mask_sampler", 1);
+	_cairo_gl_shader_bind_texture (ctx, "mask_sampler", 1);
     }
 
     _cairo_gl_set_shader (ctx, NULL);
commit 065969d78f23c634ebcb2b931cbb1fe184f2cedf
Author: Benjamin Otte <otte at redhat.com>
Date:   Wed May 19 18:21:06 2010 +0200

    gl: Separate binding to shaders from setting operands
    
    That way we only need to bind to shaders when creating them, but not
    everytime we switch shaders on text output.

diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index 61bac27..76ae6cd 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -539,31 +539,86 @@ _cairo_gl_composite_set_clip_region (cairo_gl_context_t *ctx,
 }
 
 static void
-_cairo_gl_set_tex_combine_constant_color (cairo_gl_context_t *ctx,
-					  cairo_gl_composite_t *setup,
-					  int tex_unit,
-					  GLfloat *color)
+_cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
+                                  cairo_gl_shader_t  *shader,
+                                  cairo_gl_operand_t *operand,
+                                  const char         *name)
 {
-    if (setup->shader) {
-	const char *uniform_name;
+    char uniform_name[50];
+    char *custom_part;
 
-	if (tex_unit == 0)
-	    uniform_name = "source_constant";
-	else
-	    uniform_name = "mask_constant";
+    strcpy (uniform_name, name);
+    custom_part = uniform_name + strlen (name);
 
+    switch (operand->type) {
+    default:
+    case CAIRO_GL_OPERAND_COUNT:
+        ASSERT_NOT_REACHED;
+    case CAIRO_GL_OPERAND_NONE:
+    case CAIRO_GL_OPERAND_SPANS:
+    case CAIRO_GL_OPERAND_TEXTURE:
+        break;
+    case CAIRO_GL_OPERAND_CONSTANT:
+        strcpy (custom_part, "_constant");
 	_cairo_gl_shader_bind_vec4 (ctx,
-				    setup->shader,
-				    uniform_name,
-				    color[0],
-				    color[1],
-				    color[2],
-				    color[3]);
-
-	return;
+				    shader,
+                                    uniform_name,
+                                    operand->constant.color[0],
+                                    operand->constant.color[1],
+                                    operand->constant.color[2],
+                                    operand->constant.color[3]);
+        break;
+    case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
+        strcpy (custom_part, "_matrix");
+	_cairo_gl_shader_bind_matrix (ctx, shader,
+                                      uniform_name,
+				      &operand->linear.m);
+        strcpy (custom_part, "_segment");
+	_cairo_gl_shader_bind_vec2   (ctx, shader,
+                                      uniform_name,
+				      operand->linear.segment_x,
+				      operand->linear.segment_y);
+        break;
+    case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
+        strcpy (custom_part, "_matrix");
+        _cairo_gl_shader_bind_matrix (ctx, shader,
+                                      uniform_name,
+                                      &operand->radial.m);
+        strcpy (custom_part, "_circle_1");
+        _cairo_gl_shader_bind_vec2   (ctx, shader,
+                                      uniform_name,
+                                      operand->radial.circle_1_x,
+                                      operand->radial.circle_1_y);
+        strcpy (custom_part, "_radius_0");
+        _cairo_gl_shader_bind_float  (ctx, shader,
+                                      uniform_name,
+                                      operand->radial.radius_0);
+        strcpy (custom_part, "_radius_1");
+        _cairo_gl_shader_bind_float  (ctx, shader,
+                                      uniform_name,
+                                      operand->radial.radius_1);
+        break;
     }
+}
+
+static void
+_cairo_gl_composite_bind_to_shader (cairo_gl_context_t   *ctx,
+				    cairo_gl_composite_t *setup,
+                                    cairo_gl_shader_t    *shader)
+{
+    if (shader == NULL)
+        return;
+
+    _cairo_gl_operand_bind_to_shader (ctx, shader, &setup->src, "source");
+    _cairo_gl_operand_bind_to_shader (ctx, shader, &setup->mask, "mask");
+}
 
-    /* Fall back to fixed function */
+static void
+_cairo_gl_set_tex_combine_constant_color (cairo_gl_context_t *ctx,
+					  cairo_gl_composite_t *setup,
+					  int tex_unit,
+					  GLfloat *color)
+{
     glActiveTexture (GL_TEXTURE0 + tex_unit);
     /* Have to have a dummy texture bound in order to use the combiner unit. */
     glBindTexture (ctx->tex_target, ctx->dummy_tex);
@@ -638,38 +693,12 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
 	glActiveTexture (GL_TEXTURE0);
 	glBindTexture (GL_TEXTURE_1D, setup->src.linear.tex);
 	glEnable (GL_TEXTURE_1D);
-
-	_cairo_gl_shader_bind_matrix (ctx, setup->shader,
-				      "source_matrix",
-				      &setup->src.linear.m);
-
-	_cairo_gl_shader_bind_vec2 (ctx, setup->shader,
-				    "source_segment",
-				    setup->src.linear.segment_x,
-				    setup->src.linear.segment_y);
 	break;
 
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
 	glActiveTexture (GL_TEXTURE0);
 	glBindTexture (GL_TEXTURE_1D, setup->src.linear.tex);
 	glEnable (GL_TEXTURE_1D);
-
-        _cairo_gl_shader_bind_matrix (ctx, setup->shader,
-				      "source_matrix",
-				      &setup->src.radial.m);
-
-	_cairo_gl_shader_bind_vec2 (ctx, setup->shader,
-				    "source_circle_1",
-				    setup->src.radial.circle_1_x,
-				    setup->src.radial.circle_1_y);
-
-        _cairo_gl_shader_bind_float (ctx, setup->shader,
-				     "source_radius_0",
-				     setup->src.radial.radius_0);
-
-        _cairo_gl_shader_bind_float (ctx, setup->shader,
-				     "source_radius_1",
-				     setup->src.radial.radius_1);
 	break;
     default:
     case CAIRO_GL_OPERAND_COUNT:
@@ -737,14 +766,6 @@ _cairo_gl_set_linear_gradient_mask_operand (cairo_gl_context_t *ctx,
     glActiveTexture (GL_TEXTURE1);
     glBindTexture (GL_TEXTURE_1D, setup->mask.linear.tex);
     glEnable (GL_TEXTURE_1D);
-
-    _cairo_gl_shader_bind_matrix (ctx, setup->shader,
-				  "mask_matrix", &setup->mask.linear.m);
-
-    _cairo_gl_shader_bind_vec2 (ctx, setup->shader,
-				"mask_segment",
-				setup->mask.linear.segment_x,
-				setup->mask.linear.segment_y);
 }
 
 static void
@@ -756,23 +777,6 @@ _cairo_gl_set_radial_gradient_mask_operand (cairo_gl_context_t *ctx,
     glActiveTexture (GL_TEXTURE1);
     glBindTexture (GL_TEXTURE_1D, setup->mask.radial.tex);
     glEnable (GL_TEXTURE_1D);
-
-    _cairo_gl_shader_bind_matrix (ctx, setup->shader,
-				  "mask_matrix",
-				  &setup->mask.radial.m);
-
-    _cairo_gl_shader_bind_vec2 (ctx, setup->shader,
-				"mask_circle_1",
-				setup->mask.radial.circle_1_x,
-				setup->mask.radial.circle_1_y);
-
-    _cairo_gl_shader_bind_float (ctx, setup->shader,
-				 "mask_radius_0",
-				 setup->mask.radial.radius_0);
-
-    _cairo_gl_shader_bind_float (ctx, setup->shader,
-				 "mask_radius_1",
-				 setup->mask.radial.radius_1);
 }
 
 /* This is like _cairo_gl_set_src_alpha_operand, for component alpha setup
@@ -801,14 +805,7 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
     switch (setup->mask.type) {
     case CAIRO_GL_OPERAND_CONSTANT:
 	/* Have to have a dummy texture bound in order to use the combiner unit. */
-	if (setup->shader) {
-	    _cairo_gl_shader_bind_vec4 (ctx, setup->shader,
-					"mask_constant",
-					setup->mask.constant.color[0],
-					setup->mask.constant.color[1],
-					setup->mask.constant.color[2],
-					setup->mask.constant.color[3]);
-	} else {
+	if (! setup->shader) {
 	    glBindTexture (ctx->tex_target, ctx->dummy_tex);
 	    glActiveTexture (GL_TEXTURE1);
 	    glEnable (ctx->tex_target);
@@ -1095,6 +1092,8 @@ _cairo_gl_composite_begin_component_alpha  (cairo_gl_context_t *ctx,
 				       &setup->pre_shader);
         if (unlikely (status))
             return status;
+        _cairo_gl_set_shader (ctx, setup->pre_shader);
+        _cairo_gl_composite_bind_to_shader (ctx, setup, setup->pre_shader);
     }
 
     return CAIRO_STATUS_SUCCESS;
@@ -1139,6 +1138,7 @@ _cairo_gl_composite_begin (cairo_gl_context_t *ctx,
                             setup->has_component_alpha);
 
     _cairo_gl_set_shader (ctx, setup->shader);
+    _cairo_gl_composite_bind_to_shader (ctx, setup, setup->shader);
 
     glBindBufferARB (GL_ARRAY_BUFFER_ARB, ctx->vbo);
 
diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c
index 3484321..ccd9780 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -550,7 +550,7 @@ _cairo_gl_shader_fini (cairo_gl_context_t *ctx,
         ctx->shader_impl->destroy_program (shader->program);
 }
 
-typedef enum cairo_gl_operand_target {
+typedef enum cairo_gl_operand_name {
   CAIRO_GL_OPERAND_SOURCE,
   CAIRO_GL_OPERAND_MASK,
   CAIRO_GL_OPERAND_DEST
commit c53f7778bcf274f64f801ef9ee1641a088842f60
Author: Benjamin Otte <otte at redhat.com>
Date:   Wed May 19 16:50:57 2010 +0200

    gl: Use the mask, not the source
    
    Not that we'd ever have constant color component-alpha masks, but that's
    an entirely different topic.

diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index c3d65f4..61bac27 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -804,10 +804,10 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
 	if (setup->shader) {
 	    _cairo_gl_shader_bind_vec4 (ctx, setup->shader,
 					"mask_constant",
-					setup->src.constant.color[0],
-					setup->src.constant.color[1],
-					setup->src.constant.color[2],
-					setup->src.constant.color[3]);
+					setup->mask.constant.color[0],
+					setup->mask.constant.color[1],
+					setup->mask.constant.color[2],
+					setup->mask.constant.color[3]);
 	} else {
 	    glBindTexture (ctx->tex_target, ctx->dummy_tex);
 	    glActiveTexture (GL_TEXTURE1);
commit 26e8e506b66022910c262da0618ef5be8c5a080e
Author: Benjamin Otte <otte at redhat.com>
Date:   Wed May 19 13:19:56 2010 +0200

    gl: Add _cairo_gl_surface_is_texture()
    
    It's more explicit then just checking surface->fb != 0
    Also, it makes improving that check easier.

diff --git a/src/cairo-gl-device.c b/src/cairo-gl-device.c
index e31fc05..be4298f 100644
--- a/src/cairo-gl-device.c
+++ b/src/cairo-gl-device.c
@@ -190,7 +190,7 @@ _cairo_gl_context_set_destination (cairo_gl_context_t *ctx,
     if (ctx->current_target != surface) {
 	ctx->current_target = surface;
 
-	if (surface->fb) {
+	if (_cairo_gl_surface_is_texture (surface)) {
 	    glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, surface->fb);
 	    glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);
 	    glReadBuffer (GL_COLOR_ATTACHMENT0_EXT);
@@ -206,7 +206,7 @@ _cairo_gl_context_set_destination (cairo_gl_context_t *ctx,
 
     glMatrixMode (GL_PROJECTION);
     glLoadIdentity ();
-    if (surface->fb)
+    if (_cairo_gl_surface_is_texture (surface))
 	glOrtho (0, surface->width, 0, surface->height, -1.0, 1.0);
     else
 	glOrtho (0, surface->width, surface->height, 0, -1.0, 1.0);
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 825dd93..19c34c3 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -228,6 +228,12 @@ _cairo_gl_surface_init (cairo_device_t *device,
 			cairo_content_t content,
 			int width, int height);
 
+static cairo_always_inline cairo_bool_t cairo_warn
+_cairo_gl_surface_is_texture (cairo_gl_surface_t *surface)
+{
+    return surface->fb != 0;
+}
+
 cairo_private cairo_status_t
 _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
 			      cairo_image_surface_t *src,
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index ecd30a4..992a40b 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -400,7 +400,8 @@ cairo_gl_surface_set_size (cairo_surface_t *abstract_surface,
     if (unlikely (abstract_surface->status))
 	return;
 
-    if (! _cairo_surface_is_gl (abstract_surface) || surface->fb) {
+    if (! _cairo_surface_is_gl (abstract_surface) ||
+        ! _cairo_gl_surface_is_texture (surface)) {
 	status = _cairo_surface_set_error (abstract_surface,
 		                           CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
 	return;
@@ -447,7 +448,7 @@ cairo_gl_surface_swapbuffers (cairo_surface_t *abstract_surface)
 	return;
     }
 
-    if (! surface->fb) {
+    if (! _cairo_gl_surface_is_texture (surface)) {
 	cairo_gl_context_t *ctx;
         
         if (_cairo_gl_context_acquire (surface->base.device, &ctx))
@@ -536,7 +537,7 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
 
     glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
     glPixelStorei (GL_UNPACK_ROW_LENGTH, src->stride / cpp);
-    if (dst->fb) {
+    if (_cairo_gl_surface_is_texture (dst)) {
 	glBindTexture (ctx->tex_target, dst->tex);
 	glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 	glTexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -666,12 +667,12 @@ _cairo_gl_surface_get_image (cairo_gl_surface_t      *surface,
 
     glPixelStorei (GL_PACK_ALIGNMENT, 1);
     glPixelStorei (GL_PACK_ROW_LENGTH, image->stride / cpp);
-    if (surface->fb == 0 && GLEW_MESA_pack_invert)
+    if (! _cairo_gl_surface_is_texture (surface) && GLEW_MESA_pack_invert)
 	glPixelStorei (GL_PACK_INVERT_MESA, 1);
     glReadPixels (interest->x, interest->y,
 		  interest->width, interest->height,
 		  format, type, image->data);
-    if (surface->fb == 0 && GLEW_MESA_pack_invert)
+    if (! _cairo_gl_surface_is_texture (surface) && GLEW_MESA_pack_invert)
 	glPixelStorei (GL_PACK_INVERT_MESA, 0);
 
     _cairo_gl_context_release (ctx);
commit e4cb46b50015f792b0e8c7b49f3b42f2c3c0ad00
Author: Benjamin Otte <otte at redhat.com>
Date:   Wed May 19 12:10:10 2010 +0200

    gl: Implement texture upload to window with composite()
    
    Instead of custom code that does basically the same thing, use
    a temporary surface and _cairo_gl_surface_composite() to upload images.

diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c
index 55c9eb8..3484321 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -470,7 +470,7 @@ _cairo_gl_shader_cache_destroy (void *data)
     cairo_shader_cache_entry_t *entry = data;
 
     _cairo_gl_shader_fini (entry->ctx, &entry->shader);
-    if (entry->ctx->current_shader == entry)
+    if (entry->ctx->current_shader == &entry->shader)
         entry->ctx->current_shader = NULL;
     free (entry);
 }
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 5c370b7..ecd30a4 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -45,12 +45,27 @@
 #include "cairo-gl-private.h"
 
 static cairo_int_status_t
-_cairo_gl_surface_fill_rectangles (void			   *abstract_surface,
+_cairo_gl_surface_fill_rectangles (void			   *abstract_dst,
 				   cairo_operator_t	    op,
 				   const cairo_color_t     *color,
 				   cairo_rectangle_int_t   *rects,
 				   int			    num_rects);
 
+static cairo_int_status_t
+_cairo_gl_surface_composite (cairo_operator_t		  op,
+			     const cairo_pattern_t	 *src,
+			     const cairo_pattern_t	 *mask,
+			     void			 *abstract_dst,
+			     int			  src_x,
+			     int			  src_y,
+			     int			  mask_x,
+			     int			  mask_y,
+			     int			  dst_x,
+			     int			  dst_y,
+			     unsigned int		  width,
+			     unsigned int		  height,
+			     cairo_region_t		 *clip_region);
+
 #define BIAS .375
 
 static cairo_bool_t _cairo_surface_is_gl (cairo_surface_t *surface)
@@ -556,90 +571,40 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
 	    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
 	}
     } else {
-	GLuint tex;
-	GLfloat vertices[8], texcoords[8];
-
-	if (_cairo_gl_device_has_glsl (&ctx->base)) {
-	    cairo_gl_shader_t *shader;
-
-	    status = _cairo_gl_get_shader (ctx,
-					   CAIRO_GL_OPERAND_TEXTURE,
-					   CAIRO_GL_OPERAND_NONE,
-					   CAIRO_GL_SHADER_IN_NORMAL,
-					   &shader);
-	    if (unlikely (status)) {
-		_cairo_gl_context_release (ctx);
-		goto fail;
-	    }
-
-	    _cairo_gl_set_shader (ctx, shader);
-	} else {
-	    glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-	}
-
-	status = CAIRO_STATUS_SUCCESS;
-
-	_cairo_gl_context_set_destination (ctx, dst);
-
-	glGenTextures (1, &tex);
-	glActiveTexture (GL_TEXTURE0);
-	glBindTexture (ctx->tex_target, tex);
-	glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-	glTexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-	glTexImage2D (ctx->tex_target, 0, internal_format, width, height, 0,
-		      format, type, src->data + src_y * src->stride + src_x * cpp);
-
-	glEnable (ctx->tex_target);
-	glDisable (GL_BLEND);
-
-	vertices[0] = dst_x;
-	vertices[1] = dst_y;
-	vertices[2] = dst_x + width;
-	vertices[3] = dst_y;
-	vertices[4] = dst_x + width;
-	vertices[5] = dst_y + height;
-	vertices[6] = dst_x;
-	vertices[7] = dst_y + height;
-
-	if (ctx->tex_target != GL_TEXTURE_RECTANGLE_EXT) {
-	    texcoords[0] = 0;
-	    texcoords[1] = 0;
-	    texcoords[2] = 1;
-	    texcoords[3] = 0;
-	    texcoords[4] = 1;
-	    texcoords[5] = 1;
-	    texcoords[6] = 0;
-	    texcoords[7] = 1;
-	} else {
-	    texcoords[0] = 0;
-	    texcoords[1] = 0;
-	    texcoords[2] = width;
-	    texcoords[3] = 0;
-	    texcoords[4] = width;
-	    texcoords[5] = height;
-	    texcoords[6] = 0;
-	    texcoords[7] = height;
-	}
-
-        glVertexPointer (2, GL_FLOAT, sizeof (GLfloat) * 2, vertices);
-	glEnableClientState (GL_VERTEX_ARRAY);
-
-	glClientActiveTexture (GL_TEXTURE0);
-	glTexCoordPointer (2, GL_FLOAT, sizeof (GLfloat) * 2, texcoords);
-	glEnableClientState (GL_TEXTURE_COORD_ARRAY);
-
-	glDrawArrays (GL_QUADS, 0, 4);
-
-	glDisableClientState (GL_COLOR_ARRAY);
-	glDisableClientState (GL_VERTEX_ARRAY);
-	glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+        cairo_surface_t *tmp;
+        
+        tmp = _cairo_gl_surface_create_scratch (ctx,
+                                                dst->base.content,
+                                                width, height);
+        if (unlikely (tmp->status)) {
+            cairo_surface_destroy (tmp);
+            goto FAIL;
+        }
+        status = _cairo_gl_surface_draw_image ((cairo_gl_surface_t *) tmp,
+                                               src,
+                                               src_x, src_y,
+                                               0, 0,
+                                               width, height);
+        if (status == CAIRO_STATUS_SUCCESS) {
+            cairo_surface_pattern_t tmp_pattern;
+
+            _cairo_pattern_init_for_surface (&tmp_pattern, tmp);
+            _cairo_gl_surface_composite (CAIRO_OPERATOR_SOURCE,
+                                         &tmp_pattern.base,
+                                         NULL,
+                                         dst,
+                                         0, 0,
+                                         0, 0,
+                                         dst_x, dst_y,
+                                         width, height,
+                                         NULL);
+            _cairo_pattern_fini (&tmp_pattern.base);
+        }
 
-	_cairo_gl_set_shader (ctx, NULL);
-	glDeleteTextures (1, &tex);
-	glDisable (ctx->tex_target);
+        cairo_surface_destroy (tmp);
     }
 
-fail:
+FAIL:
     glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
 
     _cairo_gl_context_release (ctx);
commit 7c8759e279f51ea722c07e4b0c70f4a49f34393d
Author: Benjamin Otte <otte at redhat.com>
Date:   Wed May 19 11:46:12 2010 +0200

    gl: cache the current shader in the context

diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index b349f57..825dd93 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -139,10 +139,12 @@ typedef struct _cairo_gl_context {
     cairo_gl_shader_t fill_rectangles_shader;
     cairo_cache_t shaders;
 
-    cairo_gl_surface_t *current_target;
     cairo_gl_glyph_cache_t glyph_cache[2];
     cairo_list_t fonts;
 
+    cairo_gl_surface_t *current_target;
+    cairo_gl_shader_t *current_shader;
+
     void (*acquire) (void *ctx);
     void (*release) (void *ctx);
 
diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c
index b364c71..55c9eb8 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -470,6 +470,8 @@ _cairo_gl_shader_cache_destroy (void *data)
     cairo_shader_cache_entry_t *entry = data;
 
     _cairo_gl_shader_fini (entry->ctx, &entry->shader);
+    if (entry->ctx->current_shader == entry)
+        entry->ctx->current_shader = NULL;
     free (entry);
 }
 
@@ -920,7 +922,12 @@ _cairo_gl_set_shader (cairo_gl_context_t *ctx,
     if (ctx->shader_impl == NULL)
 	return;
 
+    if (ctx->current_shader == shader)
+        return;
+
     ctx->shader_impl->use (shader);
+
+    ctx->current_shader = shader;
 }
 
 cairo_status_t
commit 6864ca6c25aa8147a562d7f693a95025dde807a8
Author: Benjamin Otte <otte at redhat.com>
Date:   Wed May 19 11:10:11 2010 +0200

    gl: Move _cairo_gl_set_operator() to the file it's used in
    
    Also make it a private function.

diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index b1fe4f8..c3d65f4 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -929,6 +929,63 @@ _cairo_gl_set_mask_operand (cairo_gl_context_t *ctx,
     }
 }
 
+static void
+_cairo_gl_set_operator (cairo_gl_surface_t *dst, cairo_operator_t op,
+			cairo_bool_t component_alpha)
+{
+    struct {
+	GLenum src;
+	GLenum dst;
+    } blend_factors[] = {
+	{ GL_ZERO, GL_ZERO }, /* Clear */
+	{ GL_ONE, GL_ZERO }, /* Source */
+	{ GL_ONE, GL_ONE_MINUS_SRC_ALPHA }, /* Over */
+	{ GL_DST_ALPHA, GL_ZERO }, /* In */
+	{ GL_ONE_MINUS_DST_ALPHA, GL_ZERO }, /* Out */
+	{ GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }, /* Atop */
+
+	{ GL_ZERO, GL_ONE }, /* Dest */
+	{ GL_ONE_MINUS_DST_ALPHA, GL_ONE }, /* DestOver */
+	{ GL_ZERO, GL_SRC_ALPHA }, /* DestIn */
+	{ GL_ZERO, GL_ONE_MINUS_SRC_ALPHA }, /* DestOut */
+	{ GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA }, /* DestAtop */
+
+	{ GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }, /* Xor */
+	{ GL_ONE, GL_ONE }, /* Add */
+    };
+    GLenum src_factor, dst_factor;
+
+    assert (op < ARRAY_LENGTH (blend_factors));
+
+    src_factor = blend_factors[op].src;
+    dst_factor = blend_factors[op].dst;
+
+    /* Even when the user requests CAIRO_CONTENT_COLOR, we use GL_RGBA
+     * due to texture filtering of GL_CLAMP_TO_BORDER.  So fix those
+     * bits in that case.
+     */
+    if (dst->base.content == CAIRO_CONTENT_COLOR) {
+	if (src_factor == GL_ONE_MINUS_DST_ALPHA)
+	    src_factor = GL_ZERO;
+	if (src_factor == GL_DST_ALPHA)
+	    src_factor = GL_ONE;
+    }
+
+    if (component_alpha) {
+	if (dst_factor == GL_ONE_MINUS_SRC_ALPHA)
+	    dst_factor = GL_ONE_MINUS_SRC_COLOR;
+	if (dst_factor == GL_SRC_ALPHA)
+	    dst_factor = GL_SRC_COLOR;
+    }
+
+    glEnable (GL_BLEND);
+    if (dst->base.content == CAIRO_CONTENT_ALPHA) {
+        glBlendFuncSeparate (GL_ZERO, GL_ZERO, src_factor, dst_factor);
+    } else {
+        glBlendFunc (src_factor, dst_factor);
+    }
+}
+
 static unsigned int
 _cairo_gl_operand_get_vertex_size (cairo_gl_operand_type_t type)
 {
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 7a43567..b349f57 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -264,10 +264,6 @@ _cairo_gl_context_set_destination (cairo_gl_context_t *ctx, cairo_gl_surface_t *
 cairo_private cairo_bool_t
 _cairo_gl_operator_is_supported (cairo_operator_t op);
 
-cairo_private void
-_cairo_gl_set_operator (cairo_gl_surface_t *dst, cairo_operator_t op,
-			cairo_bool_t component_alpha);
-
 cairo_private cairo_status_t
 _cairo_gl_composite_init (cairo_gl_context_t *ctx,
                           cairo_gl_composite_t *setup,
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index dd4b35d..5c370b7 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -205,63 +205,6 @@ _cairo_gl_operator_is_supported (cairo_operator_t op)
 }
 
 void
-_cairo_gl_set_operator (cairo_gl_surface_t *dst, cairo_operator_t op,
-			cairo_bool_t component_alpha)
-{
-    struct {
-	GLenum src;
-	GLenum dst;
-    } blend_factors[] = {
-	{ GL_ZERO, GL_ZERO }, /* Clear */
-	{ GL_ONE, GL_ZERO }, /* Source */
-	{ GL_ONE, GL_ONE_MINUS_SRC_ALPHA }, /* Over */
-	{ GL_DST_ALPHA, GL_ZERO }, /* In */
-	{ GL_ONE_MINUS_DST_ALPHA, GL_ZERO }, /* Out */
-	{ GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }, /* Atop */
-
-	{ GL_ZERO, GL_ONE }, /* Dest */
-	{ GL_ONE_MINUS_DST_ALPHA, GL_ONE }, /* DestOver */
-	{ GL_ZERO, GL_SRC_ALPHA }, /* DestIn */
-	{ GL_ZERO, GL_ONE_MINUS_SRC_ALPHA }, /* DestOut */
-	{ GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA }, /* DestAtop */
-
-	{ GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }, /* Xor */
-	{ GL_ONE, GL_ONE }, /* Add */
-    };
-    GLenum src_factor, dst_factor;
-
-    assert (op < ARRAY_LENGTH (blend_factors));
-
-    src_factor = blend_factors[op].src;
-    dst_factor = blend_factors[op].dst;
-
-    /* Even when the user requests CAIRO_CONTENT_COLOR, we use GL_RGBA
-     * due to texture filtering of GL_CLAMP_TO_BORDER.  So fix those
-     * bits in that case.
-     */
-    if (dst->base.content == CAIRO_CONTENT_COLOR) {
-	if (src_factor == GL_ONE_MINUS_DST_ALPHA)
-	    src_factor = GL_ZERO;
-	if (src_factor == GL_DST_ALPHA)
-	    src_factor = GL_ONE;
-    }
-
-    if (component_alpha) {
-	if (dst_factor == GL_ONE_MINUS_SRC_ALPHA)
-	    dst_factor = GL_ONE_MINUS_SRC_COLOR;
-	if (dst_factor == GL_SRC_ALPHA)
-	    dst_factor = GL_SRC_COLOR;
-    }
-
-    glEnable (GL_BLEND);
-    if (dst->base.content == CAIRO_CONTENT_ALPHA) {
-        glBlendFuncSeparate (GL_ZERO, GL_ZERO, src_factor, dst_factor);
-    } else {
-        glBlendFunc (src_factor, dst_factor);
-    }
-}
-
-void
 _cairo_gl_surface_init (cairo_device_t *device,
 			cairo_gl_surface_t *surface,
 			cairo_content_t content,
commit 0d2d4c59026c31da084e6797d109a230341b396d
Author: Benjamin Otte <otte at redhat.com>
Date:   Tue May 18 21:56:55 2010 +0200

    gl: Detect color-pattern clears of surfaces
    
    ... and use glClear() there.
    
    The common case here is a solid color and OPERATOR_OVER.

diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 66c9165..7a43567 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -264,9 +264,6 @@ _cairo_gl_context_set_destination (cairo_gl_context_t *ctx, cairo_gl_surface_t *
 cairo_private cairo_bool_t
 _cairo_gl_operator_is_supported (cairo_operator_t op);
 
-cairo_private cairo_status_t
-_cairo_gl_surface_clear (cairo_gl_surface_t *surface);
-
 cairo_private void
 _cairo_gl_set_operator (cairo_gl_surface_t *dst, cairo_operator_t op,
 			cairo_bool_t component_alpha);
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index b823594..dd4b35d 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -350,21 +350,33 @@ _cairo_gl_surface_create_scratch (cairo_gl_context_t   *ctx,
     return &surface->base;
 }
 
-cairo_status_t
-_cairo_gl_surface_clear (cairo_gl_surface_t *surface)
+static cairo_status_t
+_cairo_gl_surface_clear (cairo_gl_surface_t  *surface,
+                         const cairo_color_t *color)
 {
     cairo_gl_context_t *ctx;
     cairo_status_t status;
+    double r, g, b, a;
 
     status = _cairo_gl_context_acquire (surface->base.device, &ctx);
     if (unlikely (status))
 	return status;
 
     _cairo_gl_context_set_destination (ctx, surface);
-    if (surface->base.content == CAIRO_CONTENT_COLOR)
-	glClearColor (0.0, 0.0, 0.0, 1.0);
-    else
-	glClearColor (0.0, 0.0, 0.0, 0.0);
+    if (surface->base.content & CAIRO_CONTENT_COLOR) {
+        r = color->red   * color->alpha;
+        g = color->green * color->alpha;
+        b = color->blue  * color->alpha;
+    } else {
+        r = g = b = 0;
+    }
+    if (surface->base.content & CAIRO_CONTENT_ALPHA) {
+        a = color->alpha;
+    } else {
+        a = 1.0;
+    }
+
+    glClearColor (r, g, b, a);
     glClear (GL_COLOR_BUFFER_BIT);
     _cairo_gl_context_release (ctx);
 
@@ -406,7 +418,7 @@ cairo_gl_surface_create (cairo_device_t		*abstract_device,
     }
 
     /* Cairo surfaces start out initialized to transparent (black) */
-    status = _cairo_gl_surface_clear (surface);
+    status = _cairo_gl_surface_clear (surface, CAIRO_COLOR_TRANSPARENT);
     if (unlikely (status)) {
 	cairo_surface_destroy (&surface->base);
 	_cairo_gl_context_release (ctx);
@@ -1385,8 +1397,16 @@ _cairo_gl_surface_paint (void *abstract_surface,
 			 cairo_clip_t	    *clip)
 {
     /* simplify the common case of clearing the surface */
-    if (op == CAIRO_OPERATOR_CLEAR && clip == NULL)
-	return _cairo_gl_surface_clear (abstract_surface);
+    if (clip == NULL) {
+        if (op == CAIRO_OPERATOR_CLEAR)
+            return _cairo_gl_surface_clear (abstract_surface, CAIRO_COLOR_TRANSPARENT);
+       else if (source->type == CAIRO_PATTERN_TYPE_SOLID &&
+                (op == CAIRO_OPERATOR_SOURCE ||
+                 (op == CAIRO_OPERATOR_OVER && _cairo_pattern_is_opaque_solid (source)))) {
+            return _cairo_gl_surface_clear (abstract_surface,
+                                            &((cairo_solid_pattern_t *) source)->color);
+        }
+    }
 
     return CAIRO_INT_STATUS_UNSUPPORTED;
 }
commit b70eb275c4aa54f7c90a985b5de67da12ac08a30
Author: Benjamin Otte <otte at redhat.com>
Date:   Tue May 18 21:56:18 2010 +0200

    gl: detect image uploads and fast-path them

diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 531159b..b823594 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -965,6 +965,29 @@ _cairo_gl_surface_composite (cairo_operator_t		  op,
     cairo_status_t status;
     cairo_gl_composite_t setup;
     cairo_rectangle_int_t rect = { dst_x, dst_y, width, height };
+    int dx, dy;
+
+    if (op == CAIRO_OPERATOR_SOURCE &&
+        mask == NULL &&
+        src->type == CAIRO_PATTERN_TYPE_SURFACE &&
+        _cairo_surface_is_image (((cairo_surface_pattern_t *) src)->surface) &&
+        _cairo_matrix_is_integer_translation (&src->matrix, &dx, &dy)) {
+        cairo_image_surface_t *image = (cairo_image_surface_t *)
+            ((cairo_surface_pattern_t *) src)->surface;
+        dx += src_x;
+        dy += src_y;
+        if (dx >= 0 &&
+            dy >= 0 &&
+            dx + width <= (unsigned int) image->width &&
+            dy + height <= (unsigned int) image->height) {
+            status = _cairo_gl_surface_draw_image (dst, image,
+                                                   dx, dy,
+                                                   width, height,
+                                                   dst_x, dst_y);
+            if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+                return status;
+        }
+    }
 
     status = _cairo_gl_context_acquire (dst->base.device, &ctx);
     if (unlikely (status))
commit 8adbf3aa19fd9fb8200973ecd72cdebfd9a5364d
Author: Benjamin Otte <otte at redhat.com>
Date:   Tue May 18 20:12:44 2010 +0200

    gl: Use _cairo_gl_surface_draw_image() when caching glyphs

diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index 7ccc7fd..4252710 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -63,33 +63,8 @@ _cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx,
     cairo_gl_surface_t *cache_surface;
     cairo_gl_glyph_private_t *glyph_private;
     cairo_rtree_node_t *node = NULL;
-    cairo_image_surface_t *clone = NULL;
     cairo_status_t status;
     int width, height;
-    GLenum internal_format, format, type;
-    cairo_bool_t has_alpha;
-
-    if (! _cairo_gl_get_image_format_and_type (glyph_surface->pixman_format,
-					       &internal_format,
-					       &format,
-					       &type,
-					       &has_alpha))
-    {
-	cairo_bool_t is_supported;
-
-	clone = _cairo_image_surface_coerce (glyph_surface);
-	if (unlikely (clone->base.status))
-	    return clone->base.status;
-
-	is_supported =
-	    _cairo_gl_get_image_format_and_type (clone->pixman_format,
-					         &internal_format,
-						 &format,
-						 &type,
-						 &has_alpha);
-	assert (is_supported);
-	glyph_surface = clone;
-    }
 
     width = glyph_surface->width;
     if (width < GLYPH_CACHE_MIN_SIZE)
@@ -114,19 +89,15 @@ _cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx,
 
     cache_surface = (cairo_gl_surface_t *) cache->pattern.surface;
 
+    /* XXX: Make sure we use the mask texture. This should work automagically somehow */
     glActiveTexture (GL_TEXTURE1);
-    glBindTexture (ctx->tex_target, cache_surface->tex);
-
-    glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
-    glPixelStorei (GL_UNPACK_ROW_LENGTH,
-		   glyph_surface->stride /
-		   (PIXMAN_FORMAT_BPP (glyph_surface->pixman_format) / 8));
-    glTexSubImage2D (ctx->tex_target, 0,
-		     node->x, node->y,
-		     glyph_surface->width, glyph_surface->height,
-		     format, type,
-		     glyph_surface->data);
-    glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
+    status = _cairo_gl_surface_draw_image (cache_surface,
+                                           glyph_surface,
+                                           0, 0,
+                                           glyph_surface->width, glyph_surface->height,
+                                           node->x, node->y);
+    if (unlikely (status))
+	return status;
 
     scaled_glyph->surface_private = node;
     node->owner = &scaled_glyph->surface_private;
@@ -146,8 +117,6 @@ _cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx,
 	glyph_private->p2.y /= cache_surface->height;
     }
 
-    cairo_surface_destroy (&clone->base);
-
     return CAIRO_STATUS_SUCCESS;
 }
 
commit 915aa64ef077fe3b6094d0f1c8bd87ab5acc4868
Author: Benjamin Otte <otte at redhat.com>
Date:   Tue May 18 13:01:30 2010 +0200

    gl: Actually check errors for _cairo_gl_composite_begin()

diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index a72f93c..7ccc7fd 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -343,6 +343,8 @@ _render_glyphs (cairo_gl_surface_t	*dst,
 	    *has_component_alpha |= cache->pattern.base.has_component_alpha;
 
             status = _cairo_gl_composite_begin (ctx, &setup);
+            if (unlikely (status))
+                goto FINISH;
 	}
 
 	if (scaled_glyph->surface_private == NULL) {
commit 0222cc7d76b0dc724630b660687f98a2460eb0b9
Author: Benjamin Otte <otte at redhat.com>
Date:   Tue May 18 13:00:34 2010 +0200

    gl: Get rid of _cairo_gl_composite_set_mask_texture()
    
    Now that the glyph cache contains real surfaces, there's no longer a
    need to have a special function for it.

diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index 40efbf1..b1fe4f8 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -531,22 +531,6 @@ _cairo_gl_composite_set_mask_spans (cairo_gl_context_t *ctx,
 }
 
 void
-_cairo_gl_composite_set_mask_texture (cairo_gl_context_t *ctx,
-                                      cairo_gl_composite_t *setup,
-                                      GLuint tex,
-                                      cairo_bool_t has_component_alpha)
-{
-    _cairo_gl_operand_destroy (&setup->mask);
-
-    setup->has_component_alpha = has_component_alpha;
-
-    setup->mask.type = CAIRO_GL_OPERAND_TEXTURE;
-    setup->mask.texture.tex = tex;
-    setup->mask.texture.surface = NULL;
-    cairo_matrix_init_identity (&setup->mask.texture.attributes.matrix);
-}
-
-void
 _cairo_gl_composite_set_clip_region (cairo_gl_context_t *ctx,
                                      cairo_gl_composite_t *setup,
                                      cairo_region_t *clip_region)
diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index b49f889..a72f93c 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -333,13 +333,14 @@ _render_glyphs (cairo_gl_surface_t	*dst,
 
 	    last_format = scaled_glyph->surface->format;
 
-            _cairo_gl_composite_set_mask_texture (ctx,
-                                                  &setup,
-                                                  ((cairo_gl_surface_t *) cache->pattern.surface)->tex, 
-                                                  last_format == CAIRO_FORMAT_ARGB32);
-
-	    if (last_format == CAIRO_FORMAT_ARGB32)
-		*has_component_alpha = TRUE;
+            status = _cairo_gl_composite_set_mask (ctx,
+                                                   &setup,
+                                                   &cache->pattern.base,
+                                                   0, 0, 0, 0, 0, 0);
+            if (unlikely (status))
+                goto FINISH;
+
+	    *has_component_alpha |= cache->pattern.base.has_component_alpha;
 
             status = _cairo_gl_composite_begin (ctx, &setup);
 	}
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index d7298c9..66c9165 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -308,12 +308,6 @@ cairo_private void
 _cairo_gl_composite_set_mask_spans (cairo_gl_context_t *ctx,
                                     cairo_gl_composite_t *setup);
 
-cairo_private void
-_cairo_gl_composite_set_mask_texture (cairo_gl_context_t *ctx,
-                                      cairo_gl_composite_t *setup,
-                                      GLuint tex,
-                                      cairo_bool_t has_component_alpha);
-
 cairo_private cairo_status_t
 _cairo_gl_composite_begin (cairo_gl_context_t *ctx,
                            cairo_gl_composite_t *setup);
commit 208d9f2a7e1f66ff2764c41fe67f65e27279b2ab
Author: Benjamin Otte <otte at redhat.com>
Date:   Tue May 18 12:49:59 2010 +0200

    gl: Make glyph cache a real surface
    
    This has the huge advantage that we can use real surface functions on
    it.

diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index 7d187c5..b49f889 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -60,6 +60,7 @@ _cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx,
 				 cairo_scaled_glyph_t  *scaled_glyph)
 {
     cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
+    cairo_gl_surface_t *cache_surface;
     cairo_gl_glyph_private_t *glyph_private;
     cairo_rtree_node_t *node = NULL;
     cairo_image_surface_t *clone = NULL;
@@ -111,8 +112,10 @@ _cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx,
     if (status)
 	return status;
 
+    cache_surface = (cairo_gl_surface_t *) cache->pattern.surface;
+
     glActiveTexture (GL_TEXTURE1);
-    glBindTexture (ctx->tex_target, cache->tex);
+    glBindTexture (ctx->tex_target, cache_surface->tex);
 
     glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
     glPixelStorei (GL_UNPACK_ROW_LENGTH,
@@ -137,10 +140,10 @@ _cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx,
     glyph_private->p2.x = node->x + glyph_surface->width;
     glyph_private->p2.y = node->y + glyph_surface->height;
     if (ctx->tex_target != GL_TEXTURE_RECTANGLE_EXT) {
-	glyph_private->p1.x /= cache->width;
-	glyph_private->p1.y /= cache->height;
-	glyph_private->p2.x /= cache->width;
-	glyph_private->p2.y /= cache->height;
+	glyph_private->p1.x /= cache_surface->width;
+	glyph_private->p1.y /= cache_surface->height;
+	glyph_private->p2.x /= cache_surface->width;
+	glyph_private->p2.y /= cache_surface->height;
     }
 
     cairo_surface_destroy (&clone->base);
@@ -160,53 +163,35 @@ cairo_gl_context_get_glyph_cache (cairo_gl_context_t *ctx,
 				  cairo_format_t format)
 {
     cairo_gl_glyph_cache_t *cache;
+    cairo_content_t content;
 
     switch (format) {
     case CAIRO_FORMAT_RGB16_565:
     case CAIRO_FORMAT_ARGB32:
     case CAIRO_FORMAT_RGB24:
 	cache = &ctx->glyph_cache[0];
-	format = CAIRO_FORMAT_ARGB32;
+        content = CAIRO_CONTENT_COLOR_ALPHA;
 	break;
     case CAIRO_FORMAT_A8:
     case CAIRO_FORMAT_A1:
 	cache = &ctx->glyph_cache[1];
-	format = CAIRO_FORMAT_A8;
+        content = CAIRO_CONTENT_ALPHA;
 	break;
     case CAIRO_FORMAT_INVALID:
 	ASSERT_NOT_REACHED;
 	return NULL;
     }
 
-    if (unlikely (cache->tex == 0)) {
-	GLenum internal_format;
-
-	cache->width = GLYPH_CACHE_WIDTH;
-	cache->height = GLYPH_CACHE_HEIGHT;
-
-	switch (format) {
-	    case CAIRO_FORMAT_A1:
-	    case CAIRO_FORMAT_RGB16_565:
-	    case CAIRO_FORMAT_RGB24:
-		ASSERT_NOT_REACHED;
-	    case CAIRO_FORMAT_ARGB32:
-		internal_format = GL_RGBA;
-		break;
-	    case CAIRO_FORMAT_A8:
-		internal_format = GL_ALPHA;
-		break;
-	    case CAIRO_FORMAT_INVALID:
-		ASSERT_NOT_REACHED;
-		return NULL;
-	}
-
-	glGenTextures (1, &cache->tex);
-	glBindTexture (ctx->tex_target, cache->tex);
-	glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-	glTexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-	glTexImage2D (ctx->tex_target, 0, internal_format,
-		      GLYPH_CACHE_WIDTH, GLYPH_CACHE_HEIGHT, 0,
-		      internal_format, GL_FLOAT, NULL);
+    if (unlikely (cache->pattern.surface == NULL)) {
+        cairo_surface_t *surface;
+        surface = cairo_gl_surface_create (&ctx->base,
+                                           content,
+                                           GLYPH_CACHE_WIDTH,
+                                           GLYPH_CACHE_HEIGHT);
+        _cairo_surface_release_device_reference (surface);
+        _cairo_pattern_init_for_surface (&cache->pattern, surface);
+        cairo_surface_destroy (surface);
+        cache->pattern.base.has_component_alpha = (content == CAIRO_CONTENT_COLOR_ALPHA);
     }
 
     return cache;
@@ -350,7 +335,7 @@ _render_glyphs (cairo_gl_surface_t	*dst,
 
             _cairo_gl_composite_set_mask_texture (ctx,
                                                   &setup,
-                                                  cache->tex, 
+                                                  ((cairo_gl_surface_t *) cache->pattern.surface)->tex, 
                                                   last_format == CAIRO_FORMAT_ARGB32);
 
 	    if (last_format == CAIRO_FORMAT_ARGB32)
@@ -627,8 +612,6 @@ EMPTY:
 void
 _cairo_gl_glyph_cache_init (cairo_gl_glyph_cache_t *cache)
 {
-    cache->tex = 0;
-
     _cairo_rtree_init (&cache->rtree,
 		       GLYPH_CACHE_WIDTH,
 		       GLYPH_CACHE_HEIGHT,
@@ -642,9 +625,9 @@ _cairo_gl_glyph_cache_fini (cairo_gl_context_t *ctx,
 {
     _cairo_rtree_fini (&cache->rtree);
 
-    if (cache->tex) {
-	/* XXX Is this safe? */
-	glDeleteTextures (1, &cache->tex);
+    if (cache->pattern.surface) {
+        _cairo_pattern_fini (&cache->pattern.base);
+        cache->pattern.surface = NULL;
     }
 }
 
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 724814a..d7298c9 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -85,8 +85,7 @@ typedef struct _cairo_gl_surface {
 
 typedef struct cairo_gl_glyph_cache {
     cairo_rtree_t rtree;
-    GLuint tex;
-    unsigned int width, height;
+    cairo_surface_pattern_t pattern;
 } cairo_gl_glyph_cache_t;
 
 typedef enum cairo_gl_operand_type {
commit 050117996339cfe35add1f2cd44d0e5578d4a981
Author: Benjamin Otte <otte at redhat.com>
Date:   Tue May 18 12:02:54 2010 +0200

    surface: Add _cairo_surface_release_device_reference() API
    
    See the API documentation for that function about its intended purpose.

diff --git a/src/cairo-surface-private.h b/src/cairo-surface-private.h
index bc03119..19a93c2 100644
--- a/src/cairo-surface-private.h
+++ b/src/cairo-surface-private.h
@@ -65,6 +65,7 @@ struct _cairo_surface {
     unsigned finished : 1;
     unsigned is_clear : 1;
     unsigned has_font_options : 1;
+    unsigned owns_device : 1;
 
     cairo_user_data_array_t user_data;
     cairo_user_data_array_t mime_data;
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index cf7e054..8b67e66 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -58,6 +58,7 @@ const cairo_surface_t name = {					\
     FALSE,				/* finished */		\
     TRUE,				/* is_clear */		\
     FALSE,				/* has_font_options */	\
+    FALSE,				/* owns_device */	\
     { 0, 0, 0, NULL, },			/* user_data */		\
     { 0, 0, 0, NULL, },			/* mime_data */         \
     { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 },   /* device_transform */	\
@@ -356,6 +357,7 @@ _cairo_surface_init (cairo_surface_t			*surface,
     surface->unique_id = _cairo_surface_allocate_unique_id ();
     surface->finished = FALSE;
     surface->is_clear = FALSE;
+    surface->owns_device = (device != NULL);
 
     _cairo_user_data_array_init (&surface->user_data);
     _cairo_user_data_array_init (&surface->mime_data);
@@ -595,7 +597,8 @@ cairo_surface_destroy (cairo_surface_t *surface)
     _cairo_user_data_array_fini (&surface->user_data);
     _cairo_user_data_array_fini (&surface->mime_data);
 
-    cairo_device_destroy (surface->device);
+    if (surface->owns_device)
+        cairo_device_destroy (surface->device);
 
     free (surface);
 }
@@ -673,6 +676,27 @@ cairo_surface_finish (cairo_surface_t *surface)
 slim_hidden_def (cairo_surface_finish);
 
 /**
+ * _cairo_surface_release_device_reference:
+ * @surface: a #cairo_surface_t
+ *
+ * This function makes @surface release the reference to its device. The
+ * function is intended to be used for avoiding cycling references for
+ * surfaces that are owned by their device, for example cache surfaces.
+ * Note that the @surface will still assume that the device is available.
+ * So it is the caller's responsibility to ensure the device stays around
+ * until the @surface is destroyed. Just calling cairo_surface_finish() is
+ * not enough.
+ **/
+void
+_cairo_surface_release_device_reference (cairo_surface_t *surface)
+{
+    assert (surface->owns_device);
+
+    cairo_device_destroy (surface->device);
+    surface->owns_device = FALSE;
+}
+
+/**
  * cairo_surface_get_user_data:
  * @surface: a #cairo_surface_t
  * @key: the address of the #cairo_user_data_key_t the user data was
diff --git a/src/cairoint.h b/src/cairoint.h
index b52db6d..1f8643d 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2119,6 +2119,9 @@ _cairo_surface_set_device_scale (cairo_surface_t *surface,
 cairo_private cairo_bool_t
 _cairo_surface_has_device_transform (cairo_surface_t *surface) cairo_pure;
 
+cairo_private void
+_cairo_surface_release_device_reference (cairo_surface_t *surface);
+
 /* cairo-image-surface.c */
 
 /* XXX: In cairo 1.2.0 we added a new %CAIRO_FORMAT_RGB16_565 but
commit c489f67d1d1d6079f9b58b726ed42beea1dfc44e
Author: Benjamin Otte <otte at redhat.com>
Date:   Mon May 17 20:45:42 2010 +0200

    gl: Make a bunch of functions static
    
    They are no longer used outside of cairo_gl_composite_t.

diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index c21ee0e..40efbf1 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -610,7 +610,7 @@ _cairo_gl_set_tex_combine_constant_color (cairo_gl_context_t *ctx,
     }
 }
 
-void
+static void
 _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
 			   cairo_gl_composite_t *setup)
 {
@@ -700,7 +700,7 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
  * for creating the "source alpha" value (src.aaaa * mask.argb) required by
  * component alpha rendering.
  */
-void
+static void
 _cairo_gl_set_src_alpha_operand (cairo_gl_context_t *ctx,
 				 cairo_gl_composite_t *setup)
 {
@@ -794,7 +794,7 @@ _cairo_gl_set_radial_gradient_mask_operand (cairo_gl_context_t *ctx,
 /* This is like _cairo_gl_set_src_alpha_operand, for component alpha setup
  * of the mask part of IN to produce a "source alpha" value.
  */
-void
+static void
 _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
 					    cairo_gl_composite_t *setup)
 {
@@ -876,7 +876,7 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
     }
 }
 
-void
+static void
 _cairo_gl_set_mask_operand (cairo_gl_context_t *ctx,
 			    cairo_gl_composite_t *setup)
 {
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index d8bfcc4..724814a 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -348,22 +348,6 @@ cairo_private void
 _cairo_gl_composite_end (cairo_gl_context_t *ctx,
                          cairo_gl_composite_t *setup);
 
-cairo_private void
-_cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
-			   cairo_gl_composite_t *setup);
-
-cairo_private void
-_cairo_gl_set_src_alpha_operand (cairo_gl_context_t *ctx,
-				 cairo_gl_composite_t *setup);
-
-cairo_private void
-_cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
-				            cairo_gl_composite_t *setup);
-
-cairo_private void
-_cairo_gl_set_mask_operand (cairo_gl_context_t *ctx,
-			    cairo_gl_composite_t *setup);
-
 cairo_private cairo_bool_t
 _cairo_gl_get_image_format_and_type (pixman_format_code_t pixman_format,
 				     GLenum *internal_format, GLenum *format,
commit c8008e118a54d62690d6555c9ffabf734c39e69f
Author: Benjamin Otte <otte at redhat.com>
Date:   Mon May 17 19:16:20 2010 +0200

    gl: Don't name the union in cairo_gl_operand_t
    
    Gets rid of ultra-long variable names.

diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index c4c30de..c21ee0e 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -263,7 +263,7 @@ _cairo_gl_pattern_texture_setup (cairo_gl_context_t *ctx,
     cairo_matrix_t m;
     cairo_gl_surface_t *surface;
     cairo_surface_attributes_t *attributes;
-    attributes = &operand->operand.texture.attributes;
+    attributes = &operand->texture.attributes;
 
     status = _cairo_pattern_acquire_surface (src, &dst->base,
 					     src_x, src_y,
@@ -288,8 +288,8 @@ _cairo_gl_pattern_texture_setup (cairo_gl_context_t *ctx,
     assert (surface->base.backend == &_cairo_gl_surface_backend);
 
     operand->type = CAIRO_GL_OPERAND_TEXTURE;
-    operand->operand.texture.surface = surface;
-    operand->operand.texture.tex = surface->tex;
+    operand->texture.surface = surface;
+    operand->texture.tex = surface->tex;
     /* Translate the matrix from
      * (unnormalized src -> unnormalized src) to
      * (unnormalized dst -> unnormalized src)
@@ -327,10 +327,10 @@ _cairo_gl_solid_operand_init (cairo_gl_operand_t *operand,
 	                      const cairo_color_t *color)
 {
     operand->type = CAIRO_GL_OPERAND_CONSTANT;
-    operand->operand.constant.color[0] = color->red   * color->alpha;
-    operand->operand.constant.color[1] = color->green * color->alpha;
-    operand->operand.constant.color[2] = color->blue  * color->alpha;
-    operand->operand.constant.color[3] = color->alpha;
+    operand->constant.color[0] = color->red   * color->alpha;
+    operand->constant.color[1] = color->green * color->alpha;
+    operand->constant.color[2] = color->blue  * color->alpha;
+    operand->constant.color[3] = color->alpha;
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -360,20 +360,20 @@ _cairo_gl_gradient_operand_init (cairo_gl_context_t *ctx,
         _cairo_gl_create_gradient_texture (ctx,
 					   dst,
 					   gradient,
-					   &operand->operand.linear.tex);
+					   &operand->linear.tex);
 
 	/* Translation matrix from the destination fragment coordinates
 	 * (pixels from lower left = 0,0) to the coordinates in the
 	 */
-	cairo_matrix_init_translate (&operand->operand.linear.m, -x0, -y0);
-	cairo_matrix_multiply (&operand->operand.linear.m,
+	cairo_matrix_init_translate (&operand->linear.m, -x0, -y0);
+	cairo_matrix_multiply (&operand->linear.m,
 			       &operand->pattern->matrix,
-			       &operand->operand.linear.m);
-	cairo_matrix_translate (&operand->operand.linear.m, 0, dst->height);
-	cairo_matrix_scale (&operand->operand.linear.m, 1.0, -1.0);
+			       &operand->linear.m);
+	cairo_matrix_translate (&operand->linear.m, 0, dst->height);
+	cairo_matrix_scale (&operand->linear.m, 1.0, -1.0);
 
-	operand->operand.linear.segment_x = x1 - x0;
-	operand->operand.linear.segment_y = y1 - y0;
+	operand->linear.segment_x = x1 - x0;
+	operand->linear.segment_y = y1 - y0;
 
 	operand->type = CAIRO_GL_OPERAND_LINEAR_GRADIENT;
         return CAIRO_STATUS_SUCCESS;
@@ -394,22 +394,22 @@ _cairo_gl_gradient_operand_init (cairo_gl_context_t *ctx,
         _cairo_gl_create_gradient_texture (ctx,
 					   dst,
 					   gradient,
-					   &operand->operand.radial.tex);
+					   &operand->radial.tex);
 
 	/* Translation matrix from the destination fragment coordinates
 	 * (pixels from lower left = 0,0) to the coordinates in the
 	 */
-	cairo_matrix_init_translate (&operand->operand.radial.m, -x0, -y0);
-	cairo_matrix_multiply (&operand->operand.radial.m,
+	cairo_matrix_init_translate (&operand->radial.m, -x0, -y0);
+	cairo_matrix_multiply (&operand->radial.m,
 			       &operand->pattern->matrix,
-			       &operand->operand.radial.m);
-	cairo_matrix_translate (&operand->operand.radial.m, 0, dst->height);
-	cairo_matrix_scale (&operand->operand.radial.m, 1.0, -1.0);
+			       &operand->radial.m);
+	cairo_matrix_translate (&operand->radial.m, 0, dst->height);
+	cairo_matrix_scale (&operand->radial.m, 1.0, -1.0);
 
-	operand->operand.radial.circle_1_x = x1 - x0;
-	operand->operand.radial.circle_1_y = y1 - y0;
-	operand->operand.radial.radius_0 = r0;
-	operand->operand.radial.radius_1 = r1;
+	operand->radial.circle_1_x = x1 - x0;
+	operand->radial.circle_1_y = y1 - y0;
+	operand->radial.radius_0 = r0;
+	operand->radial.radius_1 = r1;
 
 	operand->type = CAIRO_GL_OPERAND_RADIAL_GRADIENT;
         return CAIRO_STATUS_SUCCESS;
@@ -425,18 +425,18 @@ _cairo_gl_operand_destroy (cairo_gl_operand_t *operand)
     case CAIRO_GL_OPERAND_CONSTANT:
 	break;
     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
-	glDeleteTextures (1, &operand->operand.linear.tex);
+	glDeleteTextures (1, &operand->linear.tex);
 	break;
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
-	glDeleteTextures (1, &operand->operand.radial.tex);
+	glDeleteTextures (1, &operand->radial.tex);
 	break;
     case CAIRO_GL_OPERAND_TEXTURE:
-	if (operand->operand.texture.surface != NULL) {
-	    cairo_gl_surface_t *surface = operand->operand.texture.surface;
+	if (operand->texture.surface != NULL) {
+	    cairo_gl_surface_t *surface = operand->texture.surface;
 
 	    _cairo_pattern_release_surface (operand->pattern,
 					    &surface->base,
-					    &operand->operand.texture.attributes);
+					    &operand->texture.attributes);
 	}
 	break;
     default:
@@ -541,9 +541,9 @@ _cairo_gl_composite_set_mask_texture (cairo_gl_context_t *ctx,
     setup->has_component_alpha = has_component_alpha;
 
     setup->mask.type = CAIRO_GL_OPERAND_TEXTURE;
-    setup->mask.operand.texture.tex = tex;
-    setup->mask.operand.texture.surface = NULL;
-    cairo_matrix_init_identity (&setup->mask.operand.texture.attributes.matrix);
+    setup->mask.texture.tex = tex;
+    setup->mask.texture.surface = NULL;
+    cairo_matrix_init_identity (&setup->mask.texture.attributes.matrix);
 }
 
 void
@@ -617,15 +617,15 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
     cairo_surface_attributes_t *src_attributes;
     GLfloat constant_color[4] = {0.0, 0.0, 0.0, 0.0};
 
-    src_attributes = &setup->src.operand.texture.attributes;
+    src_attributes = &setup->src.texture.attributes;
 
     switch (setup->src.type) {
     case CAIRO_GL_OPERAND_CONSTANT:
 	_cairo_gl_set_tex_combine_constant_color (ctx, setup, 0,
-						  setup->src.operand.constant.color);
+						  setup->src.constant.color);
 	break;
     case CAIRO_GL_OPERAND_TEXTURE:
-	_cairo_gl_set_texture_surface (0, setup->src.operand.texture.tex,
+	_cairo_gl_set_texture_surface (0, setup->src.texture.tex,
 				       src_attributes, ctx->tex_target);
 	if (!setup->shader) {
 	    /* Set up the constant color we use to set color to 0 if needed. */
@@ -639,7 +639,7 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
 	     * alpha-only.  We may have a teximage with color bits if
 	     * the implementation doesn't support GL_ALPHA FBOs.
 	     */
-	    if (setup->src.operand.texture.surface->base.content !=
+	    if (setup->src.texture.surface->base.content !=
 		CAIRO_CONTENT_ALPHA)
 		glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0);
 	    else
@@ -652,40 +652,40 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
 
     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
 	glActiveTexture (GL_TEXTURE0);
-	glBindTexture (GL_TEXTURE_1D, setup->src.operand.linear.tex);
+	glBindTexture (GL_TEXTURE_1D, setup->src.linear.tex);
 	glEnable (GL_TEXTURE_1D);
 
 	_cairo_gl_shader_bind_matrix (ctx, setup->shader,
 				      "source_matrix",
-				      &setup->src.operand.linear.m);
+				      &setup->src.linear.m);
 
 	_cairo_gl_shader_bind_vec2 (ctx, setup->shader,
 				    "source_segment",
-				    setup->src.operand.linear.segment_x,
-				    setup->src.operand.linear.segment_y);
+				    setup->src.linear.segment_x,
+				    setup->src.linear.segment_y);
 	break;
 
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
 	glActiveTexture (GL_TEXTURE0);
-	glBindTexture (GL_TEXTURE_1D, setup->src.operand.linear.tex);
+	glBindTexture (GL_TEXTURE_1D, setup->src.linear.tex);
 	glEnable (GL_TEXTURE_1D);
 
         _cairo_gl_shader_bind_matrix (ctx, setup->shader,
 				      "source_matrix",
-				      &setup->src.operand.radial.m);
+				      &setup->src.radial.m);
 
 	_cairo_gl_shader_bind_vec2 (ctx, setup->shader,
 				    "source_circle_1",
-				    setup->src.operand.radial.circle_1_x,
-				    setup->src.operand.radial.circle_1_y);
+				    setup->src.radial.circle_1_x,
+				    setup->src.radial.circle_1_y);
 
         _cairo_gl_shader_bind_float (ctx, setup->shader,
 				     "source_radius_0",
-				     setup->src.operand.radial.radius_0);
+				     setup->src.radial.radius_0);
 
         _cairo_gl_shader_bind_float (ctx, setup->shader,
 				     "source_radius_1",
-				     setup->src.operand.radial.radius_1);
+				     setup->src.radial.radius_1);
 	break;
     default:
     case CAIRO_GL_OPERAND_COUNT:
@@ -707,19 +707,19 @@ _cairo_gl_set_src_alpha_operand (cairo_gl_context_t *ctx,
     GLfloat constant_color[4] = {0.0, 0.0, 0.0, 0.0};
     cairo_surface_attributes_t *src_attributes;
 
-    src_attributes = &setup->src.operand.texture.attributes;
+    src_attributes = &setup->src.texture.attributes;
 
     switch (setup->src.type) {
     case CAIRO_GL_OPERAND_CONSTANT:
-	constant_color[0] = setup->src.operand.constant.color[3];
-	constant_color[1] = setup->src.operand.constant.color[3];
-	constant_color[2] = setup->src.operand.constant.color[3];
-	constant_color[3] = setup->src.operand.constant.color[3];
+	constant_color[0] = setup->src.constant.color[3];
+	constant_color[1] = setup->src.constant.color[3];
+	constant_color[2] = setup->src.constant.color[3];
+	constant_color[3] = setup->src.constant.color[3];
 	_cairo_gl_set_tex_combine_constant_color (ctx, setup, 0,
 						  constant_color);
 	break;
     case CAIRO_GL_OPERAND_TEXTURE:
-	_cairo_gl_set_texture_surface (0, setup->src.operand.texture.tex,
+	_cairo_gl_set_texture_surface (0, setup->src.texture.tex,
 				       src_attributes, ctx->tex_target);
 	if (!setup->shader) {
 	    /* Set up the combiner to just set color to the sampled texture. */
@@ -751,16 +751,16 @@ _cairo_gl_set_linear_gradient_mask_operand (cairo_gl_context_t *ctx,
     assert(setup->shader);
 
     glActiveTexture (GL_TEXTURE1);
-    glBindTexture (GL_TEXTURE_1D, setup->mask.operand.linear.tex);
+    glBindTexture (GL_TEXTURE_1D, setup->mask.linear.tex);
     glEnable (GL_TEXTURE_1D);
 
     _cairo_gl_shader_bind_matrix (ctx, setup->shader,
-				  "mask_matrix", &setup->mask.operand.linear.m);
+				  "mask_matrix", &setup->mask.linear.m);
 
     _cairo_gl_shader_bind_vec2 (ctx, setup->shader,
 				"mask_segment",
-				setup->mask.operand.linear.segment_x,
-				setup->mask.operand.linear.segment_y);
+				setup->mask.linear.segment_x,
+				setup->mask.linear.segment_y);
 }
 
 static void
@@ -770,25 +770,25 @@ _cairo_gl_set_radial_gradient_mask_operand (cairo_gl_context_t *ctx,
     assert(setup->shader);
 
     glActiveTexture (GL_TEXTURE1);
-    glBindTexture (GL_TEXTURE_1D, setup->mask.operand.radial.tex);
+    glBindTexture (GL_TEXTURE_1D, setup->mask.radial.tex);
     glEnable (GL_TEXTURE_1D);
 
     _cairo_gl_shader_bind_matrix (ctx, setup->shader,
 				  "mask_matrix",
-				  &setup->mask.operand.radial.m);
+				  &setup->mask.radial.m);
 
     _cairo_gl_shader_bind_vec2 (ctx, setup->shader,
 				"mask_circle_1",
-				setup->mask.operand.radial.circle_1_x,
-				setup->mask.operand.radial.circle_1_y);
+				setup->mask.radial.circle_1_x,
+				setup->mask.radial.circle_1_y);
 
     _cairo_gl_shader_bind_float (ctx, setup->shader,
 				 "mask_radius_0",
-				 setup->mask.operand.radial.radius_0);
+				 setup->mask.radial.radius_0);
 
     _cairo_gl_shader_bind_float (ctx, setup->shader,
 				 "mask_radius_1",
-				 setup->mask.operand.radial.radius_1);
+				 setup->mask.radial.radius_1);
 }
 
 /* This is like _cairo_gl_set_src_alpha_operand, for component alpha setup
@@ -801,7 +801,7 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
     cairo_surface_attributes_t *mask_attributes;
     GLfloat constant_color[4] = {0.0, 0.0, 0.0, 0.0};
 
-    mask_attributes = &setup->mask.operand.texture.attributes;
+    mask_attributes = &setup->mask.texture.attributes;
 
     if (!setup->shader) {
 	glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
@@ -820,17 +820,17 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
 	if (setup->shader) {
 	    _cairo_gl_shader_bind_vec4 (ctx, setup->shader,
 					"mask_constant",
-					setup->src.operand.constant.color[0],
-					setup->src.operand.constant.color[1],
-					setup->src.operand.constant.color[2],
-					setup->src.operand.constant.color[3]);
+					setup->src.constant.color[0],
+					setup->src.constant.color[1],
+					setup->src.constant.color[2],
+					setup->src.constant.color[3]);
 	} else {
 	    glBindTexture (ctx->tex_target, ctx->dummy_tex);
 	    glActiveTexture (GL_TEXTURE1);
 	    glEnable (ctx->tex_target);
 
 	    glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,
-			setup->mask.operand.constant.color);
+			setup->mask.constant.color);
 
 	    glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_CONSTANT);
 	    glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_CONSTANT);
@@ -839,7 +839,7 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
 	}
 	break;
     case CAIRO_GL_OPERAND_TEXTURE:
-	_cairo_gl_set_texture_surface (1, setup->mask.operand.texture.tex,
+	_cairo_gl_set_texture_surface (1, setup->mask.texture.tex,
 				       mask_attributes, ctx->tex_target);
 	if (!setup->shader) {
 	    /* Set up the constant color we use to set color to 0 if needed. */
@@ -849,8 +849,8 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
 	     * alpha-only.  We may have a teximage with color bits if
 	     * the implementation doesn't support GL_ALPHA FBOs.
 	     */
-	    if (setup->mask.operand.texture.surface == NULL ||
-                setup->mask.operand.texture.surface->base.content != CAIRO_CONTENT_ALPHA)
+	    if (setup->mask.texture.surface == NULL ||
+                setup->mask.texture.surface->base.content != CAIRO_CONTENT_ALPHA)
 		glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE1);
 	    else
 		glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_CONSTANT);
@@ -883,12 +883,12 @@ _cairo_gl_set_mask_operand (cairo_gl_context_t *ctx,
     switch (setup->mask.type) {
     case CAIRO_GL_OPERAND_CONSTANT:
         _cairo_gl_set_tex_combine_constant_color (ctx, setup, 1,
-                                                  setup->mask.operand.constant.color);
+                                                  setup->mask.constant.color);
         break;
 
     case CAIRO_GL_OPERAND_TEXTURE:
-        _cairo_gl_set_texture_surface (1, setup->mask.operand.texture.tex,
-                                       &setup->mask.operand.texture.attributes,
+        _cairo_gl_set_texture_surface (1, setup->mask.texture.tex,
+                                       &setup->mask.texture.attributes,
                                        ctx->tex_target);
 
         if (! setup->shader) {
@@ -1230,7 +1230,7 @@ _cairo_gl_operand_emit (cairo_gl_operand_t *operand,
         break;
     case CAIRO_GL_OPERAND_TEXTURE:
         {
-            cairo_surface_attributes_t *src_attributes = &operand->operand.texture.attributes;
+            cairo_surface_attributes_t *src_attributes = &operand->texture.attributes;
             double s = x;
             double t = y;
 
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 2a1007e..d8bfcc4 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -180,7 +180,7 @@ typedef struct cairo_gl_operand {
 	    float radius_0;
 	    float radius_1;
 	} radial;
-    } operand;
+    };
 
     const cairo_pattern_t *pattern;
 } cairo_gl_operand_t;


More information about the cairo-commit mailing list