[cairo-commit] 2 commits - src/cairo-gl-glyphs.c src/cairo-gl-private.h src/cairo-gl-surface.c
Eric Anholt
anholt at kemper.freedesktop.org
Fri Jan 22 10:34:40 PST 2010
src/cairo-gl-glyphs.c | 219 ++++++++++++++++++++++++++++++++-----------------
src/cairo-gl-private.h | 8 +
src/cairo-gl-surface.c | 6 -
3 files changed, 156 insertions(+), 77 deletions(-)
New commits:
commit 5914e995723682e0b1f685d9ff5ea5abe05ae024
Author: Eric Anholt <eric at anholt.net>
Date: Fri Jan 22 09:21:36 2010 -0800
[gl] Cache a temporary glyph compositing mask for reuse later.
Cuts firefox-talos-gfx time from 56 seconds to 43 seconds.
diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index a5560eb..ecbbd0b 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -624,12 +624,25 @@ _cairo_gl_surface_show_glyphs_via_mask (cairo_gl_surface_t *dst,
int i;
/* XXX: For non-CA, this should be CAIRO_CONTENT_ALPHA to save memory */
- mask = cairo_gl_surface_create (dst->ctx,
- CAIRO_CONTENT_COLOR_ALPHA,
- glyph_extents->width,
- glyph_extents->height);
- if (unlikely (mask->status))
- return mask->status;
+ if (dst->ctx->glyphs_temporary_mask) {
+ if (glyph_extents->width <= dst->ctx->glyphs_temporary_mask->width &&
+ glyph_extents->height <= dst->ctx->glyphs_temporary_mask->height)
+ {
+ _cairo_gl_surface_clear (dst->ctx->glyphs_temporary_mask);
+ mask = &dst->ctx->glyphs_temporary_mask->base;
+ } else {
+ cairo_surface_destroy (&dst->ctx->glyphs_temporary_mask->base);
+ dst->ctx->glyphs_temporary_mask = NULL;
+ }
+ }
+ if (!mask) {
+ mask = cairo_gl_surface_create (dst->ctx,
+ CAIRO_CONTENT_COLOR_ALPHA,
+ glyph_extents->width,
+ glyph_extents->height);
+ if (unlikely (mask->status))
+ return mask->status;
+ }
for (i = 0; i < num_glyphs; i++) {
glyphs[i].x -= glyph_extents->x;
@@ -661,7 +674,9 @@ _cairo_gl_surface_show_glyphs_via_mask (cairo_gl_surface_t *dst,
*remaining_glyphs = num_glyphs;
}
- cairo_surface_destroy (mask);
+ if (!dst->ctx->glyphs_temporary_mask)
+ dst->ctx->glyphs_temporary_mask = (cairo_gl_surface_t *)mask;
+
return status;
}
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 585557b..7d157d8 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -91,6 +91,7 @@ struct _cairo_gl_context {
GLint max_texture_size;
cairo_gl_surface_t *current_target;
+ cairo_gl_surface_t *glyphs_temporary_mask;
cairo_gl_glyph_cache_t glyph_cache[2];
void (*make_current)(void *ctx, cairo_gl_surface_t *surface);
@@ -169,6 +170,9 @@ cairo_private cairo_bool_t
_cairo_gl_operator_is_supported (cairo_operator_t op);
cairo_private void
+_cairo_gl_surface_clear (cairo_gl_surface_t *surface);
+
+cairo_private void
_cairo_gl_set_operator (cairo_gl_surface_t *dst, cairo_operator_t op,
cairo_bool_t component_alpha);
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 392a0a8..5335e4b 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -176,6 +176,8 @@ cairo_gl_context_destroy (cairo_gl_context_t *context)
context->destroy (context);
+ cairo_surface_destroy (&context->glyphs_temporary_mask->base);
+
free (context);
}
slim_hidden_def (cairo_gl_context_destroy);
@@ -541,7 +543,7 @@ _cairo_gl_surface_create_scratch (cairo_gl_context_t *ctx,
return &surface->base;
}
-static void
+void
_cairo_gl_surface_clear (cairo_gl_surface_t *surface)
{
cairo_gl_context_t *ctx;
commit 1bf0f64ee7783742fa777a496567e4da48e300dd
Author: Eric Anholt <eric at anholt.net>
Date: Thu Jan 21 14:08:11 2010 -0800
[gl] Composite component-alpha glyphs directly instead of through a mask.
Cuts gnome-terminal-vim time from 58 seconds to 20.
diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index dbc7100..a5560eb 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -40,6 +40,13 @@
#define GLYPH_CACHE_MIN_SIZE 4
#define GLYPH_CACHE_MAX_SIZE 128
+typedef enum _cairo_gl_glyphs_shader {
+ CAIRO_GL_GLYPHS_SHADER_UNSET,
+ CAIRO_GL_GLYPHS_SHADER_NORMAL,
+ CAIRO_GL_GLYPHS_SHADER_CA_SOURCE_ALPHA,
+ CAIRO_GL_GLYPHS_SHADER_CA_SOURCE,
+} cairo_gl_glyphs_shader_t;
+
typedef struct _cairo_gl_glyph_private {
cairo_rtree_node_t node;
cairo_gl_glyph_cache_t *cache;
@@ -239,42 +246,117 @@ typedef struct _cairo_gl_glyphs_setup
cairo_gl_composite_setup_t *composite;
cairo_region_t *clip;
cairo_gl_surface_t *dst;
+ cairo_gl_glyphs_shader_t shader;
+ cairo_operator_t op;
+ cairo_bool_t component_alpha;
} cairo_gl_glyphs_setup_t;
static void
+_cairo_gl_glyphs_set_shader (cairo_gl_context_t *ctx,
+ cairo_gl_glyphs_setup_t *setup,
+ cairo_gl_glyphs_shader_t shader)
+{
+ if (setup->shader == shader)
+ return;
+
+ setup->shader = shader;
+
+ if (shader != CAIRO_GL_GLYPHS_SHADER_CA_SOURCE_ALPHA)
+ _cairo_gl_set_src_operand (ctx, setup->composite);
+ else
+ _cairo_gl_set_src_alpha_operand (ctx, setup->composite);
+
+ /* Set up the IN operator for source IN mask.
+ *
+ * IN (normal, any op): dst.argb = src.argb * mask.aaaa
+ * IN (component, ADD): dst.argb = src.argb * mask.argb
+ *
+ * The mask channel selection for component alpha ADD will be updated in
+ * the loop over glyphs below.
+ */
+ 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);
+
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE1);
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE1);
+ if (setup->shader == CAIRO_GL_GLYPHS_SHADER_NORMAL)
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_ALPHA);
+ else
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_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);
+}
+
+static void
+_cairo_gl_glyphs_draw (cairo_gl_context_t *ctx,
+ cairo_gl_glyphs_setup_t *setup)
+{
+ if (!setup->component_alpha || setup->op != CAIRO_OPERATOR_OVER) {
+ glDrawArrays (GL_QUADS, 0, 4 * setup->num_prims);
+ } else {
+ _cairo_gl_set_operator (setup->dst, CAIRO_OPERATOR_DEST_OUT, TRUE);
+ _cairo_gl_glyphs_set_shader(ctx, setup,
+ CAIRO_GL_GLYPHS_SHADER_CA_SOURCE_ALPHA);
+ glDrawArrays (GL_QUADS, 0, 4 * setup->num_prims);
+
+ _cairo_gl_set_operator (setup->dst, CAIRO_OPERATOR_ADD, TRUE);
+ _cairo_gl_glyphs_set_shader(ctx, setup,
+ CAIRO_GL_GLYPHS_SHADER_CA_SOURCE);
+ glDrawArrays (GL_QUADS, 0, 4 * setup->num_prims);
+ }
+}
+
+static void
_cairo_gl_flush_glyphs (cairo_gl_context_t *ctx,
cairo_gl_glyphs_setup_t *setup)
{
int i;
- if (setup->vb != NULL) {
- glUnmapBufferARB (GL_ARRAY_BUFFER_ARB);
- setup->vb = NULL;
+ if (setup->vb == NULL)
+ return;
+
+ glUnmapBufferARB (GL_ARRAY_BUFFER_ARB);
+ setup->vb = NULL;
+
+ if (setup->num_prims == 0)
+ return;
- if (setup->num_prims != 0) {
- if (setup->clip) {
- int num_rectangles = cairo_region_num_rectangles (setup->clip);
+ if (!setup->component_alpha) {
+ _cairo_gl_set_operator (setup->dst, setup->op, FALSE);
+ _cairo_gl_glyphs_set_shader(ctx, setup, CAIRO_GL_GLYPHS_SHADER_NORMAL);
+ } else if (setup->op == CAIRO_OPERATOR_ADD) {
+ _cairo_gl_set_operator (setup->dst, setup->op, FALSE);
+ _cairo_gl_glyphs_set_shader(ctx, setup, CAIRO_GL_GLYPHS_SHADER_CA_SOURCE);
+ }
- glEnable (GL_SCISSOR_TEST);
- for (i = 0; i < num_rectangles; i++) {
- cairo_rectangle_int_t rect;
+ if (setup->clip) {
+ int num_rectangles = cairo_region_num_rectangles (setup->clip);
- cairo_region_get_rectangle (setup->clip, i, &rect);
+ glEnable (GL_SCISSOR_TEST);
+ for (i = 0; i < num_rectangles; i++) {
+ cairo_rectangle_int_t rect;
- glScissor (rect.x,
- _cairo_gl_y_flip (setup->dst, rect.y),
- rect.x + rect.width,
- _cairo_gl_y_flip (setup->dst,
- rect.y + rect.height));
- glDrawArrays (GL_QUADS, 0, 4 * setup->num_prims);
- }
- glDisable (GL_SCISSOR_TEST);
- } else {
- glDrawArrays (GL_QUADS, 0, 4 * setup->num_prims);
- }
- setup->num_prims = 0;
+ cairo_region_get_rectangle (setup->clip, i, &rect);
+
+ glScissor (rect.x,
+ _cairo_gl_y_flip (setup->dst, rect.y),
+ rect.x + rect.width,
+ _cairo_gl_y_flip (setup->dst,
+ rect.y + rect.height));
+ _cairo_gl_glyphs_draw (ctx, setup);
}
+ glDisable (GL_SCISSOR_TEST);
+ } else {
+ _cairo_gl_glyphs_draw (ctx, setup);
}
+ setup->num_prims = 0;
}
static void
@@ -366,36 +448,7 @@ _render_glyphs (cairo_gl_surface_t *dst,
ctx = _cairo_gl_context_acquire (dst->ctx);
- /* Set up the IN operator for source IN mask.
- *
- * IN (normal, any op): dst.argb = src.argb * mask.aaaa
- * IN (component, ADD): dst.argb = src.argb * mask.argb
- *
- * The mask channel selection for component alpha ADD will be updated in
- * the loop over glyphs below.
- */
- 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);
-
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE1);
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE1);
- 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_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);
-
_cairo_gl_set_destination (dst);
- /* If we're doing some CA glyphs, we're only doing it for ADD,
- * which doesn't require the source alpha value in blending.
- */
- _cairo_gl_set_operator (dst, op, FALSE);
- _cairo_gl_set_src_operand (ctx, &composite_setup);
_cairo_scaled_font_freeze_cache (scaled_font);
if (! _cairo_gl_surface_owns_font (dst, scaled_font)) {
@@ -422,6 +475,8 @@ _render_glyphs (cairo_gl_surface_t *dst,
setup.vbo_size = num_glyphs * 4 * setup.vertex_size;
if (setup.vbo_size > 4096)
setup.vbo_size = 4096;
+ setup.op = op;
+ setup.shader = CAIRO_GL_GLYPHS_SHADER_UNSET;
glGenBuffersARB (1, &vbo);
glBindBufferARB (GL_ARRAY_BUFFER_ARB, vbo);
@@ -483,14 +538,11 @@ _render_glyphs (cairo_gl_surface_t *dst,
* need to make sure we send the rgb bits down to the destination.
*/
if (last_format == CAIRO_FORMAT_ARGB32) {
- assert (op == CAIRO_OPERATOR_ADD);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
*has_component_alpha = TRUE;
+ setup.component_alpha = TRUE;
} else {
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_ALPHA);
+ setup.component_alpha = FALSE;
}
-
- /* XXX component alpha */
}
if (scaled_glyph->surface_private == NULL) {
@@ -646,18 +698,20 @@ _cairo_gl_surface_show_glyphs (void *abstract_dst,
* since only _cairo_gl_surface_composite() currently supports component
* alpha.
*/
- for (i = 0; i < num_glyphs; i++) {
- cairo_scaled_glyph_t *scaled_glyph;
-
- status = _cairo_scaled_glyph_lookup (scaled_font,
- glyphs[i].index,
- CAIRO_SCALED_GLYPH_INFO_SURFACE,
- &scaled_glyph);
- if (!_cairo_status_is_error (status) &&
- scaled_glyph->surface->format == CAIRO_FORMAT_ARGB32)
- {
- use_mask = TRUE;
- break;
+ if (!use_mask && op != CAIRO_OPERATOR_OVER) {
+ for (i = 0; i < num_glyphs; i++) {
+ cairo_scaled_glyph_t *scaled_glyph;
+
+ status = _cairo_scaled_glyph_lookup (scaled_font,
+ glyphs[i].index,
+ CAIRO_SCALED_GLYPH_INFO_SURFACE,
+ &scaled_glyph);
+ if (!_cairo_status_is_error (status) &&
+ scaled_glyph->surface->format == CAIRO_FORMAT_ARGB32)
+ {
+ use_mask = TRUE;
+ break;
+ }
}
}
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 490bc5c..585557b 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -177,6 +177,10 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
cairo_gl_composite_setup_t *setup);
cairo_private void
+_cairo_gl_set_src_alpha_operand (cairo_gl_context_t *ctx,
+ cairo_gl_composite_setup_t *setup);
+
+cairo_private void
_cairo_gl_operand_destroy (cairo_gl_composite_operand_t *operand);
cairo_private cairo_bool_t
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 2acc8b5..392a0a8 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -1216,7 +1216,7 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
* for creating the "source alpha" value (src.aaaa * mask.argb) required by
* component alpha rendering.
*/
-static void
+void
_cairo_gl_set_src_alpha_operand (cairo_gl_context_t *ctx,
cairo_gl_composite_setup_t *setup)
{
More information about the cairo-commit
mailing list