[Pixman] [PATCH 18/18] Fix destination fetching.
Søren Sandmann
sandmann at cs.au.dk
Wed Jan 5 18:28:02 PST 2011
From: Søren Sandmann Pedersen <ssp at redhat.com>
When fetching from destinations, we need to ignore transformations,
repeat and filtering. Currently we don't ignore them, which means all
kinds of bad things can happen.
This bug fixes this problem by separating the concepts of source and
destination iterator instead of using the ITER_WRITE flag to indicate
which is which.
Apart from making it simple for destination iterators to plug in
alternate fetchers, this also allows a small optimization where source
iterators no longer have a separate "next line" call; instead they are
supposed to prepare themselves for the next line in the "get_scanline"
call.
Destination iterators do now have a separate "write_back" call that is
supposed to write the pixels back to the destination and prepare the
iterator for the next scanline.
---
pixman/pixman-bits-image.c | 107 ++++++++++++++++++++++++++-----------
pixman/pixman-conical-gradient.c | 3 +-
pixman/pixman-general.c | 59 ++++++++++++++------
pixman/pixman-image.c | 2 +-
pixman/pixman-implementation.c | 77 +++++++++++++++++++---------
pixman/pixman-linear-gradient.c | 4 +-
pixman/pixman-private.h | 60 ++++++++++++---------
pixman/pixman-radial-gradient.c | 3 +-
pixman/pixman-solid-fill.c | 1 -
pixman/pixman-utils.c | 11 ----
10 files changed, 208 insertions(+), 119 deletions(-)
diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 7d588a9..4d8c1dc 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -1350,7 +1350,7 @@ static uint32_t *
get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
{
iter->image->bits.get_scanline_32 (
- iter->image, iter->x, iter->y, iter->width, iter->buffer, mask);
+ iter->image, iter->x, iter->y++, iter->width, iter->buffer, mask);
return iter->buffer;
}
@@ -1359,13 +1359,59 @@ static uint32_t *
get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
{
iter->image->bits.get_scanline_64 (
- iter->image, iter->x, iter->y, iter->width, iter->buffer, mask);
+ iter->image, iter->x, iter->y++, iter->width, iter->buffer, mask);
+
+ return iter->buffer;
+}
+
+static uint32_t *
+dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
+{
+ pixman_image_t *image = iter->image;
+ int x = iter->x;
+ int y = iter->y;
+ int width = iter->width;
+ uint32_t * buffer = iter->buffer;
+
+ image->bits.fetch_scanline_32 (image, x, y, width, buffer, mask);
+ if (image->common.alpha_map)
+ {
+ x -= image->common.alpha_origin_x;
+ y -= image->common.alpha_origin_y;
+
+ image->common.alpha_map->fetch_scanline_32 (
+ (pixman_image_t *)image->common.alpha_map,
+ x, y, width, buffer, mask);
+ }
+
+ return iter->buffer;
+}
+
+static uint32_t *
+dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
+{
+ bits_image_t * image = &iter->image->bits;
+ int x = iter->x;
+ int y = iter->y;
+ int width = iter->width;
+ uint32_t * buffer = iter->buffer;
+
+ image->fetch_scanline_64 (
+ (pixman_image_t *)image, x, y, width, buffer, mask);
+ if (image->common.alpha_map)
+ {
+ x -= image->common.alpha_origin_x;
+ y -= image->common.alpha_origin_y;
+
+ image->common.alpha_map->fetch_scanline_64 (
+ (pixman_image_t *)image->common.alpha_map, x, y, width, buffer, mask);
+ }
return iter->buffer;
}
static void
-next_line_write_narrow (pixman_iter_t *iter)
+write_back_narrow (pixman_iter_t *iter)
{
bits_image_t * image = &iter->image->bits;
int x = iter->x;
@@ -1388,7 +1434,7 @@ next_line_write_narrow (pixman_iter_t *iter)
}
static void
-next_line_write_wide (pixman_iter_t *iter)
+write_back_wide (pixman_iter_t *iter)
{
bits_image_t * image = &iter->image->bits;
int x = iter->x;
@@ -1410,25 +1456,19 @@ next_line_write_wide (pixman_iter_t *iter)
iter->y++;
}
-static uint32_t *
-get_scanline_direct_write (pixman_iter_t *iter, const uint32_t *mask)
-{
- return iter->buffer;
-}
-
static void
-next_line_direct_write (pixman_iter_t *iter)
+write_back_direct (pixman_iter_t *iter)
{
iter->buffer += iter->image->bits.rowstride;
}
void
-_pixman_bits_image_iter_init (pixman_image_t *image,
- pixman_iter_t *iter,
- int x, int y, int width, int height,
- uint8_t *buffer, iter_flags_t flags)
+_pixman_bits_image_dest_iter_init (pixman_image_t *image,
+ pixman_iter_t *iter,
+ int x, int y, int width, int height,
+ uint8_t *buffer, iter_flags_t flags)
{
- if ((flags & (ITER_NARROW | ITER_WRITE)) == (ITER_NARROW | ITER_WRITE))
+ if (flags & ITER_NARROW)
{
if (((image->common.flags &
(FAST_PATH_NO_ALPHA_MAP | FAST_PATH_NO_ACCESSORS)) ==
@@ -1439,40 +1479,43 @@ _pixman_bits_image_iter_init (pixman_image_t *image,
{
iter->buffer = image->bits.bits + y * image->bits.rowstride + x;
- iter->get_scanline = get_scanline_direct_write;
- iter->next_line = next_line_direct_write;
+ iter->get_scanline = _pixman_iter_get_scanline_noop;
+ iter->write_back = write_back_direct;
}
else
{
if ((flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) ==
- (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA))
+ (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA))
{
iter->get_scanline = _pixman_iter_get_scanline_noop;
}
else
{
- iter->get_scanline = get_scanline_narrow;
+ iter->get_scanline = dest_get_scanline_narrow;
}
- iter->next_line = next_line_write_narrow;
+ iter->write_back = write_back_narrow;
}
}
- else if (flags & ITER_WRITE)
- {
- iter->get_scanline = get_scanline_wide;
- iter->next_line = next_line_write_wide;
- }
else
{
- if (flags & ITER_NARROW)
- iter->get_scanline = get_scanline_narrow;
- else
- iter->get_scanline = get_scanline_wide;
-
- iter->next_line = _pixman_iter_next_line_regular;
+ iter->get_scanline = dest_get_scanline_wide;
+ iter->write_back = write_back_wide;
}
}
+void
+_pixman_bits_image_src_iter_init (pixman_image_t *image,
+ pixman_iter_t *iter,
+ int x, int y, int width, int height,
+ uint8_t *buffer, iter_flags_t flags)
+{
+ if (flags & ITER_NARROW)
+ iter->get_scanline = get_scanline_narrow;
+ else
+ iter->get_scanline = get_scanline_wide;
+}
+
static uint32_t *
create_bits (pixman_format_code_t format,
int width,
diff --git a/pixman/pixman-conical-gradient.c b/pixman/pixman-conical-gradient.c
index a0eeae2..9d7d2e8 100644
--- a/pixman/pixman-conical-gradient.c
+++ b/pixman/pixman-conical-gradient.c
@@ -156,6 +156,7 @@ conical_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
}
}
+ iter->y++;
return iter->buffer;
}
@@ -179,8 +180,6 @@ _pixman_conical_gradient_iter_init (pixman_image_t *image,
iter->get_scanline = conical_get_scanline_narrow;
else
iter->get_scanline = conical_get_scanline_wide;
-
- iter->next_line = _pixman_iter_next_line_regular;
}
PIXMAN_EXPORT pixman_image_t *
diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c
index 25d1fe4..16ea3a4 100644
--- a/pixman/pixman-general.c
+++ b/pixman/pixman-general.c
@@ -40,11 +40,11 @@
#include "pixman-private.h"
static void
-general_iter_init (pixman_implementation_t *imp,
- pixman_iter_t *iter,
- pixman_image_t *image,
- int x, int y, int width, int height,
- uint8_t *buffer, iter_flags_t flags)
+general_src_iter_init (pixman_implementation_t *imp,
+ pixman_iter_t *iter,
+ pixman_image_t *image,
+ int x, int y, int width, int height,
+ uint8_t *buffer, iter_flags_t flags)
{
iter->image = image;
iter->x = x;
@@ -74,7 +74,7 @@ general_iter_init (pixman_implementation_t *imp,
}
else if (image->type == BITS)
{
- _pixman_bits_image_iter_init (
+ _pixman_bits_image_src_iter_init (
image, iter, x, y, width, height, buffer, flags);
}
else
@@ -83,6 +83,30 @@ general_iter_init (pixman_implementation_t *imp,
}
}
+static void
+general_dest_iter_init (pixman_implementation_t *imp,
+ pixman_iter_t *iter,
+ pixman_image_t *image,
+ int x, int y, int width, int height,
+ uint8_t *buffer, iter_flags_t flags)
+{
+ iter->image = image;
+ iter->x = x;
+ iter->y = y;
+ iter->width = width;
+ iter->buffer = (uint32_t *)buffer;
+
+ if (image->type == BITS)
+ {
+ _pixman_bits_image_dest_iter_init (
+ image, iter, x, y, width, height, buffer, flags);
+ }
+ else
+ {
+ _pixman_log_error (FUNC, "Trying to write to a non-writable image");
+ }
+}
+
typedef struct op_info_t op_info_t;
struct op_info_t
{
@@ -166,9 +190,9 @@ general_composite_rect (pixman_implementation_t *imp,
/* src iter */
src_flags = narrow | op_flags[op].src;
- _pixman_implementation_iter_init (imp->toplevel, &src_iter, src,
- src_x, src_y, width, height,
- src_buffer, src_flags);
+ _pixman_implementation_src_iter_init (imp->toplevel, &src_iter, src,
+ src_x, src_y, width, height,
+ src_buffer, src_flags);
/* mask iter */
if ((src_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) ==
@@ -186,15 +210,15 @@ general_composite_rect (pixman_implementation_t *imp,
mask->common.component_alpha &&
PIXMAN_FORMAT_RGB (mask->bits.format);
- _pixman_implementation_iter_init (
+ _pixman_implementation_src_iter_init (
imp->toplevel, &mask_iter, mask, mask_x, mask_y, width, height,
mask_buffer, narrow | (component_alpha? 0 : ITER_IGNORE_RGB));
/* dest iter */
- _pixman_implementation_iter_init (imp->toplevel, &dest_iter, dest,
- dest_x, dest_y, width, height,
- dest_buffer,
- narrow | ITER_WRITE | op_flags[op].dst);
+ _pixman_implementation_dest_iter_init (imp->toplevel, &dest_iter, dest,
+ dest_x, dest_y, width, height,
+ dest_buffer,
+ narrow | op_flags[op].dst);
if (narrow)
{
@@ -224,9 +248,7 @@ general_composite_rect (pixman_implementation_t *imp,
compose (imp->toplevel, op, d, s, m, width);
- mask_iter.next_line (&mask_iter);
- src_iter.next_line (&src_iter);
- dest_iter.next_line (&dest_iter);
+ dest_iter.write_back (&dest_iter);
}
if (scanline_buffer != (uint8_t *) stack_scanline_buffer)
@@ -283,7 +305,8 @@ _pixman_implementation_create_general (void)
imp->blt = general_blt;
imp->fill = general_fill;
- imp->iter_init = general_iter_init;
+ imp->src_iter_init = general_src_iter_init;
+ imp->dest_iter_init = general_dest_iter_init;
return imp;
}
diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c
index e276eac..a72299b 100644
--- a/pixman/pixman-image.c
+++ b/pixman/pixman-image.c
@@ -728,7 +728,7 @@ _pixman_image_get_solid (pixman_implementation_t *imp,
uint32_t result;
pixman_iter_t iter;
- _pixman_implementation_iter_init (
+ _pixman_implementation_src_iter_init (
imp, &iter, image, 0, 0, 1, 1,
(uint8_t *)&result, ITER_NARROW);
diff --git a/pixman/pixman-implementation.c b/pixman/pixman-implementation.c
index 57134cb..6b7216f 100644
--- a/pixman/pixman-implementation.c
+++ b/pixman/pixman-implementation.c
@@ -112,17 +112,32 @@ delegate_fill (pixman_implementation_t *imp,
}
static void
-delegate_iter_init (pixman_implementation_t *imp,
- pixman_iter_t * iter,
- pixman_image_t * image,
- int x,
- int y,
- int width,
- int height,
- uint8_t * buffer,
- iter_flags_t flags)
+delegate_src_iter_init (pixman_implementation_t *imp,
+ pixman_iter_t * iter,
+ pixman_image_t * image,
+ int x,
+ int y,
+ int width,
+ int height,
+ uint8_t * buffer,
+ iter_flags_t flags)
{
- _pixman_implementation_iter_init (
+ _pixman_implementation_src_iter_init (
+ imp->delegate, iter, image, x, y, width, height, buffer, flags);
+}
+
+static void
+delegate_dest_iter_init (pixman_implementation_t *imp,
+ pixman_iter_t * iter,
+ pixman_image_t * image,
+ int x,
+ int y,
+ int width,
+ int height,
+ uint8_t * buffer,
+ iter_flags_t flags)
+{
+ _pixman_implementation_dest_iter_init (
imp->delegate, iter, image, x, y, width, height, buffer, flags);
}
@@ -148,7 +163,8 @@ _pixman_implementation_create (pixman_implementation_t *delegate,
*/
imp->blt = delegate_blt;
imp->fill = delegate_fill;
- imp->iter_init = delegate_iter_init;
+ imp->src_iter_init = delegate_src_iter_init;
+ imp->dest_iter_init = delegate_dest_iter_init;
for (i = 0; i < PIXMAN_N_OPERATORS; ++i)
{
@@ -248,31 +264,44 @@ get_scanline_null (pixman_iter_t *iter, const uint32_t *mask)
}
void
-_pixman_implementation_iter_init (pixman_implementation_t *imp,
- pixman_iter_t *iter,
- pixman_image_t *image,
- int x,
- int y,
- int width,
- int height,
- uint8_t *buffer,
- iter_flags_t flags)
+_pixman_implementation_src_iter_init (pixman_implementation_t *imp,
+ pixman_iter_t *iter,
+ pixman_image_t *image,
+ int x,
+ int y,
+ int width,
+ int height,
+ uint8_t *buffer,
+ iter_flags_t flags)
{
#define NOOP (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)
if (!image)
{
iter->get_scanline = get_scanline_null;
- iter->next_line = _pixman_iter_next_line_noop;
}
- else if ((flags & (NOOP | ITER_WRITE)) == NOOP)
+ else if ((flags & NOOP) == NOOP)
{
iter->get_scanline = _pixman_iter_get_scanline_noop;
- iter->next_line = _pixman_iter_next_line_noop;
}
else
{
- (*imp->iter_init) (
+ (*imp->src_iter_init) (
imp, iter, image, x, y, width, height, buffer, flags);
}
}
+
+void
+_pixman_implementation_dest_iter_init (pixman_implementation_t *imp,
+ pixman_iter_t *iter,
+ pixman_image_t *image,
+ int x,
+ int y,
+ int width,
+ int height,
+ uint8_t *buffer,
+ iter_flags_t flags)
+{
+ (*imp->dest_iter_init) (
+ imp, iter, image, x, y, width, height, buffer, flags);
+}
diff --git a/pixman/pixman-linear-gradient.c b/pixman/pixman-linear-gradient.c
index b778601..68845eb 100644
--- a/pixman/pixman-linear-gradient.c
+++ b/pixman/pixman-linear-gradient.c
@@ -220,6 +220,7 @@ linear_gradient_get_scanline_narrow (pixman_iter_t *iter,
}
}
+ iter->y++;
return iter->buffer;
}
@@ -251,7 +252,6 @@ _pixman_linear_gradient_iter_init (pixman_image_t *image,
linear_gradient_get_scanline_wide (iter, NULL);
iter->get_scanline = _pixman_iter_get_scanline_noop;
- iter->next_line = _pixman_iter_next_line_noop;
}
else
{
@@ -259,8 +259,6 @@ _pixman_linear_gradient_iter_init (pixman_image_t *image,
iter->get_scanline = linear_gradient_get_scanline_narrow;
else
iter->get_scanline = linear_gradient_get_scanline_wide;
-
- iter->next_line = _pixman_iter_next_line_regular;
}
}
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 2a00dc4..9e62c97 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -186,7 +186,6 @@ typedef struct pixman_iter_t pixman_iter_t;
typedef enum
{
ITER_NARROW = (1 << 0),
- ITER_WRITE = (1 << 1),
/* "Localized alpha" is when the alpha channel is used only to compute the
* alpha value of the destination and doesn't influence the RGB part.
@@ -201,15 +200,15 @@ typedef enum
* we can treat it as ARGB, which means in some cases we can avoid copying
* it to a temporary buffer.
*/
- ITER_LOCALIZED_ALPHA = (1 << 2),
- ITER_IGNORE_ALPHA = (1 << 3),
- ITER_IGNORE_RGB = (1 << 4)
+ ITER_LOCALIZED_ALPHA = (1 << 1),
+ ITER_IGNORE_ALPHA = (1 << 2),
+ ITER_IGNORE_RGB = (1 << 3)
} iter_flags_t;
struct pixman_iter_t
{
uint32_t *(* get_scanline) (pixman_iter_t *iter, const uint32_t *mask);
- void (* next_line) (pixman_iter_t *iter);
+ void (* write_back) (pixman_iter_t *iter);
pixman_image_t * image;
uint32_t * buffer;
@@ -221,10 +220,15 @@ void
_pixman_bits_image_setup_accessors (bits_image_t *image);
void
-_pixman_bits_image_iter_init (pixman_image_t *image,
- pixman_iter_t *iter,
- int x, int y, int width, int height,
- uint8_t *buffer, iter_flags_t flags);
+_pixman_bits_image_src_iter_init (pixman_image_t *image,
+ pixman_iter_t *iter,
+ int x, int y, int width, int height,
+ uint8_t *buffer, iter_flags_t flags);
+void
+_pixman_bits_image_dest_iter_init (pixman_image_t *image,
+ pixman_iter_t *iter,
+ int x, int y, int width, int height,
+ uint8_t *buffer, iter_flags_t flags);
void
_pixman_solid_fill_iter_init (pixman_image_t *image,
pixman_iter_t *iter,
@@ -432,7 +436,8 @@ struct pixman_implementation_t
pixman_blt_func_t blt;
pixman_fill_func_t fill;
- pixman_iter_init_func_t iter_init;
+ pixman_iter_init_func_t src_iter_init;
+ pixman_iter_init_func_t dest_iter_init;
pixman_combine_32_func_t combine_32[PIXMAN_N_OPERATORS];
pixman_combine_32_func_t combine_32_ca[PIXMAN_N_OPERATORS];
@@ -505,15 +510,26 @@ _pixman_implementation_fill (pixman_implementation_t *imp,
uint32_t xor);
void
-_pixman_implementation_iter_init (pixman_implementation_t *imp,
- pixman_iter_t *iter,
- pixman_image_t *image,
- int x,
- int y,
- int width,
- int height,
- uint8_t *buffer,
- iter_flags_t flags);
+_pixman_implementation_src_iter_init (pixman_implementation_t *imp,
+ pixman_iter_t *iter,
+ pixman_image_t *image,
+ int x,
+ int y,
+ int width,
+ int height,
+ uint8_t *buffer,
+ iter_flags_t flags);
+
+void
+_pixman_implementation_dest_iter_init (pixman_implementation_t *imp,
+ pixman_iter_t *iter,
+ pixman_image_t *image,
+ int x,
+ int y,
+ int width,
+ int height,
+ uint8_t *buffer,
+ iter_flags_t flags);
/* Specific implementations */
pixman_implementation_t *
@@ -555,12 +571,6 @@ _pixman_choose_implementation (void);
/*
* Utilities
*/
-void
-_pixman_iter_next_line_regular (pixman_iter_t *iter);
-
-void
-_pixman_iter_next_line_noop (pixman_iter_t *iter);
-
uint32_t *
_pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask);
diff --git a/pixman/pixman-radial-gradient.c b/pixman/pixman-radial-gradient.c
index e74a027..2f3e2e6 100644
--- a/pixman/pixman-radial-gradient.c
+++ b/pixman/pixman-radial-gradient.c
@@ -369,6 +369,7 @@ radial_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
}
}
+ iter->y++;
return iter->buffer;
}
@@ -392,8 +393,6 @@ _pixman_radial_gradient_iter_init (pixman_image_t *image,
iter->get_scanline = radial_get_scanline_narrow;
else
iter->get_scanline = radial_get_scanline_wide;
-
- iter->next_line = _pixman_iter_next_line_regular;
}
PIXMAN_EXPORT pixman_image_t *
diff --git a/pixman/pixman-solid-fill.c b/pixman/pixman-solid-fill.c
index 9795fd9..67681f2 100644
--- a/pixman/pixman-solid-fill.c
+++ b/pixman/pixman-solid-fill.c
@@ -52,7 +52,6 @@ _pixman_solid_fill_iter_init (pixman_image_t *image,
}
iter->get_scanline = _pixman_iter_get_scanline_noop;
- iter->next_line = _pixman_iter_next_line_noop;
}
static uint32_t
diff --git a/pixman/pixman-utils.c b/pixman/pixman-utils.c
index 09e4ee0..cb4e621 100644
--- a/pixman/pixman-utils.c
+++ b/pixman/pixman-utils.c
@@ -167,17 +167,6 @@ pixman_contract (uint32_t * dst,
}
}
-void
-_pixman_iter_next_line_regular (pixman_iter_t *iter)
-{
- iter->y++;
-}
-
-void
-_pixman_iter_next_line_noop (pixman_iter_t *iter)
-{
-}
-
uint32_t *
_pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask)
{
--
1.6.0.6
More information about the Pixman
mailing list