summaryrefslogtreecommitdiffstats
path: root/src/s3v_exa.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/s3v_exa.c')
-rw-r--r--src/s3v_exa.c326
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;
+}