[cairo] [PATCH] gl: Use vertex attributes to store solid color for constant operations

Martin Robinson mrobinson at igalia.com
Wed Mar 20 12:33:08 PDT 2013


>From b23b51e4489131c41c268c7bcd98f9593cd79a83 Mon Sep 17 00:00:00 2001
From: "Alejandro G. Castro" <alex at igalia.com>
Date: Thu, 21 Feb 2013 13:01:47 -0800
Subject: [PATCH] gl: Use vertex attributes to store solid color for constant
 operations

Add a rendering mode in which constant color information is passed to
shaders via vertex attributes instead of uniforms. This allows rendering
low-vertex geometry of different colors without flushing.
---
 src/cairo-gl-composite.c        |   28 +++++++++++++++++++---------
 src/cairo-gl-msaa-compositor.c  |   10 +++++-----
 src/cairo-gl-operand.c          |   29 ++++++++++++++++++++++++-----
 src/cairo-gl-private.h          |    8 ++++++--
 src/cairo-gl-shaders.c          |   38 +++++++++++++++++++++++++++++---------
 src/cairo-gl-source.c           |    2 +-
 src/cairo-gl-spans-compositor.c |    2 +-
 src/cairo-gl-traps-compositor.c |    2 +-
 8 files changed, 86 insertions(+), 33 deletions(-)

diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index 66389ec..8cad770 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -57,11 +57,13 @@ _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,
-				cairo_bool_t use_texgen)
+				cairo_bool_t use_texgen,
+				cairo_bool_t encode_color_as_attribute)
 {
     _cairo_gl_operand_destroy (&setup->src);
     return _cairo_gl_operand_init (&setup->src, pattern, setup->dst,
-				   sample, extents, use_texgen);
+				   sample, extents, use_texgen,
+				   encode_color_as_attribute);
 }
 
 void
@@ -92,7 +94,7 @@ _cairo_gl_composite_set_mask (cairo_gl_composite_t *setup,
         return CAIRO_STATUS_SUCCESS;
 
     return _cairo_gl_operand_init (&setup->mask, pattern, setup->dst,
-				   sample, extents, use_texgen);
+				   sample, extents, use_texgen, FALSE);
 }
 
 void
@@ -241,7 +243,13 @@ _cairo_gl_context_setup_operand (cairo_gl_context_t *ctx,
         break;
         /* fall through */
     case CAIRO_GL_OPERAND_CONSTANT:
-        break;
+	if (operand->constant.encode_as_attribute) {
+	    dispatch->VertexAttribPointer (CAIRO_GL_COLOR_ATTRIB_INDEX, 4,
+					   GL_FLOAT, GL_FALSE, vertex_size,
+					   ctx->vb + vertex_offset);
+	    dispatch->EnableVertexAttribArray (CAIRO_GL_COLOR_ATTRIB_INDEX);
+	}
+	break;
     case CAIRO_GL_OPERAND_TEXTURE:
         glActiveTexture (GL_TEXTURE0 + tex_unit);
         glBindTexture (ctx->tex_target, operand->texture.tex);
@@ -285,7 +293,6 @@ _cairo_gl_context_setup_spans (cairo_gl_context_t *ctx,
     cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
 
     if (! spans_enabled) {
-	dispatch->DisableVertexAttribArray (CAIRO_GL_COLOR_ATTRIB_INDEX);
 	ctx->spans = FALSE;
 	return;
     }
@@ -314,7 +321,8 @@ _cairo_gl_context_destroy_operand (cairo_gl_context_t *ctx,
         break;
         /* fall through */
     case CAIRO_GL_OPERAND_CONSTANT:
-        break;
+	if (ctx->operands[tex_unit].constant.encode_as_attribute)
+	    dispatch->DisableVertexAttribArray (CAIRO_GL_COLOR_ATTRIB_INDEX);
     case CAIRO_GL_OPERAND_TEXTURE:
         dispatch->DisableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit);
         break;
@@ -718,12 +726,14 @@ _cairo_gl_set_operands_and_operator (cairo_gl_composite_t *setup,
 
     vertex_size_changed = _cairo_gl_composite_setup_vbo (ctx, vertex_size);
 
+    if (setup->src.type != CAIRO_GL_OPERAND_CONSTANT ||
+	! setup->src.constant.encode_as_attribute)
+	_cairo_gl_context_setup_spans (ctx, setup->spans, vertex_size,
+				       dst_size + src_size + mask_size);
+
     _cairo_gl_context_setup_operand (ctx, CAIRO_GL_TEX_SOURCE, &setup->src, dst_size, vertex_size_changed);
     _cairo_gl_context_setup_operand (ctx, CAIRO_GL_TEX_MASK, &setup->mask, dst_size + src_size, vertex_size_changed);
 
-    _cairo_gl_context_setup_spans (ctx, setup->spans, vertex_size,
-				   dst_size + src_size + mask_size);
-
     _cairo_gl_set_operator (ctx, setup->op, component_alpha);
 
     if (_cairo_gl_context_is_flushed (ctx)) {
diff --git a/src/cairo-gl-msaa-compositor.c b/src/cairo-gl-msaa-compositor.c
index 28001fe..a24f2da 100644
--- a/src/cairo-gl-msaa-compositor.c
+++ b/src/cairo-gl-msaa-compositor.c
@@ -344,7 +344,7 @@ _cairo_gl_msaa_compositor_mask_source_operator (const cairo_compositor_t *compos
 					     &composite->mask_pattern.base,
 					     &composite->mask_sample_area,
 					     &composite->bounded,
-					     FALSE);
+					     FALSE, FALSE);
     if (unlikely (status))
 	goto finish;
     _cairo_gl_composite_set_multisample (&setup);
@@ -366,7 +366,7 @@ _cairo_gl_msaa_compositor_mask_source_operator (const cairo_compositor_t *compos
 					     &composite->source_pattern.base,
 					     &composite->source_sample_area,
 					     &composite->bounded,
-					     FALSE);
+					     FALSE, FALSE);
     if (unlikely (status))
 	goto finish;
     status = _cairo_gl_composite_set_mask (&setup,
@@ -470,7 +470,7 @@ _cairo_gl_msaa_compositor_mask (const cairo_compositor_t	*compositor,
 					     &composite->source_pattern.base,
 					     &composite->source_sample_area,
 					     &composite->bounded,
-					     FALSE);
+					     FALSE, FALSE);
     if (unlikely (status))
 	goto finish;
 
@@ -684,7 +684,7 @@ _cairo_gl_msaa_compositor_stroke (const cairo_compositor_t	*compositor,
 					     &composite->source_pattern.base,
 					     &composite->source_sample_area,
 					     &composite->bounded,
-					     FALSE);
+					     FALSE, FALSE);
     if (unlikely (status))
 	goto finish;
 
@@ -804,7 +804,7 @@ _cairo_gl_msaa_compositor_fill (const cairo_compositor_t	*compositor,
 					     &composite->source_pattern.base,
 					     &composite->source_sample_area,
 					     &composite->bounded,
-					     FALSE);
+					     FALSE, ! draw_path_with_traps);
     if (unlikely (status))
 	goto cleanup_setup;
 
diff --git a/src/cairo-gl-operand.c b/src/cairo-gl-operand.c
index f99400c..04bc5dc 100644
--- a/src/cairo-gl-operand.c
+++ b/src/cairo-gl-operand.c
@@ -365,7 +365,7 @@ fail:
 
 void
 _cairo_gl_solid_operand_init (cairo_gl_operand_t *operand,
-	                      const cairo_color_t *color)
+			      const cairo_color_t *color)
 {
     operand->type = CAIRO_GL_OPERAND_CONSTANT;
     operand->constant.color[0] = color->red   * color->alpha;
@@ -548,7 +548,8 @@ _cairo_gl_operand_init (cairo_gl_operand_t *operand,
 		        cairo_gl_surface_t *dst,
 			const cairo_rectangle_int_t *sample,
 			const cairo_rectangle_int_t *extents,
-			cairo_bool_t use_texgen)
+			cairo_bool_t use_texgen,
+			cairo_bool_t encode_color_as_attribute)
 {
     cairo_int_status_t status;
 
@@ -557,6 +558,7 @@ _cairo_gl_operand_init (cairo_gl_operand_t *operand,
     case CAIRO_PATTERN_TYPE_SOLID:
 	_cairo_gl_solid_operand_init (operand,
 				      &((cairo_solid_pattern_t *) pattern)->color);
+	operand->constant.encode_as_attribute = encode_color_as_attribute;
 	return CAIRO_STATUS_SUCCESS;
     case CAIRO_PATTERN_TYPE_SURFACE:
 	status = _cairo_gl_surface_operand_init (operand, pattern, dst,
@@ -662,6 +664,9 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
 	return;
 
     case CAIRO_GL_OPERAND_CONSTANT:
+	if (operand->constant.encode_as_attribute)
+	    return;
+
         strcpy (custom_part, "_constant");
 	_cairo_gl_shader_bind_vec4 (ctx,
                                     uniform_name,
@@ -746,6 +751,12 @@ _cairo_gl_operand_needs_setup (cairo_gl_operand_t *dest,
     case CAIRO_GL_OPERAND_NONE:
         return FALSE;
     case CAIRO_GL_OPERAND_CONSTANT:
+	if (dest->constant.encode_as_attribute &&
+	    source->constant.encode_as_attribute)
+	    return FALSE;
+        if (dest->constant.encode_as_attribute !=
+	    source->constant.encode_as_attribute)
+	    return TRUE;
         return dest->constant.color[0] != source->constant.color[0] ||
                dest->constant.color[1] != source->constant.color[1] ||
                dest->constant.color[2] != source->constant.color[2] ||
@@ -778,7 +789,7 @@ _cairo_gl_operand_get_vertex_size (const cairo_gl_operand_t *operand)
         ASSERT_NOT_REACHED;
     case CAIRO_GL_OPERAND_NONE:
     case CAIRO_GL_OPERAND_CONSTANT:
-        return 0;
+        return operand->constant.encode_as_attribute ? 4 * sizeof (GLfloat) : 0;
     case CAIRO_GL_OPERAND_TEXTURE:
         return operand->texture.texgen ? 0 : 2 * sizeof (GLfloat);
     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
@@ -800,8 +811,16 @@ _cairo_gl_operand_emit (cairo_gl_operand_t *operand,
     case CAIRO_GL_OPERAND_COUNT:
         ASSERT_NOT_REACHED;
     case CAIRO_GL_OPERAND_NONE:
-    case CAIRO_GL_OPERAND_CONSTANT:
-        break;
+	break;
+    case CAIRO_GL_OPERAND_CONSTANT: {
+	if (operand->constant.encode_as_attribute) {
+	    *(*vb)++ = operand->constant.color[0];
+	    *(*vb)++ = operand->constant.color[1];
+	    *(*vb)++ = operand->constant.color[2];
+	    *(*vb)++ = operand->constant.color[3];
+	}
+	break;
+    }
     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 5c9193d..4487e28 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -140,6 +140,7 @@ typedef struct cairo_gl_operand {
 	} texture;
 	struct {
 	    GLfloat color[4];
+	    cairo_bool_t encode_as_attribute;
 	} constant;
 	struct {
 	    cairo_gl_gradient_t *gradient;
@@ -215,6 +216,7 @@ typedef enum cairo_gl_var_type {
   CAIRO_GL_VAR_NONE,
   CAIRO_GL_VAR_TEXCOORDS,
   CAIRO_GL_VAR_TEXGEN,
+  CAIRO_GL_VAR_COLOR,
 } cairo_gl_var_type_t;
 
 typedef enum cairo_gl_primitive_type {
@@ -549,7 +551,8 @@ _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,
-				cairo_bool_t use_texgen);
+				cairo_bool_t use_texgen,
+				cairo_bool_t encode_color_as_attribute);
 
 cairo_private void
 _cairo_gl_composite_set_solid_source (cairo_gl_composite_t *setup,
@@ -704,7 +707,8 @@ _cairo_gl_operand_init (cairo_gl_operand_t *operand,
 		        cairo_gl_surface_t *dst,
 			const cairo_rectangle_int_t *sample,
 			const cairo_rectangle_int_t *extents,
-			cairo_bool_t use_texgen);
+			cairo_bool_t use_texgen,
+			cairo_bool_t encode_color_as_attribute);
 
 cairo_private void
 _cairo_gl_solid_operand_init (cairo_gl_operand_t *operand,
diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c
index d8de712..0bfce66 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -228,7 +228,10 @@ cairo_gl_operand_get_var_type (cairo_gl_operand_t *operand)
         ASSERT_NOT_REACHED;
     case CAIRO_GL_OPERAND_NONE:
     case CAIRO_GL_OPERAND_CONSTANT:
-        return CAIRO_GL_VAR_NONE;
+	if (operand->constant.encode_as_attribute)
+	    return CAIRO_GL_VAR_COLOR;
+	else
+	    return CAIRO_GL_VAR_NONE;
     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
@@ -263,6 +266,10 @@ cairo_gl_shader_emit_variable (cairo_output_stream_t *stream,
                                      operand_names[name],
                                      operand_names[name]);
         break;
+    case CAIRO_GL_VAR_COLOR:
+        _cairo_output_stream_printf (stream,
+				     "varying vec4 fragment_color;\n");
+        break;
     }
 }
 
@@ -286,6 +293,9 @@ cairo_gl_shader_emit_vertex (cairo_output_stream_t *stream,
         _cairo_output_stream_printf (stream,
 				     "    %s_texcoords = (%s_texgen * Vertex.xyw).xy;\n",
                                      operand_names[name], operand_names[name]);
+	break;
+    case CAIRO_GL_VAR_COLOR:
+        _cairo_output_stream_printf (stream, "    fragment_color = Color;\n");
         break;
     }
 }
@@ -382,14 +392,24 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream,
             namestr);
         break;
     case CAIRO_GL_OPERAND_CONSTANT:
-        _cairo_output_stream_printf (stream, 
-            "uniform vec4 %s_constant;\n"
-            "vec4 get_%s()\n"
-            "{\n"
-            "    return %s_constant;\n"
-            "}\n",
-            namestr, namestr, namestr);
-        break;
+	if (op->constant.encode_as_attribute) {
+	     _cairo_output_stream_printf (stream,
+		"varying vec4 fragment_color;\n"
+		"vec4 get_%s()\n"
+		"{\n"
+		"    return fragment_color;\n"
+		"}\n",
+		namestr);
+	} else {
+	    _cairo_output_stream_printf (stream,
+		"uniform vec4 %s_constant;\n"
+		"vec4 get_%s()\n"
+		"{\n"
+		"    return %s_constant;\n"
+		"}\n",
+		namestr, namestr, namestr);
+	}
+	    break;
     case CAIRO_GL_OPERAND_TEXTURE:
 	_cairo_output_stream_printf (stream,
 	     "uniform sampler2D%s %s_sampler;\n"
diff --git a/src/cairo-gl-source.c b/src/cairo-gl-source.c
index 1223529..53c3ed3 100644
--- a/src/cairo-gl-source.c
+++ b/src/cairo-gl-source.c
@@ -82,7 +82,7 @@ _cairo_gl_pattern_to_source (cairo_surface_t *dst,
     status = _cairo_gl_operand_init (&source->operand, pattern,
 				     (cairo_gl_surface_t *)dst,
 				     sample, extents,
-				     FALSE);
+				     FALSE, 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 4317ccd..bd93e9c 100644
--- a/src/cairo-gl-spans-compositor.c
+++ b/src/cairo-gl-spans-compositor.c
@@ -462,7 +462,7 @@ _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,
-					     TRUE);
+					     TRUE, FALSE);
     if (unlikely (status))
         goto FAIL;
 
diff --git a/src/cairo-gl-traps-compositor.c b/src/cairo-gl-traps-compositor.c
index 548162b..8cc35a7 100644
--- a/src/cairo-gl-traps-compositor.c
+++ b/src/cairo-gl-traps-compositor.c
@@ -361,7 +361,7 @@ traps_to_operand (void *_dst,
     status = _cairo_gl_operand_init (operand, &pattern.base, _dst,
 				     &_cairo_unbounded_rectangle,
 				     &_cairo_unbounded_rectangle,
-				     FALSE);
+				     FALSE, FALSE);
     _cairo_pattern_fini (&pattern.base);
 
     if (unlikely (status))
-- 
1.7.10.4



More information about the cairo mailing list