[Pixman] [PATCH 2/3] Optimize BILINEAR filter to NEAREST for identity transforms

Siarhei Siamashka siarhei.siamashka at gmail.com
Sun May 22 14:15:14 PDT 2011


From: Siarhei Siamashka <siarhei.siamashka at nokia.com>

When doing non-transformed composite operations with the source images
having BILINEAR filter set, standard fast paths should be still
perfectly usable just like for the NEAREST filter case.

But because BILINEAR filter samples 2x2 pixel block in the source image
for each corresponding destination pixel, FAST_PATH_SAMPLES_COVER_CLIP
flag may not be set if the composite operation covers the whole source
image including the last pixel in the scanline (the rightmost pixels of
the last 2x2 block are considered to be outside of the source image
bounds even though they have zero weight for interpolation).

The patch tries to solve this problem in the following way:
1. All the fast paths which required FAST_PATH_NO_CONVOLUTION_FILTER
   earlier, now need FAST_PATH_NEAREST_FILTER and expect that BILINEAR
   filter will be optimized to NEAREST for the cases where they are
   equivalent.
2. Now "common.filter" stores the filter value originally set by the
   client application. Inside of "compute_image_info" function, this
   value is decoded into flags and BILINEAR may be optimized to
   NEAREST here. For the consistency sake, all the code other than
   "pixman_image_set_filter" and "compute_image_info" must only
   rely on "common.flags" for filter type identification in order
   to avoid confusing between NEAREST and BILINEAR later in the code.

Fixes:
   https://bugs.freedesktop.org/show_bug.cgi?id=37421
---
 pixman/pixman-bits-image.c |   22 ++++------------------
 pixman/pixman-image.c      |   16 +++++++++++++---
 pixman/pixman-private.h    |    4 ++--
 pixman/pixman.c            |   40 ++++++++++++++++++----------------------
 4 files changed, 37 insertions(+), 45 deletions(-)

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 4e9ed14..03314e2 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -568,26 +568,12 @@ bits_image_fetch_pixel_filtered (bits_image_t *image,
 				 pixman_fixed_t y,
 				 get_pixel_t    get_pixel)
 {
-    switch (image->common.filter)
-    {
-    case PIXMAN_FILTER_NEAREST:
-    case PIXMAN_FILTER_FAST:
+    if (image->common.flags & FAST_PATH_NEAREST_FILTER)
 	return bits_image_fetch_pixel_nearest (image, x, y, get_pixel);
-	break;
-
-    case PIXMAN_FILTER_BILINEAR:
-    case PIXMAN_FILTER_GOOD:
-    case PIXMAN_FILTER_BEST:
+    else if (image->common.flags & FAST_PATH_BILINEAR_FILTER)
 	return bits_image_fetch_pixel_bilinear (image, x, y, get_pixel);
-	break;
-
-    case PIXMAN_FILTER_CONVOLUTION:
+    else if (image->common.flags & FAST_PATH_CONVOLUTION_FILTER)
 	return bits_image_fetch_pixel_convolution (image, x, y, get_pixel);
-	break;
-
-    default:
-        break;
-    }
 
     return 0;
 }
@@ -1228,7 +1214,7 @@ static const fetcher_info_t fetcher_info[] =
     { PIXMAN_any,
       (FAST_PATH_NO_ALPHA_MAP			|
        FAST_PATH_ID_TRANSFORM			|
-       FAST_PATH_NO_CONVOLUTION_FILTER		|
+       FAST_PATH_NEAREST_FILTER			|
        FAST_PATH_NO_PAD_REPEAT			|
        FAST_PATH_NO_REFLECT_REPEAT),
       bits_image_fetch_untransformed_32,
diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c
index 84bacf8..4784c22 100644
--- a/pixman/pixman-image.c
+++ b/pixman/pixman-image.c
@@ -243,20 +243,30 @@ compute_image_info (pixman_image_t *image)
     {
     case PIXMAN_FILTER_NEAREST:
     case PIXMAN_FILTER_FAST:
-	flags |= (FAST_PATH_NEAREST_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
+	flags |= FAST_PATH_NEAREST_FILTER;
 	break;
 
     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
+	{
+	    flags |= FAST_PATH_BILINEAR_FILTER;
+	}
 	break;
 
     case PIXMAN_FILTER_CONVOLUTION:
+	flags |= FAST_PATH_CONVOLUTION_FILTER;
 	break;
 
     default:
-	flags |= FAST_PATH_NO_CONVOLUTION_FILTER;
 	break;
     }
 
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 2996907..a4e4022 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -576,7 +576,7 @@ _pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask);
 
 #define FAST_PATH_ID_TRANSFORM			(1 <<  0)
 #define FAST_PATH_NO_ALPHA_MAP			(1 <<  1)
-#define FAST_PATH_NO_CONVOLUTION_FILTER		(1 <<  2)
+#define FAST_PATH_CONVOLUTION_FILTER		(1 <<  2)
 #define FAST_PATH_NO_PAD_REPEAT			(1 <<  3)
 #define FAST_PATH_NO_REFLECT_REPEAT		(1 <<  4)
 #define FAST_PATH_NO_ACCESSORS			(1 <<  5)
@@ -620,7 +620,7 @@ _pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask);
      FAST_PATH_NO_PAD_REPEAT)
 
 #define FAST_PATH_STANDARD_FLAGS					\
-    (FAST_PATH_NO_CONVOLUTION_FILTER	|				\
+    (FAST_PATH_NEAREST_FILTER		|				\
      FAST_PATH_NO_ACCESSORS		|				\
      FAST_PATH_NO_ALPHA_MAP		|				\
      FAST_PATH_NARROW_FORMAT)
diff --git a/pixman/pixman.c b/pixman/pixman.c
index 61d3a92..01cd115 100644
--- a/pixman/pixman.c
+++ b/pixman/pixman.c
@@ -588,34 +588,30 @@ analyze_extent (pixman_image_t *image, int x, int y,
 	    return TRUE;
 	}
     
-	switch (image->common.filter)
+	if (image->common.flags & FAST_PATH_NEAREST_FILTER)
+	{
+	    x_off = - pixman_fixed_e;
+	    y_off = - pixman_fixed_e;
+	    width = 0;
+	    height = 0;
+	}
+	else if (image->common.flags & FAST_PATH_BILINEAR_FILTER)
+	{
+	    x_off = - pixman_fixed_1 / 2;
+	    y_off = - pixman_fixed_1 / 2;
+	    width = pixman_fixed_1;
+	    height = pixman_fixed_1;
+	}
+	else if (image->common.flags & FAST_PATH_CONVOLUTION_FILTER)
 	{
-	case PIXMAN_FILTER_CONVOLUTION:
 	    params = image->common.filter_params;
 	    x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1);
 	    y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1);
 	    width = params[0];
 	    height = params[1];
-	    break;
-
-	case PIXMAN_FILTER_GOOD:
-	case PIXMAN_FILTER_BEST:
-	case PIXMAN_FILTER_BILINEAR:
-	    x_off = - pixman_fixed_1 / 2;
-	    y_off = - pixman_fixed_1 / 2;
-	    width = pixman_fixed_1;
-	    height = pixman_fixed_1;
-	    break;
-
-	case PIXMAN_FILTER_FAST:
-	case PIXMAN_FILTER_NEAREST:
-	    x_off = - pixman_fixed_e;
-	    y_off = - pixman_fixed_e;
-	    width = 0;
-	    height = 0;
-	    break;
-
-	default:
+	}
+	else
+	{
 	    return FALSE;
 	}
 
-- 
1.7.3.4



More information about the Pixman mailing list