[Pixman] [PATCH v14 20/22] pixman-image: Detect all 8 transforms that can do nearest filter

spitzak at gmail.com spitzak at gmail.com
Mon Mar 7 01:06:55 UTC 2016


From: Bill Spitzak <spitzak at 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 <spitzak at 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



More information about the Pixman mailing list