summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@redhat.com>2010-12-10 16:55:55 -0500
committerSøren Sandmann Pedersen <ssp@redhat.com>2011-01-18 12:42:26 -0500
commit3e635d6491d883304662aff3c72558dc9065f1f1 (patch)
tree74b0db74921dc11cd09318f7a99700da04dc1ab4
parent0f1a5c4a27d34dcf4525dc38fcb48c14f653e828 (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.c25
-rw-r--r--pixman/pixman-general.c19
-rw-r--r--pixman/pixman-private.h19
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