diff -burN via/Imakefile via_new/Imakefile --- via/Imakefile 2006-01-12 23:58:03.000000000 +0100 +++ via_new/Imakefile 2006-01-13 00:12:11.000000000 +0100 @@ -9,7 +9,13 @@ DRIDEFINES = $(GLX_DEFINES) #endif +#ifdef XF86EXA +EXAINCLUDES = -I$(XF86SRC)/exa -I$(DRMSRCDIR)/shared-core +EXADEFINES = -DVIA_HAVE_EXA +#endif + SRCS = via_driver.c \ + via_3d.c \ via_accel.c \ via_bandwidth.c \ via_mode.c \ @@ -28,6 +34,7 @@ $(DRISRCS) OBJS = via_driver.o \ + via_3d.o \ via_accel.o \ via_bandwidth.o \ via_mode.o \ @@ -57,10 +64,10 @@ -I$(XF86SRC)/rac -I$(XF86SRC)/int10 -I$(SERVERSRC)/render \ -I$(SERVERSRC)/include -I$(XINCLUDESRC) -I$(FONTINCSRC) \ -I$(EXTINCSRC) -I$(XF86SRC)/vbe -I$(XF86SRC)/shadowfb \ - -I$(SERVERSRC)/fb $(DRIINCLUDES) + -I$(SERVERSRC)/fb $(DRIINCLUDES) $(EXAINCLUDES) #endif -DEFINES = $(DRIDEFINES) +DEFINES = $(DRIDEFINES) $(EXADEFINES) #if MakeHasPosixVariableSubstitutions SubdirLibraryRule($(OBJS)) @@ -81,11 +88,14 @@ InstallDriverSDKNonExecFile(Imakefile,$(DRIVERSDKDIR)/drivers/via) InstallDriverSDKNonExecFile(via.h,$(DRIVERSDKDIR)/drivers/via) +InstallDriverSDKNonExecFile(via_3d.c,$(DRIVERSDKDIR)/drivers/via) +InstallDriverSDKNonExecFile(via_3d.h,$(DRIVERSDKDIR)/drivers/via) InstallDriverSDKNonExecFile(via_accel.c,$(DRIVERSDKDIR)/drivers/via) InstallDriverSDKNonExecFile(via_bandwidth.c,$(DRIVERSDKDIR)/drivers/via) InstallDriverSDKNonExecFile(via_bios.h,$(DRIVERSDKDIR)/drivers/via) InstallDriverSDKNonExecFile(via_cursor.c,$(DRIVERSDKDIR)/drivers/via) InstallDriverSDKNonExecFile(via_dga.c,$(DRIVERSDKDIR)/drivers/via) +InstallDriverSDKNonExecFile(via_dmabuffer.h,$(DRIVERSDKDIR)/drivers/via) InstallDriverSDKNonExecFile(via_dri.c,$(DRIVERSDKDIR)/drivers/via) InstallDriverSDKNonExecFile(via_dri.h,$(DRIVERSDKDIR)/drivers/via) InstallDriverSDKNonExecFile(via_driver.c,$(DRIVERSDKDIR)/drivers/via) diff -burN via/via_3d.c via_new/via_3d.c --- via/via_3d.c 1970-01-01 01:00:00.000000000 +0100 +++ via_new/via_3d.c 2006-01-13 00:07:19.000000000 +0100 @@ -0,0 +1,591 @@ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef VIA_HAVE_EXA + +#include "via_3d.h" +#include "via_3d_reg.h" +#include + +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 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 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]; + } +} +#endif diff -burN via/via_3d.h via_new/via_3d.h --- via/via_3d.h 1970-01-01 01:00:00.000000000 +0100 +++ via_new/via_3d.h 2006-01-12 23:57:37.000000000 +0100 @@ -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 -burN via/via_accel.c via_new/via_accel.c --- via/via_accel.c 2006-01-12 23:58:04.000000000 +0100 +++ via_new/via_accel.c 2006-01-12 23:57:37.000000000 +0100 @@ -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,6 +21,8 @@ * 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. + * + * Mostly rewritten and modified for EXA support by Thomas Hellstrom 2005. */ /************************************************************************* @@ -33,7 +36,7 @@ #include "config.h" #endif -#include +#include "Xarch.h" #include "xaalocal.h" #include "xaarop.h" #include "miline.h" @@ -41,742 +44,589 @@ #include "via_driver.h" #include "via_regs.h" #include "via_id.h" +#include "via_dmabuffer.h" +#include +#include -/* 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 - - -static void VIASetupForImageWrite( - ScrnInfoPtr pScrn, - int rop, - unsigned planemask, - int trans_color, - int bpp, - int depth); - -static void VIASubsequentImageWriteRect( - ScrnInfoPtr pScrn, - int x, - int y, - int w, - int h, - int skipleft); - -static void -VIASetupForSolidLine( - ScrnInfoPtr pScrn, - int color, - int rop, - unsigned int planemask); - -static void -VIASubsequentSolidTwoPointLine( - ScrnInfoPtr pScrn, - int x1, - int y1, - int x2, - int y2, - int flags); - -static void -VIASubsequentSolidHorVertLine( - ScrnInfoPtr pScrn, - int x, - int y, - int len, - int dir); - -static void -VIASetupForDashedLine( - ScrnInfoPtr pScrn, - int fg, - int bg, - int rop, - unsigned int planemask, - int length, - unsigned char *pattern); - -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); +#define VIAACCELPATTERNROP(vRop) (XAAGetPatternROP(vRop) << 24) +#define VIAACCELCOPYROP(vRop) (XAAGetCopyROP(vRop) << 24) -static void VIADisableClipping( ScrnInfoPtr ); +/* + * Use PCI MMIO to flush the command buffer. When AGP DMA is not available. + */ -void -VIAInitialize2DEngine(ScrnInfoPtr pScrn) +static void +viaDumpDMA(ViaCommandBuffer * buf) { - VIAPtr pVia = VIAPTR(pScrn); - CARD32 dwVQStartAddr, dwVQEndAddr; - CARD32 dwVQLen, dwVQStartL, dwVQEndL, dwVQStartEndH; - CARD32 dwGEMode; - ViaTwodContext *tdc = &pVia->td; + register CARD32 *bp = buf->buf; + CARD32 *endp = bp + buf->pos; - - /* 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); - - 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); + while (bp != endp) { + if (((bp - buf->buf) & 3) == 0) { + ErrorF("\n %04lx: ", (unsigned long)(bp - buf->buf)); } - - dwGEMode = 0; - - switch (pScrn->bitsPerPixel) { - case 16: - dwGEMode |= VIA_GEM_16bpp; - break; - case 32: - dwGEMode |= VIA_GEM_32bpp; - break; - default: - dwGEMode |= VIA_GEM_8bpp; - break; + ErrorF("0x%08x ", (unsigned)*bp++); } - - /* Set BPP and Pitch */ - tdc->mode = dwGEMode; + ErrorF("\n"); } - -#define CLEAR_CBUFFER(buf, pVia) \ - (buf)->curPos = 0; \ - (pVia)->justSetup = 1; - -#define COND_CLEAR_CBUFFER(buf, pVia) \ - if ((pVia)->justSetup == 1) { \ - (pVia)->justSetup = 0; \ - } else { \ - (buf)->curPos = 0; \ - } - -#define CBUFFER(buf,offset,value) \ - (buf)->buffer[(buf)->curPos++] = ((offset) >> 2) | 0xF0000000; \ - (buf)->buffer[(buf)->curPos++] = (value); \ - - -static void dispatchCBuffer(VIAPtr pVia, ViaCBuffer *buf) +void +viaFlushPCI(ViaCommandBuffer * buf) { - unsigned size = buf->curPos >> 1; - int i; - register CARD32 *bp = buf->buffer; + register CARD32 *bp = buf->buf; + CARD32 transSetting; + CARD32 *endp = bp + buf->pos; unsigned loop = 0; - register unsigned offset; - register unsigned value; + 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. */ - - 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 )) && - (loop++ < MAXLOOP)); - - for(i=0; ipos = 0; + buf->mode = 0; + buf->has3dState = FALSE; } -static void dispatchCBufferAGP(VIAPtr pVia, ViaCBuffer *buf) -{ +/* + * 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 +viaFlushDRIEnabled(ViaCommandBuffer * cb) +{ + ScrnInfoPtr pScrn = cb->pScrn; + VIAPtr pVia = VIAPTR(pScrn); + char *tmp = (char *)cb->buf; + int tmpSize; drm_via_cmdbuffer_t b; - b.buf = (char *)(buf->buffer); - b.size = buf->curPos*sizeof(CARD32); + /* + * Align command buffer end for AGP DMA. + */ - 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. */ + 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; } } -#endif - /* - * No AGP ringbuffer or no DRI. - */ - - dispatchCBuffer(pVia,buf); + 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. + */ -/* Acceleration init function, sets up pointers to our accelerated functions */ -Bool -VIAInitAccel(ScreenPtr pScreen) +int +viaSetupCBuffer(ScrnInfoPtr pScrn, ViaCommandBuffer * buf, unsigned size) { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; +#ifdef XF86DRI VIAPtr pVia = VIAPTR(pScrn); - XAAInfoRecPtr xaaptr; - BoxRec AvailFBArea; - unsigned long cacheEnd; - unsigned long cacheEndTmp; - - - 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; - } - if (pVia->hwcursor) { - pVia->FBFreeEnd -= VIA_CURSOR_SIZE; - pVia->CursorStart = pVia->FBFreeEnd; - } - - VIAInitialize2DEngine(pScrn); +#endif - if (pScrn->depth == 8) { - pVia->PlaneMask = 0xFF; - } - else if (pScrn->depth == 15) { - pVia->PlaneMask = 0x7FFF; - } - else if (pScrn->depth == 16) { - pVia->PlaneMask = 0xFFFF; - } - else if (pScrn->depth == 24) { - pVia->PlaneMask = 0xFFFFFF; + 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; } - - /* General acceleration flags */ - if (!(xaaptr = pVia->AccelInfoRec = XAACreateInfoRec())) - return FALSE; - - xaaptr->Flags = PIXMAP_CACHE | - OFFSCREEN_PIXMAPS | - LINEAR_FRAMEBUFFER | - MICROSOFT_ZERO_LINE_BIAS | - 0; - - if (pScrn->bitsPerPixel == 8) - xaaptr->CachePixelGranularity = 128; - - /* Clipping */ - 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; - - xaaptr->Sync = VIAAccelSync; - - /* ScreenToScreen copies */ - xaaptr->SetupForScreenToScreenCopy = VIASetupForScreenToScreenCopy; - xaaptr->SubsequentScreenToScreenCopy = VIASubsequentScreenToScreenCopy; - xaaptr->ScreenToScreenCopyFlags = NO_PLANEMASK | ROP_NEEDS_SOURCE; - - /* Solid filled rectangles */ - xaaptr->SetupForSolidFill = VIASetupForSolidFill; - xaaptr->SubsequentSolidFillRect = VIASubsequentSolidFillRect; - xaaptr->SolidFillFlags = NO_PLANEMASK | ROP_NEEDS_SOURCE; - - /* Mono 8x8 pattern fills */ - xaaptr->SetupForMono8x8PatternFill = VIASetupForMono8x8PatternFill; - xaaptr->SubsequentMono8x8PatternFillRect = - VIASubsequentMono8x8PatternFillRect; - xaaptr->Mono8x8PatternFillFlags = NO_PLANEMASK | - HARDWARE_PATTERN_PROGRAMMED_BITS | - HARDWARE_PATTERN_PROGRAMMED_ORIGIN | - BIT_ORDER_IN_BYTE_MSBFIRST | - 0; - - /* Color 8x8 pattern fills */ - xaaptr->SetupForColor8x8PatternFill = VIASetupForColor8x8PatternFill; - xaaptr->SubsequentColor8x8PatternFillRect = - VIASubsequentColor8x8PatternFillRect; - xaaptr->Color8x8PatternFillFlags = NO_PLANEMASK | - NO_TRANSPARENCY | - HARDWARE_PATTERN_PROGRAMMED_BITS | - 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 + return Success; +} - /* Solid lines */ - xaaptr->SetupForSolidLine = VIASetupForSolidLine; - xaaptr->SubsequentSolidTwoPointLine = VIASubsequentSolidTwoPointLine; - xaaptr->SubsequentSolidHorVertLine = VIASubsequentSolidHorVertLine; - xaaptr->SolidBresenhamLineErrorTermBits = 14; - xaaptr->SolidLineFlags = NO_PLANEMASK | ROP_NEEDS_SOURCE; +/* + * Free resources associated with a command buffer. + */ - /* dashed line */ - 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; +void +viaTearDownCBuffer(ViaCommandBuffer * buf) +{ + if (buf && buf->buf) + xfree(buf->buf); + buf->buf = NULL; +} - /* 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; +/* + * Leftover from VIAs code. + */ - xaaptr->SetupForScanlineCPUToScreenColorExpandFill = - VIASetupForCPUToScreenColorExpandFill; - xaaptr->SubsequentScanlineCPUToScreenColorExpandFill = - VIASubsequentScanlineCPUToScreenColorExpandFill; - xaaptr->ColorExpandBase = pVia->BltBase; - xaaptr->ColorExpandRange = VIA_MMIO_BLTSIZE; +static void +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); - /* 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; + VIASETREG(VIA_REG_TRANSET, 0xfe020000); + VIASETREG(VIA_REG_TRANSPACE, 0x00000000); +} - /* - * CLE266 has fast direct processor access to the framebuffer. - * Therefore, disable the PCI GXcopy. +/* + * 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. */ - if (pVia->Chipset == VIA_CLE266) - xaaptr->ImageWriteFlags |= NO_GXCOPY; +static void +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); +} - xaaptr->SetupForImageWrite = VIASetupForImageWrite; - xaaptr->SubsequentImageWriteRect = VIASubsequentImageWriteRect; - xaaptr->ImageWriteBase = pVia->BltBase; - xaaptr->ImageWriteRange = VIA_MMIO_BLTSIZE; +/* + * Disable the virtual command queue. + */ - /* We reserve space for pixel cache */ +void +viaDisableVQ(ScrnInfoPtr pScrn) +{ + VIAPtr pVia = VIAPTR(pScrn); - cacheEnd = pVia->FBFreeEnd / pVia->Bpl; - cacheEndTmp = (pVia->FBFreeStart + VIA_PIXMAP_CACHE_SIZE + pVia->Bpl-1) - / pVia->Bpl; + 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); +} - /* - * Use only requested pixmap size if it is less than available - * offscreen memory. +/* + * Update our 2D state (TwoDContext) with a new mode. */ - if(cacheEnd > cacheEndTmp) - cacheEnd = cacheEndTmp; - /* - * Clip to the blitter limit - */ +static Bool +viaAccelSetMode(int bpp, ViaTwodContext * tdc) +{ + switch (bpp) { + case 16: + tdc->mode = VIA_GEM_16bpp; + tdc->bytesPPShift = 1; + return TRUE; + case 32: + tdc->mode = VIA_GEM_32bpp; + tdc->bytesPPShift = 2; + return TRUE; + case 8: + tdc->mode = VIA_GEM_8bpp; + tdc->bytesPPShift = 0; + return TRUE; + default: + tdc->bytesPPShift = 0; + return FALSE; + } +} - if (cacheEnd > VIA_MAX_ACCEL_Y) - cacheEnd = VIA_MAX_ACCEL_Y; +/* + * Initialize the 2D engine and set the 2D context mode to the + * current screen depth. Also enable the virtual queue. + */ - pVia->FBFreeStart = (cacheEnd + 1) *pVia->Bpl; +void +viaInitialize2DEngine(ScrnInfoPtr pScrn) +{ + VIAPtr pVia = VIAPTR(pScrn); + ViaTwodContext *tdc = &pVia->td; + int i; /* - * Finally, we set up the video memory space available to the pixmap - * cache + * init 2D engine regs to reset 2D engine */ - AvailFBArea.x1 = 0; - AvailFBArea.y1 = 0; - AvailFBArea.x2 = pScrn->displayWidth; - AvailFBArea.y2 = cacheEnd; + for (i = 0x04; i < 0x44; i += 4) { + VIASETREG(i, 0x0); + } - xf86InitFBManager(pScreen, &AvailFBArea); - DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using %d lines for offscreen memory.\n", - AvailFBArea.y2 - pScrn->virtualY )); + viaInitAgp(pVia); - pVia->justSetup = 0; - return XAAInit(pScreen, xaaptr); + if (pVia->VQStart != 0) { + viaEnableVQ(pVia); + } else { + viaDisableVQ(pScrn); + } + + viaAccelSetMode(pScrn->bitsPerPixel, tdc); } /* - * The sync function for the GE + * Wait for acceleration engines idle. An expensive way to sync. */ + void -VIAAccelSync(ScrnInfoPtr pScrn) +viaAccelSync(ScrnInfoPtr pScrn) { 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 | VIA_3D_ENG_BUSY)) && - (loop++ < MAXLOOP)) - ; + (loop++ < MAXLOOP)) ; } -/* These are the ScreenToScreen bitblt functions. We support all ROPs, all - * directions. - * +/* + * Set 2D state clipping on. */ static void -VIASetupForScreenToScreenCopy( - ScrnInfoPtr pScrn, - int xdir, - int ydir, - int rop, - unsigned planemask, - int trans_color) +viaSetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2) { VIAPtr pVia = VIAPTR(pScrn); - int cmd; - ViaCBuffer *buf = &pVia->cBuf; ViaTwodContext *tdc = &pVia->td; - cmd = VIA_GEC_BLT | (XAAGetCopyROP(rop) << 24); + tdc->clipping = TRUE; + tdc->clipX1 = x1; + tdc->clipY1 = y1; + tdc->clipX2 = x2; + tdc->clipY2 = y2; +} - if (xdir < 0) - cmd |= VIA_GEC_DECX; +/* + * Set 2D state clipping off. + */ - if (ydir < 0) - cmd |= VIA_GEC_DECY; +static void +viaDisableClipping(ScrnInfoPtr pScrn) +{ + VIAPtr pVia = VIAPTR(pScrn); + ViaTwodContext *tdc = &pVia->td; - pVia->SavedCmd = cmd; + tdc->clipping = FALSE; +} - 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); +/* + * 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 -VIASubsequentScreenToScreenCopy( - ScrnInfoPtr pScrn, - int x1, - int y1, - int x2, - int y2, - int w, - int h) +viaAccelSolidHelper(ViaCommandBuffer * cb, int x, int y, int w, int h, + unsigned fbBase, CARD32 mode, unsigned pitch, CARD32 fg, CARD32 cmd) { - VIAPtr pVia = VIAPTR(pScrn); - ViaCBuffer *buf = &pVia->cBuf; - ViaTwodContext *tdc = &pVia->td; - CARD32 srcBase, dstBase; + 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); +} - if (!w || !h) - return; +/* + * Check if we can use a planeMask and update the 2D context accordingly. + */ + +static Bool +viaAccelPlaneMaskHelper(ViaTwodContext * tdc, CARD32 planeMask) +{ + CARD32 modeMask = (1 << ((1 << tdc->bytesPPShift) << 3)) - 1; + CARD32 curMask = 0x00000000; + CARD32 curByteMask; + int i; - srcBase = y1*pVia->Bpl + x1*pVia->Bpp; - dstBase = y2*pVia->Bpl + x2*pVia->Bpp; + if ((planeMask & modeMask) != modeMask) { - x1 = (srcBase & 31); - x2 = (dstBase & 31); + /* + * Masking doesn't work in 8bpp. + */ - switch (pScrn->bitsPerPixel) { - case 16: - x1 >>= 1; - x2 >>= 1; - break; - case 32: - x1 >>= 2; - x2 >>= 2; - break; - default: - break; + if (modeMask == 0x0F) { + tdc->keyControl &= 0x0FFFFFFF; + return FALSE; } - y1 = 0; - y2 = 0; + /* + * Translate the bit planemask to a byte planemask. + */ + + for (i = 0; i < (1 << tdc->bytesPPShift); ++i) { + curByteMask = (0xFF << i); - if (pVia->SavedCmd & VIA_GEC_DECX) { - x1 += (w - 1); - x2 += (w - 1); - } - - if (pVia->SavedCmd & VIA_GEC_DECY) { - y1 += (h - 1); - y2 += (h - 1); - } - - 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 ((planeMask & curByteMask) == 0) { + curMask |= (1 << i); + } else if ((planeMask & curByteMask) != curByteMask) { + tdc->keyControl &= 0x0FFFFFFF; + return FALSE; + } + } + ErrorF("DEBUG: planeMask 0x%08x, curMask 0%02x\n", + (unsigned)planeMask, (unsigned)curMask); + + tdc->keyControl = (tdc->keyControl & 0x0FFFFFFF) | (curMask << 28); + } + return TRUE; +} /* - * SetupForSolidFill is also called to set up for lines. + * Emit transparency state and color to the command buffer. */ static void -VIASetupForSolidFill( - ScrnInfoPtr pScrn, - int color, - int rop, - unsigned planemask) +viaAccelTransparentHelper(ViaTwodContext * tdc, ViaCommandBuffer * cb, + CARD32 keyControl, CARD32 transColor, Bool usePlaneMask) { - VIAPtr pVia = VIAPTR(pScrn); - int cmd; + 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); + } +} - cmd = VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT | - (XAAGetPatternROP(rop) << 24); +/* + * Emit a copy blit operation to the command buffer. + */ - pVia->SavedCmd = cmd; - pVia->SavedFgColor = color; +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 (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 -VIASubsequentSolidFillRect( - ScrnInfoPtr pScrn, - int x, - int y, - int w, - int h) +viaSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop, + unsigned planemask, int trans_color) { VIAPtr pVia = VIAPTR(pScrn); - ViaCBuffer *buf = &pVia->cBuf; + CARD32 cmd; ViaTwodContext *tdc = &pVia->td; - if (!w || !h) + 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; - 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)); - - 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); + 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 @@ -789,404 +639,243 @@ */ static void -VIASetupForMono8x8PatternFill( - ScrnInfoPtr pScrn, - int pattern0, - int pattern1, - int fg, - int bg, - int rop, - unsigned planemask) +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 | - (XAAGetPatternROP(rop) << 24); + VIAACCELPATTERNROP(rop); if (bg == -1) { - /* transparent mono pattern */ cmd |= VIA_GEC_MPAT_TRANS; } - pVia->SavedCmd = cmd; - pVia->SavedFgColor = fg; - pVia->SavedBgColor = bg; - pVia->SavedPattern0 = pattern0; - pVia->SavedPattern1 = pattern1; -} + 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) +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; + CARD32 patOffset; ViaTwodContext *tdc = &pVia->td; + CARD32 dstBase; + int sub; + + RING_VARS; if (!w || !h) return; - dwPatOffset = ((patOffy & 0x7) << 29) | ((patOffx & 0x7) << 26); - - 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)); - - 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); - + 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) +viaSetupForColor8x8PatternFill(ScrnInfoPtr pScrn, int patternx, int patterny, + int rop, unsigned planemask, int trans_color) { VIAPtr pVia = VIAPTR(pScrn); - int cmd; + ViaTwodContext *tdc = &pVia->td; - cmd = VIA_GEC_BLT | (XAAGetPatternROP(rop) << 24); + RING_VARS; - pVia->SavedCmd = cmd; - pVia->SavedPatternAddr = (patternx * pVia->Bpp + patterny * pVia->Bpl); + 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) +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; + CARD32 patAddr; ViaTwodContext *tdc = &pVia->td; + CARD32 dstBase; + int sub; + + RING_VARS; if (!w || !h) return; - dwPatAddr = (pVia->SavedPatternAddr >> 3) | + patAddr = (tdc->patternAddr >> 3) | ((patOffy & 0x7) << 29) | ((patOffx & 0x7) << 26); + sub = viaAccelClippingHelper(cb, y, tdc); + dstBase = pScrn->fbOffset + sub * pVia->Bpl; - /* 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)); - - 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); - + 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) +viaSetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int fg, int bg, + int rop, unsigned planemask) { VIAPtr pVia = VIAPTR(pScrn); int cmd; - ViaCBuffer *buf = &pVia->cBuf; ViaTwodContext *tdc = &pVia->td; + RING_VARS; + cmd = VIA_GEC_BLT | VIA_GEC_SRC_SYS | VIA_GEC_SRC_MONO | - (XAAGetCopyROP(rop) << 24); + VIAACCELCOPYROP(rop); if (bg == -1) { cmd |= VIA_GEC_MSRC_TRANS; } - pVia->SavedCmd = cmd; - pVia->SavedFgColor = fg; - pVia->SavedBgColor = bg; - - /* Disable Transparent Bitblt */ - CLEAR_CBUFFER( buf, pVia); - CBUFFER(buf,VIA_REG_GEMODE, tdc->mode); - CBUFFER(buf,VIA_REG_KEYCONTROL, 0x0); -} - - -static void -VIASubsequentScanlineCPUToScreenColorExpandFill( - ScrnInfoPtr pScrn, - int x, - int y, - int w, - int h, - int skipleft) -{ - 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. */ - - if (skipleft) { - VIASetClippingRectangle(pScrn, (x + skipleft), y, (x + w - 1), (y + h -1)); - } - - /* 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)); - - 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 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; - - cmd = VIA_GEC_BLT | VIA_GEC_SRC_MONO | (XAAGetCopyROP(rop) << 24); - - if (bg == -1) { - cmd |= VIA_GEC_MSRC_TRANS; - } + tdc->cmd = cmd; + tdc->fgColor = fg; + tdc->bgColor = bg; - pVia->SavedCmd = cmd; - pVia->SavedFgColor = fg; - pVia->SavedBgColor = bg; + ADVANCE_RING; - /* Disable Transparent Bitblt */ - CLEAR_CBUFFER( buf, pVia); - CBUFFER(buf,VIA_REG_KEYCONTROL, 0x0); + viaAccelTransparentHelper(tdc, cb, 0x0, 0x0, FALSE); } - static void -VIASubsequentScreenToScreenColorExpand( - ScrnInfoPtr pScrn, - int x, - int y, - int w, - int h, - int srcx, - int srcy, - int offset) +viaSubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int x, + int y, int w, int h, int skipleft) { VIAPtr pVia = VIAPTR(pScrn); - ViaCBuffer *buf = &pVia->cBuf; ViaTwodContext *tdc = &pVia->td; - CARD32 srcBase,dstBase; + int sub; - srcBase = srcy*pVia->Bpl + srcx*pVia->Bpp; - dstBase = y*pVia->Bpl + x*pVia->Bpp; + RING_VARS; - x = (dstBase & 31); - srcx = srcBase & 7; - - switch (pScrn->bitsPerPixel) { - case 16: - x >>= 1; - break; - case 32: - x >>= 2; - break; - default: - break; + if (skipleft) { + viaSetClippingRectangle(pScrn, (x + skipleft), y, (x + w - 1), + (y + h - 1)); } - srcy = 0; - y = 0; + 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); - /* 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); - - dispatchCBufferAGP(pVia, buf); + viaFlushPCI(cb); + viaDisableClipping(pScrn); } -#endif - static void -VIASetupForImageWrite( - ScrnInfoPtr pScrn, - int rop, - unsigned planemask, - int trans_color, - int bpp, - int depth) +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; - /* We don't record bpp and depth because we assume bpp is equal to - bpp of screen. Is this assume correct ? */ - - cmd = VIA_GEC_BLT | VIA_GEC_SRC_SYS | (XAAGetCopyROP(rop) << 24); + RING_VARS; - pVia->SavedCmd = cmd; - - 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_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, +viaSubsequentImageWriteRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, int skipleft) { VIAPtr pVia = VIAPTR(pScrn); - ViaCBuffer *buf = &pVia->cBuf; ViaTwodContext *tdc = &pVia->td; + int sub; + + RING_VARS; if (skipleft) { - VIASetClippingRectangle(pScrn, (x + skipleft), y, (x + w - 1), (y + h -1)); + viaSetClippingRectangle(pScrn, (x + skipleft), y, (x + w - 1), + (y + h - 1)); } - /* 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)); - - 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); + 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); } - -/* Setup for XAA solid lines. */ static void -VIASetupForSolidLine( - ScrnInfoPtr pScrn, - int color, - int rop, +viaSetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop, unsigned int planemask) { 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); + RING_VARS; - pVia->SavedCmd = cmd; - pVia->SavedFgColor = color; - - /* set solid line pattern */ - CBUFFER(buf,VIA_REG_MONOPAT0, 0xFF); - CBUFFER(buf,VIA_REG_FGCOLOR, pVia->SavedFgColor); + 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) +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; + CARD32 dstBase; + int sub; - 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; + RING_VARS; + + cmd = tdc->cmd | VIA_GEC_LINE; dx = x2 - x1; if (dx < 0) { @@ -1212,216 +901,1542 @@ cmd |= VIA_GEC_LASTPIXEL_OFF; } - /* 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)); - - /* major = 2*dmaj, minor = 2*dmin, err = -dmaj - ((bias >> octant) & 1) */ - /* K1 = 2*dmin K2 = 2*(dmin - dmax) */ - /* Error Term = (StartXfbOffset + 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 = (StartXcBuf; ViaTwodContext *tdc = &pVia->td; + CARD32 dstBase; + int sub; + + RING_VARS; + + sub = viaAccelClippingHelper(cb, y, tdc); + dstBase = pScrn->fbOffset + sub * pVia->Bpl; - /* 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)); + 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) { - 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); - } - 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); - } - dispatchCBufferAGP(pVia, buf); + 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) +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; + CARD32 pat = *(CARD32 *) pattern; ViaTwodContext *tdc = &pVia->td; - cmd = VIA_GEC_LINE | VIA_GEC_FIXCOLOR_PAT | (XAAGetPatternROP(rop) << 24); + RING_VARS; + + viaAccelTransparentHelper(tdc, cb, 0x00, 0x00, FALSE); + cmd = VIA_GEC_LINE | VIA_GEC_FIXCOLOR_PAT | VIAACCELPATTERNROP(rop); if (bg == -1) { - /* transparent mono pattern */ cmd |= VIA_GEC_MPAT_TRANS; } - pVia->SavedCmd = cmd; - pVia->SavedFgColor = fg; - pVia->SavedBgColor = bg; + 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; + 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; } - 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); + 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) +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); - int dx, dy, cmd, tmp, error = 1; - ViaCBuffer *buf = &pVia->cBuf; - ViaTwodContext *tdc = &pVia->td; + XAAInfoRecPtr xaaptr; - COND_CLEAR_CBUFFER( buf, pVia); - CBUFFER(buf,VIA_REG_GEMODE, tdc->mode); - CBUFFER(buf,VIA_REG_FGCOLOR, pVia->SavedFgColor); - cmd = pVia->SavedCmd; + /* + * General acceleration flags + */ - dx = x2 - x1; - if (dx < 0) { - dx = -dx; - cmd |= VIA_GEC_DECX; /* line will be drawn from right */ - error = 0; - } + if (!(xaaptr = pVia->AccelInfoRec = XAACreateInfoRec())) + return FALSE; - dy = y2 - y1; - if (dy < 0) { - dy = -dy; - cmd |= VIA_GEC_DECY; /* line will be drawn from bottom */ - } + xaaptr->Flags = PIXMAP_CACHE | + OFFSCREEN_PIXMAPS | LINEAR_FRAMEBUFFER | MICROSOFT_ZERO_LINE_BIAS | 0; - if (dy > dx) { - tmp = dy; - dy = dx; - dx = tmp; /* Swap 'dx' and 'dy' */ - cmd |= VIA_GEC_Y_MAJOR; /* Y major line */ - } + if (pScrn->bitsPerPixel == 8) + xaaptr->CachePixelGranularity = 128; - if (flags & OMIT_LAST) { - cmd |= VIA_GEC_LASTPIXEL_OFF; - } + 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; + + xaaptr->Sync = viaAccelSync; + + xaaptr->SetupForScreenToScreenCopy = viaSetupForScreenToScreenCopy; + xaaptr->SubsequentScreenToScreenCopy = viaSubsequentScreenToScreenCopy; + xaaptr->ScreenToScreenCopyFlags = NO_PLANEMASK | ROP_NEEDS_SOURCE; + + xaaptr->SetupForSolidFill = viaSetupForSolidFill; + xaaptr->SubsequentSolidFillRect = viaSubsequentSolidFillRect; + xaaptr->SolidFillFlags = NO_PLANEMASK | ROP_NEEDS_SOURCE; + + xaaptr->SetupForMono8x8PatternFill = viaSetupForMono8x8PatternFill; + xaaptr->SubsequentMono8x8PatternFillRect = + viaSubsequentMono8x8PatternFillRect; + xaaptr->Mono8x8PatternFillFlags = NO_PLANEMASK | + HARDWARE_PATTERN_PROGRAMMED_BITS | + HARDWARE_PATTERN_PROGRAMMED_ORIGIN | BIT_ORDER_IN_BYTE_MSBFIRST | 0; + + xaaptr->SetupForColor8x8PatternFill = viaSetupForColor8x8PatternFill; + xaaptr->SubsequentColor8x8PatternFillRect = + viaSubsequentColor8x8PatternFillRect; + xaaptr->Color8x8PatternFillFlags = NO_PLANEMASK | + NO_TRANSPARENCY | + HARDWARE_PATTERN_PROGRAMMED_BITS | + HARDWARE_PATTERN_PROGRAMMED_ORIGIN | 0; + + xaaptr->SetupForSolidLine = viaSetupForSolidLine; + xaaptr->SubsequentSolidTwoPointLine = viaSubsequentSolidTwoPointLine; + xaaptr->SubsequentSolidHorVertLine = viaSubsequentSolidHorVertLine; + xaaptr->SolidBresenhamLineErrorTermBits = 14; + xaaptr->SolidLineFlags = NO_PLANEMASK | ROP_NEEDS_SOURCE; + + 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; + + xaaptr->ScanlineCPUToScreenColorExpandFillFlags = NO_PLANEMASK | + CPU_TRANSFER_PAD_DWORD | + SCANLINE_PAD_DWORD | + BIT_ORDER_IN_BYTE_MSBFIRST | + LEFT_EDGE_CLIPPING | ROP_NEEDS_SOURCE | 0; + + xaaptr->SetupForScanlineCPUToScreenColorExpandFill = + viaSetupForCPUToScreenColorExpandFill; + xaaptr->SubsequentScanlineCPUToScreenColorExpandFill = + viaSubsequentScanlineCPUToScreenColorExpandFill; + xaaptr->ColorExpandBase = pVia->BltBase; + xaaptr->ColorExpandRange = VIA_MMIO_BLTSIZE; - /* 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)); + 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; + + /* + * 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_K8M800) + xaaptr->ImageWriteFlags |= NO_GXCOPY; + + xaaptr->SetupForImageWrite = viaSetupForImageWrite; + xaaptr->SubsequentImageWriteRect = viaSubsequentImageWriteRect; + xaaptr->ImageWriteBase = pVia->BltBase; + xaaptr->ImageWriteRange = VIA_MMIO_BLTSIZE; + + return XAAInit(pScreen, xaaptr); - /* major = 2*dmaj, minor = 2*dmin, err = -dmaj - ((bias >> octant) & 1) */ - /* K1 = 2*dmin K2 = 2*(dmin - dmax) */ - /* Error Term = (StartXmyNum]; 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 + RING_VARS; + + ++pVia->curMarker; + + /* + * Wrap around without possibly affecting the int sign bit. + */ - 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); + pVia->curMarker &= 0x7FFFFFFF; + 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; } +/* + * Wait for the value to get blitted, or in the PCI case for engine idle. + */ -static void VIADisableClipping(ScrnInfoPtr pScrn) +void +viaAccelWaitMarker(ScreenPtr pScreen, int marker) { + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; VIAPtr pVia = VIAPTR(pScrn); + CARD32 uMarker = marker; -#ifdef DEBUG_EXTRA - ErrorF("Kill ClipRect\n"); -#endif - - pVia->SavedCmd &= ~VIA_GEC_CLIP_ENABLE; + if (pVia->agpDMA) { + while ((pVia->lastMarkerRead - uMarker) > (1 << 24)) + pVia->lastMarkerRead = *pVia->markerBuf; + } else { + viaAccelSync(pScrn); + } } +#ifdef VIA_HAVE_EXA + /* - * + * Exa functions. It is assumed that EXA does not exceed the blitter limits. */ -void -ViaVQDisable(ScrnInfoPtr pScrn) + +static Bool +viaExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg) { + ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; VIAPtr pVia = VIAPTR(pScrn); - VIASETREG(VIA_REG_TRANSET, 0x00FE0000); - VIASETREG(VIA_REG_TRANSPACE, 0x00000004); + ViaTwodContext *tdc = &pVia->td; + + RING_VARS; + + if (exaGetPixmapPitch(pPixmap) & 7) + return FALSE; + + if (!viaAccelSetMode(pPixmap->drawable.depth, tdc)) + return FALSE; + + if (!viaAccelPlaneMaskHelper(tdc, planeMask)) + return FALSE; + viaAccelTransparentHelper(tdc, cb, 0x0, 0x0, TRUE); + + tdc->cmd = VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT | VIAACCELPATTERNROP(alu); + + tdc->fgColor = fg; + + return TRUE; +} + +static void +viaExaSolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2) +{ + ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; + VIAPtr pVia = VIAPTR(pScrn); + ViaTwodContext *tdc = &pVia->td; + CARD32 dstPitch, dstOffset; + + RING_VARS; + + int w = x2 - x1, h = y2 - y1; + + dstPitch = exaGetPixmapPitch(pPixmap); + dstOffset = exaGetPixmapOffset(pPixmap); + + viaAccelSolidHelper(cb, x1, y1, w, h, dstOffset, + tdc->mode, dstPitch, tdc->fgColor, tdc->cmd); + ADVANCE_RING; +} + +static void +viaExaDoneSolidCopy(PixmapPtr pPixmap) +{ +} + +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; + + RING_VARS; + + if (pSrcPixmap->drawable.bitsPerPixel != + pDstPixmap->drawable.bitsPerPixel) + return FALSE; + + if ((tdc->srcPitch = exaGetPixmapPitch(pSrcPixmap)) & 3) + return FALSE; + + if (exaGetPixmapPitch(pDstPixmap) & 7) + return FALSE; + + tdc->srcOffset = exaGetPixmapOffset(pSrcPixmap); + + tdc->cmd = VIA_GEC_BLT | VIAACCELCOPYROP(alu); + if (xdir < 0) + tdc->cmd |= VIA_GEC_DECX; + if (ydir < 0) + tdc->cmd |= VIA_GEC_DECY; + + if (!viaAccelSetMode(pDstPixmap->drawable.bitsPerPixel, tdc)) + return FALSE; + + if (!viaAccelPlaneMaskHelper(tdc, planeMask)) + return FALSE; + viaAccelTransparentHelper(tdc, cb, 0x0, 0x0, TRUE); + + return TRUE; +} + +static void +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); + ViaTwodContext *tdc = &pVia->td; + CARD32 srcOffset = tdc->srcOffset; + CARD32 dstOffset = exaGetPixmapOffset(pDstPixmap); + + RING_VARS; + + if (!width || !height) + return; + + viaAccelCopyHelper(cb, srcX, srcY, dstX, dstY, width, height, + srcOffset, dstOffset, tdc->mode, tdc->srcPitch, + exaGetPixmapPitch(pDstPixmap), tdc->cmd); + ADVANCE_RING; +} + +#ifdef VIA_DEBUG_COMPOSITE + +/* + * Borrowed from EXA core. + */ + +static void +viaExaCompositePictDesc(PicturePtr pict, char *string, int n) +{ + char format[20]; + char size[20]; + + if (!pict) { + snprintf(string, n, "None"); + return; + } + + 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; + } + + 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 +viaExaPrintComposite(CARD8 op, + PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst) +{ + char sop[20]; + char srcdesc[40], maskdesc[40], dstdesc[40]; + + switch (op) { + case PictOpSrc: + sprintf(sop, "Src"); + break; + case PictOpOver: + sprintf(sop, "Over"); + break; + default: + sprintf(sop, "0x%x", (int)op); + break; + } + + 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 + +/* + * Helper for bitdepth expansion. + */ + +static CARD32 +viaBitExpandHelper(CARD32 component, CARD32 bits) +{ + CARD32 tmp, mask; + + 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 +viaPixelARGB8888(unsigned format, void *pixelP, CARD32 * argb8888) +{ + CARD32 bits, shift, pixel, bpp; + + bpp = PICT_FORMAT_BPP(format); + + 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; +} + +/* + * Check if the above function will work. + */ + +static Bool +viaExpandablePixel(int format) +{ + int formatType = PICT_FORMAT_TYPE(format); + + return (formatType == PICT_TYPE_A || + formatType == PICT_TYPE_ABGR || formatType == PICT_TYPE_ARGB); +} + +/* + * 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); + Bool forceUpload; + + forceUpload = (pVia->lastToUpload != v3d); + pVia->lastToUpload = v3d; + +#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; +} + +static Bool +viaOrder(CARD32 val, CARD32 * shift) +{ + *shift = 0; + + while (val > (1 << *shift)) + (*shift)++; + return (val == (1 << *shift)); +} + +#ifdef XF86DRI + +/* + * 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); + 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 (!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; + } + + if (!pVia->directRenderingEnabled) + return FALSE; + + if ((srcPitch & 3) || (srcOffset & 3)) { + ErrorF("VIA EXA download src_pitch misaligned\n"); + return FALSE; + } + + useBounceBuffer = (((unsigned long)dst & 15) || (dst_pitch & 15)); + + height = h; + + if (useBounceBuffer) { + bounceAligned = (char *)(((unsigned long)pVia->dBounce + 15) & ~15); + bouncePitch = (dst_pitch + 15) & ~15; + height = VIA_DMA_DL_SIZE / bouncePitch; + } + + 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->bounce_buffer = 0; + curBlit->to_fb = 0; + + 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; + } + + 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; + } + } + } + + 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 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); + 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; + + 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; + } + + if (!pVia->texAddr) + return FALSE; + + switch (pDst->drawable.bitsPerPixel) { + case 32: + format = PICT_a8r8g8b8; + break; + case 16: + format = PICT_r5g6b5; + break; + default: + return FALSE; + } + + 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; + } + + if (sync[buf] >= 0) + viaAccelWaitMarker(pScrn->pScreen, sync[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.bounce_buffer = 0; + blit.to_fb = 1; + + exaWaitSync(pScrn->pScreen); + while (-EAGAIN == (err = + drmCommandWriteRead(pVia->drmFD, DRM_VIA_DMA_BLIT, &blit, + sizeof(blit)))) ; + if (err < 0) + return FALSE; + + while (-EAGAIN == (err = drmCommandWrite(pVia->drmFD, DRM_VIA_BLIT_SYNC, + &blit.sync, sizeof(blit.sync)))) ; + return (err == 0); +} + +#endif + +static Bool +viaExaUploadToScratch(PixmapPtr pSrc, PixmapPtr pDst) +{ + + 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; + } + + 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 Bool +viaExaCheckComposite(int op, PicturePtr pSrcPicture, + PicturePtr pMaskPicture, PicturePtr pDstPicture) +{ + + 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; + } + + /* + * 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. + */ + + 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; +} + +static Bool +viaIsAGP(VIAPtr pVia, PixmapPtr pPix, unsigned long *offset) +{ +#ifdef XF86DRI + unsigned long offs; + + if (pVia->directRenderingEnabled && !pVia->IsPCI) { + offs = (unsigned long)pPix->devPrivate.ptr - + (unsigned long)pVia->agpMappedAddr; + + 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; + + v3d->setDestination(v3d, exaGetPixmapOffset(pDst), + exaGetPixmapPitch(pDst), pDstPicture->format); + v3d->setCompositeOperator(v3d, op); + v3d->setDrawing(v3d, 0x0c, 0xFFFFFFFF, 0x000000FF, 0xFF); + + viaOrder(pSrc->drawable.width, &width); + viaOrder(pSrc->drawable.height, &height); + + /* + * 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; + } + + /* + * 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; + } + + /* + * 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 (!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; + } + } + + 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; + } + } + + 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; +} + +static void +viaExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, + int dstX, int dstY, int width, int height) +{ + ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; + VIAPtr pVia = VIAPTR(pScrn); + Via3DState *v3d = &pVia->v3d; + CARD32 col; + + if (pVia->maskP) { + viaPixelARGB8888(pVia->maskFormat, pVia->maskP, &col); + v3d->setTexBlendCol(v3d, 0, pVia->componentAlpha, col); + } + if (pVia->srcP) { + viaPixelARGB8888(pVia->srcFormat, pVia->srcP, &col); + v3d->setDrawing(v3d, 0x0c, 0xFFFFFFFF, col & 0x00FFFFFF, col >> 24); + srcX = maskX; + srcY = maskY; + } + + 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); +} + +/* + * Init EXA. Alignments are 2D engine constraints. + */ + +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; + +#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 + + pExa->accel.UploadToScratch = viaExaUploadToScratch; + pExa->accel.CheckComposite = viaExaCheckComposite; + pExa->accel.PrepareComposite = viaExaPrepareComposite; + pExa->accel.Composite = viaExaComposite; + pExa->accel.DoneComposite = viaExaDoneSolidCopy; + + if (!exaDriverInit(pScreen, pExa)) { + xfree(pExa); + return NULL; + } + + viaInit3DState(&pVia->v3d); + return pExa; +} + +#endif /* VIA_HAVE_EXA */ + +/* + * Acceleration init function. Sets up offscreen memory disposition, initializes engines + * and acceleration method. + */ + +Bool +viaInitAccel(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + VIAPtr pVia = VIAPTR(pScrn); + BoxRec AvailFBArea; + int maxY; + + 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; + } + + viaInitialize2DEngine(pScrn); + + if (pVia->hwcursor) { + pVia->FBFreeEnd -= VIA_CURSOR_SIZE; + pVia->CursorStart = pVia->FBFreeEnd; + } + + /* + * Sync marker space. + */ + + pVia->FBFreeEnd -= 32; + pVia->markerOffset = (pVia->FBFreeEnd + 31) & ~31; + pVia->markerBuf = (CARD32 *) ((char *)pVia->FBBase + pVia->markerOffset); + +#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; + + return TRUE; + } +#endif + + 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); + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using %d lines for offscreen memory.\n", + AvailFBArea.y2 - pScrn->virtualY)); + + return viaInitXAA(pScreen); +} + +/* + * Free used acceleration resorces. + */ + +void +viaExitAccel(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + VIAPtr pVia = VIAPTR(pScrn); + + viaAccelSync(pScrn); + +#ifdef VIA_HAVE_EXA + if (pVia->useEXA) { + if (pVia->exaDriverPtr) { + exaDriverFini(pScreen); + } + xfree(pVia->exaDriverPtr); + pVia->exaDriverPtr = NULL; + viaTearDownCBuffer(&pVia->cb); +#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) { + 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; + } + return; + } +#endif + if (pVia->AccelInfoRec) { + XAADestroyInfoRec(pVia->AccelInfoRec); + pVia->AccelInfoRec = NULL; + viaTearDownCBuffer(&pVia->cb); + } +} + +void +viaFinishInitAccel(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + VIAPtr pVia = VIAPTR(pScrn); + +#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; + } + } +#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 +viaAccelBlitRect(ScrnInfoPtr pScrn, int srcx, int srcy, int w, int h, + int dstx, int dsty) +{ + VIAPtr pVia = VIAPTR(pScrn); + 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 -burN via/via_cursor.c via_new/via_cursor.c --- via/via_cursor.c 2006-01-12 23:58:04.000000000 +0100 +++ via_new/via_cursor.c 2006-01-12 23:57:37.000000000 +0100 @@ -115,7 +115,7 @@ VIAPtr pVia = VIAPTR(pScrn); CARD32 dwCursorMode; - VIAAccelSync(pScrn); + viaAccelSync(pScrn); dwCursorMode = VIAGETREG(VIA_REG_CURSOR_MODE); diff -burN via/via_dga.c via_new/via_dga.c --- via/via_dga.c 2006-01-12 23:58:04.000000000 +0100 +++ via_new/via_dga.c 2006-01-12 23:57:37.000000000 +0100 @@ -36,9 +36,6 @@ 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 @@ VIADGASetMode, VIADGASetViewport, VIADGAGetViewport, - VIAAccelSync, - VIADGAFillRect, - VIADGABlitRect, + viaAccelSyncMarker, + viaAccelFillRect, + viaAccelBlitRect, NULL /* BlitTransRect */ }; @@ -303,39 +300,6 @@ 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 -burN via/via_dmabuffer.h via_new/via_dmabuffer.h --- via/via_dmabuffer.h 1970-01-01 01:00:00.000000000 +0100 +++ via_new/via_dmabuffer.h 2006-01-12 23:57:37.000000000 +0100 @@ -0,0 +1,100 @@ +/* + * Copyright (C) Thomas Hellstrom (2005) + * + * 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_DMABUFFER_H +#define VIA_DMABUFFER_H + +#include "via_3d_reg.h" + +typedef struct _ViaCommandBuffer +{ + ScrnInfoPtr pScrn; + CARD32 *buf; + CARD32 waitFlags; + unsigned pos; + unsigned bufSize; + int mode; + int header_start; + int rindex; + Bool has3dState; + void (*flushFunc) (struct _ViaCommandBuffer * cb); +} ViaCommandBuffer; + +#define VIA_DMASIZE 16384 + +#define H1_ADDR(val) (((val) >> 2) | 0xF0000000) +#define WAITFLAGS(flags) \ + (cb)->waitFlags |= (flags) + +#define BEGIN_RING(size) \ + do { \ + if (cb->flushFunc && (cb->pos > (cb->bufSize-(size)))) { \ + cb->flushFunc(cb); \ + } \ + } while(0) + +#define BEGIN_H2(paraType, h2size) \ + do{ \ + BEGIN_RING((h2size)+6); \ + if (cb->mode == 2 && (paraType) == cb->rindex) \ + break; \ + if (cb->pos & 1) \ + OUT_RING(HC_DUMMY); \ + cb->header_start = cb->pos; \ + cb->rindex = paraType; \ + cb->mode = 2; \ + OUT_RING(HALCYON_HEADER2); \ + OUT_RING((paraType) << 16); \ + if (!cb->has3dState && ((paraType) != HC_ParaType_CmdVdata)) { \ + cb->has3dState = TRUE; \ + } \ + } while(0); + +#define OUT_RING(val) do{ \ + (cb)->buf[(cb)->pos++] = (val); \ + } while(0); + +#define OUT_RING_QW(val1, val2) \ + do { \ + (cb)->buf[(cb)->pos++] = (val1); \ + (cb)->buf[(cb)->pos++] = (val2); \ + } while (0) + +#define ADVANCE_RING \ + cb->flushFunc(cb) + +#define RING_VARS \ + ViaCommandBuffer *cb = &pVia->cb + +#define OUT_RING_H1(val1, val2) \ + OUT_RING_QW(H1_ADDR(val1), val2) + +#define OUT_RING_SubA(val1, val2) \ + OUT_RING(((val1) << HC_SubA_SHIFT) | ((val2) & HC_Para_MASK)) + +extern int viaSetupCBuffer(ScrnInfoPtr pScrn, ViaCommandBuffer * buf, + unsigned size); +extern void viaTearDownCBuffer(ViaCommandBuffer * buf); +extern void viaFlushPCI(ViaCommandBuffer * buf); + +#endif diff -burN via/via_dri.c via_new/via_dri.c --- via/via_dri.c 2006-01-12 23:58:04.000000000 +0100 +++ via_new/via_dri.c 2006-01-12 23:57:37.000000000 +0100 @@ -333,11 +333,40 @@ } 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 +380,7 @@ 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 +621,7 @@ 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 +725,15 @@ 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 +776,8 @@ drmAgpRelease(pVia->drmFD); } - DRICloseScreen(pScreen); + VIAFreeLinear(&pVia->driOffScreenMem); if (pVia->pDRIInfo) { if ((pVIADRI = (VIADRIPtr) pVia->pDRIInfo->devPrivate)) { diff -burN via/via_driver.c via_new/via_driver.c --- via/via_driver.c 2006-01-12 23:58:04.000000000 +0100 +++ via_new/via_driver.c 2006-01-12 23:57:37.000000000 +0100 @@ -124,6 +124,9 @@ OPTION_PCI_BURST, OPTION_PCI_RETRY, OPTION_NOACCEL, +#ifdef VIA_HAVE_EXA + OPTION_ACCELMETHOD, +#endif OPTION_SWCURSOR, OPTION_HWCURSOR, OPTION_SHADOW_FB, @@ -156,6 +159,9 @@ #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}, @@ -262,6 +268,17 @@ NULL }; +#ifdef VIA_HAVE_EXA +static const char *exaSymbols[] = { + "exaGetVersion", + "exaDriverInit", + "exaDriverFini", + "exaOffscreenAlloc", + "exaOffscreenFree", + NULL +}; +#endif + static const char *shadowSymbols[] = { "ShadowFBInit", NULL @@ -355,6 +372,9 @@ fbSymbols, ramdacSymbols, xaaSymbols, +#ifdef VIA_HAVE_EXA + exaSymbols, +#endif shadowSymbols, vbeSymbols, i2cSymbols, @@ -843,6 +863,23 @@ 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"); + } +#endif /* VIA_HAVE_EXA */ if (pVia->shadowFB && !pVia->NoAccel) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, @@ -1351,7 +1388,7 @@ 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 +1435,13 @@ 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 +1519,7 @@ 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 +1528,15 @@ 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 */ @@ -1876,6 +1919,7 @@ vgaHWPtr hwp = VGAHWPTR(pScrn); VIAPtr pVia = VIAPTR(pScrn); + pScrn->pScreen = pScreen; DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIAScreenInit\n")); if (!VIAMapFB(pScrn)) @@ -1961,30 +2005,8 @@ 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);*/ @@ -2027,20 +2049,43 @@ 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) { + + /* + * 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); @@ -2120,9 +2165,9 @@ /* Enable the graphics engine. */ if (!pVia->NoAccel) - VIAInitialize2DEngine(pScrn); + viaInitialize2DEngine(pScrn); -#ifdef XF86DRI +#if defined(XF86DRI) || defined(VIA_HAVE_EXA) VIAInitialize3DEngine(pScrn); #endif @@ -2148,15 +2193,11 @@ 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 */ @@ -2166,16 +2207,13 @@ } 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; @@ -2276,7 +2314,7 @@ DRILock(screenInfo.screens[scrnIndex], 0); #endif - VIAAccelSync(pScrn); + viaAccelSync(pScrn); #ifdef XF86DRI if (pVia->directRenderingEnabled) @@ -2284,7 +2322,7 @@ #endif if (pVia->VQEnable) - ViaVQDisable(pScrn); + viaDisableVQ(pScrn); if (pVia->pVbe) ret = ViaVbeSetMode(pScrn, mode); @@ -2352,7 +2390,7 @@ return; } -#ifdef XF86DRI +#if defined(XF86DRI) || defined(VIA_HAVE_EXA) void VIAInitialize3DEngine(ScrnInfoPtr pScrn) { diff -burN via/via_driver.h via_new/via_driver.h --- via/via_driver.h 2006-01-12 23:58:04.000000000 +0100 +++ via_new/via_driver.h 2006-01-12 23:57:37.000000000 +0100 @@ -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 _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 @@ 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 @@ 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,37 @@ /* 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; +#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; @@ -265,6 +305,10 @@ Bool IsPCI; Bool drixinerama; ViaXvMC xvmc; + int drmVerMajor; + int drmVerMinor; + int drmVerPL; + VIAMem driOffScreenMem; #endif Bool DRIIrqEnable; Bool agpEnable; @@ -317,7 +361,7 @@ } VIAEntRec, *VIAEntPtr; /* Prototypes. */ -#ifdef XF86DRI +#if defined(XF86DRI) || defined(VIA_HAVE_EXA) void VIAInitialize3DEngine(ScrnInfoPtr pScrn); #endif @@ -329,10 +373,19 @@ 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 -burN via/via_memcpy.c via_new/via_memcpy.c --- via/via_memcpy.c 2006-01-12 23:58:05.000000000 +0100 +++ via_new/via_memcpy.c 2006-01-12 23:57:37.000000000 +0100 @@ -546,7 +546,6 @@ double cpuFreq; VIAPtr pVia = VIAPTR(pScrn); - pScrn->pScreen = pScreen; if (NULL == (cpuInfoFile = fopen("/proc/cpuinfo","r"))) { return libc_YUV42X; } diff -burN via/via_memory.c via_new/via_memory.c --- via/via_memory.c 2006-01-12 23:58:05.000000000 +0100 +++ via_new/via_memory.c 2006-01-12 23:57:37.000000000 +0100 @@ -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 @@ 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 @@ 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 @@ 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 @@ 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 -burN via/via_priv.h via_new/via_priv.h --- via/via_priv.h 2006-01-12 23:58:06.000000000 +0100 +++ via_new/via_priv.h 2006-01-12 23:57:37.000000000 +0100 @@ -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 @@ 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 -burN via/via_vbe.c via_new/via_vbe.c --- via/via_vbe.c 2006-01-12 23:58:06.000000000 +0100 +++ via_new/via_vbe.c 2006-01-12 23:57:37.000000000 +0100 @@ -161,7 +161,7 @@ pScrn->vtSema = TRUE; if (!pVia->NoAccel) - VIAInitialize2DEngine(pScrn); + viaInitialize2DEngine(pScrn); #ifdef XF86DRI VIAInitialize3DEngine(pScrn);