[cairo-commit] src/cairo-gl-composite.c src/cairo-gl-msaa-compositor.c src/cairo-gl-operand.c src/cairo-gl-private.h src/cairo-gl-shaders.c src/cairo-gl-source.c src/cairo-gl-spans-compositor.c src/cairo-gl-traps-compositor.c

Chris Wilson ickle at kemper.freedesktop.org
Mon Feb 4 02:01:38 PST 2013


 src/cairo-gl-composite.c        |   70 +++++++++++++++++++++++++++++-----------
 src/cairo-gl-msaa-compositor.c  |   21 ++++++++----
 src/cairo-gl-operand.c          |   67 ++++++++++++++++++++++++++++----------
 src/cairo-gl-private.h          |   24 ++++++++-----
 src/cairo-gl-shaders.c          |   31 +++++++++++++----
 src/cairo-gl-source.c           |    3 +
 src/cairo-gl-spans-compositor.c |    6 ++-
 src/cairo-gl-traps-compositor.c |    3 +
 8 files changed, 162 insertions(+), 63 deletions(-)

New commits:
commit 05ad89f91241b386f72f5b9bac3ebe62faff1d1b
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Feb 3 16:51:35 2013 +0000

    gl: Replace manual vertex transformation with VS computation of texcoords
    
    Not only is our point transformation code is quite slow (well at least
    compared to a real GPU), but by deriving the texture coordinates from
    the vertex position we can elide the multiple arrays that we need to
    construct and pass to GL - improving performance by eliminating CPU
    overhead from needless transforms and data shovelling.
    
    However, not all vertex emission is suitable. For instance, for glyphs
    we need to emit discontiguous texture coordinates for each glyph, but
    span generation is suitable - which fortuitously also has the largest
    vertex density and so benefits the most.
    
    The only real concern is for hardware without true vertex shader support
    (e.g. i915) but there we are already invoking the VS to transform the
    vertex into the viewport. We would need to eliminate that transform as
    well as manually compute the texture coordinates in order to eliminate
    the vertex recomputation pass.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index d8166b8..c250e72 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -56,11 +56,12 @@ cairo_int_status_t
 _cairo_gl_composite_set_source (cairo_gl_composite_t *setup,
 			        const cairo_pattern_t *pattern,
 				const cairo_rectangle_int_t *sample,
-				const cairo_rectangle_int_t *extents)
+				const cairo_rectangle_int_t *extents,
+				cairo_bool_t use_texgen)
 {
     _cairo_gl_operand_destroy (&setup->src);
     return _cairo_gl_operand_init (&setup->src, pattern, setup->dst,
-				   sample, extents);
+				   sample, extents, use_texgen);
 }
 
 void
@@ -83,14 +84,15 @@ cairo_int_status_t
 _cairo_gl_composite_set_mask (cairo_gl_composite_t *setup,
 			      const cairo_pattern_t *pattern,
 			      const cairo_rectangle_int_t *sample,
-			      const cairo_rectangle_int_t *extents)
+			      const cairo_rectangle_int_t *extents,
+			      cairo_bool_t use_texgen)
 {
     _cairo_gl_operand_destroy (&setup->mask);
     if (pattern == NULL)
         return CAIRO_STATUS_SUCCESS;
 
     return _cairo_gl_operand_init (&setup->mask, pattern, setup->dst,
-				   sample, extents);
+				   sample, extents, use_texgen);
 }
 
 void
@@ -248,10 +250,12 @@ _cairo_gl_context_setup_operand (cairo_gl_context_t *ctx,
         _cairo_gl_texture_set_filter (ctx, ctx->tex_target,
                                       operand->texture.attributes.filter);
 
-	dispatch->VertexAttribPointer (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit, 2,
-					GL_FLOAT, GL_FALSE, vertex_size,
-					ctx->vb + vertex_offset);
-	dispatch->EnableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit);
+	if (! operand->texture.texgen) {
+	    dispatch->VertexAttribPointer (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit, 2,
+					   GL_FLOAT, GL_FALSE, vertex_size,
+					   ctx->vb + vertex_offset);
+	    dispatch->EnableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit);
+	}
         break;
     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
@@ -262,10 +266,12 @@ _cairo_gl_context_setup_operand (cairo_gl_context_t *ctx,
         _cairo_gl_texture_set_extend (ctx, ctx->tex_target, operand->gradient.extend);
         _cairo_gl_texture_set_filter (ctx, ctx->tex_target, CAIRO_FILTER_BILINEAR);
 
-	dispatch->VertexAttribPointer (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit, 2,
-				       GL_FLOAT, GL_FALSE, vertex_size,
-				       ctx->vb + vertex_offset);
-	dispatch->EnableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit);
+	if (! operand->gradient.texgen) {
+	    dispatch->VertexAttribPointer (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit, 2,
+					   GL_FLOAT, GL_FALSE, vertex_size,
+					   ctx->vb + vertex_offset);
+	    dispatch->EnableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit);
+	}
 	break;
     }
 }
@@ -698,8 +704,8 @@ _cairo_gl_set_operands_and_operator (cairo_gl_composite_t *setup,
     status = CAIRO_STATUS_SUCCESS;
 
     dst_size = 2 * sizeof (GLfloat);
-    src_size = _cairo_gl_operand_get_vertex_size (setup->src.type);
-    mask_size = _cairo_gl_operand_get_vertex_size (setup->mask.type);
+    src_size = _cairo_gl_operand_get_vertex_size (&setup->src);
+    mask_size = _cairo_gl_operand_get_vertex_size (&setup->mask);
     vertex_size = dst_size + src_size + mask_size;
 
     if (setup->spans)
@@ -993,8 +999,29 @@ _cairo_gl_composite_emit_solid_span (cairo_gl_context_t *ctx,
 cairo_gl_emit_span_t
 _cairo_gl_context_choose_emit_span (cairo_gl_context_t *ctx)
 {
-    if (ctx->operands[CAIRO_GL_TEX_MASK].type != CAIRO_GL_OPERAND_NONE)
-	return _cairo_gl_composite_emit_span;
+    if (ctx->operands[CAIRO_GL_TEX_MASK].type != CAIRO_GL_OPERAND_NONE) {
+	    switch (ctx->operands[CAIRO_GL_TEX_MASK].type) {
+	    default:
+	    case CAIRO_GL_OPERAND_COUNT:
+		    ASSERT_NOT_REACHED;
+	    case CAIRO_GL_OPERAND_NONE:
+	    case CAIRO_GL_OPERAND_CONSTANT:
+		    break;
+
+	    case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
+	    case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
+	    case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
+	    case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
+		    if (!ctx->operands[CAIRO_GL_TEX_MASK].gradient.texgen)
+			    return _cairo_gl_composite_emit_span;
+		    break;
+
+	    case CAIRO_GL_OPERAND_TEXTURE:
+		    if (!ctx->operands[CAIRO_GL_TEX_MASK].texture.texgen)
+			    return _cairo_gl_composite_emit_span;
+		    break;
+	    }
+    }
 
     switch (ctx->operands[CAIRO_GL_TEX_SOURCE].type) {
     default:
@@ -1002,15 +1029,22 @@ _cairo_gl_context_choose_emit_span (cairo_gl_context_t *ctx)
         ASSERT_NOT_REACHED;
     case CAIRO_GL_OPERAND_NONE:
     case CAIRO_GL_OPERAND_CONSTANT:
-	return _cairo_gl_composite_emit_solid_span;
+	break;
 
     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
+	if (!ctx->operands[CAIRO_GL_TEX_SOURCE].gradient.texgen)
+		return _cairo_gl_composite_emit_span;
+	break;
+
     case CAIRO_GL_OPERAND_TEXTURE:
-	return _cairo_gl_composite_emit_span;
+	if (!ctx->operands[CAIRO_GL_TEX_SOURCE].texture.texgen)
+		return _cairo_gl_composite_emit_span;
     }
+
+    return _cairo_gl_composite_emit_solid_span;
 }
 
 static inline void
diff --git a/src/cairo-gl-msaa-compositor.c b/src/cairo-gl-msaa-compositor.c
index 54772ef..a0fd9a0 100644
--- a/src/cairo-gl-msaa-compositor.c
+++ b/src/cairo-gl-msaa-compositor.c
@@ -343,7 +343,8 @@ _cairo_gl_msaa_compositor_mask_source_operator (const cairo_compositor_t *compos
     status = _cairo_gl_composite_set_source (&setup,
 					     &composite->mask_pattern.base,
 					     &composite->mask_sample_area,
-					     &composite->bounded);
+					     &composite->bounded,
+					     FALSE);
     if (unlikely (status))
 	goto finish;
     _cairo_gl_composite_set_multisample (&setup);
@@ -364,13 +365,15 @@ _cairo_gl_msaa_compositor_mask_source_operator (const cairo_compositor_t *compos
     status = _cairo_gl_composite_set_source (&setup,
 					     &composite->source_pattern.base,
 					     &composite->source_sample_area,
-					     &composite->bounded);
+					     &composite->bounded,
+					     FALSE);
     if (unlikely (status))
 	goto finish;
     status = _cairo_gl_composite_set_mask (&setup,
 				           &composite->mask_pattern.base,
 					   &composite->source_sample_area,
-					   &composite->bounded);
+					   &composite->bounded,
+					   FALSE);
     if (unlikely (status))
 	goto finish;
     status = _cairo_gl_set_operands_and_operator (&setup, ctx);
@@ -462,7 +465,8 @@ _cairo_gl_msaa_compositor_mask (const cairo_compositor_t	*compositor,
     status = _cairo_gl_composite_set_source (&setup,
 					     &composite->source_pattern.base,
 					     &composite->source_sample_area,
-					     &composite->bounded);
+					     &composite->bounded,
+					     FALSE);
     if (unlikely (status))
 	goto finish;
 
@@ -470,7 +474,8 @@ _cairo_gl_msaa_compositor_mask (const cairo_compositor_t	*compositor,
 	status = _cairo_gl_composite_set_mask (&setup,
 					       &composite->mask_pattern.base,
 					       &composite->mask_sample_area,
-					       &composite->bounded);
+					       &composite->bounded,
+					       FALSE);
     }
     if (unlikely (status))
 	goto finish;
@@ -674,7 +679,8 @@ _cairo_gl_msaa_compositor_stroke (const cairo_compositor_t	*compositor,
     status = _cairo_gl_composite_set_source (&info.setup,
 					     &composite->source_pattern.base,
 					     &composite->source_sample_area,
-					     &composite->bounded);
+					     &composite->bounded,
+					     FALSE);
     if (unlikely (status))
 	goto finish;
 
@@ -793,7 +799,8 @@ _cairo_gl_msaa_compositor_fill (const cairo_compositor_t	*compositor,
     status = _cairo_gl_composite_set_source (&setup,
 					     &composite->source_pattern.base,
 					     &composite->source_sample_area,
-					     &composite->bounded);
+					     &composite->bounded,
+					     FALSE);
     if (unlikely (status))
 	goto cleanup_setup;
 
diff --git a/src/cairo-gl-operand.c b/src/cairo-gl-operand.c
index 1951266..f99400c 100644
--- a/src/cairo-gl-operand.c
+++ b/src/cairo-gl-operand.c
@@ -107,7 +107,8 @@ _cairo_gl_subsurface_clone_operand_init (cairo_gl_operand_t *operand,
 					 const cairo_pattern_t *_src,
 					 cairo_gl_surface_t *dst,
 					 const cairo_rectangle_int_t *sample,
-					 const cairo_rectangle_int_t *extents)
+					 const cairo_rectangle_int_t *extents,
+					 cairo_bool_t use_texgen)
 {
     const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src;
     cairo_surface_pattern_t local_pattern;
@@ -185,6 +186,8 @@ _cairo_gl_subsurface_clone_operand_init (cairo_gl_operand_t *operand,
     attributes->extend = src->base.extend;
     attributes->filter = src->base.filter;
     attributes->has_component_alpha = src->base.has_component_alpha;
+
+    operand->texture.texgen = use_texgen;
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -193,7 +196,8 @@ _cairo_gl_subsurface_operand_init (cairo_gl_operand_t *operand,
 				   const cairo_pattern_t *_src,
 				   cairo_gl_surface_t *dst,
 				   const cairo_rectangle_int_t *sample,
-				   const cairo_rectangle_int_t *extents)
+				   const cairo_rectangle_int_t *extents,
+				   cairo_bool_t use_texgen)
 {
     const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src;
     cairo_surface_subsurface_t *sub;
@@ -208,7 +212,8 @@ _cairo_gl_subsurface_operand_init (cairo_gl_operand_t *operand,
 	sample->y + sample->height > sub->extents.height)
     {
 	return _cairo_gl_subsurface_clone_operand_init (operand, _src,
-							dst, sample, extents);
+							dst, sample, extents,
+							use_texgen);
     }
 
     surface = (cairo_gl_surface_t *) sub->target;
@@ -239,6 +244,8 @@ _cairo_gl_subsurface_operand_init (cairo_gl_operand_t *operand,
     attributes->extend = src->base.extend;
     attributes->filter = src->base.filter;
     attributes->has_component_alpha = src->base.has_component_alpha;
+
+    operand->texture.texgen = use_texgen;
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -247,7 +254,8 @@ _cairo_gl_surface_operand_init (cairo_gl_operand_t *operand,
 				const cairo_pattern_t *_src,
 				cairo_gl_surface_t *dst,
 				const cairo_rectangle_int_t *sample,
-				const cairo_rectangle_int_t *extents)
+				const cairo_rectangle_int_t *extents,
+				cairo_bool_t use_texgen)
 {
     const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src;
     cairo_gl_surface_t *surface;
@@ -261,7 +269,8 @@ _cairo_gl_surface_operand_init (cairo_gl_operand_t *operand,
     if (surface->base.backend->type != CAIRO_SURFACE_TYPE_GL) {
 	if (_cairo_surface_is_subsurface (&surface->base))
 	    return _cairo_gl_subsurface_operand_init (operand, _src, dst,
-						      sample, extents);
+						      sample, extents,
+						      use_texgen);
 
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
@@ -286,6 +295,8 @@ _cairo_gl_surface_operand_init (cairo_gl_operand_t *operand,
     attributes->extend = src->base.extend;
     attributes->filter = src->base.filter;
     attributes->has_component_alpha = src->base.has_component_alpha;
+
+    operand->texture.texgen = use_texgen;
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -392,7 +403,8 @@ _cairo_gl_operand_translate (cairo_gl_operand_t *operand,
 static cairo_status_t
 _cairo_gl_gradient_operand_init (cairo_gl_operand_t *operand,
                                  const cairo_pattern_t *pattern,
-				 cairo_gl_surface_t *dst)
+				 cairo_gl_surface_t *dst,
+				 cairo_bool_t use_texgen)
 {
     const cairo_gradient_pattern_t *gradient = (const cairo_gradient_pattern_t *)pattern;
     cairo_status_t status;
@@ -475,6 +487,7 @@ _cairo_gl_gradient_operand_init (cairo_gl_operand_t *operand,
     }
 
     operand->gradient.extend = pattern->extend;
+    operand->gradient.texgen = use_texgen;
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -534,7 +547,8 @@ _cairo_gl_operand_init (cairo_gl_operand_t *operand,
 		        const cairo_pattern_t *pattern,
 		        cairo_gl_surface_t *dst,
 			const cairo_rectangle_int_t *sample,
-			const cairo_rectangle_int_t *extents)
+			const cairo_rectangle_int_t *extents,
+			cairo_bool_t use_texgen)
 {
     cairo_int_status_t status;
 
@@ -546,7 +560,7 @@ _cairo_gl_operand_init (cairo_gl_operand_t *operand,
 	return CAIRO_STATUS_SUCCESS;
     case CAIRO_PATTERN_TYPE_SURFACE:
 	status = _cairo_gl_surface_operand_init (operand, pattern, dst,
-						 sample, extents);
+						 sample, extents, use_texgen);
 	if (status == CAIRO_INT_STATUS_UNSUPPORTED)
 	    break;
 
@@ -554,7 +568,8 @@ _cairo_gl_operand_init (cairo_gl_operand_t *operand,
 
     case CAIRO_PATTERN_TYPE_LINEAR:
     case CAIRO_PATTERN_TYPE_RADIAL:
-	status = _cairo_gl_gradient_operand_init (operand, pattern, dst);
+	status = _cairo_gl_gradient_operand_init (operand, pattern, dst,
+						  use_texgen);
 	if (status == CAIRO_INT_STATUS_UNSUPPORTED)
 	    break;
 
@@ -634,6 +649,7 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
     char uniform_name[50];
     char *custom_part;
     static const char *names[] = { "source", "mask" };
+    const cairo_matrix_t *texgen = NULL;
 
     strcpy (uniform_name, names[tex_unit]);
     custom_part = uniform_name + strlen (names[tex_unit]);
@@ -643,7 +659,8 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
     case CAIRO_GL_OPERAND_COUNT:
         ASSERT_NOT_REACHED;
     case CAIRO_GL_OPERAND_NONE:
-        break;
+	return;
+
     case CAIRO_GL_OPERAND_CONSTANT:
         strcpy (custom_part, "_constant");
 	_cairo_gl_shader_bind_vec4 (ctx,
@@ -652,7 +669,8 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
                                     operand->constant.color[1],
                                     operand->constant.color[2],
                                     operand->constant.color[3]);
-        break;
+	return;
+
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
 	strcpy (custom_part, "_a");
@@ -695,7 +713,21 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
 	    strcpy (custom_part, "_texdims");
 	    _cairo_gl_shader_bind_vec2 (ctx, uniform_name, width, height);
 	}
-        break;
+	break;
+    }
+
+    if (operand->type == CAIRO_GL_OPERAND_TEXTURE) {
+	    if (operand->texture.texgen)
+		    texgen = &operand->texture.attributes.matrix;
+    } else {
+	    if (operand->gradient.texgen)
+		    texgen = &operand->gradient.m;
+    }
+    if (texgen) {
+	    char name[20];
+
+	    sprintf (name, "%s_texgen", names[tex_unit]);
+	    _cairo_gl_shader_bind_matrix(ctx, name, texgen);
     }
 }
 
@@ -738,9 +770,9 @@ _cairo_gl_operand_needs_setup (cairo_gl_operand_t *dest,
 }
 
 unsigned int
-_cairo_gl_operand_get_vertex_size (cairo_gl_operand_type_t type)
+_cairo_gl_operand_get_vertex_size (const cairo_gl_operand_t *operand)
 {
-    switch (type) {
+    switch (operand->type) {
     default:
     case CAIRO_GL_OPERAND_COUNT:
         ASSERT_NOT_REACHED;
@@ -748,11 +780,12 @@ _cairo_gl_operand_get_vertex_size (cairo_gl_operand_type_t type)
     case CAIRO_GL_OPERAND_CONSTANT:
         return 0;
     case CAIRO_GL_OPERAND_TEXTURE:
+        return operand->texture.texgen ? 0 : 2 * sizeof (GLfloat);
     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
-        return 2 * sizeof (GLfloat);
+        return operand->gradient.texgen ? 0 : 2 * sizeof (GLfloat);
     }
 }
 
@@ -773,7 +806,7 @@ _cairo_gl_operand_emit (cairo_gl_operand_t *operand,
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
-        {
+	if (! operand->gradient.texgen) {
 	    double s = x;
 	    double t = y;
 
@@ -784,7 +817,7 @@ _cairo_gl_operand_emit (cairo_gl_operand_t *operand,
         }
 	break;
     case CAIRO_GL_OPERAND_TEXTURE:
-        {
+	if (! operand->texture.texgen) {
             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 a75afa7..2b254f9 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -136,6 +136,7 @@ typedef struct cairo_gl_operand {
 	    cairo_gl_surface_t *surface;
 	    cairo_gl_surface_t *owns_surface;
 	    cairo_surface_attributes_t attributes;
+	    int texgen;
 	} texture;
 	struct {
 	    GLfloat color[4];
@@ -146,6 +147,7 @@ typedef struct cairo_gl_operand {
 	    cairo_circle_double_t circle_d;
 	    double radius_0, a;
 	    cairo_extend_t extend;
+	    int texgen;
 	} gradient;
     };
     unsigned int vertex_offset;
@@ -212,6 +214,7 @@ typedef enum cairo_gl_shader_in {
 typedef enum cairo_gl_var_type {
   CAIRO_GL_VAR_NONE,
   CAIRO_GL_VAR_TEXCOORDS,
+  CAIRO_GL_VAR_TEXGEN,
 } cairo_gl_var_type_t;
 
 typedef enum cairo_gl_primitive_type {
@@ -234,8 +237,8 @@ typedef void (*cairo_gl_emit_glyph_t) (cairo_gl_context_t *ctx,
 				       GLfloat glyph_x1, GLfloat glyph_y1,
 				       GLfloat glyph_x2, GLfloat glyph_y2);
 
-#define cairo_gl_var_type_hash(src,mask,spans,dest) ((spans) << 3) | ((mask) << 2 | (src << 1) | (dest))
-#define CAIRO_GL_VAR_TYPE_MAX ((CAIRO_GL_VAR_TEXCOORDS << 3) | (CAIRO_GL_VAR_TEXCOORDS << 2) | (CAIRO_GL_VAR_TEXCOORDS << 1) | CAIRO_GL_VAR_TEXCOORDS)
+#define cairo_gl_var_type_hash(src,mask,spans,dest) ((spans) << 5) | ((mask) << 3 | (src << 1) | (dest))
+#define CAIRO_GL_VAR_TYPE_MAX (1 << 6)
 
 typedef void (*cairo_gl_generic_func_t)(void);
 typedef cairo_gl_generic_func_t (*cairo_gl_get_proc_addr_func_t)(const char *procname);
@@ -334,7 +337,7 @@ struct _cairo_gl_context {
 
     cairo_bool_t has_shader_support;
 
-    GLuint vertex_shaders[CAIRO_GL_VAR_TYPE_MAX + 1];
+    GLuint vertex_shaders[CAIRO_GL_VAR_TYPE_MAX];
     cairo_gl_shader_t fill_rectangles_shader;
     cairo_cache_t shaders;
 
@@ -542,9 +545,10 @@ _cairo_gl_composite_set_clip(cairo_gl_composite_t *setup,
 
 cairo_private cairo_int_status_t
 _cairo_gl_composite_set_source (cairo_gl_composite_t *setup,
-			        const cairo_pattern_t *pattern,
+				const cairo_pattern_t *pattern,
 				const cairo_rectangle_int_t *sample,
-				const cairo_rectangle_int_t *extents);
+				const cairo_rectangle_int_t *extents,
+				cairo_bool_t use_texgen);
 
 cairo_private void
 _cairo_gl_composite_set_solid_source (cairo_gl_composite_t *setup,
@@ -558,7 +562,8 @@ cairo_private cairo_int_status_t
 _cairo_gl_composite_set_mask (cairo_gl_composite_t *setup,
 			      const cairo_pattern_t *pattern,
 			      const cairo_rectangle_int_t *sample,
-			      const cairo_rectangle_int_t *extents);
+			      const cairo_rectangle_int_t *extents,
+			      cairo_bool_t use_texgen);
 
 cairo_private void
 _cairo_gl_composite_set_mask_operand (cairo_gl_composite_t *setup,
@@ -665,7 +670,7 @@ _cairo_gl_shader_bind_vec4 (cairo_gl_context_t *ctx,
 cairo_private void
 _cairo_gl_shader_bind_matrix (cairo_gl_context_t *ctx,
 			      const char *name,
-			      cairo_matrix_t* m);
+			      const cairo_matrix_t* m);
 
 cairo_private void
 _cairo_gl_shader_bind_matrix4f (cairo_gl_context_t *ctx,
@@ -697,7 +702,8 @@ _cairo_gl_operand_init (cairo_gl_operand_t *operand,
 		        const cairo_pattern_t *pattern,
 		        cairo_gl_surface_t *dst,
 			const cairo_rectangle_int_t *sample,
-			const cairo_rectangle_int_t *extents);
+			const cairo_rectangle_int_t *extents,
+			cairo_bool_t use_texgen);
 
 cairo_private void
 _cairo_gl_solid_operand_init (cairo_gl_operand_t *operand,
@@ -713,7 +719,7 @@ cairo_private cairo_extend_t
 _cairo_gl_operand_get_extend (cairo_gl_operand_t *operand);
 
 cairo_private unsigned int
-_cairo_gl_operand_get_vertex_size (cairo_gl_operand_type_t type);
+_cairo_gl_operand_get_vertex_size (const cairo_gl_operand_t *operand);
 
 cairo_private cairo_bool_t
 _cairo_gl_operand_needs_setup (cairo_gl_operand_t *dest,
diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c
index 41672d6..ae2977c 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -215,9 +215,9 @@ _cairo_gl_shader_fini (cairo_gl_context_t *ctx,
 static const char *operand_names[] = { "source", "mask", "dest" };
 
 static cairo_gl_var_type_t
-cairo_gl_operand_get_var_type (cairo_gl_operand_type_t type)
+cairo_gl_operand_get_var_type (cairo_gl_operand_t *operand)
 {
-    switch (type) {
+    switch (operand->type) {
     default:
     case CAIRO_GL_OPERAND_COUNT:
         ASSERT_NOT_REACHED;
@@ -228,8 +228,9 @@ cairo_gl_operand_get_var_type (cairo_gl_operand_type_t type)
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
+        return operand->gradient.texgen ? CAIRO_GL_VAR_TEXGEN : CAIRO_GL_VAR_TEXCOORDS;
     case CAIRO_GL_OPERAND_TEXTURE:
-        return CAIRO_GL_VAR_TEXCOORDS;
+        return operand->texture.texgen ? CAIRO_GL_VAR_TEXGEN : CAIRO_GL_VAR_TEXCOORDS;
     }
 }
 
@@ -245,7 +246,16 @@ cairo_gl_shader_emit_variable (cairo_output_stream_t *stream,
         break;
     case CAIRO_GL_VAR_TEXCOORDS:
         _cairo_output_stream_printf (stream,
+				     "attribute vec4 MultiTexCoord%d;\n"
+                                     "varying vec2 %s_texcoords;\n",
+                                     name,
+                                     operand_names[name]);
+        break;
+    case CAIRO_GL_VAR_TEXGEN:
+        _cairo_output_stream_printf (stream,
+				     "uniform mat3 %s_texgen;\n"
                                      "varying vec2 %s_texcoords;\n",
+                                     operand_names[name],
                                      operand_names[name]);
         break;
     }
@@ -266,6 +276,12 @@ cairo_gl_shader_emit_vertex (cairo_output_stream_t *stream,
                                      "    %s_texcoords = MultiTexCoord%d.xy;\n",
                                      operand_names[name], name);
         break;
+
+    case CAIRO_GL_VAR_TEXGEN:
+        _cairo_output_stream_printf (stream,
+				     "    %s_texcoords = (%s_texgen * Vertex.xyw).xy;\n",
+                                     operand_names[name], operand_names[name]);
+        break;
     }
 }
 
@@ -301,8 +317,6 @@ cairo_gl_shader_get_vertex_source (cairo_gl_var_type_t src,
     _cairo_output_stream_printf (stream,
 				 "attribute vec4 Vertex;\n"
 				 "attribute vec4 Color;\n"
-				 "attribute vec4 MultiTexCoord0;\n"
-				 "attribute vec4 MultiTexCoord1;\n"
 				 "uniform mat4 ModelViewProjectionMatrix;\n"
 				 "void main()\n"
 				 "{\n"
@@ -920,7 +934,8 @@ _cairo_gl_shader_bind_vec4 (cairo_gl_context_t *ctx,
 
 void
 _cairo_gl_shader_bind_matrix (cairo_gl_context_t *ctx,
-			      const char *name, cairo_matrix_t* m)
+			      const char *name,
+			      const cairo_matrix_t* m)
 {
     cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
     GLint location = dispatch->GetUniformLocation (ctx->current_shader->program,
@@ -1016,8 +1031,8 @@ _cairo_gl_get_shader_by_type (cairo_gl_context_t *ctx,
     _cairo_gl_shader_init (&entry->shader);
     status = _cairo_gl_shader_compile_and_link (ctx,
 						&entry->shader,
-						cairo_gl_operand_get_var_type (source->type),
-						cairo_gl_operand_get_var_type (mask->type),
+						cairo_gl_operand_get_var_type (source),
+						cairo_gl_operand_get_var_type (mask),
 						use_coverage,
 						fs_source);
     free (fs_source);
diff --git a/src/cairo-gl-source.c b/src/cairo-gl-source.c
index 294f6f9..1223529 100644
--- a/src/cairo-gl-source.c
+++ b/src/cairo-gl-source.c
@@ -81,7 +81,8 @@ _cairo_gl_pattern_to_source (cairo_surface_t *dst,
     *src_x = *src_y = 0;
     status = _cairo_gl_operand_init (&source->operand, pattern,
 				     (cairo_gl_surface_t *)dst,
-				     sample, extents);
+				     sample, extents,
+				     FALSE);
     if (unlikely (status)) {
 	cairo_surface_destroy (&source->base);
 	return _cairo_surface_create_in_error (status);
diff --git a/src/cairo-gl-spans-compositor.c b/src/cairo-gl-spans-compositor.c
index 98efd46..92e5779 100644
--- a/src/cairo-gl-spans-compositor.c
+++ b/src/cairo-gl-spans-compositor.c
@@ -454,7 +454,8 @@ _cairo_gl_span_renderer_init (cairo_abstract_span_renderer_t	*_r,
 
     status = _cairo_gl_composite_set_source (&r->setup, source,
 					     &composite->source_sample_area,
-					     &composite->unbounded);
+					     &composite->unbounded,
+					     TRUE);
     if (unlikely (status))
         goto FAIL;
 
@@ -465,7 +466,8 @@ _cairo_gl_span_renderer_init (cairo_abstract_span_renderer_t	*_r,
 	status = _cairo_gl_composite_set_mask (&r->setup,
 					       &composite->mask_pattern.base,
 					       &composite->mask_sample_area,
-					       &composite->unbounded);
+					       &composite->unbounded,
+					       TRUE);
 	if (unlikely (status))
 	    goto FAIL;
     }
diff --git a/src/cairo-gl-traps-compositor.c b/src/cairo-gl-traps-compositor.c
index b6c2333..9589ffc 100644
--- a/src/cairo-gl-traps-compositor.c
+++ b/src/cairo-gl-traps-compositor.c
@@ -358,7 +358,8 @@ traps_to_operand (void *_dst,
     pattern.base.extend = CAIRO_EXTEND_NONE;
     status = _cairo_gl_operand_init (operand, &pattern.base, _dst,
 				     &_cairo_unbounded_rectangle,
-				     &_cairo_unbounded_rectangle);
+				     &_cairo_unbounded_rectangle,
+				     FALSE);
     _cairo_pattern_fini (&pattern.base);
 
     if (unlikely (status))


More information about the cairo-commit mailing list