via_exa_h2.c revision 90b17f1b
190b17f1bSmrg/*
290b17f1bSmrg * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
390b17f1bSmrg * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
490b17f1bSmrg * Copyright 2006 Thomas Hellström. All Rights Reserved.
590b17f1bSmrg *
690b17f1bSmrg * Permission is hereby granted, free of charge, to any person obtaining a
790b17f1bSmrg * copy of this software and associated documentation files (the "Software"),
890b17f1bSmrg * to deal in the Software without restriction, including without limitation
990b17f1bSmrg * the rights to use, copy, modify, merge, publish, distribute, sub license,
1090b17f1bSmrg * and/or sell copies of the Software, and to permit persons to whom the
1190b17f1bSmrg * Software is furnished to do so, subject to the following conditions:
1290b17f1bSmrg *
1390b17f1bSmrg * The above copyright notice and this permission notice (including the
1490b17f1bSmrg * next paragraph) shall be included in all copies or substantial portions
1590b17f1bSmrg * of the Software.
1690b17f1bSmrg *
1790b17f1bSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1890b17f1bSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1990b17f1bSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
2090b17f1bSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2190b17f1bSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2290b17f1bSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2390b17f1bSmrg * DEALINGS IN THE SOFTWARE.
2490b17f1bSmrg */
2590b17f1bSmrg
2690b17f1bSmrg/*
2790b17f1bSmrg * 2D acceleration functions for the VIA/S3G UniChrome IGPs.
2890b17f1bSmrg *
2990b17f1bSmrg * Mostly rewritten, and modified for EXA support, by Thomas Hellström.
3090b17f1bSmrg */
3190b17f1bSmrg
3290b17f1bSmrg#ifdef HAVE_CONFIG_H
3390b17f1bSmrg#include "config.h"
3490b17f1bSmrg#endif
3590b17f1bSmrg
3690b17f1bSmrg#include <X11/Xarch.h>
3790b17f1bSmrg#include "miline.h"
3890b17f1bSmrg
3990b17f1bSmrg#include "via_driver.h"
4090b17f1bSmrg#include "via_regs.h"
4190b17f1bSmrg#include "via_dmabuffer.h"
4290b17f1bSmrg#include "via_rop.h"
4390b17f1bSmrg
4490b17f1bSmrg/*
4590b17f1bSmrg * Emit clipping borders to the command buffer and update the 2D context
4690b17f1bSmrg * current command with clipping info.
4790b17f1bSmrg */
4890b17f1bSmrgstatic int
4990b17f1bSmrgviaAccelClippingHelper_H2(VIAPtr pVia, int refY)
5090b17f1bSmrg{
5190b17f1bSmrg    ViaTwodContext *tdc = &pVia->td;
5290b17f1bSmrg
5390b17f1bSmrg    RING_VARS;
5490b17f1bSmrg
5590b17f1bSmrg    if (tdc->clipping) {
5690b17f1bSmrg        refY = (refY < tdc->clipY1) ? refY : tdc->clipY1;
5790b17f1bSmrg        tdc->cmd |= VIA_GEC_CLIP_ENABLE;
5890b17f1bSmrg        BEGIN_RING(4);
5990b17f1bSmrg        OUT_RING_H1(VIA_REG_CLIPTL,
6090b17f1bSmrg                    ((tdc->clipY1 - refY) << 16) | tdc->clipX1);
6190b17f1bSmrg        OUT_RING_H1(VIA_REG_CLIPBR,
6290b17f1bSmrg		    ((tdc->clipY2 - refY) << 16) | tdc->clipX2);
6390b17f1bSmrg    } else {
6490b17f1bSmrg        tdc->cmd &= ~VIA_GEC_CLIP_ENABLE;
6590b17f1bSmrg    }
6690b17f1bSmrg    return refY;
6790b17f1bSmrg}
6890b17f1bSmrg
6990b17f1bSmrg/*
7090b17f1bSmrg * Check if we can use a planeMask and update the 2D context accordingly.
7190b17f1bSmrg */
7290b17f1bSmrgstatic Bool
7390b17f1bSmrgviaAccelPlaneMaskHelper_H2(ViaTwodContext * tdc, CARD32 planeMask)
7490b17f1bSmrg{
7590b17f1bSmrg    CARD32 modeMask = (1 << ((1 << tdc->bytesPPShift) << 3)) - 1;
7690b17f1bSmrg    CARD32 curMask = 0x00000000;
7790b17f1bSmrg    CARD32 curByteMask;
7890b17f1bSmrg    int i;
7990b17f1bSmrg
8090b17f1bSmrg    if ((planeMask & modeMask) != modeMask) {
8190b17f1bSmrg
8290b17f1bSmrg        /* Masking doesn't work in 8bpp. */
8390b17f1bSmrg        if (modeMask == 0xFF) {
8490b17f1bSmrg            tdc->keyControl &= 0x0FFFFFFF;
8590b17f1bSmrg            return FALSE;
8690b17f1bSmrg        }
8790b17f1bSmrg
8890b17f1bSmrg        /* Translate the bit planemask to a byte planemask. */
8990b17f1bSmrg        for (i = 0; i < (1 << tdc->bytesPPShift); ++i) {
9090b17f1bSmrg            curByteMask = (0xFF << (i << 3));
9190b17f1bSmrg
9290b17f1bSmrg            if ((planeMask & curByteMask) == 0) {
9390b17f1bSmrg                curMask |= (1 << i);
9490b17f1bSmrg            } else if ((planeMask & curByteMask) != curByteMask) {
9590b17f1bSmrg                tdc->keyControl &= 0x0FFFFFFF;
9690b17f1bSmrg                return FALSE;
9790b17f1bSmrg            }
9890b17f1bSmrg        }
9990b17f1bSmrg        ErrorF("DEBUG: planeMask 0x%08x, curMask 0%02x\n",
10090b17f1bSmrg               (unsigned)planeMask, (unsigned)curMask);
10190b17f1bSmrg
10290b17f1bSmrg        tdc->keyControl = (tdc->keyControl & 0x0FFFFFFF) | (curMask << 28);
10390b17f1bSmrg    }
10490b17f1bSmrg
10590b17f1bSmrg    return TRUE;
10690b17f1bSmrg}
10790b17f1bSmrg
10890b17f1bSmrg/*
10990b17f1bSmrg * Emit transparency state and color to the command buffer.
11090b17f1bSmrg */
11190b17f1bSmrgstatic void
11290b17f1bSmrgviaAccelTransparentHelper_H2(VIAPtr pVia, CARD32 keyControl,
11390b17f1bSmrg                          CARD32 transColor, Bool usePlaneMask)
11490b17f1bSmrg{
11590b17f1bSmrg    ViaTwodContext *tdc = &pVia->td;
11690b17f1bSmrg
11790b17f1bSmrg    RING_VARS;
11890b17f1bSmrg
11990b17f1bSmrg    tdc->keyControl &= ((usePlaneMask) ? 0xF0000000 : 0x00000000);
12090b17f1bSmrg    tdc->keyControl |= (keyControl & 0x0FFFFFFF);
12190b17f1bSmrg    BEGIN_RING(4);
12290b17f1bSmrg    OUT_RING_H1(VIA_REG_KEYCONTROL, tdc->keyControl);
12390b17f1bSmrg    if (keyControl) {
12490b17f1bSmrg        OUT_RING_H1(VIA_REG_SRCCOLORKEY, transColor);
12590b17f1bSmrg    }
12690b17f1bSmrg}
12790b17f1bSmrg
12890b17f1bSmrg/*
12990b17f1bSmrg * Mark Sync using the 2D blitter for AGP. NoOp for PCI.
13090b17f1bSmrg * In the future one could even launch a NULL PCI DMA command
13190b17f1bSmrg * to have an interrupt generated, provided it is possible to
13290b17f1bSmrg * write to the PCI DMA engines from the AGP command stream.
13390b17f1bSmrg */
13490b17f1bSmrgint
13590b17f1bSmrgviaAccelMarkSync_H2(ScreenPtr pScreen)
13690b17f1bSmrg{
13790b17f1bSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
13890b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
13990b17f1bSmrg
14090b17f1bSmrg    RING_VARS;
14190b17f1bSmrg
14290b17f1bSmrg    ++pVia->curMarker;
14390b17f1bSmrg
14490b17f1bSmrg    /* Wrap around without affecting the sign bit. */
14590b17f1bSmrg    pVia->curMarker &= 0x7FFFFFFF;
14690b17f1bSmrg
14790b17f1bSmrg    if (pVia->agpDMA) {
14890b17f1bSmrg        BEGIN_RING(16);
14990b17f1bSmrg        OUT_RING_H1(VIA_REG_KEYCONTROL, 0x00);
15090b17f1bSmrg        OUT_RING_H1(VIA_REG_GEMODE, VIA_GEM_32bpp);
15190b17f1bSmrg        OUT_RING_H1(VIA_REG_DSTBASE, pVia->markerOffset >> 3);
15290b17f1bSmrg        OUT_RING_H1(VIA_REG_PITCH, VIA_PITCH_ENABLE);
15390b17f1bSmrg        OUT_RING_H1(VIA_REG_DSTPOS, 0);
15490b17f1bSmrg        OUT_RING_H1(VIA_REG_DIMENSION, 0);
15590b17f1bSmrg        OUT_RING_H1(VIA_REG_FGCOLOR, pVia->curMarker);
15690b17f1bSmrg        OUT_RING_H1(VIA_REG_GECMD, (0xF0 << 24) | VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT);
15790b17f1bSmrg
15890b17f1bSmrg        ADVANCE_RING;
15990b17f1bSmrg    }
16090b17f1bSmrg    return pVia->curMarker;
16190b17f1bSmrg}
16290b17f1bSmrg
16390b17f1bSmrg/*
16490b17f1bSmrg * Exa functions. It is assumed that EXA does not exceed the blitter limits.
16590b17f1bSmrg */
16690b17f1bSmrgBool
16790b17f1bSmrgviaExaPrepareSolid_H2(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
16890b17f1bSmrg{
16990b17f1bSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
17090b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
17190b17f1bSmrg    ViaTwodContext *tdc = &pVia->td;
17290b17f1bSmrg
17390b17f1bSmrg    RING_VARS;
17490b17f1bSmrg
17590b17f1bSmrg    if (exaGetPixmapPitch(pPixmap) & 7)
17690b17f1bSmrg        return FALSE;
17790b17f1bSmrg
17890b17f1bSmrg    if (!viaAccelSetMode(pPixmap->drawable.depth, tdc))
17990b17f1bSmrg        return FALSE;
18090b17f1bSmrg
18190b17f1bSmrg    if (!viaAccelPlaneMaskHelper_H2(tdc, planeMask))
18290b17f1bSmrg        return FALSE;
18390b17f1bSmrg
18490b17f1bSmrg    viaAccelTransparentHelper_H2(pVia, 0x0, 0x0, TRUE);
18590b17f1bSmrg
18690b17f1bSmrg    tdc->cmd = VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT | VIAACCELPATTERNROP(alu);
18790b17f1bSmrg
18890b17f1bSmrg    tdc->fgColor = fg;
18990b17f1bSmrg
19090b17f1bSmrg    return TRUE;
19190b17f1bSmrg}
19290b17f1bSmrg
19390b17f1bSmrgvoid
19490b17f1bSmrgviaExaSolid_H2(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
19590b17f1bSmrg{
19690b17f1bSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
19790b17f1bSmrg    CARD32 dstOffset = exaGetPixmapOffset(pPixmap);
19890b17f1bSmrg    CARD32 dstPitch = exaGetPixmapPitch(pPixmap);
19990b17f1bSmrg    int w = x2 - x1, h = y2 - y1;
20090b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
20190b17f1bSmrg    ViaTwodContext *tdc = &pVia->td;
20290b17f1bSmrg
20390b17f1bSmrg    RING_VARS;
20490b17f1bSmrg
20590b17f1bSmrg    BEGIN_RING(14);
20690b17f1bSmrg    OUT_RING_H1(VIA_REG_GEMODE, tdc->mode);
20790b17f1bSmrg    OUT_RING_H1(VIA_REG_DSTBASE, dstOffset >> 3);
20890b17f1bSmrg    OUT_RING_H1(VIA_REG_PITCH, VIA_PITCH_ENABLE | (dstPitch >> 3) << 16);
20990b17f1bSmrg    OUT_RING_H1(VIA_REG_DSTPOS, (y1 << 16) | (x1 & 0xFFFF));
21090b17f1bSmrg    OUT_RING_H1(VIA_REG_DIMENSION, ((h - 1) << 16) | (w - 1));
21190b17f1bSmrg    OUT_RING_H1(VIA_REG_FGCOLOR, tdc->fgColor);
21290b17f1bSmrg    OUT_RING_H1(VIA_REG_GECMD, tdc->cmd);
21390b17f1bSmrg
21490b17f1bSmrg    ADVANCE_RING;
21590b17f1bSmrg}
21690b17f1bSmrg
21790b17f1bSmrgvoid
21890b17f1bSmrgviaExaDoneSolidCopy_H2(PixmapPtr pPixmap)
21990b17f1bSmrg{
22090b17f1bSmrg}
22190b17f1bSmrg
22290b17f1bSmrgBool
22390b17f1bSmrgviaExaPrepareCopy_H2(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
22490b17f1bSmrg                        int ydir, int alu, Pixel planeMask)
22590b17f1bSmrg{
22690b17f1bSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
22790b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
22890b17f1bSmrg    ViaTwodContext *tdc = &pVia->td;
22990b17f1bSmrg
23090b17f1bSmrg    RING_VARS;
23190b17f1bSmrg
23290b17f1bSmrg    if (pSrcPixmap->drawable.bitsPerPixel != pDstPixmap->drawable.bitsPerPixel)
23390b17f1bSmrg        return FALSE;
23490b17f1bSmrg
23590b17f1bSmrg    if ((tdc->srcPitch = exaGetPixmapPitch(pSrcPixmap)) & 3)
23690b17f1bSmrg        return FALSE;
23790b17f1bSmrg
23890b17f1bSmrg    if (exaGetPixmapPitch(pDstPixmap) & 7)
23990b17f1bSmrg        return FALSE;
24090b17f1bSmrg
24190b17f1bSmrg    tdc->srcOffset = exaGetPixmapOffset(pSrcPixmap);
24290b17f1bSmrg
24390b17f1bSmrg    tdc->cmd = VIA_GEC_BLT | VIAACCELCOPYROP(alu);
24490b17f1bSmrg    if (xdir < 0)
24590b17f1bSmrg        tdc->cmd |= VIA_GEC_DECX;
24690b17f1bSmrg    if (ydir < 0)
24790b17f1bSmrg        tdc->cmd |= VIA_GEC_DECY;
24890b17f1bSmrg
24990b17f1bSmrg    if (!viaAccelSetMode(pDstPixmap->drawable.bitsPerPixel, tdc))
25090b17f1bSmrg        return FALSE;
25190b17f1bSmrg
25290b17f1bSmrg    if (!viaAccelPlaneMaskHelper_H2(tdc, planeMask))
25390b17f1bSmrg        return FALSE;
25490b17f1bSmrg    viaAccelTransparentHelper_H2(pVia, 0x0, 0x0, TRUE);
25590b17f1bSmrg
25690b17f1bSmrg    return TRUE;
25790b17f1bSmrg}
25890b17f1bSmrg
25990b17f1bSmrgvoid
26090b17f1bSmrgviaExaCopy_H2(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
26190b17f1bSmrg                int width, int height)
26290b17f1bSmrg{
26390b17f1bSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
26490b17f1bSmrg    CARD32 dstOffset = exaGetPixmapOffset(pDstPixmap), val;
26590b17f1bSmrg    CARD32 dstPitch = exaGetPixmapPitch(pDstPixmap);
26690b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
26790b17f1bSmrg    ViaTwodContext *tdc = &pVia->td;
26890b17f1bSmrg
26990b17f1bSmrg    if (!width || !height)
27090b17f1bSmrg        return;
27190b17f1bSmrg
27290b17f1bSmrg    if (tdc->cmd & VIA_GEC_DECY) {
27390b17f1bSmrg        srcY += height - 1;
27490b17f1bSmrg        dstY += height - 1;
27590b17f1bSmrg    }
27690b17f1bSmrg
27790b17f1bSmrg    if (tdc->cmd & VIA_GEC_DECX) {
27890b17f1bSmrg        srcX += width - 1;
27990b17f1bSmrg        dstX += width - 1;
28090b17f1bSmrg    }
28190b17f1bSmrg    val = VIA_PITCH_ENABLE | (dstPitch >> 3) << 16 | (tdc->srcPitch >> 3);
28290b17f1bSmrg
28390b17f1bSmrg    RING_VARS;
28490b17f1bSmrg
28590b17f1bSmrg    BEGIN_RING(16);
28690b17f1bSmrg    OUT_RING_H1(VIA_REG_GEMODE, tdc->mode);
28790b17f1bSmrg    OUT_RING_H1(VIA_REG_SRCBASE, tdc->srcOffset >> 3);
28890b17f1bSmrg    OUT_RING_H1(VIA_REG_DSTBASE, dstOffset >> 3);
28990b17f1bSmrg    OUT_RING_H1(VIA_REG_PITCH, val);
29090b17f1bSmrg    OUT_RING_H1(VIA_REG_SRCPOS, (srcY << 16) | (srcX & 0xFFFF));
29190b17f1bSmrg    OUT_RING_H1(VIA_REG_DSTPOS, (dstY << 16) | (dstX & 0xFFFF));
29290b17f1bSmrg    OUT_RING_H1(VIA_REG_DIMENSION, ((height - 1) << 16) | (width - 1));
29390b17f1bSmrg    OUT_RING_H1(VIA_REG_GECMD, tdc->cmd);
29490b17f1bSmrg
29590b17f1bSmrg    ADVANCE_RING;
29690b17f1bSmrg}
29790b17f1bSmrg
29890b17f1bSmrgBool
29990b17f1bSmrgviaExaCheckComposite_H2(int op, PicturePtr pSrcPicture,
30090b17f1bSmrg                        PicturePtr pMaskPicture, PicturePtr pDstPicture)
30190b17f1bSmrg{
30290b17f1bSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPicture->pDrawable->pScreen);
30390b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
30490b17f1bSmrg    Via3DState *v3d = &pVia->v3d;
30590b17f1bSmrg
30690b17f1bSmrg    if (!pSrcPicture->pDrawable)
30790b17f1bSmrg        return FALSE;
30890b17f1bSmrg
30990b17f1bSmrg    /* Reject small composites early. They are done much faster in software. */
31090b17f1bSmrg    if (!pSrcPicture->repeat &&
31190b17f1bSmrg        pSrcPicture->pDrawable->width *
31290b17f1bSmrg        pSrcPicture->pDrawable->height < VIA_MIN_COMPOSITE)
31390b17f1bSmrg        return FALSE;
31490b17f1bSmrg
31590b17f1bSmrg    if (pMaskPicture && pMaskPicture->pDrawable &&
31690b17f1bSmrg        !pMaskPicture->repeat &&
31790b17f1bSmrg        pMaskPicture->pDrawable->width *
31890b17f1bSmrg        pMaskPicture->pDrawable->height < VIA_MIN_COMPOSITE)
31990b17f1bSmrg        return FALSE;
32090b17f1bSmrg
32190b17f1bSmrg    if (pMaskPicture && pMaskPicture->repeat &&
32290b17f1bSmrg        pMaskPicture->repeatType != RepeatNormal)
32390b17f1bSmrg        return FALSE;
32490b17f1bSmrg
32590b17f1bSmrg    if (pMaskPicture && pMaskPicture->componentAlpha) {
32690b17f1bSmrg#ifdef VIA_DEBUG_COMPOSITE
32790b17f1bSmrg        viaExaPrintCompositeInfo("Component Alpha operation", op,  pSrcPicture, pMaskPicture, pDstPicture);
32890b17f1bSmrg#endif
32990b17f1bSmrg        return FALSE;
33090b17f1bSmrg    }
33190b17f1bSmrg
33290b17f1bSmrg    if (!v3d->opSupported(op)) {
33390b17f1bSmrg#ifdef VIA_DEBUG_COMPOSITE
33490b17f1bSmrg        viaExaPrintCompositeInfo("Operator not supported", op, pSrcPicture, pMaskPicture, pDstPicture);
33590b17f1bSmrg#endif
33690b17f1bSmrg        return FALSE;
33790b17f1bSmrg    }
33890b17f1bSmrg
33990b17f1bSmrg    /*
34090b17f1bSmrg     * FIXME: A8 destination formats are currently not supported and do not
34190b17f1bSmrg     * seem supported by the hardware, although there are some leftover
34290b17f1bSmrg     * register settings apparent in the via_3d_reg.h file. We need to fix this
34390b17f1bSmrg     * (if important), by using component ARGB8888 operations with bitmask.
34490b17f1bSmrg     */
34590b17f1bSmrg
34690b17f1bSmrg    if (!v3d->dstSupported(pDstPicture->format)) {
34790b17f1bSmrg#ifdef VIA_DEBUG_COMPOSITE
34890b17f1bSmrg        viaExaPrintCompositeInfo(" Destination format not supported", op, pSrcPicture, pMaskPicture, pDstPicture);
34990b17f1bSmrg#endif
35090b17f1bSmrg        return FALSE;
35190b17f1bSmrg    }
35290b17f1bSmrg
35390b17f1bSmrg    if (v3d->texSupported(pSrcPicture->format)) {
35490b17f1bSmrg        if (pMaskPicture && (PICT_FORMAT_A(pMaskPicture->format) == 0 ||
35590b17f1bSmrg                             !v3d->texSupported(pMaskPicture->format))) {
35690b17f1bSmrg#ifdef VIA_DEBUG_COMPOSITE
35790b17f1bSmrg            viaExaPrintCompositeInfo("Mask format not supported", op, pSrcPicture, pMaskPicture, pDstPicture);
35890b17f1bSmrg#endif
35990b17f1bSmrg            return FALSE;
36090b17f1bSmrg        }
36190b17f1bSmrg        return TRUE;
36290b17f1bSmrg    }
36390b17f1bSmrg#ifdef VIA_DEBUG_COMPOSITE
36490b17f1bSmrg    viaExaPrintCompositeInfo("Src format not supported", op, pSrcPicture, pMaskPicture, pDstPicture);
36590b17f1bSmrg#endif
36690b17f1bSmrg    return FALSE;
36790b17f1bSmrg}
36890b17f1bSmrg
36990b17f1bSmrgstatic Bool
37090b17f1bSmrgviaIsAGP(VIAPtr pVia, PixmapPtr pPix, unsigned long *offset)
37190b17f1bSmrg{
37290b17f1bSmrg#ifdef HAVE_DRI
37390b17f1bSmrg    unsigned long offs;
37490b17f1bSmrg
37590b17f1bSmrg    if (pVia->directRenderingType && !pVia->IsPCI) {
37690b17f1bSmrg        offs = ((unsigned long)pPix->devPrivate.ptr
37790b17f1bSmrg                - (unsigned long)pVia->agpMappedAddr);
37890b17f1bSmrg
37990b17f1bSmrg        if ((offs - pVia->scratchOffset) < pVia->agpSize) {
38090b17f1bSmrg            *offset = offs + pVia->agpAddr;
38190b17f1bSmrg            return TRUE;
38290b17f1bSmrg        }
38390b17f1bSmrg    }
38490b17f1bSmrg#endif
38590b17f1bSmrg    return FALSE;
38690b17f1bSmrg}
38790b17f1bSmrg
38890b17f1bSmrgstatic Bool
38990b17f1bSmrgviaExaIsOffscreen(PixmapPtr pPix)
39090b17f1bSmrg{
39190b17f1bSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pPix->drawable.pScreen);
39290b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
39390b17f1bSmrg
39490b17f1bSmrg    return ((unsigned long)pPix->devPrivate.ptr -
39590b17f1bSmrg            (unsigned long) drm_bo_map(pScrn, pVia->drmmode.front_bo)) < pVia->drmmode.front_bo->size;
39690b17f1bSmrg}
39790b17f1bSmrg
39890b17f1bSmrgBool
39990b17f1bSmrgviaExaPrepareComposite_H2(int op, PicturePtr pSrcPicture,
40090b17f1bSmrg                            PicturePtr pMaskPicture, PicturePtr pDstPicture,
40190b17f1bSmrg                            PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
40290b17f1bSmrg{
40390b17f1bSmrg    CARD32 height, width;
40490b17f1bSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
40590b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
40690b17f1bSmrg    Via3DState *v3d = &pVia->v3d;
40790b17f1bSmrg    int curTex = 0;
40890b17f1bSmrg    ViaTexBlendingModes srcMode;
40990b17f1bSmrg    Bool isAGP;
41090b17f1bSmrg    unsigned long offset;
41190b17f1bSmrg
41290b17f1bSmrg    /* Workaround: EXA crash with new libcairo2 on a VIA VX800 (#298) */
41390b17f1bSmrg    /* TODO Add real source only pictures */
41490b17f1bSmrg    if (!pSrc) {
41590b17f1bSmrg	    ErrorF("pSrc is NULL\n");
41690b17f1bSmrg	    return FALSE;
41790b17f1bSmrg	}
41890b17f1bSmrg
41990b17f1bSmrg    v3d->setDestination(v3d, exaGetPixmapOffset(pDst),
42090b17f1bSmrg                        exaGetPixmapPitch(pDst), pDstPicture->format);
42190b17f1bSmrg    v3d->setCompositeOperator(v3d, op);
42290b17f1bSmrg    v3d->setDrawing(v3d, 0x0c, 0xFFFFFFFF, 0x000000FF, 0xFF);
42390b17f1bSmrg
42490b17f1bSmrg    viaOrder(pSrc->drawable.width, &width);
42590b17f1bSmrg    viaOrder(pSrc->drawable.height, &height);
42690b17f1bSmrg
42790b17f1bSmrg    /*
42890b17f1bSmrg     * For one-pixel repeat mask pictures we avoid using multitexturing by
42990b17f1bSmrg     * modifying the src's texture blending equation and feed the pixel
43090b17f1bSmrg     * value as a constant alpha for the src's texture. Multitexturing on the
43190b17f1bSmrg     * Unichromes seems somewhat slow, so this speeds up translucent windows.
43290b17f1bSmrg     */
43390b17f1bSmrg
43490b17f1bSmrg    srcMode = via_src;
43590b17f1bSmrg    pVia->maskP = NULL;
43690b17f1bSmrg    if (pMaskPicture &&
43790b17f1bSmrg        (pMaskPicture->pDrawable->height == 1) &&
43890b17f1bSmrg        (pMaskPicture->pDrawable->width == 1) &&
43990b17f1bSmrg        pMaskPicture->repeat && viaExpandablePixel(pMaskPicture->format)) {
44090b17f1bSmrg        pVia->maskP = pMask->devPrivate.ptr;
44190b17f1bSmrg        pVia->maskFormat = pMaskPicture->format;
44290b17f1bSmrg        pVia->componentAlpha = pMaskPicture->componentAlpha;
44390b17f1bSmrg        srcMode = ((pMaskPicture->componentAlpha)
44490b17f1bSmrg                   ? via_src_onepix_comp_mask : via_src_onepix_mask);
44590b17f1bSmrg    }
44690b17f1bSmrg
44790b17f1bSmrg    /*
44890b17f1bSmrg     * One-Pixel repeat src pictures go as solid color instead of textures.
44990b17f1bSmrg     * Speeds up window shadows.
45090b17f1bSmrg     */
45190b17f1bSmrg
45290b17f1bSmrg    pVia->srcP = NULL;
45390b17f1bSmrg    if (pSrcPicture && pSrcPicture->repeat
45490b17f1bSmrg        && (pSrcPicture->pDrawable->height == 1)
45590b17f1bSmrg        && (pSrcPicture->pDrawable->width == 1)
45690b17f1bSmrg        && viaExpandablePixel(pSrcPicture->format)) {
45790b17f1bSmrg        pVia->srcP = pSrc->devPrivate.ptr;
45890b17f1bSmrg        pVia->srcFormat = pSrcPicture->format;
45990b17f1bSmrg    }
46090b17f1bSmrg
46190b17f1bSmrg    /* Exa should be smart enough to eliminate this IN operation. */
46290b17f1bSmrg    if (pVia->srcP && pVia->maskP) {
46390b17f1bSmrg        ErrorF("Bad one-pixel IN composite operation. "
46490b17f1bSmrg               "EXA needs to be smarter.\n");
46590b17f1bSmrg        return FALSE;
46690b17f1bSmrg    }
46790b17f1bSmrg
46890b17f1bSmrg    if (!pVia->srcP) {
46990b17f1bSmrg        offset = exaGetPixmapOffset(pSrc);
47090b17f1bSmrg        isAGP = viaIsAGP(pVia, pSrc, &offset);
47190b17f1bSmrg        if (!isAGP && !viaExaIsOffscreen(pSrc))
47290b17f1bSmrg            return FALSE;
47390b17f1bSmrg        if (!v3d->setTexture(v3d, curTex, offset,
47490b17f1bSmrg                             exaGetPixmapPitch(pSrc), pVia->nPOT[curTex],
47590b17f1bSmrg                             1 << width, 1 << height, pSrcPicture->format,
47690b17f1bSmrg                             via_repeat, via_repeat, srcMode, isAGP)) {
47790b17f1bSmrg            return FALSE;
47890b17f1bSmrg        }
47990b17f1bSmrg        curTex++;
48090b17f1bSmrg    }
48190b17f1bSmrg
48290b17f1bSmrg    if (pMaskPicture && !pVia->maskP) {
48390b17f1bSmrg        offset = exaGetPixmapOffset(pMask);
48490b17f1bSmrg        isAGP = viaIsAGP(pVia, pMask, &offset);
48590b17f1bSmrg        if (!isAGP && !viaExaIsOffscreen(pMask))
48690b17f1bSmrg            return FALSE;
48790b17f1bSmrg        viaOrder(pMask->drawable.width, &width);
48890b17f1bSmrg        viaOrder(pMask->drawable.height, &height);
48990b17f1bSmrg        if (!v3d->setTexture(v3d, curTex, offset,
49090b17f1bSmrg                             exaGetPixmapPitch(pMask), pVia->nPOT[curTex],
49190b17f1bSmrg                             1 << width, 1 << height, pMaskPicture->format,
49290b17f1bSmrg                             via_repeat, via_repeat,
49390b17f1bSmrg                             ((pMaskPicture->componentAlpha)
49490b17f1bSmrg                              ? via_comp_mask : via_mask), isAGP)) {
49590b17f1bSmrg            return FALSE;
49690b17f1bSmrg        }
49790b17f1bSmrg        curTex++;
49890b17f1bSmrg    }
49990b17f1bSmrg
50090b17f1bSmrg    v3d->setFlags(v3d, curTex, FALSE, TRUE, TRUE);
50190b17f1bSmrg    v3d->emitState(v3d, &pVia->cb, viaCheckUpload(pScrn, v3d));
50290b17f1bSmrg    v3d->emitClipRect(v3d, &pVia->cb, 0, 0, pDst->drawable.width,
50390b17f1bSmrg                      pDst->drawable.height);
50490b17f1bSmrg
50590b17f1bSmrg    return TRUE;
50690b17f1bSmrg}
50790b17f1bSmrg
50890b17f1bSmrgvoid
50990b17f1bSmrgviaExaComposite_H2(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
51090b17f1bSmrg                    int dstX, int dstY, int width, int height)
51190b17f1bSmrg{
51290b17f1bSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
51390b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
51490b17f1bSmrg    Via3DState *v3d = &pVia->v3d;
51590b17f1bSmrg    CARD32 col;
51690b17f1bSmrg
51790b17f1bSmrg    if (pVia->maskP) {
51890b17f1bSmrg        viaPixelARGB8888(pVia->maskFormat, pVia->maskP, &col);
51990b17f1bSmrg        v3d->setTexBlendCol(v3d, 0, pVia->componentAlpha, col);
52090b17f1bSmrg    }
52190b17f1bSmrg    if (pVia->srcP) {
52290b17f1bSmrg        viaPixelARGB8888(pVia->srcFormat, pVia->srcP, &col);
52390b17f1bSmrg        v3d->setDrawing(v3d, 0x0c, 0xFFFFFFFF, col & 0x00FFFFFF, col >> 24);
52490b17f1bSmrg        srcX = maskX;
52590b17f1bSmrg        srcY = maskY;
52690b17f1bSmrg    }
52790b17f1bSmrg
52890b17f1bSmrg    if (pVia->maskP || pVia->srcP)
52990b17f1bSmrg        v3d->emitState(v3d, &pVia->cb, viaCheckUpload(pScrn, v3d));
53090b17f1bSmrg
53190b17f1bSmrg    v3d->emitQuad(v3d, &pVia->cb, dstX, dstY, srcX, srcY, maskX, maskY,
53290b17f1bSmrg                  width, height);
53390b17f1bSmrg}
53490b17f1bSmrg
53590b17f1bSmrgvoid
53690b17f1bSmrgviaAccelTextureBlit(ScrnInfoPtr pScrn, unsigned long srcOffset,
53790b17f1bSmrg                    unsigned srcPitch, unsigned w, unsigned h, unsigned srcX,
53890b17f1bSmrg                    unsigned srcY, unsigned srcFormat, unsigned long dstOffset,
53990b17f1bSmrg                    unsigned dstPitch, unsigned dstX, unsigned dstY,
54090b17f1bSmrg                    unsigned dstFormat, int rotate)
54190b17f1bSmrg{
54290b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
54390b17f1bSmrg    CARD32 wOrder, hOrder;
54490b17f1bSmrg    Via3DState *v3d = &pVia->v3d;
54590b17f1bSmrg
54690b17f1bSmrg    viaOrder(w, &wOrder);
54790b17f1bSmrg    viaOrder(h, &hOrder);
54890b17f1bSmrg
54990b17f1bSmrg    v3d->setDestination(v3d, dstOffset, dstPitch, dstFormat);
55090b17f1bSmrg    v3d->setDrawing(v3d, 0x0c, 0xFFFFFFFF, 0x000000FF, 0x00);
55190b17f1bSmrg    v3d->setFlags(v3d, 1, TRUE, TRUE, FALSE);
55290b17f1bSmrg    v3d->setTexture(v3d, 0, srcOffset, srcPitch, TRUE,
55390b17f1bSmrg                    1 << wOrder, 1 << hOrder, srcFormat,
55490b17f1bSmrg                    via_single, via_single, via_src, FALSE);
55590b17f1bSmrg    v3d->emitState(v3d, &pVia->cb, viaCheckUpload(pScrn, v3d));
55690b17f1bSmrg    v3d->emitClipRect(v3d, &pVia->cb, dstX, dstY, w, h);
55790b17f1bSmrg    v3d->emitQuad(v3d, &pVia->cb, dstX, dstY, srcX, srcY, 0, 0, w, h);
55890b17f1bSmrg}
559