From: Michel Dänzer <[email protected]>

Add support for solid pictures in exaTryDriverSolidFill(), but otherwise just
pass solid and gradient pictures to the driver Composite hook.

While we're at it, clean up the logic to detect Composite operations which are
effectively solid fills or copies. This should also fix some false negatives
and positives.
---

Daniel / Peter, is it okay if I push this for 1.7? E.g. the Gallium Xorg state
tracker will be able to accelerate solid and gradient pictures soon, and it
would be too bad if xserver 1.7 still prevented that.

There's some potential for regressions (though I haven't found any with a
hacked rendercheck -t fill), but I'm confident that those could be fixed for
the release.

 exa/exa_render.c |  349 ++++++++++++++++++++++++++++++++----------------------
 1 files changed, 206 insertions(+), 143 deletions(-)

diff --git a/exa/exa_render.c b/exa/exa_render.c
index 1ac29f2..1468c5c 100644
--- a/exa/exa_render.c
+++ b/exa/exa_render.c
@@ -77,11 +77,17 @@ static void exaCompositeFallbackPictDesc(PicturePtr pict, 
char *string, int n)
        break;
     }
 
-    loc = exaGetOffscreenPixmap(pict->pDrawable, &temp, &temp) ? 's' : 'm';
+    if (pict->pDrawable)
+       loc = exaGetOffscreenPixmap(pict->pDrawable, &temp, &temp) ? 's' : 'm';
 
-    snprintf(size, 20, "%dx%d%s", pict->pDrawable->width,
-            pict->pDrawable->height, pict->repeat ?
-            " R" : "");
+       snprintf(size, 20, "%dx%d%s", pict->pDrawable->width,
+                pict->pDrawable->height, pict->repeat ?
+                " R" : "");
+    else {
+       loc = '-';
+
+       snprintf(size, 20, "%s", pict->repeat ? " R" : "");
+    }
 
     snprintf(string, n, "%p:%c fmt %s (%s)", pict->pDrawable, loc, format, 
size);
 }
@@ -151,9 +157,6 @@ exaGetPixelFromRGBA(CARD32  *pixel,
 
     *pixel = 0;
 
-    if (!PICT_FORMAT_COLOR(format))
-       return FALSE;
-
     rbits = PICT_FORMAT_R(format);
     gbits = PICT_FORMAT_G(format);
     bbits = PICT_FORMAT_B(format);
@@ -174,6 +177,11 @@ exaGetPixelFromRGBA(CARD32 *pixel,
        gshift = bshift - gbits;
        rshift = gshift - rbits;
        ashift = 0;
+    } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_A) {
+       bshift = 32;
+       gshift = 32;
+       rshift = 32;
+       ashift = 0;
     } else
        return FALSE;
 
@@ -196,9 +204,6 @@ exaGetRGBAFromPixel(CARD32  pixel,
     int rbits, bbits, gbits, abits;
     int rshift, bshift, gshift, ashift;
 
-    if (!PICT_FORMAT_COLOR(format))
-       return FALSE;
-
     rbits = PICT_FORMAT_R(format);
     gbits = PICT_FORMAT_G(format);
     bbits = PICT_FORMAT_B(format);
@@ -219,6 +224,11 @@ exaGetRGBAFromPixel(CARD32 pixel,
        gshift = bshift - gbits;
        rshift = gshift - rbits;
        ashift = 0;
+    } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_A) {
+       bshift = 32;
+       gshift = 32;
+       rshift = 32;
+       ashift = 0;
     } else
        return FALSE;
 
@@ -268,27 +278,22 @@ exaTryDriverSolidFill(PicturePtr  pSrc,
     int nbox;
     int dst_off_x, dst_off_y;
     PixmapPtr pSrcPix, pDstPix;
-    ExaPixmapPrivPtr pSrcExaPix, pDstExaPix;
+    ExaPixmapPrivPtr pDstExaPix;
     CARD32 pixel;
     CARD16 red, green, blue, alpha;
 
     pDstPix = exaGetDrawablePixmap (pDst->pDrawable);
-    pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable);
-
-    pSrcExaPix = ExaGetPixmapPriv(pSrcPix);
     pDstExaPix = ExaGetPixmapPriv(pDstPix);
 
-    /* Check whether the accelerator can use these pixmaps.
+    /* Check whether the accelerator can use the destination pixmap.
      */
-    if (pSrcExaPix->accel_blocked || pDstExaPix->accel_blocked)
+    if (pDstExaPix->accel_blocked)
     {
        return -1;
     }
 
     xDst += pDst->pDrawable->x;
     yDst += pDst->pDrawable->y;
-    xSrc += pSrc->pDrawable->x;
-    ySrc += pSrc->pDrawable->y;
 
     if (!miComputeCompositeRegion (&region, pSrc, NULL, pDst,
                                   xSrc, ySrc, 0, 0, xDst, yDst,
@@ -299,7 +304,41 @@ exaTryDriverSolidFill(PicturePtr   pSrc,
 
     REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
 
-    pixel = exaGetPixmapFirstPixel (pSrcPix);
+    if (pSrc->pDrawable) {
+       xSrc += pSrc->pDrawable->x;
+       ySrc += pSrc->pDrawable->y;
+
+       pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable);
+       pixel = exaGetPixmapFirstPixel (pSrcPix);
+
+       if (!exaGetRGBAFromPixel(pixel, &red, &green, &blue, &alpha,
+                                pSrc->format))
+       {
+           REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+           return -1;
+       }
+    } else {
+       pixel = pSrc->pSourcePict->solidFill.color;
+
+       alpha = pixel >> 24;
+       alpha |= alpha << 8;
+
+       red = (pixel >> 16) & 0xff;
+       red |= red << 8;
+
+       green = pixel & 0xff00;
+       green |= green >> 8;
+
+       blue = pixel & 0xff;
+       blue |= blue << 8;
+    }
+
+    if (!exaGetPixelFromRGBA(&pixel, red, green, blue, alpha,
+                       pDst->format))
+    {
+       REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+       return -1;
+    }
 
     if (pExaScr->do_migration) {
        ExaMigrationRec pixmaps[1];
@@ -316,20 +355,6 @@ exaTryDriverSolidFill(PicturePtr   pSrc,
        return 0;
     }
 
-    if (!exaGetRGBAFromPixel(pixel, &red, &green, &blue, &alpha,
-                        pSrc->format))
-    {
-       REGION_UNINIT(pDst->pDrawable->pScreen, &region);
-       return -1;
-    }
-
-    if (!exaGetPixelFromRGBA(&pixel, red, green, blue, alpha,
-                       pDst->format))
-    {
-       REGION_UNINIT(pDst->pDrawable->pScreen, &region);
-       return -1;
-    }
-
     if (!(*pExaScr->info->PrepareSolid) (pDstPix, GXcopy, 0xffffffff, pixel))
     {
        REGION_UNINIT(pDst->pDrawable->pScreen, &region);
@@ -362,16 +387,18 @@ exaTryDriverCompositeRects(CARD8         op,
 {
     ExaScreenPriv (pDst->pDrawable->pScreen);
     int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
-    PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix;
-    ExaPixmapPrivPtr pSrcExaPix, pMaskExaPix = NULL, pDstExaPix;
+    PixmapPtr pSrcPix = NULL, pMaskPix = NULL, pDstPix;
+    ExaPixmapPrivPtr pSrcExaPix = NULL, pMaskExaPix = NULL, pDstExaPix;
 
     if (!pExaScr->info->PrepareComposite)
        return -1;
 
-    pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
-    pSrcExaPix = ExaGetPixmapPriv(pSrcPix);
+    if (pSrc->pDrawable) {
+       pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
+       pSrcExaPix = ExaGetPixmapPriv(pSrcPix);
+    }
 
-    if (pMask) {
+    if (pMask && pMask->pDrawable) {
        pMaskPix = exaGetDrawablePixmap(pMask->pDrawable);
        pMaskExaPix = ExaGetPixmapPriv(pMaskPix);
     }
@@ -383,8 +410,9 @@ exaTryDriverCompositeRects(CARD8           op,
      * FIXME: If it cannot, use temporary pixmaps so that the drawing
      * happens within limits.
      */
-    if (pSrcExaPix->accel_blocked || pDstExaPix->accel_blocked ||
-       (pMask && pMaskExaPix->accel_blocked))
+    if (pDstExaPix->accel_blocked ||
+       (pSrcExaPix && pSrcExaPix->accel_blocked) ||
+       (pMaskExaPix && pMaskExaPix->accel_blocked))
     {
        return -1;
     }
@@ -397,37 +425,45 @@ exaTryDriverCompositeRects(CARD8         op,
 
     if (pExaScr->do_migration) {
        ExaMigrationRec pixmaps[3];
+       int i = 0;
+
+       pixmaps[i].as_dst = TRUE;
+       pixmaps[i].as_src = exaOpReadsDestination(op);
+       pixmaps[i].pPix = pDstPix;
+       pixmaps[i].pReg = NULL;
+       i++;
+
+       if (pSrcPix) {
+           pixmaps[i].as_dst = FALSE;
+           pixmaps[i].as_src = TRUE;
+           pixmaps[i].pPix = pSrcPix;
+           pixmaps[i].pReg = NULL;
+           i++;
+       }
 
-       pixmaps[0].as_dst = TRUE;
-       pixmaps[0].as_src = exaOpReadsDestination(op);
-       pixmaps[0].pPix = pDstPix;
-       pixmaps[0].pReg = NULL;
-       pixmaps[1].as_dst = FALSE;
-       pixmaps[1].as_src = TRUE;
-       pixmaps[1].pPix = pSrcPix;
-       pixmaps[1].pReg = NULL;
-       if (pMask) {
-           pixmaps[2].as_dst = FALSE;
-           pixmaps[2].as_src = TRUE;
-           pixmaps[2].pPix = pMaskPix;
-           pixmaps[2].pReg = NULL;
-           exaDoMigration(pixmaps, 3, TRUE);
-       } else
-           exaDoMigration(pixmaps, 2, TRUE);
+       if (pMaskPix) {
+           pixmaps[i].as_dst = FALSE;
+           pixmaps[i].as_src = TRUE;
+           pixmaps[i].pPix = pMaskPix;
+           pixmaps[i].pReg = NULL;
+           i++;
+       }
+
+       exaDoMigration(pixmaps, i, TRUE);
     }
 
     pDstPix = exaGetOffscreenPixmap (pDst->pDrawable, &dst_off_x, &dst_off_y);
     if (!pDstPix)
        return 0;
-    
-    pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
 
-    if (!pSrcPix)
-       return 0;
+    if (pSrcPix) {
+       pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, 
&src_off_y);
+       if (!pSrcPix)
+           return 0;
+    }
 
-    if (pMask) {
+    if (pMaskPix) {
        pMaskPix = exaGetOffscreenPixmap (pMask->pDrawable, &mask_off_x, 
&mask_off_y);
-
        if (!pMaskPix)
            return 0;
     }
@@ -440,15 +476,24 @@ exaTryDriverCompositeRects(CARD8         op,
     {
        INT16 xDst = rects->xDst + pDst->pDrawable->x;
        INT16 yDst = rects->yDst + pDst->pDrawable->y;
-       INT16 xMask = pMask ? rects->xMask + pMask->pDrawable->x : 0;
-       INT16 yMask = pMask ? rects->yMask + pMask->pDrawable->y : 0;
-       INT16 xSrc = rects->xSrc + pSrc->pDrawable->x;
-       INT16 ySrc = rects->ySrc + pSrc->pDrawable->y;
-
+       INT16 xMask = rects->xMask;
+       INT16 yMask = rects->yMask;
+       INT16 xSrc = rects->xSrc;
+       INT16 ySrc = rects->ySrc;
        RegionRec region;
        BoxPtr pbox;
        int nbox;
-       
+
+       if (pMaskPix) {
+           xMask += pMask->pDrawable->x;
+           yMask += pMask->pDrawable->y;
+       }
+
+       if (pSrcPix) {
+           xSrc += pSrc->pDrawable->x;
+           ySrc += pSrc->pDrawable->y;
+       }
+
        if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
                                       xSrc, ySrc, xMask, yMask, xDst, yDst,
                                       rects->width, rects->height))
@@ -635,16 +680,18 @@ exaTryDriverComposite(CARD8               op,
     BoxPtr pbox;
     int nbox;
     int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
-    PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix;
-    ExaPixmapPrivPtr pSrcExaPix, pMaskExaPix = NULL, pDstExaPix;
+    PixmapPtr pSrcPix = NULL, pMaskPix = NULL, pDstPix;
+    ExaPixmapPrivPtr pSrcExaPix = NULL, pMaskExaPix = NULL, pDstExaPix;
 
-    pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
-    pSrcExaPix = ExaGetPixmapPriv(pSrcPix);
+    if (pSrc->pDrawable) {
+       pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
+       pSrcExaPix = ExaGetPixmapPriv(pSrcPix);
+    }
 
     pDstPix = exaGetDrawablePixmap(pDst->pDrawable);
     pDstExaPix = ExaGetPixmapPriv(pDstPix);
 
-    if (pMask) {
+    if (pMask && pMask->pDrawable) {
        pMaskPix = exaGetDrawablePixmap(pMask->pDrawable);
         pMaskExaPix = ExaGetPixmapPriv(pMaskPix);
     }
@@ -653,8 +700,8 @@ exaTryDriverComposite(CARD8         op,
      * FIXME: If it cannot, use temporary pixmaps so that the drawing
      * happens within limits.
      */
-    if (pSrcExaPix->accel_blocked ||
-       pDstExaPix->accel_blocked ||
+    if (pDstExaPix->accel_blocked ||
+       (pSrcExaPix && pSrcExaPix->accel_blocked) ||
        (pMask && (pMaskExaPix->accel_blocked)))
     {
        return -1;
@@ -663,13 +710,15 @@ exaTryDriverComposite(CARD8               op,
     xDst += pDst->pDrawable->x;
     yDst += pDst->pDrawable->y;
 
-    if (pMask) {
+    if (pMaskPix) {
        xMask += pMask->pDrawable->x;
        yMask += pMask->pDrawable->y;
     }
 
-    xSrc += pSrc->pDrawable->x;
-    ySrc += pSrc->pDrawable->y;
+    if (pSrcPix) {
+       xSrc += pSrc->pDrawable->x;
+       ySrc += pSrc->pDrawable->y;
+    }
 
     if (pExaScr->info->CheckComposite &&
        !(*pExaScr->info->CheckComposite) (op, pSrc, pMask, pDst))
@@ -688,36 +737,51 @@ exaTryDriverComposite(CARD8               op,
 
     if (pExaScr->do_migration) {
        ExaMigrationRec pixmaps[3];
+       int i = 0;
+
+       pixmaps[i].as_dst = TRUE;
+       pixmaps[i].as_src = exaOpReadsDestination(op);
+       pixmaps[i].pPix = pDstPix;
+       pixmaps[i].pReg = pixmaps[0].as_src ? NULL : &region;
+       i++;
+
+       if (pSrcPix) {
+           pixmaps[i].as_dst = FALSE;
+           pixmaps[i].as_src = TRUE;
+           pixmaps[i].pPix = pSrcPix;
+           pixmaps[i].pReg = NULL;
+           i++;
+       }
 
-       pixmaps[0].as_dst = TRUE;
-       pixmaps[0].as_src = exaOpReadsDestination(op);
-       pixmaps[0].pPix = pDstPix;
-       pixmaps[0].pReg = pixmaps[0].as_src ? NULL : &region;
-       pixmaps[1].as_dst = FALSE;
-       pixmaps[1].as_src = TRUE;
-       pixmaps[1].pPix = pSrcPix;
-       pixmaps[1].pReg = NULL;
-       if (pMask) {
-           pixmaps[2].as_dst = FALSE;
-           pixmaps[2].as_src = TRUE;
-           pixmaps[2].pPix = pMaskPix;
-           pixmaps[2].pReg = NULL;
-           exaDoMigration(pixmaps, 3, TRUE);
-       } else
-           exaDoMigration(pixmaps, 2, TRUE);
+       if (pMaskPix) {
+           pixmaps[i].as_dst = FALSE;
+           pixmaps[i].as_src = TRUE;
+           pixmaps[i].pPix = pMaskPix;
+           pixmaps[i].pReg = NULL;
+           i++;
+       }
+
+       exaDoMigration(pixmaps, i, TRUE);
     }
 
-    pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
-    if (pMask)
+    if (pSrcPix) {
+       pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, 
&src_off_y);
+       if (!pSrcPix) {
+           REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+           return 0;
+       }
+    }
+
+    if (pMaskPix) {
        pMaskPix = exaGetOffscreenPixmap (pMask->pDrawable, &mask_off_x,
                                          &mask_off_y);
-
-    if (!exaPixmapIsOffscreen(pDstPix)) {
-       REGION_UNINIT(pDst->pDrawable->pScreen, &region);
-       return 0;
+       if (!pMaskPix) {
+           REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+           return 0;
+       }
     }
 
-    if (!pSrcPix || (pMask && !pMaskPix)) {
+    if (!exaPixmapIsOffscreen(pDstPix)) {
        REGION_UNINIT(pDst->pDrawable->pScreen, &region);
        return 0;
     }
@@ -868,45 +932,44 @@ exaComposite(CARD8        op,
     Bool saveMaskRepeat = pMask ? pMask->repeat : 0;
     RegionRec region;
 
-    /* We currently don't support acceleration of gradients, or other pictures
-     * with a NULL pDrawable.
-     */
-    if (pExaScr->swappedOut ||
-       pSrc->pDrawable == NULL || (pMask != NULL && pMask->pDrawable == NULL))
-    {
+    if (pExaScr->swappedOut)
        goto fallback;
-    }
 
     /* Remove repeat in source if useless */
-    if (pSrc->repeat && !pSrc->transform && xSrc >= 0 &&
+    if (pSrc->pDrawable && pSrc->repeat && !pSrc->transform && xSrc >= 0 &&
        (xSrc + width) <= pSrc->pDrawable->width && ySrc >= 0 &&
        (ySrc + height) <= pSrc->pDrawable->height)
            pSrc->repeat = 0;
 
-    if (!pMask)
+    if (!pMask && !pSrc->alphaMap && !pDst->alphaMap &&
+       (op == PictOpSrc || (op == PictOpOver && !PICT_FORMAT_A(pSrc->format))))
     {
-      if ((op == PictOpSrc &&
-          ((pSrc->format == pDst->format) ||
-           (pSrc->format==PICT_b8g8r8a8 && pDst->format==PICT_b8g8r8x8) ||
-           (pSrc->format==PICT_a8r8g8b8 && pDst->format==PICT_x8r8g8b8) ||
-           (pSrc->format==PICT_a8b8g8r8 && pDst->format==PICT_x8b8g8r8))) ||
-         (op == PictOpOver && !pSrc->alphaMap && !pDst->alphaMap &&
-          pSrc->format == pDst->format &&
-          (pSrc->format==PICT_x8r8g8b8 || pSrc->format==PICT_x8b8g8r8 ||
-           pSrc->format==PICT_b8g8r8x8)))
+       if (pSrc->pDrawable ?
+           (pSrc->pDrawable->width == 1 && pSrc->pDrawable->height == 1 &&
+            pSrc->repeat) :
+           (pSrc->pSourcePict->type == SourcePictTypeSolidFill))
        {
-           if (pSrc->pDrawable->width == 1 &&
-               pSrc->pDrawable->height == 1 &&
-               pSrc->repeat)
-           {
-               ret = exaTryDriverSolidFill(pSrc, pDst, xSrc, ySrc, xDst, yDst,
-                                           width, height);
-               if (ret == 1)
-                   goto done;
-           }
-           else if (pSrc->pDrawable != NULL &&
-                    !pSrc->repeat &&
-                    !pSrc->transform)
+           ret = exaTryDriverSolidFill(pSrc, pDst, xSrc, ySrc, xDst, yDst,
+                                       width, height);
+           if (ret == 1)
+               goto done;
+       } else if (pSrc->pDrawable && !pSrc->transform &&
+           ((op == PictOpSrc &&
+             (pSrc->format == pDst->format ||
+              (PICT_FORMAT_COLOR(pDst->format) &&
+               PICT_FORMAT_COLOR(pSrc->format) &&
+               pDst->format == PICT_FORMAT(PICT_FORMAT_BPP(pSrc->format),
+                                           PICT_FORMAT_TYPE(pSrc->format),
+                                           0,
+                                           PICT_FORMAT_R(pSrc->format),
+                                           PICT_FORMAT_G(pSrc->format),
+                                           PICT_FORMAT_B(pSrc->format))))) ||
+            (op == PictOpOver && pSrc->format == pDst->format &&
+             !PICT_FORMAT_A(pSrc->format))))
+       {
+           if (!pSrc->repeat && xSrc >= 0 && ySrc >= 0 &&
+               (xSrc + width <= pSrc->pDrawable->width) &&
+               (ySrc + height <= pSrc->pDrawable->height))
            {
                Bool ret;
                xDst += pDst->pDrawable->x;
@@ -935,10 +998,9 @@ exaComposite(CARD8 op,
 
                goto done;
            }
-           else if (pSrc->pDrawable != NULL &&
-                    pSrc->pDrawable->type == DRAWABLE_PIXMAP &&
-                    !pSrc->transform &&
-                    pSrc->repeatType == RepeatNormal)
+
+           if (pSrc->repeat && pSrc->repeatType == RepeatNormal &&
+               pSrc->pDrawable->type == DRAWABLE_PIXMAP)
            {
                DDXPointRec patOrg;
 
@@ -988,9 +1050,9 @@ exaComposite(CARD8 op,
     }
 
     /* Remove repeat in mask if useless */
-    if (pMask && pMask->repeat && !pMask->transform && xMask >= 0 &&
-       (xMask + width) <= pMask->pDrawable->width && yMask >= 0 &&
-       (yMask + height) <= pMask->pDrawable->height)
+    if (pMask && pMask->pDrawable && pMask->repeat && !pMask->transform &&
+       xMask >= 0 && (xMask + width) <= pMask->pDrawable->width &&
+       yMask >= 0 && (yMask + height) <= pMask->pDrawable->height)
            pMask->repeat = 0;
 
     if (pExaScr->info->PrepareComposite &&
@@ -1006,9 +1068,10 @@ exaComposite(CARD8       op,
        /* For generic masks and solid src pictures, mach64 can do Over in two
         * passes, similar to the component-alpha case.
         */
-       isSrcSolid = pSrc->pDrawable->width == 1 &&
-                    pSrc->pDrawable->height == 1 &&
-                    pSrc->repeat;
+       isSrcSolid = pSrc->pDrawable ?
+           (pSrc->pDrawable->width == 1 && pSrc->pDrawable->height == 1 &&
+            pSrc->repeat) :
+           (pSrc->pSourcePict->type == SourcePictTypeSolidFill);
 
        /* If we couldn't do the Composite in a single pass, and it was a
         * component-alpha Over, see if we can do it in two passes with
-- 
1.6.3.3

_______________________________________________
xorg-devel mailing list
[email protected]
http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to