From: Bill Spitzak <spit...@gmail.com> 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 <spit...@gmail.com> --- pixman/pixman-image.c | 119 ++++++++++++++++++++++++-------------------------- 1 file changed, 57 insertions(+), 62 deletions(-) diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index 1ff1a49..8ad2891 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; } -- 1.9.1 _______________________________________________ Pixman mailing list Pixman@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/pixman