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