summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@redhat.com>2012-05-28 02:36:22 -0400
committerSøren Sandmann Pedersen <ssp@redhat.com>2012-06-02 08:19:38 -0400
commit934c9d8546b71ddea91ac16b0928101903e2608e (patch)
tree19ece1a6b1ca0cbf405ac0b26486338a4881ad4a
parenta162189dc0fa9978a3b5b6dd24f9bc12995805ed (diff)
Speed up _pixman_composite_glyphs_no_mask()
Bypass much of the overhead of pixman_image_composite32() by only computing the composite region once instead of once per glyph, and by only looking up the composite function whenever the glyph format or flags change. As part of this, the pixman_compute_composite_region32() was renamed to _pixman_compute_composite_region32() and exported in pixman-private.h. I couldn't find a trace that would reliably demonstrate that this is actually an improvement by itself (since _pixman_composite_glyphs_no_mask() is called so rarely), but together with the following optimization for solid sources, there is a small but reliable improvement to the xfce4-a1-terminal cairo trace.
-rw-r--r--pixman/pixman-glyph.c91
-rw-r--r--pixman/pixman-private.h13
-rw-r--r--pixman/pixman.c30
3 files changed, 111 insertions, 23 deletions
diff --git a/pixman/pixman-glyph.c b/pixman/pixman-glyph.c
index 186ef47e..921eff15 100644
--- a/pixman/pixman-glyph.c
+++ b/pixman/pixman-glyph.c
@@ -399,24 +399,99 @@ pixman_composite_glyphs_no_mask (pixman_op_t op,
int n_glyphs,
pixman_glyph_t *glyphs)
{
+ pixman_region32_t region;
+ pixman_format_code_t glyph_format = PIXMAN_null;
+ uint32_t glyph_flags = 0;
+ pixman_format_code_t dest_format;
+ uint32_t dest_flags;
+ pixman_composite_func_t func = NULL;
+ pixman_implementation_t *implementation = NULL;
+ pixman_composite_info_t info;
int i;
+ _pixman_image_validate (src);
+ _pixman_image_validate (dest);
+
+ dest_format = dest->common.extended_format_code;
+ dest_flags = dest->common.flags;
+
+ pixman_region32_init (&region);
+ if (!_pixman_compute_composite_region32 (
+ &region,
+ src, NULL, dest,
+ src_x - dest_x, src_y - dest_y, 0, 0, 0, 0,
+ dest->bits.width, dest->bits.height))
+ {
+ goto out;
+ }
+
+ info.op = op;
+ info.src_image = src;
+ info.dest_image = dest;
+ info.src_flags = src->common.flags;
+ info.dest_flags = dest->common.flags;
+
for (i = 0; i < n_glyphs; ++i)
{
glyph_t *glyph = (glyph_t *)glyphs[i].glyph;
pixman_image_t *glyph_img = glyph->image;
+ pixman_box32_t glyph_box;
+ pixman_box32_t *pbox;
+ uint32_t extra = FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
+ pixman_box32_t composite_box;
+ int n;
- pixman_image_composite32 (op, src, glyph_img, dest,
- src_x + glyphs[i].x - glyph->origin_x,
- src_y + glyphs[i].y - glyph->origin_y,
- 0, 0,
- dest_x + glyphs[i].x - glyph->origin_x,
- dest_y + glyphs[i].y - glyph->origin_y,
- glyph_img->bits.width,
- glyph_img->bits.height);
+ glyph_box.x1 = dest_x + glyphs[i].x - glyph->origin_x;
+ glyph_box.y1 = dest_y + glyphs[i].y - glyph->origin_y;
+ glyph_box.x2 = glyph_box.x1 + glyph->image->bits.width;
+ glyph_box.y2 = glyph_box.y1 + glyph->image->bits.height;
+
+ pbox = pixman_region32_rectangles (&region, &n);
+
+ info.mask_image = glyph_img;
+
+ while (n--)
+ {
+ if (box32_intersect (&composite_box, pbox, &glyph_box))
+ {
+ if (glyph_img->common.extended_format_code != glyph_format ||
+ glyph_img->common.flags != glyph_flags)
+ {
+ glyph_format = glyph_img->common.extended_format_code;
+ glyph_flags = glyph_img->common.flags;
+
+ _pixman_lookup_composite_function (
+ get_implementation(), op,
+ src->common.extended_format_code, src->common.flags,
+ glyph_format, glyph_flags | extra,
+ dest_format, dest_flags,
+ &implementation, &func);
+
+ if (!func)
+ goto out;
+ }
+
+ info.src_x = src_x + composite_box.x1 - dest_x;
+ info.src_y = src_y + composite_box.y1 - dest_y;
+ info.mask_x = composite_box.x1 - (dest_x + glyphs[i].x - glyph->origin_x);
+ info.mask_y = composite_box.y1 - (dest_y + glyphs[i].y - glyph->origin_y);
+ info.dest_x = composite_box.x1;
+ info.dest_y = composite_box.y1;
+ info.width = composite_box.x2 - composite_box.x1;
+ info.height = composite_box.y2 - composite_box.y1;
+
+ info.mask_flags = glyph_flags;
+
+ func (implementation, &info);
+ }
+ pbox++;
+ }
pixman_list_move_to_front (&cache->mru, &glyph->mru_link);
}
+
+out:
+ pixman_region32_fini (&region);
}
static void
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 83234260..873f3218 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -581,6 +581,19 @@ _pixman_choose_implementation (void);
/*
* Utilities
*/
+pixman_bool_t
+_pixman_compute_composite_region32 (pixman_region32_t * region,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dest_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height);
uint32_t *
_pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask);
diff --git a/pixman/pixman.c b/pixman/pixman.c
index 7d841d3d..0137c3ca 100644
--- a/pixman/pixman.c
+++ b/pixman/pixman.c
@@ -224,19 +224,19 @@ clip_source_image (pixman_region32_t * region,
* returns FALSE if the final region is empty. Indistinguishable from
* an allocation failure, but rendering ignores those anyways.
*/
-static pixman_bool_t
-pixman_compute_composite_region32 (pixman_region32_t * region,
- pixman_image_t * src_image,
- pixman_image_t * mask_image,
- pixman_image_t * dest_image,
- int32_t src_x,
- int32_t src_y,
- int32_t mask_x,
- int32_t mask_y,
- int32_t dest_x,
- int32_t dest_y,
- int32_t width,
- int32_t height)
+pixman_bool_t
+_pixman_compute_composite_region32 (pixman_region32_t * region,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dest_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
{
region->extents.x1 = dest_x;
region->extents.x2 = dest_x + width;
@@ -615,7 +615,7 @@ pixman_image_composite32 (pixman_op_t op,
pixman_region32_init (&region);
- if (!pixman_compute_composite_region32 (
+ if (!_pixman_compute_composite_region32 (
&region, src, mask, dest,
src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
{
@@ -1114,7 +1114,7 @@ pixman_compute_composite_region (pixman_region16_t * region,
pixman_region32_init (&r32);
- retval = pixman_compute_composite_region32 (
+ retval = _pixman_compute_composite_region32 (
&r32, src_image, mask_image, dest_image,
src_x, src_y, mask_x, mask_y, dest_x, dest_y,
width, height);