summaryrefslogtreecommitdiff
path: root/src/savage_exa.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/savage_exa.c')
-rw-r--r--src/savage_exa.c481
1 files changed, 481 insertions, 0 deletions
diff --git a/src/savage_exa.c b/src/savage_exa.c
new file mode 100644
index 0000000..1cb2711
--- /dev/null
+++ b/src/savage_exa.c
@@ -0,0 +1,481 @@
+/*
+ * The exa accel file for the Savage driver.
+ *
+ * Created 2005-2006 by Alex Deucher
+ * Revision:
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "savage_driver.h"
+#include "savage_regs.h"
+#include "savage_bci.h"
+#include "savage_streams.h"
+
+#ifdef XF86DRI
+#define _XF86DRI_SERVER_
+#include "savage_dri.h"
+#endif
+
+static void
+SavageEXASync(ScreenPtr pScreen, int marker);
+
+static Bool
+SavagePrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg);
+
+static void
+SavageSolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2);
+
+static void
+SavageDoneSolid(PixmapPtr pPixmap);
+
+static Bool
+SavagePrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, int ydir,
+ int alu, Pixel planemask);
+
+static void
+SavageCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, int width, int height);
+
+static void
+SavageDoneCopy(PixmapPtr pDstPixmap);
+
+Bool
+SavageUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, int src_pitch);
+
+#if 0
+Bool
+SavageDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, char *dst, int dst_pitch);
+#endif
+
+#if 0
+#define GXclear 0x00
+#define GXand 0x88
+#define GXandReverse 0x44
+#define GXcopy 0xCC
+#define GXandInverted 0x22
+#define GXnoop 0xAA
+#define GXxor 0x66
+#define GXor 0xEE
+#define GXnor 0x11
+#define GXequiv 0x99
+#define GXinvert 0x55
+#define GXorReverse 0xDD
+#define GXcopyInverted 0x33
+#define GXorInverted 0xBB
+#define GXnand 0x77
+#define GXset 0xFF
+#endif
+
+static int SavageGetCopyROP(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 SavageGetCopyROP_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
+SavageEXAInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ SavagePtr psav = SAVPTR(pScrn);
+
+ if (!(psav->EXADriverPtr = exaDriverAlloc())) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to allocate EXADriverRec.\n");
+ return FALSE;
+ }
+
+ /*ErrorF("in SavageEXAinit\n");*/
+
+ psav->EXADriverPtr->exa_major = 2;
+ psav->EXADriverPtr->exa_minor = 0;
+
+ /* use the linear aperture */
+ psav->EXADriverPtr->memoryBase = psav->FBBase + pScrn->fbOffset;
+
+ psav->EXADriverPtr->memorySize = psav->EXAendfb;
+
+
+ if (psav->bTiled) {
+ if (pScrn->bitsPerPixel == 16) {
+ psav->EXADriverPtr->offScreenBase =
+ ((pScrn->virtualX+63)/64)*((pScrn->virtualY+15)/16) * 2048;
+ } else {
+ psav->EXADriverPtr->offScreenBase =
+ ((pScrn->virtualX+31)/32)*((pScrn->virtualY+15)/16) * 2048;
+ }
+ } else {
+ psav->EXADriverPtr->offScreenBase =
+ ((pScrn->virtualY * psav->lDelta + SAVAGE_BUFFER_ALIGN) & ~SAVAGE_BUFFER_ALIGN);
+ }
+
+ if (psav->EXADriverPtr->memorySize > psav->EXADriverPtr->offScreenBase) {
+ psav->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Not enough video RAM for EXA offscreen memory manager.\n");
+ }
+
+ if (psav->bTiled) {
+ psav->EXADriverPtr->pixmapPitchAlign = 128; /* ~127 */
+ } else {
+ psav->EXADriverPtr->pixmapPitchAlign = 32; /* ~31 */
+ }
+
+ if (psav->Chipset == S3_SAVAGE2000 ||
+ psav->Chipset == S3_SUPERSAVAGE) {
+ psav->EXADriverPtr->pixmapOffsetAlign = 128; /* octword */
+ } else {
+ psav->EXADriverPtr->pixmapOffsetAlign = 64; /* qword */
+ }
+
+ /* engine has 12 bit coordinates */
+ psav->EXADriverPtr->maxX = 4095;
+ psav->EXADriverPtr->maxY = 4095;
+
+ /* Sync */
+ psav->EXADriverPtr->WaitMarker = SavageEXASync;
+#if 1
+ /* Solid fill */
+ psav->EXADriverPtr->PrepareSolid = SavagePrepareSolid;
+ psav->EXADriverPtr->Solid = SavageSolid;
+ psav->EXADriverPtr->DoneSolid = SavageDoneSolid;
+
+ /* Copy */
+ psav->EXADriverPtr->PrepareCopy = SavagePrepareCopy;
+ psav->EXADriverPtr->Copy = SavageCopy;
+ psav->EXADriverPtr->DoneCopy = SavageDoneCopy;
+#endif
+ /* Composite not implemented yet */
+ /* savage3d series only have one tmu */
+
+#if 1
+ /* host data blit */
+ psav->EXADriverPtr->UploadToScreen = SavageUploadToScreen;
+#endif
+#if 0
+ psav->EXADriverPtr->accel.DownloadFromScreen = SavageDownloadFromScreen;
+#endif
+
+ if(!exaDriverInit(pScreen, psav->EXADriverPtr)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "exaDriverinit failed.\n");
+ return FALSE;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Savage EXA Acceleration enabled.\n");
+ return TRUE;
+ }
+
+}
+static void
+SavageEXASync(ScreenPtr pScreen, int marker)
+{
+ SavagePtr psav = SAVPTR(xf86Screens[pScreen->myNum]);
+ psav->WaitIdleEmpty(psav);
+}
+
+static unsigned int
+SavageSetBD(SavagePtr psav, PixmapPtr pPixmap)
+{
+ unsigned int pixpitch, bd = 0;
+ unsigned int tile16, tile32;
+
+ /* front buffer can be tiled */
+ if (psav->bTiled && exaGetPixmapOffset(pPixmap) == 0) {
+ switch( psav->Chipset ) {
+ case S3_SAVAGE3D:
+ case S3_SAVAGE_MX:
+ case S3_SAVAGE4:
+ tile16 = BCI_BD_TILE_16;
+ tile32 = BCI_BD_TILE_32;
+ break;
+ case S3_TWISTER:
+ case S3_PROSAVAGE:
+ case S3_PROSAVAGEDDR:
+ case S3_SUPERSAVAGE:
+ case S3_SAVAGE2000:
+ default:
+ tile16 = BCI_BD_TILE_DESTINATION;
+ tile32 = BCI_BD_TILE_DESTINATION;
+ break;
+ }
+ } else {
+ tile16 = BCI_BD_TILE_NONE;
+ tile32 = BCI_BD_TILE_NONE;
+ }
+
+ /* HW uses width */
+ pixpitch = exaGetPixmapPitch(pPixmap) / (pPixmap->drawable.bitsPerPixel >> 3);
+
+ BCI_BD_SET_BPP(bd, pPixmap->drawable.bitsPerPixel);
+ BCI_BD_SET_STRIDE(bd, pixpitch);
+
+ if (pPixmap->drawable.bitsPerPixel == 32)
+ bd |= BCI_BD_BW_DISABLE | tile32;
+ else
+ bd |= BCI_BD_BW_DISABLE | tile16;
+
+ return bd;
+
+}
+
+static Bool
+SavagePrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+ SavagePtr psav = SAVPTR(pScrn);
+ int cmd;
+ BCI_GET_PTR;
+
+ /*ErrorF("in preparesolid\n");*/
+
+ cmd = BCI_CMD_RECT
+ | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP
+ | BCI_CMD_DEST_PBD_NEW | BCI_CMD_SRC_SOLID
+ | BCI_CMD_SEND_COLOR;
+
+ BCI_CMD_SET_ROP( cmd, SavageGetCopyROP(alu) );
+
+ psav->pbd_offset = exaGetPixmapOffset(pPixmap);
+ psav->pbd_high = SavageSetBD(psav, pPixmap);
+
+ psav->SavedBciCmd = cmd;
+ psav->SavedFgColor = fg;
+
+ psav->WaitQueue(psav,6);
+
+ BCI_SEND(BCI_SET_REGISTER
+ | BCI_SET_REGISTER_COUNT(1)
+ | BCI_BITPLANE_WRITE_MASK);
+ BCI_SEND(planemask);
+
+ BCI_SEND(psav->SavedBciCmd);
+ BCI_SEND(psav->pbd_offset);
+ BCI_SEND(psav->pbd_high);
+ BCI_SEND(psav->SavedFgColor);
+
+ return TRUE;
+}
+
+static void
+SavageSolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+ SavagePtr psav = SAVPTR(pScrn);
+ int w = x2 - x1;
+ int h = y2 - y1;
+ BCI_GET_PTR;
+
+ if( !w || !h )
+ return;
+
+ psav->WaitQueue(psav,2);
+ BCI_SEND(BCI_X_Y(x1, y1));
+ BCI_SEND(BCI_W_H(w, h));
+
+}
+
+static void
+SavageDoneSolid(PixmapPtr pPixmap)
+{
+}
+
+static Bool
+SavagePrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, int ydir,
+ int alu, Pixel planemask)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
+ SavagePtr psav = SAVPTR(pScrn);
+ int cmd;
+ BCI_GET_PTR;
+
+ /*ErrorF("in preparecopy\n");*/
+
+ cmd = BCI_CMD_RECT | BCI_CMD_DEST_PBD_NEW | BCI_CMD_SRC_SBD_COLOR_NEW;
+
+ BCI_CMD_SET_ROP( cmd, SavageGetCopyROP(alu) );
+
+ if (xdir > 0 ) cmd |= BCI_CMD_RECT_XP;
+ if (ydir > 0 ) cmd |= BCI_CMD_RECT_YP;
+
+ psav->sbd_offset = exaGetPixmapOffset(pSrcPixmap);
+ psav->pbd_offset = exaGetPixmapOffset(pDstPixmap);
+
+ psav->sbd_high = SavageSetBD(psav, pSrcPixmap);
+ psav->pbd_high = SavageSetBD(psav, pDstPixmap);
+
+ psav->SavedBciCmd = cmd;
+
+ psav->WaitQueue(psav,7);
+
+ BCI_SEND(BCI_SET_REGISTER
+ | BCI_SET_REGISTER_COUNT(1)
+ | BCI_BITPLANE_WRITE_MASK);
+ BCI_SEND(planemask);
+
+ BCI_SEND(psav->SavedBciCmd);
+ /* src */
+ BCI_SEND(psav->sbd_offset);
+ BCI_SEND(psav->sbd_high);
+ /* dst */
+ BCI_SEND(psav->pbd_offset);
+ BCI_SEND(psav->pbd_high);
+
+ return TRUE;
+}
+
+static void
+SavageCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, int width, int height)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
+ SavagePtr psav = SAVPTR(pScrn);
+ BCI_GET_PTR;
+
+ if (!width || !height) return;
+
+ if (!(psav->SavedBciCmd & BCI_CMD_RECT_XP)) {
+ width --;
+ srcX += width;
+ dstX += width;
+ width ++;
+ }
+ if (!(psav->SavedBciCmd & BCI_CMD_RECT_YP)) {
+ height --;
+ srcY += height;
+ dstY += height;
+ height ++;
+ }
+
+ psav->WaitQueue(psav,4);
+ BCI_SEND(BCI_X_Y(srcX, srcY));
+ BCI_SEND(BCI_X_Y(dstX, dstY));
+ BCI_SEND(BCI_W_H(width, height));
+
+}
+
+static void
+SavageDoneCopy(PixmapPtr pDstPixmap)
+{
+}
+
+Bool
+SavageUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, int src_pitch)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+ SavagePtr psav = SAVPTR(pScrn);
+ BCI_GET_PTR;
+ int i, j, dwords, Bpp;
+ unsigned int cmd;
+ CARD32 * srcp;
+
+ Bpp = pDst->drawable.bitsPerPixel / 8;
+ dwords = ((w * Bpp) + 3) >> 2;
+
+ psav->sbd_offset = exaGetPixmapOffset(pDst);
+ psav->sbd_high = SavageSetBD(psav, pDst);
+
+ cmd = BCI_CMD_RECT
+ | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP
+ | BCI_CMD_DEST_SBD_NEW
+ | BCI_CMD_SRC_COLOR; /* host color data */
+
+ BCI_CMD_SET_ROP( cmd, 0xCC ); /* GXcopy */
+
+ /*ErrorF("in UTS\n");*/
+
+ psav->WaitQueue(psav, 5);
+ BCI_SEND(cmd);
+
+ /* dst */
+ BCI_SEND(psav->sbd_offset);
+ BCI_SEND(psav->sbd_high);
+
+ BCI_SEND(BCI_X_Y(x, y));
+ BCI_SEND(BCI_W_H(w, h));
+
+ for (i = 0; i < h; i++) {
+ srcp = (CARD32 *)src;
+ BCI_RESET;
+ for (j = dwords; j > 0; j--) {
+ CARD32 dw = *srcp;
+ BCI_SEND(dw);
+ srcp++;
+ }
+ src += src_pitch;
+ }
+
+ return TRUE;
+}
+
+#if 0
+Bool
+SavageDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, char *dst, int dst_pitch)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
+ unsigned char *src;
+ int src_pitch = exaGetPixmapPitch(pSrc);
+ int bpp = pSrc->drawable.bitsPerPixel;
+
+ /* do the copy */
+ src = pSrc->devPrivate.ptr;
+ src += (x * bpp / 8) + (y * src_pitch);
+ w *= bpp / 8;
+
+ while (h--) {
+ memcpy(dst, src, w);
+ src += src_pitch;
+ dst += dst_pitch;
+ }
+ return TRUE;
+}
+
+#endif