/* 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; }