From f2d8a5caa63596739b4dc47c00daaaafd9f522e2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=B8ren=20Sandmann?= Date: Mon, 10 Mar 2008 23:41:52 -0400 Subject: [PATCH] Add rounding epsilon for NEAREST filter after transformation, not before. For nearest filtering, the transformed location must be rounded to the nearest sample. For locations that precisely in the middle between two samples, we round down by adding -epsilon to the coordinates. Before, we would do this on untransformed coordinates. This patch changes it to happen after transformation. It also clarifies the difference between sample locations and rounding. Reported by Robert O'Callahan. --- pixman/pixman-compose.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/pixman/pixman-compose.c b/pixman/pixman-compose.c index 1b2d581..faf2523 100644 --- a/pixman/pixman-compose.c +++ b/pixman/pixman-compose.c @@ -4180,6 +4180,19 @@ fbFetchTransformed_Convolution(bits_image_t * pict, int width, uint32_t *buffer, } static void +adjust (pixman_vector_t *v, pixman_vector_t *u, pixman_fixed_t adjustment) +{ + int delta_v = (adjustment * v->vector[2]) >> 16; + int delta_u = (adjustment * u->vector[2]) >> 16; + + v->vector[0] += delta_v; + v->vector[1] += delta_v; + + u->vector[0] += delta_u; + u->vector[1] += delta_u; +} + +static void fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits) { uint32_t *bits; @@ -4192,8 +4205,8 @@ fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uint32_t *buffe stride = pict->rowstride; /* reference point is the center of the pixel */ - v.vector[0] = pixman_int_to_fixed(x) + pixman_fixed_1 / 2 - 1; - v.vector[1] = pixman_int_to_fixed(y) + pixman_fixed_1 / 2 - 1; + v.vector[0] = pixman_int_to_fixed(x) + pixman_fixed_1 / 2; + v.vector[1] = pixman_int_to_fixed(y) + pixman_fixed_1 / 2; v.vector[2] = pixman_fixed_1; /* when using convolution filters or PIXMAN_REPEAT_PAD one might get here without a transform */ @@ -4216,8 +4229,14 @@ fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uint32_t *buffe unit.vector[2] = 0; } + /* This allows filtering code to pretend that pixels are located at integer coordinates */ + adjust (&v, &unit, -(pixman_fixed_1 / 2)); + if (pict->common.filter == PIXMAN_FILTER_NEAREST || pict->common.filter == PIXMAN_FILTER_FAST) { + /* Round down to closest integer, ensuring that 0.5 rounds to 0, not 1 */ + adjust (&v, &unit, pixman_fixed_1 / 2 - pixman_fixed_e); + if (pict->common.repeat == PIXMAN_REPEAT_NORMAL) { fbFetchTransformed_Nearest_Normal(pict, width, buffer, mask, maskBits, affine, v, unit); @@ -4235,12 +4254,6 @@ fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uint32_t *buffe pict->common.filter == PIXMAN_FILTER_GOOD || pict->common.filter == PIXMAN_FILTER_BEST) { - /* adjust vector for maximum contribution at 0.5, 0.5 of each texel. */ - v.vector[0] -= v.vector[2] / 2; - v.vector[1] -= v.vector[2] / 2; - unit.vector[0] -= unit.vector[2] / 2; - unit.vector[1] -= unit.vector[2] / 2; - if (pict->common.repeat == PIXMAN_REPEAT_NORMAL) { fbFetchTransformed_Bilinear_Normal(pict, width, buffer, mask, maskBits, affine, v, unit); @@ -4256,6 +4269,9 @@ fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uint32_t *buffe } else if (pict->common.filter == PIXMAN_FILTER_CONVOLUTION) { + /* Round to closest integer, ensuring that 0.5 rounds to 0, not 1 */ + adjust (&v, &unit, pixman_fixed_1 / 2 - pixman_fixed_e); + fbFetchTransformed_Convolution(pict, width, buffer, mask, maskBits, affine, v, unit); } -- 2.7.4