diff options
author | Søren Sandmann Pedersen <ssp@redhat.com> | 2010-12-10 16:55:55 -0500 |
---|---|---|
committer | Søren Sandmann Pedersen <ssp@redhat.com> | 2011-01-18 12:42:26 -0500 |
commit | 3e635d6491d883304662aff3c72558dc9065f1f1 (patch) | |
tree | 74b0db74921dc11cd09318f7a99700da04dc1ab4 | |
parent | 0f1a5c4a27d34dcf4525dc38fcb48c14f653e828 (diff) |
Add direct-write optimization back
Introduce a new ITER_LOCALIZED_ALPHA flag that indicates that the
alpha value computed is used only for the alpha channel of the output;
it doesn't affect the RGB channels.
Then in pixman-bits-image.c, if a destination is either a8r8g8b8 or
x8r8g8b8 with localized alpha, the iterator will return a pointer
directly into the image.
-rw-r--r-- | pixman/pixman-bits-image.c | 25 | ||||
-rw-r--r-- | pixman/pixman-general.c | 19 | ||||
-rw-r--r-- | pixman/pixman-private.h | 19 |
3 files changed, 58 insertions, 5 deletions
diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index 983e23cd..8d4e4f5d 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -1438,6 +1438,12 @@ dest_write_back_wide (pixman_iter_t *iter) iter->y++; } +static void +dest_write_back_direct (pixman_iter_t *iter) +{ + iter->buffer += iter->image->bits.rowstride; +} + void _pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter, @@ -1446,8 +1452,23 @@ _pixman_bits_image_dest_iter_init (pixman_image_t *image, { if (flags & ITER_NARROW) { - iter->get_scanline = dest_get_scanline_narrow; - iter->write_back = dest_write_back_narrow; + if (((image->common.flags & + (FAST_PATH_NO_ALPHA_MAP | FAST_PATH_NO_ACCESSORS)) == + (FAST_PATH_NO_ALPHA_MAP | FAST_PATH_NO_ACCESSORS)) && + (image->bits.format == PIXMAN_a8r8g8b8 || + (image->bits.format == PIXMAN_x8r8g8b8 && + (flags & ITER_LOCALIZED_ALPHA)))) + { + iter->buffer = image->bits.bits + y * image->bits.rowstride + x; + + iter->get_scanline = _pixman_iter_get_scanline_noop; + iter->write_back = dest_write_back_direct; + } + else + { + iter->get_scanline = dest_get_scanline_narrow; + iter->write_back = dest_write_back_narrow; + } } else { diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c index e2f1dc3f..e7a72833 100644 --- a/pixman/pixman-general.c +++ b/pixman/pixman-general.c @@ -130,7 +130,7 @@ general_composite_rect (pixman_implementation_t *imp, pixman_iter_t src_iter, mask_iter, dest_iter; pixman_combine_32_func_t compose; pixman_bool_t component_alpha; - iter_flags_t narrow; + iter_flags_t narrow, dest_flags; int Bpp; int i; @@ -167,9 +167,24 @@ general_composite_rect (pixman_implementation_t *imp, mask_x, mask_y, width, height, mask_buffer, narrow); + if (op == PIXMAN_OP_CLEAR || + op == PIXMAN_OP_SRC || + op == PIXMAN_OP_DST || + op == PIXMAN_OP_OVER || + op == PIXMAN_OP_IN_REVERSE || + op == PIXMAN_OP_OUT_REVERSE || + op == PIXMAN_OP_ADD) + { + dest_flags = narrow | ITER_LOCALIZED_ALPHA; + } + else + { + dest_flags = narrow; + } + _pixman_implementation_dest_iter_init (imp->toplevel, &dest_iter, dest, dest_x, dest_y, width, height, - dest_buffer, narrow); + dest_buffer, dest_flags); component_alpha = mask && diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index c3321e15..0aeae2ec 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -185,7 +185,24 @@ union pixman_image typedef struct pixman_iter_t pixman_iter_t; typedef enum { - ITER_NARROW = (1 << 0), + ITER_NARROW = (1 << 0), + + /* "Localized alpha" is when the alpha channel is used only to compute + * the alpha value of the destination. This means that the computation + * of the RGB values of the result is independent of the alpha value. + * + * For example, the OVER operator has localized alpha for the + * destination, because the RGB values of the result can be computed + * without knowing the destination alpha. Similarly, ADD has localized + * alpha for both source and destination because the RGB values of the + * result can be computed without knowing the alpha value of source or + * destination. + * + * When he destination is xRGB, this is useful knowledge, because then + * we can treat it as if it were ARGB, which means in some cases we can + * avoid copying it to a temporary buffer. + */ + ITER_LOCALIZED_ALPHA = (1 << 1) } iter_flags_t; struct pixman_iter_t |