summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Spitzak <spitzak@gmail.com>2016-03-06 17:06:55 -0800
committerSøren Sandmann Pedersen <soren.sandmann@gmail.com>2016-03-11 00:00:46 -0500
commit6b056bad2f909d0e4542a1974efb1a370467c69a (patch)
treec765ef0e3bee90aa777ef879a82e8999424a4e09
parenta98c7bdfe3f82d92f52fcfee722323b34d4f7656 (diff)
pixman-image: Detect all 8 transforms that can do nearest filter
This patch consolidates the examination of the matrix into one place, and detects the reflected versions of the transforms that can be done with nearest filter. v14: Split this code from the GOOD/BEST as I think it will be accepted. Signed-off-by: Bill Spitzak <spitzak@gmail.com>
-rw-r--r--pixman/pixman-image.c119
1 files changed, 57 insertions, 62 deletions
diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c
index 1ff1a497..8ad28912 100644
--- a/pixman/pixman-image.c
+++ b/pixman/pixman-image.c
@@ -266,52 +266,82 @@ compute_image_info (pixman_image_t *image)
{
pixman_format_code_t code;
uint32_t flags = 0;
+ int nearest_ok = FALSE;
+ pixman_fixed_t (*m)[3];
/* Transform */
if (!image->common.transform)
{
+ nearest_ok = TRUE;
flags |= (FAST_PATH_ID_TRANSFORM |
FAST_PATH_X_UNIT_POSITIVE |
FAST_PATH_Y_UNIT_ZERO |
FAST_PATH_AFFINE_TRANSFORM);
+ m = 0;
}
else
{
+ m = image->common.transform->matrix;
+
flags |= FAST_PATH_HAS_TRANSFORM;
- if (image->common.transform->matrix[2][0] == 0 &&
- image->common.transform->matrix[2][1] == 0 &&
- image->common.transform->matrix[2][2] == pixman_fixed_1)
+ if (m[2][0] == 0 &&
+ m[2][1] == 0 &&
+ m[2][2] == pixman_fixed_1)
{
flags |= FAST_PATH_AFFINE_TRANSFORM;
- if (image->common.transform->matrix[0][1] == 0 &&
- image->common.transform->matrix[1][0] == 0)
+ if (m[0][1] == 0 &&
+ m[1][0] == 0)
{
- if (image->common.transform->matrix[0][0] == -pixman_fixed_1 &&
- image->common.transform->matrix[1][1] == -pixman_fixed_1)
+ flags |= FAST_PATH_SCALE_TRANSFORM;
+ if (abs(m[0][0]) == pixman_fixed_1 &&
+ abs(m[1][1]) == pixman_fixed_1)
{
- flags |= FAST_PATH_ROTATE_180_TRANSFORM;
+ /* no scaling */
+ nearest_ok = TRUE;
+ if (m[0][0] < 0 && m[1][1] < 0)
+ flags |= FAST_PATH_ROTATE_180_TRANSFORM;
}
- flags |= FAST_PATH_SCALE_TRANSFORM;
}
- else if (image->common.transform->matrix[0][0] == 0 &&
- image->common.transform->matrix[1][1] == 0)
+ else if (m[0][0] == 0 &&
+ m[1][1] == 0)
{
- pixman_fixed_t m01 = image->common.transform->matrix[0][1];
- pixman_fixed_t m10 = image->common.transform->matrix[1][0];
+ /* x/y axis are swapped, 90 degree rotation */
+ if (abs(m[0][1]) == pixman_fixed_1 &&
+ abs(m[1][0]) == pixman_fixed_1)
+ {
+ /* no scaling */
+ nearest_ok = TRUE;
+ if (m[0][1] < 0 && m[1][0] > 0)
+ flags |= FAST_PATH_ROTATE_90_TRANSFORM;
+ else if (m[0][1] > 0 && m[1][0] < 0)
+ flags |= FAST_PATH_ROTATE_270_TRANSFORM;
+ }
+ }
- if (m01 == -pixman_fixed_1 && m10 == pixman_fixed_1)
- flags |= FAST_PATH_ROTATE_90_TRANSFORM;
- else if (m01 == pixman_fixed_1 && m10 == -pixman_fixed_1)
- flags |= FAST_PATH_ROTATE_270_TRANSFORM;
+ if (nearest_ok)
+ {
+ /* reject non-integer translation: */
+ if (pixman_fixed_frac (m[0][2] | m[1][2]))
+ nearest_ok = FALSE;
+ /* FIXME: there are some affine-test failures, showing
+ * that handling of BILINEAR and NEAREST filter is not
+ * quite equivalent when getting close to 32K for the
+ * translation components of the matrix. That's likely
+ * some bug, but for now just skip BILINEAR->NEAREST
+ * optimization in this case.
+ */
+ else if (abs(m[0][2]) > pixman_int_to_fixed (30000) ||
+ abs(m[1][2]) > pixman_int_to_fixed (30000))
+ nearest_ok = FALSE;
}
}
- if (image->common.transform->matrix[0][0] > 0)
+ if (m[0][0] > 0)
flags |= FAST_PATH_X_UNIT_POSITIVE;
- if (image->common.transform->matrix[1][0] == 0)
+ if (m[1][0] == 0)
flags |= FAST_PATH_Y_UNIT_ZERO;
}
@@ -326,48 +356,10 @@ compute_image_info (pixman_image_t *image)
case PIXMAN_FILTER_BILINEAR:
case PIXMAN_FILTER_GOOD:
case PIXMAN_FILTER_BEST:
- flags |= (FAST_PATH_BILINEAR_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
-
- /* Here we have a chance to optimize BILINEAR filter to NEAREST if
- * they are equivalent for the currently used transformation matrix.
- */
- if (flags & FAST_PATH_ID_TRANSFORM)
- {
- flags |= FAST_PATH_NEAREST_FILTER;
- }
- else if (
- /* affine and integer translation components in matrix ... */
- ((flags & FAST_PATH_AFFINE_TRANSFORM) &&
- !pixman_fixed_frac (image->common.transform->matrix[0][2] |
- image->common.transform->matrix[1][2])) &&
- (
- /* ... combined with a simple rotation */
- (flags & (FAST_PATH_ROTATE_90_TRANSFORM |
- FAST_PATH_ROTATE_180_TRANSFORM |
- FAST_PATH_ROTATE_270_TRANSFORM)) ||
- /* ... or combined with a simple non-rotated translation */
- (image->common.transform->matrix[0][0] == pixman_fixed_1 &&
- image->common.transform->matrix[1][1] == pixman_fixed_1 &&
- image->common.transform->matrix[0][1] == 0 &&
- image->common.transform->matrix[1][0] == 0)
- )
- )
- {
- /* FIXME: there are some affine-test failures, showing that
- * handling of BILINEAR and NEAREST filter is not quite
- * equivalent when getting close to 32K for the translation
- * components of the matrix. That's likely some bug, but for
- * now just skip BILINEAR->NEAREST optimization in this case.
- */
- pixman_fixed_t magic_limit = pixman_int_to_fixed (30000);
- if (image->common.transform->matrix[0][2] <= magic_limit &&
- image->common.transform->matrix[1][2] <= magic_limit &&
- image->common.transform->matrix[0][2] >= -magic_limit &&
- image->common.transform->matrix[1][2] >= -magic_limit)
- {
- flags |= FAST_PATH_NEAREST_FILTER;
- }
- }
+ if (nearest_ok)
+ flags |= (FAST_PATH_NEAREST_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
+ else
+ flags |= (FAST_PATH_BILINEAR_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
break;
case PIXMAN_FILTER_CONVOLUTION:
@@ -378,7 +370,10 @@ compute_image_info (pixman_image_t *image)
break;
default:
- flags |= FAST_PATH_NO_CONVOLUTION_FILTER;
+ if (nearest_ok)
+ flags |= (FAST_PATH_NEAREST_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
+ else
+ flags |= FAST_PATH_NO_CONVOLUTION_FILTER;
break;
}