diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2013-02-03 16:51:35 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2013-02-04 09:57:53 +0000 |
commit | 05ad89f91241b386f72f5b9bac3ebe62faff1d1b (patch) | |
tree | 556a6b823e1c35af5759964542868f6666ac4837 | |
parent | d15a71f128c73ce1da19e6ff5a4e2fe044b58749 (diff) |
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@chris-wilson.co.uk>
-rw-r--r-- | src/cairo-gl-composite.c | 70 | ||||
-rw-r--r-- | src/cairo-gl-msaa-compositor.c | 21 | ||||
-rw-r--r-- | src/cairo-gl-operand.c | 67 | ||||
-rw-r--r-- | src/cairo-gl-private.h | 24 | ||||
-rw-r--r-- | src/cairo-gl-shaders.c | 31 | ||||
-rw-r--r-- | src/cairo-gl-source.c | 3 | ||||
-rw-r--r-- | src/cairo-gl-spans-compositor.c | 6 | ||||
-rw-r--r-- | src/cairo-gl-traps-compositor.c | 3 |
8 files changed, 162 insertions, 63 deletions
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c index d8166b83..c250e720 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 54772efb..a0fd9a0e 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 19512668..f99400ca 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 a75afa7e..2b254f98 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 41672d62..ae2977c5 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 294f6f91..12235295 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 98efd465..92e57797 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 b6c23333..9589ffcb 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)) |