Index: src/Makefile.am =================================================================== RCS file: /cvs/xorg/driver/xf86-video-mga/src/Makefile.am,v retrieving revision 1.4 diff -u -p -r1.4 Makefile.am --- src/Makefile.am 14 Aug 2005 00:18:25 -0000 1.4 +++ src/Makefile.am 20 Mar 2006 21:54:58 -0000 @@ -56,6 +56,7 @@ mga_drv_la_SOURCES = \ mga_dh.c \ mga_driver.c \ mga_esc.c \ + mga_exa.c \ mga_g450pll.c \ mga.h \ mga_halmod.c \ Index: src/mga.h =================================================================== RCS file: /cvs/xorg/driver/xf86-video-mga/src/mga.h,v retrieving revision 1.11 diff -u -p -r1.11 mga.h --- src/mga.h 9 Nov 2005 21:31:20 -0000 1.11 +++ src/mga.h 20 Mar 2006 21:54:59 -0000 @@ -16,6 +16,7 @@ #include "compiler.h" #include "xaa.h" +#include "exa.h" #include "xf86Cursor.h" #include "vgaHW.h" #include "colormapst.h" @@ -87,7 +88,8 @@ typedef enum { OPTION_MONITOR2POS, OPTION_METAMODES, OPTION_OLDDMA, - OPTION_PCIDMA + OPTION_PCIDMA, + OPTION_ACCELMETHOD } MGAOpts; @@ -407,6 +409,8 @@ typedef struct { MGARamdacRec Dac; Bool HasSDRAM; Bool NoAccel; + Bool Exa; + ExaDriverPtr ExaDriver; Bool SyncOnGreen; Bool Dac6Bit; Bool HWCursor; Index: src/mga_driver.c =================================================================== RCS file: /cvs/xorg/driver/xf86-video-mga/src/mga_driver.c,v retrieving revision 1.18 diff -u -p -r1.18 mga_driver.c --- src/mga_driver.c 9 Sep 2005 23:15:45 -0000 1.18 +++ src/mga_driver.c 20 Mar 2006 21:54:59 -0000 @@ -225,6 +225,7 @@ static const OptionInfoRec MGAOptions[] { OPTION_METAMODES, "MetaModes", OPTV_ANYSTR, {0}, FALSE }, { OPTION_OLDDMA, "OldDmaInit", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_PCIDMA, "ForcePciDma", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_ACCELMETHOD, "AccelMethod", OPTV_ANYSTR, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; @@ -269,6 +270,14 @@ static const char *xf8_32bppSymbols[] = NULL }; +static const char *exaSymbols[] = { + "exaDriverInit", + "exaDriverFini", + "exaGetPixmapOffset", + "exaGetVersion", + NULL +}; + static const char *xaaSymbols[] = { "XAACachePlanarMonoStipple", "XAACreateInfoRec", @@ -446,7 +455,7 @@ mgaSetup(pointer module, pointer opts, i * Tell the loader about symbols from other modules that this module * might refer to. */ - LoaderRefSymLists(vgahwSymbols, xaaSymbols, + LoaderRefSymLists(vgahwSymbols, xaaSymbols, exaSymbols, xf8_32bppSymbols, ramdacSymbols, ddcSymbols, i2cSymbols, shadowSymbols, fbdevHWSymbols, vbeSymbols, @@ -1432,6 +1441,17 @@ MGAPreInit(ScrnInfoPtr pScrn, int flags) if (xf86ReturnOptValBool(pMga->Options, OPTION_NOACCEL, FALSE)) { pMga->NoAccel = TRUE; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); + } else { + int from = X_DEFAULT; + char *s = xf86GetOptValString(pMga->Options, OPTION_ACCELMETHOD); + pMga->NoAccel = FALSE; + pMga->Exa = FALSE; + if (!xf86NameCmp(s, "EXA")) { + pMga->Exa = TRUE; + from = X_CONFIG; + } + xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration\n", + pMga->Exa ? "EXA" : "XAA"); } if (xf86ReturnOptValBool(pMga->Options, OPTION_PCI_RETRY, FALSE)) { pMga->UsePCIRetry = TRUE; @@ -2255,11 +2275,17 @@ MGAPreInit(ScrnInfoPtr pScrn, int flags) /* Load XAA if needed */ if (!pMga->NoAccel) { - if (!xf86LoadSubModule(pScrn, "xaa")) { - MGAFreeRec(pScrn); - return FALSE; + if (pMga->Exa) { + if (!xf86LoadSubModule(pScrn, "exa")) { + MGAFreeRec(pScrn); + return FALSE; + } else xf86LoaderReqSymLists(exaSymbols, NULL); + } else { + if (!xf86LoadSubModule(pScrn, "xaa")) { + MGAFreeRec(pScrn); + return FALSE; + } else xf86LoaderReqSymLists(xaaSymbols, NULL); } - xf86LoaderReqSymLists(xaaSymbols, NULL); } /* Load ramdac if needed */ @@ -3237,8 +3263,12 @@ MGAScreenInit(int scrnIndex, ScreenPtr p if(!pMga->ShadowFB) /* hardware cursor needs to wrap this layer */ MGADGAInit(pScreen); - if (!pMga->NoAccel) - MGAStormAccelInit(pScreen); + if (!pMga->NoAccel) { + if (pMga->Exa) + mgaExaInit(pScreen); + else + MGAStormAccelInit(pScreen); + } miInitializeBackingStore(pScreen); xf86SetBackingStore(pScreen); @@ -3745,6 +3775,10 @@ MGACloseScreen(int scrnIndex, ScreenPtr if (pMga->AccelInfoRec) XAADestroyInfoRec(pMga->AccelInfoRec); + if (pMga->ExaDriver) { + exaDriverFini(pScreen); + xfree(pMga->ExaDriver); + } if (pMga->CursorInfoRec) xf86DestroyCursorInfoRec(pMga->CursorInfoRec); if (pMga->ShadowPtr) Index: src/mga_exa.c =================================================================== RCS file: src/mga_exa.c diff -N src/mga_exa.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/mga_exa.c 20 Mar 2006 21:54:59 -0000 @@ -0,0 +1,711 @@ +/* + * Copyright 2006 Red Hat, Inc. + * + * 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 + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * them 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 MERCHANTIBILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS 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. + * + * Authors: + * Adam Jackson + */ + +/* + * Sources: + * - mga kdrive accel by Anders Carlsson + * - mga g400 Render accel by Damien Ciabrini + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" + +#include "mga.h" +#include "mga_reg.h" +#include "mga_macros.h" + +#include "exa.h" +#ifdef XF86DRI +#include "mga_dri.h" +#endif + +#if 0 +#define DEBUG_MSG(x) ErrorF x +#else +#define DEBUG_MSG(x) +#endif + +#define PMGA(x) \ + MGAPtr pMga = xf86Screens[x->drawable.pScreen->myNum]->driverPrivate; +#define QUIESCE_DMA(x) + +/* stuff stolen from mga_storm.c */ +#define BLIT_LEFT 1 +#define BLIT_UP 4 + +static const CARD32 mgaRop[16] = { + /* GXclear */ MGADWG_RPL | 0x00000000, /* 0 */ + /* GXand */ MGADWG_RSTR | 0x00080000, /* src AND dst */ + /* GXandReverse */ MGADWG_RSTR | 0x00040000, /* src AND NOT dst */ + /* GXcopy */ MGADWG_RSTR | 0x000c0000, /* src */ + /* GXandInverted */ MGADWG_RSTR | 0x00020000, /* NOT src AND dst */ + /* GXnoop */ MGADWG_RSTR | 0x000a0000, /* dst */ + /* GXxor */ MGADWG_RSTR | 0x00060000, /* src XOR dst */ + /* GXor */ MGADWG_RSTR | 0x000e0000, /* src OR dst */ + /* GXnor */ MGADWG_RSTR | 0x00010000, /* NOT src AND NOT dst */ + /* GXequiv */ MGADWG_RSTR | 0x00090000, /* NOT src XOR dst */ + /* GXinvert */ MGADWG_RSTR | 0x00050000, /* NOT dst */ + /* GXorReverse */ MGADWG_RSTR | 0x000d0000, /* src OR NOT dst */ + /* GXcopyInverted */ MGADWG_RPL | 0x00030000, /* NOT src */ + /* GXorInverted */ MGADWG_RSTR | 0x000b0000, /* NOT src OR dst */ + /* GXnand */ MGADWG_RSTR | 0x00070000, /* NOT src OR NOT dst */ + /* GXset */ MGADWG_RPL | 0x000f0000 /* 1 */ +}; + +static const CARD32 atype[16] = { + MGADWG_RPL | 0x00000000, MGADWG_RSTR | 0x00080000, + MGADWG_RSTR | 0x00040000, MGADWG_BLK | 0x000c0000, + MGADWG_RSTR | 0x00020000, MGADWG_RSTR | 0x000a0000, + MGADWG_RSTR | 0x00060000, MGADWG_RSTR | 0x000e0000, + MGADWG_RSTR | 0x00010000, MGADWG_RSTR | 0x00090000, + MGADWG_RSTR | 0x00050000, MGADWG_RSTR | 0x000d0000, + MGADWG_RPL | 0x00030000, MGADWG_RSTR | 0x000b0000, + MGADWG_RSTR | 0x00070000, MGADWG_RPL | 0x000f0000 +}; + +static const CARD32 atype_noblk[16] = { + MGADWG_RPL | 0x00000000, MGADWG_RSTR | 0x00080000, + MGADWG_RSTR | 0x00040000, MGADWG_RPL | 0x000c0000, + MGADWG_RSTR | 0x00020000, MGADWG_RSTR | 0x000a0000, + MGADWG_RSTR | 0x00060000, MGADWG_RSTR | 0x000e0000, + MGADWG_RSTR | 0x00010000, MGADWG_RSTR | 0x00090000, + MGADWG_RSTR | 0x00050000, MGADWG_RSTR | 0x000d0000, + MGADWG_RPL | 0x00030000, MGADWG_RSTR | 0x000b0000, + MGADWG_RSTR | 0x00070000, MGADWG_RPL | 0x000f0000 +}; + +static CARD32 +mgaGetPixmapPitch(PixmapPtr pPix) +{ + return exaGetPixmapPitch(pPix) / (pPix->drawable.bitsPerPixel >> 3); +} + +static void +mgaNoopDone(PixmapPtr pPixmap) +{ +} + +static Bool +mgaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg) +{ + PMGA(pPixmap); + QUIESCE_DMA(); + + pMga->FilledRectCMD = MGADWG_TRAP | MGADWG_SOLID | MGADWG_ARZERO | + MGADWG_SGNZERO | MGADWG_SHIFTZERO | mgaRop[alu]; + + WAITFIFO(5); + OUTREG(MGAREG_PITCH, mgaGetPixmapPitch(pPixmap)); + OUTREG(MGAREG_DSTORG, exaGetPixmapOffset(pPixmap)); + OUTREG(MGAREG_FCOL, fg); + OUTREG(MGAREG_PLNWT, planemask); + OUTREG(MGAREG_DWGCTL, pMga->FilledRectCMD); + + return TRUE; +} + +static void +mgaSolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2) +{ + PMGA(pPixmap); + + WAITFIFO(2); + OUTREG(MGAREG_FXBNDRY, (x2 << 16) | (x1 & 0xffff)); + OUTREG(MGAREG_YDSTLEN | MGAREG_EXEC, (y1 << 16) | (y2 - y1)); +} + +static CARD32 src_pitch; /* kill me */ + +static Bool +mgaPrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, int xdir, int ydir, int alu, + Pixel planemask) +{ + PMGA(pSrc); + int blit_direction = 0; + int dwgctl = 0; + + QUIESCE_DMA(); + + DEBUG_MSG(("s: %x@%x d: %x@%x xdir %d ydir %d alu %d pm %d\n", + exaGetPixmapOffset(pSrc), exaGetPixmapPitch(pSrc), + exaGetPixmapOffset(pDst), exaGetPixmapPitch(pDst), + xdir, ydir, alu, planemask)); + + if (xdir < 0) blit_direction |= BLIT_LEFT; + if (ydir < 0) blit_direction |= BLIT_UP; + pMga->BltScanDirection = blit_direction; + + dwgctl = mgaRop[alu] | MGADWG_SHIFTZERO | MGADWG_BITBLT | MGADWG_BFCOL; + src_pitch = mgaGetPixmapPitch(pSrc); + + WAITFIFO(7); + OUTREG(MGAREG_PITCH, mgaGetPixmapPitch(pDst)); + OUTREG(MGAREG_SRCORG, exaGetPixmapOffset(pSrc)); + OUTREG(MGAREG_DSTORG, exaGetPixmapOffset(pDst)); + OUTREG(MGAREG_DWGCTL, dwgctl); + OUTREG(MGAREG_SGN, blit_direction); + OUTREG(MGAREG_PLNWT, planemask); + /* this is crap */ + OUTREG(MGAREG_AR5, (ydir < -0 ? -1 : 1) * src_pitch); + + return TRUE; +} + +/* this whole thing is bogus. */ +static void +mgaCopy(PixmapPtr pDst, int srcx, int srcy, int dstx, int dsty, int w, int h) +{ + PMGA(pDst); + int start, end; + + DEBUG_MSG((" %d,%d -> %d,%d %dx%d\n", srcx, srcy, dstx,dsty, w, h)); + + w--; + if (pMga->BltScanDirection & BLIT_UP) { + srcy += h - 1; + dsty += h - 1; + } + start = end = srcy * src_pitch + srcx; + if (pMga->BltScanDirection & BLIT_LEFT) + start += w; + else + end += w; + + DEBUG_MSG((" end %d start %d dstx %d dsty %d w %d h %d\n", + end, start, dstx, dsty, w, h)); + WAITFIFO(4); + OUTREG(MGAREG_AR0, end); + OUTREG(MGAREG_AR3, start); + OUTREG(MGAREG_FXBNDRY, ((dstx + w) << 16) | (dstx & 0xffff)); + OUTREG(MGAREG_YDSTLEN | MGAREG_EXEC, (dsty << 16) | h); +} + +/* XXX move these into pMga */ +static PicturePtr currentSrcPicture; +static PicturePtr currentMaskPicture; +static PixmapPtr currentSrc; +static PixmapPtr currentMask; +static int src_w2; +static int src_h2; +static int mask_w2; +static int mask_h2; + +struct blendinfo { + Bool dst_alpha; + Bool src_alpha; + CARD32 blend_cntl; +}; + +static const struct blendinfo mgaBlendOp[] = { + {0, 0, MGA_SRC_ZERO | MGA_DST_ZERO}, + {0, 0, MGA_SRC_ONE | MGA_DST_ZERO}, + {0, 0, MGA_SRC_ZERO | MGA_DST_ONE}, + {0, 1, MGA_SRC_ONE | MGA_DST_ONE_MINUS_SRC_ALPHA}, + {1, 0, MGA_SRC_ONE_MINUS_DST_ALPHA | MGA_DST_ONE}, + {1, 0, MGA_SRC_DST_ALPHA | MGA_DST_ZERO}, + {0, 1, MGA_SRC_ZERO | MGA_DST_SRC_ALPHA}, + {1, 0, MGA_SRC_ONE_MINUS_DST_ALPHA | MGA_DST_ZERO}, + {0, 1, MGA_SRC_ZERO | MGA_DST_ONE_MINUS_SRC_ALPHA}, + {1, 1, MGA_SRC_DST_ALPHA | MGA_DST_ONE_MINUS_SRC_ALPHA}, + {1, 1, MGA_SRC_ONE_MINUS_DST_ALPHA | MGA_DST_SRC_ALPHA}, + {1, 1, MGA_SRC_ONE_MINUS_DST_ALPHA | MGA_DST_ONE_MINUS_SRC_ALPHA}, + {0, 0, MGA_SRC_ONE | MGA_DST_ONE}, +}; + +struct formatinfo { + int fmt; + CARD32 card_fmt; +}; + +static const struct formatinfo texformats[] = { + { PICT_a8r8g8b8, MGA_TW32 }, + { PICT_x8r8g8b8, MGA_TW32 }, + { PICT_r5g6b5, MGA_TW16 }, + { PICT_a1r5g5b5, MGA_TW15 }, + { PICT_x1r5g5b5, MGA_TW15 }, + { PICT_a4r4g4b4, MGA_TW12 }, + { PICT_x4r4g4b4, MGA_TW12 }, + { PICT_a8, MGA_TW8A }, +}; + +static int +MGA_LOG2( int val ) +{ + int ret = 0; + if (val==1) return 0; + while (val >> ret) + ret++; + + return ((1 << (ret-1)) == val) ? (ret-1) : ret; +} + +static Bool +mgaCheckSourceTexture(int tmu, PicturePtr pPict) +{ + int w = pPict->pDrawable->width; + int h = pPict->pDrawable->height; + int i; + CARD32 texctl = 0; + + if ((w > 2047) || (h > 2047)){ + DEBUG_MSG(("Picture w/h too large (%dx%d)\n", w, h)); + return FALSE; + } + + for (i = 0; i < sizeof(texformats) / sizeof(texformats[0]); i++) { + if (texformats[i].fmt == pPict->format) { + texctl = texformats[i].card_fmt; + break; + } + } + if (texctl == 0) { + DEBUG_MSG(("Unsupported picture format 0x%x\n", pPict->format)); + return FALSE; + } + + if (pPict->repeat && ((w & (w - 1)) != 0 || (h & (h - 1)) != 0)) { + DEBUG_MSG(("NPOT repeat unsupported (%dx%d)\n", w, h)); + return FALSE; + } + + if (pPict->filter != PictFilterNearest && + pPict->filter != PictFilterBilinear) { + DEBUG_MSG(("Unsupported filter 0x%x\n", pPict->filter)); + return FALSE; + } + + return TRUE; +} + +static Bool +mgaCheckComposite(int op, PicturePtr pSrcPict, PicturePtr pMaskPict, + PicturePtr pDstPict) +{ + if (op >= sizeof(mgaBlendOp) / sizeof(mgaBlendOp[0])) { + DEBUG_MSG(("unsupported op %x", op)); + return FALSE; + } + + if (!mgaCheckSourceTexture(0, pSrcPict)) + return FALSE; + + if (pMaskPict!= NULL) { + if (PICT_FORMAT_A(pMaskPict->format) == 0) { + DEBUG_MSG(("Mask without alpha unsupported")); + return FALSE; + } + if (!mgaCheckSourceTexture(1, pMaskPict)) + return FALSE; + if (pMaskPict->componentAlpha) { + DEBUG_MSG(("Component alpha unsupported")); + return FALSE; + } + } + + switch (pDstPict->format) { + case PICT_a8: + DEBUG_MSG(("render to A8 unsupported")); + return FALSE; + default: + break; + } + + return TRUE; +} + +static Bool +PrepareSourceTexture(int tmu, PicturePtr pSrcPicture, PixmapPtr pSrc) +{ + PMGA(pSrc); + int i; + int pitch = mgaGetPixmapPitch(pSrc); + int w = pSrc->drawable.width; + int h = pSrc->drawable.height; + int w_log2 = MGA_LOG2(w); + int h_log2 = MGA_LOG2(h); + + int texctl = MGA_PITCHLIN | ((pitch & (2048 - 1)) << 9) | + MGA_CLAMPUV | MGA_NOPERSPECTIVE; + int flags = 0; + int texctl2 = MGA_G400_TC2_MAGIC | flags; + + for (i = 0; i < sizeof(texformats) / sizeof(texformats[0]); i++) { + if (texformats[i].fmt == pSrcPicture->format) { + texctl |= texformats[i].card_fmt; + break; + } + } + + if (PICT_FORMAT_A(pSrcPicture->format) != 0) { + texctl |= MGA_TAKEY; + } else { + texctl |= MGA_TAMASK | MGA_TAKEY; + } + + if (pSrcPicture->repeat) { + texctl &= ~MGA_CLAMPUV; + } + + if (tmu == 1) + texctl2 |= MGA_TC2_DUALTEX | MGA_TC2_SELECT_TMU1 | flags; + + WAITFIFO(6); + OUTREG(MGAREG_TEXCTL2, texctl2); + OUTREG(MGAREG_TEXCTL, texctl); + /* Source (texture) address + pitch */ + OUTREG(MGAREG_TEXORG, exaGetPixmapOffset(pSrc)); + OUTREG(MGAREG_TEXWIDTH, (w-1)<<18 | ((8-w_log2)&63)<<9 | w_log2); + OUTREG(MGAREG_TEXHEIGHT, (h-1)<<18 | ((8-h_log2)&63)<<9 | h_log2); + /* Set blit filtering flags */ + if (pSrcPicture->filter == PictFilterBilinear) + OUTREG(MGAREG_TEXFILTER, (0x10<<21) | MGA_MAG_BILIN | MGA_MIN_BILIN); + else + OUTREG(MGAREG_TEXFILTER, (0x10<<21) | MGA_MAG_NRST | MGA_MIN_NRST); + + if (tmu == 1) { + WAITFIFO(1); + OUTREG(MGAREG_TEXCTL2, MGA_G400_TC2_MAGIC | MGA_TC2_DUALTEX | flags); + } + + return TRUE; +} + +static void +setTMIncrementsRegs(PixmapPtr pPix, int X_incx, int X_incy, int X_init, + int Y_incx, int Y_incy, int Y_init, + int H_incx, int H_incy, int H_init) { + PMGA(pPix); + int mga_fx_width_size, mga_fx_height_size; + int decalw = mga_fx_width_size - 16; + int decalh = mga_fx_height_size - 16; + + mga_fx_width_size = 20 - MGA_LOG2(pPix->drawable.width); + mga_fx_height_size = 20 - MGA_LOG2(pPix->drawable.height); + + /* Convert 16 bits fixpoint -> MGA variable size fixpoint */ + if (decalw >= 0) { + X_incx = X_incx << decalw; + X_incy = X_incy << decalw; + X_init = X_init << decalw; + } else { + decalw =- decalw; + X_incx = X_incx >> decalw; + X_incy = X_incy >> decalw; + X_init = X_init >> decalw; + } + + /* Convert 16 bits fixpoint -> MGA variable size fixpoint */ + if (decalh >= 0) { + Y_incx = Y_incx << decalh; + Y_incy = Y_incy << decalh; + Y_init = Y_init << decalh; + } else { + decalh =- decalh; + Y_incx = Y_incx >> decalh; + Y_incy = Y_incy >> decalh; + Y_init = Y_init >> decalh; + } + + /* Set TM registers */ + WAITFIFO(9); + OUTREG(MGAREG_TMR0, X_incx); + OUTREG(MGAREG_TMR1, Y_incx); + OUTREG(MGAREG_TMR2, X_incy); + OUTREG(MGAREG_TMR3, Y_incy); + OUTREG(MGAREG_TMR4, H_incx); + OUTREG(MGAREG_TMR5, H_incy); + OUTREG(MGAREG_TMR6, X_init); + OUTREG(MGAREG_TMR7, Y_init); + OUTREG(MGAREG_TMR8, H_init); +} + +/* XXX these look like magic */ +#define C_ARG1_CUR 0x0 +#define C_ARG1_ALPHA MGA_TDS_COLOR_ARG1_REPLICATEALPHA +#define C_ARG2_DIFFUSE MGA_TDS_COLOR_ARG2_DIFFUSE +#define C_ARG2_FCOL MGA_TDS_COLOR_ARG2_FCOL +#define C_ARG2_PREV MGA_TDS_COLOR_ARG2_PREVSTAGE +#define C_ARG1_INV MGA_TDS_COLOR_ARG1_INV +#define C_ARG2_INV MGA_TDS_COLOR_ARG2_INV +#define COLOR_MUL MGA_TDS_COLOR_SEL_MUL +#define COLOR_ARG1 MGA_TDS_COLOR_SEL_ARG1 +#define COLOR_ARG2 MGA_TDS_COLOR_SEL_ARG2 +#define A_ARG1_CUR 0x0 +#define A_ARG2_IGN A_ARG2_DIFFUSE +#define A_ARG2_FCOL MGA_TDS_ALPHA_ARG2_FCOL +#define A_ARG2_DIFFUSE MGA_TDS_ALPHA_ARG2_DIFFUSE +#define A_ARG2_PREV MGA_TDS_ALPHA_ARG2_PREVSTAGE +#define ALPHA_MUL MGA_TDS_ALPHA_SEL_MUL +#define ALPHA_ARG1 MGA_TDS_ALPHA_SEL_ARG1 +#define ALPHA_ARG2 MGA_TDS_ALPHA_SEL_ARG2 + +static Bool +mgaPrepareComposite(int op, PicturePtr pSrcPict, PicturePtr pMaskPict, + PicturePtr pDstPict, PixmapPtr pSrc, PixmapPtr pMask, + PixmapPtr pDst) +{ + PMGA(pDst); + CARD32 ds0 = 0, ds1 = 0, cmd, blendcntl; + + WAITFIFO(3); + OUTREG(MGAREG_FCOL, 0xff000000); + OUTREG(MGAREG_DSTORG, exaGetPixmapOffset(pDst)); + OUTREG(MGAREG_PITCH, mgaGetPixmapPitch(pDst)); + + if (!PrepareSourceTexture(0, pSrcPict, pSrc)) return FALSE; + if (pMask != NULL) { + if (!PrepareSourceTexture(1, pMaskPict, pMask)) return FALSE; + } + + if (pSrcPict->format == PICT_a8) { + /* C = 0 A = As */ + /* MGA HW: A8 format makes RGB white. We use FCOL for the black + * If FCOL was not 0, it would have been be premultiplied (RENDER) + * color component would have been: + * C_ARG1_ALPHA | C_ARG2_FCOL | COLOR_MUL + */ + ds0=C_ARG2_FCOL | COLOR_ARG2 | + A_ARG1_CUR | ALPHA_ARG1; + /* MGA HW: TMU1 must be enabled when DUALSTAGE0 contains something */ + if (pMask == NULL) { + if (!PrepareSourceTexture(1, pSrcPict, pSrc)) return FALSE; + ds1=C_ARG2_PREV | COLOR_ARG2 | + A_ARG2_PREV | ALPHA_ARG2; + } + } else { + /* C = Cs A = As */ + ds0=C_ARG1_CUR | COLOR_ARG1 | + A_ARG1_CUR | ALPHA_ARG1; + } + + if (pMask != NULL) { + /* As or Am might be NULL. in this case we don't multiply because, + * the alpha component holds garbage. + */ + int color,alpha; + if (PICT_FORMAT_A(pMaskPict->format) == 0) { + /* C = Cs */ + color = C_ARG2_PREV | COLOR_ARG2; + } else { + /* C = Am * Cs */ + color = C_ARG1_ALPHA | C_ARG2_PREV | COLOR_MUL; + } + + if (PICT_FORMAT_A(pMaskPict->format) == 0) { + /* A = As */ + alpha = A_ARG2_PREV | ALPHA_ARG2; + } else if (PICT_FORMAT_A(pSrcPict->format) == 0) { + /* A = Am */ + alpha = A_ARG1_CUR | ALPHA_ARG1; + } else { + /* A = Am * As */ + alpha = A_ARG1_CUR | A_ARG2_PREV | ALPHA_MUL; + } + + ds1 = color | alpha; + } + + cmd = MGADWG_TEXTURE_TRAP | MGADWG_I | 0x000c0000 | + MGADWG_SHIFTZERO | MGADWG_SGNZERO | MGADWG_ARZERO; + blendcntl = mgaBlendOp[op].blend_cntl; + if (PICT_FORMAT_A(pDstPict->format) == 0 && mgaBlendOp[op].dst_alpha) { + if ((blendcntl & MGA_SRC_BLEND_MASK) == MGA_SRC_DST_ALPHA) + blendcntl = (blendcntl & ~MGA_SRC_BLEND_MASK) | MGA_SRC_ONE; + else if ((blendcntl&MGA_SRC_BLEND_MASK) == MGA_SRC_ONE_MINUS_DST_ALPHA) + blendcntl = (blendcntl & ~MGA_SRC_BLEND_MASK) | MGA_SRC_ZERO; + } + + WAITFIFO(4); + OUTREG(MGAREG_TDUALSTAGE0, ds0); + OUTREG(MGAREG_TDUALSTAGE1, ds1); + OUTREG(MGAREG_DWGCTL, cmd); + OUTREG(MGAREG_ALPHACTRL, MGA_ALPHACHANNEL | blendcntl); + + currentSrcPicture = pSrcPict; + currentMaskPicture = pMaskPict; + currentSrc = pSrc; + currentMask = pMask; + src_w2 = MGA_LOG2 (currentSrc->drawable.width); + src_h2 = MGA_LOG2 (currentSrc->drawable.height); + if (currentMask) { + mask_w2 = MGA_LOG2 (currentMask->drawable.width); + mask_h2 = MGA_LOG2 (currentMask->drawable.height); + } + + return TRUE; +} + +static void +mgaComposite(PixmapPtr pDst, int srcx, int srcy, int maskx, int masky, + int dstx, int dsty, int w, int h) +{ + PMGA(pDst); + + srcx %= currentSrc->drawable.width; + srcy %= currentSrc->drawable.height; + if (currentMask) { + maskx %= currentMask->drawable.width; + maskx %= currentMask->drawable.height; + } + + if (currentSrcPicture->transform) + setTMIncrementsRegs(currentSrc, + currentSrcPicture->transform->matrix[0][0], + currentSrcPicture->transform->matrix[0][1], + currentSrcPicture->transform->matrix[0][2] + + (srcx << 16), + currentSrcPicture->transform->matrix[1][0], + currentSrcPicture->transform->matrix[1][1], + currentSrcPicture->transform->matrix[1][2] + + (srcy << 16), + currentSrcPicture->transform->matrix[2][0], + currentSrcPicture->transform->matrix[2][1], + currentSrcPicture->transform->matrix[2][2]); + else + setTMIncrementsRegs(currentSrc, + 1 << 16, 0, srcx << 16, + 0, 1 << 16, srcy << 16, + 0, 0, 0x10000); + + if (currentMask) { + WAITFIFO(1); + OUTREG(MGAREG_TEXCTL2, + MGA_G400_TC2_MAGIC | MGA_TC2_DUALTEX | MGA_TC2_SELECT_TMU1); + if (currentMaskPicture->transform) + setTMIncrementsRegs(currentMask, + currentMaskPicture->transform->matrix[0][0], + currentMaskPicture->transform->matrix[0][1], + currentMaskPicture->transform->matrix[0][2] + + (maskx << 16), + currentMaskPicture->transform->matrix[1][0], + currentMaskPicture->transform->matrix[1][1], + currentMaskPicture->transform->matrix[1][2] + + (masky << 16), + currentMaskPicture->transform->matrix[2][0], + currentMaskPicture->transform->matrix[2][1], + currentMaskPicture->transform->matrix[2][2]); + else + setTMIncrementsRegs(currentMask, + 1 << 16, 0, maskx << 16, + 0, 1 << 16, masky << 16, + 0, 0, 0x10000); + + WAITFIFO(1); + OUTREG(MGAREG_TEXCTL2, MGA_G400_TC2_MAGIC | MGA_TC2_DUALTEX); + } + + WAITFIFO(2); + OUTREG(MGAREG_FXBNDRY, ((dstx + w) << 16) | (dstx & 0xffff)); + OUTREG(MGAREG_YDSTLEN | MGAREG_EXEC, (dsty << 16) | (h & 0xffff)); +} + +static Bool +mgaUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, + int src_pitch) +{ +} + +static Bool +mgaDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, char *dst, + int dst_pitch) +{ +} + +static void +mgaWaitMarker(ScreenPtr pScreen, int marker) +{ +} + +Bool +mgaExaInit(ScreenPtr pScreen) +{ + ExaDriverPtr pExa; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + MGAPtr pMga = pScrn->driverPrivate; + + if (exaGetVersion() < EXA_MAKE_VERSION(0, 2, 0)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "EXA version is too old " + "(got 0x%3x, need >= 0x020)\n", exaGetVersion()); + return FALSE; + } + + if (!(pExa = calloc(1, sizeof(*pExa)))) { + pMga->NoAccel = TRUE; + return FALSE; + } + pMga->ExaDriver = pExa; + + pExa->card.flags = EXA_OFFSCREEN_PIXMAPS | EXA_OFFSCREEN_ALIGN_POT; + pExa->card.memoryBase = pMga->FbStart; + pExa->card.memorySize = pMga->FbUsableSize - 4096; + pExa->card.offScreenBase = (pScrn->virtualX * pScrn->virtualY * + pScrn->bitsPerPixel/8) + 4096; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "X %d Y %d bpp %d\n", + pScrn->virtualX, pScrn->virtualY, pScrn->bitsPerPixel); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Start at %p, size %x, osb %x\n", + pExa->card.memoryBase, pExa->card.memorySize, + pExa->card.offScreenBase); + + pExa->card.pixmapOffsetAlign = 64; + pExa->card.pixmapPitchAlign = 64; + pExa->card.maxX = 2048; + pExa->card.maxY = 2048; + + pExa->accel.WaitMarker = mgaWaitMarker; + pExa->accel.PrepareSolid = mgaPrepareSolid; + pExa->accel.Solid = mgaSolid; + pExa->accel.DoneSolid = mgaNoopDone; + pExa->accel.PrepareCopy = mgaPrepareCopy; + pExa->accel.Copy = mgaCopy; + pExa->accel.DoneCopy = mgaNoopDone; + + if (1) { + pExa->accel.CheckComposite = mgaCheckComposite; + pExa->accel.PrepareComposite = mgaPrepareComposite; + pExa->accel.Composite = mgaComposite; + pExa->accel.DoneComposite = mgaNoopDone; + } + + if (0) { + pExa->accel.DownloadFromScreen = mgaDownloadFromScreen; + pExa->accel.UploadToScreen = mgaUploadToScreen; + } + + /* XXX fill in the XAA setup code here */ +#if 0 + if(pMga->HasSDRAM) { + pMga->Atype = pMga->AtypeNoBLK = atype_noblk; + } else { + pMga->Atype = atype; + pMga->AtypeNoBLK = atype_noblk; + } +#endif + + return exaDriverInit(pScreen, pExa); +} Index: src/mga_reg.h =================================================================== RCS file: /cvs/xorg/driver/xf86-video-mga/src/mga_reg.h,v retrieving revision 1.2 diff -u -p -r1.2 mga_reg.h --- src/mga_reg.h 23 Apr 2004 19:37:16 -0000 1.2 +++ src/mga_reg.h 20 Mar 2006 21:55:01 -0000 @@ -465,14 +465,114 @@ #define MGAREG_TEXWIDTH 0x2c28 #define MGAREG_TEXHEIGHT 0x2c2c #define MGAREG_TEXCTL 0x2c30 +# define MGA_TW4 (0x00000000) +# define MGA_TW8 (0x00000001) +# define MGA_TW15 (0x00000002) +# define MGA_TW16 (0x00000003) +# define MGA_TW12 (0x00000004) +# define MGA_TW32 (0x00000006) +# define MGA_TW8A (0x00000007) +# define MGA_TW8AL (0x00000008) +# define MGA_TW422 (0x0000000A) +# define MGA_TW422UYVY (0x0000000B) +# define MGA_PITCHLIN (0x00000100) +# define MGA_NOPERSPECTIVE (0x00200000) +# define MGA_TAKEY (0x02000000) +# define MGA_TAMASK (0x04000000) +# define MGA_CLAMPUV (0x18000000) #define MGAREG_TEXCTL2 0x2c3c +# define MGA_G400_TC2_MAGIC (0x00008000) +# define MGA_TC2_DECALBLEND (0x00000001) +# define MGA_TC2_IDECAL (0x00000002) +# define MGA_TC2_DECALDIS (0x00000004) +# define MGA_TC2_CKSTRANSDIS (0x00000010) +# define MGA_TC2_BORDEREN (0x00000020) +# define MGA_TC2_SPECEN (0x00000040) +# define MGA_TC2_DUALTEX (0x00000080) +# define MGA_TC2_TABLEFOG (0x00000100) +# define MGA_TC2_BUMPMAP (0x00000200) +# define MGA_TC2_SELECT_TMU1 (0x80000000) #define MGAREG_TEXTRANS 0x2c34 #define MGAREG_TEXTRANSHIGH 0x2c38 #define MGAREG_TEXFILTER 0x2c58 +# define MGA_MIN_NRST (0x00000000) +# define MGA_MIN_BILIN (0x00000002) +# define MGA_MIN_ANISO (0x0000000D) +# define MGA_MAG_NRST (0x00000000) +# define MGA_MAG_BILIN (0x00000020) #define MGAREG_ALPHASTART 0x2c70 #define MGAREG_ALPHAXINC 0x2c74 #define MGAREG_ALPHAYINC 0x2c78 #define MGAREG_ALPHACTRL 0x2c7c +# define MGA_SRC_ZERO (0x00000000) +# define MGA_SRC_ONE (0x00000001) +# define MGA_SRC_DST_COLOR (0x00000002) +# define MGA_SRC_ONE_MINUS_DST_COLOR (0x00000003) +# define MGA_SRC_ALPHA (0x00000004) +# define MGA_SRC_ONE_MINUS_SRC_ALPHA (0x00000005) +# define MGA_SRC_DST_ALPHA (0x00000006) +# define MGA_SRC_ONE_MINUS_DST_ALPHA (0x00000007) +# define MGA_SRC_SRC_ALPHA_SATURATE (0x00000008) +# define MGA_SRC_BLEND_MASK (0x0000000f) +# define MGA_DST_ZERO (0x00000000) +# define MGA_DST_ONE (0x00000010) +# define MGA_DST_SRC_COLOR (0x00000020) +# define MGA_DST_ONE_MINUS_SRC_COLOR (0x00000030) +# define MGA_DST_SRC_ALPHA (0x00000040) +# define MGA_DST_ONE_MINUS_SRC_ALPHA (0x00000050) +# define MGA_DST_DST_ALPHA (0x00000060) +# define MGA_DST_ONE_MINUS_DST_ALPHA (0x00000070) +# define MGA_DST_BLEND_MASK (0x00000070) +# define MGA_ALPHACHANNEL (0x00000100) +# define MGA_VIDEOALPHA (0x00000200) +# define MGA_DIFFUSEDALPHA (0x01000000) +# define MGA_MODULATEDALPHA (0x02000000) +#define MGAREG_TDUALSTAGE0 (0x2CF8) +#define MGAREG_TDUALSTAGE1 (0x2CFC) +# define MGA_TDS_COLOR_ARG2_DIFFUSE (0x00000000) +# define MGA_TDS_COLOR_ARG2_SPECULAR (0x00000001) +# define MGA_TDS_COLOR_ARG2_FCOL (0x00000002) +# define MGA_TDS_COLOR_ARG2_PREVSTAGE (0x00000003) +# define MGA_TDS_COLOR_ALPHA_DIFFUSE (0x00000000) +# define MGA_TDS_COLOR_ALPHA_FCOL (0x00000004) +# define MGA_TDS_COLOR_ALPHA_CURRTEX (0x00000008) +# define MGA_TDS_COLOR_ALPHA_PREVTEX (0x0000000c) +# define MGA_TDS_COLOR_ALPHA_PREVSTAGE (0x00000010) +# define MGA_TDS_COLOR_ARG1_REPLICATEALPHA (0x00000020) +# define MGA_TDS_COLOR_ARG1_INV (0x00000040) +# define MGA_TDS_COLOR_ARG2_REPLICATEALPHA (0x00000080) +# define MGA_TDS_COLOR_ARG2_INV (0x00000100) +# define MGA_TDS_COLOR_ALPHA1INV (0x00000200) +# define MGA_TDS_COLOR_ALPHA2INV (0x00000400) +# define MGA_TDS_COLOR_ARG1MUL_ALPHA1 (0x00000800) +# define MGA_TDS_COLOR_ARG2MUL_ALPHA2 (0x00001000) +# define MGA_TDS_COLOR_ARG1ADD_MULOUT (0x00002000) +# define MGA_TDS_COLOR_ARG2ADD_MULOUT (0x00004000) +# define MGA_TDS_COLOR_MODBRIGHT_2X (0x00008000) +# define MGA_TDS_COLOR_MODBRIGHT_4X (0x00010000) +# define MGA_TDS_COLOR_ADD_SUB (0x00000000) +# define MGA_TDS_COLOR_ADD_ADD (0x00020000) +# define MGA_TDS_COLOR_ADD2X (0x00040000) +# define MGA_TDS_COLOR_ADDBIAS (0x00080000) +# define MGA_TDS_COLOR_BLEND (0x00100000) +# define MGA_TDS_COLOR_SEL_ARG1 (0x00000000) +# define MGA_TDS_COLOR_SEL_ARG2 (0x00200000) +# define MGA_TDS_COLOR_SEL_ADD (0x00400000) +# define MGA_TDS_COLOR_SEL_MUL (0x00600000) +# define MGA_TDS_ALPHA_ARG1_INV (0x00800000) +# define MGA_TDS_ALPHA_ARG2_DIFFUSE (0x00000000) +# define MGA_TDS_ALPHA_ARG2_FCOL (0x01000000) +# define MGA_TDS_ALPHA_ARG2_PREVTEX (0x02000000) +# define MGA_TDS_ALPHA_ARG2_PREVSTAGE (0x03000000) +# define MGA_TDS_ALPHA_ARG2_INV (0x04000000) +# define MGA_TDS_ALPHA_ADD (0x08000000) +# define MGA_TDS_ALPHA_ADDBIAS (0x10000000) +# define MGA_TDS_ALPHA_ADD2X (0x20000000) +# define MGA_TDS_ALPHA_SEL_ARG1 (0x00000000) +# define MGA_TDS_ALPHA_SEL_ARG2 (0x40000000) +# define MGA_TDS_ALPHA_SEL_ADD (0x80000000) +# define MGA_TDS_ALPHA_SEL_MUL (0xc0000000) + #define MGAREG_DWGSYNC 0x2c4c #define MGAREG_AGP_PLL 0x1e4c