On Thu, Jan 6, 2011 at 3:28 AM, Søren Sandmann <sandm...@cs.au.dk> wrote: > From: Søren Sandmann Pedersen <s...@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.
This patch changes the iterators interface. How about starting with this interface? Would it bloat the previous commits a lot? > > 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)) This looks like a whitespace fix. Can it be merged with the patch which adds this code? > { > 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 > > _______________________________________________ > Pixman mailing list > Pixman@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/pixman > _______________________________________________ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman