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_H2(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,
     60                     ((tdc->clipY1 - refY) << 16) | tdc->clipX1);
     61         OUT_RING_H1(VIA_REG_CLIPBR,
     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_H2(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_H2(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, tdc->keyControl);
    123     if (keyControl) {
    124         OUT_RING_H1(VIA_REG_SRCCOLORKEY, 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_H2(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         OUT_RING_H1(VIA_REG_KEYCONTROL, 0x00);
    150         OUT_RING_H1(VIA_REG_GEMODE, VIA_GEM_32bpp);
    151         OUT_RING_H1(VIA_REG_DSTBASE, pVia->markerOffset >> 3);
    152         OUT_RING_H1(VIA_REG_PITCH, VIA_PITCH_ENABLE);
    153         OUT_RING_H1(VIA_REG_DSTPOS, 0);
    154         OUT_RING_H1(VIA_REG_DIMENSION, 0);
    155         OUT_RING_H1(VIA_REG_FGCOLOR, pVia->curMarker);
    156         OUT_RING_H1(VIA_REG_GECMD, (0xF0 << 24) | VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT);
    157 
    158         ADVANCE_RING;
    159     }
    160     return pVia->curMarker;
    161 }
    162 
    163 /*
    164  * Exa functions. It is assumed that EXA does not exceed the blitter limits.
    165  */
    166 Bool
    167 viaExaPrepareSolid_H2(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
    168 {
    169     ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
    170     VIAPtr pVia = VIAPTR(pScrn);
    171     ViaTwodContext *tdc = &pVia->td;
    172 
    173     if (exaGetPixmapPitch(pPixmap) & 7)
    174         return FALSE;
    175 
    176     if (!viaAccelSetMode(pPixmap->drawable.depth, tdc))
    177         return FALSE;
    178 
    179     if (!viaAccelPlaneMaskHelper_H2(tdc, planeMask))
    180         return FALSE;
    181 
    182     viaAccelTransparentHelper_H2(pVia, 0x0, 0x0, TRUE);
    183 
    184     tdc->cmd = VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT | VIAACCELPATTERNROP(alu);
    185 
    186     tdc->fgColor = fg;
    187 
    188     return TRUE;
    189 }
    190 
    191 void
    192 viaExaSolid_H2(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
    193 {
    194     ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
    195     CARD32 dstOffset = exaGetPixmapOffset(pPixmap);
    196     CARD32 dstPitch = exaGetPixmapPitch(pPixmap);
    197     int w = x2 - x1, h = y2 - y1;
    198     VIAPtr pVia = VIAPTR(pScrn);
    199     ViaTwodContext *tdc = &pVia->td;
    200 
    201     RING_VARS;
    202 
    203     BEGIN_RING(14);
    204     OUT_RING_H1(VIA_REG_GEMODE, tdc->mode);
    205     OUT_RING_H1(VIA_REG_DSTBASE, dstOffset >> 3);
    206     OUT_RING_H1(VIA_REG_PITCH, VIA_PITCH_ENABLE | (dstPitch >> 3) << 16);
    207     OUT_RING_H1(VIA_REG_DSTPOS, (y1 << 16) | (x1 & 0xFFFF));
    208     OUT_RING_H1(VIA_REG_DIMENSION, ((h - 1) << 16) | (w - 1));
    209     OUT_RING_H1(VIA_REG_FGCOLOR, tdc->fgColor);
    210     OUT_RING_H1(VIA_REG_GECMD, tdc->cmd);
    211 
    212     ADVANCE_RING;
    213 }
    214 
    215 void
    216 viaExaDoneSolidCopy_H2(PixmapPtr pPixmap)
    217 {
    218 }
    219 
    220 Bool
    221 viaExaPrepareCopy_H2(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
    222                         int ydir, int alu, Pixel planeMask)
    223 {
    224     ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
    225     VIAPtr pVia = VIAPTR(pScrn);
    226     ViaTwodContext *tdc = &pVia->td;
    227 
    228     if (pSrcPixmap->drawable.bitsPerPixel != pDstPixmap->drawable.bitsPerPixel)
    229         return FALSE;
    230 
    231     if ((tdc->srcPitch = exaGetPixmapPitch(pSrcPixmap)) & 3)
    232         return FALSE;
    233 
    234     if (exaGetPixmapPitch(pDstPixmap) & 7)
    235         return FALSE;
    236 
    237     tdc->srcOffset = exaGetPixmapOffset(pSrcPixmap);
    238 
    239     tdc->cmd = VIA_GEC_BLT | VIAACCELCOPYROP(alu);
    240     if (xdir < 0)
    241         tdc->cmd |= VIA_GEC_DECX;
    242     if (ydir < 0)
    243         tdc->cmd |= VIA_GEC_DECY;
    244 
    245     if (!viaAccelSetMode(pDstPixmap->drawable.bitsPerPixel, tdc))
    246         return FALSE;
    247 
    248     if (!viaAccelPlaneMaskHelper_H2(tdc, planeMask))
    249         return FALSE;
    250     viaAccelTransparentHelper_H2(pVia, 0x0, 0x0, TRUE);
    251 
    252     return TRUE;
    253 }
    254 
    255 void
    256 viaExaCopy_H2(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
    257                 int width, int height)
    258 {
    259     ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
    260     CARD32 dstOffset = exaGetPixmapOffset(pDstPixmap), val;
    261     CARD32 dstPitch = exaGetPixmapPitch(pDstPixmap);
    262     VIAPtr pVia = VIAPTR(pScrn);
    263     ViaTwodContext *tdc = &pVia->td;
    264 
    265     if (!width || !height)
    266         return;
    267 
    268     if (tdc->cmd & VIA_GEC_DECY) {
    269         srcY += height - 1;
    270         dstY += height - 1;
    271     }
    272 
    273     if (tdc->cmd & VIA_GEC_DECX) {
    274         srcX += width - 1;
    275         dstX += width - 1;
    276     }
    277     val = VIA_PITCH_ENABLE | (dstPitch >> 3) << 16 | (tdc->srcPitch >> 3);
    278 
    279     RING_VARS;
    280 
    281     BEGIN_RING(16);
    282     OUT_RING_H1(VIA_REG_GEMODE, tdc->mode);
    283     OUT_RING_H1(VIA_REG_SRCBASE, tdc->srcOffset >> 3);
    284     OUT_RING_H1(VIA_REG_DSTBASE, dstOffset >> 3);
    285     OUT_RING_H1(VIA_REG_PITCH, val);
    286     OUT_RING_H1(VIA_REG_SRCPOS, (srcY << 16) | (srcX & 0xFFFF));
    287     OUT_RING_H1(VIA_REG_DSTPOS, (dstY << 16) | (dstX & 0xFFFF));
    288     OUT_RING_H1(VIA_REG_DIMENSION, ((height - 1) << 16) | (width - 1));
    289     OUT_RING_H1(VIA_REG_GECMD, tdc->cmd);
    290 
    291     ADVANCE_RING;
    292 }
    293 
    294 Bool
    295 viaExaCheckComposite_H2(int op, PicturePtr pSrcPicture,
    296                         PicturePtr pMaskPicture, PicturePtr pDstPicture)
    297 {
    298     ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPicture->pDrawable->pScreen);
    299     VIAPtr pVia = VIAPTR(pScrn);
    300     Via3DState *v3d = &pVia->v3d;
    301 
    302     if (!pSrcPicture->pDrawable)
    303         return FALSE;
    304 
    305     /* Reject small composites early. They are done much faster in software. */
    306     if (!pSrcPicture->repeat &&
    307         pSrcPicture->pDrawable->width *
    308         pSrcPicture->pDrawable->height < VIA_MIN_COMPOSITE)
    309         return FALSE;
    310 
    311     if (pMaskPicture && pMaskPicture->pDrawable &&
    312         !pMaskPicture->repeat &&
    313         pMaskPicture->pDrawable->width *
    314         pMaskPicture->pDrawable->height < VIA_MIN_COMPOSITE)
    315         return FALSE;
    316 
    317     if (pMaskPicture && pMaskPicture->repeat &&
    318         pMaskPicture->repeatType != RepeatNormal)
    319         return FALSE;
    320 
    321     if (pMaskPicture && pMaskPicture->componentAlpha) {
    322 #ifdef VIA_DEBUG_COMPOSITE
    323         viaExaPrintCompositeInfo("Component Alpha operation", op,  pSrcPicture, pMaskPicture, pDstPicture);
    324 #endif
    325         return FALSE;
    326     }
    327 
    328     if (!v3d->opSupported(op)) {
    329 #ifdef VIA_DEBUG_COMPOSITE
    330         viaExaPrintCompositeInfo("Operator not supported", op, pSrcPicture, pMaskPicture, pDstPicture);
    331 #endif
    332         return FALSE;
    333     }
    334 
    335     /*
    336      * FIXME: A8 destination formats are currently not supported and do not
    337      * seem supported by the hardware, although there are some leftover
    338      * register settings apparent in the via_3d_reg.h file. We need to fix this
    339      * (if important), by using component ARGB8888 operations with bitmask.
    340      */
    341 
    342     if (!v3d->dstSupported(pDstPicture->format)) {
    343 #ifdef VIA_DEBUG_COMPOSITE
    344         viaExaPrintCompositeInfo(" Destination format not supported", op, pSrcPicture, pMaskPicture, pDstPicture);
    345 #endif
    346         return FALSE;
    347     }
    348 
    349     if (v3d->texSupported(pSrcPicture->format)) {
    350         if (pMaskPicture && (PICT_FORMAT_A(pMaskPicture->format) == 0 ||
    351                              !v3d->texSupported(pMaskPicture->format))) {
    352 #ifdef VIA_DEBUG_COMPOSITE
    353             viaExaPrintCompositeInfo("Mask format not supported", op, pSrcPicture, pMaskPicture, pDstPicture);
    354 #endif
    355             return FALSE;
    356         }
    357         return TRUE;
    358     }
    359 #ifdef VIA_DEBUG_COMPOSITE
    360     viaExaPrintCompositeInfo("Src format not supported", op, pSrcPicture, pMaskPicture, pDstPicture);
    361 #endif
    362     return FALSE;
    363 }
    364 
    365 static Bool
    366 viaIsAGP(VIAPtr pVia, PixmapPtr pPix, unsigned long *offset)
    367 {
    368 #ifdef HAVE_DRI
    369     unsigned long offs;
    370 
    371     if (pVia->directRenderingType && !pVia->IsPCI) {
    372         offs = ((unsigned long)pPix->devPrivate.ptr
    373                 - (unsigned long)pVia->agpMappedAddr);
    374 
    375         if ((offs - pVia->scratchOffset) < pVia->agpSize) {
    376             *offset = offs + pVia->agpAddr;
    377             return TRUE;
    378         }
    379     }
    380 #endif
    381     return FALSE;
    382 }
    383 
    384 static Bool
    385 viaExaIsOffscreen(PixmapPtr pPix)
    386 {
    387     ScrnInfoPtr pScrn = xf86ScreenToScrn(pPix->drawable.pScreen);
    388     VIAPtr pVia = VIAPTR(pScrn);
    389 
    390     return ((unsigned long)pPix->devPrivate.ptr -
    391             (unsigned long) drm_bo_map(pScrn, pVia->drmmode.front_bo)) < pVia->drmmode.front_bo->size;
    392 }
    393 
    394 Bool
    395 viaExaPrepareComposite_H2(int op, PicturePtr pSrcPicture,
    396                             PicturePtr pMaskPicture, PicturePtr pDstPicture,
    397                             PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
    398 {
    399     CARD32 height, width;
    400     ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
    401     VIAPtr pVia = VIAPTR(pScrn);
    402     Via3DState *v3d = &pVia->v3d;
    403     int curTex = 0;
    404     ViaTexBlendingModes srcMode;
    405     Bool isAGP;
    406     unsigned long offset;
    407 
    408     /* Workaround: EXA crash with new libcairo2 on a VIA VX800 (#298) */
    409     /* TODO Add real source only pictures */
    410     if (!pSrc) {
    411 	    ErrorF("pSrc is NULL\n");
    412 	    return FALSE;
    413 	}
    414 
    415     v3d->setDestination(v3d, exaGetPixmapOffset(pDst),
    416                         exaGetPixmapPitch(pDst), pDstPicture->format);
    417     v3d->setCompositeOperator(v3d, op);
    418     v3d->setDrawing(v3d, 0x0c, 0xFFFFFFFF, 0x000000FF, 0xFF);
    419 
    420     viaOrder(pSrc->drawable.width, &width);
    421     viaOrder(pSrc->drawable.height, &height);
    422 
    423     /*
    424      * For one-pixel repeat mask pictures we avoid using multitexturing by
    425      * modifying the src's texture blending equation and feed the pixel
    426      * value as a constant alpha for the src's texture. Multitexturing on the
    427      * Unichromes seems somewhat slow, so this speeds up translucent windows.
    428      */
    429 
    430     srcMode = via_src;
    431     pVia->maskP = NULL;
    432     if (pMaskPicture &&
    433         (pMaskPicture->pDrawable->height == 1) &&
    434         (pMaskPicture->pDrawable->width == 1) &&
    435         pMaskPicture->repeat && viaExpandablePixel(pMaskPicture->format)) {
    436         pVia->maskP = pMask->devPrivate.ptr;
    437         pVia->maskFormat = pMaskPicture->format;
    438         pVia->componentAlpha = pMaskPicture->componentAlpha;
    439         srcMode = ((pMaskPicture->componentAlpha)
    440                    ? via_src_onepix_comp_mask : via_src_onepix_mask);
    441     }
    442 
    443     /*
    444      * One-Pixel repeat src pictures go as solid color instead of textures.
    445      * Speeds up window shadows.
    446      */
    447 
    448     pVia->srcP = NULL;
    449     if (pSrcPicture && pSrcPicture->repeat
    450         && (pSrcPicture->pDrawable->height == 1)
    451         && (pSrcPicture->pDrawable->width == 1)
    452         && viaExpandablePixel(pSrcPicture->format)) {
    453         pVia->srcP = pSrc->devPrivate.ptr;
    454         pVia->srcFormat = pSrcPicture->format;
    455     }
    456 
    457     /* Exa should be smart enough to eliminate this IN operation. */
    458     if (pVia->srcP && pVia->maskP) {
    459         ErrorF("Bad one-pixel IN composite operation. "
    460                "EXA needs to be smarter.\n");
    461         return FALSE;
    462     }
    463 
    464     if (!pVia->srcP) {
    465         offset = exaGetPixmapOffset(pSrc);
    466         isAGP = viaIsAGP(pVia, pSrc, &offset);
    467         if (!isAGP && !viaExaIsOffscreen(pSrc))
    468             return FALSE;
    469         if (!v3d->setTexture(v3d, curTex, offset,
    470                              exaGetPixmapPitch(pSrc), pVia->nPOT[curTex],
    471                              1 << width, 1 << height, pSrcPicture->format,
    472                              via_repeat, via_repeat, srcMode, isAGP)) {
    473             return FALSE;
    474         }
    475         curTex++;
    476     }
    477 
    478     if (pMaskPicture && !pVia->maskP) {
    479         offset = exaGetPixmapOffset(pMask);
    480         isAGP = viaIsAGP(pVia, pMask, &offset);
    481         if (!isAGP && !viaExaIsOffscreen(pMask))
    482             return FALSE;
    483         viaOrder(pMask->drawable.width, &width);
    484         viaOrder(pMask->drawable.height, &height);
    485         if (!v3d->setTexture(v3d, curTex, offset,
    486                              exaGetPixmapPitch(pMask), pVia->nPOT[curTex],
    487                              1 << width, 1 << height, pMaskPicture->format,
    488                              via_repeat, via_repeat,
    489                              ((pMaskPicture->componentAlpha)
    490                               ? via_comp_mask : via_mask), isAGP)) {
    491             return FALSE;
    492         }
    493         curTex++;
    494     }
    495 
    496     v3d->setFlags(v3d, curTex, FALSE, TRUE, TRUE);
    497     v3d->emitState(v3d, &pVia->cb, viaCheckUpload(pScrn, v3d));
    498     v3d->emitClipRect(v3d, &pVia->cb, 0, 0, pDst->drawable.width,
    499                       pDst->drawable.height);
    500 
    501     return TRUE;
    502 }
    503 
    504 void
    505 viaExaComposite_H2(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
    506                     int dstX, int dstY, int width, int height)
    507 {
    508     ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
    509     VIAPtr pVia = VIAPTR(pScrn);
    510     Via3DState *v3d = &pVia->v3d;
    511     CARD32 col;
    512 
    513     if (pVia->maskP) {
    514         viaPixelARGB8888(pVia->maskFormat, pVia->maskP, &col);
    515         v3d->setTexBlendCol(v3d, 0, pVia->componentAlpha, col);
    516     }
    517     if (pVia->srcP) {
    518         viaPixelARGB8888(pVia->srcFormat, pVia->srcP, &col);
    519         v3d->setDrawing(v3d, 0x0c, 0xFFFFFFFF, col & 0x00FFFFFF, col >> 24);
    520         srcX = maskX;
    521         srcY = maskY;
    522     }
    523 
    524     if (pVia->maskP || pVia->srcP)
    525         v3d->emitState(v3d, &pVia->cb, viaCheckUpload(pScrn, v3d));
    526 
    527     v3d->emitQuad(v3d, &pVia->cb, dstX, dstY, srcX, srcY, maskX, maskY,
    528                   width, height);
    529 }
    530 
    531 void
    532 viaAccelTextureBlit(ScrnInfoPtr pScrn, unsigned long srcOffset,
    533                     unsigned srcPitch, unsigned w, unsigned h, unsigned srcX,
    534                     unsigned srcY, unsigned srcFormat, unsigned long dstOffset,
    535                     unsigned dstPitch, unsigned dstX, unsigned dstY,
    536                     unsigned dstFormat, int rotate)
    537 {
    538     VIAPtr pVia = VIAPTR(pScrn);
    539     CARD32 wOrder, hOrder;
    540     Via3DState *v3d = &pVia->v3d;
    541 
    542     viaOrder(w, &wOrder);
    543     viaOrder(h, &hOrder);
    544 
    545     v3d->setDestination(v3d, dstOffset, dstPitch, dstFormat);
    546     v3d->setDrawing(v3d, 0x0c, 0xFFFFFFFF, 0x000000FF, 0x00);
    547     v3d->setFlags(v3d, 1, TRUE, TRUE, FALSE);
    548     v3d->setTexture(v3d, 0, srcOffset, srcPitch, TRUE,
    549                     1 << wOrder, 1 << hOrder, srcFormat,
    550                     via_single, via_single, via_src, FALSE);
    551     v3d->emitState(v3d, &pVia->cb, viaCheckUpload(pScrn, v3d));
    552     v3d->emitClipRect(v3d, &pVia->cb, dstX, dstY, w, h);
    553     v3d->emitQuad(v3d, &pVia->cb, dstX, dstY, srcX, srcY, 0, 0, w, h);
    554 }
    555