diff options
author | Søren Sandmann Pedersen <sandmann@redhat.com> | 2010-03-04 02:30:22 -0500 |
---|---|---|
committer | Søren Sandmann Pedersen <sandmann@redhat.com> | 2010-03-04 02:30:22 -0500 |
commit | 14bb054d9695abb284e22a1de31337e0e41bb4e3 (patch) | |
tree | ca4fff205f7a7ff5a9f3bdc356b1bde13d1f618b | |
parent | 9a8e404d44b6ed9817d088966cec324a38e60897 (diff) | |
parent | 3db76b90049f23723a0519d572b9cda7c672f7d5 (diff) |
Merge branch 'more-flags'
-rw-r--r-- | pixman/pixman-bits-image.c | 52 | ||||
-rw-r--r-- | pixman/pixman-image.c | 283 | ||||
-rw-r--r-- | pixman/pixman-private.h | 15 | ||||
-rw-r--r-- | pixman/pixman.c | 160 |
4 files changed, 256 insertions, 254 deletions
diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index 6befcbb..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,9 +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; - - bits->common.need_workaround = - source_image_needs_out_of_bounds_workaround (bits); } static uint32_t * diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index 6036c56..d09d193 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; } @@ -243,12 +242,220 @@ _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) +{ + pixman_format_code_t code; + uint32_t flags = 0; + + /* Transform */ + 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; + } + + /* Alpha map */ + if (!image->common.alpha_map) + flags |= FAST_PATH_NO_ALPHA_MAP; + + /* Filter */ + switch (image->common.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; + + default: + flags |= FAST_PATH_NO_CONVOLUTION_FILTER; + break; + } + + /* Repeat mode */ + switch (image->common.repeat) + { + case PIXMAN_REPEAT_REFLECT: + flags |= FAST_PATH_NO_PAD_REPEAT; + break; + + case PIXMAN_REPEAT_PAD: + flags |= FAST_PATH_NO_REFLECT_REPEAT; + break; + + 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; + + 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; + break; + + case BITS: + if (image->bits.width == 1 && + image->bits.height == 1 && + image->common.repeat != PIXMAN_REPEAT_NONE) + { + code = PIXMAN_solid; + } + else + { + code = image->bits.format; + + if (!image->common.transform && + image->common.repeat == PIXMAN_REPEAT_NORMAL) + { + flags |= FAST_PATH_SIMPLE_REPEAT; + } + } + + if (image->common.repeat != PIXMAN_REPEAT_NONE && + !PIXMAN_FORMAT_A (image->bits.format)) + { + flags |= FAST_PATH_IS_OPAQUE; + } + + if (source_image_needs_out_of_bounds_workaround (&image->bits)) + flags |= FAST_PATH_NEEDS_WORKAROUND; + + 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->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; + } + } + } + break; + + default: + code = PIXMAN_unknown; + 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; + image->common.extended_format_code = code; +} + void _pixman_image_validate (pixman_image_t *image) { if (image->common.dirty) { + compute_image_info (image); + + /* It is important that property_changed is + * called *after* compute_image_info() because + * property_changed() can make use of the flags + * to set up accessors etc. + */ image->common.property_changed (image); + image->common.dirty = FALSE; } @@ -522,25 +729,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) @@ -560,58 +748,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 7ed8aa7..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; @@ -103,6 +102,9 @@ struct image_common pixman_image_destroy_func_t destroy_func; void * destroy_data; + + uint32_t flags; + pixman_format_code_t extended_format_code; }; struct source_image @@ -281,12 +283,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); - -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); @@ -562,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) @@ -578,6 +574,9 @@ _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_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 6a260ed..c0a985e 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) @@ -117,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 @@ -153,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); @@ -448,69 +447,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 = 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; - - if (_pixman_image_is_solid (image)) - *code = PIXMAN_solid; - else if (image->common.type == BITS) - *code = image->bits.format; - else - *code = PIXMAN_unknown; -} - static force_inline pixman_bool_t image_covers (pixman_image_t *image, pixman_box32_t *extents, @@ -548,22 +484,33 @@ 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; + 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; - get_image_info (src, &src_format, &src_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) && @@ -575,20 +522,17 @@ do_composite (pixman_implementation_t *imp, else if (src_format == PIXMAN_x8r8g8b8) 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; - + + /* 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 ( @@ -631,7 +575,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); @@ -643,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); } @@ -697,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); @@ -726,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 |