diff options
Diffstat (limited to 'src/savage_exa.c')
-rw-r--r-- | src/savage_exa.c | 481 |
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 |