diff options
author | Thomas Hellstrom <unichrome@shipmail.org> | 2006-02-22 17:35:33 +0000 |
---|---|---|
committer | Thomas Hellstrom <unichrome@shipmail.org> | 2006-02-22 17:35:33 +0000 |
commit | 58fdf3195122dacd4535377d6fdd55de48dfeb01 (patch) | |
tree | 52ec572427b8079bf22eeb4300cbd8121fed3a21 | |
parent | 6611b34cd5b56b4ad786e6cada872ceaf2b7b6c4 (diff) |
Bugzilla #5180 <https://bugs.freedesktop.org/show_bug.cgi?id=5180> XAA
rework and EXA support including render / composite accel.
-rw-r--r-- | ChangeLog | 55 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/via_3d.c | 584 | ||||
-rw-r--r-- | src/via_3d.h | 120 | ||||
-rw-r--r-- | src/via_accel.c | 3174 | ||||
-rw-r--r-- | src/via_cursor.c | 2 | ||||
-rw-r--r-- | src/via_dga.c | 42 | ||||
-rw-r--r-- | src/via_dri.c | 58 | ||||
-rw-r--r-- | src/via_driver.c | 184 | ||||
-rw-r--r-- | src/via_driver.h | 114 | ||||
-rw-r--r-- | src/via_memcpy.c | 1 | ||||
-rw-r--r-- | src/via_memory.c | 82 | ||||
-rw-r--r-- | src/via_priv.h | 8 | ||||
-rw-r--r-- | src/via_vbe.c | 2 |
14 files changed, 3184 insertions, 1244 deletions
@@ -1,5 +1,60 @@ 2006-02-22 Thomas Hellstrom <thomas-at-tungstengraphics.com> + * src/Makefile.am: + * src/via_3d.c: (via3DDstFormat), (via3DTexFormat), + (via3DDstSupported), (via3DTexSupported), (viaSet3DDestination), + (viaSet3DDrawing), (viaSet3DFlags), (viaOrder), (viaSet3DTexture), + (viaSet3DTexBlendCol), (viaSet3DCompositeOperator), + (via3DOpSupported), (via3DEmitQuad), (via3DEmitState), + (via3DEmitClipRect), (viaInit3DState): + * src/via_3d.h: + * src/via_accel.c: (viaDumpDMA), (viaFlushPCI), + (viaFlushDRIEnabled), (viaSetupCBuffer), (viaTearDownCBuffer), + (viaInitAgp), (viaEnableVQ), (viaDisableVQ), (viaAccelSetMode), + (viaInitialize2DEngine), (viaAccelSync), (viaSetClippingRectangle), + (viaDisableClipping), (viaAccelClippingHelper), + (viaAccelSolidHelper), (viaAccelPlaneMaskHelper), + (viaAccelTransparentHelper), (viaAccelCopyHelper), + (viaSetupForScreenToScreenCopy), (viaSubsequentScreenToScreenCopy), + (viaSetupForSolidFill), (viaSubsequentSolidFillRect), + (viaSetupForMono8x8PatternFill), + (viaSubsequentMono8x8PatternFillRect), + (viaSetupForColor8x8PatternFill), + (viaSubsequentColor8x8PatternFillRect), + (viaSetupForCPUToScreenColorExpandFill), + (viaSubsequentScanlineCPUToScreenColorExpandFill), + (viaSetupForImageWrite), (viaSubsequentImageWriteRect), + (viaSetupForSolidLine), (viaSubsequentSolidTwoPointLine), + (viaSubsequentSolidHorVertLine), (viaSetupForDashedLine), + (viaSubsequentDashedTwoPointLine), (viaInitXAA), + (viaAccelMarkSync), (viaAccelWaitMarker), (viaExaPrepareSolid), + (viaExaSolid), (viaExaDoneSolidCopy), (viaExaPrepareCopy), + (viaExaCopy), (viaExaCompositePictDesc), (viaExaPrintComposite), + (viaBitExpandHelper), (viaPixelARGB8888), (viaExpandablePixel), + (viaCheckUpload), (viaOrder), (viaExaDownloadFromScreen), + (viaExaTexUploadToScreen), (viaExaUploadToScreen), + (viaExaUploadToScratch), (viaExaCheckComposite), (viaIsAGP), + (viaIsOffscreen), (viaExaPrepareComposite), (viaExaComposite), + (viaInitExa), (viaInitAccel), (viaExitAccel), (viaFinishInitAccel), + (viaAccelBlitRect), (viaAccelFillRect), (viaAccelSyncMarker): + * src/via_cursor.c: (VIALoadCursorImage): + * src/via_dga.c: + * src/via_dri.c: (VIADRIRingBufferInit), (VIADRIFBInit), + (VIADRIScreenInit), (VIADRICloseScreen): + * src/via_driver.c: (VIASetup), (VIAPreInit), (VIALeaveVT), + (VIAScreenInit), (VIAInternalScreenInit), (VIAWriteMode), + (VIACloseScreen), (VIASwitchMode): + * src/via_driver.h: + * src/via_memcpy.c: (viaVidCopyInit): + * src/via_memory.c: (VIAFreeLinear), (offScreenLinear), + (VIAAllocLinear), (VIAInitLinear): + * src/via_priv.h: + * src/via_vbe.c: (ViaVbeSetMode): + Bugzilla #5180 <https://bugs.freedesktop.org/show_bug.cgi?id=5180> + XAA rework and EXA support including render / composite accel. + +2006-02-22 Thomas Hellstrom <thomas-at-tungstengraphics.com> + * src/via_mode.c: (ViaModePrimary): Import Luc's fix for sometimes-blanking CRTs. (Luc Verhaegen) diff --git a/src/Makefile.am b/src/Makefile.am index be33590..228b115 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -30,6 +30,8 @@ via_drv_la_LDFLAGS = -module -avoid-version via_drv_ladir = @moduledir@/drivers via_drv_la_SOURCES = \ + via_3d.h \ + via_3d.c \ via_accel.c \ via_bandwidth.c \ via_bios.h \ diff --git a/src/via_3d.c b/src/via_3d.c new file mode 100644 index 0000000..54fb360 --- /dev/null +++ b/src/via_3d.c @@ -0,0 +1,584 @@ +/* + * Copyright 2006 Thomas Hellstrom. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "via_3d.h" +#include "via_3d_reg.h" +#include <picturestr.h> + +typedef struct +{ + Bool supported; + CARD32 col0; + CARD32 col1; + CARD32 al0; + CARD32 al1; +} ViaCompositeOperator; + +typedef struct +{ + CARD32 pictFormat; + Bool dstSupported; + Bool texSupported; + CARD32 dstFormat; + CARD32 texFormat; +} Via3DFormat; + +static ViaCompositeOperator viaOperatorModes[256]; +static Via3DFormat via3DFormats[256]; + +#define VIA_NUM_3D_OPCODES 19 +#define VIA_NUM_3D_FORMATS 15 +#define VIA_FMT_HASH(arg) (((((arg) >> 1) + (arg)) >> 8) & 0xFF) + +static const CARD32 viaOpCodes[VIA_NUM_3D_OPCODES][5] = { + {PictOpClear, 0x05, 0x45, 0x40, 0x80}, + {PictOpSrc, 0x15, 0x45, 0x50, 0x80}, + {PictOpDst, 0x05, 0x55, 0x40, 0x90}, + {PictOpOver, 0x15, 0x52, 0x50, 0x91}, + {PictOpOverReverse, 0x13, 0x45, 0x52, 0x90}, + {PictOpIn, 0x03, 0x45, 0x42, 0x80}, + {PictOpInReverse, 0x05, 0x42, 0x40, 0x81}, + {PictOpOut, 0x13, 0x45, 0x52, 0x80}, + {PictOpOutReverse, 0x05, 0x52, 0x40, 0x91}, + {PictOpAtop, 0x03, 0x52, 0x42, 0x91}, + {PictOpAtopReverse, 0x13, 0x42, 0x52, 0x81}, + {PictOpXor, 0x15, 0x52, 0x52, 0x91}, + {PictOpAdd, 0x15, 0x55, 0x50, 0x90}, + {PictOpDisjointClear, 0x05, 0x45, 0x40, 0x80}, + {PictOpDisjointSrc, 0x15, 0x45, 0x50, 0x80}, + {PictOpDisjointDst, 0x05, 0x55, 0x40, 0x90}, + {PictOpConjointClear, 0x05, 0x45, 0x40, 0x80}, + {PictOpConjointSrc, 0x15, 0x45, 0x50, 0x80}, + {PictOpConjointDst, 0x05, 0x55, 0x40, 0x90} +}; + +static const CARD32 viaFormats[VIA_NUM_3D_FORMATS][5] = { + {PICT_x1r5g5b5, HC_HDBFM_RGB555, HC_HTXnFM_RGB555, 1, 1}, + {PICT_r5g6b5, HC_HDBFM_RGB565, HC_HTXnFM_RGB565, 1, 1}, + {PICT_a4r4g4b4, HC_HDBFM_ARGB4444, HC_HTXnFM_ARGB4444, 1, 1}, + {PICT_a1r5g5b5, HC_HDBFM_ARGB1555, HC_HTXnFM_ARGB1555, 1, 1}, + {PICT_x1b5g5r5, HC_HDBFM_BGR555, HC_HTXnFM_BGR555, 1, 1}, + {PICT_b5g6r5, HC_HDBFM_BGR565, HC_HTXnFM_BGR565, 1, 1}, + {PICT_a4b4g4r4, HC_HDBFM_ABGR4444, HC_HTXnFM_ABGR4444, 1, 1}, + {PICT_a1b5g5r5, HC_HDBFM_ABGR1555, HC_HTXnFM_ABGR1555, 1, 1}, + {PICT_x8r8g8b8, HC_HDBFM_ARGB0888, HC_HTXnFM_ARGB0888, 1, 1}, + {PICT_a8r8g8b8, HC_HDBFM_ARGB8888, HC_HTXnFM_ARGB8888, 1, 1}, + {PICT_x8b8g8r8, HC_HDBFM_ABGR0888, HC_HTXnFM_ABGR0888, 1, 1}, + {PICT_a8b8g8r8, HC_HDBFM_ABGR8888, HC_HTXnFM_ABGR8888, 1, 1}, + {PICT_a8, 0x00, HC_HTXnFM_A8, 0, 1}, + {PICT_a4, 0x00, HC_HTXnFM_A4, 0, 1}, + {PICT_a1, 0x00, HC_HTXnFM_A1, 0, 1} +}; + +static CARD32 +via3DDstFormat(int format) +{ + return via3DFormats[VIA_FMT_HASH(format)].dstFormat; +} + +static CARD32 +via3DTexFormat(int format) +{ + return via3DFormats[VIA_FMT_HASH(format)].texFormat; +} + +static Bool +via3DDstSupported(int format) +{ + Via3DFormat *fm = via3DFormats + VIA_FMT_HASH(format); + + if (fm->pictFormat != format) + return FALSE; + return fm->dstSupported; +} + +static Bool +via3DTexSupported(int format) +{ + Via3DFormat *fm = via3DFormats + VIA_FMT_HASH(format); + + if (fm->pictFormat != format) + return FALSE; + return fm->texSupported; +} + +static void +viaSet3DDestination(Via3DState * v3d, CARD32 offset, CARD32 pitch, int format) +{ + v3d->drawingDirty = TRUE; /* Affects planemask format. */ + v3d->destDirty = TRUE; + v3d->destOffset = offset; + v3d->destPitch = pitch; + v3d->destFormat = via3DDstFormat(format); + v3d->destDepth = (v3d->destFormat < HC_HDBFM_ARGB0888) ? 16 : 32; +} + +static void +viaSet3DDrawing(Via3DState * v3d, int rop, + CARD32 planeMask, CARD32 solidColor, CARD32 solidAlpha) +{ + v3d->drawingDirty = TRUE; + v3d->rop = rop; + v3d->planeMask = planeMask; + v3d->solidColor = solidColor; + v3d->solidAlpha = solidAlpha; +} + +static void +viaSet3DFlags(Via3DState * v3d, int numTextures, + Bool writeAlpha, Bool writeColor, Bool blend) +{ + v3d->enableDirty = TRUE; + v3d->blendDirty = TRUE; + v3d->numTextures = numTextures; + v3d->writeAlpha = writeAlpha; + v3d->writeColor = writeColor; + v3d->blend = blend; +} + +static Bool +viaOrder(CARD32 val, CARD32 * shift) +{ + *shift = 0; + + while (val > (1 << *shift)) + (*shift)++; + return (val == (1 << *shift)); +} + +static Bool +viaSet3DTexture(Via3DState * v3d, int tex, CARD32 offset, + CARD32 pitch, CARD32 width, CARD32 height, int format, + ViaTextureModes sMode, ViaTextureModes tMode, + ViaTexBlendingModes blendingMode, Bool agpTexture) +{ + ViaTextureUnit *vTex = v3d->tex + tex; + + vTex->textureLevel0Offset = offset; + if (!viaOrder(pitch, &vTex->textureLevel0Exp)) + return FALSE; + vTex->textureLevel0Pitch = pitch; + if (!viaOrder(width, &vTex->textureLevel0WExp)) + return FALSE; + if (!viaOrder(height, &vTex->textureLevel0HExp)) + return FALSE; + + if (pitch <= 4) { + ErrorF("Warning! texture pitch is leq 4\n"); + } + + vTex->textureFormat = via3DTexFormat(format); + + switch (blendingMode) { + case via_src: + vTex->texCsat = (0x01 << 23) | (0x10 << 14) | (0x03 << 7) | 0x00; + vTex->texAsat = + (0x0B << 14) | ((PICT_FORMAT_A(format) ? 0x04 : 0x02) << 7) | + 0x03; + vTex->texRCa = 0x00000000; + vTex->texRAa = 0x00000000; + vTex->texBColDirty = TRUE; + break; + case via_src_onepix_mask: + vTex->texCsat = (0x01 << 23) | (0x09 << 14) | (0x03 << 7) | 0x00; + vTex->texAsat = + (0x03 << 14) | ((PICT_FORMAT_A(format) ? 0x04 : 0x02) << 7) | + 0x03; + break; + case via_src_onepix_comp_mask: + vTex->texCsat = (0x01 << 23) | (0x09 << 14) | (0x03 << 7) | 0x00; + vTex->texAsat = + (0x03 << 14) | ((PICT_FORMAT_A(format) ? 0x04 : 0x02) << 7) | + 0x03; + break; + case via_mask: + vTex->texCsat = (0x01 << 23) | (0x07 << 14) | (0x04 << 7) | 0x00; + vTex->texAsat = (0x01 << 23) | (0x04 << 14) | (0x02 << 7) | 0x03; + break; + case via_comp_mask: + vTex->texCsat = (0x01 << 23) | (0x03 << 14) | (0x04 << 7) | 0x00; + vTex->texAsat = (0x01 << 23) | (0x04 << 14) | (0x02 << 7) | 0x03; + break; + default: + return FALSE; + } + + vTex->textureDirty = TRUE; + vTex->textureModesS = sMode - via_single; + vTex->textureModesT = tMode - via_single; + + vTex->agpTexture = agpTexture; + return TRUE; +} + +static void +viaSet3DTexBlendCol(Via3DState * v3d, int tex, Bool component, CARD32 color) +{ + CARD32 alpha; + ViaTextureUnit *vTex = v3d->tex + tex; + + vTex->texRAa = (color >> 8) & 0x00FF0000; + if (component) { + vTex->texRCa = (color & 0x00FFFFFF); + } else { + alpha = color >> 24; + vTex->texRCa = alpha | (alpha << 8) | (alpha << 16) | (alpha << 24); + } + vTex->texBColDirty = TRUE; +} + +/* + * Check if compositing operator is supported and return corresponding register setting. + */ + +static void +viaSet3DCompositeOperator(Via3DState * v3d, CARD8 op) +{ + ViaCompositeOperator *vOp = viaOperatorModes + op; + + v3d->blendDirty = TRUE; + if (v3d && vOp->supported) { + v3d->blendCol0 = vOp->col0 << 4; + v3d->blendCol1 = vOp->col1 << 2; + v3d->blendAl0 = vOp->al0 << 4; + v3d->blendAl1 = vOp->al1 << 2; + } +} + +static Bool +via3DOpSupported(CARD8 op) +{ + return viaOperatorModes[op].supported; +} + +static void +via3DEmitQuad(Via3DState * v3d, ViaCommandBuffer * cb, int dstX, int dstY, + int src0X, int src0Y, int src1X, int src1Y, int w, int h) +{ + CARD32 acmd; + float dx1, dx2, dy1, dy2, sx1[2], sx2[2], sy1[2], sy2[2], wf; + double scalex, scaley; + int i, numTex; + ViaTextureUnit *vTex; + + numTex = v3d->numTextures; + dx1 = dstX; + dx2 = dstX + w; + dy1 = dstY; + dy2 = dstY + h; + + if (numTex) { + sx1[0] = src0X; + sx1[1] = src1X; + sy1[0] = src0Y; + sy1[1] = src1Y; + for (i = 0; i < numTex; ++i) { + vTex = v3d->tex + i; + scalex = 1. / (double)((1 << vTex->textureLevel0WExp)); + scaley = 1. / (double)((1 << vTex->textureLevel0HExp)); + sx2[i] = sx1[i] + w; + sy2[i] = sy1[i] + h; + sx1[i] *= scalex; + sy1[i] *= scaley; + sx2[i] *= scalex; + sy2[i] *= scaley; + } + } + + wf = 0.05; + + /* + * Vertex buffer. Emit two 3-point triangles. The W or Z coordinate + * is needed for AGP DMA, and the W coordinate is for some obscure + * reason needed for texture mapping to be done correctly. So emit + * a w value after the x and y coordinates. + */ + + BEGIN_H2(HC_ParaType_CmdVdata, 22 + numTex * 6); + acmd = ((1 << 14) | (1 << 13) | (1 << 11)); + if (numTex) + acmd |= ((1 << 7) | (1 << 8)); + OUT_RING_SubA(0xEC, acmd); + + acmd = 2 << 16; + OUT_RING_SubA(0xEE, acmd); + + OUT_RING(*((CARD32 *) (&dx1))); + OUT_RING(*((CARD32 *) (&dy1))); + OUT_RING(*((CARD32 *) (&wf))); + for (i = 0; i < numTex; ++i) { + OUT_RING(*((CARD32 *) (sx1 + i))); + OUT_RING(*((CARD32 *) (sy1 + i))); + } + + OUT_RING(*((CARD32 *) (&dx2))); + OUT_RING(*((CARD32 *) (&dy1))); + OUT_RING(*((CARD32 *) (&wf))); + for (i = 0; i < numTex; ++i) { + OUT_RING(*((CARD32 *) (sx2 + i))); + OUT_RING(*((CARD32 *) (sy1 + i))); + } + + OUT_RING(*((CARD32 *) (&dx1))); + OUT_RING(*((CARD32 *) (&dy2))); + OUT_RING(*((CARD32 *) (&wf))); + for (i = 0; i < numTex; ++i) { + OUT_RING(*((CARD32 *) (sx1 + i))); + OUT_RING(*((CARD32 *) (sy2 + i))); + } + + OUT_RING(*((CARD32 *) (&dx1))); + OUT_RING(*((CARD32 *) (&dy2))); + OUT_RING(*((CARD32 *) (&wf))); + for (i = 0; i < numTex; ++i) { + OUT_RING(*((CARD32 *) (sx1 + i))); + OUT_RING(*((CARD32 *) (sy2 + i))); + } + + OUT_RING(*((CARD32 *) (&dx2))); + OUT_RING(*((CARD32 *) (&dy1))); + OUT_RING(*((CARD32 *) (&wf))); + for (i = 0; i < numTex; ++i) { + OUT_RING(*((CARD32 *) (sx2 + i))); + OUT_RING(*((CARD32 *) (sy1 + i))); + } + + OUT_RING(*((CARD32 *) (&dx2))); + OUT_RING(*((CARD32 *) (&dy2))); + OUT_RING(*((CARD32 *) (&wf))); + for (i = 0; i < numTex; ++i) { + OUT_RING(*((CARD32 *) (sx2 + i))); + OUT_RING(*((CARD32 *) (sy2 + i))); + } + OUT_RING_SubA(0xEE, + acmd | HC_HPLEND_MASK | HC_HPMValidN_MASK | HC_HE3Fire_MASK); + OUT_RING_SubA(0xEE, + acmd | HC_HPLEND_MASK | HC_HPMValidN_MASK | HC_HE3Fire_MASK); + + ADVANCE_RING; +} + +static void +via3DEmitState(Via3DState * v3d, ViaCommandBuffer * cb, Bool forceUpload) +{ + int i; + Bool saveHas3dState; + ViaTextureUnit *vTex; + + /* + * Destination buffer location, format and pitch. + */ + + if (forceUpload || v3d->destDirty) { + v3d->destDirty = FALSE; + BEGIN_H2(HC_ParaType_NotTex, 3); + + OUT_RING_SubA(HC_SubA_HDBBasL, v3d->destOffset & 0x00FFFFFF); + OUT_RING_SubA(HC_SubA_HDBBasH, v3d->destOffset >> 24); + OUT_RING_SubA(HC_SubA_HDBFM, v3d->destFormat | + (v3d->destPitch & HC_HDBPit_MASK) | HC_HDBLoc_Local); + } + + if (forceUpload || v3d->blendDirty) { + v3d->blendDirty = FALSE; + BEGIN_H2(HC_ParaType_NotTex, 6); + OUT_RING_SubA(HC_SubA_HABLRFCa, 0x00); + OUT_RING_SubA(HC_SubA_HABLRFCb, 0x00); + OUT_RING_SubA(HC_SubA_HABLCsat, v3d->blendCol0); + OUT_RING_SubA(HC_SubA_HABLCop, v3d->blendCol1); + OUT_RING_SubA(HC_SubA_HABLAsat, v3d->blendAl0); + OUT_RING_SubA(HC_SubA_HABLAop, v3d->blendAl1); + } + + if (forceUpload || v3d->drawingDirty) { + + CARD32 planeMaskLo, planeMaskHi; + + v3d->drawingDirty = FALSE; + BEGIN_H2(HC_ParaType_NotTex, 4); + + /* + * Raster operation and Planemask. + */ + + if ( /* v3d->destDepth == 16 Bad Docs? */ FALSE) { + planeMaskLo = (v3d->planeMask & 0x000000FF) << 16; + planeMaskHi = (v3d->planeMask & 0x0000FF00) >> 8; + } else { + planeMaskLo = v3d->planeMask & 0x00FFFFFF; + planeMaskHi = v3d->planeMask >> 24; + } + + OUT_RING_SubA(HC_SubA_HROP, ((v3d->rop & 0x0F) << 8) | planeMaskHi); + OUT_RING_SubA(HC_SubA_HFBBMSKL, planeMaskLo); + + /* + * Solid shading color and alpha. Pixel center at + * floating coordinates (X.5,Y.5). + */ + + OUT_RING_SubA(HC_SubA_HSolidCL, + (v3d->solidColor & 0x00FFFFFF) | (0 << 23)); + OUT_RING_SubA(HC_SubA_HPixGC, + ((v3d->solidColor & 0xFF000000) >> 16) | (0 << 23) | (v3d-> + solidAlpha & 0xFF)); + } + + if (forceUpload || v3d->enableDirty) { + v3d->enableDirty = FALSE; + BEGIN_H2(HC_ParaType_NotTex, 1); + + OUT_RING_SubA(HC_SubA_HEnable, + ((v3d->writeColor) ? HC_HenCW_MASK : 0) | + ((v3d->blend) ? HC_HenABL_MASK : 0) | + ((v3d->numTextures) ? HC_HenTXMP_MASK : 0) | + ((v3d->writeAlpha) ? HC_HenAW_MASK : 0)); + + if (v3d->numTextures) { + BEGIN_H2((HC_ParaType_Tex | (HC_SubType_TexGeneral << 8)), 2); + OUT_RING_SubA(HC_SubA_HTXSMD, (0 << 7) | (0 << 6) | + (((v3d->numTextures - 1) & 0x1) << 3) | (0 << 1) | 1); + OUT_RING_SubA(HC_SubA_HTXSMD, (0 << 7) | (0 << 6) | + (((v3d->numTextures - 1) & 0x1) << 3) | (0 << 1) | 0); + } + } + + for (i = 0; i < v3d->numTextures; ++i) { + vTex = v3d->tex + i; + + if (forceUpload || vTex->textureDirty) { + vTex->textureDirty = FALSE; + + BEGIN_H2((HC_ParaType_Tex | + (((i == 0) ? HC_SubType_Tex0 : HC_SubType_Tex1) << 8)), + 13); + + OUT_RING_SubA(HC_SubA_HTXnFM, (vTex->textureFormat | + (vTex->agpTexture ? HC_HTXnLoc_AGP : HC_HTXnLoc_Local))); + OUT_RING_SubA(HC_SubA_HTXnL0BasL, + vTex->textureLevel0Offset & 0x00FFFFFF); + OUT_RING_SubA(HC_SubA_HTXnL012BasH, + vTex->textureLevel0Offset >> 24); + OUT_RING_SubA(HC_SubA_HTXnL0Pit, vTex->textureLevel0Exp << 20); + OUT_RING_SubA(HC_SubA_HTXnL0_5WE, vTex->textureLevel0WExp); + OUT_RING_SubA(HC_SubA_HTXnL0_5HE, vTex->textureLevel0HExp); + OUT_RING_SubA(HC_SubA_HTXnL0OS, 0x00); + OUT_RING_SubA(HC_SubA_HTXnTB, 0x00); + OUT_RING_SubA(HC_SubA_HTXnMPMD, + (((unsigned)vTex->textureModesT) << 19) | (((unsigned)vTex-> + textureModesS) << 16)); + + OUT_RING_SubA(HC_SubA_HTXnTBLCsat, vTex->texCsat); + OUT_RING_SubA(HC_SubA_HTXnTBLCop, (0x00 << 22) | (0x00 << 19) | + (0x00 << 14) | (0x02 << 11) | + (0x00 << 7) | (0x03 << 3) | 0x02); + OUT_RING_SubA(HC_SubA_HTXnTBLAsat, vTex->texAsat); + OUT_RING_SubA(HC_SubA_HTXnTBLRFog, 0x00); + } + } + + for (i = 0; i < v3d->numTextures; ++i) { + vTex = v3d->tex + i; + + if (forceUpload || vTex->texBColDirty) { + saveHas3dState = cb->has3dState; + vTex->texBColDirty = FALSE; + BEGIN_H2((HC_ParaType_Tex | + (((i == 0) ? HC_SubType_Tex0 : HC_SubType_Tex1) << 8)), + 2); + OUT_RING_SubA(HC_SubA_HTXnTBLRAa, vTex->texRAa); + OUT_RING_SubA(HC_SubA_HTXnTBLRCa, vTex->texRCa); + cb->has3dState = saveHas3dState; + } + } +} + +/* + * Cliprect. Considered not important for the DRM 3D State, so restore the + * has3dState flag afterwards. + */ + +static void +via3DEmitClipRect(Via3DState * v3d, ViaCommandBuffer * cb, int x, int y, + int w, int h) +{ + Bool saveHas3dState; + + saveHas3dState = cb->has3dState; + BEGIN_H2(HC_ParaType_NotTex, 4); + OUT_RING_SubA(HC_SubA_HClipTB, (y << 12) | (y + h)); + OUT_RING_SubA(HC_SubA_HClipLR, (x << 12) | (x + w)); + cb->has3dState = saveHas3dState; +} + +void +viaInit3DState(Via3DState * v3d) +{ + ViaCompositeOperator *op; + int i; + CARD32 tmp, hash; + Via3DFormat *format; + + v3d->setDestination = viaSet3DDestination; + v3d->setDrawing = viaSet3DDrawing; + v3d->setFlags = viaSet3DFlags; + v3d->setTexture = viaSet3DTexture; + v3d->setTexBlendCol = viaSet3DTexBlendCol; + v3d->opSupported = via3DOpSupported; + v3d->setCompositeOperator = viaSet3DCompositeOperator; + v3d->emitQuad = via3DEmitQuad; + v3d->emitState = via3DEmitState; + v3d->emitClipRect = via3DEmitClipRect; + v3d->dstSupported = via3DDstSupported; + v3d->texSupported = via3DTexSupported; + + for (i = 0; i < 256; ++i) { + viaOperatorModes[i].supported = FALSE; + } + + for (i = 0; i < VIA_NUM_3D_OPCODES; ++i) { + op = viaOperatorModes + viaOpCodes[i][0]; + op->supported = TRUE; + op->col0 = viaOpCodes[i][1]; + op->col1 = viaOpCodes[i][2]; + op->al0 = viaOpCodes[i][3]; + op->al1 = viaOpCodes[i][4]; + } + + for (i = 0; i < 256; ++i) { + via3DFormats[i].pictFormat = 0x00; + } + for (i = 0; i < VIA_NUM_3D_FORMATS; ++i) { + tmp = viaFormats[i][0]; + hash = VIA_FMT_HASH(tmp); + format = via3DFormats + hash; + if (format->pictFormat) { + ErrorF("BUG: Bad hash function\n"); + } + format->pictFormat = tmp; + format->dstSupported = (viaFormats[i][3] != 0x00); + format->texSupported = (viaFormats[i][4] != 0x00); + format->dstFormat = viaFormats[i][1]; + format->texFormat = viaFormats[i][2]; + } +} diff --git a/src/via_3d.h b/src/via_3d.h new file mode 100644 index 0000000..118b6c9 --- /dev/null +++ b/src/via_3d.h @@ -0,0 +1,120 @@ +/* + * Copyright 2006 Thomas Hellstrom. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef VIA_3D_H +#define VIA_3D_H + +#include "xf86.h" +#include "via_dmabuffer.h" + +#define VIA_NUM_TEXUNITS 2 + +typedef enum +{ + via_single, + via_clamp, + via_repeat, + via_mirror, + via_warp +} ViaTextureModes; + +typedef enum +{ + via_src, + via_src_onepix_mask, + via_src_onepix_comp_mask, + via_mask, + via_comp_mask +} ViaTexBlendingModes; + +typedef struct _ViaTextureUnit +{ + CARD32 textureLevel0Offset; + CARD32 textureLevel0Pitch; + CARD32 textureLevel0Exp; + CARD32 textureLevel0WExp; + CARD32 textureLevel0HExp; + CARD32 textureFormat; + CARD32 textureModesT; + CARD32 textureModesS; + CARD32 texCsat; + CARD32 texRCa; + CARD32 texAsat; + CARD32 texRAa; + Bool agpTexture; + Bool textureDirty; + Bool texBColDirty; +} ViaTextureUnit; + +typedef struct _Via3DState +{ + Bool destDirty; + Bool blendDirty; + Bool enableDirty; + Bool drawingDirty; + CARD32 rop; + CARD32 planeMask; + CARD32 solidColor; + CARD32 solidAlpha; + CARD32 destOffset; + CARD32 destPitch; + CARD32 destFormat; + int destDepth; + int numTextures; + Bool blend; + CARD32 blendCol0; + CARD32 blendCol1; + CARD32 blendAl0; + CARD32 blendAl1; + Bool writeAlpha; + Bool writeColor; + Bool useDestAlpha; + ViaTextureUnit tex[VIA_NUM_TEXUNITS]; + void (*setDestination) (struct _Via3DState * v3d, CARD32 offset, + CARD32 pitch, int format); + void (*setDrawing) (struct _Via3DState * v3d, int rop, + CARD32 planeMask, CARD32 solidColor, CARD32 solidAlpha); + void (*setFlags) (struct _Via3DState * v3d, int numTextures, + Bool writeAlpha, Bool writeColor, Bool blend); + Bool(*setTexture) (struct _Via3DState * v3d, int tex, CARD32 offset, + CARD32 pitch, CARD32 width, CARD32 height, int format, + ViaTextureModes sMode, ViaTextureModes tMode, + ViaTexBlendingModes blendingMode, Bool agpTexture); + void (*setTexBlendCol) (struct _Via3DState * v3d, int tex, Bool component, + CARD32 color); + void (*setCompositeOperator) (struct _Via3DState * v3d, CARD8 op); + Bool(*opSupported) (CARD8 op); + void (*emitQuad) (struct _Via3DState * v3d, ViaCommandBuffer * cb, + int dstX, int dstY, int src0X, int src0Y, int src1X, int src1Y, int w, + int h); + void (*emitState) (struct _Via3DState * v3d, ViaCommandBuffer * cb, + Bool forceUpload); + void (*emitClipRect) (struct _Via3DState * v3d, ViaCommandBuffer * cb, + int x, int y, int w, int h); + Bool(*dstSupported) (int format); + Bool(*texSupported) (int format); +} Via3DState; + +void viaInit3DState(Via3DState * v3d); + +#endif diff --git a/src/via_accel.c b/src/via_accel.c index 7467f6a..0960746 100644 --- a/src/via_accel.c +++ b/src/via_accel.c @@ -1,6 +1,7 @@ /* * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * Copyright 2006 Thomas Hellstrom. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,14 +21,9 @@ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. - */ - -/************************************************************************* * - * File: via_accel.c - * Content: 2D acceleration function for VIA/S3G UniChrome - * - ************************************************************************/ + * Mostly rewritten and modified for EXA support by Thomas Hellstrom 2005. + */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -41,1387 +37,2419 @@ #include "via_driver.h" #include "via_regs.h" #include "via_id.h" +#include "via_dmabuffer.h" -/* Forward declaration of functions used in the driver */ - -static void VIASetupForScreenToScreenCopy( - ScrnInfoPtr pScrn, - int xdir, - int ydir, - int rop, - unsigned planemask, - int trans_color); - -static void VIASubsequentScreenToScreenCopy( - ScrnInfoPtr pScrn, - int x1, - int y1, - int x2, - int y2, - int w, - int h); - -static void VIASetupForSolidFill( - ScrnInfoPtr pScrn, - int color, - int rop, - unsigned planemask); - -static void VIASubsequentSolidFillRect( - ScrnInfoPtr pScrn, - int x, - int y, - int w, - int h); - -static void VIASetupForMono8x8PatternFill( - ScrnInfoPtr pScrn, - int pattern0, - int pattern1, - int fg, - int bg, - int rop, - unsigned planemask); - -static void VIASubsequentMono8x8PatternFillRect( - ScrnInfoPtr pScrn, - int patOffx, - int patOffy, - int x, - int y, - int w, - int h); - -static void VIASetupForColor8x8PatternFill( - ScrnInfoPtr pScrn, - int patternx, - int patterny, - int rop, - unsigned planemask, - int trans_color); - -static void VIASubsequentColor8x8PatternFillRect( - ScrnInfoPtr pScrn, - int patOffx, - int patOffy, - int x, - int y, - int w, - int h); - -static void VIASetupForCPUToScreenColorExpandFill( - ScrnInfoPtr pScrn, - int fg, - int bg, - int rop, - unsigned planemask); - -static void VIASubsequentScanlineCPUToScreenColorExpandFill( - ScrnInfoPtr pScrn, - int x, - int y, - int w, - int h, - int skipleft); - -#if 0 /* Buggy. Temporarily disabled 2005-01-23 */ -static void VIASetupForScreenToScreenColorExpand( - ScrnInfoPtr pScrn, - int bg, - int fg, - int rop, - unsigned planemask); - -static void VIASubsequentScreenToScreenColorExpand( - ScrnInfoPtr pScrn, - int x, - int y, - int w, - int h, - int srcx, - int srcy, - int offset); -#endif +#define VIAACCELPATTERNROP(vRop) (XAAGetPatternROP(vRop) << 24) +#define VIAACCELCOPYROP(vRop) (XAAGetCopyROP(vRop) << 24) +/* + * Use PCI MMIO to flush the command buffer. When AGP DMA is not available. + */ -static void VIASetupForImageWrite( - ScrnInfoPtr pScrn, - int rop, - unsigned planemask, - int trans_color, - int bpp, - int depth); +static void +viaDumpDMA(ViaCommandBuffer * buf) +{ + register CARD32 *bp = buf->buf; + CARD32 *endp = bp + buf->pos; -static void VIASubsequentImageWriteRect( - ScrnInfoPtr pScrn, - int x, - int y, - int w, - int h, - int skipleft); + while (bp != endp) { + if (((bp - buf->buf) & 3) == 0) { + ErrorF("\n %04lx: ", (unsigned long)(bp - buf->buf)); + } + ErrorF("0x%08x ", (unsigned)*bp++); + } + ErrorF("\n"); +} -static void -VIASetupForSolidLine( - ScrnInfoPtr pScrn, - int color, - int rop, - unsigned int planemask); +void +viaFlushPCI(ViaCommandBuffer * buf) +{ + register CARD32 *bp = buf->buf; + CARD32 transSetting; + CARD32 *endp = bp + buf->pos; + unsigned loop = 0; + register CARD32 offset = 0; + register CARD32 value; + VIAPtr pVia = VIAPTR(buf->pScrn); + + while (bp < endp) { + if (*bp == HALCYON_HEADER2) { + if (++bp == endp) + return; + VIASETREG(VIA_REG_TRANSET, transSetting = *bp++); + while (bp < endp) { + if ((transSetting != HC_ParaType_CmdVdata) && + ((*bp == HALCYON_HEADER2) + || (*bp & HALCYON_HEADER1MASK) == HALCYON_HEADER1)) + break; + VIASETREG(VIA_REG_TRANSPACE, *bp++); + } + } else if ((*bp & HALCYON_HEADER1MASK) == HALCYON_HEADER1) { + + while (bp < endp) { + if (*bp == HALCYON_HEADER2) + break; + if (offset == 0) { + /* + * Not doing this wait will probably stall the processor + * for an unacceptable amount of time in VIASETREG while other high + * priority interrupts may be pending. + */ + while (!(VIAGETREG(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) + && (loop++ < MAXLOOP)) ; + while ((VIAGETREG(VIA_REG_STATUS) & (VIA_CMD_RGTR_BUSY | + VIA_2D_ENG_BUSY)) + && (loop++ < MAXLOOP)) ; + } + offset = (*bp++ & 0x0FFFFFFF) << 2; + value = *bp++; + VIASETREG(offset, value); + } + } else { + ErrorF("Command stream parser error.\n"); + } + } + buf->pos = 0; + buf->mode = 0; + buf->has3dState = FALSE; +} -static void -VIASubsequentSolidTwoPointLine( - ScrnInfoPtr pScrn, - int x1, - int y1, - int x2, - int y2, - int flags); +/* + * Flush the command buffer using DRM. If in PCI mode, we can bypass DRM, + * but not for command buffers that contains 3D engine state, since then + * the DRM command verifier will lose track of the 3D engine state. + */ +#ifdef XF86DRI static void -VIASubsequentSolidHorVertLine( - ScrnInfoPtr pScrn, - int x, - int y, - int len, - int dir); +viaFlushDRIEnabled(ViaCommandBuffer * cb) +{ + ScrnInfoPtr pScrn = cb->pScrn; + VIAPtr pVia = VIAPTR(pScrn); + char *tmp = (char *)cb->buf; + int tmpSize; + drm_via_cmdbuffer_t b; + + /* + * Align command buffer end for AGP DMA. + */ + + if (pVia->agpDMA && cb->mode == 2 && cb->rindex != HC_ParaType_CmdVdata + && (cb->pos & 1)) { + OUT_RING(HC_DUMMY); + } + + tmpSize = cb->pos * sizeof(CARD32); + if (pVia->agpDMA || (pVia->directRenderingEnabled && cb->has3dState)) { + cb->mode = 0; + cb->has3dState = FALSE; + while (tmpSize > 0) { + b.size = (tmpSize > VIA_DMASIZE) ? VIA_DMASIZE : tmpSize; + tmpSize -= b.size; + b.buf = tmp; + tmp += b.size; + if (drmCommandWrite(pVia->drmFD, + ((pVia->agpDMA) ? DRM_VIA_CMDBUFFER : DRM_VIA_PCICMD), &b, + sizeof(b))) { + ErrorF("DRM command buffer submission failed.\n"); + viaDumpDMA(cb); + return; + } + } + cb->pos = 0; + } else { + viaFlushPCI(cb); + } +} +#endif + +/* + * Initialize a command buffer. Some fields are currently not used since they + * are intended for Unichrome Pro group A video commands. + */ + +int +viaSetupCBuffer(ScrnInfoPtr pScrn, ViaCommandBuffer * buf, unsigned size) +{ +#ifdef XF86DRI + VIAPtr pVia = VIAPTR(pScrn); +#endif + + buf->pScrn = pScrn; + buf->bufSize = ((size == 0) ? VIA_DMASIZE : size) >> 2; + buf->buf = (CARD32 *) xcalloc(buf->bufSize, sizeof(CARD32)); + if (!buf->buf) + return BadAlloc; + buf->waitFlags = 0; + buf->pos = 0; + buf->mode = 0; + buf->header_start = 0; + buf->rindex = 0; + buf->has3dState = FALSE; + buf->flushFunc = viaFlushPCI; +#ifdef XF86DRI + if (pVia->directRenderingEnabled) { + buf->flushFunc = viaFlushDRIEnabled; + } +#endif + return Success; +} + +/* + * Free resources associated with a command buffer. + */ + +void +viaTearDownCBuffer(ViaCommandBuffer * buf) +{ + if (buf && buf->buf) + xfree(buf->buf); + buf->buf = NULL; +} + +/* + * Leftover from VIAs code. + */ static void -VIASetupForDashedLine( - ScrnInfoPtr pScrn, - int fg, - int bg, - int rop, - unsigned int planemask, - int length, - unsigned char *pattern); +viaInitAgp(VIAPtr pVia) +{ + VIASETREG(VIA_REG_TRANSET, 0x00100000); + VIASETREG(VIA_REG_TRANSPACE, 0x00000000); + VIASETREG(VIA_REG_TRANSPACE, 0x00333004); + VIASETREG(VIA_REG_TRANSPACE, 0x60000000); + VIASETREG(VIA_REG_TRANSPACE, 0x61000000); + VIASETREG(VIA_REG_TRANSPACE, 0x62000000); + VIASETREG(VIA_REG_TRANSPACE, 0x63000000); + VIASETREG(VIA_REG_TRANSPACE, 0x64000000); + VIASETREG(VIA_REG_TRANSPACE, 0x7D000000); + + VIASETREG(VIA_REG_TRANSET, 0xfe020000); + VIASETREG(VIA_REG_TRANSPACE, 0x00000000); +} + +/* + * Initialize the virtual command queue. Header 2 commands can be put + * in this queue for buffering. AFAIK it doesn't handle Header 1 + * commands, which is really a pity, since it has to be idled before + * issuing a H1 command. + */ static void -VIASubsequentDashedTwoPointLine( - ScrnInfoPtr pScrn, - int x1, - int y1, - int x2, - int y2, - int flags, - int phase); - -static void VIASetClippingRectangle( - ScrnInfoPtr pScrn, - int x1, - int y1, - int x2, - int y2); - -static void VIADisableClipping( ScrnInfoPtr ); +viaEnableVQ(VIAPtr pVia) +{ + CARD32 + vqStartAddr = pVia->VQStart, + vqEndAddr = pVia->VQEnd, + vqStartL = 0x50000000 | (vqStartAddr & 0xFFFFFF), + vqEndL = 0x51000000 | (vqEndAddr & 0xFFFFFF), + vqStartEndH = 0x52000000 | ((vqStartAddr & 0xFF000000) >> 24) | + ((vqEndAddr & 0xFF000000) >> 16), + vqLen = 0x53000000 | (VIA_VQ_SIZE >> 3); + + VIASETREG(VIA_REG_TRANSET, 0x00fe0000); + VIASETREG(VIA_REG_TRANSPACE, 0x080003fe); + VIASETREG(VIA_REG_TRANSPACE, 0x0a00027c); + VIASETREG(VIA_REG_TRANSPACE, 0x0b000260); + VIASETREG(VIA_REG_TRANSPACE, 0x0c000274); + VIASETREG(VIA_REG_TRANSPACE, 0x0d000264); + VIASETREG(VIA_REG_TRANSPACE, 0x0e000000); + VIASETREG(VIA_REG_TRANSPACE, 0x0f000020); + VIASETREG(VIA_REG_TRANSPACE, 0x1000027e); + VIASETREG(VIA_REG_TRANSPACE, 0x110002fe); + VIASETREG(VIA_REG_TRANSPACE, 0x200f0060); + + VIASETREG(VIA_REG_TRANSPACE, 0x00000006); + VIASETREG(VIA_REG_TRANSPACE, 0x40008c0f); + VIASETREG(VIA_REG_TRANSPACE, 0x44000000); + VIASETREG(VIA_REG_TRANSPACE, 0x45080c04); + VIASETREG(VIA_REG_TRANSPACE, 0x46800408); + + VIASETREG(VIA_REG_TRANSPACE, vqStartEndH); + VIASETREG(VIA_REG_TRANSPACE, vqStartL); + VIASETREG(VIA_REG_TRANSPACE, vqEndL); + VIASETREG(VIA_REG_TRANSPACE, vqLen); +} + +/* + * Disable the virtual command queue. + */ void -VIAInitialize2DEngine(ScrnInfoPtr pScrn) +viaDisableVQ(ScrnInfoPtr pScrn) { - VIAPtr pVia = VIAPTR(pScrn); - CARD32 dwVQStartAddr, dwVQEndAddr; - CARD32 dwVQLen, dwVQStartL, dwVQEndL, dwVQStartEndH; - CARD32 dwGEMode; - ViaTwodContext *tdc = &pVia->td; + VIAPtr pVia = VIAPTR(pScrn); + VIASETREG(VIA_REG_TRANSET, 0x00fe0000); + VIASETREG(VIA_REG_TRANSPACE, 0x00000004); + VIASETREG(VIA_REG_TRANSPACE, 0x40008c0f); + VIASETREG(VIA_REG_TRANSPACE, 0x44000000); + VIASETREG(VIA_REG_TRANSPACE, 0x45080c04); + VIASETREG(VIA_REG_TRANSPACE, 0x46800408); +} - /* init 2D engine regs to reset 2D engine */ - VIASETREG(0x04, 0x0); - VIASETREG(0x08, 0x0); - VIASETREG(0x0c, 0x0); - VIASETREG(0x10, 0x0); - VIASETREG(0x14, 0x0); - VIASETREG(0x18, 0x0); - VIASETREG(0x1c, 0x0); - VIASETREG(0x20, 0x0); - VIASETREG(0x24, 0x0); - VIASETREG(0x28, 0x0); - VIASETREG(0x2c, 0x0); - VIASETREG(0x30, 0x0); - VIASETREG(0x34, 0x0); - VIASETREG(0x38, 0x0); - VIASETREG(0x3c, 0x0); - VIASETREG(0x40, 0x0); - - /* Init AGP and VQ regs */ - VIASETREG(0x43c, 0x00100000); - VIASETREG(0x440, 0x00000000); - VIASETREG(0x440, 0x00333004); - VIASETREG(0x440, 0x60000000); - VIASETREG(0x440, 0x61000000); - VIASETREG(0x440, 0x62000000); - VIASETREG(0x440, 0x63000000); - VIASETREG(0x440, 0x64000000); - VIASETREG(0x440, 0x7D000000); - - VIASETREG(0x43c, 0xfe020000); - VIASETREG(0x440, 0x00000000); +/* + * Update our 2D state (TwoDContext) with a new mode. + */ - if (pVia->VQStart != 0) { - /* Enable VQ */ - dwVQStartAddr = pVia->VQStart; - dwVQEndAddr = pVia->VQEnd; - dwVQStartL = 0x50000000 | (dwVQStartAddr & 0xFFFFFF); - dwVQEndL = 0x51000000 | (dwVQEndAddr & 0xFFFFFF); - dwVQStartEndH = 0x52000000 | ((dwVQStartAddr & 0xFF000000) >> 24) | - ((dwVQEndAddr & 0xFF000000) >> 16); - dwVQLen = 0x53000000 | (VIA_VQ_SIZE >> 3); - - VIASETREG(0x43c, 0x00fe0000); - VIASETREG(0x440, 0x080003fe); - VIASETREG(0x440, 0x0a00027c); - VIASETREG(0x440, 0x0b000260); - VIASETREG(0x440, 0x0c000274); - VIASETREG(0x440, 0x0d000264); - VIASETREG(0x440, 0x0e000000); - VIASETREG(0x440, 0x0f000020); - VIASETREG(0x440, 0x1000027e); - VIASETREG(0x440, 0x110002fe); - VIASETREG(0x440, 0x200f0060); - - VIASETREG(0x440, 0x00000006); - VIASETREG(0x440, 0x40008c0f); - VIASETREG(0x440, 0x44000000); - VIASETREG(0x440, 0x45080c04); - VIASETREG(0x440, 0x46800408); - - VIASETREG(0x440, dwVQStartEndH); - VIASETREG(0x440, dwVQStartL); - VIASETREG(0x440, dwVQEndL); - VIASETREG(0x440, dwVQLen); - } - else { - /* Diable VQ */ - VIASETREG(0x43c, 0x00fe0000); - VIASETREG(0x440, 0x00000004); - VIASETREG(0x440, 0x40008c0f); - VIASETREG(0x440, 0x44000000); - VIASETREG(0x440, 0x45080c04); - VIASETREG(0x440, 0x46800408); - } - - dwGEMode = 0; - - switch (pScrn->bitsPerPixel) { +static Bool +viaAccelSetMode(int bpp, ViaTwodContext * tdc) +{ + switch (bpp) { case 16: - dwGEMode |= VIA_GEM_16bpp; - break; + tdc->mode = VIA_GEM_16bpp; + tdc->bytesPPShift = 1; + return TRUE; case 32: - dwGEMode |= VIA_GEM_32bpp; - break; + tdc->mode = VIA_GEM_32bpp; + tdc->bytesPPShift = 2; + return TRUE; + case 8: + tdc->mode = VIA_GEM_8bpp; + tdc->bytesPPShift = 0; + return TRUE; default: - dwGEMode |= VIA_GEM_8bpp; - break; + tdc->bytesPPShift = 0; + return FALSE; } - - /* Set BPP and Pitch */ - tdc->mode = dwGEMode; } +/* + * Initialize the 2D engine and set the 2D context mode to the + * current screen depth. Also enable the virtual queue. + */ + +void +viaInitialize2DEngine(ScrnInfoPtr pScrn) +{ + VIAPtr pVia = VIAPTR(pScrn); + ViaTwodContext *tdc = &pVia->td; + int i; + + /* + * init 2D engine regs to reset 2D engine + */ + + for (i = 0x04; i < 0x44; i += 4) { + VIASETREG(i, 0x0); + } -#define CLEAR_CBUFFER(buf, pVia) \ - (buf)->curPos = 0; \ - (pVia)->justSetup = 1; + viaInitAgp(pVia); -#define COND_CLEAR_CBUFFER(buf, pVia) \ - if ((pVia)->justSetup == 1) { \ - (pVia)->justSetup = 0; \ - } else { \ - (buf)->curPos = 0; \ + if (pVia->VQStart != 0) { + viaEnableVQ(pVia); + } else { + viaDisableVQ(pScrn); } -#define CBUFFER(buf,offset,value) \ - (buf)->buffer[(buf)->curPos++] = ((offset) >> 2) | 0xF0000000; \ - (buf)->buffer[(buf)->curPos++] = (value); \ - + viaAccelSetMode(pScrn->bitsPerPixel, tdc); +} + +/* + * Wait for acceleration engines idle. An expensive way to sync. + */ -static void dispatchCBuffer(VIAPtr pVia, ViaCBuffer *buf) +void +viaAccelSync(ScrnInfoPtr pScrn) { - unsigned size = buf->curPos >> 1; - int i; - register CARD32 *bp = buf->buffer; - unsigned loop = 0; - register unsigned offset; - register unsigned value; - - /* - * Not doing this wait will probably stall the processor - * for an unacceptable amount of time in VIASETREG while other high - * priority interrupts may be pending. - */ - + VIAPtr pVia = VIAPTR(pScrn); + int loop = 0; + mem_barrier(); - while (!(VIAGETREG(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && (loop++ < MAXLOOP)); + while (!(VIAGETREG(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) + && (loop++ < MAXLOOP)) ; + while ((VIAGETREG(VIA_REG_STATUS) & - (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY )) && - (loop++ < MAXLOOP)); - - for(i=0; i<size; ++i) { - offset = (*bp++ & 0x0FFFFFFF) << 2; - value = *bp++; - VIASETREG( offset , value); + (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY)) && + (loop++ < MAXLOOP)) ; +} + +/* + * Set 2D state clipping on. + */ + +static void +viaSetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2) +{ + VIAPtr pVia = VIAPTR(pScrn); + ViaTwodContext *tdc = &pVia->td; + + tdc->clipping = TRUE; + tdc->clipX1 = x1; + tdc->clipY1 = y1; + tdc->clipX2 = x2; + tdc->clipY2 = y2; +} + +/* + * Set 2D state clipping off. + */ + +static void +viaDisableClipping(ScrnInfoPtr pScrn) +{ + VIAPtr pVia = VIAPTR(pScrn); + ViaTwodContext *tdc = &pVia->td; + + tdc->clipping = FALSE; +} + +/* + * Emit clipping borders to the command buffer and update the 2D context + * current command with clipping info. + */ + +static int +viaAccelClippingHelper(ViaCommandBuffer * cb, int refY, ViaTwodContext * tdc) +{ + if (tdc->clipping) { + refY = (refY < tdc->clipY1) ? refY : tdc->clipY1; + tdc->cmd |= VIA_GEC_CLIP_ENABLE; + BEGIN_RING(4); + OUT_RING_H1(VIA_REG_CLIPTL, + ((tdc->clipY1 - refY) << 16) | tdc->clipX1); + OUT_RING_H1(VIA_REG_CLIPBR, + ((tdc->clipY2 - refY) << 16) | tdc->clipX2); + } else { + tdc->cmd &= ~VIA_GEC_CLIP_ENABLE; } + return refY; + +} + +/* + * Emit a solid blit operation to the command buffer. + */ + +static void +viaAccelSolidHelper(ViaCommandBuffer * cb, int x, int y, int w, int h, + unsigned fbBase, CARD32 mode, unsigned pitch, CARD32 fg, CARD32 cmd) +{ + BEGIN_RING(14); + OUT_RING_H1(VIA_REG_GEMODE, mode); + OUT_RING_H1(VIA_REG_DSTBASE, fbBase >> 3); + OUT_RING_H1(VIA_REG_PITCH, VIA_PITCH_ENABLE | (pitch >> 3) << 16); + OUT_RING_H1(VIA_REG_DSTPOS, (y << 16) | x); + OUT_RING_H1(VIA_REG_DIMENSION, ((h - 1) << 16) | (w - 1)); + OUT_RING_H1(VIA_REG_FGCOLOR, fg); + OUT_RING_H1(VIA_REG_GECMD, cmd); } -static void dispatchCBufferAGP(VIAPtr pVia, ViaCBuffer *buf) +/* + * Check if we can use a planeMask and update the 2D context accordingly. + */ + +static Bool +viaAccelPlaneMaskHelper(ViaTwodContext * tdc, CARD32 planeMask) { -#ifdef XF86DRI - drm_via_cmdbuffer_t b; - - b.buf = (char *)(buf->buffer); - b.size = buf->curPos*sizeof(CARD32); - - if (pVia->directRenderingEnabled && pVia->agpEnable && pVia->dma2d) { - VIADRIPtr pVIADRI = pVia->pDRIInfo->devPrivate; - if (pVIADRI->ringBufActive) { - if (drmCommandWrite(pVia->drmFD,DRM_VIA_CMDBUFFER,&b,sizeof(b))) - dispatchCBuffer(pVia,buf); /* No success using AGP. Try PCI instead. */ - return; + CARD32 modeMask = (1 << ((1 << tdc->bytesPPShift) << 3)) - 1; + CARD32 curMask = 0x00000000; + CARD32 curByteMask; + int i; + + if ((planeMask & modeMask) != modeMask) { + + /* + * Masking doesn't work in 8bpp. + */ + + if (modeMask == 0xFF) { + tdc->keyControl &= 0x0FFFFFFF; + return FALSE; } + + /* + * Translate the bit planemask to a byte planemask. + */ + + for (i = 0; i < (1 << tdc->bytesPPShift); ++i) { + curByteMask = (0xFF << (i << 3)); + + if ((planeMask & curByteMask) == 0) { + curMask |= (1 << i); + } else if ((planeMask & curByteMask) != curByteMask) { + tdc->keyControl &= 0x0FFFFFFF; + return FALSE; + } + } + + tdc->keyControl = (tdc->keyControl & 0x0FFFFFFF) | (curMask << 28); } -#endif - /* - * No AGP ringbuffer or no DRI. - */ - dispatchCBuffer(pVia,buf); + return TRUE; } +/* + * Emit transparency state and color to the command buffer. + */ -/* Acceleration init function, sets up pointers to our accelerated functions */ -Bool -VIAInitAccel(ScreenPtr pScreen) +static void +viaAccelTransparentHelper(ViaTwodContext * tdc, ViaCommandBuffer * cb, + CARD32 keyControl, CARD32 transColor, Bool usePlaneMask) { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - VIAPtr pVia = VIAPTR(pScrn); - XAAInfoRecPtr xaaptr; - BoxRec AvailFBArea; - unsigned long cacheEnd; - unsigned long cacheEndTmp; - + tdc->keyControl &= ((usePlaneMask) ? 0xF0000000 : 0x00000000); + tdc->keyControl |= (keyControl & 0x0FFFFFFF); + BEGIN_RING(4); + OUT_RING_H1(VIA_REG_KEYCONTROL, tdc->keyControl); + if (keyControl) { + OUT_RING_H1(VIA_REG_SRCCOLORKEY, transColor); + } +} - pVia->VQStart = 0; - if (((pVia->FBFreeEnd - pVia->FBFreeStart) >= VIA_VQ_SIZE) && - pVia->VQEnable) { - /* Reserved space for VQ */ - pVia->VQStart = pVia->FBFreeEnd - VIA_VQ_SIZE; - pVia->VQEnd = pVia->VQStart + VIA_VQ_SIZE - 1; - pVia->FBFreeEnd -= VIA_VQ_SIZE; +/* + * Emit a copy blit operation to the command buffer. + */ + +static void +viaAccelCopyHelper(ViaCommandBuffer * cb, int xs, int ys, int xd, int yd, + int w, int h, unsigned srcFbBase, unsigned dstFbBase, CARD32 mode, + unsigned srcPitch, unsigned dstPitch, CARD32 cmd) +{ + if (cmd & VIA_GEC_DECY) { + ys += h - 1; + yd += h - 1; } - if (pVia->hwcursor) { - pVia->FBFreeEnd -= VIA_CURSOR_SIZE; - pVia->CursorStart = pVia->FBFreeEnd; + + if (cmd & VIA_GEC_DECX) { + xs += w - 1; + xd += w - 1; + } + + BEGIN_RING(16); + OUT_RING_H1(VIA_REG_GEMODE, mode); + OUT_RING_H1(VIA_REG_SRCBASE, srcFbBase >> 3); + OUT_RING_H1(VIA_REG_DSTBASE, dstFbBase >> 3); + OUT_RING_H1(VIA_REG_PITCH, VIA_PITCH_ENABLE | + ((dstPitch >> 3) << 16) | (srcPitch >> 3)); + OUT_RING_H1(VIA_REG_SRCPOS, (ys << 16) | xs); + OUT_RING_H1(VIA_REG_DSTPOS, (yd << 16) | xd); + OUT_RING_H1(VIA_REG_DIMENSION, ((h - 1) << 16) | (w - 1)); + OUT_RING_H1(VIA_REG_GECMD, cmd); +} + +/* + * XAA functions. Note that the 2047 line blitter limit has been worked around by adding + * min(y1, y2, clipping y) * stride to the offset (which is recommended by VIA docs). + * The y values (including clipping) must be subtracted accordingly. + */ + +static void +viaSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop, + unsigned planemask, int trans_color) +{ + VIAPtr pVia = VIAPTR(pScrn); + CARD32 cmd; + ViaTwodContext *tdc = &pVia->td; + + RING_VARS; + + cmd = VIA_GEC_BLT | VIAACCELCOPYROP(rop); + + if (xdir < 0) + cmd |= VIA_GEC_DECX; + + if (ydir < 0) + cmd |= VIA_GEC_DECY; + + tdc->cmd = cmd; + viaAccelTransparentHelper(tdc, cb, (trans_color != -1) ? 0x4000 : 0x0000, + trans_color, FALSE); +} + +static void +viaSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, + int x2, int y2, int w, int h) +{ + VIAPtr pVia = VIAPTR(pScrn); + ViaTwodContext *tdc = &pVia->td; + int sub; + + RING_VARS; + + if (!w || !h) + return; + + sub = viaAccelClippingHelper(cb, y2, tdc); + viaAccelCopyHelper(cb, x1, 0, x2, y2 - sub, w, h, + pScrn->fbOffset + pVia->Bpl * y1, pScrn->fbOffset + pVia->Bpl * sub, + tdc->mode, pVia->Bpl, pVia->Bpl, tdc->cmd); + ADVANCE_RING; +} + +/* + * SetupForSolidFill is also called to set up for lines. + */ + +static void +viaSetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, + unsigned planemask) +{ + VIAPtr pVia = VIAPTR(pScrn); + ViaTwodContext *tdc = &pVia->td; + + RING_VARS; + + tdc->cmd = VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT | VIAACCELPATTERNROP(rop); + tdc->fgColor = color; + viaAccelTransparentHelper(tdc, cb, 0x00, 0x00, FALSE); +} + +static void +viaSubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) +{ + VIAPtr pVia = VIAPTR(pScrn); + ViaTwodContext *tdc = &pVia->td; + int sub; + + RING_VARS; + + if (!w || !h) + return; + + sub = viaAccelClippingHelper(cb, y, tdc); + viaAccelSolidHelper(cb, x, y - sub, w, h, + pScrn->fbOffset + pVia->Bpl * sub, tdc->mode, pVia->Bpl, tdc->fgColor, + tdc->cmd); + ADVANCE_RING; +} + +/* + * Original VIA comment: + * The meaning of the two pattern paremeters to Setup & Subsequent for + * Mono8x8Patterns varies depending on the flag bits. We specify + * HW_PROGRAMMED_BITS, which means our hardware can handle 8x8 patterns + * without caching in the frame buffer. Thus, Setup gets the pattern bits. + * There is no way with BCI to rotate an 8x8 pattern, so we do NOT specify + * HW_PROGRAMMED_ORIGIN. XAA wil rotate it for us and pass the rotated + * pattern to both Setup and Subsequent. If we DID specify PROGRAMMED_ORIGIN, + * then Setup would get the unrotated pattern, and Subsequent gets the + * origin values. + */ + +static void +viaSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int pattern0, int pattern1, + int fg, int bg, int rop, unsigned planemask) +{ + VIAPtr pVia = VIAPTR(pScrn); + int cmd; + ViaTwodContext *tdc = &pVia->td; + + RING_VARS; + + cmd = VIA_GEC_BLT | VIA_GEC_PAT_REG | VIA_GEC_PAT_MONO | + VIAACCELPATTERNROP(rop); + + if (bg == -1) { + cmd |= VIA_GEC_MPAT_TRANS; } - VIAInitialize2DEngine(pScrn); + tdc->cmd = cmd; + tdc->fgColor = fg; + tdc->bgColor = bg; + tdc->pattern0 = pattern0; + tdc->pattern1 = pattern1; + viaAccelTransparentHelper(tdc, cb, 0x00, 0x00, FALSE); + +} + +static void +viaSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int patOffx, + int patOffy, int x, int y, int w, int h) +{ + VIAPtr pVia = VIAPTR(pScrn); + CARD32 patOffset; + ViaTwodContext *tdc = &pVia->td; + CARD32 dstBase; + int sub; + + RING_VARS; + + if (!w || !h) + return; + + patOffset = ((patOffy & 0x7) << 29) | ((patOffx & 0x7) << 26); + sub = viaAccelClippingHelper(cb, y, tdc); + dstBase = pScrn->fbOffset + sub * pVia->Bpl; + + BEGIN_RING(22); + OUT_RING_H1(VIA_REG_GEMODE, tdc->mode); + OUT_RING_H1(VIA_REG_DSTBASE, dstBase >> 3); + OUT_RING_H1(VIA_REG_PITCH, VIA_PITCH_ENABLE | ((pVia->Bpl >> 3) << 16)); + OUT_RING_H1(VIA_REG_DSTPOS, ((y - sub) << 16) | x); + OUT_RING_H1(VIA_REG_DIMENSION, (((h - 1) << 16) | (w - 1))); + OUT_RING_H1(VIA_REG_PATADDR, patOffset); + OUT_RING_H1(VIA_REG_FGCOLOR, tdc->fgColor); + OUT_RING_H1(VIA_REG_BGCOLOR, tdc->bgColor); + OUT_RING_H1(VIA_REG_MONOPAT0, tdc->pattern0); + OUT_RING_H1(VIA_REG_MONOPAT1, tdc->pattern1); + OUT_RING_H1(VIA_REG_GECMD, tdc->cmd); + ADVANCE_RING; +} + +static void +viaSetupForColor8x8PatternFill(ScrnInfoPtr pScrn, int patternx, int patterny, + int rop, unsigned planemask, int trans_color) +{ + VIAPtr pVia = VIAPTR(pScrn); + ViaTwodContext *tdc = &pVia->td; + + RING_VARS; + + tdc->cmd = VIA_GEC_BLT | VIAACCELPATTERNROP(rop); + tdc->patternAddr = (patternx * pVia->Bpp + patterny * pVia->Bpl); + viaAccelTransparentHelper(tdc, cb, (trans_color != -1) ? 0x4000 : 0x0000, + trans_color, FALSE); +} + +static void +viaSubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrn, int patOffx, + int patOffy, int x, int y, int w, int h) +{ + VIAPtr pVia = VIAPTR(pScrn); + CARD32 patAddr; + ViaTwodContext *tdc = &pVia->td; + CARD32 dstBase; + int sub; - if (pScrn->depth == 8) { - pVia->PlaneMask = 0xFF; + RING_VARS; + + if (!w || !h) + return; + + patAddr = (tdc->patternAddr >> 3) | + ((patOffy & 0x7) << 29) | ((patOffx & 0x7) << 26); + sub = viaAccelClippingHelper(cb, y, tdc); + dstBase = pScrn->fbOffset + sub * pVia->Bpl; + + BEGIN_RING(14); + OUT_RING_H1(VIA_REG_GEMODE, tdc->mode); + OUT_RING_H1(VIA_REG_DSTBASE, dstBase >> 3); + OUT_RING_H1(VIA_REG_PITCH, VIA_PITCH_ENABLE | ((pVia->Bpl >> 3) << 16)); + OUT_RING_H1(VIA_REG_DSTPOS, ((y - sub) << 16) | x); + OUT_RING_H1(VIA_REG_DIMENSION, (((h - 1) << 16) | (w - 1))); + OUT_RING_H1(VIA_REG_PATADDR, patAddr); + OUT_RING_H1(VIA_REG_GECMD, tdc->cmd); + ADVANCE_RING; +} + +/* + * CPU to screen functions cannot use AGP due to complicated syncing. Therefore the + * command buffer is flushed before new command emissions and viaFluchPCI is called + * explicitly instead of cb->flushFunc() at the end of each CPU to screen function. + * Should the buffer get completely filled again by a CPU to screen command emission, + * a horrible error will occur. + */ + +static void +viaSetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int fg, int bg, + int rop, unsigned planemask) +{ + VIAPtr pVia = VIAPTR(pScrn); + int cmd; + ViaTwodContext *tdc = &pVia->td; + + RING_VARS; + + cmd = VIA_GEC_BLT | VIA_GEC_SRC_SYS | VIA_GEC_SRC_MONO | + VIAACCELCOPYROP(rop); + + if (bg == -1) { + cmd |= VIA_GEC_MSRC_TRANS; } - else if (pScrn->depth == 15) { - pVia->PlaneMask = 0x7FFF; + + tdc->cmd = cmd; + tdc->fgColor = fg; + tdc->bgColor = bg; + + ADVANCE_RING; + + viaAccelTransparentHelper(tdc, cb, 0x0, 0x0, FALSE); +} + +static void +viaSubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int x, + int y, int w, int h, int skipleft) +{ + VIAPtr pVia = VIAPTR(pScrn); + ViaTwodContext *tdc = &pVia->td; + int sub; + + RING_VARS; + + if (skipleft) { + viaSetClippingRectangle(pScrn, (x + skipleft), y, (x + w - 1), + (y + h - 1)); + } + + sub = viaAccelClippingHelper(cb, y, tdc); + BEGIN_RING(4); + OUT_RING_H1(VIA_REG_BGCOLOR, tdc->bgColor); + OUT_RING_H1(VIA_REG_FGCOLOR, tdc->fgColor); + viaAccelCopyHelper(cb, 0, 0, x, y - sub, w, h, 0, + pScrn->fbOffset + sub * pVia->Bpl, tdc->mode, pVia->Bpl, pVia->Bpl, + tdc->cmd); + + viaFlushPCI(cb); + viaDisableClipping(pScrn); +} + +static void +viaSetupForImageWrite(ScrnInfoPtr pScrn, int rop, unsigned planemask, + int trans_color, int bpp, int depth) +{ + VIAPtr pVia = VIAPTR(pScrn); + ViaTwodContext *tdc = &pVia->td; + + RING_VARS; + + tdc->cmd = VIA_GEC_BLT | VIA_GEC_SRC_SYS | VIAACCELCOPYROP(rop); + ADVANCE_RING; + viaAccelTransparentHelper(tdc, cb, (trans_color != -1) ? 0x4000 : 0x0000, + trans_color, FALSE); +} + +static void +viaSubsequentImageWriteRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, + int skipleft) +{ + VIAPtr pVia = VIAPTR(pScrn); + ViaTwodContext *tdc = &pVia->td; + int sub; + + RING_VARS; + + if (skipleft) { + viaSetClippingRectangle(pScrn, (x + skipleft), y, (x + w - 1), + (y + h - 1)); + } + + sub = viaAccelClippingHelper(cb, y, tdc); + viaAccelCopyHelper(cb, 0, 0, x, y - sub, w, h, 0, + pScrn->fbOffset + pVia->Bpl * sub, tdc->mode, pVia->Bpl, pVia->Bpl, + tdc->cmd); + + viaFlushPCI(cb); + viaDisableClipping(pScrn); +} + +static void +viaSetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop, + unsigned int planemask) +{ + VIAPtr pVia = VIAPTR(pScrn); + ViaTwodContext *tdc = &pVia->td; + + RING_VARS; + + viaAccelTransparentHelper(tdc, cb, 0x00, 0x00, FALSE); + tdc->cmd = VIA_GEC_FIXCOLOR_PAT | VIAACCELPATTERNROP(rop); + tdc->fgColor = color; + + BEGIN_RING(6); + OUT_RING_H1(VIA_REG_GEMODE, tdc->mode); + OUT_RING_H1(VIA_REG_MONOPAT0, 0xFF); + OUT_RING_H1(VIA_REG_FGCOLOR, tdc->fgColor); +} + +static void +viaSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1, + int x2, int y2, int flags) +{ + VIAPtr pVia = VIAPTR(pScrn); + int dx, dy, cmd, tmp, error = 1; + ViaTwodContext *tdc = &pVia->td; + CARD32 dstBase; + int sub; + + RING_VARS; + + cmd = tdc->cmd | VIA_GEC_LINE; + + dx = x2 - x1; + if (dx < 0) { + dx = -dx; + cmd |= VIA_GEC_DECX; /* line will be drawn from right */ + error = 0; } - else if (pScrn->depth == 16) { - pVia->PlaneMask = 0xFFFF; + + dy = y2 - y1; + if (dy < 0) { + dy = -dy; + cmd |= VIA_GEC_DECY; /* line will be drawn from bottom */ } - else if (pScrn->depth == 24) { - pVia->PlaneMask = 0xFFFFFF; + + if (dy > dx) { + tmp = dy; + dy = dx; + dx = tmp; /* Swap 'dx' and 'dy' */ + cmd |= VIA_GEC_Y_MAJOR; /* Y major line */ } - /* General acceleration flags */ + if (flags & OMIT_LAST) { + cmd |= VIA_GEC_LASTPIXEL_OFF; + } + + sub = viaAccelClippingHelper(cb, (y1 < y2) ? y1 : y2, tdc); + + dstBase = pScrn->fbOffset + sub * pVia->Bpl; + y1 -= sub; + y2 -= sub; + + BEGIN_RING(14); + OUT_RING_H1(VIA_REG_DSTBASE, dstBase >> 3); + OUT_RING_H1(VIA_REG_PITCH, VIA_PITCH_ENABLE | ((pVia->Bpl >> 3) << 16)); + + /* + * major = 2*dmaj, minor = 2*dmin, err = -dmaj - ((bias >> octant) & 1) + * K1 = 2*dmin K2 = 2*(dmin - dmax) + * Error Term = (StartX<EndX) ? (2*dmin - dmax - 1) : (2*(dmin - dmax)) + */ + + OUT_RING_H1(VIA_REG_LINE_K1K2, + ((((dy << 1) & 0x3fff) << 16) | (((dy - dx) << 1) & 0x3fff))); + OUT_RING_H1(VIA_REG_LINE_XY, ((y1 << 16) | x1)); + OUT_RING_H1(VIA_REG_DIMENSION, dx); + OUT_RING_H1(VIA_REG_LINE_ERROR, + (((dy << 1) - dx - error) & 0x3fff) | 0xFF0000); + OUT_RING_H1(VIA_REG_GECMD, cmd); + ADVANCE_RING; + +} + +static void +viaSubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y, int len, + int dir) +{ + VIAPtr pVia = VIAPTR(pScrn); + ViaTwodContext *tdc = &pVia->td; + CARD32 dstBase; + int sub; + + RING_VARS; + + sub = viaAccelClippingHelper(cb, y, tdc); + dstBase = pScrn->fbOffset + sub * pVia->Bpl; + + BEGIN_RING(10); + OUT_RING_H1(VIA_REG_DSTBASE, dstBase >> 3); + OUT_RING_H1(VIA_REG_PITCH, VIA_PITCH_ENABLE | ((pVia->Bpl >> 3) << 16)); + + if (dir == DEGREES_0) { + OUT_RING_H1(VIA_REG_DSTPOS, ((y - sub) << 16) | x); + OUT_RING_H1(VIA_REG_DIMENSION, (len - 1)); + OUT_RING_H1(VIA_REG_GECMD, tdc->cmd | VIA_GEC_BLT); + } else { + OUT_RING_H1(VIA_REG_DSTPOS, ((y - sub) << 16) | x); + OUT_RING_H1(VIA_REG_DIMENSION, ((len - 1) << 16)); + OUT_RING_H1(VIA_REG_GECMD, tdc->cmd | VIA_GEC_BLT); + } + ADVANCE_RING; +} + +static void +viaSetupForDashedLine(ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int length, unsigned char *pattern) +{ + VIAPtr pVia = VIAPTR(pScrn); + int cmd; + CARD32 pat = *(CARD32 *) pattern; + ViaTwodContext *tdc = &pVia->td; + + RING_VARS; + + viaAccelTransparentHelper(tdc, cb, 0x00, 0x00, FALSE); + cmd = VIA_GEC_LINE | VIA_GEC_FIXCOLOR_PAT | VIAACCELPATTERNROP(rop); + + if (bg == -1) { + cmd |= VIA_GEC_MPAT_TRANS; + } + + tdc->cmd = cmd; + tdc->fgColor = fg; + tdc->bgColor = bg; + + switch (length) { + case 2: + pat |= pat << 2; /* fall through */ + case 4: + pat |= pat << 4; /* fall through */ + case 8: + pat |= pat << 8; /* fall through */ + case 16: + pat |= pat << 16; + } + + tdc->pattern0 = pat; + + BEGIN_RING(8); + OUT_RING_H1(VIA_REG_GEMODE, tdc->mode); + OUT_RING_H1(VIA_REG_FGCOLOR, tdc->fgColor); + OUT_RING_H1(VIA_REG_BGCOLOR, tdc->bgColor); + OUT_RING_H1(VIA_REG_MONOPAT0, tdc->pattern0); +} + +static void +viaSubsequentDashedTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1, int x2, + int y2, int flags, int phase) +{ + viaSubsequentSolidTwoPointLine(pScrn, x1, y1, x2, y2, flags); +} + +static int +viaInitXAA(ScreenPtr pScreen) +{ + + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + VIAPtr pVia = VIAPTR(pScrn); + XAAInfoRecPtr xaaptr; + + /* + * General acceleration flags + */ + if (!(xaaptr = pVia->AccelInfoRec = XAACreateInfoRec())) - return FALSE; + return FALSE; xaaptr->Flags = PIXMAP_CACHE | - OFFSCREEN_PIXMAPS | - LINEAR_FRAMEBUFFER | - MICROSOFT_ZERO_LINE_BIAS | - 0; + OFFSCREEN_PIXMAPS | LINEAR_FRAMEBUFFER | MICROSOFT_ZERO_LINE_BIAS | 0; if (pScrn->bitsPerPixel == 8) - xaaptr->CachePixelGranularity = 128; + xaaptr->CachePixelGranularity = 128; - /* Clipping */ - xaaptr->SetClippingRectangle = VIASetClippingRectangle; - xaaptr->DisableClipping = VIADisableClipping; + xaaptr->SetClippingRectangle = viaSetClippingRectangle; + xaaptr->DisableClipping = viaDisableClipping; xaaptr->ClippingFlags = HARDWARE_CLIP_SOLID_FILL | HARDWARE_CLIP_SOLID_LINE | HARDWARE_CLIP_DASHED_LINE | HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY | HARDWARE_CLIP_MONO_8x8_FILL | HARDWARE_CLIP_COLOR_8x8_FILL | - HARDWARE_CLIP_SCREEN_TO_SCREEN_COLOR_EXPAND | - 0; + HARDWARE_CLIP_SCREEN_TO_SCREEN_COLOR_EXPAND | 0; - xaaptr->Sync = VIAAccelSync; + xaaptr->Sync = viaAccelSync; - /* ScreenToScreen copies */ - xaaptr->SetupForScreenToScreenCopy = VIASetupForScreenToScreenCopy; - xaaptr->SubsequentScreenToScreenCopy = VIASubsequentScreenToScreenCopy; + xaaptr->SetupForScreenToScreenCopy = viaSetupForScreenToScreenCopy; + xaaptr->SubsequentScreenToScreenCopy = viaSubsequentScreenToScreenCopy; xaaptr->ScreenToScreenCopyFlags = NO_PLANEMASK | ROP_NEEDS_SOURCE; - /* Solid filled rectangles */ - xaaptr->SetupForSolidFill = VIASetupForSolidFill; - xaaptr->SubsequentSolidFillRect = VIASubsequentSolidFillRect; + xaaptr->SetupForSolidFill = viaSetupForSolidFill; + xaaptr->SubsequentSolidFillRect = viaSubsequentSolidFillRect; xaaptr->SolidFillFlags = NO_PLANEMASK | ROP_NEEDS_SOURCE; - /* Mono 8x8 pattern fills */ - xaaptr->SetupForMono8x8PatternFill = VIASetupForMono8x8PatternFill; + xaaptr->SetupForMono8x8PatternFill = viaSetupForMono8x8PatternFill; xaaptr->SubsequentMono8x8PatternFillRect = - VIASubsequentMono8x8PatternFillRect; + viaSubsequentMono8x8PatternFillRect; xaaptr->Mono8x8PatternFillFlags = NO_PLANEMASK | HARDWARE_PATTERN_PROGRAMMED_BITS | - HARDWARE_PATTERN_PROGRAMMED_ORIGIN | - BIT_ORDER_IN_BYTE_MSBFIRST | - 0; + HARDWARE_PATTERN_PROGRAMMED_ORIGIN | BIT_ORDER_IN_BYTE_MSBFIRST | 0; - /* Color 8x8 pattern fills */ - xaaptr->SetupForColor8x8PatternFill = VIASetupForColor8x8PatternFill; + xaaptr->SetupForColor8x8PatternFill = viaSetupForColor8x8PatternFill; xaaptr->SubsequentColor8x8PatternFillRect = - VIASubsequentColor8x8PatternFillRect; + viaSubsequentColor8x8PatternFillRect; xaaptr->Color8x8PatternFillFlags = NO_PLANEMASK | NO_TRANSPARENCY | HARDWARE_PATTERN_PROGRAMMED_BITS | - HARDWARE_PATTERN_PROGRAMMED_ORIGIN | - 0; + HARDWARE_PATTERN_PROGRAMMED_ORIGIN | 0; -#if 0 /* Buggy. Temporarily disabled 2005-01-23 */ - - /* Screen to Screen color expansion. */ - xaaptr->SetupForScreenToScreenColorExpandFill = - VIASetupForScreenToScreenColorExpand; - xaaptr->SubsequentScreenToScreenColorExpandFill = - VIASubsequentScreenToScreenColorExpand; - xaaptr->ScreenToScreenColorExpandFillFlags = NO_PLANEMASK | - BIT_ORDER_IN_BYTE_MSBFIRST | - ROP_NEEDS_SOURCE | - 0; -#endif - - /* Solid lines */ - xaaptr->SetupForSolidLine = VIASetupForSolidLine; - xaaptr->SubsequentSolidTwoPointLine = VIASubsequentSolidTwoPointLine; - xaaptr->SubsequentSolidHorVertLine = VIASubsequentSolidHorVertLine; + xaaptr->SetupForSolidLine = viaSetupForSolidLine; + xaaptr->SubsequentSolidTwoPointLine = viaSubsequentSolidTwoPointLine; + xaaptr->SubsequentSolidHorVertLine = viaSubsequentSolidHorVertLine; xaaptr->SolidBresenhamLineErrorTermBits = 14; xaaptr->SolidLineFlags = NO_PLANEMASK | ROP_NEEDS_SOURCE; - /* dashed line */ - xaaptr->SetupForDashedLine = VIASetupForDashedLine; - xaaptr->SubsequentDashedTwoPointLine = VIASubsequentDashedTwoPointLine; + xaaptr->SetupForDashedLine = viaSetupForDashedLine; + xaaptr->SubsequentDashedTwoPointLine = viaSubsequentDashedTwoPointLine; xaaptr->DashPatternMaxLength = 8; xaaptr->DashedLineFlags = NO_PLANEMASK | ROP_NEEDS_SOURCE | - LINE_PATTERN_POWER_OF_2_ONLY | - LINE_PATTERN_MSBFIRST_LSBJUSTIFIED | - 0; + LINE_PATTERN_POWER_OF_2_ONLY | LINE_PATTERN_MSBFIRST_LSBJUSTIFIED | 0; - /* CPU to Screen color expansion */ xaaptr->ScanlineCPUToScreenColorExpandFillFlags = NO_PLANEMASK | CPU_TRANSFER_PAD_DWORD | SCANLINE_PAD_DWORD | BIT_ORDER_IN_BYTE_MSBFIRST | - LEFT_EDGE_CLIPPING | - ROP_NEEDS_SOURCE | - 0; + LEFT_EDGE_CLIPPING | ROP_NEEDS_SOURCE | 0; xaaptr->SetupForScanlineCPUToScreenColorExpandFill = - VIASetupForCPUToScreenColorExpandFill; + viaSetupForCPUToScreenColorExpandFill; xaaptr->SubsequentScanlineCPUToScreenColorExpandFill = - VIASubsequentScanlineCPUToScreenColorExpandFill; + viaSubsequentScanlineCPUToScreenColorExpandFill; xaaptr->ColorExpandBase = pVia->BltBase; xaaptr->ColorExpandRange = VIA_MMIO_BLTSIZE; - /* ImageWrite */ xaaptr->ImageWriteFlags = NO_PLANEMASK | CPU_TRANSFER_PAD_DWORD | SCANLINE_PAD_DWORD | BIT_ORDER_IN_BYTE_MSBFIRST | - LEFT_EDGE_CLIPPING | - ROP_NEEDS_SOURCE | - SYNC_AFTER_IMAGE_WRITE | - 0; - + LEFT_EDGE_CLIPPING | ROP_NEEDS_SOURCE | SYNC_AFTER_IMAGE_WRITE | 0; + /* - * CLE266 has fast direct processor access to the framebuffer. - * Therefore, disable the PCI GXcopy. + * Most Unichromes are much faster using processor to + * framebuffer writes than using the 2D engine for this. + * test with x11perf -shmput500! */ - - if (pVia->Chipset == VIA_CLE266) - xaaptr->ImageWriteFlags |= NO_GXCOPY; - xaaptr->SetupForImageWrite = VIASetupForImageWrite; - xaaptr->SubsequentImageWriteRect = VIASubsequentImageWriteRect; + if (pVia->Chipset != VIA_K8M800) + xaaptr->ImageWriteFlags |= NO_GXCOPY; + + xaaptr->SetupForImageWrite = viaSetupForImageWrite; + xaaptr->SubsequentImageWriteRect = viaSubsequentImageWriteRect; xaaptr->ImageWriteBase = pVia->BltBase; xaaptr->ImageWriteRange = VIA_MMIO_BLTSIZE; - /* We reserve space for pixel cache */ - - cacheEnd = pVia->FBFreeEnd / pVia->Bpl; - cacheEndTmp = (pVia->FBFreeStart + VIA_PIXMAP_CACHE_SIZE + pVia->Bpl-1) - / pVia->Bpl; - - /* - * Use only requested pixmap size if it is less than available - * offscreen memory. - */ + return XAAInit(pScreen, xaaptr); - if(cacheEnd > cacheEndTmp) - cacheEnd = cacheEndTmp; - /* - * Clip to the blitter limit - */ +} - if (cacheEnd > VIA_MAX_ACCEL_Y) - cacheEnd = VIA_MAX_ACCEL_Y; +/* + * Mark Sync using the 2D blitter for AGP. NoOp for PCI. + * In the future one could even launch a NULL PCI DMA command + * to have an interrupt generated, provided it is possible to + * write to the PCI DMA engines from the AGP command stream. + */ - pVia->FBFreeStart = (cacheEnd + 1) *pVia->Bpl; +int +viaAccelMarkSync(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + VIAPtr pVia = VIAPTR(pScrn); + + RING_VARS; + + ++pVia->curMarker; /* - * Finally, we set up the video memory space available to the pixmap - * cache + * Wrap around without possibly affecting the int sign bit. */ - AvailFBArea.x1 = 0; - AvailFBArea.y1 = 0; - AvailFBArea.x2 = pScrn->displayWidth; - AvailFBArea.y2 = cacheEnd; - - xf86InitFBManager(pScreen, &AvailFBArea); - DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using %d lines for offscreen memory.\n", - AvailFBArea.y2 - pScrn->virtualY )); + pVia->curMarker &= 0x7FFFFFFF; - pVia->justSetup = 0; - return XAAInit(pScreen, xaaptr); + if (pVia->agpDMA) { + BEGIN_RING(2); + OUT_RING_H1(VIA_REG_KEYCONTROL, 0x00); + viaAccelSolidHelper(cb, 0, 0, 1, 1, pVia->markerOffset, + VIA_GEM_32bpp, 4, pVia->curMarker, + (0xF0 << 24) | VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT); + ADVANCE_RING; + } + return pVia->curMarker; } /* - * The sync function for the GE + * Wait for the value to get blitted, or in the PCI case for engine idle. */ -void -VIAAccelSync(ScrnInfoPtr pScrn) + +void +viaAccelWaitMarker(ScreenPtr pScreen, int marker) { + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; VIAPtr pVia = VIAPTR(pScrn); - int loop = 0; - - mem_barrier(); - - while (!(VIAGETREG(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && (loop++ < MAXLOOP)) - ; - - while ((VIAGETREG(VIA_REG_STATUS) & - (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY)) && - (loop++ < MAXLOOP)) - ; + CARD32 uMarker = marker; + + if (pVia->agpDMA) { + while ((pVia->lastMarkerRead - uMarker) > (1 << 24)) + pVia->lastMarkerRead = *pVia->markerBuf; + } else { + viaAccelSync(pScrn); + } } -/* These are the ScreenToScreen bitblt functions. We support all ROPs, all - * directions. - * +#ifdef VIA_HAVE_EXA + +/* + * Exa functions. It is assumed that EXA does not exceed the blitter limits. */ -static void -VIASetupForScreenToScreenCopy( - ScrnInfoPtr pScrn, - int xdir, - int ydir, - int rop, - unsigned planemask, - int trans_color) -{ - VIAPtr pVia = VIAPTR(pScrn); - int cmd; - ViaCBuffer *buf = &pVia->cBuf; +static Bool +viaExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg) +{ + ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; + VIAPtr pVia = VIAPTR(pScrn); ViaTwodContext *tdc = &pVia->td; - cmd = VIA_GEC_BLT | (XAAGetCopyROP(rop) << 24); + RING_VARS; - if (xdir < 0) - cmd |= VIA_GEC_DECX; + if (exaGetPixmapPitch(pPixmap) & 7) + return FALSE; - if (ydir < 0) - cmd |= VIA_GEC_DECY; + if (!viaAccelSetMode(pPixmap->drawable.depth, tdc)) + return FALSE; - pVia->SavedCmd = cmd; + if (!viaAccelPlaneMaskHelper(tdc, planeMask)) + return FALSE; + viaAccelTransparentHelper(tdc, cb, 0x0, 0x0, TRUE); - CLEAR_CBUFFER( buf, pVia); - CBUFFER(buf,VIA_REG_GEMODE, tdc->mode); - if (trans_color != -1) { - /* Transparent Bitblt */ - CBUFFER(buf,VIA_REG_SRCCOLORKEY, trans_color); - CBUFFER(buf,VIA_REG_KEYCONTROL, 0x4000); - } - else { - /* Disable Transparent Bitblt */ - CBUFFER(buf,VIA_REG_KEYCONTROL, 0x0); - } + tdc->cmd = VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT | VIAACCELPATTERNROP(alu); + + tdc->fgColor = fg; + + return TRUE; } static void -VIASubsequentScreenToScreenCopy( - ScrnInfoPtr pScrn, - int x1, - int y1, - int x2, - int y2, - int w, - int h) +viaExaSolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2) { + ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; VIAPtr pVia = VIAPTR(pScrn); - ViaCBuffer *buf = &pVia->cBuf; ViaTwodContext *tdc = &pVia->td; - CARD32 srcBase, dstBase; + CARD32 dstPitch, dstOffset; - if (!w || !h) - return; + RING_VARS; - srcBase = y1*pVia->Bpl + x1*pVia->Bpp; - dstBase = y2*pVia->Bpl + x2*pVia->Bpp; + int w = x2 - x1, h = y2 - y1; - x1 = (srcBase & 31); - x2 = (dstBase & 31); + dstPitch = exaGetPixmapPitch(pPixmap); + dstOffset = exaGetPixmapOffset(pPixmap); - switch (pScrn->bitsPerPixel) { - case 16: - x1 >>= 1; - x2 >>= 1; - break; - case 32: - x1 >>= 2; - x2 >>= 2; - break; - default: - break; - } + viaAccelSolidHelper(cb, x1, y1, w, h, dstOffset, + tdc->mode, dstPitch, tdc->fgColor, tdc->cmd); + ADVANCE_RING; +} - y1 = 0; - y2 = 0; +static void +viaExaDoneSolidCopy(PixmapPtr pPixmap) +{ +} - if (pVia->SavedCmd & VIA_GEC_DECX) { - x1 += (w - 1); - x2 += (w - 1); - } +static Bool +viaExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, + int ydir, int alu, Pixel planeMask) +{ + ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; + VIAPtr pVia = VIAPTR(pScrn); + ViaTwodContext *tdc = &pVia->td; - if (pVia->SavedCmd & VIA_GEC_DECY) { - y1 += (h - 1); - y2 += (h - 1); - } + RING_VARS; - COND_CLEAR_CBUFFER( buf, pVia); - CBUFFER(buf,VIA_REG_GEMODE, tdc->mode ); - /* Set Src and Dst base address and pitch, pitch is qword */ - CBUFFER(buf,VIA_REG_SRCBASE, (srcBase & ~31) >> 3); - CBUFFER(buf,VIA_REG_DSTBASE, (dstBase & ~31) >> 3); - CBUFFER(buf,VIA_REG_PITCH, VIA_PITCH_ENABLE | - (pVia->Bpl >> 3) | ((pVia->Bpl >> 3) << 16)); - CBUFFER(buf,VIA_REG_SRCPOS, ((y1 << 16) | x1)); - CBUFFER(buf,VIA_REG_DSTPOS, ((y2 << 16) | x2)); - CBUFFER(buf,VIA_REG_DIMENSION, (((h - 1) << 16) | (w - 1))); - CBUFFER(buf,VIA_REG_GECMD, pVia->SavedCmd); - dispatchCBufferAGP(pVia, buf); -} + if (pSrcPixmap->drawable.bitsPerPixel != + pDstPixmap->drawable.bitsPerPixel) + return FALSE; + if ((tdc->srcPitch = exaGetPixmapPitch(pSrcPixmap)) & 3) + return FALSE; -/* - * SetupForSolidFill is also called to set up for lines. - */ + if (exaGetPixmapPitch(pDstPixmap) & 7) + return FALSE; -static void -VIASetupForSolidFill( - ScrnInfoPtr pScrn, - int color, - int rop, - unsigned planemask) -{ - VIAPtr pVia = VIAPTR(pScrn); - int cmd; + tdc->srcOffset = exaGetPixmapOffset(pSrcPixmap); - cmd = VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT | - (XAAGetPatternROP(rop) << 24); + tdc->cmd = VIA_GEC_BLT | VIAACCELCOPYROP(alu); + if (xdir < 0) + tdc->cmd |= VIA_GEC_DECX; + if (ydir < 0) + tdc->cmd |= VIA_GEC_DECY; - pVia->SavedCmd = cmd; - pVia->SavedFgColor = color; -} + if (!viaAccelSetMode(pDstPixmap->drawable.bitsPerPixel, tdc)) + return FALSE; + if (!viaAccelPlaneMaskHelper(tdc, planeMask)) + return FALSE; + viaAccelTransparentHelper(tdc, cb, 0x0, 0x0, TRUE); + + return TRUE; +} static void -VIASubsequentSolidFillRect( - ScrnInfoPtr pScrn, - int x, - int y, - int w, - int h) +viaExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, + int width, int height) { + ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; VIAPtr pVia = VIAPTR(pScrn); - ViaCBuffer *buf = &pVia->cBuf; ViaTwodContext *tdc = &pVia->td; + CARD32 srcOffset = tdc->srcOffset; + CARD32 dstOffset = exaGetPixmapOffset(pDstPixmap); - if (!w || !h) - return; - - COND_CLEAR_CBUFFER( buf, pVia); - CBUFFER(buf,VIA_REG_GEMODE, tdc->mode); - /* Set Src and Dst base address and pitch, pitch is qword */ - CBUFFER(buf,VIA_REG_SRCBASE, 0x0); - CBUFFER(buf,VIA_REG_DSTBASE, 0x0); - CBUFFER(buf,VIA_REG_PITCH, VIA_PITCH_ENABLE | - ((pScrn->displayWidth * pScrn->bitsPerPixel >> 3) >> 3) | - (((pScrn->displayWidth * pScrn->bitsPerPixel >> 3) >> 3) << 16)); + RING_VARS; - CBUFFER(buf,VIA_REG_DSTPOS, ((y << 16) | x)); - CBUFFER(buf,VIA_REG_DIMENSION, (((h - 1) << 16) | (w - 1))); - CBUFFER(buf,VIA_REG_FGCOLOR, pVia->SavedFgColor); - CBUFFER(buf,VIA_REG_GECMD, pVia->SavedCmd); - dispatchCBufferAGP(pVia, buf); + if (!width || !height) + return; + viaAccelCopyHelper(cb, srcX, srcY, dstX, dstY, width, height, + srcOffset, dstOffset, tdc->mode, tdc->srcPitch, + exaGetPixmapPitch(pDstPixmap), tdc->cmd); + ADVANCE_RING; } - -/* - * The meaning of the two pattern paremeters to Setup & Subsequent for - * Mono8x8Patterns varies depending on the flag bits. We specify - * HW_PROGRAMMED_BITS, which means our hardware can handle 8x8 patterns - * without caching in the frame buffer. Thus, Setup gets the pattern bits. - * There is no way with BCI to rotate an 8x8 pattern, so we do NOT specify - * HW_PROGRAMMED_ORIGIN. XAA wil rotate it for us and pass the rotated - * pattern to both Setup and Subsequent. If we DID specify PROGRAMMED_ORIGIN, - * then Setup would get the unrotated pattern, and Subsequent gets the - * origin values. - */ - +#ifdef VIA_DEBUG_COMPOSITE static void -VIASetupForMono8x8PatternFill( - ScrnInfoPtr pScrn, - int pattern0, - int pattern1, - int fg, - int bg, - int rop, - unsigned planemask) +viaExaCompositePictDesc(PicturePtr pict, char *string, int n) { - VIAPtr pVia = VIAPTR(pScrn); - int cmd; + char format[20]; + char size[20]; - cmd = VIA_GEC_BLT | VIA_GEC_PAT_REG | VIA_GEC_PAT_MONO | - (XAAGetPatternROP(rop) << 24); + if (!pict) { + snprintf(string, n, "None"); + return; + } - if (bg == -1) { - /* transparent mono pattern */ - cmd |= VIA_GEC_MPAT_TRANS; + switch (pict->format) { + case PICT_x8r8g8b8: + snprintf(format, 20, "RGB8888"); + break; + case PICT_a8r8g8b8: + snprintf(format, 20, "ARGB8888"); + break; + case PICT_r5g6b5: + snprintf(format, 20, "RGB565 "); + break; + case PICT_x1r5g5b5: + snprintf(format, 20, "RGB555 "); + break; + case PICT_a8: + snprintf(format, 20, "A8 "); + break; + case PICT_a1: + snprintf(format, 20, "A1 "); + break; + default: + snprintf(format, 20, "0x%x", (int)pict->format); + break; } - pVia->SavedCmd = cmd; - pVia->SavedFgColor = fg; - pVia->SavedBgColor = bg; - pVia->SavedPattern0 = pattern0; - pVia->SavedPattern1 = pattern1; -} + snprintf(size, 20, "%dx%d%s", pict->pDrawable->width, + pict->pDrawable->height, pict->repeat ? " R" : ""); + snprintf(string, n, "0x%lx: fmt %s (%s)", (long)pict->pDrawable, format, + size); +} static void -VIASubsequentMono8x8PatternFillRect( - ScrnInfoPtr pScrn, - int patOffx, - int patOffy, - int x, - int y, - int w, - int h) -{ - VIAPtr pVia = VIAPTR(pScrn); - CARD32 dwPatOffset; - ViaCBuffer *buf = &pVia->cBuf; - ViaTwodContext *tdc = &pVia->td; - - if (!w || !h) - return; - - dwPatOffset = ((patOffy & 0x7) << 29) | ((patOffx & 0x7) << 26); +viaExaPrintComposite(CARD8 op, + PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst) +{ + char sop[20]; + char srcdesc[40], maskdesc[40], dstdesc[40]; - COND_CLEAR_CBUFFER( buf, pVia); - CBUFFER(buf,VIA_REG_GEMODE, tdc->mode); - /* Set Src and Dst base address and pitch, pitch is qword */ - CBUFFER(buf,VIA_REG_SRCBASE, 0x0); - CBUFFER(buf,VIA_REG_DSTBASE, 0x0); - CBUFFER(buf,VIA_REG_PITCH, VIA_PITCH_ENABLE | - ((pScrn->displayWidth * pScrn->bitsPerPixel >> 3) >> 3) | - (((pScrn->displayWidth * pScrn->bitsPerPixel >> 3) >> 3) << 16)); + switch (op) { + case PictOpSrc: + sprintf(sop, "Src"); + break; + case PictOpOver: + sprintf(sop, "Over"); + break; + default: + sprintf(sop, "0x%x", (int)op); + break; + } - CBUFFER(buf,VIA_REG_DSTPOS, ((y << 16) | x)); - CBUFFER(buf,VIA_REG_DIMENSION, (((h - 1) << 16) | (w - 1))); - CBUFFER(buf,VIA_REG_PATADDR, dwPatOffset); - CBUFFER(buf,VIA_REG_FGCOLOR, pVia->SavedFgColor); - CBUFFER(buf,VIA_REG_BGCOLOR, pVia->SavedBgColor); - CBUFFER(buf,VIA_REG_MONOPAT0, pVia->SavedPattern0); - CBUFFER(buf,VIA_REG_MONOPAT1, pVia->SavedPattern1); - CBUFFER(buf,VIA_REG_GECMD, pVia->SavedCmd); - dispatchCBufferAGP(pVia, buf); + viaExaCompositePictDesc(pSrc, srcdesc, 40); + viaExaCompositePictDesc(pMask, maskdesc, 40); + viaExaCompositePictDesc(pDst, dstdesc, 40); + ErrorF("Composite fallback: op %s, \n" + " src %s, \n" + " mask %s, \n" + " dst %s, \n", sop, srcdesc, maskdesc, dstdesc); } +#endif -static void -VIASetupForColor8x8PatternFill( - ScrnInfoPtr pScrn, - int patternx, - int patterny, - int rop, - unsigned planemask, - int trans_color) -{ - VIAPtr pVia = VIAPTR(pScrn); - int cmd; +/* + * Helper for bitdepth expansion. + */ - cmd = VIA_GEC_BLT | (XAAGetPatternROP(rop) << 24); +static CARD32 +viaBitExpandHelper(CARD32 component, CARD32 bits) +{ + CARD32 tmp, mask; - pVia->SavedCmd = cmd; - pVia->SavedPatternAddr = (patternx * pVia->Bpp + patterny * pVia->Bpl); + mask = (1 << (8 - bits)) - 1; + tmp = component << (8 - bits); + return ((component & 1) ? tmp | mask : tmp); } +/* + * Extract the components from a pixel of format "format" to an + * argb8888 pixel. This is used to extract data from one-pixel repeat pixmaps. + * Assumes little endian. + */ static void -VIASubsequentColor8x8PatternFillRect( - ScrnInfoPtr pScrn, - int patOffx, - int patOffy, - int x, - int y, - int w, - int h) -{ - VIAPtr pVia = VIAPTR(pScrn); - CARD32 dwPatAddr; - ViaCBuffer *buf = &pVia->cBuf; - ViaTwodContext *tdc = &pVia->td; +viaPixelARGB8888(unsigned format, void *pixelP, CARD32 * argb8888) +{ + CARD32 bits, shift, pixel, bpp; - if (!w || !h) - return; + bpp = PICT_FORMAT_BPP(format); - dwPatAddr = (pVia->SavedPatternAddr >> 3) | - ((patOffy & 0x7) << 29) | ((patOffx & 0x7) << 26); + if (bpp <= 8) { + pixel = *((CARD8 *) pixelP); + } else if (bpp <= 16) { + pixel = *((CARD16 *) pixelP); + } else { + pixel = *((CARD32 *) pixelP); + } + + switch (PICT_FORMAT_TYPE(format)) { + case PICT_TYPE_A: + bits = PICT_FORMAT_A(format); + *argb8888 = viaBitExpandHelper(pixel & ((1 << bits) - 1), bits) << 24; + return; + case PICT_TYPE_ARGB: + shift = 0; + bits = PICT_FORMAT_B(format); + *argb8888 = viaBitExpandHelper(pixel & ((1 << bits) - 1), bits); + shift += bits; + bits = PICT_FORMAT_G(format); + *argb8888 |= + viaBitExpandHelper((pixel >> shift) & ((1 << bits) - 1), + bits) << 8; + shift += bits; + bits = PICT_FORMAT_R(format); + *argb8888 |= + viaBitExpandHelper((pixel >> shift) & ((1 << bits) - 1), + bits) << 16; + shift += bits; + bits = PICT_FORMAT_A(format); + *argb8888 |= ((bits) ? + viaBitExpandHelper((pixel >> shift) & ((1 << bits) - 1), + bits) : 0xFF) << 24; + return; + case PICT_TYPE_ABGR: + shift = 0; + bits = PICT_FORMAT_B(format); + *argb8888 = viaBitExpandHelper(pixel & ((1 << bits) - 1), bits) << 16; + shift += bits; + bits = PICT_FORMAT_G(format); + *argb8888 |= + viaBitExpandHelper((pixel >> shift) & ((1 << bits) - 1), + bits) << 8; + shift += bits; + bits = PICT_FORMAT_R(format); + *argb8888 |= + viaBitExpandHelper((pixel >> shift) & ((1 << bits) - 1), bits); + shift += bits; + bits = PICT_FORMAT_A(format); + *argb8888 |= ((bits) ? + viaBitExpandHelper((pixel >> shift) & ((1 << bits) - 1), + bits) : 0xFF) << 24; + return; + default: + break; + } + return; +} - /* Set Src and Dst base address and pitch, pitch is qword */ - COND_CLEAR_CBUFFER( buf, pVia); - CBUFFER(buf,VIA_REG_GEMODE, tdc->mode); - CBUFFER(buf,VIA_REG_SRCBASE, 0x0); - CBUFFER(buf,VIA_REG_DSTBASE, 0x0); - CBUFFER(buf,VIA_REG_PITCH, VIA_PITCH_ENABLE | - ((pScrn->displayWidth * pScrn->bitsPerPixel >> 3) >> 3) | - (((pScrn->displayWidth * pScrn->bitsPerPixel >> 3) >> 3) << 16)); +/* + * Check if the above function will work. + */ - CBUFFER(buf,VIA_REG_DSTPOS, ((y << 16) | x)); - CBUFFER(buf,VIA_REG_DIMENSION, (((h - 1) << 16) | (w - 1))); - CBUFFER(buf,VIA_REG_PATADDR, dwPatAddr); - CBUFFER(buf,VIA_REG_GECMD, pVia->SavedCmd); - dispatchCBufferAGP(pVia, buf); +static Bool +viaExpandablePixel(int format) +{ + int formatType = PICT_FORMAT_TYPE(format); + return (formatType == PICT_TYPE_A || + formatType == PICT_TYPE_ABGR || formatType == PICT_TYPE_ARGB); } -static void -VIASetupForCPUToScreenColorExpandFill( - ScrnInfoPtr pScrn, - int fg, - int bg, - int rop, - unsigned planemask) +/* + * Check if we need to force upload of the whole 3D state (if other clients or) + * subsystems have touched the 3D engine). Also tell DRI clients and subsystems * that we have touched the 3D engine. + */ + +static Bool +viaCheckUpload(ScrnInfoPtr pScrn, Via3DState * v3d) { - VIAPtr pVia = VIAPTR(pScrn); - int cmd; - ViaCBuffer *buf = &pVia->cBuf; - ViaTwodContext *tdc = &pVia->td; + VIAPtr pVia = VIAPTR(pScrn); + Bool forceUpload; - cmd = VIA_GEC_BLT | VIA_GEC_SRC_SYS | VIA_GEC_SRC_MONO | - (XAAGetCopyROP(rop) << 24); + forceUpload = (pVia->lastToUpload != v3d); + pVia->lastToUpload = v3d; - if (bg == -1) { - cmd |= VIA_GEC_MSRC_TRANS; +#ifdef XF86DRI + if (pVia->directRenderingEnabled) { + volatile drm_via_sarea_t *saPriv = (drm_via_sarea_t *) + DRIGetSAREAPrivate(pScrn->pScreen); + int myContext = DRIGetContext(pScrn->pScreen); + + forceUpload = forceUpload || (saPriv->ctxOwner != myContext); + saPriv->ctxOwner = myContext; } +#endif + return forceUpload; +} - pVia->SavedCmd = cmd; - pVia->SavedFgColor = fg; - pVia->SavedBgColor = bg; +static Bool +viaOrder(CARD32 val, CARD32 * shift) +{ + *shift = 0; - /* Disable Transparent Bitblt */ - CLEAR_CBUFFER( buf, pVia); - CBUFFER(buf,VIA_REG_GEMODE, tdc->mode); - CBUFFER(buf,VIA_REG_KEYCONTROL, 0x0); + while (val > (1 << *shift)) + (*shift)++; + return (val == (1 << *shift)); } +#ifdef XF86DRI -static void -VIASubsequentScanlineCPUToScreenColorExpandFill( - ScrnInfoPtr pScrn, - int x, - int y, - int w, - int h, - int skipleft) +/* + * Use PCI DMA if we can. If the system alignments don't match we're using + * an aligned bounce buffer for pipelined PCI DMA and memcpy. + * throughput for large transfers is around 65 MB/s. + */ + +static Bool +viaExaDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, + char *dst, int dst_pitch) { + ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; VIAPtr pVia = VIAPTR(pScrn); - ViaCBuffer *buf = &pVia->cBuf; - ViaTwodContext *tdc = &pVia->td; - - /* XAA will be sending bitmap data next. */ - /* We should probably wait for empty/idle here. */ + drm_via_dmablit_t blit[2], *curBlit; + unsigned srcPitch = exaGetPixmapPitch(pSrc); + unsigned wBytes = (pSrc->drawable.bitsPerPixel * w + 7) >> 3; + unsigned srcOffset; + int err, buf, height, i; + char *bounceAligned = NULL; + unsigned bouncePitch = 0; + Bool sync[2], useBounceBuffer; + unsigned totSize; - if (skipleft) { - VIASetClippingRectangle(pScrn, (x + skipleft), y, (x + w - 1), (y + h -1)); + if (!w || !h) + return TRUE; + + srcOffset = x * pSrc->drawable.bitsPerPixel; + if (srcOffset & 3) + return FALSE; + srcOffset = exaGetPixmapOffset(pSrc) + y * srcPitch + (srcOffset >> 3); + + totSize = wBytes * h; + + exaWaitSync(pScrn->pScreen); + if (totSize < VIA_MIN_DOWNLOAD) { + bounceAligned = (char *)pVia->FBBase + srcOffset; + while (h--) { + memcpy(dst, bounceAligned, wBytes); + dst += dst_pitch; + bounceAligned += srcPitch; + } + return TRUE; } - /* Set Src and Dst base address and pitch, pitch is qword */ - COND_CLEAR_CBUFFER( buf, pVia); - CBUFFER(buf,VIA_REG_GEMODE, tdc->mode); - CBUFFER(buf,VIA_REG_SRCBASE, 0x0); - CBUFFER(buf,VIA_REG_DSTBASE, 0x0); - CBUFFER(buf,VIA_REG_PITCH, VIA_PITCH_ENABLE | - ((pScrn->displayWidth * pScrn->bitsPerPixel >> 3) >> 3) | - (((pScrn->displayWidth * pScrn->bitsPerPixel >> 3) >> 3) << 16)); + if (!pVia->directRenderingEnabled) + return FALSE; - CBUFFER(buf,VIA_REG_SRCPOS, 0); - CBUFFER(buf,VIA_REG_DSTPOS, ((y << 16) | x)); - CBUFFER(buf,VIA_REG_DIMENSION, (((h - 1) << 16) | (w - 1))); - CBUFFER(buf,VIA_REG_FGCOLOR, pVia->SavedFgColor); - CBUFFER(buf,VIA_REG_BGCOLOR, pVia->SavedBgColor); - CBUFFER(buf,VIA_REG_GECMD, pVia->SavedCmd); - dispatchCBuffer(pVia, buf); + if ((srcPitch & 3) || (srcOffset & 3)) { + ErrorF("VIA EXA download src_pitch misaligned\n"); + return FALSE; + } -} + useBounceBuffer = (((unsigned long)dst & 15) || (dst_pitch & 15)); -#if 0 /* Buggy. Temporarily disabled 2005-01-23 */ -static void -VIASetupForScreenToScreenColorExpand( - ScrnInfoPtr pScrn, - int fg, - int bg, - int rop, - unsigned int planemask) -{ - VIAPtr pVia = VIAPTR(pScrn); - int cmd; - ViaCBuffer *buf = &pVia->cBuf; + height = h; + + if (useBounceBuffer) { + bounceAligned = (char *)(((unsigned long)pVia->dBounce + 15) & ~15); + bouncePitch = (dst_pitch + 15) & ~15; + height = VIA_DMA_DL_SIZE / bouncePitch; + } - cmd = VIA_GEC_BLT | VIA_GEC_SRC_MONO | (XAAGetCopyROP(rop) << 24); + sync[0] = FALSE; + sync[1] = FALSE; + buf = 0; + err = 0; + + while (h && !err) { + curBlit = blit + buf; + + curBlit->num_lines = (h > height) ? height : h; + h -= curBlit->num_lines; + curBlit->line_length = wBytes; + curBlit->fb_addr = srcOffset; + curBlit->fb_stride = srcPitch; + curBlit->mem_addr = (unsigned char *) + ((useBounceBuffer) ? bounceAligned + VIA_DMA_DL_SIZE * buf : dst); + curBlit->mem_stride = (useBounceBuffer) ? bouncePitch : dst_pitch; + curBlit->to_fb = 0; +#if (VIA_DRM_VERSION >= ((2 << 16) | 9)) + curBlit->flags = 0; +#endif - if (bg == -1) { - cmd |= VIA_GEC_MSRC_TRANS; + while (-EAGAIN == (err = + drmCommandWriteRead(pVia->drmFD, DRM_VIA_DMA_BLIT, curBlit, + sizeof(*curBlit)))) ; + sync[buf] = TRUE; + buf = (buf) ? 0 : 1; + curBlit = blit + buf; + + if (sync[buf] && !err) { + while (-EAGAIN == (err = + drmCommandWrite(pVia->drmFD, DRM_VIA_BLIT_SYNC, + &curBlit->sync, sizeof(curBlit->sync)))) ; + sync[buf] = FALSE; + if (!err && useBounceBuffer) { + for (i = 0; i < curBlit->num_lines; ++i) { + memcpy(dst, curBlit->mem_addr, curBlit->line_length); + dst += dst_pitch; + curBlit->mem_addr += curBlit->mem_stride; + } + } + } + srcOffset += height * srcPitch; } - pVia->SavedCmd = cmd; - pVia->SavedFgColor = fg; - pVia->SavedBgColor = bg; + buf = (buf) ? 0 : 1; + curBlit = blit + buf; + + if (sync[buf] && !err) { + while (-EAGAIN == (err = + drmCommandWrite(pVia->drmFD, DRM_VIA_BLIT_SYNC, + &curBlit->sync, sizeof(curBlit->sync)))) ; + if (!err && useBounceBuffer) { + for (i = 0; i < curBlit->num_lines; ++i) { + memcpy(dst, curBlit->mem_addr, curBlit->line_length); + dst += dst_pitch; + curBlit->mem_addr += curBlit->mem_stride; + } + } + } - /* Disable Transparent Bitblt */ - CLEAR_CBUFFER( buf, pVia); - CBUFFER(buf,VIA_REG_KEYCONTROL, 0x0); + return (err == 0); } +/* + * Upload to framebuffer memory using memcpy to AGP pipelined with a + * 3D engine texture operation from AGP to framebuffer. The AGP buffers (2) + * should be kept rather small for optimal pipelining. + */ -static void -VIASubsequentScreenToScreenColorExpand( - ScrnInfoPtr pScrn, - int x, - int y, - int w, - int h, - int srcx, - int srcy, - int offset) +static Bool +viaExaTexUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, + int src_pitch) { + ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; VIAPtr pVia = VIAPTR(pScrn); - ViaCBuffer *buf = &pVia->cBuf; - ViaTwodContext *tdc = &pVia->td; - CARD32 srcBase,dstBase; + unsigned dstPitch = exaGetPixmapPitch(pDst); + unsigned wBytes = (w * pDst->drawable.bitsPerPixel + 7) >> 3; + unsigned dstOffset; + CARD32 texWidth, texHeight, texPitch; + int format; + char *dst; + int i, sync[2], yOffs, bufH, bufOffs, height; + Bool buf; + Via3DState *v3d = &pVia->v3d; - srcBase = srcy*pVia->Bpl + srcx*pVia->Bpp; - dstBase = y*pVia->Bpl + x*pVia->Bpp; + if (!w || !h) + return TRUE; + + + if (wBytes * h < VIA_MIN_TEX_UPLOAD) { + dstOffset = x * pDst->drawable.bitsPerPixel; + if (dstOffset & 3) + return FALSE; + dst = + (char *)pVia->FBBase + (exaGetPixmapOffset(pDst) + y * dstPitch + + (dstOffset >> 3)); + exaWaitSync(pScrn->pScreen); + + while (h--) { + memcpy(dst, src, wBytes); + dst += dstPitch; + src += src_pitch; + } + return TRUE; + } - x = (dstBase & 31); - srcx = srcBase & 7; + if (!pVia->texAddr) + return FALSE; - switch (pScrn->bitsPerPixel) { - case 16: - x >>= 1; - break; + switch (pDst->drawable.bitsPerPixel) { case 32: - x >>= 2; + format = PICT_a8r8g8b8; + break; + case 16: + format = PICT_r5g6b5; break; default: - break; + return FALSE; } - srcy = 0; - y = 0; + dstOffset = exaGetPixmapOffset(pDst); + viaOrder(wBytes, &texPitch); + if (texPitch < 3) + texPitch = 3; + height = VIA_AGP_UPL_SIZE >> texPitch; + if (height > 1024) + height = 1024; + texPitch = 1 << texPitch; + viaOrder(w, &texWidth); + texWidth = 1 << texWidth; + + texHeight = height << 1; + bufOffs = texPitch * height; + + v3d->setDestination(v3d, dstOffset, dstPitch, format); + v3d->setDrawing(v3d, 0x0c, 0xFFFFFFFF, 0x000000FF, 0x00); + v3d->setFlags(v3d, 1, TRUE, TRUE, FALSE); + if (!v3d->setTexture(v3d, 0, pVia->texOffset + pVia->agpAddr, texPitch, + texWidth, texHeight, format, via_single, via_single, via_src, + TRUE)) + return FALSE; + + v3d->emitState(v3d, &pVia->cb, viaCheckUpload(pScrn, v3d)); + v3d->emitClipRect(v3d, &pVia->cb, 0, 0, pDst->drawable.width, + pDst->drawable.height); + + buf = 1; + yOffs = 0; + sync[0] = -1; + sync[1] = -1; + + while (h) { + buf = (buf) ? 0 : 1; + bufH = (h > height) ? height : h; + dst = pVia->texAddr + ((buf) ? bufOffs : 0); + + if (sync[buf] >= 0) + viaAccelWaitMarker(pScrn->pScreen, sync[buf]); + + for (i = 0; i < bufH; ++i) { + memcpy(dst, src, wBytes); + dst += texPitch; + src += src_pitch; + } + + v3d->emitQuad(v3d, &pVia->cb, x, y + yOffs, 0, (buf) ? height : 0, 0, + 0, w, bufH); + + sync[buf] = viaAccelMarkSync(pScrn->pScreen); + + h -= bufH; + yOffs += bufH; + } - /* Set Src and Dst base address and pitch, pitch is qword */ - COND_CLEAR_CBUFFER( buf, pVia); - CBUFFER(buf,VIA_REG_GEMODE, tdc->mode); - CBUFFER(buf,VIA_REG_KEYCONTROL, 0x0); - CBUFFER(buf,VIA_REG_SRCBASE, (srcBase & ~7) >> 3); - CBUFFER(buf,VIA_REG_DSTBASE, (dstBase & ~31) >> 3); - CBUFFER(buf,VIA_REG_PITCH, VIA_PITCH_ENABLE | - ((pScrn->displayWidth * pScrn->bitsPerPixel >> 3) >> 3) | - (((pScrn->displayWidth * pScrn->bitsPerPixel >> 3) >> 3) << 16)); - CBUFFER(buf,VIA_REG_SRCPOS, (srcx << 6) | offset); - CBUFFER(buf,VIA_REG_DSTPOS, ((y << 16) | x)); - CBUFFER(buf,VIA_REG_DIMENSION, (((h - 1) << 16) | (w - 1))); - CBUFFER(buf,VIA_REG_FGCOLOR, pVia->SavedFgColor); - CBUFFER(buf,VIA_REG_BGCOLOR, pVia->SavedBgColor); - CBUFFER(buf,VIA_REG_GECMD, pVia->SavedCmd); + if (sync[buf] >= 0) + viaAccelWaitMarker(pScrn->pScreen, sync[buf]); - dispatchCBufferAGP(pVia, buf); + return TRUE; } +/* + * I'm not sure PCI DMA upload is necessary. Seems buggy for widths below 65, and I'd guess that in + * most situations, CPU direct writes are faster. Use DMA only when alignments match. At least + * it saves some CPU cycles. + */ + +static Bool +viaExaUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, + int src_pitch) +{ + ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; + VIAPtr pVia = VIAPTR(pScrn); + drm_via_dmablit_t blit; + unsigned dstPitch = exaGetPixmapPitch(pDst); + unsigned wBytes = (w * pDst->drawable.bitsPerPixel + 7) >> 3; + unsigned dstOffset; + char *dst; + int err; + + dstOffset = x * pDst->drawable.bitsPerPixel; + if (dstOffset & 3) + return FALSE; + dstOffset = exaGetPixmapOffset(pDst) + y * dstPitch + (dstOffset >> 3); + + if (wBytes * h < VIA_MIN_UPLOAD || wBytes < 65) { + dst = (char *)pVia->FBBase + dstOffset; + + exaWaitSync(pScrn->pScreen); + while (h--) { + memcpy(dst, src, wBytes); + dst += dstPitch; + src += src_pitch; + } + return TRUE; + } + + if (!pVia->directRenderingEnabled) + return FALSE; + + if (((unsigned long)src & 15) || (src_pitch & 15)) + return FALSE; + + if ((dstPitch & 3) || (dstOffset & 3)) + return FALSE; + + blit.line_length = wBytes; + blit.num_lines = h; + blit.fb_addr = dstOffset; + blit.fb_stride = dstPitch; + blit.mem_addr = (unsigned char *) src; + blit.mem_stride = src_pitch; + blit.to_fb = 1; +#if (VIA_DRM_VERSION >= ((2 << 16) | 9)) + blit.flags = 0; #endif -static void -VIASetupForImageWrite( - ScrnInfoPtr pScrn, - int rop, - unsigned planemask, - int trans_color, - int bpp, - int depth) -{ - VIAPtr pVia = VIAPTR(pScrn); - int cmd; - ViaCBuffer *buf = &pVia->cBuf; - ViaTwodContext *tdc = &pVia->td; + exaWaitSync(pScrn->pScreen); + while (-EAGAIN == (err = + drmCommandWriteRead(pVia->drmFD, DRM_VIA_DMA_BLIT, &blit, + sizeof(blit)))) ; + if (err < 0) + return FALSE; - /* We don't record bpp and depth because we assume bpp is equal to - bpp of screen. Is this assume correct ? */ + while (-EAGAIN == (err = drmCommandWrite(pVia->drmFD, DRM_VIA_BLIT_SYNC, + &blit.sync, sizeof(blit.sync)))) ; + return (err == 0); +} - cmd = VIA_GEC_BLT | VIA_GEC_SRC_SYS | (XAAGetCopyROP(rop) << 24); +#endif - pVia->SavedCmd = cmd; +static Bool +viaExaUploadToScratch(PixmapPtr pSrc, PixmapPtr pDst) +{ - CLEAR_CBUFFER( buf, pVia); - CBUFFER(buf,VIA_REG_GEMODE, tdc->mode); - if (trans_color != -1) { - /* Transparent Bitblt */ - CBUFFER(buf,VIA_REG_SRCCOLORKEY, trans_color); - CBUFFER(buf,VIA_REG_KEYCONTROL, 0x4000); + ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; + VIAPtr pVia = VIAPTR(pScrn); + char *src, *dst; + unsigned w, wBytes, srcPitch, h; + CARD32 dstPitch; + + if (!pVia->scratchAddr) + return FALSE; + + *pDst = *pSrc; + w = pSrc->drawable.width; + h = pSrc->drawable.height; + wBytes = (w * pSrc->drawable.bitsPerPixel + 7) >> 3; + + viaOrder(wBytes, &dstPitch); + dstPitch = 1 << dstPitch; + if (dstPitch < 8) + dstPitch = 8; + if (dstPitch * h > VIA_SCRATCH_SIZE) { + ErrorF("EXA UploadToScratch Failed\n"); + return FALSE; } - else { - /* Disable Transparent Bitblt */ - CBUFFER(buf,VIA_REG_KEYCONTROL, 0x0); + + pDst->devKind = dstPitch; + pDst->devPrivate.ptr = dst = pVia->scratchAddr; + src = pSrc->devPrivate.ptr; + srcPitch = exaGetPixmapPitch(pSrc); + + /* + * Copying to AGP needs not be HW accelerated. + * and if scratch is in FB, we are without DRI and hw accel. + */ + + while (h--) { + memcpy(dst, src, wBytes); + dst += dstPitch; + src += srcPitch; } -} + return TRUE; +} -static void -VIASubsequentImageWriteRect( - ScrnInfoPtr pScrn, - int x, - int y, - int w, - int h, - int skipleft) +static Bool +viaExaCheckComposite(int op, PicturePtr pSrcPicture, + PicturePtr pMaskPicture, PicturePtr pDstPicture) { - VIAPtr pVia = VIAPTR(pScrn); - ViaCBuffer *buf = &pVia->cBuf; - ViaTwodContext *tdc = &pVia->td; - if (skipleft) { - VIASetClippingRectangle(pScrn, (x + skipleft), y, (x + w - 1), (y + h -1)); + ScrnInfoPtr pScrn = xf86Screens[pDstPicture->pDrawable->pScreen->myNum]; + VIAPtr pVia = VIAPTR(pScrn); + Via3DState *v3d = &pVia->v3d; + + /* + * Reject small composites early. They are done much faster in software. + */ + + if (!pSrcPicture->repeat && + pSrcPicture->pDrawable->width * + pSrcPicture->pDrawable->height < VIA_MIN_COMPOSITE) + return FALSE; + + if (pMaskPicture && + !pMaskPicture->repeat && + pMaskPicture->pDrawable->width * + pMaskPicture->pDrawable->height < VIA_MIN_COMPOSITE) + return FALSE; + + if (pMaskPicture && pMaskPicture->componentAlpha) + return FALSE; + + if (!v3d->opSupported(op)) { +#ifdef VIA_DEBUG_COMPOSITE + ErrorF("Operator not supported\n"); + viaExaPrintComposite(op, pSrcPicture, pMaskPicture, pDstPicture); +#endif + return FALSE; } - /* Set Src and Dst base address and pitch, pitch is qword */ - COND_CLEAR_CBUFFER( buf, pVia); - CBUFFER(buf,VIA_REG_GEMODE, tdc->mode); - CBUFFER(buf,VIA_REG_SRCBASE, 0x0); - CBUFFER(buf,VIA_REG_DSTBASE, 0x0); - CBUFFER(buf,VIA_REG_PITCH, VIA_PITCH_ENABLE | - ((pScrn->displayWidth * pScrn->bitsPerPixel >> 3) >> 3) | - (((pScrn->displayWidth * pScrn->bitsPerPixel >> 3) >> 3) << 16)); + /* + * FIXME: A8 destination formats are currently not supported and does + * not seem supported by the hardware, althought there are some left-over + * register settings apparent in the via_3d_reg.h file. We need to fix this + * (if important), by using component ARGB8888 operations with bitmask. + */ - CBUFFER(buf,VIA_REG_SRCPOS, 0); - CBUFFER(buf,VIA_REG_DSTPOS, ((y << 16) | x)); - CBUFFER(buf,VIA_REG_DIMENSION, (((h - 1) << 16) | (w - 1))); - CBUFFER(buf,VIA_REG_GECMD, pVia->SavedCmd); - dispatchCBuffer(pVia, buf); + if (!v3d->dstSupported(pDstPicture->format)) { +#ifdef VIA_DEBUG_COMPOSITE + ErrorF("Destination format not supported:\n"); + viaExaPrintComposite(op, pSrcPicture, pMaskPicture, pDstPicture); +#endif + return FALSE; + } -} + if (v3d->texSupported(pSrcPicture->format)) { + if (pMaskPicture && (PICT_FORMAT_A(pMaskPicture->format) == 0 || + !v3d->texSupported(pMaskPicture->format))) { +#ifdef VIA_DEBUG_COMPOSITE + ErrorF("Mask format not supported:\n"); + viaExaPrintComposite(op, pSrcPicture, pMaskPicture, pDstPicture); +#endif + return FALSE; + } + return TRUE; + } +#ifdef VIA_DEBUG_COMPOSITE + ErrorF("Src format not supported:\n"); + viaExaPrintComposite(op, pSrcPicture, pMaskPicture, pDstPicture); +#endif + return FALSE; +} -/* Setup for XAA solid lines. */ -static void -VIASetupForSolidLine( - ScrnInfoPtr pScrn, - int color, - int rop, - unsigned int planemask) +static Bool +viaIsAGP(VIAPtr pVia, PixmapPtr pPix, unsigned long *offset) { - VIAPtr pVia = VIAPTR(pScrn); - int cmd; - ViaCBuffer *buf = &pVia->cBuf; - ViaTwodContext *tdc = &pVia->td; - - CLEAR_CBUFFER( buf, pVia); - CBUFFER(buf,VIA_REG_GEMODE, tdc->mode); - /* we move VIA_GEC_LINE from here to the place firing command */ - cmd = VIA_GEC_FIXCOLOR_PAT | (XAAGetPatternROP(rop) << 24); +#ifdef XF86DRI + unsigned long offs; - pVia->SavedCmd = cmd; - pVia->SavedFgColor = color; + if (pVia->directRenderingEnabled && !pVia->IsPCI) { + offs = (unsigned long)pPix->devPrivate.ptr - + (unsigned long)pVia->agpMappedAddr; - /* set solid line pattern */ - CBUFFER(buf,VIA_REG_MONOPAT0, 0xFF); - CBUFFER(buf,VIA_REG_FGCOLOR, pVia->SavedFgColor); + if ((offs - pVia->scratchOffset) < VIA_SCRATCH_SIZE) { + *offset = offs + pVia->agpAddr; + return TRUE; + } + } +#endif + return FALSE; +} +static Bool +viaIsOffscreen(VIAPtr pVia, PixmapPtr pPix) +{ + return ((unsigned long)pPix->devPrivate.ptr - + (unsigned long)pVia->FBBase) < pVia->videoRambytes; } +static Bool +viaExaPrepareComposite(int op, PicturePtr pSrcPicture, + PicturePtr pMaskPicture, PicturePtr pDstPicture, + PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst) +{ + CARD32 height, width; + ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; + VIAPtr pVia = VIAPTR(pScrn); + Via3DState *v3d = &pVia->v3d; + int curTex = 0; + ViaTexBlendingModes srcMode; + Bool isAGP; + unsigned long offset; -static void -VIASubsequentSolidTwoPointLine( - ScrnInfoPtr pScrn, - int x1, - int y1, - int x2, - int y2, - int flags) -{ - VIAPtr pVia = VIAPTR(pScrn); - int dx, dy, cmd, tmp, error = 1; - ViaCBuffer *buf = &pVia->cBuf; - ViaTwodContext *tdc = &pVia->td; + v3d->setDestination(v3d, exaGetPixmapOffset(pDst), + exaGetPixmapPitch(pDst), pDstPicture->format); + v3d->setCompositeOperator(v3d, op); + v3d->setDrawing(v3d, 0x0c, 0xFFFFFFFF, 0x000000FF, 0xFF); - COND_CLEAR_CBUFFER( buf, pVia); - CBUFFER(buf,VIA_REG_GEMODE, tdc->mode); - CBUFFER(buf,VIA_REG_FGCOLOR, pVia->SavedFgColor); - cmd = pVia->SavedCmd | VIA_GEC_LINE; + viaOrder(pSrc->drawable.width, &width); + viaOrder(pSrc->drawable.height, &height); - dx = x2 - x1; - if (dx < 0) { - dx = -dx; - cmd |= VIA_GEC_DECX; /* line will be drawn from right */ - error = 0; + /* + * For One-pixel repeat mask pictures we avoid using multitexturing by + * modifying the src's texture blending equation and feed the pixel + * value as a constant alpha for the src's texture. Multitexturing on the + * unichromes seem somewhat slow, so this speeds up translucent windows. + */ + + srcMode = via_src; + pVia->maskP = NULL; + if (pMaskPicture && + (pMaskPicture->pDrawable->height == 1) && + (pMaskPicture->pDrawable->width == 1) && + pMaskPicture->repeat && viaExpandablePixel(pMaskPicture->format)) { + pVia->maskP = pMask->devPrivate.ptr; + pVia->maskFormat = pMaskPicture->format; + pVia->componentAlpha = pMaskPicture->componentAlpha; + srcMode = + (pMaskPicture-> + componentAlpha) ? via_src_onepix_comp_mask : via_src_onepix_mask; } - dy = y2 - y1; - if (dy < 0) { - dy = -dy; - cmd |= VIA_GEC_DECY; /* line will be drawn from bottom */ + /* + * One-Pixel repeat src pictures go as solid color instead of textures. + * Speeds up window shadows. + */ + + pVia->srcP = NULL; + if (pSrcPicture && + (pSrcPicture->pDrawable->height == 1) && + (pSrcPicture->pDrawable->width == 1) && + pSrcPicture->repeat && viaExpandablePixel(pSrcPicture->format)) { + pVia->srcP = pSrc->devPrivate.ptr; + pVia->srcFormat = pSrcPicture->format; } - if (dy > dx) { - tmp = dy; - dy = dx; - dx = tmp; /* Swap 'dx' and 'dy' */ - cmd |= VIA_GEC_Y_MAJOR; /* Y major line */ + /* + * Exa should be smart enough to eliminate this IN operation. + */ + + if (pVia->srcP && pVia->maskP) { + ErrorF + ("Bad one-pixel IN composite operation. EXA needs to be smarter.\n"); + return FALSE; } - if (flags & OMIT_LAST) { - cmd |= VIA_GEC_LASTPIXEL_OFF; + if (!pVia->srcP) { + offset = exaGetPixmapOffset(pSrc); + isAGP = viaIsAGP(pVia, pSrc, &offset); + if (!isAGP && !viaIsOffscreen(pVia, pSrc)) + return FALSE; + if (!v3d->setTexture(v3d, curTex++, offset, + exaGetPixmapPitch(pSrc), 1 << width, 1 << height, + pSrcPicture->format, via_repeat, via_repeat, + srcMode, isAGP)) + return FALSE; } - /* Set Src and Dst base address and pitch, pitch is qword */ - CBUFFER(buf,VIA_REG_SRCBASE, 0x0); - CBUFFER(buf,VIA_REG_DSTBASE, 0x0); - CBUFFER(buf,VIA_REG_PITCH, VIA_PITCH_ENABLE | - ((pScrn->displayWidth * pScrn->bitsPerPixel >> 3) >> 3) | - (((pScrn->displayWidth * pScrn->bitsPerPixel >> 3) >> 3) << 16)); + if (pMaskPicture && !pVia->maskP) { + offset = exaGetPixmapOffset(pMask); + isAGP = viaIsAGP(pVia, pMask, &offset); + if (!isAGP && !viaIsOffscreen(pVia, pMask)) + return FALSE; + viaOrder(pMask->drawable.width, &width); + viaOrder(pMask->drawable.height, &height); + if (!v3d->setTexture(v3d, curTex++, offset, + exaGetPixmapPitch(pMask), 1 << width, 1 << height, + pMaskPicture->format, via_repeat, via_repeat, + (pMaskPicture->componentAlpha) ? via_comp_mask : via_mask, + isAGP)) + return FALSE; + } - /* major = 2*dmaj, minor = 2*dmin, err = -dmaj - ((bias >> octant) & 1) */ - /* K1 = 2*dmin K2 = 2*(dmin - dmax) */ - /* Error Term = (StartX<EndX) ? (2*dmin - dmax - 1) : (2*(dmin - dmax)) */ - CBUFFER(buf,VIA_REG_LINE_K1K2, ((((dy << 1) & 0x3fff) << 16)| - (((dy - dx) << 1) & 0x3fff))); - CBUFFER(buf,VIA_REG_LINE_XY, ((y1 << 16) | x1)); - CBUFFER(buf,VIA_REG_DIMENSION, dx); - CBUFFER(buf,VIA_REG_LINE_ERROR, (((dy << 1) - dx - error) & 0x3fff)); - CBUFFER(buf,VIA_REG_GECMD, cmd); - dispatchCBufferAGP(pVia, buf); + v3d->setFlags(v3d, curTex, FALSE, TRUE, TRUE); + v3d->emitState(v3d, &pVia->cb, viaCheckUpload(pScrn, v3d)); + v3d->emitClipRect(v3d, &pVia->cb, 0, 0, pDst->drawable.width, + pDst->drawable.height); + return TRUE; } - -/* Subsequent XAA solid horizontal and vertical lines */ static void -VIASubsequentSolidHorVertLine( - ScrnInfoPtr pScrn, - int x, - int y, - int len, - int dir) +viaExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, + int dstX, int dstY, int width, int height) { - VIAPtr pVia = VIAPTR(pScrn); - ViaCBuffer *buf = &pVia->cBuf; - ViaTwodContext *tdc = &pVia->td; - - /* Set Src and Dst base address and pitch, pitch is qword */ - COND_CLEAR_CBUFFER( buf, pVia); - CBUFFER(buf,VIA_REG_GEMODE, tdc->mode); - CBUFFER(buf,VIA_REG_FGCOLOR, pVia->SavedFgColor); - CBUFFER(buf,VIA_REG_SRCBASE, 0x0); - CBUFFER(buf,VIA_REG_DSTBASE, 0x0); - CBUFFER(buf,VIA_REG_PITCH, VIA_PITCH_ENABLE | - ((pScrn->displayWidth * pScrn->bitsPerPixel >> 3) >> 3) | - (((pScrn->displayWidth * pScrn->bitsPerPixel >> 3) >> 3) << 16)); + ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; + VIAPtr pVia = VIAPTR(pScrn); + Via3DState *v3d = &pVia->v3d; + CARD32 col; - if (dir == DEGREES_0) { - CBUFFER(buf,VIA_REG_DSTPOS, ((y << 16) | x)); - CBUFFER(buf,VIA_REG_DIMENSION, (len - 1)); - CBUFFER(buf,VIA_REG_GECMD, pVia->SavedCmd | VIA_GEC_BLT); + if (pVia->maskP) { + viaPixelARGB8888(pVia->maskFormat, pVia->maskP, &col); + v3d->setTexBlendCol(v3d, 0, pVia->componentAlpha, col); } - else { - CBUFFER(buf,VIA_REG_DSTPOS, ((y << 16) | x)); - CBUFFER(buf,VIA_REG_DIMENSION, ((len - 1) << 16)); - CBUFFER(buf,VIA_REG_GECMD, pVia->SavedCmd | VIA_GEC_BLT); + if (pVia->srcP) { + viaPixelARGB8888(pVia->srcFormat, pVia->srcP, &col); + v3d->setDrawing(v3d, 0x0c, 0xFFFFFFFF, col & 0x00FFFFFF, col >> 24); + srcX = maskX; + srcY = maskY; } - dispatchCBufferAGP(pVia, buf); + + if (pVia->maskP || pVia->srcP) + v3d->emitState(v3d, &pVia->cb, viaCheckUpload(pScrn, v3d)); + + v3d->emitQuad(v3d, &pVia->cb, dstX, dstY, srcX, srcY, maskX, maskY, width, + height); } -static void -VIASetupForDashedLine( - ScrnInfoPtr pScrn, - int fg, - int bg, - int rop, - unsigned int planemask, - int length, - unsigned char *pattern) -{ - VIAPtr pVia = VIAPTR(pScrn); - int cmd; - CARD32 pat = *(CARD32 *)pattern; - ViaCBuffer *buf = &pVia->cBuf; - ViaTwodContext *tdc = &pVia->td; +/* + * Init EXA. Alignments are 2D engine constraints. + */ - cmd = VIA_GEC_LINE | VIA_GEC_FIXCOLOR_PAT | (XAAGetPatternROP(rop) << 24); +static ExaDriverPtr +viaInitExa(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + VIAPtr pVia = VIAPTR(pScrn); + ExaDriverPtr pExa = (ExaDriverPtr) xnfcalloc(sizeof(ExaDriverRec), 1); + + if (!pExa) + return NULL; + + pExa->card.memoryBase = pVia->FBBase; + pExa->card.memorySize = pVia->FBFreeEnd; + pExa->card.offScreenBase = pScrn->virtualY * pVia->Bpl; + pExa->card.pixmapOffsetAlign = 32; + pExa->card.pixmapPitchAlign = 16; + pExa->card.flags = EXA_OFFSCREEN_PIXMAPS | EXA_OFFSCREEN_ALIGN_POT; + pExa->card.maxX = 2047; + pExa->card.maxY = 2047; + + pExa->accel.WaitMarker = viaAccelWaitMarker; + pExa->accel.MarkSync = viaAccelMarkSync; + pExa->accel.PrepareSolid = viaExaPrepareSolid; + pExa->accel.Solid = viaExaSolid; + pExa->accel.DoneSolid = viaExaDoneSolidCopy; + pExa->accel.PrepareCopy = viaExaPrepareCopy; + pExa->accel.Copy = viaExaCopy; + pExa->accel.DoneCopy = viaExaDoneSolidCopy; - if (bg == -1) { - /* transparent mono pattern */ - cmd |= VIA_GEC_MPAT_TRANS; +#ifdef XF86DRI + if (pVia->directRenderingEnabled) { +#ifdef linux + if ((pVia->drmVerMajor > 2) || + ((pVia->drmVerMajor == 2) && (pVia->drmVerMinor >= 7))) { + if (pVia->Chipset != VIA_K8M800) + pExa->accel.UploadToScreen = viaExaUploadToScreen; + pExa->accel.DownloadFromScreen = viaExaDownloadFromScreen; + } +#endif + if (pVia->Chipset == VIA_K8M800) + pExa->accel.UploadToScreen = viaExaTexUploadToScreen; } +#endif - pVia->SavedCmd = cmd; - pVia->SavedFgColor = fg; - pVia->SavedBgColor = bg; + pExa->accel.UploadToScratch = viaExaUploadToScratch; - switch (length) { - case 2: pat |= pat << 2; /* fall through */ - case 4: pat |= pat << 4; /* fall through */ - case 8: pat |= pat << 8; /* fall through */ - case 16: pat |= pat << 16; + if (!pVia->noComposite) { + pExa->accel.CheckComposite = viaExaCheckComposite; + pExa->accel.PrepareComposite = viaExaPrepareComposite; + pExa->accel.Composite = viaExaComposite; + pExa->accel.DoneComposite = viaExaDoneSolidCopy; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO,"[EXA] Disabling EXA accelerated composite.\n"); } - pVia->SavedPattern0 = pat; - CLEAR_CBUFFER( buf, pVia); - CBUFFER(buf,VIA_REG_GEMODE, tdc->mode); - CBUFFER(buf,VIA_REG_FGCOLOR, pVia->SavedFgColor); - CBUFFER(buf,VIA_REG_BGCOLOR, pVia->SavedBgColor); - CBUFFER(buf,VIA_REG_MONOPAT0, pVia->SavedPattern0); + if (!exaDriverInit(pScreen, pExa)) { + xfree(pExa); + return NULL; + } + viaInit3DState(&pVia->v3d); + return pExa; } +#endif /* VIA_HAVE_EXA */ -static void -VIASubsequentDashedTwoPointLine( - ScrnInfoPtr pScrn, - int x1, - int y1, - int x2, - int y2, - int flags, - int phase) -{ - VIAPtr pVia = VIAPTR(pScrn); - int dx, dy, cmd, tmp, error = 1; - ViaCBuffer *buf = &pVia->cBuf; - ViaTwodContext *tdc = &pVia->td; +/* + * Acceleration init function. Sets up offscreen memory disposition, initializes engines + * and acceleration method. + */ - COND_CLEAR_CBUFFER( buf, pVia); - CBUFFER(buf,VIA_REG_GEMODE, tdc->mode); - CBUFFER(buf,VIA_REG_FGCOLOR, pVia->SavedFgColor); - cmd = pVia->SavedCmd; +Bool +viaInitAccel(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + VIAPtr pVia = VIAPTR(pScrn); + BoxRec AvailFBArea; + int maxY; - dx = x2 - x1; - if (dx < 0) { - dx = -dx; - cmd |= VIA_GEC_DECX; /* line will be drawn from right */ - error = 0; + pVia->VQStart = 0; + if (((pVia->FBFreeEnd - pVia->FBFreeStart) >= VIA_VQ_SIZE) && + pVia->VQEnable) { + pVia->VQStart = pVia->FBFreeEnd - VIA_VQ_SIZE; + pVia->VQEnd = pVia->VQStart + VIA_VQ_SIZE - 1; + pVia->FBFreeEnd -= VIA_VQ_SIZE; } - dy = y2 - y1; - if (dy < 0) { - dy = -dy; - cmd |= VIA_GEC_DECY; /* line will be drawn from bottom */ + viaInitialize2DEngine(pScrn); + + if (pVia->hwcursor) { + pVia->FBFreeEnd -= VIA_CURSOR_SIZE; + pVia->CursorStart = pVia->FBFreeEnd; } - if (dy > dx) { - tmp = dy; - dy = dx; - dx = tmp; /* Swap 'dx' and 'dy' */ - cmd |= VIA_GEC_Y_MAJOR; /* Y major line */ + /* + * Sync marker space. + */ + + pVia->FBFreeEnd -= 32; + pVia->markerOffset = (pVia->FBFreeEnd + 31) & ~31; + pVia->markerBuf = (CARD32 *) ((char *)pVia->FBBase + pVia->markerOffset); + *pVia->markerBuf = 0; + pVia->curMarker = 0; + pVia->lastMarkerRead = 0; + +#ifdef VIA_HAVE_EXA +#ifdef XF86DRI + pVia->texAddr = NULL; + pVia->dBounce = NULL; + pVia->scratchAddr = NULL; +#endif + if (pVia->useEXA) { + pVia->exaDriverPtr = viaInitExa(pScreen); + if (!pVia->exaDriverPtr) { + + /* + * Docs recommend turning off also Xv here, but we handle this + * case with the old linear offscreen FB manager through + * VIAInitLinear. + */ + + pVia->NoAccel = TRUE; + return FALSE; + } + + pVia->driSize = (pVia->FBFreeEnd - pVia->FBFreeStart) / 2; + if (pVia->driSize > (16 * 1024 * 1024)) + pVia->driSize = 16 * 1024 * 1024; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO,"[EXA] Enabled EXA acceleration.\n"); + return TRUE; } +#endif - if (flags & OMIT_LAST) { - cmd |= VIA_GEC_LASTPIXEL_OFF; + AvailFBArea.x1 = 0; + AvailFBArea.y1 = 0; + AvailFBArea.x2 = pScrn->displayWidth; + + /* + * Memory distribution for XAA is tricky. We'd like to make the + * pixmap cache no larger than 3 x visible screen size, otherwise + * XAA may get slow for some undetermined reason. + */ + +#ifdef XF86DRI + if (pVia->directRenderingEnabled) { + pVia->driSize = (pVia->FBFreeEnd - pVia->FBFreeStart) / 2; + maxY = pScrn->virtualY + (pVia->driSize / pVia->Bpl); + } else +#endif + { + maxY = pVia->FBFreeEnd / pVia->Bpl; } + if (maxY > 4 * pScrn->virtualY) + maxY = 4 * pScrn->virtualY; + + pVia->FBFreeStart = (maxY + 1) * pVia->Bpl; + + AvailFBArea.y2 = maxY; + xf86InitFBManager(pScreen, &AvailFBArea); + VIAInitLinear(pScreen); + + pVia->driSize = (pVia->FBFreeEnd - pVia->FBFreeStart - pVia->Bpl); - /* Set Src and Dst base address and pitch, pitch is qword */ - CBUFFER(buf,VIA_REG_SRCBASE, 0x0); - CBUFFER(buf,VIA_REG_DSTBASE, 0x0); - CBUFFER(buf,VIA_REG_PITCH, VIA_PITCH_ENABLE | - ((pScrn->displayWidth * pScrn->bitsPerPixel >> 3) >> 3) | - (((pScrn->displayWidth * pScrn->bitsPerPixel >> 3) >> 3) << 16)); + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using %d lines for offscreen memory.\n", + AvailFBArea.y2 - pScrn->virtualY)); - /* major = 2*dmaj, minor = 2*dmin, err = -dmaj - ((bias >> octant) & 1) */ - /* K1 = 2*dmin K2 = 2*(dmin - dmax) */ - /* Error Term = (StartX<EndX) ? (2*dmin - dmax - 1) : (2*(dmin - dmax)) */ - CBUFFER(buf,VIA_REG_LINE_K1K2, ((((dy << 1) & 0x3fff) << 16)| - (((dy - dx) << 1) & 0x3fff))); - CBUFFER(buf,VIA_REG_LINE_XY, ((y1 << 16) | x1)); - CBUFFER(buf,VIA_REG_DIMENSION, dx); - CBUFFER(buf,VIA_REG_LINE_ERROR, (((dy << 1) - dx - error) & 0x3fff) | 0xFF0000); - CBUFFER(buf,VIA_REG_GECMD, cmd); - dispatchCBufferAGP(pVia, buf); + return viaInitXAA(pScreen); } +/* + * Free used acceleration resorces. + */ -static void -VIASetClippingRectangle( - ScrnInfoPtr pScrn, - int x1, - int y1, - int x2, - int y2) +void +viaExitAccel(ScreenPtr pScreen) { + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; VIAPtr pVia = VIAPTR(pScrn); - ViaCBuffer *buf = &pVia->cBuf; - ViaTwodContext *tdc = &pVia->td; - - COND_CLEAR_CBUFFER( buf, pVia); - pVia->justSetup = 0; - CBUFFER(buf,VIA_REG_GEMODE, tdc->mode); -#ifdef DEBUG_EXTRA - ErrorF("ClipRect, (%4d,%4d)-(%4d,%4d) \n", x1, y1, x2, y2 ); -#endif - CBUFFER(buf,VIA_REG_CLIPTL, ((y1 << 16) | x1)); - CBUFFER(buf,VIA_REG_CLIPBR, ((y2 << 16) | x2)); - pVia->SavedCmd |= VIA_GEC_CLIP_ENABLE; - dispatchCBufferAGP(pVia, buf); + viaAccelSync(pScrn); + viaTearDownCBuffer(&pVia->cb); +#ifdef VIA_HAVE_EXA + if (pVia->useEXA) { +#ifdef XF86DRI + if (pVia->directRenderingEnabled) { + if (pVia->texAddr) { + drmCommandWrite(pVia->drmFD, DRM_VIA_FREEMEM, + &pVia->texAGPBuffer, sizeof(drm_via_mem_t)); + pVia->texAddr = NULL; + } + if (pVia->scratchAddr && !pVia->IsPCI && + ((unsigned long)pVia->scratchAddr - + (unsigned long)pVia->agpMappedAddr == pVia->scratchOffset)) { + drmCommandWrite(pVia->drmFD, DRM_VIA_FREEMEM, + &pVia->scratchAGPBuffer, sizeof(drm_via_mem_t)); + pVia->scratchAddr = NULL; + } + } + if (pVia->dBounce) + xfree(pVia->dBounce); +#endif + if (pVia->scratchAddr) { + exaOffscreenFree(pScreen, pVia->scratchFBBuffer); + pVia->scratchAddr = NULL; + } + if (pVia->exaDriverPtr) { + exaDriverFini(pScreen); + } + xfree(pVia->exaDriverPtr); + pVia->exaDriverPtr = NULL; + return; + } +#endif + if (pVia->AccelInfoRec) { + XAADestroyInfoRec(pVia->AccelInfoRec); + pVia->AccelInfoRec = NULL; + } } -static void VIADisableClipping(ScrnInfoPtr pScrn) +/* + * Allocate command buffer and + * buffers for accelerated upload, download and + * the EXA scratch area. The Scratch area resides primarily in + * AGP memory but reverts to FB if AGP is not available. + */ + +void +viaFinishInitAccel(ScreenPtr pScreen) { + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; VIAPtr pVia = VIAPTR(pScrn); -#ifdef DEBUG_EXTRA - ErrorF("Kill ClipRect\n"); +#ifdef VIA_HAVE_EXA +#ifdef XF86DRI + int size, ret; + + if (pVia->directRenderingEnabled && pVia->useEXA) { + + pVia->dBounce = xcalloc(VIA_DMA_DL_SIZE * 2, 1); + + if (!pVia->IsPCI) { + + /* + * Allocate upload and scratch space. + */ + + if (pVia->exaDriverPtr->accel.UploadToScreen == + viaExaTexUploadToScreen) { + + size = VIA_AGP_UPL_SIZE * 2 + 32; + pVia->texAGPBuffer.context = 1; + pVia->texAGPBuffer.size = size; + pVia->texAGPBuffer.type = VIA_MEM_AGP; + ret = + drmCommandWriteRead(pVia->drmFD, DRM_VIA_ALLOCMEM, + &pVia->texAGPBuffer, sizeof(drm_via_mem_t)); + + if (ret || size != pVia->texAGPBuffer.size) { + pVia->texAGPBuffer.size = 0; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Allocated %u kiB of AGP memory for system to frame-buffer transfer.\n", + size / 1024); + pVia->texOffset = (pVia->texAGPBuffer.offset + 31) & ~31; + pVia->texAddr = + (char *)pVia->agpMappedAddr + pVia->texOffset; + } + + } + + size = VIA_SCRATCH_SIZE + 32; + pVia->scratchAGPBuffer.context = 1; + pVia->scratchAGPBuffer.size = size; + pVia->scratchAGPBuffer.type = VIA_MEM_AGP; + ret = + drmCommandWriteRead(pVia->drmFD, DRM_VIA_ALLOCMEM, + &pVia->scratchAGPBuffer, sizeof(drm_via_mem_t)); + if (ret || size != pVia->scratchAGPBuffer.size) { + pVia->scratchAGPBuffer.size = 0; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Allocated %u kiB of AGP memory for EXA scratch area.\n", + size / 1024); + pVia->scratchOffset = + (pVia->scratchAGPBuffer.offset + 31) & ~31; + pVia->scratchAddr = + (char *)pVia->agpMappedAddr + pVia->scratchOffset; + } + + } + } #endif + if (!pVia->scratchAddr && pVia->useEXA) { + + pVia->scratchFBBuffer = + exaOffscreenAlloc(pScreen, VIA_SCRATCH_SIZE, 32, TRUE, NULL, + NULL); + if (pVia->scratchFBBuffer) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Allocated %u kiB of framebuffer memory for EXA scratch area.\n", + VIA_SCRATCH_SIZE / 1024); + pVia->scratchOffset = pVia->scratchFBBuffer->offset; + pVia->scratchAddr = (char *)pVia->FBBase + pVia->scratchOffset; + } - pVia->SavedCmd &= ~VIA_GEC_CLIP_ENABLE; + } +#endif + if (Success != viaSetupCBuffer(pScrn, &pVia->cb, 0)) { + pVia->NoAccel = TRUE; + viaExitAccel(pScreen); + return; + } } /* - * + * DGA accelerated functions go here and let them be independent of acceleration + * method. */ -void -ViaVQDisable(ScrnInfoPtr pScrn) + +void +viaAccelBlitRect(ScrnInfoPtr pScrn, int srcx, int srcy, int w, int h, + int dstx, int dsty) { VIAPtr pVia = VIAPTR(pScrn); - VIASETREG(VIA_REG_TRANSET, 0x00FE0000); - VIASETREG(VIA_REG_TRANSPACE, 0x00000004); + ViaTwodContext *tdc = &pVia->td; + unsigned dstOffset = pScrn->fbOffset + dsty * pVia->Bpl; + unsigned srcOffset = pScrn->fbOffset + srcy * pVia->Bpl; + + RING_VARS; + + if (!w || !h) + return; + + if (!pVia->NoAccel) { + + int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1; + int ydir = (srcy < dsty) ? -1 : 1; + CARD32 cmd = VIA_GEC_BLT | VIAACCELCOPYROP(GXcopy); + + if (xdir < 0) + cmd |= VIA_GEC_DECX; + if (ydir < 0) + cmd |= VIA_GEC_DECY; + + viaAccelSetMode(pScrn->bitsPerPixel, tdc); + viaAccelTransparentHelper(tdc, cb, 0x0, 0x0, FALSE); + viaAccelCopyHelper(cb, srcx, 0, dstx, 0, w, h, srcOffset, dstOffset, + tdc->mode, pVia->Bpl, pVia->Bpl, cmd); + pVia->accelMarker = viaAccelMarkSync(pScrn->pScreen); + ADVANCE_RING; + } +} + +void +viaAccelFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned long color) +{ + VIAPtr pVia = VIAPTR(pScrn); + unsigned dstBase = pScrn->fbOffset + y * pVia->Bpl; + ViaTwodContext *tdc = &pVia->td; + CARD32 cmd = VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT | + VIAACCELPATTERNROP(GXcopy); + RING_VARS; + + if (!w || !h) + return; + + if (!pVia->NoAccel) { + viaAccelSetMode(pScrn->bitsPerPixel, tdc); + viaAccelTransparentHelper(tdc, cb, 0x0, 0x0, FALSE); + viaAccelSolidHelper(cb, x, 0, w, h, dstBase, tdc->mode, + pVia->Bpl, color, cmd); + pVia->accelMarker = viaAccelMarkSync(pScrn->pScreen); + ADVANCE_RING; + } +} + +void +viaAccelSyncMarker(ScrnInfoPtr pScrn) +{ + VIAPtr pVia = VIAPTR(pScrn); + + viaAccelWaitMarker(pScrn->pScreen, pVia->accelMarker); } diff --git a/src/via_cursor.c b/src/via_cursor.c index 29c3f4b..1ab1133 100644 --- a/src/via_cursor.c +++ b/src/via_cursor.c @@ -115,7 +115,7 @@ VIALoadCursorImage(ScrnInfoPtr pScrn, unsigned char* src) VIAPtr pVia = VIAPTR(pScrn); CARD32 dwCursorMode; - VIAAccelSync(pScrn); + viaAccelSync(pScrn); dwCursorMode = VIAGETREG(VIA_REG_CURSOR_MODE); diff --git a/src/via_dga.c b/src/via_dga.c index 2331915..3c13674 100644 --- a/src/via_dga.c +++ b/src/via_dga.c @@ -36,9 +36,6 @@ static Bool VIADGAOpenFramebuffer(ScrnInfoPtr, char **, unsigned char **, static Bool VIADGASetMode(ScrnInfoPtr, DGAModePtr); static int VIADGAGetViewport(ScrnInfoPtr); static void VIADGASetViewport(ScrnInfoPtr, int, int, int); -static void VIADGAFillRect(ScrnInfoPtr, int, int, int, int, unsigned long); -static void VIADGABlitRect(ScrnInfoPtr, int, int, int, int, int, int); - static DGAFunctionRec VIADGAFuncs = { @@ -47,9 +44,9 @@ DGAFunctionRec VIADGAFuncs = { VIADGASetMode, VIADGASetViewport, VIADGAGetViewport, - VIAAccelSync, - VIADGAFillRect, - VIADGABlitRect, + viaAccelSyncMarker, + viaAccelFillRect, + viaAccelBlitRect, NULL /* BlitTransRect */ }; @@ -303,39 +300,6 @@ VIADGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags) pVia->DGAViewportStatus = 0; /* MGAAdjustFrame loops until finished */ } - -static void -VIADGAFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, unsigned long color) -{ - VIAPtr pVia = VIAPTR(pScrn); - - if (pVia->AccelInfoRec) { - (*pVia->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0); - (*pVia->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); - SET_SYNC_FLAG(pVia->AccelInfoRec); - } -} - - -static void -VIADGABlitRect(ScrnInfoPtr pScrn, int srcx, int srcy, int w, int h, - int dstx, int dsty) -{ - VIAPtr pVia = VIAPTR(pScrn); - - if (pVia->AccelInfoRec) { - int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1; - int ydir = (srcy < dsty) ? -1 : 1; - - (*pVia->AccelInfoRec->SetupForScreenToScreenCopy)( - pScrn, xdir, ydir, GXcopy, ~0, -1); - (*pVia->AccelInfoRec->SubsequentScreenToScreenCopy)( - pScrn, srcx, srcy, dstx, dsty, w, h); - SET_SYNC_FLAG(pVia->AccelInfoRec); - } -} - - static Bool VIADGAOpenFramebuffer( ScrnInfoPtr pScrn, diff --git a/src/via_dri.c b/src/via_dri.c index 7f64d21..2caf4d0 100644 --- a/src/via_dri.c +++ b/src/via_dri.c @@ -160,13 +160,8 @@ VIADRIRingBufferInit(ScrnInfoPtr pScrn) if (pVia->agpEnable) { drm_via_dma_init_t ringBufInit; - drmVersionPtr drmVer; - if (NULL == (drmVer = drmGetVersion(pVia->drmFD))) { - return FALSE; - } - - if (((drmVer->version_major <= 1) && (drmVer->version_minor <= 3))) { + if (((pVia->drmVerMajor <= 1) && (pVia->drmVerMinor <= 3))) { return FALSE; } @@ -333,11 +328,40 @@ static Bool VIADRIAgpInit(ScreenPtr pScreen, VIAPtr pVia) } static Bool VIADRIFBInit(ScreenPtr pScreen, VIAPtr pVia) { - int FBSize = pVia->FBFreeEnd-pVia->FBFreeStart; - int FBOffset = pVia->FBFreeStart; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + int FBSize = pVia->driSize; + int FBOffset; VIADRIPtr pVIADRI = pVia->pDRIInfo->devPrivate; + + if (FBSize < pVia->Bpl) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[drm] No DRM framebuffer heap available.\n"); + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[drm] Please increase the frame buffer\n"); + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[drm] memory area in BIOS. Disabling DRI.\n"); + return FALSE; + } + if (FBSize < 3*(pScrn->virtualY * pVia->Bpl)) { + xf86DrvMsg(pScreen->myNum, X_WARNING, + "[drm] The DRM Heap and Pixmap cache memory could be too small\n"); + xf86DrvMsg(pScreen->myNum, X_WARNING, + "[drm] for optimal performance. Please increase the frame buffer\n"); + xf86DrvMsg(pScreen->myNum, X_WARNING, + "[drm] memory area in BIOS.\n"); + } + + pVia->driOffScreenMem.pool = 0; + if (Success != VIAAllocLinear(&pVia->driOffScreenMem, pScrn, FBSize)) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[drm] failed to allocate offscreen frame buffer area\n"); + return FALSE; + } + + FBOffset = pVia->driOffScreenMem.base; + pVIADRI->fbOffset = FBOffset; - pVIADRI->fbSize = pVia->videoRambytes; + pVIADRI->fbSize = FBSize; { drm_via_fb_t fb; @@ -351,9 +375,7 @@ static Bool VIADRIFBInit(ScreenPtr pScreen, VIAPtr pVia) return FALSE; } else { xf86DrvMsg(pScreen->myNum, X_INFO, - "[drm] FBFreeStart= 0x%08x FBFreeEnd= 0x%08x " - "FBSize= 0x%08x\n", - pVia->FBFreeStart, pVia->FBFreeEnd, FBSize); + "[drm] Using %d bytes for DRM memory heap.\n", FBSize); return TRUE; } } @@ -594,6 +616,7 @@ Bool VIADRIScreenInit(ScreenPtr pScreen) VIAPtr pVia = VIAPTR(pScrn); DRIInfoPtr pDRIInfo; VIADRIPtr pVIADRI; + drmVersionPtr drmVer; /* if symbols or version check fails, we still want this to be NULL */ pVia->pDRIInfo = NULL; @@ -697,6 +720,15 @@ Bool VIADRIScreenInit(ScreenPtr pScreen) return FALSE; } + if (NULL == (drmVer = drmGetVersion(pVia->drmFD))) { + VIADRICloseScreen(pScreen); + return FALSE; + } + pVia->drmVerMajor = drmVer->version_major; + pVia->drmVerMinor = drmVer->version_minor; + pVia->drmVerPL = drmVer->version_patchlevel; + drmFreeVersion(drmVer); + if (!(VIAInitVisualConfigs(pScreen))) { VIADRICloseScreen(pScreen); @@ -739,8 +771,8 @@ VIADRICloseScreen(ScreenPtr pScreen) drmAgpRelease(pVia->drmFD); } - DRICloseScreen(pScreen); + VIAFreeLinear(&pVia->driOffScreenMem); if (pVia->pDRIInfo) { if ((pVIADRI = (VIADRIPtr) pVia->pDRIInfo->devPrivate)) { diff --git a/src/via_driver.c b/src/via_driver.c index 4cd5958..90bee5c 100644 --- a/src/via_driver.c +++ b/src/via_driver.c @@ -124,6 +124,9 @@ typedef enum { OPTION_PCI_BURST, OPTION_PCI_RETRY, OPTION_NOACCEL, +#ifdef VIA_HAVE_EXA + OPTION_ACCELMETHOD, +#endif OPTION_SWCURSOR, OPTION_HWCURSOR, OPTION_SHADOW_FB, @@ -143,7 +146,8 @@ typedef enum { OPTION_DISABLEIRQ, OPTION_TVDEFLICKER, OPTION_AGP_DMA, - OPTION_2D_DMA + OPTION_2D_DMA, + OPTION_EXA_NOCOMPOSITE } VIAOpts; @@ -156,6 +160,9 @@ static OptionInfoRec VIAOptions[] = #endif /* HAVE_DEBUG */ {OPTION_VBEMODES, "VBEModes", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE}, +#ifdef VIA_HAVE_EXA + {OPTION_ACCELMETHOD, "AccelMethod", OPTV_STRING, {0}, FALSE}, +#endif /* VIA_HAVE_EXA */ {OPTION_HWCURSOR, "HWCursor", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_SWCURSOR, "SWCursor", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE}, @@ -176,6 +183,7 @@ static OptionInfoRec VIAOptions[] = {OPTION_DISABLEIRQ, "DisableIRQ", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_AGP_DMA, "EnableAGPDMA", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_2D_DMA, "NoAGPFor2D", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_EXA_NOCOMPOSITE, "ExaNoComposite", OPTV_BOOLEAN, {0}, FALSE}, {-1, NULL, OPTV_NONE, {0}, FALSE} }; @@ -262,6 +270,20 @@ static const char *xaaSymbols[] = { NULL }; +#ifdef VIA_HAVE_EXA +static const char *exaSymbols[] = { + "exaGetVersion", + "exaDriverInit", + "exaDriverFini", + "exaOffscreenAlloc", + "exaOffscreenFree", + "exaGetPixmapPitch", + "exaGetPixmapOffset", + "exaWaitSync", + NULL +}; +#endif + static const char *shadowSymbols[] = { "ShadowFBInit", NULL @@ -355,6 +377,9 @@ static pointer VIASetup(pointer module, pointer opts, int *errmaj, int *errmin) fbSymbols, ramdacSymbols, xaaSymbols, +#ifdef VIA_HAVE_EXA + exaSymbols, +#endif shadowSymbols, vbeSymbols, i2cSymbols, @@ -843,6 +868,35 @@ static Bool VIAPreInit(ScrnInfoPtr pScrn, int flags) else { pVia->NoAccel = FALSE; } +#ifdef VIA_HAVE_EXA + if(!pVia->NoAccel) { + from = X_DEFAULT; + if((s = (char *)xf86GetOptValString(VIAOptions, OPTION_ACCELMETHOD))) { + if(!xf86NameCmp(s,"XAA")) { + from = X_CONFIG; + pVia->useEXA = FALSE; + } + else if(!xf86NameCmp(s,"EXA")) { + from = X_CONFIG; + pVia->useEXA = TRUE; + } + } + xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration architecture\n", + pVia->useEXA ? "EXA" : "XAA"); + + pVia->noComposite = FALSE; + if (pVia->useEXA) { + if (xf86ReturnOptValBool(VIAOptions, OPTION_EXA_NOCOMPOSITE, FALSE)) { + pVia->noComposite = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Option: ExaNoComposite - Disable Composite acceleration for EXA\n"); + } else { + pVia->noComposite = FALSE; + } + } + + } +#endif /* VIA_HAVE_EXA */ if (pVia->shadowFB && !pVia->NoAccel) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, @@ -1351,7 +1405,7 @@ static Bool VIAPreInit(ScrnInfoPtr pScrn, int flags) NULL, /* list of line pitches */ 256, /* mini line pitch */ 3344, /* max line pitch */ - 16 * pScrn->bitsPerPixel, /* pitch inc (bits) */ + 32*8, /* pitch inc (bits) */ 128, /* min height */ 2508, /* max height */ pScrn->display->virtualX, /* virtual width */ @@ -1398,6 +1452,13 @@ static Bool VIAPreInit(ScrnInfoPtr pScrn, int flags) return FALSE; } xf86LoaderReqSymLists(xaaSymbols, NULL); +#ifdef VIA_HAVE_EXA + if(!xf86LoadSubModule(pScrn, "exa")) { + VIAFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(exaSymbols, NULL); +#endif } if (pVia->hwcursor) { @@ -1475,11 +1536,7 @@ static void VIALeaveVT(int scrnIndex, int flags) DRILock(screenInfo.screens[scrnIndex], 0); #endif - VIAAccelSync(pScrn); - - -#ifdef XF86DRI - if (pVia->directRenderingEnabled) { + viaAccelSync(pScrn); /* * Next line apparently helps fix 3D hang on VT switch. @@ -1488,12 +1545,15 @@ static void VIALeaveVT(int scrnIndex, int flags) hwp->writeSeq(hwp, 0x1A, pVia->SavedReg.SR1A | 0x40); +#ifdef XF86DRI + if (pVia->directRenderingEnabled) { + VIADRIRingBufferCleanup(pScrn); } #endif if (pVia->VQEnable) - ViaVQDisable(pScrn); + viaDisableVQ(pScrn); /* Save video status and turn off all video activities */ @@ -1875,7 +1935,8 @@ VIAScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; vgaHWPtr hwp = VGAHWPTR(pScrn); VIAPtr pVia = VIAPTR(pScrn); - + + pScrn->pScreen = pScreen; DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIAScreenInit\n")); if (!VIAMapFB(pScrn)) @@ -1961,30 +2022,9 @@ VIAScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) fbPictureInit(pScreen, 0, 0); if (!pVia->NoAccel) { - VIAInitAccel(pScreen); - } else { - /* - * This is needed because xf86InitFBManagerLinear in VIAInitLinear - * needs xf86InitFBManager to have been initialized, and - * xf86InitFBManager needs at least one line of free memory to - * work. This is only for Xv in Noaccel part, and since Xv is in some - * sense accelerated, it might be a better idea to disable it - * altogether. - */ - BoxRec AvailFBArea; - - AvailFBArea.x1 = 0; - AvailFBArea.y1 = 0; - AvailFBArea.x2 = pScrn->displayWidth; - AvailFBArea.y2 = pScrn->virtualY + 1; - /* - * Update FBFreeStart also for other memory managers, since - * we steal one line to make xf86InitFBManager work. - */ - pVia->FBFreeStart = (AvailFBArea.y2 + 1) * pVia->Bpl; - xf86InitFBManager(pScreen, &AvailFBArea); + viaInitAccel(pScreen); } - + miInitializeBackingStore(pScreen); xf86SetBackingStore(pScreen); /*xf86SetSilkenMouse(pScreen);*/ @@ -2017,11 +2057,6 @@ VIAScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- Palette loaded\n")); - if (!pVia->IsSecondary) - memset(pVia->FBBase, 0x00, pVia->videoRambytes); - - vgaHWBlankScreen(pScrn, TRUE); - pVia->CloseScreen = pScreen->CloseScreen; pScreen->SaveScreen = VIASaveScreen; pScreen->CloseScreen = VIACloseScreen; @@ -2030,20 +2065,61 @@ VIAScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- DPMS set up\n")); DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- Color maps etc. set up\n")); + pVia->agpDMA = FALSE; #ifdef XF86DRI if (pVia->directRenderingEnabled) pVia->directRenderingEnabled = VIADRIFinishScreenInit(pScreen); - if (pVia->directRenderingEnabled) + if (pVia->directRenderingEnabled) { + VIADRIPtr pVIADRI = pVia->pDRIInfo->devPrivate; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering enabled\n"); - else { + pVia->agpDMA = pVia->dma2d && pVIADRI->ringBufActive; + } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering disabled\n"); - VIAInitLinear(pScreen); } -#else - VIAInitLinear(pScreen); #endif + if (!pVia->NoAccel) + viaFinishInitAccel(pScreen); + + if (pVia->NoAccel) { + memset(pVia->FBBase, 0x00, pVia->videoRambytes); + } else { +#ifdef XF86DRI + if (pVia->directRenderingEnabled) + DRILock(screenInfo.screens[scrnIndex], 0); +#endif + viaAccelFillRect(pScrn, pScrn->frameX0, pScrn->frameY0, + pScrn->displayWidth, pScrn->virtualY, + 0x00000000); + viaAccelSyncMarker(pScrn); +#ifdef XF86DRI + if (pVia->directRenderingEnabled) + DRIUnlock(screenInfo.screens[scrnIndex]); +#endif + } + vgaHWBlankScreen(pScrn, TRUE); + + if (pVia->NoAccel) { + + /* + * This is only for Xv in Noaccel path, and since Xv is in some + * sense accelerated, it might be a better idea to disable it + * altogether. + */ + + BoxRec AvailFBArea; + + AvailFBArea.x1 = 0; + AvailFBArea.y1 = 0; + AvailFBArea.x2 = pScrn->displayWidth; + AvailFBArea.y2 = pScrn->virtualY + 1; + pVia->FBFreeStart=(AvailFBArea.y2 + 1)*pVia->Bpl; + xf86InitFBManager(pScreen, &AvailFBArea); + VIAInitLinear(pScreen); + pVia->driSize = (pVia->FBFreeEnd - pVia->FBFreeStart - pVia->Bpl); + } viaInitVideo(pScreen); @@ -2097,6 +2173,7 @@ static int VIAInternalScreenInit(int scrnIndex, ScreenPtr pScreen) FBStart = pVia->FBBase; } + ErrorF("fbScreenInit"); return fbScreenInit(pScreen, FBStart, width, height, pScrn->xDpi, pScrn->yDpi, displayWidth, pScrn->bitsPerPixel); } @@ -2123,9 +2200,9 @@ VIAWriteMode(ScrnInfoPtr pScrn, DisplayModePtr mode) /* Enable the graphics engine. */ if (!pVia->NoAccel) - VIAInitialize2DEngine(pScrn); + viaInitialize2DEngine(pScrn); -#ifdef XF86DRI +#if defined(XF86DRI) || defined(VIA_HAVE_EXA) VIAInitialize3DEngine(pScrn); #endif @@ -2151,15 +2228,11 @@ static Bool VIACloseScreen(int scrnIndex, ScreenPtr pScreen) DRILock(screenInfo.screens[scrnIndex], 0); #endif /* Wait Hardware Engine idle to exit graphical mode */ - VIAAccelSync(pScrn); + viaAccelSync(pScrn); -#ifdef XF86DRI /* Fix 3D Hang after X restart */ - - if (pVia->directRenderingEnabled) hwp->writeSeq(hwp, 0x1A, pVia->SavedReg.SR1A | 0x40); -#endif if (!pVia->IsSecondary) { /* Turn off all video activities */ @@ -2169,16 +2242,13 @@ static Bool VIACloseScreen(int scrnIndex, ScreenPtr pScreen) } if (pVia->VQEnable) - ViaVQDisable(pScrn); + viaDisableVQ(pScrn); } #ifdef XF86DRI if (pVia->directRenderingEnabled) VIADRICloseScreen(pScreen); #endif - if (pVia->AccelInfoRec) { - XAADestroyInfoRec(pVia->AccelInfoRec); - pVia->AccelInfoRec = NULL; - } + viaExitAccel(pScreen); if (pVia->CursorInfoRec) { xf86DestroyCursorInfoRec(pVia->CursorInfoRec); pVia->CursorInfoRec = NULL; @@ -2279,7 +2349,7 @@ VIASwitchMode(int scrnIndex, DisplayModePtr mode, int flags) DRILock(screenInfo.screens[scrnIndex], 0); #endif - VIAAccelSync(pScrn); + viaAccelSync(pScrn); #ifdef XF86DRI if (pVia->directRenderingEnabled) @@ -2287,7 +2357,7 @@ VIASwitchMode(int scrnIndex, DisplayModePtr mode, int flags) #endif if (pVia->VQEnable) - ViaVQDisable(pScrn); + viaDisableVQ(pScrn); if (pVia->pVbe) ret = ViaVbeSetMode(pScrn, mode); @@ -2355,7 +2425,7 @@ static void VIADPMS(ScrnInfoPtr pScrn, int mode, int flags) return; } -#ifdef XF86DRI +#if defined(XF86DRI) || defined(VIA_HAVE_EXA) void VIAInitialize3DEngine(ScrnInfoPtr pScrn) { diff --git a/src/via_driver.h b/src/via_driver.h index 84c8657..fc5a765 100644 --- a/src/via_driver.h +++ b/src/via_driver.h @@ -55,6 +55,8 @@ #include "via_bios.h" #include "via_priv.h" #include "via_swov.h" +#include "via_dmabuffer.h" +#include "via_3d.h" #ifdef XF86DRI #define _XF86DRI_SERVER_ @@ -70,12 +72,24 @@ #define PATCHLEVEL 33 #define VIA_VERSION ((VERSION_MAJOR<<24) | (VERSION_MINOR<<16) | PATCHLEVEL) -#define VIA_MAX_ACCEL_X (2047) -#define VIA_MAX_ACCEL_Y (2047) -#define VIA_PIXMAP_CACHE_SIZE (4 * (VIA_MAX_ACCEL_X + 1) * (VIA_MAX_ACCEL_Y +1)) +#ifdef VIA_HAVE_EXA +#include "exa.h" +#define VIA_AGP_UPL_SIZE (1024*128) +#define VIA_DMA_DL_SIZE (1024*128) +#define VIA_SCRATCH_SIZE (2048*1024) + + /* + * Pixmap sizes below which we don't try to do hw accel. + */ + +#define VIA_MIN_COMPOSITE 1 /*400*/ +#define VIA_MIN_UPLOAD 4000 +#define VIA_MIN_TEX_UPLOAD 400 +#define VIA_MIN_DOWNLOAD 400 +#endif + #define VIA_CURSOR_SIZE (4 * 1024) #define VIA_VQ_SIZE (256 * 1024) -#define VIA_CBUFFERSIZE 512 typedef struct { CARD8 SR08, SR0A, SR0F; @@ -134,15 +148,25 @@ typedef struct { typedef struct _twodContext { CARD32 mode; + CARD32 cmd; + CARD32 fgColor; + CARD32 bgColor; + CARD32 pattern0; + CARD32 pattern1; + CARD32 patternAddr; + CARD32 keyControl; + unsigned srcOffset; + unsigned srcPitch; + unsigned Bpp; + unsigned bytesPPShift; + Bool clipping; + int clipX1; + int clipX2; + int clipY1; + int clipY2; } ViaTwodContext; typedef struct{ - unsigned curPos; - CARD32 buffer[VIA_CBUFFERSIZE]; - int status; -} ViaCBuffer; - -typedef struct{ /* textMode */ CARD8 *state, *pstate; /* SVGA state */ int statePage, stateSize, stateMode; @@ -155,13 +179,13 @@ typedef struct _VIA { VIARegRec SavedReg; xf86CursorInfoPtr CursorInfoRec; int Bpp, Bpl; - unsigned PlaneMask; Bool FirstInit; unsigned long videoRambytes; int videoRamKbytes; int FBFreeStart; int FBFreeEnd; + int driSize; int CursorStart; int VQStart; int VQEnd; @@ -179,11 +203,6 @@ typedef struct _VIA { unsigned char* FBBase; CARD8 MemClk; - /* Private memory pool management */ - int SWOVUsed[MEM_BLOCKS]; /* Free map for SWOV pool */ - unsigned long SWOVPool; /* Base of SWOV pool */ - unsigned long SWOVSize; /* Size of SWOV blocks */ - /* Here are all the Options */ Bool VQEnable; Bool pci_burst; @@ -212,16 +231,38 @@ typedef struct _VIA { /* Support for XAA acceleration */ XAAInfoRecPtr AccelInfoRec; - xRectangle Rect; - CARD32 SavedCmd; - CARD32 SavedFgColor; - CARD32 SavedBgColor; - CARD32 SavedPattern0; - CARD32 SavedPattern1; - CARD32 SavedPatternAddr; - int justSetup; ViaTwodContext td; - ViaCBuffer cBuf; + Via3DState v3d; + Via3DState *lastToUpload; + ViaCommandBuffer cb; + int accelMarker; + CARD32 markerOffset; + CARD32 *markerBuf; + CARD32 curMarker; + CARD32 lastMarkerRead; + Bool agpDMA; +#ifdef VIA_HAVE_EXA + ExaDriverPtr exaDriverPtr; + ExaOffscreenArea *exa_scratch; + unsigned int exa_scratch_next; + Bool useEXA; + void *maskP; + CARD32 maskFormat; + Bool componentAlpha; + void *srcP; + CARD32 srcFormat; + ExaOffscreenArea *scratchFBBuffer; + unsigned scratchOffset; + char * scratchAddr; + Bool noComposite; +#ifdef XF86DRI + drm_via_mem_t scratchAGPBuffer; + drm_via_mem_t texAGPBuffer; + unsigned texOffset; + char * texAddr; + char * dBounce; +#endif +#endif /* BIOS Info Ptr */ VIABIOSInfoPtr pBIOSInfo; @@ -266,6 +307,10 @@ typedef struct _VIA { Bool IsPCI; Bool drixinerama; ViaXvMC xvmc; + int drmVerMajor; + int drmVerMinor; + int drmVerPL; + VIAMem driOffScreenMem; #endif Bool DRIIrqEnable; Bool agpEnable; @@ -318,7 +363,7 @@ typedef struct } VIAEntRec, *VIAEntPtr; /* Prototypes. */ -#ifdef XF86DRI +#if defined(XF86DRI) || defined(VIA_HAVE_EXA) void VIAInitialize3DEngine(ScrnInfoPtr pScrn); #endif @@ -330,10 +375,19 @@ void ViaCursorStore(ScrnInfoPtr pScrn); void ViaCursorRestore(ScrnInfoPtr pScrn); /* In via_accel.c. */ -Bool VIAInitAccel(ScreenPtr); -void VIAInitialize2DEngine(ScrnInfoPtr); -void VIAAccelSync(ScrnInfoPtr); -void ViaVQDisable(ScrnInfoPtr pScrn); +Bool viaInitAccel(ScreenPtr); +void viaInitialize2DEngine(ScrnInfoPtr); +void viaAccelSync(ScrnInfoPtr); +void viaDisableVQ(ScrnInfoPtr); +void viaExitAccel(ScreenPtr); +void viaAccelBlitRect(ScrnInfoPtr, int, int, int, int, int, int); +void viaAccelFillRect(ScrnInfoPtr, int, int, int, int, unsigned long); +void viaAccelSyncMarker(ScrnInfoPtr); +void viaFinishInitAccel(ScreenPtr); +void viaAccelWaitMarker(ScreenPtr, int); +int viaAccelMarkSync(ScreenPtr); + + /* In via_shadow.c */ void ViaShadowFBInit(ScrnInfoPtr pScrn, ScreenPtr pScreen); diff --git a/src/via_memcpy.c b/src/via_memcpy.c index ccf0f07..aa490af 100644 --- a/src/via_memcpy.c +++ b/src/via_memcpy.c @@ -546,7 +546,6 @@ vidCopyFunc viaVidCopyInit( char *copyType, double cpuFreq; VIAPtr pVia = VIAPTR(pScrn); - pScrn->pScreen = pScreen; if (NULL == (cpuInfoFile = fopen("/proc/cpuinfo","r"))) { return libc_YUV42X; } diff --git a/src/via_memory.c b/src/via_memory.c index 95c9dfb..37fbb84 100644 --- a/src/via_memory.c +++ b/src/via_memory.c @@ -43,47 +43,68 @@ #endif /* - * Isolate the wonders of X memory allocation, DRI memory allocation + * Isolate the wonders of X memory allocation and DRI memory allocation * and 4.3 or 4.4 differences in once abstraction * * The pool code indicates who provided the memory * 0 - nobody - * 1 - xf86 linear (Used in 4.4 only - current) + * 1 - xf86 linear * 2 - DRM - * 3 - Preallocated buffer (Used in 4.3 only - removed) */ void VIAFreeLinear(VIAMemPtr mem) { DEBUG(ErrorF("Freed %lu (pool %d)\n", mem->base, mem->pool)); - switch(mem->pool) - { + switch(mem->pool) { + case 0: + return; case 1: +#ifdef VIA_HAVE_EXA + { + VIAPtr pVia = VIAPTR(mem->pScrn); + if (pVia->useEXA && !pVia->NoAccel) { + exaOffscreenFree(mem->pScrn->pScreen, mem->exa); + mem->linear = NULL; + mem->pool = 0; + return; + } + } +#endif xf86FreeOffscreenLinear(mem->linear); mem->linear = NULL; mem->pool = 0; return; case 2: #ifdef XF86DRI - if(drmCommandWrite(mem->drm_fd, DRM_VIA_FREEMEM, + if(drmCommandWriteRead(mem->drm_fd, DRM_VIA_FREEMEM, &mem->drm, sizeof(drm_via_mem_t)) < 0) ErrorF("DRM module failed free.\n"); #endif mem->pool = 0; return; - case 0: - case 3: /* deprecated */ - default: - return; } } - static unsigned long offScreenLinear(VIAMemPtr mem, ScrnInfoPtr pScrn, unsigned long size) { - int depth = (pScrn->bitsPerPixel + 7) >> 3; - /* Make sure we don't truncate requested size */ + int depth = pScrn->bitsPerPixel >> 3; + +#ifdef VIA_HAVE_EXA + VIAPtr pVia = VIAPTR(pScrn); + + if (pVia->useEXA && !pVia->NoAccel) { + + mem->exa = exaOffscreenAlloc(pScrn->pScreen, size, + 32, TRUE, NULL,NULL); + if (mem->exa == NULL) + return BadAlloc; + mem->base = mem->exa->offset; + mem->pool = 1; + return Success; + } +#endif + mem->linear = xf86AllocateOffscreenLinear(pScrn->pScreen, ( size + depth - 1 ) / depth, 32, NULL, NULL, NULL); @@ -98,15 +119,15 @@ static unsigned long offScreenLinear(VIAMemPtr mem, ScrnInfoPtr pScrn, unsigned long VIAAllocLinear(VIAMemPtr mem, ScrnInfoPtr pScrn, unsigned long size) { - if(mem->pool) - ErrorF("VIA Double Alloc.\n"); - #ifdef XF86DRI - { VIAPtr pVia = VIAPTR(pScrn); int ret; + if(mem->pool) + ErrorF("VIA Double Alloc.\n"); + if(pVia->directRenderingEnabled) { + mem->pScrn = pScrn; mem->drm_fd = pVia->drmFD; mem->drm.context = 1; mem->drm.size = size; @@ -114,8 +135,9 @@ unsigned long VIAAllocLinear(VIAMemPtr mem, ScrnInfoPtr pScrn, unsigned long siz ret = drmCommandWriteRead(mem->drm_fd, DRM_VIA_ALLOCMEM, &mem->drm, sizeof(drm_via_mem_t)); if (ret || (size != mem->drm.size)) { + /* - * Try XY Fallback before failing. + * Try X Offsceen fallback before failing. */ if (Success == offScreenLinear(mem, pScrn, size)) @@ -127,15 +149,17 @@ unsigned long VIAAllocLinear(VIAMemPtr mem, ScrnInfoPtr pScrn, unsigned long siz mem->base = mem->drm.offset; mem->pool = 2; DEBUG(ErrorF("Fulfilled via DRI at %lu\n", mem->base)); - return 0; - } + return Success; } -#endif /* XF86DRI */ - +#endif + { + mem->pScrn = pScrn; if (Success == offScreenLinear(mem, pScrn, size)) return Success; ErrorF("Linear memory allocation failed\n"); return BadAlloc; + } + return Success; } void VIAInitLinear(ScreenPtr pScreen) @@ -143,13 +167,15 @@ void VIAInitLinear(ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; VIAPtr pVia = VIAPTR(pScrn); - /* - * In the 44 path we must take care not to truncate offset and size so - * that we get overlaps. If there is available memory below line 2048 - * we use it. - */ +#ifdef VIA_HAVE_EXA + if (pVia->useEXA && !pVia->NoAccel) { + return; + } else +#endif + { unsigned long offset = (pVia->FBFreeStart + pVia->Bpp - 1 ) / pVia->Bpp; - unsigned long size = pVia->FBFreeEnd / pVia->Bpp - offset; + long size = pVia->FBFreeEnd / pVia->Bpp - offset; if (size > 0) xf86InitFBManagerLinear(pScreen, offset, size); + } } diff --git a/src/via_priv.h b/src/via_priv.h index 2f0cf31..325e5f9 100644 --- a/src/via_priv.h +++ b/src/via_priv.h @@ -4,6 +4,9 @@ #ifdef XF86DRI #include "via_drm.h" #endif +#ifdef VIA_HAVE_EXA +#include "exa.h" +#endif /* * Alignment macro functions @@ -116,9 +119,12 @@ typedef struct { int drm_fd; /* Fd in DRM mode */ drm_via_mem_t drm; /* DRM management object */ #endif - int slot; /* Pool 3 slot */ void *pVia; /* VIA driver pointer */ FBLinearPtr linear; /* X linear pool info ptr */ +#ifdef VIA_HAVE_EXA + ExaOffscreenArea *exa; +#endif + ScrnInfoPtr pScrn; } VIAMem; typedef VIAMem *VIAMemPtr; diff --git a/src/via_vbe.c b/src/via_vbe.c index e23b224..e6f484c 100644 --- a/src/via_vbe.c +++ b/src/via_vbe.c @@ -158,7 +158,7 @@ ViaVbeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) pScrn->vtSema = TRUE; if (!pVia->NoAccel) - VIAInitialize2DEngine(pScrn); + viaInitialize2DEngine(pScrn); #ifdef XF86DRI VIAInitialize3DEngine(pScrn); |