[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