Add FAST_PATH_SAMPLES_COVER_CLIP and FAST_PATH_16BIT_SAFE
authorAlexander Larsson <alexl@redhat.com>
Fri, 12 Mar 2010 14:41:01 +0000 (15:41 +0100)
committerSøren Sandmann Pedersen <ssp@redhat.com>
Wed, 17 Mar 2010 15:03:05 +0000 (11:03 -0400)
FAST_PATH_SAMPLES_COVER_CLIP:

This is set of the source sample grid, unrepeated but transformed
completely completely covers the clip destination. If this is set
you can use a simple scaled that doesn't have to care about the repeat
mode.

FAST_PATH_16BIT_SAFE:

This signifies two things:
1) The size of the src/mask fits in a 16.16 fixed point, so something like:

    max_vx = src_image->bits.width << 16;

    Is allowed and is guaranteed to not overflow max_vx

2) When stepping the source space we're guaranteed to never overflow
   a 16.16 bit fix point variable, even if we step one extra step
   in the destination space. This means that a loop doing:

   x = vx >> 16;
   vx += unit_x;    d = src_row[x];

   will never overflow vx causing x to be negative.

   And additionally, if you track vx like above and apply NORMAL repeat
   after the vx addition with something like:

   while (vx >= max_vx) vx -= max_vx;

   This will never overflow the vx even on the final increment that
   takes vx one past the end of where we will read, which makes the
   repeat loop safe.

pixman/pixman-private.h
pixman/pixman.c

index 65314b9..0cf9113 100644 (file)
@@ -580,6 +580,8 @@ _pixman_choose_implementation (void);
 #define FAST_PATH_IS_OPAQUE                    (1 << 13)
 #define FAST_PATH_NEEDS_WORKAROUND             (1 << 14)
 #define FAST_PATH_NO_NONE_REPEAT               (1 << 15)
+#define FAST_PATH_SAMPLES_COVER_CLIP           (1 << 16)
+#define FAST_PATH_16BIT_SAFE                   (1 << 17)
 
 #define _FAST_PATH_STANDARD_FLAGS                                      \
     (FAST_PATH_ID_TRANSFORM            |                               \
index 68483a0..56c9536 100644 (file)
@@ -479,24 +479,75 @@ walk_region_internal (pixman_implementation_t *imp,
     }
 }
 
-static force_inline pixman_bool_t
-image_covers (pixman_image_t *image,
-              pixman_box32_t *extents,
-              int             x,
-              int             y)
+#define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX))
+
+static force_inline uint32_t
+compute_src_extents_flags (pixman_image_t *image,
+                          pixman_box32_t *extents,
+                          int             x,
+                          int             y)
 {
-    if (image->common.type == BITS &&
-       image->common.repeat == PIXMAN_REPEAT_NONE)
+    pixman_box16_t extents16;
+    uint32_t flags;
+
+    flags = FAST_PATH_COVERS_CLIP;
+
+    if (image->common.type != BITS)
+       return flags;
+
+    if (image->common.repeat == PIXMAN_REPEAT_NONE &&
+       (x > extents->x1 || y > extents->y1 ||
+        x + image->bits.width < extents->x2 ||
+        y + image->bits.height < extents->y2))
+    {
+       flags &= ~FAST_PATH_COVERS_CLIP;
+    }
+
+    if (IS_16BIT (extents->x1 - x) &&
+       IS_16BIT (extents->y1 - y) &&
+       IS_16BIT (extents->x2 - x) &&
+       IS_16BIT (extents->y2 - y))
     {
-       if (x > extents->x1 || y > extents->y1 ||
-           x + image->bits.width < extents->x2 ||
-           y + image->bits.height < extents->y2)
+       extents16.x1 = extents->x1 - x;
+       extents16.y1 = extents->y1 - y;
+       extents16.x2 = extents->x2 - x;
+       extents16.y2 = extents->y2 - y;
+
+       if (!image->common.transform ||
+           pixman_transform_bounds (image->common.transform, &extents16))
        {
-           return FALSE;
+           if (extents16.x1 >= 0  && extents16.y1 >= 0 &&
+               extents16.x2 <= image->bits.width &&
+               extents16.y2 <= image->bits.height)
+           {
+               flags |= FAST_PATH_SAMPLES_COVER_CLIP;
+           }
        }
     }
 
-    return TRUE;
+    if (IS_16BIT (extents->x1 - x - 1) &&
+       IS_16BIT (extents->y1 - y - 1) &&
+       IS_16BIT (extents->x2 - x + 1) &&
+       IS_16BIT (extents->y2 - y + 1))
+    {
+       extents16.x1 = extents->x1 - x - 1;
+       extents16.y1 = extents->y1 - y - 1;
+       extents16.x2 = extents->x2 - x + 1;
+       extents16.y2 = extents->y2 - y + 1;
+
+       if (/* src space expanded by one in dest space fits in 16 bit */
+           (!image->common.transform ||
+            pixman_transform_bounds (image->common.transform, &extents16)) &&
+           /* And src image size can be used as 16.16 fixed point */
+           image->bits.width < 0x7fff &&
+           image->bits.height < 0x7fff)
+       {
+           /* Then we're "16bit safe" */
+           flags |= FAST_PATH_16BIT_SAFE;
+       }
+    }
+
+    return flags;
 }
 
 #define N_CACHED_FAST_PATHS 8
@@ -588,11 +639,10 @@ do_composite (pixman_implementation_t *imp,
     
     extents = pixman_region32_extents (&region);
     
-    if (image_covers (src, extents, dest_x - src_x, dest_y - src_y))
-       src_flags |= FAST_PATH_COVERS_CLIP;
-    
-    if (mask && image_covers (mask, extents, dest_x - mask_x, dest_y - mask_y))
-       mask_flags |= FAST_PATH_COVERS_CLIP;
+    src_flags |= compute_src_extents_flags (src, extents, dest_x - src_x, dest_y - src_y);
+
+    if (mask)
+       mask_flags |= compute_src_extents_flags (mask, extents, dest_x - mask_x, dest_y - mask_y);
 
     /*
      * Check if we can replace our operator by a simpler one