summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2010-02-03 12:24:41 -0800
committerEric Anholt <eric@anholt.net>2010-02-04 07:05:41 -0800
commit0fceac4d52d4b574b9c1f911b83d15dc7e01691d (patch)
treebc90901a08e1470c92d71eb1f4782e62bfb86d0d
parent8357336ed7be91ad359d205b1f223486d13215f2 (diff)
[gl] Move the component alpha composite to using GLSL when available.
-rw-r--r--src/cairo-gl-surface.c165
1 files changed, 108 insertions, 57 deletions
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index c5abbbd2..650c3c7c 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -1125,9 +1125,29 @@ _cairo_gl_operand_destroy (cairo_gl_composite_operand_t *operand)
}
static void
-_cairo_gl_set_tex_combine_constant_color (cairo_gl_context_t *ctx, int tex_unit,
+_cairo_gl_set_tex_combine_constant_color (cairo_gl_context_t *ctx,
+ cairo_gl_composite_setup_t *setup,
+ int tex_unit,
GLfloat *color)
{
+ if (setup->shader) {
+ const char *uniform_name;
+
+ if (tex_unit == 0)
+ uniform_name = "constant_source";
+ else
+ uniform_name = "constant_mask";
+
+ bind_vec4_to_shader(setup->shader->program,
+ uniform_name,
+ color[0],
+ color[1],
+ color[2],
+ color[3]);
+ return;
+ }
+
+ /* Fall back to fixed function */
glActiveTexture (GL_TEXTURE0 + tex_unit);
/* Have to have a dummy texture bound in order to use the combiner unit. */
glBindTexture (GL_TEXTURE_2D, ctx->dummy_tex);
@@ -1169,17 +1189,8 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
switch (setup->src.type) {
case OPERAND_CONSTANT:
- if (setup->shader) {
- bind_vec4_to_shader(setup->shader->program,
- "constant_source",
- setup->src.operand.constant.color[0],
- setup->src.operand.constant.color[1],
- setup->src.operand.constant.color[2],
- setup->src.operand.constant.color[3]);
- } else {
- _cairo_gl_set_tex_combine_constant_color (ctx, 0,
- setup->src.operand.constant.color);
- }
+ _cairo_gl_set_tex_combine_constant_color (ctx, setup, 0,
+ setup->src.operand.constant.color);
break;
case OPERAND_TEXTURE:
_cairo_gl_set_texture_surface (0, setup->src.operand.texture.tex,
@@ -1228,24 +1239,23 @@ _cairo_gl_set_src_alpha_operand (cairo_gl_context_t *ctx,
constant_color[1] = setup->src.operand.constant.color[3];
constant_color[2] = setup->src.operand.constant.color[3];
constant_color[3] = setup->src.operand.constant.color[3];
- _cairo_gl_set_tex_combine_constant_color (ctx, 0, constant_color);
+ _cairo_gl_set_tex_combine_constant_color (ctx, setup, 0,
+ constant_color);
break;
case OPERAND_TEXTURE:
- constant_color[0] = 0.0;
- constant_color[1] = 0.0;
- constant_color[2] = 0.0;
- constant_color[3] = 1.0;
_cairo_gl_set_texture_surface (0, setup->src.operand.texture.tex,
src_attributes);
- /* Set up the combiner to just set color to the sampled texture. */
- glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
- glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
- glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
+ if (!setup->shader) {
+ /* Set up the combiner to just set color to the sampled texture. */
+ glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+ glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
+ glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0);
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE0);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_ALPHA);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0);
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE0);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_ALPHA);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
+ }
break;
}
}
@@ -1262,49 +1272,61 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
mask_attributes = &setup->mask.operand.texture.attributes;
- glActiveTexture (GL_TEXTURE1);
- glEnable (GL_TEXTURE_2D);
- glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
- glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
- glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
+ if (!setup->shader) {
+ glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+ glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
+ glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PREVIOUS);
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PREVIOUS);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PREVIOUS);
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PREVIOUS);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
+ }
switch (setup->mask.type) {
case OPERAND_CONSTANT:
/* Have to have a dummy texture bound in order to use the combiner unit. */
- glBindTexture (GL_TEXTURE_2D, ctx->dummy_tex);
-
- glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,
- setup->mask.operand.constant.color);
+ if (setup->shader) {
+ bind_vec4_to_shader(setup->shader->program,
+ "constant_mask",
+ setup->src.operand.constant.color[0],
+ setup->src.operand.constant.color[1],
+ setup->src.operand.constant.color[2],
+ setup->src.operand.constant.color[3]);
+ } else {
+ glBindTexture (GL_TEXTURE_2D, ctx->dummy_tex);
+ glActiveTexture (GL_TEXTURE1);
+ glEnable (GL_TEXTURE_2D);
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_CONSTANT);
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_CONSTANT);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
+ glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,
+ setup->mask.operand.constant.color);
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_CONSTANT);
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_CONSTANT);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
+ }
break;
case OPERAND_TEXTURE:
_cairo_gl_set_texture_surface (1, setup->mask.operand.texture.tex,
mask_attributes);
- /* Set up the constant color we use to set color to 0 if needed. */
- glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant_color);
+ if (!setup->shader) {
+ /* Set up the constant color we use to set color to 0 if needed. */
+ glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant_color);
- /* Force the mask color to 0 if the surface should be alpha-only.
- * We may have a teximage with color bits if the implementation doesn't
- * support GL_ALPHA FBOs.
- */
- if (setup->mask.operand.texture.surface->base.content !=
- CAIRO_CONTENT_ALPHA)
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE1);
- else
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_CONSTANT);
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE1);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
+ /* Force the mask color to 0 if the surface should be
+ * alpha-only. We may have a teximage with color bits if
+ * the implementation doesn't support GL_ALPHA FBOs.
+ */
+ if (setup->mask.operand.texture.surface->base.content !=
+ CAIRO_CONTENT_ALPHA)
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE1);
+ else
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_CONSTANT);
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE1);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
+ }
break;
}
}
@@ -1387,6 +1409,8 @@ _cairo_gl_surface_composite_component_alpha (cairo_operator_t op,
int num_vertices, i;
GLenum err;
cairo_gl_composite_setup_t setup;
+ cairo_gl_shader_program_t *ca_source_program = NULL;
+ cairo_gl_shader_program_t *ca_source_alpha_program = NULL;
if (op != CAIRO_OPERATOR_OVER)
return UNSUPPORTED ("unsupported component alpha operator");
@@ -1418,6 +1442,27 @@ _cairo_gl_surface_composite_component_alpha (cairo_operator_t op,
return status;
}
+ status = _cairo_gl_get_program (ctx,
+ setup.src.source,
+ setup.mask.mask,
+ CAIRO_GL_SHADER_IN_CA_SOURCE,
+ &ca_source_program);
+ if (!_cairo_status_is_error (status)) {
+ status = _cairo_gl_get_program (ctx,
+ setup.src.source,
+ setup.mask.mask,
+ CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA,
+ &ca_source_alpha_program);
+ if (_cairo_status_is_error (status)) {
+ /* We'll fall back to fixed function instead. */
+ ca_source_program = NULL;
+ status = CAIRO_STATUS_SUCCESS;
+ }
+ } else {
+ /* We'll fall back to fixed function instead. */
+ status = CAIRO_STATUS_SUCCESS;
+ }
+
_cairo_gl_set_destination (dst);
if (clip_region != NULL) {
@@ -1499,16 +1544,22 @@ _cairo_gl_surface_composite_component_alpha (cairo_operator_t op,
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
}
+ setup.shader = ca_source_alpha_program;
+ _cairo_gl_use_program (setup.shader);
_cairo_gl_set_operator (dst, CAIRO_OPERATOR_DEST_OUT, TRUE);
_cairo_gl_set_src_alpha_operand (ctx, &setup);
_cairo_gl_set_component_alpha_mask_operand (ctx, &setup);
glDrawArrays (GL_QUADS, 0, num_vertices);
+ setup.shader = ca_source_program;
+ _cairo_gl_use_program (setup.shader);
_cairo_gl_set_operator (dst, CAIRO_OPERATOR_ADD, TRUE);
_cairo_gl_set_src_operand (ctx, &setup);
+ _cairo_gl_set_component_alpha_mask_operand (ctx, &setup);
glDrawArrays (GL_QUADS, 0, num_vertices);
glDisable (GL_BLEND);
+ _cairo_gl_use_program (NULL);
glDisableClientState (GL_VERTEX_ARRAY);
@@ -1635,7 +1686,7 @@ _cairo_gl_surface_composite (cairo_operator_t op,
if (mask != NULL) {
switch (setup.mask.type) {
case OPERAND_CONSTANT:
- _cairo_gl_set_tex_combine_constant_color (ctx, 1,
+ _cairo_gl_set_tex_combine_constant_color (ctx, &setup, 1,
setup.mask.operand.constant.color);
break;