xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

exa_render.c (40349B)


      1 /*
      2  * Copyright © 2001 Keith Packard
      3  *
      4  * Partly based on code that is Copyright © The XFree86 Project Inc.
      5  *
      6  * Permission to use, copy, modify, distribute, and sell this software and its
      7  * documentation for any purpose is hereby granted without fee, provided that
      8  * the above copyright notice appear in all copies and that both that
      9  * copyright notice and this permission notice appear in supporting
     10  * documentation, and that the name of Keith Packard not be used in
     11  * advertising or publicity pertaining to distribution of the software without
     12  * specific, written prior permission.  Keith Packard makes no
     13  * representations about the suitability of this software for any purpose.  It
     14  * is provided "as is" without express or implied warranty.
     15  *
     16  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     17  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     18  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     19  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     20  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     21  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     22  * PERFORMANCE OF THIS SOFTWARE.
     23  */
     24 
     25 #ifdef HAVE_DIX_CONFIG_H
     26 #include <dix-config.h>
     27 #endif
     28 
     29 #include <stdlib.h>
     30 
     31 #include "exa_priv.h"
     32 
     33 #include "mipict.h"
     34 
     35 #if DEBUG_TRACE_FALL
     36 static void
     37 exaCompositeFallbackPictDesc(PicturePtr pict, char *string, int n)
     38 {
     39     char format[20];
     40     char size[20];
     41     char loc;
     42     int temp;
     43 
     44     if (!pict) {
     45         snprintf(string, n, "None");
     46         return;
     47     }
     48 
     49     switch (pict->format) {
     50     case PICT_a8r8g8b8:
     51         snprintf(format, 20, "ARGB8888");
     52         break;
     53     case PICT_x8r8g8b8:
     54         snprintf(format, 20, "XRGB8888");
     55         break;
     56     case PICT_b8g8r8a8:
     57         snprintf(format, 20, "BGRA8888");
     58         break;
     59     case PICT_b8g8r8x8:
     60         snprintf(format, 20, "BGRX8888");
     61         break;
     62     case PICT_r5g6b5:
     63         snprintf(format, 20, "RGB565  ");
     64         break;
     65     case PICT_x1r5g5b5:
     66         snprintf(format, 20, "RGB555  ");
     67         break;
     68     case PICT_a8:
     69         snprintf(format, 20, "A8      ");
     70         break;
     71     case PICT_a1:
     72         snprintf(format, 20, "A1      ");
     73         break;
     74     default:
     75         snprintf(format, 20, "0x%x", (int) pict->format);
     76         break;
     77     }
     78 
     79     if (pict->pDrawable) {
     80         loc = exaGetOffscreenPixmap(pict->pDrawable, &temp, &temp) ? 's' : 'm';
     81 
     82         snprintf(size, 20, "%dx%d%s", pict->pDrawable->width,
     83                  pict->pDrawable->height, pict->repeat ? " R" : "");
     84     }
     85     else {
     86         loc = '-';
     87 
     88         snprintf(size, 20, "%s", pict->repeat ? " R" : "");
     89     }
     90 
     91     snprintf(string, n, "%p:%c fmt %s (%s)", pict->pDrawable, loc, format,
     92              size);
     93 }
     94 
     95 static void
     96 exaPrintCompositeFallback(CARD8 op,
     97                           PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst)
     98 {
     99     char sop[20];
    100     char srcdesc[40], maskdesc[40], dstdesc[40];
    101 
    102     switch (op) {
    103     case PictOpSrc:
    104         snprintf(sop, sizeof(sop), "Src");
    105         break;
    106     case PictOpOver:
    107         snprintf(sop, sizeof(sop), "Over");
    108         break;
    109     default:
    110         snprintf(sop, sizeof(sop), "0x%x", (int) op);
    111         break;
    112     }
    113 
    114     exaCompositeFallbackPictDesc(pSrc, srcdesc, 40);
    115     exaCompositeFallbackPictDesc(pMask, maskdesc, 40);
    116     exaCompositeFallbackPictDesc(pDst, dstdesc, 40);
    117 
    118     ErrorF("Composite fallback: op %s, \n"
    119            "                    src  %s, \n"
    120            "                    mask %s, \n"
    121            "                    dst  %s, \n", sop, srcdesc, maskdesc, dstdesc);
    122 }
    123 #endif                          /* DEBUG_TRACE_FALL */
    124 
    125 Bool
    126 exaOpReadsDestination(CARD8 op)
    127 {
    128     /* FALSE (does not read destination) is the list of ops in the protocol
    129      * document with "0" in the "Fb" column and no "Ab" in the "Fa" column.
    130      * That's just Clear and Src.  ReduceCompositeOp() will already have
    131      * converted con/disjoint clear/src to Clear or Src.
    132      */
    133     switch (op) {
    134     case PictOpClear:
    135     case PictOpSrc:
    136         return FALSE;
    137     default:
    138         return TRUE;
    139     }
    140 }
    141 
    142 static Bool
    143 exaGetPixelFromRGBA(CARD32 *pixel,
    144                     CARD16 red,
    145                     CARD16 green,
    146                     CARD16 blue, CARD16 alpha, PictFormatPtr pFormat)
    147 {
    148     int rbits, bbits, gbits, abits;
    149     int rshift, bshift, gshift, ashift;
    150 
    151     *pixel = 0;
    152 
    153     if (!PICT_FORMAT_COLOR(pFormat->format) &&
    154         PICT_FORMAT_TYPE(pFormat->format) != PICT_TYPE_A)
    155         return FALSE;
    156 
    157     rbits = PICT_FORMAT_R(pFormat->format);
    158     gbits = PICT_FORMAT_G(pFormat->format);
    159     bbits = PICT_FORMAT_B(pFormat->format);
    160     abits = PICT_FORMAT_A(pFormat->format);
    161 
    162     rshift = pFormat->direct.red;
    163     gshift = pFormat->direct.green;
    164     bshift = pFormat->direct.blue;
    165     ashift = pFormat->direct.alpha;
    166 
    167     *pixel |= (blue >> (16 - bbits)) << bshift;
    168     *pixel |= (red >> (16 - rbits)) << rshift;
    169     *pixel |= (green >> (16 - gbits)) << gshift;
    170     *pixel |= (alpha >> (16 - abits)) << ashift;
    171 
    172     return TRUE;
    173 }
    174 
    175 static Bool
    176 exaGetRGBAFromPixel(CARD32 pixel,
    177                     CARD16 *red,
    178                     CARD16 *green,
    179                     CARD16 *blue,
    180                     CARD16 *alpha,
    181                     PictFormatPtr pFormat, PictFormatShort format)
    182 {
    183     int rbits, bbits, gbits, abits;
    184     int rshift, bshift, gshift, ashift;
    185 
    186     if (!PICT_FORMAT_COLOR(format) && PICT_FORMAT_TYPE(format) != PICT_TYPE_A)
    187         return FALSE;
    188 
    189     rbits = PICT_FORMAT_R(format);
    190     gbits = PICT_FORMAT_G(format);
    191     bbits = PICT_FORMAT_B(format);
    192     abits = PICT_FORMAT_A(format);
    193 
    194     if (pFormat) {
    195         rshift = pFormat->direct.red;
    196         gshift = pFormat->direct.green;
    197         bshift = pFormat->direct.blue;
    198         ashift = pFormat->direct.alpha;
    199     }
    200     else if (format == PICT_a8r8g8b8) {
    201         rshift = 16;
    202         gshift = 8;
    203         bshift = 0;
    204         ashift = 24;
    205     }
    206     else
    207         FatalError("EXA bug: exaGetRGBAFromPixel() doesn't match "
    208                    "createSourcePicture()\n");
    209 
    210     if (rbits) {
    211         *red = ((pixel >> rshift) & ((1 << rbits) - 1)) << (16 - rbits);
    212         while (rbits < 16) {
    213             *red |= *red >> rbits;
    214             rbits <<= 1;
    215         }
    216 
    217         *green = ((pixel >> gshift) & ((1 << gbits) - 1)) << (16 - gbits);
    218         while (gbits < 16) {
    219             *green |= *green >> gbits;
    220             gbits <<= 1;
    221         }
    222 
    223         *blue = ((pixel >> bshift) & ((1 << bbits) - 1)) << (16 - bbits);
    224         while (bbits < 16) {
    225             *blue |= *blue >> bbits;
    226             bbits <<= 1;
    227         }
    228     }
    229     else {
    230         *red = 0x0000;
    231         *green = 0x0000;
    232         *blue = 0x0000;
    233     }
    234 
    235     if (abits) {
    236         *alpha = ((pixel >> ashift) & ((1 << abits) - 1)) << (16 - abits);
    237         while (abits < 16) {
    238             *alpha |= *alpha >> abits;
    239             abits <<= 1;
    240         }
    241     }
    242     else
    243         *alpha = 0xffff;
    244 
    245     return TRUE;
    246 }
    247 
    248 static int
    249 exaTryDriverSolidFill(PicturePtr pSrc,
    250                       PicturePtr pDst,
    251                       INT16 xSrc,
    252                       INT16 ySrc,
    253                       INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
    254 {
    255     ExaScreenPriv(pDst->pDrawable->pScreen);
    256     RegionRec region;
    257     BoxPtr pbox;
    258     int nbox;
    259     int dst_off_x, dst_off_y;
    260     PixmapPtr pSrcPix, pDstPix;
    261     ExaPixmapPrivPtr pDstExaPix;
    262     CARD32 pixel;
    263     CARD16 red, green, blue, alpha;
    264 
    265     pDstPix = exaGetDrawablePixmap(pDst->pDrawable);
    266     pDstExaPix = ExaGetPixmapPriv(pDstPix);
    267 
    268     /* Check whether the accelerator can use the destination pixmap.
    269      */
    270     if (pDstExaPix->accel_blocked) {
    271         return -1;
    272     }
    273 
    274     xDst += pDst->pDrawable->x;
    275     yDst += pDst->pDrawable->y;
    276     if (pSrc->pDrawable) {
    277         xSrc += pSrc->pDrawable->x;
    278         ySrc += pSrc->pDrawable->y;
    279     }
    280 
    281     if (!miComputeCompositeRegion(&region, pSrc, NULL, pDst,
    282                                   xSrc, ySrc, 0, 0, xDst, yDst, width, height))
    283         return 1;
    284 
    285     exaGetDrawableDeltas(pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y);
    286 
    287     RegionTranslate(&region, dst_off_x, dst_off_y);
    288 
    289     if (pSrc->pDrawable) {
    290         pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
    291         pixel = exaGetPixmapFirstPixel(pSrcPix);
    292     }
    293     else
    294         miRenderColorToPixel(PictureMatchFormat(pDst->pDrawable->pScreen, 32,
    295                                                 pSrc->format),
    296                              &pSrc->pSourcePict->solidFill.fullcolor,
    297                              &pixel);
    298 
    299     if (!exaGetRGBAFromPixel(pixel, &red, &green, &blue, &alpha,
    300                              pSrc->pFormat, pSrc->format) ||
    301         !exaGetPixelFromRGBA(&pixel, red, green, blue, alpha, pDst->pFormat)) {
    302         RegionUninit(&region);
    303         return -1;
    304     }
    305 
    306     if (pExaScr->do_migration) {
    307         ExaMigrationRec pixmaps[1];
    308 
    309         pixmaps[0].as_dst = TRUE;
    310         pixmaps[0].as_src = FALSE;
    311         pixmaps[0].pPix = pDstPix;
    312         pixmaps[0].pReg = &region;
    313         exaDoMigration(pixmaps, 1, TRUE);
    314     }
    315 
    316     if (!exaPixmapHasGpuCopy(pDstPix)) {
    317         RegionUninit(&region);
    318         return 0;
    319     }
    320 
    321     if (!(*pExaScr->info->PrepareSolid) (pDstPix, GXcopy, 0xffffffff, pixel)) {
    322         RegionUninit(&region);
    323         return -1;
    324     }
    325 
    326     nbox = RegionNumRects(&region);
    327     pbox = RegionRects(&region);
    328 
    329     while (nbox--) {
    330         (*pExaScr->info->Solid) (pDstPix, pbox->x1, pbox->y1, pbox->x2,
    331                                  pbox->y2);
    332         pbox++;
    333     }
    334 
    335     (*pExaScr->info->DoneSolid) (pDstPix);
    336     exaMarkSync(pDst->pDrawable->pScreen);
    337 
    338     RegionUninit(&region);
    339     return 1;
    340 }
    341 
    342 static int
    343 exaTryDriverCompositeRects(CARD8 op,
    344                            PicturePtr pSrc,
    345                            PicturePtr pMask,
    346                            PicturePtr pDst,
    347                            int nrect, ExaCompositeRectPtr rects)
    348 {
    349     ExaScreenPriv(pDst->pDrawable->pScreen);
    350     int src_off_x = 0, src_off_y = 0, mask_off_x = 0, mask_off_y = 0;
    351     int dst_off_x, dst_off_y;
    352     PixmapPtr pSrcPix = NULL, pMaskPix = NULL, pDstPix;
    353     ExaPixmapPrivPtr pSrcExaPix = NULL, pMaskExaPix = NULL, pDstExaPix;
    354 
    355     if (!pExaScr->info->PrepareComposite)
    356         return -1;
    357 
    358     if (pSrc->pDrawable) {
    359         pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
    360         pSrcExaPix = ExaGetPixmapPriv(pSrcPix);
    361     }
    362 
    363     if (pMask && pMask->pDrawable) {
    364         pMaskPix = exaGetDrawablePixmap(pMask->pDrawable);
    365         pMaskExaPix = ExaGetPixmapPriv(pMaskPix);
    366     }
    367 
    368     pDstPix = exaGetDrawablePixmap(pDst->pDrawable);
    369     pDstExaPix = ExaGetPixmapPriv(pDstPix);
    370 
    371     /* Check whether the accelerator can use these pixmaps.
    372      * FIXME: If it cannot, use temporary pixmaps so that the drawing
    373      * happens within limits.
    374      */
    375     if (pDstExaPix->accel_blocked ||
    376         (pSrcExaPix && pSrcExaPix->accel_blocked) ||
    377         (pMaskExaPix && pMaskExaPix->accel_blocked)) {
    378         return -1;
    379     }
    380 
    381     if (pExaScr->info->CheckComposite &&
    382         !(*pExaScr->info->CheckComposite) (op, pSrc, pMask, pDst)) {
    383         return -1;
    384     }
    385 
    386     if (pExaScr->do_migration) {
    387         ExaMigrationRec pixmaps[3];
    388         int i = 0;
    389 
    390         pixmaps[i].as_dst = TRUE;
    391         pixmaps[i].as_src = exaOpReadsDestination(op);
    392         pixmaps[i].pPix = pDstPix;
    393         pixmaps[i].pReg = NULL;
    394         i++;
    395 
    396         if (pSrcPix) {
    397             pixmaps[i].as_dst = FALSE;
    398             pixmaps[i].as_src = TRUE;
    399             pixmaps[i].pPix = pSrcPix;
    400             pixmaps[i].pReg = NULL;
    401             i++;
    402         }
    403 
    404         if (pMaskPix) {
    405             pixmaps[i].as_dst = FALSE;
    406             pixmaps[i].as_src = TRUE;
    407             pixmaps[i].pPix = pMaskPix;
    408             pixmaps[i].pReg = NULL;
    409             i++;
    410         }
    411 
    412         exaDoMigration(pixmaps, i, TRUE);
    413     }
    414 
    415     pDstPix = exaGetOffscreenPixmap(pDst->pDrawable, &dst_off_x, &dst_off_y);
    416     if (!pDstPix)
    417         return 0;
    418 
    419     if (pSrcPix) {
    420         pSrcPix =
    421             exaGetOffscreenPixmap(pSrc->pDrawable, &src_off_x, &src_off_y);
    422         if (!pSrcPix)
    423             return 0;
    424     }
    425 
    426     if (pMaskPix) {
    427         pMaskPix =
    428             exaGetOffscreenPixmap(pMask->pDrawable, &mask_off_x, &mask_off_y);
    429         if (!pMaskPix)
    430             return 0;
    431     }
    432 
    433     if (!(*pExaScr->info->PrepareComposite) (op, pSrc, pMask, pDst, pSrcPix,
    434                                              pMaskPix, pDstPix))
    435         return -1;
    436 
    437     while (nrect--) {
    438         INT16 xDst = rects->xDst + pDst->pDrawable->x;
    439         INT16 yDst = rects->yDst + pDst->pDrawable->y;
    440         INT16 xMask = rects->xMask;
    441         INT16 yMask = rects->yMask;
    442         INT16 xSrc = rects->xSrc;
    443         INT16 ySrc = rects->ySrc;
    444         RegionRec region;
    445         BoxPtr pbox;
    446         int nbox;
    447 
    448         if (pMaskPix) {
    449             xMask += pMask->pDrawable->x;
    450             yMask += pMask->pDrawable->y;
    451         }
    452 
    453         if (pSrcPix) {
    454             xSrc += pSrc->pDrawable->x;
    455             ySrc += pSrc->pDrawable->y;
    456         }
    457 
    458         if (!miComputeCompositeRegion(&region, pSrc, pMask, pDst,
    459                                       xSrc, ySrc, xMask, yMask, xDst, yDst,
    460                                       rects->width, rects->height))
    461             goto next_rect;
    462 
    463         RegionTranslate(&region, dst_off_x, dst_off_y);
    464 
    465         nbox = RegionNumRects(&region);
    466         pbox = RegionRects(&region);
    467 
    468         xMask = xMask + mask_off_x - xDst - dst_off_x;
    469         yMask = yMask + mask_off_y - yDst - dst_off_y;
    470         xSrc = xSrc + src_off_x - xDst - dst_off_x;
    471         ySrc = ySrc + src_off_y - yDst - dst_off_y;
    472 
    473         while (nbox--) {
    474             (*pExaScr->info->Composite) (pDstPix,
    475                                          pbox->x1 + xSrc,
    476                                          pbox->y1 + ySrc,
    477                                          pbox->x1 + xMask,
    478                                          pbox->y1 + yMask,
    479                                          pbox->x1,
    480                                          pbox->y1,
    481                                          pbox->x2 - pbox->x1,
    482                                          pbox->y2 - pbox->y1);
    483             pbox++;
    484         }
    485 
    486  next_rect:
    487         RegionUninit(&region);
    488 
    489         rects++;
    490     }
    491 
    492     (*pExaScr->info->DoneComposite) (pDstPix);
    493     exaMarkSync(pDst->pDrawable->pScreen);
    494 
    495     return 1;
    496 }
    497 
    498 /**
    499  * Copy a number of rectangles from source to destination in a single
    500  * operation. This is specialized for glyph rendering: we don't have the
    501  * special-case fallbacks found in exaComposite() - if the driver can support
    502  * it, we use the driver functionality, otherwise we fall back straight to
    503  * software.
    504  */
    505 void
    506 exaCompositeRects(CARD8 op,
    507                   PicturePtr pSrc,
    508                   PicturePtr pMask,
    509                   PicturePtr pDst, int nrect, ExaCompositeRectPtr rects)
    510 {
    511     ExaScreenPriv(pDst->pDrawable->pScreen);
    512     int n;
    513     ExaCompositeRectPtr r;
    514     int ret;
    515 
    516     /* If we get a mask, that means we're rendering to the exaGlyphs
    517      * destination directly, so the damage layer takes care of this.
    518      */
    519     if (!pMask) {
    520         RegionRec region;
    521         int x1 = MAXSHORT;
    522         int y1 = MAXSHORT;
    523         int x2 = MINSHORT;
    524         int y2 = MINSHORT;
    525         BoxRec box;
    526 
    527         /* We have to manage the damage ourselves, since CompositeRects isn't
    528          * something in the screen that can be managed by the damage extension,
    529          * and EXA depends on damage to track what needs to be migrated between
    530          * the gpu and the cpu.
    531          */
    532 
    533         /* Compute the overall extents of the composited region - we're making
    534          * the assumption here that we are compositing a bunch of glyphs that
    535          * cluster closely together and damaging each glyph individually would
    536          * be a loss compared to damaging the bounding box.
    537          */
    538         n = nrect;
    539         r = rects;
    540         while (n--) {
    541             int rect_x2 = r->xDst + r->width;
    542             int rect_y2 = r->yDst + r->height;
    543 
    544             if (r->xDst < x1)
    545                 x1 = r->xDst;
    546             if (r->yDst < y1)
    547                 y1 = r->yDst;
    548             if (rect_x2 > x2)
    549                 x2 = rect_x2;
    550             if (rect_y2 > y2)
    551                 y2 = rect_y2;
    552 
    553             r++;
    554         }
    555 
    556         if (x2 <= x1 || y2 <= y1)
    557             return;
    558 
    559         box.x1 = x1;
    560         box.x2 = x2 < MAXSHORT ? x2 : MAXSHORT;
    561         box.y1 = y1;
    562         box.y2 = y2 < MAXSHORT ? y2 : MAXSHORT;
    563 
    564         /* The pixmap migration code relies on pendingDamage indicating
    565          * the bounds of the current rendering, so we need to force
    566          * the actual damage into that region before we do anything, and
    567          * (see use of DamagePendingRegion in exaCopyDirty)
    568          */
    569 
    570         RegionInit(&region, &box, 1);
    571 
    572         DamageRegionAppend(pDst->pDrawable, &region);
    573 
    574         RegionUninit(&region);
    575     }
    576 
    577     /************************************************************/
    578 
    579     ValidatePicture(pSrc);
    580     if (pMask)
    581         ValidatePicture(pMask);
    582     ValidatePicture(pDst);
    583 
    584     ret = exaTryDriverCompositeRects(op, pSrc, pMask, pDst, nrect, rects);
    585 
    586     if (ret != 1) {
    587         if (ret == -1 && op == PictOpOver && pMask && pMask->componentAlpha &&
    588             (!pExaScr->info->CheckComposite ||
    589              ((*pExaScr->info->CheckComposite) (PictOpOutReverse, pSrc, pMask,
    590                                                 pDst) &&
    591               (*pExaScr->info->CheckComposite) (PictOpAdd, pSrc, pMask,
    592                                                 pDst)))) {
    593             ret =
    594                 exaTryDriverCompositeRects(PictOpOutReverse, pSrc, pMask, pDst,
    595                                            nrect, rects);
    596             if (ret == 1) {
    597                 op = PictOpAdd;
    598                 ret = exaTryDriverCompositeRects(op, pSrc, pMask, pDst, nrect,
    599                                                  rects);
    600             }
    601         }
    602 
    603         if (ret != 1) {
    604             n = nrect;
    605             r = rects;
    606             while (n--) {
    607                 ExaCheckComposite(op, pSrc, pMask, pDst,
    608                                   r->xSrc, r->ySrc,
    609                                   r->xMask, r->yMask,
    610                                   r->xDst, r->yDst, r->width, r->height);
    611                 r++;
    612             }
    613         }
    614     }
    615 
    616     /************************************************************/
    617 
    618     if (!pMask) {
    619         /* Now we have to flush the damage out from pendingDamage => damage
    620          * Calling DamageRegionProcessPending has that effect.
    621          */
    622 
    623         DamageRegionProcessPending(pDst->pDrawable);
    624     }
    625 }
    626 
    627 static int
    628 exaTryDriverComposite(CARD8 op,
    629                       PicturePtr pSrc,
    630                       PicturePtr pMask,
    631                       PicturePtr pDst,
    632                       INT16 xSrc,
    633                       INT16 ySrc,
    634                       INT16 xMask,
    635                       INT16 yMask,
    636                       INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
    637 {
    638     ExaScreenPriv(pDst->pDrawable->pScreen);
    639     RegionRec region;
    640     BoxPtr pbox;
    641     int nbox;
    642     int src_off_x, src_off_y, mask_off_x = 0, mask_off_y = 0, dst_off_x, dst_off_y;
    643     PixmapPtr pSrcPix = NULL, pMaskPix = NULL, pDstPix;
    644     ExaPixmapPrivPtr pSrcExaPix = NULL, pMaskExaPix = NULL, pDstExaPix;
    645 
    646     if (pSrc->pDrawable) {
    647         pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
    648         pSrcExaPix = ExaGetPixmapPriv(pSrcPix);
    649     }
    650 
    651     pDstPix = exaGetDrawablePixmap(pDst->pDrawable);
    652     pDstExaPix = ExaGetPixmapPriv(pDstPix);
    653 
    654     if (pMask && pMask->pDrawable) {
    655         pMaskPix = exaGetDrawablePixmap(pMask->pDrawable);
    656         pMaskExaPix = ExaGetPixmapPriv(pMaskPix);
    657     }
    658 
    659     /* Check whether the accelerator can use these pixmaps.
    660      * FIXME: If it cannot, use temporary pixmaps so that the drawing
    661      * happens within limits.
    662      */
    663     if (pDstExaPix->accel_blocked ||
    664         (pSrcExaPix && pSrcExaPix->accel_blocked) ||
    665         (pMaskExaPix && (pMaskExaPix->accel_blocked))) {
    666         return -1;
    667     }
    668 
    669     xDst += pDst->pDrawable->x;
    670     yDst += pDst->pDrawable->y;
    671 
    672     if (pMaskPix) {
    673         xMask += pMask->pDrawable->x;
    674         yMask += pMask->pDrawable->y;
    675     }
    676 
    677     if (pSrcPix) {
    678         xSrc += pSrc->pDrawable->x;
    679         ySrc += pSrc->pDrawable->y;
    680     }
    681 
    682     if (pExaScr->info->CheckComposite &&
    683         !(*pExaScr->info->CheckComposite) (op, pSrc, pMask, pDst)) {
    684         return -1;
    685     }
    686 
    687     if (!miComputeCompositeRegion(&region, pSrc, pMask, pDst,
    688                                   xSrc, ySrc, xMask, yMask, xDst, yDst,
    689                                   width, height))
    690         return 1;
    691 
    692     exaGetDrawableDeltas(pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y);
    693 
    694     RegionTranslate(&region, dst_off_x, dst_off_y);
    695 
    696     if (pExaScr->do_migration) {
    697         ExaMigrationRec pixmaps[3];
    698         int i = 0;
    699 
    700         pixmaps[i].as_dst = TRUE;
    701         pixmaps[i].as_src = exaOpReadsDestination(op);
    702         pixmaps[i].pPix = pDstPix;
    703         pixmaps[i].pReg = pixmaps[0].as_src ? NULL : &region;
    704         i++;
    705 
    706         if (pSrcPix) {
    707             pixmaps[i].as_dst = FALSE;
    708             pixmaps[i].as_src = TRUE;
    709             pixmaps[i].pPix = pSrcPix;
    710             pixmaps[i].pReg = NULL;
    711             i++;
    712         }
    713 
    714         if (pMaskPix) {
    715             pixmaps[i].as_dst = FALSE;
    716             pixmaps[i].as_src = TRUE;
    717             pixmaps[i].pPix = pMaskPix;
    718             pixmaps[i].pReg = NULL;
    719             i++;
    720         }
    721 
    722         exaDoMigration(pixmaps, i, TRUE);
    723     }
    724 
    725     if (pSrcPix) {
    726         pSrcPix =
    727             exaGetOffscreenPixmap(pSrc->pDrawable, &src_off_x, &src_off_y);
    728         if (!pSrcPix) {
    729             RegionUninit(&region);
    730             return 0;
    731         }
    732     }
    733 
    734     if (pMaskPix) {
    735         pMaskPix = exaGetOffscreenPixmap(pMask->pDrawable, &mask_off_x,
    736                                          &mask_off_y);
    737         if (!pMaskPix) {
    738             RegionUninit(&region);
    739             return 0;
    740         }
    741     }
    742 
    743     if (!exaPixmapHasGpuCopy(pDstPix)) {
    744         RegionUninit(&region);
    745         return 0;
    746     }
    747 
    748     if (!(*pExaScr->info->PrepareComposite) (op, pSrc, pMask, pDst, pSrcPix,
    749                                              pMaskPix, pDstPix)) {
    750         RegionUninit(&region);
    751         return -1;
    752     }
    753 
    754     nbox = RegionNumRects(&region);
    755     pbox = RegionRects(&region);
    756 
    757     xMask = xMask + mask_off_x - xDst - dst_off_x;
    758     yMask = yMask + mask_off_y - yDst - dst_off_y;
    759 
    760     xSrc = xSrc + src_off_x - xDst - dst_off_x;
    761     ySrc = ySrc + src_off_y - yDst - dst_off_y;
    762 
    763     while (nbox--) {
    764         (*pExaScr->info->Composite) (pDstPix,
    765                                      pbox->x1 + xSrc,
    766                                      pbox->y1 + ySrc,
    767                                      pbox->x1 + xMask,
    768                                      pbox->y1 + yMask,
    769                                      pbox->x1,
    770                                      pbox->y1,
    771                                      pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
    772         pbox++;
    773     }
    774     (*pExaScr->info->DoneComposite) (pDstPix);
    775     exaMarkSync(pDst->pDrawable->pScreen);
    776 
    777     RegionUninit(&region);
    778     return 1;
    779 }
    780 
    781 /**
    782  * exaTryMagicTwoPassCompositeHelper implements PictOpOver using two passes of
    783  * simpler operations PictOpOutReverse and PictOpAdd. Mainly used for component
    784  * alpha and limited 1-tmu cards.
    785  *
    786  * From http://anholt.livejournal.com/32058.html:
    787  *
    788  * The trouble is that component-alpha rendering requires two different sources
    789  * for blending: one for the source value to the blender, which is the
    790  * per-channel multiplication of source and mask, and one for the source alpha
    791  * for multiplying with the destination channels, which is the multiplication
    792  * of the source channels by the mask alpha. So the equation for Over is:
    793  *
    794  * dst.A = src.A * mask.A + (1 - (src.A * mask.A)) * dst.A
    795  * dst.R = src.R * mask.R + (1 - (src.A * mask.R)) * dst.R
    796  * dst.G = src.G * mask.G + (1 - (src.A * mask.G)) * dst.G
    797  * dst.B = src.B * mask.B + (1 - (src.A * mask.B)) * dst.B
    798  *
    799  * But we can do some simpler operations, right? How about PictOpOutReverse,
    800  * which has a source factor of 0 and dest factor of (1 - source alpha). We
    801  * can get the source alpha value (srca.X = src.A * mask.X) out of the texture
    802  * blenders pretty easily. So we can do a component-alpha OutReverse, which
    803  * gets us:
    804  *
    805  * dst.A = 0 + (1 - (src.A * mask.A)) * dst.A
    806  * dst.R = 0 + (1 - (src.A * mask.R)) * dst.R
    807  * dst.G = 0 + (1 - (src.A * mask.G)) * dst.G
    808  * dst.B = 0 + (1 - (src.A * mask.B)) * dst.B
    809  *
    810  * OK. And if an op doesn't use the source alpha value for the destination
    811  * factor, then we can do the channel multiplication in the texture blenders
    812  * to get the source value, and ignore the source alpha that we wouldn't use.
    813  * We've supported this in the Radeon driver for a long time. An example would
    814  * be PictOpAdd, which does:
    815  *
    816  * dst.A = src.A * mask.A + dst.A
    817  * dst.R = src.R * mask.R + dst.R
    818  * dst.G = src.G * mask.G + dst.G
    819  * dst.B = src.B * mask.B + dst.B
    820  *
    821  * Hey, this looks good! If we do a PictOpOutReverse and then a PictOpAdd right
    822  * after it, we get:
    823  *
    824  * dst.A = src.A * mask.A + ((1 - (src.A * mask.A)) * dst.A)
    825  * dst.R = src.R * mask.R + ((1 - (src.A * mask.R)) * dst.R)
    826  * dst.G = src.G * mask.G + ((1 - (src.A * mask.G)) * dst.G)
    827  * dst.B = src.B * mask.B + ((1 - (src.A * mask.B)) * dst.B)
    828  */
    829 
    830 static int
    831 exaTryMagicTwoPassCompositeHelper(CARD8 op,
    832                                   PicturePtr pSrc,
    833                                   PicturePtr pMask,
    834                                   PicturePtr pDst,
    835                                   INT16 xSrc,
    836                                   INT16 ySrc,
    837                                   INT16 xMask,
    838                                   INT16 yMask,
    839                                   INT16 xDst,
    840                                   INT16 yDst, CARD16 width, CARD16 height)
    841 {
    842     ExaScreenPriv(pDst->pDrawable->pScreen);
    843 
    844     assert(op == PictOpOver);
    845 
    846     if (pExaScr->info->CheckComposite &&
    847         (!(*pExaScr->info->CheckComposite) (PictOpOutReverse, pSrc, pMask,
    848                                             pDst) ||
    849          !(*pExaScr->info->CheckComposite) (PictOpAdd, pSrc, pMask, pDst))) {
    850         return -1;
    851     }
    852 
    853     /* Now, we think we should be able to accelerate this operation. First,
    854      * composite the destination to be the destination times the source alpha
    855      * factors.
    856      */
    857     exaComposite(PictOpOutReverse, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
    858                  xDst, yDst, width, height);
    859 
    860     /* Then, add in the source value times the destination alpha factors (1.0).
    861      */
    862     exaComposite(PictOpAdd, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
    863                  xDst, yDst, width, height);
    864 
    865     return 1;
    866 }
    867 
    868 void
    869 exaComposite(CARD8 op,
    870              PicturePtr pSrc,
    871              PicturePtr pMask,
    872              PicturePtr pDst,
    873              INT16 xSrc,
    874              INT16 ySrc,
    875              INT16 xMask,
    876              INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
    877 {
    878     ExaScreenPriv(pDst->pDrawable->pScreen);
    879     int ret = -1;
    880     Bool saveSrcRepeat = pSrc->repeat;
    881     Bool saveMaskRepeat = pMask ? pMask->repeat : 0;
    882     RegionRec region;
    883 
    884     if (pExaScr->swappedOut)
    885         goto fallback;
    886 
    887     /* Remove repeat in source if useless */
    888     if (pSrc->pDrawable && pSrc->repeat && !pSrc->transform && xSrc >= 0 &&
    889         (xSrc + width) <= pSrc->pDrawable->width && ySrc >= 0 &&
    890         (ySrc + height) <= pSrc->pDrawable->height)
    891         pSrc->repeat = 0;
    892 
    893     if (!pMask && !pSrc->alphaMap && !pDst->alphaMap &&
    894         (op == PictOpSrc || (op == PictOpOver && !PICT_FORMAT_A(pSrc->format))))
    895     {
    896         if (pSrc->pDrawable ?
    897             (pSrc->pDrawable->width == 1 && pSrc->pDrawable->height == 1 &&
    898              pSrc->repeat) :
    899             (pSrc->pSourcePict->type == SourcePictTypeSolidFill)) {
    900             ret = exaTryDriverSolidFill(pSrc, pDst, xSrc, ySrc, xDst, yDst,
    901                                         width, height);
    902             if (ret == 1)
    903                 goto done;
    904         }
    905         else if (pSrc->pDrawable && !pSrc->transform &&
    906                  ((op == PictOpSrc &&
    907                    (pSrc->format == pDst->format ||
    908                     (PICT_FORMAT_COLOR(pDst->format) &&
    909                      PICT_FORMAT_COLOR(pSrc->format) &&
    910                      pDst->format == PICT_FORMAT(PICT_FORMAT_BPP(pSrc->format),
    911                                                  PICT_FORMAT_TYPE(pSrc->format),
    912                                                  0,
    913                                                  PICT_FORMAT_R(pSrc->format),
    914                                                  PICT_FORMAT_G(pSrc->format),
    915                                                  PICT_FORMAT_B(pSrc->format)))))
    916                   || (op == PictOpOver && pSrc->format == pDst->format &&
    917                       !PICT_FORMAT_A(pSrc->format)))) {
    918             if (!pSrc->repeat && xSrc >= 0 && ySrc >= 0 &&
    919                 (xSrc + width <= pSrc->pDrawable->width) &&
    920                 (ySrc + height <= pSrc->pDrawable->height)) {
    921                 Bool suc;
    922 
    923                 xDst += pDst->pDrawable->x;
    924                 yDst += pDst->pDrawable->y;
    925                 xSrc += pSrc->pDrawable->x;
    926                 ySrc += pSrc->pDrawable->y;
    927 
    928                 if (!miComputeCompositeRegion(&region, pSrc, pMask, pDst,
    929                                               xSrc, ySrc, xMask, yMask, xDst,
    930                                               yDst, width, height))
    931                     goto done;
    932 
    933                 suc = exaHWCopyNtoN(pSrc->pDrawable, pDst->pDrawable, NULL,
    934                                     RegionRects(&region),
    935                                     RegionNumRects(&region), xSrc - xDst,
    936                                     ySrc - yDst, FALSE, FALSE);
    937                 RegionUninit(&region);
    938 
    939                 /* Reset values to their original values. */
    940                 xDst -= pDst->pDrawable->x;
    941                 yDst -= pDst->pDrawable->y;
    942                 xSrc -= pSrc->pDrawable->x;
    943                 ySrc -= pSrc->pDrawable->y;
    944 
    945                 if (!suc)
    946                     goto fallback;
    947 
    948                 goto done;
    949             }
    950 
    951             if (pSrc->repeat && pSrc->repeatType == RepeatNormal &&
    952                 pSrc->pDrawable->type == DRAWABLE_PIXMAP) {
    953                 DDXPointRec patOrg;
    954 
    955                 /* Let's see if the driver can do the repeat in one go */
    956                 if (pExaScr->info->PrepareComposite && !pSrc->alphaMap &&
    957                     !pDst->alphaMap) {
    958                     ret = exaTryDriverComposite(op, pSrc, pMask, pDst, xSrc,
    959                                                 ySrc, xMask, yMask, xDst, yDst,
    960                                                 width, height);
    961                     if (ret == 1)
    962                         goto done;
    963                 }
    964 
    965                 /* Now see if we can use exaFillRegionTiled() */
    966                 xDst += pDst->pDrawable->x;
    967                 yDst += pDst->pDrawable->y;
    968                 xSrc += pSrc->pDrawable->x;
    969                 ySrc += pSrc->pDrawable->y;
    970 
    971                 if (!miComputeCompositeRegion(&region, pSrc, pMask, pDst, xSrc,
    972                                               ySrc, xMask, yMask, xDst, yDst,
    973                                               width, height))
    974                     goto done;
    975 
    976                 /* pattern origin is the point in the destination drawable
    977                  * corresponding to (0,0) in the source */
    978                 patOrg.x = xDst - xSrc;
    979                 patOrg.y = yDst - ySrc;
    980 
    981                 ret = exaFillRegionTiled(pDst->pDrawable, &region,
    982                                          (PixmapPtr) pSrc->pDrawable,
    983                                          &patOrg, FB_ALLONES, GXcopy, CT_NONE);
    984 
    985                 RegionUninit(&region);
    986 
    987                 if (ret)
    988                     goto done;
    989 
    990                 /* Let's be correct and restore the variables to their original state. */
    991                 xDst -= pDst->pDrawable->x;
    992                 yDst -= pDst->pDrawable->y;
    993                 xSrc -= pSrc->pDrawable->x;
    994                 ySrc -= pSrc->pDrawable->y;
    995             }
    996         }
    997     }
    998 
    999     /* Remove repeat in mask if useless */
   1000     if (pMask && pMask->pDrawable && pMask->repeat && !pMask->transform &&
   1001         xMask >= 0 && (xMask + width) <= pMask->pDrawable->width &&
   1002         yMask >= 0 && (yMask + height) <= pMask->pDrawable->height)
   1003         pMask->repeat = 0;
   1004 
   1005     if (pExaScr->info->PrepareComposite &&
   1006         !pSrc->alphaMap && (!pMask || !pMask->alphaMap) && !pDst->alphaMap) {
   1007         Bool isSrcSolid;
   1008 
   1009         ret = exaTryDriverComposite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask,
   1010                                     yMask, xDst, yDst, width, height);
   1011         if (ret == 1)
   1012             goto done;
   1013 
   1014         /* For generic masks and solid src pictures, mach64 can do Over in two
   1015          * passes, similar to the component-alpha case.
   1016          */
   1017         isSrcSolid = pSrc->pDrawable ?
   1018             (pSrc->pDrawable->width == 1 && pSrc->pDrawable->height == 1 &&
   1019              pSrc->repeat) :
   1020             (pSrc->pSourcePict->type == SourcePictTypeSolidFill);
   1021 
   1022         /* If we couldn't do the Composite in a single pass, and it was a
   1023          * component-alpha Over, see if we can do it in two passes with
   1024          * an OutReverse and then an Add.
   1025          */
   1026         if (ret == -1 && op == PictOpOver && pMask &&
   1027             (pMask->componentAlpha || isSrcSolid)) {
   1028             ret = exaTryMagicTwoPassCompositeHelper(op, pSrc, pMask, pDst,
   1029                                                     xSrc, ySrc,
   1030                                                     xMask, yMask, xDst, yDst,
   1031                                                     width, height);
   1032             if (ret == 1)
   1033                 goto done;
   1034         }
   1035     }
   1036 
   1037  fallback:
   1038 #if DEBUG_TRACE_FALL
   1039     exaPrintCompositeFallback(op, pSrc, pMask, pDst);
   1040 #endif
   1041 
   1042     ExaCheckComposite(op, pSrc, pMask, pDst, xSrc, ySrc,
   1043                       xMask, yMask, xDst, yDst, width, height);
   1044 
   1045  done:
   1046     pSrc->repeat = saveSrcRepeat;
   1047     if (pMask)
   1048         pMask->repeat = saveMaskRepeat;
   1049 }
   1050 
   1051 /**
   1052  * Same as miCreateAlphaPicture, except it uses ExaCheckPolyFillRect instead
   1053  * of PolyFillRect to initialize the pixmap after creating it, to prevent
   1054  * the pixmap from being migrated.
   1055  *
   1056  * See the comments about exaTrapezoids and exaTriangles.
   1057  */
   1058 static PicturePtr
   1059 exaCreateAlphaPicture(ScreenPtr pScreen,
   1060                       PicturePtr pDst,
   1061                       PictFormatPtr pPictFormat, CARD16 width, CARD16 height)
   1062 {
   1063     PixmapPtr pPixmap;
   1064     PicturePtr pPicture;
   1065     GCPtr pGC;
   1066     int error;
   1067     xRectangle rect;
   1068 
   1069     if (width > 32767 || height > 32767)
   1070         return 0;
   1071 
   1072     if (!pPictFormat) {
   1073         if (pDst->polyEdge == PolyEdgeSharp)
   1074             pPictFormat = PictureMatchFormat(pScreen, 1, PICT_a1);
   1075         else
   1076             pPictFormat = PictureMatchFormat(pScreen, 8, PICT_a8);
   1077         if (!pPictFormat)
   1078             return 0;
   1079     }
   1080 
   1081     pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
   1082                                         pPictFormat->depth, 0);
   1083     if (!pPixmap)
   1084         return 0;
   1085     pGC = GetScratchGC(pPixmap->drawable.depth, pScreen);
   1086     if (!pGC) {
   1087         (*pScreen->DestroyPixmap) (pPixmap);
   1088         return 0;
   1089     }
   1090     ValidateGC(&pPixmap->drawable, pGC);
   1091     rect.x = 0;
   1092     rect.y = 0;
   1093     rect.width = width;
   1094     rect.height = height;
   1095     ExaCheckPolyFillRect(&pPixmap->drawable, pGC, 1, &rect);
   1096     exaPixmapDirty(pPixmap, 0, 0, width, height);
   1097     FreeScratchGC(pGC);
   1098     pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat,
   1099                              0, 0, serverClient, &error);
   1100     (*pScreen->DestroyPixmap) (pPixmap);
   1101     return pPicture;
   1102 }
   1103 
   1104 /**
   1105  * exaTrapezoids is essentially a copy of miTrapezoids that uses
   1106  * exaCreateAlphaPicture instead of miCreateAlphaPicture.
   1107  *
   1108  * The problem with miCreateAlphaPicture is that it calls PolyFillRect
   1109  * to initialize the contents after creating the pixmap, which
   1110  * causes the pixmap to be moved in for acceleration. The subsequent
   1111  * call to RasterizeTrapezoid won't be accelerated however, which
   1112  * forces the pixmap to be moved out again.
   1113  *
   1114  * exaCreateAlphaPicture avoids this roundtrip by using ExaCheckPolyFillRect
   1115  * to initialize the contents.
   1116  */
   1117 void
   1118 exaTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
   1119               PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
   1120               int ntrap, xTrapezoid * traps)
   1121 {
   1122     ScreenPtr pScreen = pDst->pDrawable->pScreen;
   1123     PictureScreenPtr ps = GetPictureScreen(pScreen);
   1124     BoxRec bounds;
   1125 
   1126     if (maskFormat) {
   1127         PicturePtr pPicture;
   1128         INT16 xDst, yDst;
   1129         INT16 xRel, yRel;
   1130 
   1131         miTrapezoidBounds(ntrap, traps, &bounds);
   1132 
   1133         if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
   1134             return;
   1135 
   1136         xDst = traps[0].left.p1.x >> 16;
   1137         yDst = traps[0].left.p1.y >> 16;
   1138 
   1139         pPicture = exaCreateAlphaPicture(pScreen, pDst, maskFormat,
   1140                                          bounds.x2 - bounds.x1,
   1141                                          bounds.y2 - bounds.y1);
   1142         if (!pPicture)
   1143             return;
   1144 
   1145         exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
   1146         for (; ntrap; ntrap--, traps++)
   1147             if (xTrapezoidValid(traps))
   1148                 (*ps->RasterizeTrapezoid) (pPicture, traps, -bounds.x1, -bounds.y1);
   1149         exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
   1150 
   1151         xRel = bounds.x1 + xSrc - xDst;
   1152         yRel = bounds.y1 + ySrc - yDst;
   1153         CompositePicture(op, pSrc, pPicture, pDst,
   1154                          xRel, yRel, 0, 0, bounds.x1, bounds.y1,
   1155                          bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
   1156         FreePicture(pPicture, 0);
   1157     }
   1158     else {
   1159         if (pDst->polyEdge == PolyEdgeSharp)
   1160             maskFormat = PictureMatchFormat(pScreen, 1, PICT_a1);
   1161         else
   1162             maskFormat = PictureMatchFormat(pScreen, 8, PICT_a8);
   1163         for (; ntrap; ntrap--, traps++)
   1164             exaTrapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, traps);
   1165     }
   1166 }
   1167 
   1168 /**
   1169  * exaTriangles is essentially a copy of miTriangles that uses
   1170  * exaCreateAlphaPicture instead of miCreateAlphaPicture.
   1171  *
   1172  * The problem with miCreateAlphaPicture is that it calls PolyFillRect
   1173  * to initialize the contents after creating the pixmap, which
   1174  * causes the pixmap to be moved in for acceleration. The subsequent
   1175  * call to AddTriangles won't be accelerated however, which forces the pixmap
   1176  * to be moved out again.
   1177  *
   1178  * exaCreateAlphaPicture avoids this roundtrip by using ExaCheckPolyFillRect
   1179  * to initialize the contents.
   1180  */
   1181 void
   1182 exaTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
   1183              PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
   1184              int ntri, xTriangle * tris)
   1185 {
   1186     ScreenPtr pScreen = pDst->pDrawable->pScreen;
   1187     PictureScreenPtr ps = GetPictureScreen(pScreen);
   1188     BoxRec bounds;
   1189 
   1190     if (maskFormat) {
   1191         PicturePtr pPicture;
   1192         INT16 xDst, yDst;
   1193         INT16 xRel, yRel;
   1194 
   1195         miTriangleBounds(ntri, tris, &bounds);
   1196 
   1197         if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
   1198             return;
   1199 
   1200         xDst = tris[0].p1.x >> 16;
   1201         yDst = tris[0].p1.y >> 16;
   1202 
   1203         pPicture = exaCreateAlphaPicture(pScreen, pDst, maskFormat,
   1204                                          bounds.x2 - bounds.x1,
   1205                                          bounds.y2 - bounds.y1);
   1206         if (!pPicture)
   1207             return;
   1208 
   1209         exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
   1210         (*ps->AddTriangles) (pPicture, -bounds.x1, -bounds.y1, ntri, tris);
   1211         exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
   1212 
   1213         xRel = bounds.x1 + xSrc - xDst;
   1214         yRel = bounds.y1 + ySrc - yDst;
   1215         CompositePicture(op, pSrc, pPicture, pDst,
   1216                          xRel, yRel, 0, 0, bounds.x1, bounds.y1,
   1217                          bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
   1218         FreePicture(pPicture, 0);
   1219     }
   1220     else {
   1221         if (pDst->polyEdge == PolyEdgeSharp)
   1222             maskFormat = PictureMatchFormat(pScreen, 1, PICT_a1);
   1223         else
   1224             maskFormat = PictureMatchFormat(pScreen, 8, PICT_a8);
   1225 
   1226         for (; ntri; ntri--, tris++)
   1227             exaTriangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, tris);
   1228     }
   1229 }