[Pixman] [PATCH v2 7/8] Speed up _pixman_composite_glyphs_no_mask()
Søren Sandmann
sandmann at cs.au.dk
Sat Jun 2 06:23:56 PDT 2012
From: Søren Sandmann Pedersen <ssp at redhat.com>
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.
---
pixman/pixman-glyph.c | 91 ++++++++++++++++++++++++++++++++++++++++++-----
pixman/pixman-private.h | 13 +++++++
pixman/pixman.c | 30 ++++++++--------
3 files changed, 111 insertions(+), 23 deletions(-)
diff --git a/pixman/pixman-glyph.c b/pixman/pixman-glyph.c
index 186ef47..921eff1 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 (®ion);
+ if (!_pixman_compute_composite_region32 (
+ ®ion,
+ 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 (®ion, &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 (®ion);
}
static void
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 8323426..873f321 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 7d841d3..0137c3c 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 (®ion);
- if (!pixman_compute_composite_region32 (
+ if (!_pixman_compute_composite_region32 (
®ion, 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);
--
1.7.10.2
More information about the Pixman
mailing list