BILINEAR->NEAREST filter optimization for simple rotation and translation
authorSiarhei Siamashka <siarhei.siamashka@nokia.com>
Sun, 22 May 2011 19:51:00 +0000 (22:51 +0300)
committerSøren Sandmann Pedersen <ssp@redhat.com>
Wed, 21 Sep 2011 22:55:25 +0000 (18:55 -0400)
Simple rotation and translation are the additional cases when BILINEAR
filter can be safely reduced to NEAREST.

pixman/pixman-image.c

index 88262f7..a3bb9b6 100644 (file)
@@ -251,9 +251,46 @@ compute_image_info (pixman_image_t *image)
     case PIXMAN_FILTER_BEST:
        flags |= (FAST_PATH_BILINEAR_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
 
-       /* Reduce BILINEAR to NEAREST for identity transforms */
+       /* 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;
+           }
+       }
        break;
 
     case PIXMAN_FILTER_CONVOLUTION: