summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@redhat.com>2010-12-12 07:34:42 -0500
committerSøren Sandmann Pedersen <ssp@redhat.com>2011-01-03 15:59:43 -0500
commit93cd8b31a869828dc4014650c001c6d85d49ebe8 (patch)
treee0f6b47adf89aea683b48d88e2b9f63c81da2b39
parent670abaec2459c9b98eb24bdb2a0ffe70e6e2839d (diff)
Fix destination fetching.iterators3
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.
-rw-r--r--pixman/pixman-bits-image.c107
-rw-r--r--pixman/pixman-conical-gradient.c3
-rw-r--r--pixman/pixman-general.c59
-rw-r--r--pixman/pixman-image.c2
-rw-r--r--pixman/pixman-implementation.c77
-rw-r--r--pixman/pixman-linear-gradient.c4
-rw-r--r--pixman/pixman-private.h60
-rw-r--r--pixman/pixman-radial-gradient.c3
-rw-r--r--pixman/pixman-solid-fill.c1
-rw-r--r--pixman/pixman-utils.c11
10 files changed, 208 insertions, 119 deletions
diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 7d588a9b..4d8c1dc3 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 a0eeae2b..9d7d2e8b 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 25d1fe43..16ea3a45 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 e276eacb..a72299b3 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 57134cb4..6b7216fe 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 b7786011..68845ebd 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 2a00dc4e..9e62c97f 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 e74a0276..2f3e2e6c 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 9795fd9c..67681f2c 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 09e4ee07..cb4e6219 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)
{