pixman: Branch 'master'

Søren Sandmann Pedersen sandmann at kemper.freedesktop.org
Thu Sep 18 16:48:48 PDT 2008


 pixman/pixman-region.c      |    9 ++
 pixman/pixman-transformed.c |  148 ++++++++++++++++++--------------------------
 2 files changed, 70 insertions(+), 87 deletions(-)

New commits:
commit b5a9002d2e3f0d961bcfe2acee6e9a0f1c583d5d
Author: Søren Sandmann Pedersen <sandmann at daimi.au.dk>
Date:   Thu Sep 18 19:28:31 2008 -0400

    Inline fetch functions in pixman-transformed.c
    
    There was significant performance overhead associated with indirect
    call to the fetch functions, so inline them.
    
    Also, the old code assumed that if the number of rectangles in the
    source clip was 1, then the clip was identical to the image
    boundaries. Fix that by running a full region_contains_point()
    whenever the source clip is different from pict->common.full_region.
    
    Based on a patch from Antoine Azar.

diff --git a/pixman/pixman-region.c b/pixman/pixman-region.c
index 559454a..3718d65 100644
--- a/pixman/pixman-region.c
+++ b/pixman/pixman-region.c
@@ -1998,7 +1998,9 @@ PREFIX(_contains_point) (region_type_t * region,
         return(FALSE);
     if (numRects == 1)
     {
-	*box = region->extents;
+        if (box)
+	    *box = region->extents;
+
 	return(TRUE);
     }
     for (pbox = PIXREGION_BOXPTR(region), pboxEnd = pbox + numRects;
@@ -2011,7 +2013,10 @@ PREFIX(_contains_point) (region_type_t * region,
 	   break;		/* missed it */
 	if (x >= pbox->x2)
 	   continue;		/* not there yet */
-	*box = *pbox;
+
+        if (box)
+	    *box = *pbox;
+
 	return(TRUE);
     }
     return(FALSE);
diff --git a/pixman/pixman-transformed.c b/pixman/pixman-transformed.c
index 5ad92ae..fca1cdb 100644
--- a/pixman/pixman-transformed.c
+++ b/pixman/pixman-transformed.c
@@ -47,28 +47,41 @@
  */
 typedef FASTCALL uint32_t (*fetchFromRegionProc)(bits_image_t *pict, int x, int y, uint32_t *buffer, fetchPixelProc32 fetch, pixman_box32_t *box);
 
+/*
+ * There are two properties we can make use of when fetching pixels
+ *
+ * (a) Is the source clip just the image itself?
+ *
+ * (b) Do we know the coordinates of the pixel to fetch are
+ *     within the image boundaries;
+ *
+ * Source clips are almost never used, so the important case to optimize
+ * for is when src_clip is false. Since inside_bounds is statically known,
+ * the last part of the if statement will normally be optimized away.
+ */
 static inline uint32_t
-fbFetchFromNoRegion(bits_image_t *pict, int x, int y, uint32_t *buffer, fetchPixelProc32 fetch, pixman_box32_t *box)
+do_fetch (bits_image_t *pict, int x, int y, fetchPixelProc32 fetch,
+	  pixman_bool_t src_clip,
+	  pixman_bool_t inside_bounds)
 {
-    return fetch (pict, x, y);
-}
-
-static uint32_t
-fbFetchFromNRectangles(bits_image_t *pict, int x, int y, uint32_t *buffer, fetchPixelProc32 fetch, pixman_box32_t *box)
-{
-    pixman_box32_t box2;
-    if (pixman_region32_contains_point (pict->common.src_clip, x, y, &box2))
-        return fbFetchFromNoRegion(pict, x, y, buffer, fetch, box);
+    if (src_clip)
+    {
+	if (pixman_region32_contains_point (pict->common.src_clip, x, y,NULL))
+	    return fetch (pict, x, y);
+	else
+	    return 0;
+    }
+    else if (inside_bounds)
+    {
+	return fetch (pict, x, y);
+    }
     else
-        return 0;
-}
-
-static uint32_t
-fbFetchFromOneRectangle(bits_image_t *pict, int x, int y, uint32_t *buffer, fetchPixelProc32 fetch, pixman_box32_t *box)
-{
-    pixman_box32_t box2 = *box;
-    return ((x < box2.x1) | (x >= box2.x2) | (y < box2.y1) | (y >= box2.y2)) ?
-        0 : fbFetchFromNoRegion(pict, x, y, buffer, fetch, box);
+    {
+	if (x >= 0 && x < pict->width && y >= 0 && y < pict->height)
+	    return fetch (pict, x, y);
+	else
+	    return 0;
+    }
 }
 
 /*
@@ -77,18 +90,14 @@ fbFetchFromOneRectangle(bits_image_t *pict, int x, int y, uint32_t *buffer, fetc
 static void
 fbFetchTransformed_Nearest_Normal(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit)
 {
-    pixman_box32_t* box = NULL;
     fetchPixelProc32   fetch;
-    fetchFromRegionProc fetchFromRegion;
+    pixman_bool_t src_clip;
     int x, y, i;
 
     /* initialize the two function pointers */
     fetch = ACCESS(pixman_fetchPixelProcForPicture32)(pict);
 
-    if(pixman_region32_n_rects (pict->common.src_clip) == 1)
-        fetchFromRegion = fbFetchFromNoRegion;
-    else
-        fetchFromRegion = fbFetchFromNRectangles;
+    src_clip = pict->common.src_clip != &(pict->common.full_region);
 
     for ( i = 0; i < width; ++i)
     {
@@ -110,7 +119,8 @@ fbFetchTransformed_Nearest_Normal(bits_image_t * pict, int width, uint32_t *buff
                     y = MOD(v.vector[1]>>16, pict->height);
                     x = MOD(v.vector[0]>>16, pict->width);
                 }
-                *(buffer + i) = fetchFromRegion(pict, x, y, buffer, fetch, box);
+
+                *(buffer + i) = do_fetch (pict, x, y, fetch, src_clip, TRUE);
             }
         }
 
@@ -123,18 +133,14 @@ fbFetchTransformed_Nearest_Normal(bits_image_t * pict, int width, uint32_t *buff
 static void
 fbFetchTransformed_Nearest_Pad(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit)
 {
-    pixman_box32_t *box = NULL;
-    fetchPixelProc32   fetch;
-    fetchFromRegionProc fetchFromRegion;
+    pixman_bool_t src_clip;
+    fetchPixelProc32 fetch;
     int x, y, i;
 
     /* initialize the two function pointers */
     fetch = ACCESS(pixman_fetchPixelProcForPicture32)(pict);
 
-    if(pixman_region32_n_rects (pict->common.src_clip) == 1)
-        fetchFromRegion = fbFetchFromNoRegion;
-    else
-        fetchFromRegion = fbFetchFromNRectangles;
+    src_clip = pict->common.src_clip != &(pict->common.full_region);
 
     for (i = 0; i < width; ++i)
     {
@@ -157,7 +163,7 @@ fbFetchTransformed_Nearest_Pad(bits_image_t * pict, int width, uint32_t *buffer,
                     x = CLIP(v.vector[0]>>16, 0, pict->width-1);
                 }
 
-                *(buffer + i) = fetchFromRegion(pict, x, y, buffer, fetch, box);
+                *(buffer + i) = do_fetch (pict, x, y, fetch, src_clip, TRUE);
             }
         }
 
@@ -170,23 +176,13 @@ fbFetchTransformed_Nearest_Pad(bits_image_t * pict, int width, uint32_t *buffer,
 static void
 fbFetchTransformed_Nearest_General(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit)
 {
-    pixman_box32_t *box = NULL;
     fetchPixelProc32   fetch;
-    fetchFromRegionProc fetchFromRegion;
+    pixman_bool_t src_clip;
     int x, y, i;
 
-    /* initialize the two function pointers */
     fetch = ACCESS(pixman_fetchPixelProcForPicture32)(pict);
 
-    if(pixman_region32_n_rects (pict->common.src_clip) == 1)
-    {
-        box = &(pict->common.src_clip->extents);
-        fetchFromRegion = fbFetchFromOneRectangle;
-    }
-    else
-    {
-        fetchFromRegion = fbFetchFromNRectangles;
-    }
+    src_clip = pict->common.src_clip != &(pict->common.full_region);
 
     for (i = 0; i < width; ++i) {
         if (!mask || mask[i] & maskBits)
@@ -201,7 +197,8 @@ fbFetchTransformed_Nearest_General(bits_image_t * pict, int width, uint32_t *buf
                     y = v.vector[1]>>16;
                     x = v.vector[0]>>16;
                 }
-                *(buffer + i) = fetchFromRegion(pict, x, y, buffer, fetch, box);
+
+                *(buffer + i) = do_fetch (pict, x, y, fetch, src_clip, FALSE);
             }
         }
         v.vector[0] += unit.vector[0];
@@ -213,18 +210,13 @@ fbFetchTransformed_Nearest_General(bits_image_t * pict, int width, uint32_t *buf
 static void
 fbFetchTransformed_Bilinear_Normal(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit)
 {
-    pixman_box32_t *box = NULL;
+    pixman_bool_t src_clip;
     fetchPixelProc32   fetch;
-    fetchFromRegionProc fetchFromRegion;
     int i;
 
-    /* initialize the two function pointers */
     fetch = ACCESS(pixman_fetchPixelProcForPicture32)(pict);
 
-    if(pixman_region32_n_rects (pict->common.src_clip) == 1)
-        fetchFromRegion = fbFetchFromNoRegion;
-    else
-        fetchFromRegion = fbFetchFromNRectangles;
+    src_clip = pict->common.src_clip != &(pict->common.full_region);
 
     for (i = 0; i < width; ++i) {
         if (!mask || mask[i] & maskBits)
@@ -261,10 +253,10 @@ fbFetchTransformed_Bilinear_Normal(bits_image_t * pict, int width, uint32_t *buf
                 y1 = MOD (y1, pict->height);
                 y2 = MOD (y2, pict->height);
 
-                tl = fetchFromRegion(pict, x1, y1, buffer, fetch, box);
-                tr = fetchFromRegion(pict, x2, y1, buffer, fetch, box);
-                bl = fetchFromRegion(pict, x1, y2, buffer, fetch, box);
-                br = fetchFromRegion(pict, x2, y2, buffer, fetch, box);
+                tl = do_fetch (pict, x1, y1, fetch, src_clip, TRUE);
+                tr = do_fetch (pict, x2, y1, fetch, src_clip, TRUE);
+                bl = do_fetch (pict, x1, y2, fetch, src_clip, TRUE);
+                br = do_fetch (pict, x2, y2, fetch, src_clip, TRUE);
 
                 ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
                 fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
@@ -290,18 +282,14 @@ fbFetchTransformed_Bilinear_Normal(bits_image_t * pict, int width, uint32_t *buf
 static void
 fbFetchTransformed_Bilinear_Pad(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit)
 {
-    pixman_box32_t *box = NULL;
+    pixman_bool_t src_clip;
     fetchPixelProc32   fetch;
-    fetchFromRegionProc fetchFromRegion;
     int i;
 
     /* initialize the two function pointers */
     fetch = ACCESS(pixman_fetchPixelProcForPicture32)(pict);
 
-    if(pixman_region32_n_rects (pict->common.src_clip) == 1)
-        fetchFromRegion = fbFetchFromNoRegion;
-    else
-        fetchFromRegion = fbFetchFromNRectangles;
+    src_clip = pict->common.src_clip != &(pict->common.full_region);
 
     for (i = 0; i < width; ++i) {
         if (!mask || mask[i] & maskBits)
@@ -338,10 +326,10 @@ fbFetchTransformed_Bilinear_Pad(bits_image_t * pict, int width, uint32_t *buffer
                 y1 = CLIP (y1, 0, pict->height-1);
                 y2 = CLIP (y2, 0, pict->height-1);
 
-                tl = fetchFromRegion(pict, x1, y1, buffer, fetch, box);
-                tr = fetchFromRegion(pict, x2, y1, buffer, fetch, box);
-                bl = fetchFromRegion(pict, x1, y2, buffer, fetch, box);
-                br = fetchFromRegion(pict, x2, y2, buffer, fetch, box);
+                tl = do_fetch(pict, x1, y1, fetch, src_clip, TRUE);
+                tr = do_fetch(pict, x2, y1, fetch, src_clip, TRUE);
+                bl = do_fetch(pict, x1, y2, fetch, src_clip, TRUE);
+                br = do_fetch(pict, x2, y2, fetch, src_clip, TRUE);
 
                 ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
                 fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
@@ -367,23 +355,14 @@ fbFetchTransformed_Bilinear_Pad(bits_image_t * pict, int width, uint32_t *buffer
 static void
 fbFetchTransformed_Bilinear_General(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit)
 {
-    pixman_box32_t *box = NULL;
+    pixman_bool_t src_clip;
     fetchPixelProc32   fetch;
-    fetchFromRegionProc fetchFromRegion;
     int i;
 
     /* initialize the two function pointers */
     fetch = ACCESS(pixman_fetchPixelProcForPicture32)(pict);
 
-    if(pixman_region32_n_rects (pict->common.src_clip) == 1)
-    {
-        box = &(pict->common.src_clip->extents);
-        fetchFromRegion = fbFetchFromOneRectangle;
-    }
-    else
-    {
-        fetchFromRegion = fbFetchFromNRectangles;
-    }
+    src_clip = pict->common.src_clip != &(pict->common.full_region);
 
     for (i = 0; i < width; ++i)
     {
@@ -416,10 +395,10 @@ fbFetchTransformed_Bilinear_General(bits_image_t * pict, int width, uint32_t *bu
                 idistx = 256 - distx;
                 idisty = 256 - disty;
 
-                tl = fetchFromRegion(pict, x1, y1, buffer, fetch, box);
-                tr = fetchFromRegion(pict, x2, y1, buffer, fetch, box);
-                bl = fetchFromRegion(pict, x1, y2, buffer, fetch, box);
-                br = fetchFromRegion(pict, x2, y2, buffer, fetch, box);
+                tl = do_fetch(pict, x1, y1, fetch, src_clip, FALSE);
+                tr = do_fetch(pict, x2, y1, fetch, src_clip, FALSE);
+                bl = do_fetch(pict, x1, y2, fetch, src_clip, FALSE);
+                br = do_fetch(pict, x2, y2, fetch, src_clip, FALSE);
 
                 ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
                 fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
@@ -446,7 +425,6 @@ fbFetchTransformed_Bilinear_General(bits_image_t * pict, int width, uint32_t *bu
 static void
 fbFetchTransformed_Convolution(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit)
 {
-    pixman_box32_t dummy;
     fetchPixelProc32 fetch;
     int i;
 
@@ -508,7 +486,7 @@ fbFetchTransformed_Convolution(bits_image_t * pict, int width, uint32_t *buffer,
                                 default:
                                     tx = x;
                             }
-                            if (pixman_region32_contains_point (pict->common.src_clip, tx, ty, &dummy)) {
+                            if (pixman_region32_contains_point (pict->common.src_clip, tx, ty, NULL)) {
                                 uint32_t c = fetch(pict, tx, ty);
 
                                 srtot += Red(c) * *p;


More information about the xorg-commit mailing list