diff options
Diffstat (limited to 'src/nv50_exa.c')
-rw-r--r-- | src/nv50_exa.c | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/src/nv50_exa.c b/src/nv50_exa.c new file mode 100644 index 0000000..6536715 --- /dev/null +++ b/src/nv50_exa.c @@ -0,0 +1,254 @@ +#include "nv_include.h" + +#define NV50_2D_NOP 0x00000100 +#define NV50_2D_UNK110 0x00000110 +#define NV50_2D_DST_FORMAT 0x00000200 +#define NV50_2D_SRC_FORMAT 0x00000230 +#define NV50_2D_SRC_FORMAT_8BPP 0x000000f3 +#define NV50_2D_SRC_FORMAT_15BPP 0x000000f8 +#define NV50_2D_SRC_FORMAT_16BPP 0x000000e8 +#define NV50_2D_SRC_FORMAT_24BPP 0x000000e6 +#define NV50_2D_SRC_FORMAT_32BPP 0x000000cf +#define NV50_2D_CLIP_X 0x00000280 +#define NV50_2D_SET_OPERATION 0x000002ac +#define NV50_2D_SET_OPERATION_ROP_AND 0x00000001 +#define NV50_2D_SET_OPERATION_SRCCOPY 0x00000003 +#define NV50_2D_RASTER_OP 0x000002a0 +#define NV50_2D_PATTERN_FORMAT 0x000002e8 +#define NV50_2D_PATTERN_COLOR_0 0x000002f0 +#define NV50_2D_RECT_UNK580 0x00000580 +#define NV50_2D_RECT_FORMAT 0x00000584 +#define NV50_2D_RECT_X1 0x00000600 +#define NV50_2D_BLIT_DST_X 0x000008b0 + +#define NV50EXA_LOCALS(p) \ + ScrnInfoPtr pScrn = xf86Screens[(p)->drawable.pScreen->myNum]; \ + NVPtr pNv = NVPTR(pScrn); \ + (void)pNv + +static Bool +NV50EXA2DSurfaceFormat(PixmapPtr pPix, uint32_t *fmt) +{ + NV50EXA_LOCALS(pPix); + + switch (pPix->drawable.depth) { + case 8 : *fmt = NV50_2D_SRC_FORMAT_8BPP; break; + case 15: *fmt = NV50_2D_SRC_FORMAT_15BPP; break; + case 16: *fmt = NV50_2D_SRC_FORMAT_16BPP; break; + case 24: *fmt = NV50_2D_SRC_FORMAT_24BPP; break; + case 32: *fmt = NV50_2D_SRC_FORMAT_32BPP; break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Unknown surface format for bpp=%d\n", + pPix->drawable.depth); + return FALSE; + } + + return TRUE; +} + +static Bool +NV50EXAAcquireSurface2D(PixmapPtr pPix, int is_src) +{ + NV50EXA_LOCALS(pPix); + int mthd = is_src ? NV50_2D_SRC_FORMAT : NV50_2D_DST_FORMAT; + uint32_t fmt; + + if (!NV50EXA2DSurfaceFormat(pPix, &fmt)) + return FALSE; + + NVDmaStart(pNv, NvSub2D, mthd, 2); + NVDmaNext (pNv, fmt); + NVDmaNext (pNv, 1); + + NVDmaStart(pNv, NvSub2D, mthd + 0x14, 5); + NVDmaNext (pNv, (uint32_t)exaGetPixmapPitch(pPix)); + NVDmaNext (pNv, pPix->drawable.width); + NVDmaNext (pNv, pPix->drawable.height); + NVDmaNext (pNv, 0); + NVDmaNext (pNv, NVAccelGetPixmapOffset(pPix)); + + if (is_src == 0) { + NVDmaStart(pNv, NvSub2D, NV50_2D_CLIP_X, 4); + NVDmaNext (pNv, 0); + NVDmaNext (pNv, 0); + NVDmaNext (pNv, pPix->drawable.width); + NVDmaNext (pNv, pPix->drawable.height); + } + + return TRUE; +} + +static Bool +NV50EXAAcquireSurfaces(PixmapPtr pdPix) +{ + NV50EXA_LOCALS(pdPix); + + return TRUE; +} + +static void +NV50EXAReleaseSurfaces(PixmapPtr pdPix) +{ + NV50EXA_LOCALS(pdPix); + + NVDmaStart(pNv, NvSub2D, NV50_2D_NOP, 1); + NVDmaNext (pNv, 0); + NVDmaKickoff(pNv); +} + +static void +NV50EXASetPattern(PixmapPtr pdPix, int col0, int col1, int pat0, int pat1) +{ + NV50EXA_LOCALS(pdPix); + + NVDmaStart(pNv, NvSub2D, NV50_2D_PATTERN_COLOR_0, 4); + NVDmaNext (pNv, col0); + NVDmaNext (pNv, col1); + NVDmaNext (pNv, pat0); + NVDmaNext (pNv, pat1); +} + +extern const int NVCopyROP[16]; +static void +NV50EXASetROP(PixmapPtr pdPix, int alu, Pixel planemask) +{ + NV50EXA_LOCALS(pdPix); + int rop = NVCopyROP[alu]; + + NVDmaStart(pNv, NvSub2D, NV50_2D_SET_OPERATION, 1); + if(alu == GXcopy && planemask == ~0) { + NVDmaNext (pNv, NV50_2D_SET_OPERATION_SRCCOPY); + return; + } else { + NVDmaNext (pNv, NV50_2D_SET_OPERATION_ROP_AND); + } + + NVDmaStart(pNv, NvSub2D, NV50_2D_PATTERN_FORMAT, 1); + switch (pdPix->drawable.depth) { + case 8: NVDmaNext(pNv, 3); break; + case 15: NVDmaNext(pNv, 1); break; + case 16: NVDmaNext(pNv, 0); break; + case 24: + case 32: + default: + NVDmaNext(pNv, 2); + break; + } + + if(planemask != ~0) { + NV50EXASetPattern(pdPix, 0, planemask, ~0, ~0); + rop = (rop & 0xf0) | 0x0a; + } else + if((pNv->currentRop & 0x0f) == 0x0a) { + NV50EXASetPattern(pdPix, ~0, ~0, ~0, ~0); + } + + if (pNv->currentRop != rop) { + NVDmaStart(pNv, NvSub2D, NV50_2D_RASTER_OP, 1); + NVDmaNext (pNv, rop); + pNv->currentRop = rop; + } +} + +Bool +NV50EXAPrepareSolid(PixmapPtr pdPix, int alu, Pixel planemask, Pixel fg) +{ + NV50EXA_LOCALS(pdPix); + uint32_t fmt; + + if(pdPix->drawable.depth > 24) + return FALSE; + if (!NV50EXA2DSurfaceFormat(pdPix, &fmt)) + return FALSE; + + if (!NV50EXAAcquireSurface2D(pdPix, 0)) + return FALSE; + if (!NV50EXAAcquireSurfaces(pdPix)) + return FALSE; + NV50EXASetROP(pdPix, alu, planemask); + + NVDmaStart(pNv, NvSub2D, NV50_2D_RECT_UNK580, 3); + NVDmaNext (pNv, 4); + NVDmaNext (pNv, fmt); + NVDmaNext (pNv, fg); + + return TRUE; +} + +void +NV50EXASolid(PixmapPtr pdPix, int x1, int y1, int x2, int y2) +{ + NV50EXA_LOCALS(pdPix); + + NVDmaStart(pNv, NvSub2D, NV50_2D_RECT_X1, 4); + NVDmaNext (pNv, x1); + NVDmaNext (pNv, y1); + NVDmaNext (pNv, x2); + NVDmaNext (pNv, y2); + + if((x2 - x1) * (y2 - y1) >= 512) + NVDmaKickoff(pNv); +} + +void +NV50EXADoneSolid(PixmapPtr pdPix) +{ + NV50EXA_LOCALS(pdPix); + + NV50EXAReleaseSurfaces(pdPix); +} + +Bool +NV50EXAPrepareCopy(PixmapPtr psPix, PixmapPtr pdPix, int dx, int dy, + int alu, Pixel planemask) +{ + NV50EXA_LOCALS(pdPix); + + if (!NV50EXAAcquireSurface2D(psPix, 1)) + return FALSE; + if (!NV50EXAAcquireSurface2D(pdPix, 0)) + return FALSE; + if (!NV50EXAAcquireSurfaces(pdPix)) + return FALSE; + NV50EXASetROP(pdPix, alu, planemask); + + return TRUE; +} + +void +NV50EXACopy(PixmapPtr pdPix, int srcX , int srcY, + int dstX , int dstY, + int width, int height) +{ + NV50EXA_LOCALS(pdPix); + + NVDmaStart(pNv, NvSub2D, NV50_2D_UNK110, 1); + NVDmaNext (pNv, 0); + NVDmaStart(pNv, NvSub2D, NV50_2D_BLIT_DST_X, 12); + NVDmaNext (pNv, dstX); + NVDmaNext (pNv, dstY); + NVDmaNext (pNv, width); + NVDmaNext (pNv, height); + NVDmaNext (pNv, 0); + NVDmaNext (pNv, 1); + NVDmaNext (pNv, 0); + NVDmaNext (pNv, 1); + NVDmaNext (pNv, 0); + NVDmaNext (pNv, srcX); + NVDmaNext (pNv, 0); + NVDmaNext (pNv, srcY); + + if(width * height >= 512) + NVDmaKickoff(pNv); +} + +void +NV50EXADoneCopy(PixmapPtr pdPix) +{ + NV50EXA_LOCALS(pdPix); + + NV50EXAReleaseSurfaces(pdPix); +} + + |