diff options
author | Bill Spitzak <spitzak@gmail.com> | 2016-03-06 17:06:55 -0800 |
---|---|---|
committer | Søren Sandmann Pedersen <soren.sandmann@gmail.com> | 2016-03-11 00:00:46 -0500 |
commit | 6b056bad2f909d0e4542a1974efb1a370467c69a (patch) | |
tree | c765ef0e3bee90aa777ef879a82e8999424a4e09 | |
parent | a98c7bdfe3f82d92f52fcfee722323b34d4f7656 (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.c | 119 |
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; } |