Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
      3  * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
      4  * Copyright 2006 Thomas Hellstrm. All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sub license,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice (including the
     14  * next paragraph) shall be included in all copies or substantial portions
     15  * of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     23  * DEALINGS IN THE SOFTWARE.
     24  */
     25 
     26 /*
     27  * 2D acceleration functions for the VIA/S3G UniChrome IGPs.
     28  *
     29  * Mostly rewritten, and modified for EXA support, by Thomas Hellstrm.
     30  */
     31 
     32 #ifdef HAVE_CONFIG_H
     33 #include "config.h"
     34 #endif
     35 
     36 #include <X11/Xarch.h>
     37 #include "miline.h"
     38 
     39 #include "via_driver.h"
     40 #include "via_regs.h"
     41 #include "via_dmabuffer.h"
     42 #include "via_rop.h"
     43 
     44 /*
     45  * Emit clipping borders to the command buffer and update the 2D context
     46  * current command with clipping info.
     47  */
     48 static int
     49 viaAccelClippingHelper_H6(VIAPtr pVia, int refY)
     50 {
     51     ViaTwodContext *tdc = &pVia->td;
     52 
     53     RING_VARS;
     54 
     55     if (tdc->clipping) {
     56         refY = (refY < tdc->clipY1) ? refY : tdc->clipY1;
     57         tdc->cmd |= VIA_GEC_CLIP_ENABLE;
     58         BEGIN_RING(4);
     59         OUT_RING_H1(VIA_REG_CLIPTL_M1,
     60                     ((tdc->clipY1 - refY) << 16) | tdc->clipX1);
     61         OUT_RING_H1(VIA_REG_CLIPBR_M1,
     62 		    ((tdc->clipY2 - refY) << 16) | tdc->clipX2);
     63     } else {
     64         tdc->cmd &= ~VIA_GEC_CLIP_ENABLE;
     65     }
     66     return refY;
     67 }
     68 
     69 /*
     70  * Check if we can use a planeMask and update the 2D context accordingly.
     71  */
     72 static Bool
     73 viaAccelPlaneMaskHelper_H6(ViaTwodContext * tdc, CARD32 planeMask)
     74 {
     75     CARD32 modeMask = (1 << ((1 << tdc->bytesPPShift) << 3)) - 1;
     76     CARD32 curMask = 0x00000000;
     77     CARD32 curByteMask;
     78     int i;
     79 
     80     if ((planeMask & modeMask) != modeMask) {
     81 
     82         /* Masking doesn't work in 8bpp. */
     83         if (modeMask == 0xFF) {
     84             tdc->keyControl &= 0x0FFFFFFF;
     85             return FALSE;
     86         }
     87 
     88         /* Translate the bit planemask to a byte planemask. */
     89         for (i = 0; i < (1 << tdc->bytesPPShift); ++i) {
     90             curByteMask = (0xFF << (i << 3));
     91 
     92             if ((planeMask & curByteMask) == 0) {
     93                 curMask |= (1 << i);
     94             } else if ((planeMask & curByteMask) != curByteMask) {
     95                 tdc->keyControl &= 0x0FFFFFFF;
     96                 return FALSE;
     97             }
     98         }
     99         ErrorF("DEBUG: planeMask 0x%08x, curMask 0%02x\n",
    100                (unsigned)planeMask, (unsigned)curMask);
    101 
    102         tdc->keyControl = (tdc->keyControl & 0x0FFFFFFF) | (curMask << 28);
    103     }
    104 
    105     return TRUE;
    106 }
    107 
    108 /*
    109  * Emit transparency state and color to the command buffer.
    110  */
    111 static void
    112 viaAccelTransparentHelper_H6(VIAPtr pVia, CARD32 keyControl,
    113                           CARD32 transColor, Bool usePlaneMask)
    114 {
    115     ViaTwodContext *tdc = &pVia->td;
    116 
    117     RING_VARS;
    118 
    119     tdc->keyControl &= ((usePlaneMask) ? 0xF0000000 : 0x00000000);
    120     tdc->keyControl |= (keyControl & 0x0FFFFFFF);
    121     BEGIN_RING(4);
    122     OUT_RING_H1(VIA_REG_KEYCONTROL_M1, tdc->keyControl);
    123     if (keyControl) {
    124         OUT_RING_H1(VIA_REG_SRCCOLORKEY_M1, transColor);
    125     }
    126 }
    127 
    128 /*
    129  * Mark Sync using the 2D blitter for AGP. NoOp for PCI.
    130  * In the future one could even launch a NULL PCI DMA command
    131  * to have an interrupt generated, provided it is possible to
    132  * write to the PCI DMA engines from the AGP command stream.
    133  */
    134 int
    135 viaAccelMarkSync_H6(ScreenPtr pScreen)
    136 {
    137     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    138     VIAPtr pVia = VIAPTR(pScrn);
    139 
    140     RING_VARS;
    141 
    142     ++pVia->curMarker;
    143 
    144     /* Wrap around without affecting the sign bit. */
    145     pVia->curMarker &= 0x7FFFFFFF;
    146 
    147     if (pVia->agpDMA) {
    148         BEGIN_RING(16);
    149 
    150         OUT_RING_H1(VIA_REG_KEYCONTROL_M1, 0x00);
    151         OUT_RING_H1(VIA_REG_GEMODE_M1, VIA_GEM_32bpp);
    152         OUT_RING_H1(VIA_REG_DSTBASE_M1, pVia->curMarker >> 3);
    153         OUT_RING_H1(VIA_REG_PITCH_M1, 0);
    154         OUT_RING_H1(VIA_REG_DSTPOS_M1, 0);
    155         OUT_RING_H1(VIA_REG_DIMENSION_M1, 0);
    156         OUT_RING_H1(VIA_REG_MONOPATFGC_M1, pVia->curMarker);
    157         OUT_RING_H1(VIA_REG_GECMD_M1, (0xF0 << 24) | VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT);
    158 
    159         ADVANCE_RING;
    160     }
    161     return pVia->curMarker;
    162 }
    163 
    164 /*
    165  * Exa functions. It is assumed that EXA does not exceed the blitter limits.
    166  */
    167 Bool
    168 viaExaPrepareSolid_H6(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
    169 {
    170     ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
    171     VIAPtr pVia = VIAPTR(pScrn);
    172     ViaTwodContext *tdc = &pVia->td;
    173 
    174     if (exaGetPixmapPitch(pPixmap) & 7)
    175         return FALSE;
    176 
    177     if (!viaAccelSetMode(pPixmap->drawable.depth, tdc))
    178         return FALSE;
    179 
    180     if (!viaAccelPlaneMaskHelper_H6(tdc, planeMask))
    181         return FALSE;
    182 
    183     viaAccelTransparentHelper_H6(pVia, 0x0, 0x0, TRUE);
    184 
    185     tdc->cmd = VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT | VIAACCELPATTERNROP(alu);
    186 
    187     tdc->fgColor = fg;
    188 
    189     return TRUE;
    190 }
    191 
    192 void
    193 viaExaSolid_H6(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
    194 {
    195     ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
    196     CARD32 dstOffset = exaGetPixmapOffset(pPixmap);
    197     CARD32 dstPitch = exaGetPixmapPitch(pPixmap);
    198     int w = x2 - x1, h = y2 - y1;
    199     VIAPtr pVia = VIAPTR(pScrn);
    200     ViaTwodContext *tdc = &pVia->td;
    201 
    202     RING_VARS;
    203 
    204     BEGIN_RING(14);
    205     OUT_RING_H1(VIA_REG_GEMODE_M1, tdc->mode);
    206     OUT_RING_H1(VIA_REG_DSTBASE_M1, dstOffset >> 3);
    207     OUT_RING_H1(VIA_REG_PITCH_M1, (dstPitch >> 3) << 16);
    208     OUT_RING_H1(VIA_REG_DSTPOS_M1, (y1 << 16) | (x1 & 0xFFFF));
    209     OUT_RING_H1(VIA_REG_DIMENSION_M1, ((h - 1) << 16) | (w - 1));
    210     OUT_RING_H1(VIA_REG_MONOPATFGC_M1, tdc->fgColor);
    211     OUT_RING_H1(VIA_REG_GECMD_M1, tdc->cmd);
    212 
    213     ADVANCE_RING;
    214 }
    215 
    216 void
    217 viaExaDoneSolidCopy_H6(PixmapPtr pPixmap)
    218 {
    219 }
    220 
    221 Bool
    222 viaExaPrepareCopy_H6(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
    223                         int ydir, int alu, Pixel planeMask)
    224 {
    225     ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
    226     VIAPtr pVia = VIAPTR(pScrn);
    227     ViaTwodContext *tdc = &pVia->td;
    228 
    229     if (pSrcPixmap->drawable.bitsPerPixel != pDstPixmap->drawable.bitsPerPixel)
    230         return FALSE;
    231 
    232     if ((tdc->srcPitch = exaGetPixmapPitch(pSrcPixmap)) & 3)
    233         return FALSE;
    234 
    235     if (exaGetPixmapPitch(pDstPixmap) & 7)
    236         return FALSE;
    237 
    238     tdc->srcOffset = exaGetPixmapOffset(pSrcPixmap);
    239 
    240     tdc->cmd = VIA_GEC_BLT | VIAACCELCOPYROP(alu);
    241     if (xdir < 0)
    242         tdc->cmd |= VIA_GEC_DECX;
    243     if (ydir < 0)
    244         tdc->cmd |= VIA_GEC_DECY;
    245 
    246     if (!viaAccelSetMode(pDstPixmap->drawable.bitsPerPixel, tdc))
    247         return FALSE;
    248 
    249     if (!viaAccelPlaneMaskHelper_H6(tdc, planeMask))
    250         return FALSE;
    251     viaAccelTransparentHelper_H6(pVia, 0x0, 0x0, TRUE);
    252 
    253     return TRUE;
    254 }
    255 
    256 void
    257 viaExaCopy_H6(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
    258                 int width, int height)
    259 {
    260     ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
    261     CARD32 dstOffset = exaGetPixmapOffset(pDstPixmap), val;
    262     CARD32 dstPitch = exaGetPixmapPitch(pDstPixmap);
    263     VIAPtr pVia = VIAPTR(pScrn);
    264     ViaTwodContext *tdc = &pVia->td;
    265 
    266     if (!width || !height)
    267         return;
    268 
    269     RING_VARS;
    270 
    271     if (tdc->cmd & VIA_GEC_DECY) {
    272         srcY += height - 1;
    273         dstY += height - 1;
    274     }
    275 
    276     if (tdc->cmd & VIA_GEC_DECX) {
    277         srcX += width - 1;
    278         dstX += width - 1;
    279     }
    280     val = (dstPitch >> 3) << 16 | (tdc->srcPitch >> 3);
    281 
    282     BEGIN_RING(16);
    283     OUT_RING_H1(VIA_REG_GEMODE_M1, tdc->mode);
    284     OUT_RING_H1(VIA_REG_SRCBASE_M1, tdc->srcOffset >> 3);
    285     OUT_RING_H1(VIA_REG_DSTBASE_M1, dstOffset >> 3);
    286     OUT_RING_H1(VIA_REG_PITCH_M1, val);
    287 
    288     OUT_RING_H1(VIA_REG_SRCPOS_M1, (srcY << 16) | (srcX & 0xFFFF));
    289     OUT_RING_H1(VIA_REG_DSTPOS_M1, (dstY << 16) | (dstX & 0xFFFF));
    290     OUT_RING_H1(VIA_REG_DIMENSION_M1, ((height - 1) << 16) | (width - 1));
    291     OUT_RING_H1(VIA_REG_GECMD_M1, tdc->cmd);
    292 
    293     ADVANCE_RING;
    294 }
    295 
    296 Bool
    297 viaExaCheckComposite_H6(int op, PicturePtr pSrcPicture,
    298                         PicturePtr pMaskPicture, PicturePtr pDstPicture)
    299 {
    300     ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPicture->pDrawable->pScreen);
    301     VIAPtr pVia = VIAPTR(pScrn);
    302     Via3DState *v3d = &pVia->v3d;
    303 
    304     if (!pSrcPicture->pDrawable) {
    305         return FALSE;
    306     }
    307     /* Reject small composites early. They are done much faster in software. */
    308     if (!pSrcPicture->repeat &&
    309         pSrcPicture->pDrawable->width *
    310         pSrcPicture->pDrawable->height < VIA_MIN_COMPOSITE) {
    311 
    312 #ifdef VIA_DEBUG_COMPOSITE
    313         viaExaPrintCompositeInfo("Source picture too small", op,  pSrcPicture, pMaskPicture, pDstPicture);
    314 #endif
    315         return FALSE;
    316     }
    317 
    318     if (pMaskPicture && pMaskPicture->pDrawable &&
    319         !pMaskPicture->repeat &&
    320         pMaskPicture->pDrawable->width *
    321         pMaskPicture->pDrawable->height < VIA_MIN_COMPOSITE) {
    322 #ifdef VIA_DEBUG_COMPOSITE
    323         viaExaPrintCompositeInfo("Mask picture too small", op,  pSrcPicture, pMaskPicture, pDstPicture);
    324 #endif
    325         return FALSE;
    326     }
    327 
    328     if (pMaskPicture && pMaskPicture->repeat && pMaskPicture->repeatType != RepeatNormal) {
    329 #ifdef VIA_DEBUG_COMPOSITE
    330         viaExaPrintCompositeInfo("Repeat is different than normal", op,  pSrcPicture, pMaskPicture, pDstPicture);
    331 #endif
    332         return FALSE;
    333     }
    334     if (pMaskPicture && pMaskPicture->componentAlpha) {
    335 #ifdef VIA_DEBUG_COMPOSITE
    336         viaExaPrintCompositeInfo("Component Alpha operation", op,  pSrcPicture, pMaskPicture, pDstPicture);
    337 #endif
    338         return FALSE;
    339     }
    340 
    341     if (!v3d->opSupported(op)) {
    342 #ifdef VIA_DEBUG_COMPOSITE
    343         viaExaPrintCompositeInfo("Operator not supported", op, pSrcPicture, pMaskPicture, pDstPicture);
    344 #endif
    345         return FALSE;
    346     }
    347 
    348     /*
    349      * FIXME: A8 destination formats are currently not supported and do not
    350      * seem supported by the hardware, although there are some leftover
    351      * register settings apparent in the via_3d_reg.h file. We need to fix this
    352      * (if important), by using component ARGB8888 operations with bitmask.
    353      */
    354 
    355     if (!v3d->dstSupported(pDstPicture->format)) {
    356 #ifdef VIA_DEBUG_COMPOSITE
    357         viaExaPrintCompositeInfo("Destination format not supported", op, pSrcPicture, pMaskPicture, pDstPicture);
    358 #endif
    359         return FALSE;
    360     }
    361 
    362     if (v3d->texSupported(pSrcPicture->format)) {
    363         if (pMaskPicture && (PICT_FORMAT_A(pMaskPicture->format) == 0 ||
    364                              !v3d->texSupported(pMaskPicture->format))) {
    365 #ifdef VIA_DEBUG_COMPOSITE
    366             viaExaPrintCompositeInfo("Mask format not supported", op, pSrcPicture, pMaskPicture, pDstPicture);
    367 #endif
    368             return FALSE;
    369         }
    370         return TRUE;
    371     }
    372 #ifdef VIA_DEBUG_COMPOSITE
    373     viaExaPrintCompositeInfo("Src format not supported",op, pSrcPicture, pMaskPicture, pDstPicture);
    374 #endif
    375     return FALSE;
    376 }
    377 
    378 static Bool
    379 viaIsAGP(VIAPtr pVia, PixmapPtr pPix, unsigned long *offset)
    380 {
    381 #ifdef HAVE_DRI
    382     unsigned long offs;
    383 
    384     if (pVia->directRenderingType && !pVia->IsPCI) {
    385         offs = ((unsigned long)pPix->devPrivate.ptr
    386                 - (unsigned long)pVia->agpMappedAddr);
    387 
    388         if ((offs - pVia->scratchOffset) < pVia->agpSize) {
    389             *offset = offs + pVia->agpAddr;
    390             return TRUE;
    391         }
    392     }
    393 #endif
    394     return FALSE;
    395 }
    396 
    397 static Bool
    398 viaExaIsOffscreen(PixmapPtr pPix)
    399 {
    400     ScrnInfoPtr pScrn = xf86ScreenToScrn(pPix->drawable.pScreen);
    401     VIAPtr pVia = VIAPTR(pScrn);
    402 
    403     return ((unsigned long)pPix->devPrivate.ptr -
    404             (unsigned long) drm_bo_map(pScrn, pVia->drmmode.front_bo)) < pVia->drmmode.front_bo->size;
    405 }
    406 
    407 Bool
    408 viaExaPrepareComposite_H6(int op, PicturePtr pSrcPicture,
    409                             PicturePtr pMaskPicture, PicturePtr pDstPicture,
    410                             PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
    411 {
    412     CARD32 height, width;
    413     ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
    414     VIAPtr pVia = VIAPTR(pScrn);
    415     Via3DState *v3d = &pVia->v3d;
    416     int curTex = 0;
    417     ViaTexBlendingModes srcMode;
    418     Bool isAGP;
    419     unsigned long offset;
    420 
    421     /* Workaround: EXA crash with new libcairo2 on a VIA VX800 (#298) */
    422     /* TODO Add real source only pictures */
    423     if (!pSrc) {
    424 	    ErrorF("pSrc is NULL\n");
    425 	    return FALSE;
    426 	}
    427 
    428     v3d->setDestination(v3d, exaGetPixmapOffset(pDst),
    429                         exaGetPixmapPitch(pDst), pDstPicture->format);
    430     v3d->setCompositeOperator(v3d, op);
    431     v3d->setDrawing(v3d, 0x0c, 0xFFFFFFFF, 0x000000FF, 0xFF);
    432 
    433     viaOrder(pSrc->drawable.width, &width);
    434     viaOrder(pSrc->drawable.height, &height);
    435 
    436     /*
    437      * For one-pixel repeat mask pictures we avoid using multitexturing by
    438      * modifying the src's texture blending equation and feed the pixel
    439      * value as a constant alpha for the src's texture. Multitexturing on the
    440      * Unichromes seems somewhat slow, so this speeds up translucent windows.
    441      */
    442 
    443     srcMode = via_src;
    444     pVia->maskP = NULL;
    445     if (pMaskPicture &&
    446         (pMaskPicture->pDrawable->height == 1) &&
    447         (pMaskPicture->pDrawable->width == 1) &&
    448         pMaskPicture->repeat && viaExpandablePixel(pMaskPicture->format)) {
    449         pVia->maskP = pMask->devPrivate.ptr;
    450         pVia->maskFormat = pMaskPicture->format;
    451         pVia->componentAlpha = pMaskPicture->componentAlpha;
    452         srcMode = ((pMaskPicture->componentAlpha)
    453                    ? via_src_onepix_comp_mask : via_src_onepix_mask);
    454     }
    455 
    456     /*
    457      * One-Pixel repeat src pictures go as solid color instead of textures.
    458      * Speeds up window shadows.
    459      */
    460 
    461     pVia->srcP = NULL;
    462     if (pSrcPicture && pSrcPicture->repeat
    463         && (pSrcPicture->pDrawable->height == 1)
    464         && (pSrcPicture->pDrawable->width == 1)
    465         && viaExpandablePixel(pSrcPicture->format)) {
    466         pVia->srcP = pSrc->devPrivate.ptr;
    467         pVia->srcFormat = pSrcPicture->format;
    468     }
    469 
    470     /* Exa should be smart enough to eliminate this IN operation. */
    471     if (pVia->srcP && pVia->maskP) {
    472         ErrorF("Bad one-pixel IN composite operation. "
    473                "EXA needs to be smarter.\n");
    474         return FALSE;
    475     }
    476 
    477     if (!pVia->srcP) {
    478         offset = exaGetPixmapOffset(pSrc);
    479         isAGP = viaIsAGP(pVia, pSrc, &offset);
    480         if (!isAGP && !viaExaIsOffscreen(pSrc))
    481             return FALSE;
    482         if (!v3d->setTexture(v3d, curTex, offset,
    483                              exaGetPixmapPitch(pSrc), pVia->nPOT[curTex],
    484                              1 << width, 1 << height, pSrcPicture->format,
    485                              via_repeat, via_repeat, srcMode, isAGP)) {
    486             return FALSE;
    487         }
    488         curTex++;
    489     }
    490 
    491     if (pMaskPicture && !pVia->maskP) {
    492         offset = exaGetPixmapOffset(pMask);
    493         isAGP = viaIsAGP(pVia, pMask, &offset);
    494         if (!isAGP && !viaExaIsOffscreen(pMask))
    495             return FALSE;
    496         viaOrder(pMask->drawable.width, &width);
    497         viaOrder(pMask->drawable.height, &height);
    498         if (!v3d->setTexture(v3d, curTex, offset,
    499                              exaGetPixmapPitch(pMask), pVia->nPOT[curTex],
    500                              1 << width, 1 << height, pMaskPicture->format,
    501                              via_repeat, via_repeat,
    502                              ((pMaskPicture->componentAlpha)
    503                               ? via_comp_mask : via_mask), isAGP)) {
    504             return FALSE;
    505         }
    506         curTex++;
    507     }
    508 
    509     v3d->setFlags(v3d, curTex, FALSE, TRUE, TRUE);
    510     v3d->emitState(v3d, &pVia->cb, viaCheckUpload(pScrn, v3d));
    511     v3d->emitClipRect(v3d, &pVia->cb, 0, 0, pDst->drawable.width,
    512                       pDst->drawable.height);
    513 
    514     return TRUE;
    515 }
    516 
    517 void
    518 viaExaComposite_H6(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
    519                     int dstX, int dstY, int width, int height)
    520 {
    521     ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
    522     VIAPtr pVia = VIAPTR(pScrn);
    523     Via3DState *v3d = &pVia->v3d;
    524     CARD32 col;
    525 
    526     if (pVia->maskP) {
    527         viaPixelARGB8888(pVia->maskFormat, pVia->maskP, &col);
    528         v3d->setTexBlendCol(v3d, 0, pVia->componentAlpha, col);
    529     }
    530     if (pVia->srcP) {
    531         viaPixelARGB8888(pVia->srcFormat, pVia->srcP, &col);
    532         v3d->setDrawing(v3d, 0x0c, 0xFFFFFFFF, col & 0x00FFFFFF, col >> 24);
    533         srcX = maskX;
    534         srcY = maskY;
    535     }
    536 
    537     if (pVia->maskP || pVia->srcP)
    538         v3d->emitState(v3d, &pVia->cb, viaCheckUpload(pScrn, v3d));
    539 
    540     v3d->emitQuad(v3d, &pVia->cb, dstX, dstY, srcX, srcY, maskX, maskY,
    541                   width, height);
    542 }
    543