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    if (exaGetPixmapPitch(pPixmap) & 7)
17490b17f1bSmrg        return FALSE;
17590b17f1bSmrg
17690b17f1bSmrg    if (!viaAccelSetMode(pPixmap->drawable.depth, tdc))
17790b17f1bSmrg        return FALSE;
17890b17f1bSmrg
17990b17f1bSmrg    if (!viaAccelPlaneMaskHelper_H2(tdc, planeMask))
18090b17f1bSmrg        return FALSE;
18190b17f1bSmrg
18290b17f1bSmrg    viaAccelTransparentHelper_H2(pVia, 0x0, 0x0, TRUE);
18390b17f1bSmrg
18490b17f1bSmrg    tdc->cmd = VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT | VIAACCELPATTERNROP(alu);
18590b17f1bSmrg
18690b17f1bSmrg    tdc->fgColor = fg;
18790b17f1bSmrg
18890b17f1bSmrg    return TRUE;
18990b17f1bSmrg}
19090b17f1bSmrg
19190b17f1bSmrgvoid
19290b17f1bSmrgviaExaSolid_H2(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
19390b17f1bSmrg{
19490b17f1bSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
19590b17f1bSmrg    CARD32 dstOffset = exaGetPixmapOffset(pPixmap);
19690b17f1bSmrg    CARD32 dstPitch = exaGetPixmapPitch(pPixmap);
19790b17f1bSmrg    int w = x2 - x1, h = y2 - y1;
19890b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
19990b17f1bSmrg    ViaTwodContext *tdc = &pVia->td;
20090b17f1bSmrg
20190b17f1bSmrg    RING_VARS;
20290b17f1bSmrg
20390b17f1bSmrg    BEGIN_RING(14);
20490b17f1bSmrg    OUT_RING_H1(VIA_REG_GEMODE, tdc->mode);
20590b17f1bSmrg    OUT_RING_H1(VIA_REG_DSTBASE, dstOffset >> 3);
20690b17f1bSmrg    OUT_RING_H1(VIA_REG_PITCH, VIA_PITCH_ENABLE | (dstPitch >> 3) << 16);
20790b17f1bSmrg    OUT_RING_H1(VIA_REG_DSTPOS, (y1 << 16) | (x1 & 0xFFFF));
20890b17f1bSmrg    OUT_RING_H1(VIA_REG_DIMENSION, ((h - 1) << 16) | (w - 1));
20990b17f1bSmrg    OUT_RING_H1(VIA_REG_FGCOLOR, tdc->fgColor);
21090b17f1bSmrg    OUT_RING_H1(VIA_REG_GECMD, tdc->cmd);
21190b17f1bSmrg
21290b17f1bSmrg    ADVANCE_RING;
21390b17f1bSmrg}
21490b17f1bSmrg
21590b17f1bSmrgvoid
21690b17f1bSmrgviaExaDoneSolidCopy_H2(PixmapPtr pPixmap)
21790b17f1bSmrg{
21890b17f1bSmrg}
21990b17f1bSmrg
22090b17f1bSmrgBool
22190b17f1bSmrgviaExaPrepareCopy_H2(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
22290b17f1bSmrg                        int ydir, int alu, Pixel planeMask)
22390b17f1bSmrg{
22490b17f1bSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
22590b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
22690b17f1bSmrg    ViaTwodContext *tdc = &pVia->td;
22790b17f1bSmrg
22890b17f1bSmrg    if (pSrcPixmap->drawable.bitsPerPixel != pDstPixmap->drawable.bitsPerPixel)
22990b17f1bSmrg        return FALSE;
23090b17f1bSmrg
23190b17f1bSmrg    if ((tdc->srcPitch = exaGetPixmapPitch(pSrcPixmap)) & 3)
23290b17f1bSmrg        return FALSE;
23390b17f1bSmrg
23490b17f1bSmrg    if (exaGetPixmapPitch(pDstPixmap) & 7)
23590b17f1bSmrg        return FALSE;
23690b17f1bSmrg
23790b17f1bSmrg    tdc->srcOffset = exaGetPixmapOffset(pSrcPixmap);
23890b17f1bSmrg
23990b17f1bSmrg    tdc->cmd = VIA_GEC_BLT | VIAACCELCOPYROP(alu);
24090b17f1bSmrg    if (xdir < 0)
24190b17f1bSmrg        tdc->cmd |= VIA_GEC_DECX;
24290b17f1bSmrg    if (ydir < 0)
24390b17f1bSmrg        tdc->cmd |= VIA_GEC_DECY;
24490b17f1bSmrg
24590b17f1bSmrg    if (!viaAccelSetMode(pDstPixmap->drawable.bitsPerPixel, tdc))
24690b17f1bSmrg        return FALSE;
24790b17f1bSmrg
24890b17f1bSmrg    if (!viaAccelPlaneMaskHelper_H2(tdc, planeMask))
24990b17f1bSmrg        return FALSE;
25090b17f1bSmrg    viaAccelTransparentHelper_H2(pVia, 0x0, 0x0, TRUE);
25190b17f1bSmrg
25290b17f1bSmrg    return TRUE;
25390b17f1bSmrg}
25490b17f1bSmrg
25590b17f1bSmrgvoid
25690b17f1bSmrgviaExaCopy_H2(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
25790b17f1bSmrg                int width, int height)
25890b17f1bSmrg{
25990b17f1bSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
26090b17f1bSmrg    CARD32 dstOffset = exaGetPixmapOffset(pDstPixmap), val;
26190b17f1bSmrg    CARD32 dstPitch = exaGetPixmapPitch(pDstPixmap);
26290b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
26390b17f1bSmrg    ViaTwodContext *tdc = &pVia->td;
26490b17f1bSmrg
26590b17f1bSmrg    if (!width || !height)
26690b17f1bSmrg        return;
26790b17f1bSmrg
26890b17f1bSmrg    if (tdc->cmd & VIA_GEC_DECY) {
26990b17f1bSmrg        srcY += height - 1;
27090b17f1bSmrg        dstY += height - 1;
27190b17f1bSmrg    }
27290b17f1bSmrg
27390b17f1bSmrg    if (tdc->cmd & VIA_GEC_DECX) {
27490b17f1bSmrg        srcX += width - 1;
27590b17f1bSmrg        dstX += width - 1;
27690b17f1bSmrg    }
27790b17f1bSmrg    val = VIA_PITCH_ENABLE | (dstPitch >> 3) << 16 | (tdc->srcPitch >> 3);
27890b17f1bSmrg
27990b17f1bSmrg    RING_VARS;
28090b17f1bSmrg
28190b17f1bSmrg    BEGIN_RING(16);
28290b17f1bSmrg    OUT_RING_H1(VIA_REG_GEMODE, tdc->mode);
28390b17f1bSmrg    OUT_RING_H1(VIA_REG_SRCBASE, tdc->srcOffset >> 3);
28490b17f1bSmrg    OUT_RING_H1(VIA_REG_DSTBASE, dstOffset >> 3);
28590b17f1bSmrg    OUT_RING_H1(VIA_REG_PITCH, val);
28690b17f1bSmrg    OUT_RING_H1(VIA_REG_SRCPOS, (srcY << 16) | (srcX & 0xFFFF));
28790b17f1bSmrg    OUT_RING_H1(VIA_REG_DSTPOS, (dstY << 16) | (dstX & 0xFFFF));
28890b17f1bSmrg    OUT_RING_H1(VIA_REG_DIMENSION, ((height - 1) << 16) | (width - 1));
28990b17f1bSmrg    OUT_RING_H1(VIA_REG_GECMD, tdc->cmd);
29090b17f1bSmrg
29190b17f1bSmrg    ADVANCE_RING;
29290b17f1bSmrg}
29390b17f1bSmrg
29490b17f1bSmrgBool
29590b17f1bSmrgviaExaCheckComposite_H2(int op, PicturePtr pSrcPicture,
29690b17f1bSmrg                        PicturePtr pMaskPicture, PicturePtr pDstPicture)
29790b17f1bSmrg{
29890b17f1bSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPicture->pDrawable->pScreen);
29990b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
30090b17f1bSmrg    Via3DState *v3d = &pVia->v3d;
30190b17f1bSmrg
30290b17f1bSmrg    if (!pSrcPicture->pDrawable)
30390b17f1bSmrg        return FALSE;
30490b17f1bSmrg
30590b17f1bSmrg    /* Reject small composites early. They are done much faster in software. */
30690b17f1bSmrg    if (!pSrcPicture->repeat &&
30790b17f1bSmrg        pSrcPicture->pDrawable->width *
30890b17f1bSmrg        pSrcPicture->pDrawable->height < VIA_MIN_COMPOSITE)
30990b17f1bSmrg        return FALSE;
31090b17f1bSmrg
31190b17f1bSmrg    if (pMaskPicture && pMaskPicture->pDrawable &&
31290b17f1bSmrg        !pMaskPicture->repeat &&
31390b17f1bSmrg        pMaskPicture->pDrawable->width *
31490b17f1bSmrg        pMaskPicture->pDrawable->height < VIA_MIN_COMPOSITE)
31590b17f1bSmrg        return FALSE;
31690b17f1bSmrg
31790b17f1bSmrg    if (pMaskPicture && pMaskPicture->repeat &&
31890b17f1bSmrg        pMaskPicture->repeatType != RepeatNormal)
31990b17f1bSmrg        return FALSE;
32090b17f1bSmrg
32190b17f1bSmrg    if (pMaskPicture && pMaskPicture->componentAlpha) {
32290b17f1bSmrg#ifdef VIA_DEBUG_COMPOSITE
32390b17f1bSmrg        viaExaPrintCompositeInfo("Component Alpha operation", op,  pSrcPicture, pMaskPicture, pDstPicture);
32490b17f1bSmrg#endif
32590b17f1bSmrg        return FALSE;
32690b17f1bSmrg    }
32790b17f1bSmrg
32890b17f1bSmrg    if (!v3d->opSupported(op)) {
32990b17f1bSmrg#ifdef VIA_DEBUG_COMPOSITE
33090b17f1bSmrg        viaExaPrintCompositeInfo("Operator not supported", op, pSrcPicture, pMaskPicture, pDstPicture);
33190b17f1bSmrg#endif
33290b17f1bSmrg        return FALSE;
33390b17f1bSmrg    }
33490b17f1bSmrg
33590b17f1bSmrg    /*
33690b17f1bSmrg     * FIXME: A8 destination formats are currently not supported and do not
33790b17f1bSmrg     * seem supported by the hardware, although there are some leftover
33890b17f1bSmrg     * register settings apparent in the via_3d_reg.h file. We need to fix this
33990b17f1bSmrg     * (if important), by using component ARGB8888 operations with bitmask.
34090b17f1bSmrg     */
34190b17f1bSmrg
34290b17f1bSmrg    if (!v3d->dstSupported(pDstPicture->format)) {
34390b17f1bSmrg#ifdef VIA_DEBUG_COMPOSITE
34490b17f1bSmrg        viaExaPrintCompositeInfo(" Destination format not supported", op, pSrcPicture, pMaskPicture, pDstPicture);
34590b17f1bSmrg#endif
34690b17f1bSmrg        return FALSE;
34790b17f1bSmrg    }
34890b17f1bSmrg
34990b17f1bSmrg    if (v3d->texSupported(pSrcPicture->format)) {
35090b17f1bSmrg        if (pMaskPicture && (PICT_FORMAT_A(pMaskPicture->format) == 0 ||
35190b17f1bSmrg                             !v3d->texSupported(pMaskPicture->format))) {
35290b17f1bSmrg#ifdef VIA_DEBUG_COMPOSITE
35390b17f1bSmrg            viaExaPrintCompositeInfo("Mask format not supported", op, pSrcPicture, pMaskPicture, pDstPicture);
35490b17f1bSmrg#endif
35590b17f1bSmrg            return FALSE;
35690b17f1bSmrg        }
35790b17f1bSmrg        return TRUE;
35890b17f1bSmrg    }
35990b17f1bSmrg#ifdef VIA_DEBUG_COMPOSITE
36090b17f1bSmrg    viaExaPrintCompositeInfo("Src format not supported", op, pSrcPicture, pMaskPicture, pDstPicture);
36190b17f1bSmrg#endif
36290b17f1bSmrg    return FALSE;
36390b17f1bSmrg}
36490b17f1bSmrg
36590b17f1bSmrgstatic Bool
36690b17f1bSmrgviaIsAGP(VIAPtr pVia, PixmapPtr pPix, unsigned long *offset)
36790b17f1bSmrg{
36890b17f1bSmrg#ifdef HAVE_DRI
36990b17f1bSmrg    unsigned long offs;
37090b17f1bSmrg
37190b17f1bSmrg    if (pVia->directRenderingType && !pVia->IsPCI) {
37290b17f1bSmrg        offs = ((unsigned long)pPix->devPrivate.ptr
37390b17f1bSmrg                - (unsigned long)pVia->agpMappedAddr);
37490b17f1bSmrg
37590b17f1bSmrg        if ((offs - pVia->scratchOffset) < pVia->agpSize) {
37690b17f1bSmrg            *offset = offs + pVia->agpAddr;
37790b17f1bSmrg            return TRUE;
37890b17f1bSmrg        }
37990b17f1bSmrg    }
38090b17f1bSmrg#endif
38190b17f1bSmrg    return FALSE;
38290b17f1bSmrg}
38390b17f1bSmrg
38490b17f1bSmrgstatic Bool
38590b17f1bSmrgviaExaIsOffscreen(PixmapPtr pPix)
38690b17f1bSmrg{
38790b17f1bSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pPix->drawable.pScreen);
38890b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
38990b17f1bSmrg
39090b17f1bSmrg    return ((unsigned long)pPix->devPrivate.ptr -
39190b17f1bSmrg            (unsigned long) drm_bo_map(pScrn, pVia->drmmode.front_bo)) < pVia->drmmode.front_bo->size;
39290b17f1bSmrg}
39390b17f1bSmrg
39490b17f1bSmrgBool
39590b17f1bSmrgviaExaPrepareComposite_H2(int op, PicturePtr pSrcPicture,
39690b17f1bSmrg                            PicturePtr pMaskPicture, PicturePtr pDstPicture,
39790b17f1bSmrg                            PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
39890b17f1bSmrg{
39990b17f1bSmrg    CARD32 height, width;
40090b17f1bSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
40190b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
40290b17f1bSmrg    Via3DState *v3d = &pVia->v3d;
40390b17f1bSmrg    int curTex = 0;
40490b17f1bSmrg    ViaTexBlendingModes srcMode;
40590b17f1bSmrg    Bool isAGP;
40690b17f1bSmrg    unsigned long offset;
40790b17f1bSmrg
40890b17f1bSmrg    /* Workaround: EXA crash with new libcairo2 on a VIA VX800 (#298) */
40990b17f1bSmrg    /* TODO Add real source only pictures */
41090b17f1bSmrg    if (!pSrc) {
41190b17f1bSmrg	    ErrorF("pSrc is NULL\n");
41290b17f1bSmrg	    return FALSE;
41390b17f1bSmrg	}
41490b17f1bSmrg
41590b17f1bSmrg    v3d->setDestination(v3d, exaGetPixmapOffset(pDst),
41690b17f1bSmrg                        exaGetPixmapPitch(pDst), pDstPicture->format);
41790b17f1bSmrg    v3d->setCompositeOperator(v3d, op);
41890b17f1bSmrg    v3d->setDrawing(v3d, 0x0c, 0xFFFFFFFF, 0x000000FF, 0xFF);
41990b17f1bSmrg
42090b17f1bSmrg    viaOrder(pSrc->drawable.width, &width);
42190b17f1bSmrg    viaOrder(pSrc->drawable.height, &height);
42290b17f1bSmrg
42390b17f1bSmrg    /*
42490b17f1bSmrg     * For one-pixel repeat mask pictures we avoid using multitexturing by
42590b17f1bSmrg     * modifying the src's texture blending equation and feed the pixel
42690b17f1bSmrg     * value as a constant alpha for the src's texture. Multitexturing on the
42790b17f1bSmrg     * Unichromes seems somewhat slow, so this speeds up translucent windows.
42890b17f1bSmrg     */
42990b17f1bSmrg
43090b17f1bSmrg    srcMode = via_src;
43190b17f1bSmrg    pVia->maskP = NULL;
43290b17f1bSmrg    if (pMaskPicture &&
43390b17f1bSmrg        (pMaskPicture->pDrawable->height == 1) &&
43490b17f1bSmrg        (pMaskPicture->pDrawable->width == 1) &&
43590b17f1bSmrg        pMaskPicture->repeat && viaExpandablePixel(pMaskPicture->format)) {
43690b17f1bSmrg        pVia->maskP = pMask->devPrivate.ptr;
43790b17f1bSmrg        pVia->maskFormat = pMaskPicture->format;
43890b17f1bSmrg        pVia->componentAlpha = pMaskPicture->componentAlpha;
43990b17f1bSmrg        srcMode = ((pMaskPicture->componentAlpha)
44090b17f1bSmrg                   ? via_src_onepix_comp_mask : via_src_onepix_mask);
44190b17f1bSmrg    }
44290b17f1bSmrg
44390b17f1bSmrg    /*
44490b17f1bSmrg     * One-Pixel repeat src pictures go as solid color instead of textures.
44590b17f1bSmrg     * Speeds up window shadows.
44690b17f1bSmrg     */
44790b17f1bSmrg
44890b17f1bSmrg    pVia->srcP = NULL;
44990b17f1bSmrg    if (pSrcPicture && pSrcPicture->repeat
45090b17f1bSmrg        && (pSrcPicture->pDrawable->height == 1)
45190b17f1bSmrg        && (pSrcPicture->pDrawable->width == 1)
45290b17f1bSmrg        && viaExpandablePixel(pSrcPicture->format)) {
45390b17f1bSmrg        pVia->srcP = pSrc->devPrivate.ptr;
45490b17f1bSmrg        pVia->srcFormat = pSrcPicture->format;
45590b17f1bSmrg    }
45690b17f1bSmrg
45790b17f1bSmrg    /* Exa should be smart enough to eliminate this IN operation. */
45890b17f1bSmrg    if (pVia->srcP && pVia->maskP) {
45990b17f1bSmrg        ErrorF("Bad one-pixel IN composite operation. "
46090b17f1bSmrg               "EXA needs to be smarter.\n");
46190b17f1bSmrg        return FALSE;
46290b17f1bSmrg    }
46390b17f1bSmrg
46490b17f1bSmrg    if (!pVia->srcP) {
46590b17f1bSmrg        offset = exaGetPixmapOffset(pSrc);
46690b17f1bSmrg        isAGP = viaIsAGP(pVia, pSrc, &offset);
46790b17f1bSmrg        if (!isAGP && !viaExaIsOffscreen(pSrc))
46890b17f1bSmrg            return FALSE;
46990b17f1bSmrg        if (!v3d->setTexture(v3d, curTex, offset,
47090b17f1bSmrg                             exaGetPixmapPitch(pSrc), pVia->nPOT[curTex],
47190b17f1bSmrg                             1 << width, 1 << height, pSrcPicture->format,
47290b17f1bSmrg                             via_repeat, via_repeat, srcMode, isAGP)) {
47390b17f1bSmrg            return FALSE;
47490b17f1bSmrg        }
47590b17f1bSmrg        curTex++;
47690b17f1bSmrg    }
47790b17f1bSmrg
47890b17f1bSmrg    if (pMaskPicture && !pVia->maskP) {
47990b17f1bSmrg        offset = exaGetPixmapOffset(pMask);
48090b17f1bSmrg        isAGP = viaIsAGP(pVia, pMask, &offset);
48190b17f1bSmrg        if (!isAGP && !viaExaIsOffscreen(pMask))
48290b17f1bSmrg            return FALSE;
48390b17f1bSmrg        viaOrder(pMask->drawable.width, &width);
48490b17f1bSmrg        viaOrder(pMask->drawable.height, &height);
48590b17f1bSmrg        if (!v3d->setTexture(v3d, curTex, offset,
48690b17f1bSmrg                             exaGetPixmapPitch(pMask), pVia->nPOT[curTex],
48790b17f1bSmrg                             1 << width, 1 << height, pMaskPicture->format,
48890b17f1bSmrg                             via_repeat, via_repeat,
48990b17f1bSmrg                             ((pMaskPicture->componentAlpha)
49090b17f1bSmrg                              ? via_comp_mask : via_mask), isAGP)) {
49190b17f1bSmrg            return FALSE;
49290b17f1bSmrg        }
49390b17f1bSmrg        curTex++;
49490b17f1bSmrg    }
49590b17f1bSmrg
49690b17f1bSmrg    v3d->setFlags(v3d, curTex, FALSE, TRUE, TRUE);
49790b17f1bSmrg    v3d->emitState(v3d, &pVia->cb, viaCheckUpload(pScrn, v3d));
49890b17f1bSmrg    v3d->emitClipRect(v3d, &pVia->cb, 0, 0, pDst->drawable.width,
49990b17f1bSmrg                      pDst->drawable.height);
50090b17f1bSmrg
50190b17f1bSmrg    return TRUE;
50290b17f1bSmrg}
50390b17f1bSmrg
50490b17f1bSmrgvoid
50590b17f1bSmrgviaExaComposite_H2(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
50690b17f1bSmrg                    int dstX, int dstY, int width, int height)
50790b17f1bSmrg{
50890b17f1bSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
50990b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
51090b17f1bSmrg    Via3DState *v3d = &pVia->v3d;
51190b17f1bSmrg    CARD32 col;
51290b17f1bSmrg
51390b17f1bSmrg    if (pVia->maskP) {
51490b17f1bSmrg        viaPixelARGB8888(pVia->maskFormat, pVia->maskP, &col);
51590b17f1bSmrg        v3d->setTexBlendCol(v3d, 0, pVia->componentAlpha, col);
51690b17f1bSmrg    }
51790b17f1bSmrg    if (pVia->srcP) {
51890b17f1bSmrg        viaPixelARGB8888(pVia->srcFormat, pVia->srcP, &col);
51990b17f1bSmrg        v3d->setDrawing(v3d, 0x0c, 0xFFFFFFFF, col & 0x00FFFFFF, col >> 24);
52090b17f1bSmrg        srcX = maskX;
52190b17f1bSmrg        srcY = maskY;
52290b17f1bSmrg    }
52390b17f1bSmrg
52490b17f1bSmrg    if (pVia->maskP || pVia->srcP)
52590b17f1bSmrg        v3d->emitState(v3d, &pVia->cb, viaCheckUpload(pScrn, v3d));
52690b17f1bSmrg
52790b17f1bSmrg    v3d->emitQuad(v3d, &pVia->cb, dstX, dstY, srcX, srcY, maskX, maskY,
52890b17f1bSmrg                  width, height);
52990b17f1bSmrg}
53090b17f1bSmrg
53190b17f1bSmrgvoid
53290b17f1bSmrgviaAccelTextureBlit(ScrnInfoPtr pScrn, unsigned long srcOffset,
53390b17f1bSmrg                    unsigned srcPitch, unsigned w, unsigned h, unsigned srcX,
53490b17f1bSmrg                    unsigned srcY, unsigned srcFormat, unsigned long dstOffset,
53590b17f1bSmrg                    unsigned dstPitch, unsigned dstX, unsigned dstY,
53690b17f1bSmrg                    unsigned dstFormat, int rotate)
53790b17f1bSmrg{
53890b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
53990b17f1bSmrg    CARD32 wOrder, hOrder;
54090b17f1bSmrg    Via3DState *v3d = &pVia->v3d;
54190b17f1bSmrg
54290b17f1bSmrg    viaOrder(w, &wOrder);
54390b17f1bSmrg    viaOrder(h, &hOrder);
54490b17f1bSmrg
54590b17f1bSmrg    v3d->setDestination(v3d, dstOffset, dstPitch, dstFormat);
54690b17f1bSmrg    v3d->setDrawing(v3d, 0x0c, 0xFFFFFFFF, 0x000000FF, 0x00);
54790b17f1bSmrg    v3d->setFlags(v3d, 1, TRUE, TRUE, FALSE);
54890b17f1bSmrg    v3d->setTexture(v3d, 0, srcOffset, srcPitch, TRUE,
54990b17f1bSmrg                    1 << wOrder, 1 << hOrder, srcFormat,
55090b17f1bSmrg                    via_single, via_single, via_src, FALSE);
55190b17f1bSmrg    v3d->emitState(v3d, &pVia->cb, viaCheckUpload(pScrn, v3d));
55290b17f1bSmrg    v3d->emitClipRect(v3d, &pVia->cb, dstX, dstY, w, h);
55390b17f1bSmrg    v3d->emitQuad(v3d, &pVia->cb, dstX, dstY, srcX, srcY, 0, 0, w, h);
55490b17f1bSmrg}
555