Soeren Sandmann <sandm...@daimi.au.dk> writes: > Instead, I think both issues can be fixed by using a new function: > > compute_sample_bounds (transform, box, filter) > > that would do the rounded transformation on each of the four corner > pixels, adding the filter extents, and then compute the bounding box > of that instead. Does that seem like a reasonable plan?
Here is an attempt at doing this. Soren >From 1c04ce9105522ef68b28ea3a299135081d77a2b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Sandmann=20Pedersen?= <s...@redhat.com> Date: Thu, 22 Jul 2010 04:27:45 -0400 Subject: [PATCH] Add new compute_sample_extents() and use it for FAST_PATH_SAMPLES_COVER_CLIP Previously we were using pixman_transform_bounds() to compute which source samples would be used for a composite operation. This is incorrect though because (a) pixman_transform_bounds() is transforming the bounding box of the destination samples, which means it is too pessimistic, (b) it isn't rounding the same way as we do during sampling, which could make it too optimistic in some cases, and (c) it didn't take the filter of the operation into account. The new function takes care of all three issues. --- pixman/pixman.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 107 insertions(+), 8 deletions(-) diff --git a/pixman/pixman.c b/pixman/pixman.c index 80a766a..9d184ed 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -488,6 +488,108 @@ walk_region_internal (pixman_implementation_t *imp, } } +static pixman_bool_t +compute_sample_extent (pixman_image_t *image, + pixman_box16_t *box) +{ + pixman_transform_t *transform = image->common.transform; + pixman_filter_t filter = image->common.filter; + int x1, y1, x2, y2; + pixman_fixed_t *params; + pixman_fixed_t x_off, y_off; + int width, height; + pixman_vector_t v[4]; + int i; + + switch (filter) + { + case PIXMAN_FILTER_CONVOLUTION: + params = image->common.filter_params; + x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1); + y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1); + width = pixman_fixed_to_int (params[0]); + height = pixman_fixed_to_int (params[1]); + break; + + case PIXMAN_FILTER_GOOD: + case PIXMAN_FILTER_BEST: + case PIXMAN_FILTER_BILINEAR: + x_off = - pixman_fixed_1 / 2; + y_off = - pixman_fixed_1 / 2; + width = 1; + height = 1; + break; + + case PIXMAN_FILTER_FAST: + case PIXMAN_FILTER_NEAREST: + x_off = - pixman_fixed_e; + y_off = - pixman_fixed_e; + width = 0; + height = 0; + break; + + default: + return FALSE; + } + + if (!transform) + { + box->x1 = pixman_fixed_to_int (pixman_int_to_fixed (box->x1) + pixman_fixed_1 / 2 + x_off); + box->y1 = pixman_fixed_to_int (pixman_int_to_fixed (box->y1) + pixman_fixed_1 / 2 + y_off); + box->x2 = pixman_fixed_to_int (pixman_int_to_fixed (box->x2) - pixman_fixed_1 / 2 + x_off) + width + 1; + box->y2 = pixman_fixed_to_int (pixman_int_to_fixed (box->y2) - pixman_fixed_1 / 2 + y_off) + height + 1; + return TRUE; + } + + v[0].vector[0] = pixman_int_to_fixed (box->x1) + pixman_fixed_1 / 2; + v[0].vector[1] = pixman_int_to_fixed (box->y1) + pixman_fixed_1 / 2; + v[0].vector[2] = pixman_int_to_fixed (1); + + v[1].vector[0] = pixman_int_to_fixed (box->x2) - pixman_fixed_1 / 2; + v[1].vector[1] = pixman_int_to_fixed (box->y1) + pixman_fixed_1 / 2; + v[1].vector[2] = pixman_int_to_fixed (1); + + v[2].vector[0] = pixman_int_to_fixed (box->x2) - pixman_fixed_1 / 2; + v[2].vector[1] = pixman_int_to_fixed (box->y2) - pixman_fixed_1 / 2; + v[2].vector[2] = pixman_int_to_fixed (1); + + v[3].vector[0] = pixman_int_to_fixed (box->x1) + pixman_fixed_1 / 2; + v[3].vector[1] = pixman_int_to_fixed (box->y2) - pixman_fixed_1 / 2; + v[3].vector[2] = pixman_int_to_fixed (1); + + for (i = 0; i < 4; ++i) + { + if (!pixman_transform_point (transform, &v[i])) + return FALSE; + + x1 = pixman_fixed_to_int (v[i].vector[0] + x_off); + y1 = pixman_fixed_to_int (v[i].vector[1] + y_off); + x2 = x1 + width + 1; + y2 = y1 + height + 1; + + if (i == 0) + { + box->x1 = x1; + box->y1 = y1; + box->x2 = x2; + box->y2 = y2; + } + else + { + if (x1 < box->x1) + box->x1 = x1; + if (y1 < box->y1) + box->y1 = y1; + if (x2 > box->x2) + box->x2 = x2; + if (y2 > box->y2) + box->y2 = y2; + } + } + + return TRUE; +} + #define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX)) static force_inline uint32_t @@ -522,15 +624,12 @@ compute_src_extents_flags (pixman_image_t *image, extents16.x2 = extents->x2 - x; extents16.y2 = extents->y2 - y; - if (!image->common.transform || - pixman_transform_bounds (image->common.transform, &extents16)) + if (compute_sample_extent (image, &extents16) && + extents16.x1 >= 0 && extents16.y1 >= 0 && + extents16.x2 <= image->bits.width && + extents16.y2 <= image->bits.height) { - if (extents16.x1 >= 0 && extents16.y1 >= 0 && - extents16.x2 <= image->bits.width && - extents16.y2 <= image->bits.height) - { - flags |= FAST_PATH_SAMPLES_COVER_CLIP; - } + flags |= FAST_PATH_SAMPLES_COVER_CLIP; } } -- 1.7.0.1 _______________________________________________ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman