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

Martin Robinson <[email protected]>
Newsgroups gmane.comp.lib.cairo
Message-ID <[email protected]>
From b23b51e4489131c41c268c7bcd98f9593cd79a83 Mon Sep 17 00:00:00 2001
From: "Alejandro G. Castro" <[email protected]>
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

-- 
cairo mailing list
[email protected]
http://lists.cairographics.org/mailman/listinfo/cairo
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.