[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