diff options
author | Søren Sandmann Pedersen <ssp@redhat.com> | 2010-12-12 07:34:42 -0500 |
---|---|---|
committer | Søren Sandmann Pedersen <ssp@redhat.com> | 2011-01-03 15:59:43 -0500 |
commit | 93cd8b31a869828dc4014650c001c6d85d49ebe8 (patch) | |
tree | e0f6b47adf89aea683b48d88e2b9f63c81da2b39 | |
parent | 670abaec2459c9b98eb24bdb2a0ffe70e6e2839d (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.c | 107 | ||||
-rw-r--r-- | pixman/pixman-conical-gradient.c | 3 | ||||
-rw-r--r-- | pixman/pixman-general.c | 59 | ||||
-rw-r--r-- | pixman/pixman-image.c | 2 | ||||
-rw-r--r-- | pixman/pixman-implementation.c | 77 | ||||
-rw-r--r-- | pixman/pixman-linear-gradient.c | 4 | ||||
-rw-r--r-- | pixman/pixman-private.h | 60 | ||||
-rw-r--r-- | pixman/pixman-radial-gradient.c | 3 | ||||
-rw-r--r-- | pixman/pixman-solid-fill.c | 1 | ||||
-rw-r--r-- | 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 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) { |