diff options
Diffstat (limited to 'src/s3v_exa.c')
-rw-r--r-- | src/s3v_exa.c | 326 |
1 files changed, 326 insertions, 0 deletions
diff --git a/src/s3v_exa.c b/src/s3v_exa.c new file mode 100644 index 0000000..c1df938 --- /dev/null +++ b/src/s3v_exa.c @@ -0,0 +1,326 @@ +/* The exa acceleration file for the S3 ViRGE driver. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "s3v.h" +#include "regs3v.h" + +#include "miline.h" + +#include "servermd.h" /* LOG2_BYTES_PER_SCANLINE_PAD */ + +static void S3VEXASync( + ScreenPtr pScreen, + int marker); + +static Bool S3VPrepareSolid( + PixmapPtr pPixmap, + int alu, Pixel planemask, + Pixel fg); + +static void S3VSolid( + PixmapPtr pPixmap, + int x1, int y1, + int x2, int y2); + +static void S3VDoneSolid( + PixmapPtr pPixmap); + +static Bool S3VPrepareCopy( + PixmapPtr pSrcPixmap, + PixmapPtr pDstPixmap, + int xdir, int ydir, + int alu, Pixel planemask); + +static void S3VCopy( + PixmapPtr pDstPixmap, + int srcX, int srcY, + int dstX, int dstY, + int width, int height); + +static void S3VDoneCopy( + PixmapPtr pDstPixmap); + +Bool S3VUploadToScreen( + PixmapPtr pDst, + int x, int y, + int w, int h, + char *src, int src_pitch); + +#if 1 +Bool S3VDownloadFromScreen( + PixmapPtr pSrc, + int x, int y, + int w, int h, + char *dst, int dst_pitch); +#endif + +static int S3VGetCopyROP(int rop) { + + int ALUCopyROP[16] = + { + 0x00, /*ROP_0 GXclear */ + 0x88, /*ROP_DSa GXand */ + 0x44, /*ROP_SDna GXandReverse */ + 0xCC, /*ROP_S GXcopy */ + 0x22, /*ROP_DSna GXandInverted */ + 0xAA, /*ROP_D GXnoop */ + 0x66, /*ROP_DSx GXxor */ + 0xEE, /*ROP_DSo GXor */ + 0x11, /*ROP_DSon GXnor */ + 0x99, /*ROP_DSxn GXequiv */ + 0x55, /*ROP_Dn GXinvert*/ + 0xDD, /*ROP_SDno GXorReverse */ + 0x33, /*ROP_Sn GXcopyInverted */ + 0xBB, /*ROP_DSno GXorInverted */ + 0x77, /*ROP_DSan GXnand */ + 0xFF, /*ROP_1 GXset */ + }; + + return (ALUCopyROP[rop]); + +} + +static int S3VGetCopyROP_PM(int rop) { + + int ALUCopyROP_PM[16] = + { + 0x00, /*ROP_0*/ /* not used */ + 0x75, /*ROP_DSPnoa*/ + 0x45, /*ROP_DPSnaon*/ + 0xCA, /*ROP_DPSDxax*/ + 0xD5, /*ROP_DPSana*/ + 0xAA, /*ROP_D*/ /* not used */ + 0x6A, /*ROP_DPSax*/ + 0xEA, /*ROP_DPSao*/ + 0x15, /*ROP_DPSaon*/ + 0x95, /*ROP_DPSaxn*/ + 0x55, /*ROP_Dn*/ /* not used */ + 0xD5, /*ROP_DPSanan*/ + 0x2E, /*ROP_PSDPxox*/ /* is that correct ? */ + 0xBA, /*ROP_DPSnao*/ + 0x75, /*ROP_DSPnoan*/ + 0xFF, /*ROP_1*/ /* not used */ + }; + + return (ALUCopyROP_PM[rop]); + +} + +Bool +S3VEXAInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + S3VPtr ps3v = S3VPTR(pScrn); + + if (!(ps3v->EXADriverPtr = exaDriverAlloc())) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate EXADriverRec.\n"); + return FALSE; + } + + ps3v->EXADriverPtr->exa_major = 2; + ps3v->EXADriverPtr->exa_minor = 0; + + /* use the linear aperture */ + ps3v->EXADriverPtr->memoryBase = ps3v->FBBase + pScrn->fbOffset; + ps3v->EXADriverPtr->memorySize = ps3v->EXAendfb; + + /* No tile support ? */ + ps3v->EXADriverPtr->offScreenBase = (pScrn->displayWidth * pScrn->bitsPerPixel >> 3) * pScrn->virtualY; + + if (ps3v->EXADriverPtr->memorySize > ps3v->EXADriverPtr->offScreenBase) { + ps3v->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Not enough video RAM for EXA offscreen memory manager.\n"); + } + + /* No tile support ? */ + ps3v->EXADriverPtr->pixmapPitchAlign = 32; /* ~31 */ + + if (ps3v->Chipset == S3_ViRGE_DXGX) + ps3v->EXADriverPtr->pixmapOffsetAlign = 64; /* quadword */ + + /* engine has 12 bit coordinates */ + ps3v->EXADriverPtr->maxX = 1023; + ps3v->EXADriverPtr->maxY = 1023; + + /* Sync */ + ps3v->EXADriverPtr->WaitMarker = S3VEXASync; + +#if 1 + /* Solid fill */ + ps3v->EXADriverPtr->PrepareSolid = S3VPrepareSolid; + ps3v->EXADriverPtr->Solid = S3VSolid; + ps3v->EXADriverPtr->DoneSolid = S3VDoneSolid; + + /* Copy */ + ps3v->EXADriverPtr->PrepareCopy = S3VPrepareCopy; + ps3v->EXADriverPtr->Copy = S3VCopy; + ps3v->EXADriverPtr->DoneCopy = S3VDoneCopy; + + /* Composite not implemented yet */ + /* virge series only have one tmu */ + +#endif + +#if 0 + /* host data blit */ + ps3v->EXADriverPtr->UploadToScreen = S3VUploadToScreen; +#endif +#if 0 + ps3v->EXADriverPtr->DownloadFromScreen = S3VDownloadFromScreen; +#endif + + if(!exaDriverInit(pScreen, ps3v->EXADriverPtr)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "exaDriverinit failed.\n"); + return FALSE; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "S3ViRGE EXA Acceleration enabled.\n"); + return TRUE; + } + +} + +static void +S3VEXASync(ScreenPtr pScreen, int marker) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + S3VPtr ps3v = S3VPTR(pScrn); + WaitIdleEmpty(); +} + +static Bool +S3VPrepareSolid (PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg) +{ + ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; + S3VPtr ps3v = S3VPTR(pScrn); + + return FALSE; +} + +static void +S3VSolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2) +{ + ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; + S3VPtr ps3v = S3VPTR(pScrn); + + int w = x2 - x1; + int h = y2 - y1; + + if ( !w || !h ) + return; + + WAITFIFO(2); + OUTREG(RWIDTH_HEIGHT, ((w -1) << 16) | h); + WAITCMD(); + OUTREG(RDEST_XY, (x1 << 16) | y1); +} + +static void +S3VDoneSolid(PixmapPtr pPixmap) +{ +} + +static Bool +S3VPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, int ydir, int alu, Pixel Planemask) +{ + ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; + S3VPtr ps3v = S3VPTR(pScrn); + + switch (pDstPixmap->drawable.bitsPerPixel) { + case 8: ps3v->CommonCmd = DRAW | DST_8BPP; + break; + case 16: ps3v->CommonCmd = DRAW | DST_16BPP; + break; + case 24: ps3v->CommonCmd = DRAW | DST_24BPP; + break; + } + + ps3v->AccelCmd = ps3v->CommonCmd | S3VGetCopyROP(alu) | CMD_AUTOEXEC | CMD_BITBLT; + if(xdir > 0) ps3v->AccelCmd |= CMD_XP; + if(ydir > 0) ps3v->AccelCmd |= CMD_YP; + + ps3v->dst_offset = exaGetPixmapOffset(pDstPixmap); + ps3v->dst_stride = exaGetPixmapPitch(pDstPixmap); + + ps3v->src_offset = exaGetPixmapOffset(pSrcPixmap); + ps3v->src_stride = exaGetPixmapPitch(pSrcPixmap); + + WAITFIFO(4); // wait for 4 registers to become free. + OUTREG(SRC_BASE, ps3v->src_offset); + OUTREG(DEST_BASE, ps3v->dst_offset); + OUTREG(DEST_SRC_STR, ps3v->src_stride | (ps3v->dst_stride << 16)); + OUTREG(CMD_SET, ps3v->AccelCmd); + return TRUE; +} + +static void +S3VCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, int width, int height) +{ + ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; + S3VPtr ps3v = S3VPTR(pScrn); + + if (!width || !height) return; + + width--; + if (!(ps3v->AccelCmd & CMD_XP)) { + srcX += width; + dstX += width; + } + + if (!(ps3v->AccelCmd & CMD_YP)) { + srcY += height -1; + dstY += height -1; + } + + WAITFIFO(3); // wait for 3 registers + OUTREG(RWIDTH_HEIGHT, (width << 16) | height); + OUTREG(RSRC_XY, (srcX << 16) | srcY); + WAITCMD(); + OUTREG(RDEST_XY, (dstX << 16) | dstY); + +} + +static void +S3VDoneCopy(PixmapPtr pDstPixmap) +{ +} + +Bool +S3VUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, int src_pitch) +{ + ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; + S3VPtr ps3v = S3VPTR(pScrn); + + int i, j, dwords, Bpp; + + Bpp = pDst->drawable.bitsPerPixel / 8; + dwords = ((w * Bpp) + 3) >> 2; + + ps3v->src_offset = exaGetPixmapOffset(pDst); + ps3v->src_stride = exaGetPixmapPitch(pDst); + + switch (pDst->drawable.bitsPerPixel) { + case 8: ps3v->CommonCmd = DRAW | DST_8BPP; + break; + case 16: ps3v->CommonCmd = DRAW | DST_16BPP; + break; + case 24: ps3v->CommonCmd = DRAW | DST_24BPP; + break; + } + + ps3v->AccelCmd = ps3v->CommonCmd | 0xCC | CMD_XP | CMD_YP | CMD_BITBLT; + WAITFIFO(3); + OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16 | h)); + OUTREG(RSRC_XY, (ps3v->src_offset << 16)| ps3v->src_stride); + WAITCMD(); + OUTREG(CMD_SET, ps3v->AccelCmd); + + return TRUE; +} |