From a7ad9c7c9dcb78e0c5ad00145b119dfe929eb307 Mon Sep 17 00:00:00 2001 From: Søren Sandmann Pedersen Date: Fri, 18 Sep 2009 03:54:36 -0400 Subject: Compute the image flags at validation time instead of composite time Instead of computing all the image flags at composite time, we compute them once in _pixman_image_validate() and cache them in the image. --- pixman/pixman-image.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++ pixman/pixman-private.h | 2 ++ pixman/pixman.c | 52 ++------------------------------------------ 3 files changed, 61 insertions(+), 50 deletions(-) diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index 6036c56..880c49f 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -243,12 +243,69 @@ _pixman_image_reset_clip_region (pixman_image_t *image) image->common.have_clip_region = FALSE; } +static void +compute_flags (pixman_image_t *image) +{ + uint32_t flags = 0; + + if (!image->common.transform) + { + flags |= FAST_PATH_ID_TRANSFORM; + } + else if (image->common.transform && + image->common.transform->matrix[0][1] == 0 && + image->common.transform->matrix[1][0] == 0 && + image->common.transform->matrix[2][0] == 0 && + image->common.transform->matrix[2][1] == 0 && + image->common.transform->matrix[2][2] == pixman_fixed_1) + { + flags |= FAST_PATH_SCALE_TRANSFORM; + } + + if (!image->common.alpha_map) + flags |= FAST_PATH_NO_ALPHA_MAP; + + if (image->common.filter != PIXMAN_FILTER_CONVOLUTION) + { + flags |= FAST_PATH_NO_CONVOLUTION_FILTER; + + if (image->common.filter == PIXMAN_FILTER_NEAREST) + flags |= FAST_PATH_NEAREST_FILTER; + } + + if (image->common.repeat != PIXMAN_REPEAT_PAD) + flags |= FAST_PATH_NO_PAD_REPEAT; + + if (image->common.repeat != PIXMAN_REPEAT_REFLECT) + flags |= FAST_PATH_NO_REFLECT_REPEAT; + + flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NO_WIDE_FORMAT); + if (image->common.type == BITS) + { + if (image->bits.read_func || image->bits.write_func) + flags &= ~FAST_PATH_NO_ACCESSORS; + + if (PIXMAN_FORMAT_IS_WIDE (image->bits.format)) + flags &= ~FAST_PATH_NO_WIDE_FORMAT; + } + + if (image->common.component_alpha) + flags |= FAST_PATH_COMPONENT_ALPHA; + else + flags |= FAST_PATH_UNIFIED_ALPHA; + + image->common.flags = flags; +} + void _pixman_image_validate (pixman_image_t *image) { if (image->common.dirty) { image->common.property_changed (image); + + compute_flags (image); + image->common.dirty = FALSE; } diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index 7ed8aa7..2cafe3a 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -103,6 +103,8 @@ struct image_common pixman_image_destroy_func_t destroy_func; void * destroy_data; + + uint32_t flags; }; struct source_image diff --git a/pixman/pixman.c b/pixman/pixman.c index 6a260ed..c7d3bcc 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -453,56 +453,8 @@ get_image_info (pixman_image_t *image, pixman_format_code_t *code, uint32_t *flags) { - *flags = 0; - - if (!image->common.transform) - { - *flags |= FAST_PATH_ID_TRANSFORM; - } - else - { - if (image->common.transform->matrix[0][1] == 0 && - image->common.transform->matrix[1][0] == 0 && - image->common.transform->matrix[2][0] == 0 && - image->common.transform->matrix[2][1] == 0 && - image->common.transform->matrix[2][2] == pixman_fixed_1) - { - *flags |= FAST_PATH_SCALE_TRANSFORM; - } - } - - if (!image->common.alpha_map) - *flags |= FAST_PATH_NO_ALPHA_MAP; - - if (image->common.filter != PIXMAN_FILTER_CONVOLUTION) - { - *flags |= FAST_PATH_NO_CONVOLUTION_FILTER; - - if (image->common.filter == PIXMAN_FILTER_NEAREST) - *flags |= FAST_PATH_NEAREST_FILTER; - } - - if (image->common.repeat != PIXMAN_REPEAT_PAD) - *flags |= FAST_PATH_NO_PAD_REPEAT; - - if (image->common.repeat != PIXMAN_REPEAT_REFLECT) - *flags |= FAST_PATH_NO_REFLECT_REPEAT; - - *flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NO_WIDE_FORMAT); - if (image->type == BITS) - { - if (image->bits.read_func || image->bits.write_func) - *flags &= ~FAST_PATH_NO_ACCESSORS; - - if (PIXMAN_FORMAT_IS_WIDE (image->bits.format)) - *flags &= ~FAST_PATH_NO_WIDE_FORMAT; - } - - if (image->common.component_alpha) - *flags |= FAST_PATH_COMPONENT_ALPHA; - else - *flags |= FAST_PATH_UNIFIED_ALPHA; - + *flags = image->common.flags; + if (_pixman_image_is_solid (image)) *code = PIXMAN_solid; else if (image->common.type == BITS) -- cgit v1.2.3 From fb0096a282c5b6e7ca9eb59a05d9ff738dccfd4b Mon Sep 17 00:00:00 2001 From: Søren Sandmann Pedersen Date: Mon, 22 Feb 2010 05:16:27 -0500 Subject: Add new FAST_PATH_SIMPLE_REPEAT flag This flags indicates that the image is untransformed an repeating. Such images can be composited quickly by simply repeating the composite operation. --- pixman/pixman-private.h | 1 + pixman/pixman.c | 26 +++++++++++--------------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index 2cafe3a..f4f0397 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -580,6 +580,7 @@ _pixman_choose_implementation (void); #define FAST_PATH_UNIFIED_ALPHA (1 << 9) #define FAST_PATH_SCALE_TRANSFORM (1 << 10) #define FAST_PATH_NEAREST_FILTER (1 << 11) +#define FAST_PATH_SIMPLE_REPEAT (1 << 12) #define _FAST_PATH_STANDARD_FLAGS \ (FAST_PATH_ID_TRANSFORM | \ diff --git a/pixman/pixman.c b/pixman/pixman.c index c7d3bcc..09fc7e1 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -456,11 +456,20 @@ get_image_info (pixman_image_t *image, *flags = image->common.flags; if (_pixman_image_is_solid (image)) + { *code = PIXMAN_solid; + } else if (image->common.type == BITS) + { *code = image->bits.format; + + if (!image->common.transform && image->common.repeat == PIXMAN_REPEAT_NORMAL) + *flags |= FAST_PATH_SIMPLE_REPEAT; + } else + { *code = PIXMAN_unknown; + } } static force_inline pixman_bool_t @@ -500,7 +509,6 @@ do_composite (pixman_implementation_t *imp, { pixman_format_code_t src_format, mask_format, dest_format; uint32_t src_flags, mask_flags, dest_flags; - pixman_bool_t src_repeat, mask_repeat; pixman_region32_t region; pixman_box32_t *extents; @@ -528,19 +536,6 @@ do_composite (pixman_implementation_t *imp, src_format = mask_format = PIXMAN_rpixbuf; } - src_repeat = - src->type == BITS && - src_flags & FAST_PATH_ID_TRANSFORM && - src->common.repeat == PIXMAN_REPEAT_NORMAL && - src_format != PIXMAN_solid; - - mask_repeat = - mask && - mask->type == BITS && - mask_flags & FAST_PATH_ID_TRANSFORM && - mask->common.repeat == PIXMAN_REPEAT_NORMAL && - mask_format != PIXMAN_solid; - pixman_region32_init (®ion); if (!pixman_compute_composite_region32 ( @@ -583,7 +578,8 @@ do_composite (pixman_implementation_t *imp, src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height, - src_repeat, mask_repeat, + (src_flags & FAST_PATH_SIMPLE_REPEAT), + (mask_flags & FAST_PATH_SIMPLE_REPEAT), ®ion, info->func); -- cgit v1.2.3 From 45006e5e648b85df65b922f893c9802c9ecce38e Mon Sep 17 00:00:00 2001 From: Søren Sandmann Pedersen Date: Fri, 18 Sep 2009 04:06:30 -0400 Subject: Move computation of extended format code to validate. Instead of computing the extended format on every composite, just compute it once and store it in the image. --- pixman/pixman-image.c | 25 +++++++++++++++++++++++-- pixman/pixman-private.h | 1 + pixman/pixman.c | 37 +++++++++---------------------------- 3 files changed, 33 insertions(+), 30 deletions(-) diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index 880c49f..89a5a09 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -244,8 +244,9 @@ _pixman_image_reset_clip_region (pixman_image_t *image) } static void -compute_flags (pixman_image_t *image) +compute_image_info (pixman_image_t *image) { + pixman_format_code_t code; uint32_t flags = 0; if (!image->common.transform) @@ -294,7 +295,27 @@ compute_flags (pixman_image_t *image) else flags |= FAST_PATH_UNIFIED_ALPHA; + if (_pixman_image_is_solid (image)) + { + code = PIXMAN_solid; + } + else if (image->common.type == BITS) + { + code = image->bits.format; + + if (!image->common.transform && + image->common.repeat == PIXMAN_REPEAT_NORMAL) + { + flags |= FAST_PATH_SIMPLE_REPEAT; + } + } + else + { + code = PIXMAN_unknown; + } + image->common.flags = flags; + image->common.extended_format_code = code; } void @@ -304,7 +325,7 @@ _pixman_image_validate (pixman_image_t *image) { image->common.property_changed (image); - compute_flags (image); + compute_image_info (image); image->common.dirty = FALSE; } diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index f4f0397..edee738 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -105,6 +105,7 @@ struct image_common void * destroy_data; uint32_t flags; + pixman_format_code_t extended_format_code; }; struct source_image diff --git a/pixman/pixman.c b/pixman/pixman.c index 09fc7e1..e1bef17 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -448,30 +448,6 @@ walk_region_internal (pixman_implementation_t *imp, } } -static void -get_image_info (pixman_image_t *image, - pixman_format_code_t *code, - uint32_t *flags) -{ - *flags = image->common.flags; - - if (_pixman_image_is_solid (image)) - { - *code = PIXMAN_solid; - } - else if (image->common.type == BITS) - { - *code = image->bits.format; - - if (!image->common.transform && image->common.repeat == PIXMAN_REPEAT_NORMAL) - *flags |= FAST_PATH_SIMPLE_REPEAT; - } - else - { - *code = PIXMAN_unknown; - } -} - static force_inline pixman_bool_t image_covers (pixman_image_t *image, pixman_box32_t *extents, @@ -512,18 +488,23 @@ do_composite (pixman_implementation_t *imp, pixman_region32_t region; pixman_box32_t *extents; - get_image_info (src, &src_format, &src_flags); + src_format = src->common.extended_format_code; + src_flags = src->common.flags; + if (mask) { - get_image_info (mask, &mask_format, &mask_flags); + mask_format = mask->common.extended_format_code; + mask_flags = mask->common.flags; } else { mask_format = PIXMAN_null; mask_flags = 0; } - get_image_info (dest, &dest_format, &dest_flags); - + + dest_format = dest->common.extended_format_code; + dest_flags = dest->common.flags; + /* Check for pixbufs */ if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) && (src->type == BITS && src->bits.bits == mask->bits.bits) && -- cgit v1.2.3 From 2a6ba862abd8859014d11a742247fa1f1225729b Mon Sep 17 00:00:00 2001 From: Søren Sandmann Pedersen Date: Fri, 18 Sep 2009 04:17:57 -0400 Subject: Eliminate _pixman_image_is_solid() Instead of calling this function in compute_image_info(), just do the relevant checks when the extended format is computed. Move computation of solidness to validate --- pixman/pixman-image.c | 40 +++++++++++++++------------------------- pixman/pixman-private.h | 3 --- 2 files changed, 15 insertions(+), 28 deletions(-) diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index 89a5a09..ff0fbbb 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -295,18 +295,27 @@ compute_image_info (pixman_image_t *image) else flags |= FAST_PATH_UNIFIED_ALPHA; - if (_pixman_image_is_solid (image)) + if (image->type == SOLID) { code = PIXMAN_solid; } else if (image->common.type == BITS) { - code = image->bits.format; - - if (!image->common.transform && - image->common.repeat == PIXMAN_REPEAT_NORMAL) + if (image->bits.width == 1 && + image->bits.height == 1 && + image->common.repeat != PIXMAN_REPEAT_NONE) + { + code = PIXMAN_solid; + } + else { - flags |= FAST_PATH_SIMPLE_REPEAT; + code = image->bits.format; + + if (!image->common.transform && + image->common.repeat == PIXMAN_REPEAT_NORMAL) + { + flags |= FAST_PATH_SIMPLE_REPEAT; + } } } else @@ -600,25 +609,6 @@ pixman_image_get_depth (pixman_image_t *image) return 0; } -pixman_bool_t -_pixman_image_is_solid (pixman_image_t *image) -{ - if (image->type == SOLID) - return TRUE; - - if (image->type != BITS || - image->bits.width != 1 || - image->bits.height != 1) - { - return FALSE; - } - - if (image->common.repeat == PIXMAN_REPEAT_NONE) - return FALSE; - - return TRUE; -} - uint32_t _pixman_image_get_solid (pixman_image_t * image, pixman_format_code_t format) diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index edee738..1ad452a 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -287,9 +287,6 @@ _pixman_image_validate (pixman_image_t *image); pixman_bool_t _pixman_image_is_opaque (pixman_image_t *image); -pixman_bool_t -_pixman_image_is_solid (pixman_image_t *image); - uint32_t _pixman_image_get_solid (pixman_image_t * image, pixman_format_code_t format); -- cgit v1.2.3 From f27f17ce22b6d0ac587600930c3657180066aac8 Mon Sep 17 00:00:00 2001 From: Søren Sandmann Pedersen Date: Fri, 18 Sep 2009 11:54:21 -0400 Subject: Eliminate _pixman_image_is_opaque() in favor of a new FAST_PATH_IS_OPAQUE flag The new FAST_PATH_IS_OPAQUE flag is computed along with the others in _pixman_image_validate(). --- pixman/pixman-image.c | 96 +++++++++++++++++++++---------------------------- pixman/pixman-private.h | 4 +-- pixman/pixman.c | 7 ++-- 3 files changed, 45 insertions(+), 62 deletions(-) diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index ff0fbbb..1014e64 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -298,6 +298,9 @@ compute_image_info (pixman_image_t *image) if (image->type == SOLID) { code = PIXMAN_solid; + + if (image->solid.color.alpha == 0xffff) + flags |= FAST_PATH_IS_OPAQUE; } else if (image->common.type == BITS) { @@ -317,10 +320,48 @@ compute_image_info (pixman_image_t *image) flags |= FAST_PATH_SIMPLE_REPEAT; } } + + if (image->common.repeat != PIXMAN_REPEAT_NONE && + !PIXMAN_FORMAT_A (image->bits.format)) + { + flags |= FAST_PATH_IS_OPAQUE; + } } else { code = PIXMAN_unknown; + + if (image->type == LINEAR || image->type == RADIAL) + { + if (image->common.repeat != PIXMAN_REPEAT_NONE) + { + int i; + + flags |= FAST_PATH_IS_OPAQUE; + + for (i = 0; i < image->gradient.n_stops; ++i) + { + if (image->gradient.stops[i].color.alpha != 0xffff) + { + flags &= ~FAST_PATH_IS_OPAQUE; + break; + } + } + } + } + } + + /* Both alpha maps and convolution filters can introduce + * non-opaqueness in otherwise opaque images. Also + * an image with component alpha turned on is only opaque + * if all channels are opaque, so we simply turn it off + * unconditionally for those images. + */ + if (image->common.alpha_map || + image->common.filter == PIXMAN_FILTER_CONVOLUTION || + image->common.component_alpha) + { + flags &= ~FAST_PATH_IS_OPAQUE; } image->common.flags = flags; @@ -628,58 +669,3 @@ _pixman_image_get_solid (pixman_image_t * image, return result; } - -pixman_bool_t -_pixman_image_is_opaque (pixman_image_t *image) -{ - int i; - - if (image->common.alpha_map) - return FALSE; - - switch (image->type) - { - case BITS: - if (image->common.repeat == PIXMAN_REPEAT_NONE) - return FALSE; - - if (PIXMAN_FORMAT_A (image->bits.format)) - return FALSE; - break; - - case LINEAR: - case RADIAL: - if (image->common.repeat == PIXMAN_REPEAT_NONE) - return FALSE; - - for (i = 0; i < image->gradient.n_stops; ++i) - { - if (image->gradient.stops[i].color.alpha != 0xffff) - return FALSE; - } - break; - - case CONICAL: - /* Conical gradients always have a transparent border */ - return FALSE; - break; - - case SOLID: - if (image->solid.color.alpha != 0xffff) - return FALSE; - break; - - default: - return FALSE; - break; - } - - /* Convolution filters can introduce translucency if the sum of the - * weights is lower than 1. - */ - if (image->common.filter == PIXMAN_FILTER_CONVOLUTION) - return FALSE; - - return TRUE; -} - diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index 1ad452a..d08440e 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -284,9 +284,6 @@ _pixman_image_reset_clip_region (pixman_image_t *image); void _pixman_image_validate (pixman_image_t *image); -pixman_bool_t -_pixman_image_is_opaque (pixman_image_t *image); - uint32_t _pixman_image_get_solid (pixman_image_t * image, pixman_format_code_t format); @@ -579,6 +576,7 @@ _pixman_choose_implementation (void); #define FAST_PATH_SCALE_TRANSFORM (1 << 10) #define FAST_PATH_NEAREST_FILTER (1 << 11) #define FAST_PATH_SIMPLE_REPEAT (1 << 12) +#define FAST_PATH_IS_OPAQUE (1 << 13) #define _FAST_PATH_STANDARD_FLAGS \ (FAST_PATH_ID_TRANSFORM | \ diff --git a/pixman/pixman.c b/pixman/pixman.c index e1bef17..905c7b2 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -88,14 +88,13 @@ pixman_optimize_operator (pixman_op_t op, pixman_bool_t is_source_opaque; pixman_bool_t is_dest_opaque; const optimized_operator_info_t *info = pixman_operator_can_be_optimized (op); - if (!info || mask_image) return op; - is_source_opaque = _pixman_image_is_opaque (src_image); - is_dest_opaque = _pixman_image_is_opaque (dst_image); + is_source_opaque = src_image->common.flags & FAST_PATH_IS_OPAQUE; + is_dest_opaque = dst_image->common.flags & FAST_PATH_IS_OPAQUE; - if (is_source_opaque == FALSE && is_dest_opaque == FALSE) + if (!is_source_opaque && !is_dest_opaque) return op; if (is_source_opaque && is_dest_opaque) -- cgit v1.2.3 From 35af45d5e3d3f893ccaa4ab2f947100eb9d840ac Mon Sep 17 00:00:00 2001 From: Søren Sandmann Pedersen Date: Mon, 22 Feb 2010 06:06:22 -0500 Subject: Turn need_workaround into another flag. Instead of storing it as a boolean in the image struct, just use another flag for it. --- pixman/pixman-bits-image.c | 6 +++-- pixman/pixman-image.c | 11 ++++++--- pixman/pixman-private.h | 4 ++-- pixman/pixman.c | 60 +++++++++++++++++++++------------------------- 4 files changed, 41 insertions(+), 40 deletions(-) diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index 6befcbb..90d6ad9 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -986,8 +986,10 @@ bits_image_property_changed (pixman_image_t *image) bits->store_scanline_64 = bits_image_store_scanline_64; bits->store_scanline_32 = bits_image_store_scanline_32; - bits->common.need_workaround = - source_image_needs_out_of_bounds_workaround (bits); + if (source_image_needs_out_of_bounds_workaround (bits)) + bits->common.flags |= FAST_PATH_NEEDS_WORKAROUND; + else + bits->common.flags &= ~FAST_PATH_NEEDS_WORKAROUND; } static uint32_t * diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index 1014e64..ef02993 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -117,7 +117,6 @@ _pixman_image_allocate (void) common->client_clip = FALSE; common->destroy_func = NULL; common->destroy_data = NULL; - common->need_workaround = FALSE; common->dirty = TRUE; } @@ -373,10 +372,16 @@ _pixman_image_validate (pixman_image_t *image) { if (image->common.dirty) { - image->common.property_changed (image); - compute_image_info (image); + /* It is important that property_changed is + * called *after* compute_image_info() because + * the NEEDS_WORKAROUND flag is computed in + * property_changed(). And compute_image_info() + * completely overwrites the flags field + */ + image->common.property_changed (image); + image->common.dirty = FALSE; } diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index d08440e..94451d3 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -86,7 +86,6 @@ struct image_common * the image is used as a source */ pixman_bool_t dirty; - pixman_bool_t need_workaround; pixman_transform_t * transform; pixman_repeat_t repeat; pixman_filter_t filter; @@ -559,7 +558,7 @@ _pixman_choose_implementation (void); #define PIXMAN_pixbuf PIXMAN_FORMAT (0, 2, 0, 0, 0, 0) #define PIXMAN_rpixbuf PIXMAN_FORMAT (0, 3, 0, 0, 0, 0) #define PIXMAN_unknown PIXMAN_FORMAT (0, 4, 0, 0, 0, 0) -#define PIXMAN_any PIXMAN_FORMAT (0, 5, 0, 0, 0, 0) +#define PIXMAN_any PIXMAN_FORMAT (0, 5, 0, 0, 0, 0) #define PIXMAN_OP_any (PIXMAN_N_OPERATORS + 1) @@ -577,6 +576,7 @@ _pixman_choose_implementation (void); #define FAST_PATH_NEAREST_FILTER (1 << 11) #define FAST_PATH_SIMPLE_REPEAT (1 << 12) #define FAST_PATH_IS_OPAQUE (1 << 13) +#define FAST_PATH_NEEDS_WORKAROUND (1 << 14) #define _FAST_PATH_STANDARD_FLAGS \ (FAST_PATH_ID_TRANSFORM | \ diff --git a/pixman/pixman.c b/pixman/pixman.c index 905c7b2..c0a985e 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -116,7 +116,7 @@ apply_workaround (pixman_image_t *image, int * save_dx, int * save_dy) { - if (image && image->common.need_workaround) + if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND)) { /* Some X servers generate images that point to the * wrong place in memory, but then set the clip region @@ -152,7 +152,7 @@ apply_workaround (pixman_image_t *image, static void unapply_workaround (pixman_image_t *image, uint32_t *bits, int dx, int dy) { - if (image && image->common.need_workaround) + if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND)) { image->bits.bits = bits; pixman_region32_translate (&image->common.clip_region, dx, dy); @@ -486,6 +486,13 @@ do_composite (pixman_implementation_t *imp, uint32_t src_flags, mask_flags, dest_flags; pixman_region32_t region; pixman_box32_t *extents; + uint32_t *src_bits; + int src_dx, src_dy; + uint32_t *mask_bits; + int mask_dx, mask_dy; + uint32_t *dest_bits; + int dest_dx, dest_dy; + pixman_bool_t need_workaround; src_format = src->common.extended_format_code; src_flags = src->common.flags; @@ -515,7 +522,17 @@ do_composite (pixman_implementation_t *imp, else if (src_format == PIXMAN_x8r8g8b8) src_format = mask_format = PIXMAN_rpixbuf; } - + + /* Check for workaround */ + need_workaround = (src_flags | mask_flags | dest_flags) & FAST_PATH_NEEDS_WORKAROUND; + + if (need_workaround) + { + apply_workaround (src, &src_x, &src_y, &src_bits, &src_dx, &src_dy); + apply_workaround (mask, &mask_x, &mask_y, &mask_bits, &mask_dx, &mask_dy); + apply_workaround (dest, &dest_x, &dest_y, &dest_bits, &dest_dx, &dest_dy); + } + pixman_region32_init (®ion); if (!pixman_compute_composite_region32 ( @@ -571,6 +588,13 @@ do_composite (pixman_implementation_t *imp, } done: + if (need_workaround) + { + unapply_workaround (src, src_bits, src_dx, src_dy); + unapply_workaround (mask, mask_bits, mask_dx, mask_dy); + unapply_workaround (dest, dest_bits, dest_dx, dest_dy); + } + pixman_region32_fini (®ion); } @@ -625,14 +649,6 @@ pixman_image_composite32 (pixman_op_t op, int32_t width, int32_t height) { - uint32_t *src_bits; - int src_dx, src_dy; - uint32_t *mask_bits; - int mask_dx, mask_dy; - uint32_t *dest_bits; - int dest_dx, dest_dy; - pixman_bool_t need_workaround; - _pixman_image_validate (src); if (mask) _pixman_image_validate (mask); @@ -654,34 +670,12 @@ pixman_image_composite32 (pixman_op_t op, if (!imp) imp = _pixman_choose_implementation (); - need_workaround = - (src->common.need_workaround) || - (mask && mask->common.need_workaround) || - (dest->common.need_workaround); - - if (need_workaround) - { - apply_workaround (src, &src_x, &src_y, &src_bits, &src_dx, &src_dy); - apply_workaround (mask, &mask_x, &mask_y, &mask_bits, &mask_dx, &mask_dy); - apply_workaround (dest, &dest_x, &dest_y, &dest_bits, &dest_dx, &dest_dy); - } - do_composite (imp, op, src, mask, dest, src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height); - - if (need_workaround) - { - if (src->common.need_workaround) - unapply_workaround (src, src_bits, src_dx, src_dy); - if (mask && mask->common.need_workaround) - unapply_workaround (mask, mask_bits, mask_dx, mask_dy); - if (dest->common.need_workaround) - unapply_workaround (dest, dest_bits, dest_dx, dest_dy); - } } PIXMAN_EXPORT pixman_bool_t -- cgit v1.2.3 From ac44db334066f68a837914a52d8d1368c85161ad Mon Sep 17 00:00:00 2001 From: Søren Sandmann Pedersen Date: Sun, 14 Feb 2010 19:14:44 -0500 Subject: Move workaround code to pixman-image.c It is more natural to put it where all the other flags are computed. --- pixman/pixman-bits-image.c | 54 ------------------------------------------ pixman/pixman-image.c | 59 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 55 insertions(+), 58 deletions(-) diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index 90d6ad9..3d78ff0 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -875,55 +875,6 @@ bits_image_fetch_untransformed_64 (pixman_image_t * image, } } -static pixman_bool_t out_of_bounds_workaround = TRUE; - -/* Old X servers rely on out-of-bounds accesses when they are asked - * to composite with a window as the source. They create a pixman image - * pointing to some bogus position in memory, but then they set a clip - * region to the position where the actual bits are. - * - * Due to a bug in old versions of pixman, where it would not clip - * against the image bounds when a clip region was set, this would - * actually work. So by default we allow certain out-of-bound access - * to happen unless explicitly disabled. - * - * Fixed X servers should call this function to disable the workaround. - */ -PIXMAN_EXPORT void -pixman_disable_out_of_bounds_workaround (void) -{ - out_of_bounds_workaround = FALSE; -} - -static pixman_bool_t -source_image_needs_out_of_bounds_workaround (bits_image_t *image) -{ - if (image->common.clip_sources && - image->common.repeat == PIXMAN_REPEAT_NONE && - image->common.have_clip_region && - out_of_bounds_workaround) - { - if (!image->common.client_clip) - { - /* There is no client clip, so if the clip region extends beyond the - * drawable geometry, it must be because the X server generated the - * bogus clip region. - */ - const pixman_box32_t *extents = pixman_region32_extents (&image->common.clip_region); - - if (extents->x1 >= 0 && extents->x2 <= image->width && - extents->y1 >= 0 && extents->y2 <= image->height) - { - return FALSE; - } - } - - return TRUE; - } - - return FALSE; -} - static void bits_image_property_changed (pixman_image_t *image) { @@ -985,11 +936,6 @@ bits_image_property_changed (pixman_image_t *image) bits->store_scanline_64 = bits_image_store_scanline_64; bits->store_scanline_32 = bits_image_store_scanline_32; - - if (source_image_needs_out_of_bounds_workaround (bits)) - bits->common.flags |= FAST_PATH_NEEDS_WORKAROUND; - else - bits->common.flags &= ~FAST_PATH_NEEDS_WORKAROUND; } static uint32_t * diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index ef02993..e66ae88 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -242,6 +242,55 @@ _pixman_image_reset_clip_region (pixman_image_t *image) image->common.have_clip_region = FALSE; } +static pixman_bool_t out_of_bounds_workaround = TRUE; + +/* Old X servers rely on out-of-bounds accesses when they are asked + * to composite with a window as the source. They create a pixman image + * pointing to some bogus position in memory, but then they set a clip + * region to the position where the actual bits are. + * + * Due to a bug in old versions of pixman, where it would not clip + * against the image bounds when a clip region was set, this would + * actually work. So by default we allow certain out-of-bound access + * to happen unless explicitly disabled. + * + * Fixed X servers should call this function to disable the workaround. + */ +PIXMAN_EXPORT void +pixman_disable_out_of_bounds_workaround (void) +{ + out_of_bounds_workaround = FALSE; +} + +static pixman_bool_t +source_image_needs_out_of_bounds_workaround (bits_image_t *image) +{ + if (image->common.clip_sources && + image->common.repeat == PIXMAN_REPEAT_NONE && + image->common.have_clip_region && + out_of_bounds_workaround) + { + if (!image->common.client_clip) + { + /* There is no client clip, so if the clip region extends beyond the + * drawable geometry, it must be because the X server generated the + * bogus clip region. + */ + const pixman_box32_t *extents = pixman_region32_extents (&image->common.clip_region); + + if (extents->x1 >= 0 && extents->x2 <= image->width && + extents->y1 >= 0 && extents->y2 <= image->height) + { + return FALSE; + } + } + + return TRUE; + } + + return FALSE; +} + static void compute_image_info (pixman_image_t *image) { @@ -325,6 +374,9 @@ compute_image_info (pixman_image_t *image) { flags |= FAST_PATH_IS_OPAQUE; } + + if (source_image_needs_out_of_bounds_workaround (&image->bits)) + flags |= FAST_PATH_NEEDS_WORKAROUND; } else { @@ -374,11 +426,10 @@ _pixman_image_validate (pixman_image_t *image) { compute_image_info (image); - /* It is important that property_changed is + /* It is important that property_changed is * called *after* compute_image_info() because - * the NEEDS_WORKAROUND flag is computed in - * property_changed(). And compute_image_info() - * completely overwrites the flags field + * property_changed() can make use of the flags + * to set up accessors etc. */ image->common.property_changed (image); -- cgit v1.2.3 From 3db76b90049f23723a0519d572b9cda7c672f7d5 Mon Sep 17 00:00:00 2001 From: Søren Sandmann Pedersen Date: Sun, 14 Feb 2010 19:18:35 -0500 Subject: Restructure the flags computation in compute_image_info(). Restructure the code to use switches instead of ifs. This saves a few comparisons and make the code slightly easier to follow. Also add some comments. --- pixman/pixman-image.c | 95 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 59 insertions(+), 36 deletions(-) diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index e66ae88..d09d193 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -276,7 +276,8 @@ source_image_needs_out_of_bounds_workaround (bits_image_t *image) * drawable geometry, it must be because the X server generated the * bogus clip region. */ - const pixman_box32_t *extents = pixman_region32_extents (&image->common.clip_region); + const pixman_box32_t *extents = + pixman_region32_extents (&image->common.clip_region); if (extents->x1 >= 0 && extents->x2 <= image->width && extents->y1 >= 0 && extents->y2 <= image->height) @@ -297,12 +298,12 @@ compute_image_info (pixman_image_t *image) pixman_format_code_t code; uint32_t flags = 0; + /* Transform */ if (!image->common.transform) { flags |= FAST_PATH_ID_TRANSFORM; } - else if (image->common.transform && - image->common.transform->matrix[0][1] == 0 && + else if (image->common.transform->matrix[0][1] == 0 && image->common.transform->matrix[1][0] == 0 && image->common.transform->matrix[2][0] == 0 && image->common.transform->matrix[2][1] == 0 && @@ -311,47 +312,61 @@ compute_image_info (pixman_image_t *image) flags |= FAST_PATH_SCALE_TRANSFORM; } + /* Alpha map */ if (!image->common.alpha_map) flags |= FAST_PATH_NO_ALPHA_MAP; - if (image->common.filter != PIXMAN_FILTER_CONVOLUTION) + /* Filter */ + switch (image->common.filter) { - flags |= FAST_PATH_NO_CONVOLUTION_FILTER; + case PIXMAN_FILTER_NEAREST: + case PIXMAN_FILTER_FAST: + flags |= (FAST_PATH_NEAREST_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER); + break; + + case PIXMAN_FILTER_CONVOLUTION: + break; - if (image->common.filter == PIXMAN_FILTER_NEAREST) - flags |= FAST_PATH_NEAREST_FILTER; + default: + flags |= FAST_PATH_NO_CONVOLUTION_FILTER; + break; } - if (image->common.repeat != PIXMAN_REPEAT_PAD) + /* Repeat mode */ + switch (image->common.repeat) + { + case PIXMAN_REPEAT_REFLECT: flags |= FAST_PATH_NO_PAD_REPEAT; + break; - if (image->common.repeat != PIXMAN_REPEAT_REFLECT) + case PIXMAN_REPEAT_PAD: flags |= FAST_PATH_NO_REFLECT_REPEAT; + break; - flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NO_WIDE_FORMAT); - if (image->common.type == BITS) - { - if (image->bits.read_func || image->bits.write_func) - flags &= ~FAST_PATH_NO_ACCESSORS; - - if (PIXMAN_FORMAT_IS_WIDE (image->bits.format)) - flags &= ~FAST_PATH_NO_WIDE_FORMAT; + default: + flags |= (FAST_PATH_NO_REFLECT_REPEAT | FAST_PATH_NO_PAD_REPEAT); + break; } + /* Component alpha */ if (image->common.component_alpha) flags |= FAST_PATH_COMPONENT_ALPHA; else flags |= FAST_PATH_UNIFIED_ALPHA; - if (image->type == SOLID) + flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NO_WIDE_FORMAT); + + /* Type specific checks */ + switch (image->type) { + case SOLID: code = PIXMAN_solid; if (image->solid.color.alpha == 0xffff) flags |= FAST_PATH_IS_OPAQUE; - } - else if (image->common.type == BITS) - { + break; + + case BITS: if (image->bits.width == 1 && image->bits.height == 1 && image->common.repeat != PIXMAN_REPEAT_NONE) @@ -377,29 +392,37 @@ compute_image_info (pixman_image_t *image) if (source_image_needs_out_of_bounds_workaround (&image->bits)) flags |= FAST_PATH_NEEDS_WORKAROUND; - } - else - { + + if (image->bits.read_func || image->bits.write_func) + flags &= ~FAST_PATH_NO_ACCESSORS; + + if (PIXMAN_FORMAT_IS_WIDE (image->bits.format)) + flags &= ~FAST_PATH_NO_WIDE_FORMAT; + break; + + case LINEAR: + case RADIAL: code = PIXMAN_unknown; - if (image->type == LINEAR || image->type == RADIAL) + if (image->common.repeat != PIXMAN_REPEAT_NONE) { - if (image->common.repeat != PIXMAN_REPEAT_NONE) - { - int i; - - flags |= FAST_PATH_IS_OPAQUE; + int i; - for (i = 0; i < image->gradient.n_stops; ++i) + flags |= FAST_PATH_IS_OPAQUE; + for (i = 0; i < image->gradient.n_stops; ++i) + { + if (image->gradient.stops[i].color.alpha != 0xffff) { - if (image->gradient.stops[i].color.alpha != 0xffff) - { - flags &= ~FAST_PATH_IS_OPAQUE; - break; - } + flags &= ~FAST_PATH_IS_OPAQUE; + break; } } } + break; + + default: + code = PIXMAN_unknown; + break; } /* Both alpha maps and convolution filters can introduce -- cgit v1.2.3