Module Name:    xsrc
Committed By:   macallan
Date:           Thu Jul 12 21:19:55 UTC 2018

Modified Files:
        xsrc/external/mit/xf86-video-nv/dist/src: nv_driver.c nv_proto.h
            nv_type.h nv_xaa.c
Added Files:
        xsrc/external/mit/xf86-video-nv/dist/src: nv_exa.c

Log Message:
add mostly working EXA support
tested on a GeForce 6800 Ultra in a G5
still produces occasional artifacts but good enough to run a bunch of xterms
and gtk2 applications


To generate a diff of this commit:
cvs rdiff -u -r1.9 -r1.10 \
    xsrc/external/mit/xf86-video-nv/dist/src/nv_driver.c
cvs rdiff -u -r0 -r1.1 xsrc/external/mit/xf86-video-nv/dist/src/nv_exa.c
cvs rdiff -u -r1.1.1.3 -r1.2 \
    xsrc/external/mit/xf86-video-nv/dist/src/nv_proto.h
cvs rdiff -u -r1.1.1.4 -r1.2 \
    xsrc/external/mit/xf86-video-nv/dist/src/nv_type.h
cvs rdiff -u -r1.1.1.2 -r1.2 \
    xsrc/external/mit/xf86-video-nv/dist/src/nv_xaa.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: xsrc/external/mit/xf86-video-nv/dist/src/nv_driver.c
diff -u xsrc/external/mit/xf86-video-nv/dist/src/nv_driver.c:1.9 xsrc/external/mit/xf86-video-nv/dist/src/nv_driver.c:1.10
--- xsrc/external/mit/xf86-video-nv/dist/src/nv_driver.c:1.9	Sun Mar  5 01:57:26 2017
+++ xsrc/external/mit/xf86-video-nv/dist/src/nv_driver.c	Thu Jul 12 21:19:54 2018
@@ -2058,11 +2058,22 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
 
     /* Load XAA if needed */
     if (!pNv->NoAccel) {
+    	pNv->UseEXA = 1;
+#ifdef HAVE_XAA_H
 	if (!xf86LoadSubModule(pScrn, "xaa")) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Falling back to shadwwfb\n");
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Falling back to shadowfb\n");
 	    pNv->NoAccel = 1;
 	    pNv->ShadowFB = 1;
+	} else
+	    pNv->UseEXA = 0;
+#else
+	if (!xf86LoadSubModule(pScrn, "exa")) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Falling back to shadowfb\n");
+	    pNv->NoAccel = 1;
+	    pNv->UseEXA = 0;
+	    pNv->ShadowFB = 1;
 	}
+#endif
     }
 
     /* Load ramdac if needed */
@@ -2591,6 +2602,7 @@ NVScreenInit(SCREEN_INIT_ARGS_DECL)
     if(offscreenHeight > 32767)
         offscreenHeight = 32767;
 
+#ifdef HAVE_XAA_H
     AvailFBArea.x1 = 0;
     AvailFBArea.y1 = 0;
     AvailFBArea.x2 = pScrn->displayWidth;
@@ -2599,7 +2611,10 @@ NVScreenInit(SCREEN_INIT_ARGS_DECL)
     
     if (!pNv->NoAccel)
 	NVAccelInit(pScreen);
-    
+#endif
+    if ((!pNv->NoAccel) && (pNv->UseEXA == 1))
+	NvInitExa(pScreen);
+
     xf86SetBackingStore(pScreen);
     xf86SetSilkenMouse(pScreen);
 

Index: xsrc/external/mit/xf86-video-nv/dist/src/nv_proto.h
diff -u xsrc/external/mit/xf86-video-nv/dist/src/nv_proto.h:1.1.1.3 xsrc/external/mit/xf86-video-nv/dist/src/nv_proto.h:1.2
--- xsrc/external/mit/xf86-video-nv/dist/src/nv_proto.h:1.1.1.3	Sun Mar  5 01:55:42 2017
+++ xsrc/external/mit/xf86-video-nv/dist/src/nv_proto.h	Thu Jul 12 21:19:54 2018
@@ -34,8 +34,13 @@ Bool   NVAccelInit(ScreenPtr pScreen);
 void   NVSync(ScrnInfoPtr pScrn);
 void   NVResetGraphics(ScrnInfoPtr pScrn);
 void   NVDmaKickoff(NVPtr pNv);
+void   NVDMAKickoffCallback(ScrnInfoPtr pScrn);
 void   NVDmaWait(NVPtr pNv, int size);
 void   NVWaitVSync(NVPtr pNv);
+void   NVSetRopSolid(ScrnInfoPtr pScrn, CARD32 rop, CARD32 planemask);
+
+/* in nv_exa.c */
+Bool   NvInitExa(ScreenPtr pScreen);
 
 /* in nv_dga.c */
 Bool   NVDGAInit(ScreenPtr pScreen);

Index: xsrc/external/mit/xf86-video-nv/dist/src/nv_type.h
diff -u xsrc/external/mit/xf86-video-nv/dist/src/nv_type.h:1.1.1.4 xsrc/external/mit/xf86-video-nv/dist/src/nv_type.h:1.2
--- xsrc/external/mit/xf86-video-nv/dist/src/nv_type.h:1.1.1.4	Sun Mar  5 01:55:42 2017
+++ xsrc/external/mit/xf86-video-nv/dist/src/nv_type.h	Thu Jul 12 21:19:54 2018
@@ -5,6 +5,7 @@
 #include "vgaHW.h"
 #include "xf86Cursor.h"
 #include "xf86int10.h"
+#include "exa.h"
 
 #define NV_ARCH_04  0x04
 #define NV_ARCH_10  0x10
@@ -128,6 +129,7 @@ typedef struct {
 #ifdef HAVE_XAA_H
     XAAInfoRecPtr       AccelInfoRec;
 #endif
+    ExaDriverPtr 	pExa;
     xf86CursorInfoPtr   CursorInfoRec;
     DGAModePtr          DGAModes;
     int                 numDGAModes;

Index: xsrc/external/mit/xf86-video-nv/dist/src/nv_xaa.c
diff -u xsrc/external/mit/xf86-video-nv/dist/src/nv_xaa.c:1.1.1.2 xsrc/external/mit/xf86-video-nv/dist/src/nv_xaa.c:1.2
--- xsrc/external/mit/xf86-video-nv/dist/src/nv_xaa.c:1.1.1.2	Sun Jun  2 08:24:14 2013
+++ xsrc/external/mit/xf86-video-nv/dist/src/nv_xaa.c	Thu Jul 12 21:19:54 2018
@@ -106,7 +106,7 @@ NVDmaKickoff(NVPtr pNv)
    You can't jump to the location of your put offset.  We write put
    at the jump offset + SKIPS dwords with noop padding in between
    to solve this problem */
-#define SKIPS  8
+#define SKIPS  16
 
 void 
 NVDmaWait (
@@ -176,7 +176,7 @@ NVSetPattern(
     NVDmaNext (pNv, pat1);
 }
 
-static void 
+void 
 NVSetRopSolid(ScrnInfoPtr pScrn, CARD32 rop, CARD32 planemask)
 {
     NVPtr pNv = NVPTR(pScrn);
@@ -282,16 +282,30 @@ void NVResetGraphics(ScrnInfoPtr pScrn)
 void NVSync(ScrnInfoPtr pScrn)
 {
     NVPtr pNv = NVPTR(pScrn);
-
+    int bail = 10000000;
+    
     if(pNv->DMAKickoffCallback)
        (*pNv->DMAKickoffCallback)(pScrn);
 
-    while(READ_GET(pNv) != pNv->dmaPut);
-
-    while(pNv->PGRAPH[0x0700/4]);
+    while((READ_GET(pNv) != pNv->dmaPut) && (bail > 0)) bail--;
+    if (bail == 0) {
+    	xf86Msg(X_ERROR, "DMA drain timeout\n");
+    	goto crap;
+    }
+    
+    bail = 10000000;
+    while((pNv->PGRAPH[0x0700/4]) && (bail > 0)) bail--;
+    if (bail == 0) {
+    	xf86Msg(X_ERROR, "engine stalled\n");
+    	goto crap;
+    }
+    return;
+    
+crap:
+    NVResetGraphics(pScrn);
 }
 
-static void
+ void
 NVDMAKickoffCallback (ScrnInfoPtr pScrn)
 {
    NVPtr pNv = NVPTR(pScrn);

Added files:

Index: xsrc/external/mit/xf86-video-nv/dist/src/nv_exa.c
diff -u /dev/null xsrc/external/mit/xf86-video-nv/dist/src/nv_exa.c:1.1
--- /dev/null	Thu Jul 12 21:19:55 2018
+++ xsrc/external/mit/xf86-video-nv/dist/src/nv_exa.c	Thu Jul 12 21:19:54 2018
@@ -0,0 +1,334 @@
+/*
+ * crude EXA support for geforce chips
+ *
+ * Copyright (C) 2018 Michael Lorenz
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * MICHAEL LORENZ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* $NetBSD: nv_exa.c,v 1.1 2018/07/12 21:19:54 macallan Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "nv_include.h"
+#include "miline.h"
+#include "nv_dma.h"
+#include "exa.h"
+
+//#define DEBUG
+
+#ifdef DEBUG
+#define ENTER xf86Msg(X_ERROR, "%s\n", __func__)
+#define LEAVE xf86Msg(X_ERROR, "%s done\n", __func__)
+#else
+#define ENTER
+#define LEAVE
+#endif
+
+static void
+NvWaitMarker(ScreenPtr pScreen, int Marker)
+{
+	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+	ENTER;
+	NVSync(pScrn);
+	LEAVE;
+}
+
+static Bool
+NvPrepareCopy
+(
+    PixmapPtr pSrcPixmap,
+    PixmapPtr pDstPixmap,
+    int       xdir,
+    int       ydir,
+    int       rop,
+    Pixel     planemask
+)
+{
+	ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
+	NVPtr pNv = NVPTR(pScrn);
+	int srcpitch, srcoff, dstpitch, dstoff;
+
+	ENTER;
+	if (pSrcPixmap->drawable.bitsPerPixel != 32)
+		xf86Msg(X_ERROR, "%s %d bpp\n", __func__, pSrcPixmap->drawable.bitsPerPixel);
+	planemask |= ~0 << pNv->CurrentLayout.depth;
+	NVSetRopSolid(pScrn, rop, planemask);
+	pNv->DMAKickoffCallback = NVDMAKickoffCallback;
+	dstpitch = exaGetPixmapPitch(pDstPixmap);
+	dstoff = exaGetPixmapOffset(pDstPixmap);
+	srcpitch = exaGetPixmapPitch(pSrcPixmap);
+	srcoff = exaGetPixmapOffset(pSrcPixmap);
+
+	NVDmaStart(pNv, SURFACE_PITCH, 3);
+	NVDmaNext (pNv, srcpitch | (dstpitch << 16));
+	NVDmaNext (pNv, srcoff);
+	NVDmaNext (pNv, dstoff);
+
+	LEAVE;
+	return TRUE;
+}
+
+static void
+NvCopy
+(
+    PixmapPtr pDstPixmap,
+    int       srcX,
+    int       srcY,
+    int       dstX,
+    int       dstY,
+    int       w,
+    int       h
+)
+{
+	ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
+	NVPtr pNv = NVPTR(pScrn);
+
+	NVDmaStart(pNv, BLIT_POINT_SRC, 3);
+	NVDmaNext (pNv, (srcY << 16) | srcX);
+	NVDmaNext (pNv, (dstY << 16) | dstX);
+	NVDmaNext (pNv, (h  << 16) | w);
+
+	if((w * h) >= 512)
+		NVDmaKickoff(pNv); 
+
+	LEAVE;
+}
+
+static void
+NvDoneCopy(PixmapPtr pDstPixmap)
+{
+    ENTER;
+    LEAVE;
+}
+
+static Bool
+NvPrepareSolid(
+    PixmapPtr pPixmap,
+    int rop,
+    Pixel planemask,
+    Pixel color)
+{
+	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+	NVPtr pNv = NVPTR(pScrn);
+	int pitch, off;
+
+	ENTER;
+	if (pPixmap->drawable.bitsPerPixel != 32)
+		xf86Msg(X_ERROR, "%s %d bpp\n", __func__, pPixmap->drawable.bitsPerPixel);
+	planemask |= ~0 << pNv->CurrentLayout.depth;
+
+
+	pitch = exaGetPixmapPitch(pPixmap);
+	off = exaGetPixmapOffset(pPixmap);
+
+	NVDmaStart(pNv, SURFACE_PITCH, 3);
+	NVDmaNext (pNv, pitch | (pitch << 16));
+	NVDmaNext (pNv, off);
+	NVDmaNext (pNv, off);
+
+	NVSetRopSolid(pScrn, rop, planemask);
+	pNv->DMAKickoffCallback = NVDMAKickoffCallback;
+	NVDmaStart(pNv, RECT_SOLID_COLOR, 1);
+	NVDmaNext (pNv, color);
+
+	LEAVE;
+	return TRUE;
+}
+
+static void
+NvSolid(
+    PixmapPtr pPixmap,
+    int x1,
+    int y1,
+    int x2,
+    int y2)
+{
+	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+	NVPtr pNv = NVPTR(pScrn);
+	int w = x2 - x1, h = y2 - y1;
+
+	ENTER;
+	NVDmaStart(pNv, RECT_SOLID_RECTS(0), 2);
+	NVDmaNext (pNv, (x1 << 16) | y1);
+	NVDmaNext (pNv, (w << 16) | h);
+
+	if((w * h) >= 512)
+		NVDmaKickoff(pNv);
+
+	LEAVE;
+}
+
+/*
+ * Memcpy-based UTS.
+ */
+static Bool
+NvUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h,
+    char *src, int src_pitch)
+{
+	ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+	NVPtr pNv = NVPTR(pScrn);
+	unsigned char *dst = pNv->FbStart + exaGetPixmapOffset(pDst);
+	int dst_pitch = exaGetPixmapPitch(pDst);
+
+	int bpp    = pDst->drawable.bitsPerPixel;
+	int cpp    = (bpp + 7) >> 3;
+	int wBytes = w * cpp;
+
+	ENTER;
+	dst += (x * cpp) + (y * dst_pitch);
+
+	NVSync(pScrn);
+
+	while (h--) {
+		memcpy(dst, src, wBytes);
+		src += src_pitch;
+		dst += dst_pitch;
+	}
+	_NV_FENCE()
+	LEAVE;
+	return TRUE;
+}
+
+/*
+ * Memcpy-based DFS.
+ */
+static Bool
+NvDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
+    char *dst, int dst_pitch)
+{
+	ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
+	NVPtr pNv = NVPTR(pScrn);
+	unsigned char *src = pNv->FbStart + exaGetPixmapOffset(pSrc);
+	int src_pitch = exaGetPixmapPitch(pSrc);
+
+	int bpp    = pSrc->drawable.bitsPerPixel;
+	int cpp    = (bpp + 7) >> 3;
+	int wBytes = w * cpp;
+
+	ENTER;
+	src += (x * cpp) + (y * src_pitch);
+
+	NVSync(pScrn);
+
+	while (h--) {
+		memcpy(dst, src, wBytes);
+		src += src_pitch;
+		dst += dst_pitch;
+	}
+	LEAVE;
+	return TRUE;
+}
+
+#ifdef __arm__
+static Bool
+NvPrepareAccess(PixmapPtr pPix, int index)
+{
+	ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
+	NVPtr pNv = NVPTR(pScrn);
+
+	IgsWaitReady(fPtr);
+	return TRUE;	
+}
+
+static void
+NvFinishAccess(PixmapPtr pPix, int index)
+{
+}
+#endif
+
+Bool
+NvInitExa(ScreenPtr pScreen)
+{
+	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+	NVPtr pNv = NVPTR(pScrn);
+	ExaDriverPtr pExa;
+	int surfaceFormat, rectFormat;
+
+	pExa = exaDriverAlloc();
+	if (!pExa)
+		return FALSE;
+
+	pNv->pExa = pExa;
+
+	NVResetGraphics(pScrn);
+
+	pExa->exa_major = EXA_VERSION_MAJOR;
+	pExa->exa_minor = EXA_VERSION_MINOR;
+
+	pExa->memoryBase = pNv->FbStart;
+	pExa->memorySize = pNv->ScratchBufferStart & (~63);
+	pExa->offScreenBase = pScrn->virtualY * 
+				pScrn->displayWidth * pScrn->bitsPerPixel >> 3;
+	pExa->pixmapOffsetAlign = 64;
+	pExa->pixmapPitchAlign = 64;
+
+	pExa->flags = EXA_OFFSCREEN_PIXMAPS |
+		      EXA_SUPPORTS_OFFSCREEN_OVERLAPS |
+		      EXA_MIXED_PIXMAPS;
+
+	pExa->maxX = 8192;
+	pExa->maxY = 8192;	
+
+	pExa->WaitMarker = NvWaitMarker;
+	pExa->PrepareSolid = NvPrepareSolid;
+	pExa->Solid = NvSolid;
+	pExa->DoneSolid = NvDoneCopy;
+	pExa->PrepareCopy = NvPrepareCopy;
+	pExa->Copy = NvCopy;
+	pExa->DoneCopy = NvDoneCopy;
+
+	switch(pNv->CurrentLayout.depth) {
+	case 24:
+		surfaceFormat = SURFACE_FORMAT_DEPTH24;
+		rectFormat = RECT_FORMAT_DEPTH24;
+		break;
+	case 16:
+	case 15:
+		surfaceFormat = SURFACE_FORMAT_DEPTH16;
+		rectFormat = RECT_FORMAT_DEPTH16;
+		break;
+	default:
+		surfaceFormat = SURFACE_FORMAT_DEPTH8;
+		rectFormat = RECT_FORMAT_DEPTH8;
+		break;
+	}
+	NVDmaStart(pNv, SURFACE_FORMAT, 1);
+	NVDmaNext (pNv, surfaceFormat);
+	NVDmaStart(pNv, RECT_FORMAT, 1);
+	NVDmaNext (pNv, rectFormat);
+
+	pNv->currentRop = ~0;  /* set to something invalid */
+	NVSetRopSolid(pScrn, GXcopy, ~0);
+
+	NVDmaKickoff(pNv);
+
+	/* EXA hits more optimized paths when it does not have to fallback 
+	 * because of missing UTS/DFS, hook memcpy-based UTS/DFS.
+	 */
+	pExa->UploadToScreen = NvUploadToScreen;
+	pExa->DownloadFromScreen = NvDownloadFromScreen;
+#ifdef __arm__
+	pExa->PrepareAccess = IgsPrepareAccess;
+	pExa->FinishAccess = IgsFinishAccess;
+#endif
+	return exaDriverInit(pScreen, pExa);
+}

Reply via email to