Martin Pieuchot
2015-12-11 09:09:20 UTC
Without hardware acceleration my PowerBook G4 12'' with a NVIDIA
GeForce FX Go 5200 is unusable. Since XAA is no longer supported,
here's a simple EXA backend for nv(4) based on the XAA sources and
Nouveau. It only implements Solid and Copy but that already makes
a huge difference.
To test it you need to regenerate configure scripts for xf86-video-nv
as described in /usr/xenocara/README.
I can provide a diff for upstream it the driver is still maintained.
I'd like to hear from people using NVidia cards.
Index: nv_driver.c
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-nv/src/nv_driver.c,v
retrieving revision 1.17
diff -u -p -r1.17 nv_driver.c
--- nv_driver.c 30 May 2014 06:42:00 -0000 1.17
+++ nv_driver.c 10 Dec 2015 18:31:09 -0000
@@ -637,6 +637,7 @@ typedef enum {
OPTION_SW_CURSOR,
OPTION_HW_CURSOR,
OPTION_NOACCEL,
+ OPTION_ACCEL_METHOD,
OPTION_SHADOW_FB,
OPTION_FBDEV,
OPTION_ROTATE,
@@ -654,6 +655,7 @@ static const OptionInfoRec NVOptions[] =
{ OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE },
{ OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_FBDEV, "UseFBDev", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE },
@@ -1346,7 +1348,7 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
int i, max_width, max_height;
ClockRangePtr clockRanges;
const char *s;
- Bool config_mon_rates;
+ Bool rc, config_mon_rates;
if (flags & PROBE_DETECT) {
EntityInfoPtr pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
@@ -1599,6 +1601,20 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
"Using framebuffer device\n");
}
+ if (!pNv->NoAccel) {
+ from = X_DEFAULT;
+ pNv->useEXA = TRUE;
+ if((s = (char *)xf86GetOptValString(pNv->Options, OPTION_ACCEL_METHOD))) {
+ if(!xf86NameCmp(s,"XAA")) {
+ from = X_CONFIG;
+ pNv->useEXA = FALSE;
+ } else if(!xf86NameCmp(s,"EXA")) {
+ from = X_CONFIG;
+ pNv->useEXA = TRUE;
+ }
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration method\n", pNv->useEXA ? "EXA" : "XAA");
+ }
if (pNv->FBDev) {
/* check for linux framebuffer device */
if (!xf86LoadSubModule(pScrn, "fbdevhw")) {
@@ -2051,12 +2067,12 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
return FALSE;
}
- /* Load XAA if needed */
+ /* Load XAA/EXA if needed */
if (!pNv->NoAccel) {
- if (!xf86LoadSubModule(pScrn, "xaa")) {
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Falling back to shadwwfb\n");
- pNv->NoAccel = 1;
- pNv->ShadowFB = 1;
+ if (!xf86LoadSubModule(pScrn, pNv->useEXA ? "exa" : "xaa")) {
+ xf86FreeInt10(pNv->pInt);
+ NVFreeRec(pScrn);
+ return FALSE;
}
}
@@ -2584,15 +2600,26 @@ NVScreenInit(SCREEN_INIT_ARGS_DECL)
if(offscreenHeight > 32767)
offscreenHeight = 32767;
+ if (!pNv->useEXA) {
AvailFBArea.x1 = 0;
AvailFBArea.y1 = 0;
AvailFBArea.x2 = pScrn->displayWidth;
AvailFBArea.y2 = offscreenHeight;
xf86InitFBManager(pScreen, &AvailFBArea);
-
- if (!pNv->NoAccel)
- NVAccelInit(pScreen);
-
+ }
+
+ if (!pNv->NoAccel) {
+ if (pNv->useEXA) {
+ if(!NVExaInit(pScreen, pScrn)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "EXA hardware acceleration initialization failed\n");
+ return FALSE;
+ }
+ } else /* XAA */
+ NVAccelInit(pScreen);
+ }
+ NVResetGraphics(pScrn);
+
xf86SetBackingStore(pScreen);
xf86SetSilkenMouse(pScreen);
Index: nv_exa.c
===================================================================
RCS file: nv_exa.c
diff -N nv_exa.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ nv_exa.c 10 Dec 2015 18:31:09 -0000
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2003 NVIDIA, Corporation
+ *
+ * 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 THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "nv_include.h"
+#include "exa.h"
+#include "nv_dma.h"
+
+Bool
+NVAccelGetCtxSurf2DFormatFromPixmap(PixmapPtr pPix, int *fmt_ret)
+{
+ switch (pPix->drawable.bitsPerPixel) {
+ case 32:
+ *fmt_ret = SURFACE_FORMAT_A8R8G8B8;
+ break;
+ case 24:
+ *fmt_ret = SURFACE_FORMAT_X8R8G8B8;
+ break;
+ case 16:
+ *fmt_ret = SURFACE_FORMAT_R5G6B5;
+ break;
+ case 8:
+ *fmt_ret = SURFACE_FORMAT_Y8;
+ break;
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+Bool
+NVAccelGetCtxSurf2DFormatFromPicture(PicturePtr pPict, int *fmt_ret)
+{
+ switch (pPict->format) {
+ case PICT_a8r8g8b8:
+ *fmt_ret = SURFACE_FORMAT_A8R8G8B8;
+ break;
+ case PICT_x8r8g8b8:
+ *fmt_ret = SURFACE_FORMAT_X8R8G8B8;
+ break;
+ case PICT_r5g6b5:
+ *fmt_ret = SURFACE_FORMAT_R5G6B5;
+ break;
+ case PICT_a8:
+ *fmt_ret = SURFACE_FORMAT_Y8;
+ break;
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+Bool
+NVAccelSetCtxSurf2D(NVPtr pNv, PixmapPtr psPix, PixmapPtr pdPix, int format)
+{
+ NVDmaStart(pNv, SURFACE_FORMAT, 4);
+ NVDmaNext(pNv, format);
+ NVDmaNext(pNv, ((uint32_t)exaGetPixmapPitch(pdPix) << 16) |
+ (uint32_t)exaGetPixmapPitch(psPix));
+ NVDmaNext(pNv, exaGetPixmapOffset(psPix));
+ NVDmaNext(pNv, exaGetPixmapOffset(pdPix));
+
+ return TRUE;
+}
+
+static CARD32
+rectFormat(DrawablePtr pDrawable)
+{
+ switch (pDrawable->bitsPerPixel) {
+ case 32:
+ case 24:
+ return RECT_FORMAT_DEPTH24;
+ break;
+ case 16:
+ return RECT_FORMAT_DEPTH16;
+ break;
+ default:
+ return RECT_FORMAT_DEPTH8;
+ break;
+ }
+}
+
+static void
+NVExaWaitMarker(ScreenPtr pScreen, int marker)
+{
+ NVSync(xf86ScreenToScrn(pScreen));
+}
+
+static Bool
+NVExaPrepareSolid(PixmapPtr pPix, int alu, Pixel planemask, Pixel fg)
+{
+ ScrnInfoPtr pScrn = xf86ScreenToScrn(pPix->drawable.pScreen);
+ NVPtr pNv = NVPTR(pScrn);
+ int fmt;
+
+ /* When SURFACE_FORMAT_A8R8G8B8 is used with GDI_RECTANGLE_TEXT, the
+ * alpha channel gets forced to 0xFF for some reason. We're using
+ * SURFACE_FORMAT_Y32 as a workaround
+ */
+ if (!NVAccelGetCtxSurf2DFormatFromPixmap(pPix, &fmt))
+ return FALSE;
+ if (fmt == SURFACE_FORMAT_A8R8G8B8)
+ fmt = 0xb;
+
+ planemask |= ~0 << pPix->drawable.bitsPerPixel;
+ if (planemask != ~0 || alu != GXcopy) {
+ if (pPix->drawable.bitsPerPixel == 32)
+ return FALSE;
+ NVSetRopSolid(pScrn, alu, planemask);
+ NVDmaStart(pNv, 0xC2FC, 1);
+ NVDmaNext(pNv, 1 /* ROP_AND */);
+ } else {
+ NVDmaStart(pNv, 0xC2FC, 1);
+ NVDmaNext(pNv, 3 /* SRCCOPY */);
+ }
+
+ if (!NVAccelSetCtxSurf2D(pNv, pPix, pPix, fmt))
+ return FALSE;
+
+ NVDmaStart(pNv, RECT_FORMAT, 1);
+ NVDmaNext(pNv, rectFormat(&pPix->drawable));
+ NVDmaStart(pNv, RECT_SOLID_COLOR, 1);
+ NVDmaNext(pNv, fg);
+
+ pNv->DMAKickoffCallback = NVDMAKickoffCallback;
+
+ return TRUE;
+}
+
+static void
+NVExaSolid(PixmapPtr pPix, int x1, int y1, int x2, int y2)
+{
+ ScrnInfoPtr pScrn = xf86ScreenToScrn(pPix->drawable.pScreen);
+ NVPtr pNv = NVPTR(pScrn);
+ int width = x2 - x1;
+ int height = y2 - y1;
+
+ NVDmaStart(pNv, RECT_SOLID_RECTS(0), 2);
+ NVDmaNext(pNv, (x1 << 16) | y1);
+ NVDmaNext(pNv, (width << 16) | height);
+
+ if ((width * height) >= 512)
+ NVDmaKickoff(pNv);
+}
+
+static void
+NVExaDoneSolid(PixmapPtr pPix)
+{
+}
+
+static Bool
+NVExaPrepareCopy(PixmapPtr psPix, PixmapPtr pdPix, int dx, int dy, int alu,
+ Pixel planemask)
+{
+ ScrnInfoPtr pScrn = xf86ScreenToScrn(psPix->drawable.pScreen);
+ NVPtr pNv = NVPTR(pScrn);
+ int fmt;
+
+ if (psPix->drawable.bitsPerPixel !=
+ pdPix->drawable.bitsPerPixel)
+ return FALSE;
+
+ if (!NVAccelGetCtxSurf2DFormatFromPixmap(pdPix, &fmt))
+ return FALSE;
+
+ planemask |= ~0 << pdPix->drawable.bitsPerPixel;
+ if (planemask != ~0 || alu != GXcopy) {
+ if (pdPix->drawable.bitsPerPixel == 32)
+ return FALSE;
+ NVSetRopSolid(pScrn, alu, planemask);
+ NVDmaStart(pNv, 0xA2FC, 1);
+ NVDmaNext(pNv, 1 /* ROP_AND */);
+ } else {
+ NVDmaStart(pNv, 0xA2FC, 1);
+ NVDmaNext(pNv, 3 /* SRCCOPY */);
+ }
+
+ if (!NVAccelSetCtxSurf2D(pNv, psPix, pdPix, fmt))
+ return FALSE;
+
+ pNv->DMAKickoffCallback = NVDMAKickoffCallback;
+ return TRUE;
+}
+
+static void
+NVExaCopy(PixmapPtr pdPix, int srcX, int srcY, int dstX, int dstY, int width,
+ int height)
+{
+ ScrnInfoPtr pScrn = xf86ScreenToScrn(pdPix->drawable.pScreen);
+ NVPtr pNv = NVPTR(pScrn);
+
+ NVDmaStart(pNv, BLIT_POINT_SRC, 3);
+ NVDmaNext(pNv, (srcY << 16) | srcX);
+ NVDmaNext(pNv, (dstY << 16) | dstX);
+ NVDmaNext(pNv, (height << 16) | width);
+
+ if ((width * height) >= 512)
+ NVDmaKickoff(pNv);
+}
+
+static void
+NVExaDoneCopy(PixmapPtr pdPix)
+{
+}
+
+Bool
+NVExaInit(ScreenPtr pScreen, ScrnInfoPtr pScrn)
+{
+ NVPtr pNv = NVPTR(pScrn);
+
+ if (!(pNv->EXADriverPtr = exaDriverAlloc())) {
+ pNv->NoAccel = TRUE;
+ return FALSE;
+ }
+
+ pNv->EXADriverPtr->exa_major = EXA_VERSION_MAJOR;
+ pNv->EXADriverPtr->exa_minor = EXA_VERSION_MINOR;
+
+ pNv->EXADriverPtr->memoryBase = pNv->FbStart;
+ pNv->EXADriverPtr->memorySize = pNv->ScratchBufferStart;
+
+ pNv->EXADriverPtr->offScreenBase = 0;
+
+ pNv->EXADriverPtr->pixmapOffsetAlign = 256;
+ pNv->EXADriverPtr->pixmapPitchAlign = 64;
+
+ pNv->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
+
+ pNv->EXADriverPtr->maxX = 32768;
+ pNv->EXADriverPtr->maxY = 32768;
+
+ pNv->EXADriverPtr->WaitMarker = NVExaWaitMarker;
+
+ pNv->EXADriverPtr->PrepareCopy = NVExaPrepareCopy;
+ pNv->EXADriverPtr->Copy = NVExaCopy;
+ pNv->EXADriverPtr->DoneCopy = NVExaDoneCopy;
+
+ pNv->EXADriverPtr->PrepareSolid = NVExaPrepareSolid;
+ pNv->EXADriverPtr->Solid = NVExaSolid;
+ pNv->EXADriverPtr->DoneSolid = NVExaDoneSolid;
+
+ return exaDriverInit(pScreen, pNv->EXADriverPtr);
+}
Index: nv_video.c
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-nv/src/nv_video.c,v
retrieving revision 1.4
diff -u -p -r1.4 nv_video.c
--- nv_video.c 16 Aug 2012 16:35:27 -0000 1.4
+++ nv_video.c 10 Dec 2015 18:31:09 -0000
@@ -534,10 +534,44 @@ NVPutOverlayImage (
}
+#ifndef ExaOffscreenMarkUsed
+extern void ExaOffscreenMarkUsed(PixmapPtr);
+#endif
+#ifndef exaGetDrawablePixmap
+extern PixmapPtr exaGetDrawablePixmap(DrawablePtr);
+#endif
+#ifndef exaPixmapIsOffscreen
+extern Bool exaPixmapIsOffscreen(PixmapPtr p);
+#endif
+/* To support EXA 2.0, 2.1 has this in the header */
+#ifndef exaMoveInPixmap
+extern void exaMoveInPixmap(PixmapPtr pPixmap);
+#endif
+/**
+ * NVPutBlitImage
+ *
+ * @param pScrn screen
+ * @param src_offset
+ * @param id colorspace of image
+ * @param src_pitch
+ * @param dstBox
+ * @param x1
+ * @param y1
+ * @param x2
+ * @param y2
+ * @param width
+ * @param height
+ * @param src_w
+ * @param src_h
+ * @param drw_w
+ * @param drw_h
+ * @param clipBoxes
+ * @param pDraw
+ */
static void
NVPutBlitImage (
- ScrnInfoPtr pScrnInfo,
+ ScrnInfoPtr pScrn,
int offset,
int id,
int dstPitch,
@@ -552,15 +586,59 @@ NVPutBlitImage (
short src_h,
short drw_w,
short drw_h,
- RegionPtr clipBoxes
+ RegionPtr clipBoxes,
+ DrawablePtr pDraw
)
{
- NVPtr pNv = NVPTR(pScrnInfo);
+ NVPtr pNv = NVPTR(pScrn);
NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
- BoxPtr pbox = REGION_RECTS(clipBoxes);
- int nbox = REGION_NUM_RECTS(clipBoxes);
+ BoxPtr pbox;
+ int nbox;
CARD32 dsdx, dtdy, size, point, srcpoint, format;
+ if (pNv->useEXA) {
+ ScreenPtr pScreen = pScrn->pScreen;
+ PixmapPtr pPix = exaGetDrawablePixmap(pDraw);
+ int dst_format;
+
+ /* Try to get the dest drawable into vram */
+ if (!exaPixmapIsOffscreen(pPix)) {
+ exaMoveInPixmap(pPix);
+ ExaOffscreenMarkUsed(pPix);
+ }
+
+ /* If we failed, draw directly onto the screen pixmap.
+ * Not sure if this is the best approach, maybe failing
+ * with BadAlloc would be better?
+ */
+ if (!exaPixmapIsOffscreen(pPix)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "XV: couldn't move dst surface into vram\n");
+ pPix = pScreen->GetScreenPixmap(pScreen);
+ }
+
+ NVAccelGetCtxSurf2DFormatFromPixmap(pPix, &dst_format);
+ NVAccelSetCtxSurf2D(pNv, pPix, pPix, dst_format);
+
+#ifdef COMPOSITE
+ /* Adjust coordinates if drawing to an offscreen pixmap */
+ if (pPix->screen_x || pPix->screen_y) {
+ REGION_TRANSLATE(pScrn->pScreen, clipBoxes,
+ -pPix->screen_x,
+ -pPix->screen_y);
+ dstBox->x1 -= pPix->screen_x;
+ dstBox->x2 -= pPix->screen_x;
+ dstBox->y1 -= pPix->screen_y;
+ dstBox->y2 -= pPix->screen_y;
+ }
+
+ DamageDamageRegion((DrawablePtr)pPix, clipBoxes);
+#endif
+ }
+
+ pbox = REGION_RECTS(clipBoxes);
+ nbox = REGION_NUM_RECTS(clipBoxes);
+
dsdx = (src_w << 20) / drw_w;
dtdy = (src_h << 20) / drw_h;
@@ -623,12 +701,17 @@ NVPutBlitImage (
pbox++;
}
- if(pNv->CurrentLayout.depth == 15) {
- NVDmaStart(pNv, SURFACE_FORMAT, 1);
- NVDmaNext (pNv, SURFACE_FORMAT_DEPTH16);
+ if (!pNv->useEXA) {
+ if(pNv->CurrentLayout.depth == 15) {
+ NVDmaStart(pNv, SURFACE_FORMAT, 1);
+ NVDmaNext (pNv, SURFACE_FORMAT_DEPTH16);
+ }
}
NVDmaKickoff(pNv);
+ if (pNv->useEXA)
+ exaMarkSync(pScrn->pScreen);
+ else
#ifdef HAVE_XAA_H
SET_SYNC_FLAG(pNv->AccelInfoRec);
#endif
@@ -1185,7 +1268,7 @@ static int NVPutImage
NVPutBlitImage(pScrnInfo, offset, id, dstPitch, &dstBox,
xa, ya, xb, yb,
width, height, src_w, src_h, drw_w, drw_h,
- clipBoxes);
+ clipBoxes, pDraw);
} else {
NVPutOverlayImage(pScrnInfo, offset, id, dstPitch, &dstBox,
xa, ya, xb, yb,
Index: nv_xaa.c
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-nv/src/nv_xaa.c,v
retrieving revision 1.3
diff -u -p -r1.3 nv_xaa.c
--- nv_xaa.c 16 Aug 2012 16:35:27 -0000 1.3
+++ nv_xaa.c 10 Dec 2015 18:31:09 -0000
@@ -176,7 +176,7 @@ NVSetPattern(
NVDmaNext (pNv, pat1);
}
-static void
+void
NVSetRopSolid(ScrnInfoPtr pScrn, CARD32 rop, CARD32 planemask)
{
NVPtr pNv = NVPTR(pScrn);
@@ -270,13 +270,15 @@ void NVResetGraphics(ScrnInfoPtr pScrn)
NVDmaStart(pNv, RECT_FORMAT, 1);
NVDmaNext (pNv, rectFormat);
- NVDmaStart(pNv, LINE_FORMAT, 1);
- NVDmaNext (pNv, lineFormat);
+ if (!pNv->useEXA) {
+ NVDmaStart(pNv, LINE_FORMAT, 1);
+ NVDmaNext (pNv, lineFormat);
+ }
pNv->currentRop = ~0; /* set to something invalid */
NVSetRopSolid(pScrn, GXcopy, ~0);
- NVDmaKickoff(pNv);
+ /*NVDmaKickoff(pNv);*/
}
void NVSync(ScrnInfoPtr pScrn)
@@ -291,7 +293,7 @@ void NVSync(ScrnInfoPtr pScrn)
while(pNv->PGRAPH[0x0700/4]);
}
-static void
+void
NVDMAKickoffCallback (ScrnInfoPtr pScrn)
{
NVPtr pNv = NVPTR(pScrn);
Index: nv_dma.h
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-nv/src/nv_dma.h,v
retrieving revision 1.2
diff -u -p -r1.2 nv_dma.h
--- nv_dma.h 29 Jul 2008 20:04:57 -0000 1.2
+++ nv_dma.h 10 Dec 2015 18:31:09 -0000
@@ -21,17 +21,40 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
+#ifndef NV_DMA_H
+#define NV_DMA_H
+
+#define NVDmaNext(pNv, data) do { \
+ (pNv)->dmaBase[(pNv)->dmaCurrent++] = (data); \
+} while(0)
+
+#define NVDmaStart(pNv, tag, size) do { \
+ if((pNv)->dmaFree <= (size)) \
+ NVDmaWait(pNv, size); \
+ NVDmaNext(pNv, ((size) << 18) | (tag)); \
+ (pNv)->dmaFree -= ((size) + 1); \
+} while(0)
+
+
#define SURFACE_FORMAT 0x00000300
-#define SURFACE_FORMAT_DEPTH8 0x00000001
-#define SURFACE_FORMAT_DEPTH15 0x00000002
-#define SURFACE_FORMAT_DEPTH16 0x00000004
-#define SURFACE_FORMAT_DEPTH24 0x00000006
+#define SURFACE_FORMAT_Y8 0x00000001
+#define SURFACE_FORMAT_X1R5G5B5 0x00000002
+#define SURFACE_FORMAT_R5G6B5 0x00000004
+#define SURFACE_FORMAT_X8R8G8B8 0x00000006
+#define SURFACE_FORMAT_A8R8G8B8 0x0000000a
#define SURFACE_PITCH 0x00000304
#define SURFACE_PITCH_SRC 15:0
#define SURFACE_PITCH_DST 31:16
#define SURFACE_OFFSET_SRC 0x00000308
#define SURFACE_OFFSET_DST 0x0000030C
+/* compat */
+#define SURFACE_FORMAT_DEPTH8 SURFACE_FORMAT_Y8
+#define SURFACE_FORMAT_DEPTH15 SURFACE_FORMAT_X1R5G5B5
+#define SURFACE_FORMAT_DEPTH16 SURFACE_FORMAT_R5G6B5
+#define SURFACE_FORMAT_DEPTH24 SURFACE_FORMAT_X8R8G8B8
+#define SURFACE_FORMAT_DEPTH32 SURFACE_FORMAT_A8R8G8B8
+
#define ROP_SET 0x00002300
#define PATTERN_FORMAT 0x00004300
@@ -165,3 +188,5 @@
#define STRETCH_BLIT_SRC_POINT 0x0000E40C
#define STRETCH_BLIT_SRC_POINT_U 15:0
#define STRETCH_BLIT_SRC_POINT_V 31:16
+
+#endif /* NV_DMA_H */
Index: nv_include.h
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-nv/src/nv_include.h,v
retrieving revision 1.4
diff -u -p -r1.4 nv_include.h
--- nv_include.h 12 May 2013 13:06:25 -0000 1.4
+++ nv_include.h 10 Dec 2015 18:31:09 -0000
@@ -40,6 +40,8 @@
#ifdef HAVE_XAA_H
#include "xaa.h"
#endif
+#include "exa.h"
+
#include "xf86fbman.h"
#include "xf86cmap.h"
#include "shadowfb.h"
Index: nv_local.h
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-nv/src/nv_local.h,v
retrieving revision 1.3
diff -u -p -r1.3 nv_local.h
--- nv_local.h 18 Nov 2013 19:45:41 -0000 1.3
+++ nv_local.h 10 Dec 2015 18:31:09 -0000
@@ -54,16 +54,6 @@ typedef unsigned int U032;
#define VGA_WR08(p,i,d) NV_WR08(p,i,d)
#define VGA_RD08(p,i) NV_RD08(p,i)
-#define NVDmaNext(pNv, data) \
- (pNv)->dmaBase[(pNv)->dmaCurrent++] = (data)
-
-#define NVDmaStart(pNv, tag, size) { \
- if((pNv)->dmaFree <= (size)) \
- NVDmaWait(pNv, size); \
- NVDmaNext(pNv, ((size) << 18) | (tag)); \
- (pNv)->dmaFree -= ((size) + 1); \
-}
-
#if defined(__i386__)
#define _NV_FENCE() outb(0x3D0, 0);
#else
Index: nv_proto.h
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-nv/src/nv_proto.h,v
retrieving revision 1.3
diff -u -p -r1.3 nv_proto.h
--- nv_proto.h 18 Nov 2013 19:45:41 -0000 1.3
+++ nv_proto.h 10 Dec 2015 18:31:09 -0000
@@ -34,8 +34,17 @@ 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);
+
+/* int nv_exa.c */
+uint32_t NVAccelGetPixmapOffset(NVPtr pNv, PixmapPtr pPix);
+Bool NVAccelGetCtxSurf2DFormatFromPixmap(PixmapPtr pPix, int *fmt_ret);
+Bool NVAccelGetCtxSurf2DFormatFromPicture(PicturePtr pPix, int *fmt_ret);
+Bool NVAccelSetCtxSurf2D(NVPtr pNv, PixmapPtr psPix, PixmapPtr pdPix, int fmt);
+Bool NVExaInit(ScreenPtr pScreen, ScrnInfoPtr pScrn);
/* in nv_dga.c */
Bool NVDGAInit(ScreenPtr pScreen);
Index: nv_type.h
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-nv/src/nv_type.h,v
retrieving revision 1.4
diff -u -p -r1.4 nv_type.h
--- nv_type.h 18 Nov 2013 19:45:41 -0000 1.4
+++ nv_type.h 10 Dec 2015 18:31:09 -0000
@@ -12,6 +12,39 @@
#define NV_ARCH_30 0x30
#define NV_ARCH_40 0x40
+#define CHIPSET_NV03 0x0010
+#define CHIPSET_NV04 0x0020
+#define CHIPSET_NV10 0x0100
+#define CHIPSET_NV11 0x0110
+#define CHIPSET_NV15 0x0150
+#define CHIPSET_NV17 0x0170
+#define CHIPSET_NV18 0x0180
+#define CHIPSET_NFORCE 0x01A0
+#define CHIPSET_NFORCE2 0x01F0
+#define CHIPSET_NV20 0x0200
+#define CHIPSET_NV25 0x0250
+#define CHIPSET_NV28 0x0280
+#define CHIPSET_NV30 0x0300
+#define CHIPSET_NV31 0x0310
+#define CHIPSET_NV34 0x0320
+#define CHIPSET_NV35 0x0330
+#define CHIPSET_NV36 0x0340
+#define CHIPSET_NV40 0x0040
+#define CHIPSET_NV41 0x00C0
+#define CHIPSET_NV43 0x0140
+#define CHIPSET_NV44 0x0160
+#define CHIPSET_NV44A 0x0220
+#define CHIPSET_NV45 0x0210
+#define CHIPSET_MISC_BRIDGED 0x00F0
+#define CHIPSET_G70 0x0090
+#define CHIPSET_G71 0x0290
+#define CHIPSET_G72 0x01D0
+#define CHIPSET_G73 0x0390
+// integrated GeForces (6100, 6150)
+#define CHIPSET_C51 0x0240
+// variant of C51, seems based on a G70 design
+#define CHIPSET_C512 0x03D0
+#define CHIPSET_G73_BRIDGED 0x02E0
#define NV_BITMASK(t,b) (((unsigned)(1U << (((t)-(b)+1)))-1) << (b))
#define NV_MASKEXPAND(mask) NV_BITMASK(1?mask,0?mask)
@@ -77,6 +110,7 @@ typedef struct {
RIVA_HW_STATE *CurrentState;
CARD32 Architecture;
CARD32 CursorStart;
+ int offscreenHeight;
EntityInfoPtr pEnt;
#if XSERVER_LIBPCIACCESS
struct pci_device *PciInfo;
@@ -125,9 +159,16 @@ typedef struct {
volatile U008 *PDIO0;
volatile U008 *PDIO;
volatile U032 *PRAMDAC;
+
+ /* XAA */
#ifdef HAVE_XAA_H
XAAInfoRecPtr AccelInfoRec;
#endif
+
+ /* EXA */
+ ExaDriverPtr EXADriverPtr;
+ Bool useEXA;
+
xf86CursorInfoPtr CursorInfoRec;
DGAModePtr DGAModes;
int numDGAModes;
Index: Makefile.am
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-nv/src/Makefile.am,v
retrieving revision 1.4
diff -u -p -r1.4 Makefile.am
--- Makefile.am 16 Aug 2012 16:35:27 -0000 1.4
+++ Makefile.am 10 Dec 2015 18:31:09 -0000
@@ -46,6 +46,7 @@ nv_sources = \
nv_shadow.c \
nv_type.h \
nv_video.c \
+ nv_exa.c \
nv_xaa.c
riva_sources = \
GeForce FX Go 5200 is unusable. Since XAA is no longer supported,
here's a simple EXA backend for nv(4) based on the XAA sources and
Nouveau. It only implements Solid and Copy but that already makes
a huge difference.
To test it you need to regenerate configure scripts for xf86-video-nv
as described in /usr/xenocara/README.
I can provide a diff for upstream it the driver is still maintained.
I'd like to hear from people using NVidia cards.
Index: nv_driver.c
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-nv/src/nv_driver.c,v
retrieving revision 1.17
diff -u -p -r1.17 nv_driver.c
--- nv_driver.c 30 May 2014 06:42:00 -0000 1.17
+++ nv_driver.c 10 Dec 2015 18:31:09 -0000
@@ -637,6 +637,7 @@ typedef enum {
OPTION_SW_CURSOR,
OPTION_HW_CURSOR,
OPTION_NOACCEL,
+ OPTION_ACCEL_METHOD,
OPTION_SHADOW_FB,
OPTION_FBDEV,
OPTION_ROTATE,
@@ -654,6 +655,7 @@ static const OptionInfoRec NVOptions[] =
{ OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE },
{ OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_FBDEV, "UseFBDev", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE },
@@ -1346,7 +1348,7 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
int i, max_width, max_height;
ClockRangePtr clockRanges;
const char *s;
- Bool config_mon_rates;
+ Bool rc, config_mon_rates;
if (flags & PROBE_DETECT) {
EntityInfoPtr pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
@@ -1599,6 +1601,20 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
"Using framebuffer device\n");
}
+ if (!pNv->NoAccel) {
+ from = X_DEFAULT;
+ pNv->useEXA = TRUE;
+ if((s = (char *)xf86GetOptValString(pNv->Options, OPTION_ACCEL_METHOD))) {
+ if(!xf86NameCmp(s,"XAA")) {
+ from = X_CONFIG;
+ pNv->useEXA = FALSE;
+ } else if(!xf86NameCmp(s,"EXA")) {
+ from = X_CONFIG;
+ pNv->useEXA = TRUE;
+ }
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration method\n", pNv->useEXA ? "EXA" : "XAA");
+ }
if (pNv->FBDev) {
/* check for linux framebuffer device */
if (!xf86LoadSubModule(pScrn, "fbdevhw")) {
@@ -2051,12 +2067,12 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
return FALSE;
}
- /* Load XAA if needed */
+ /* Load XAA/EXA if needed */
if (!pNv->NoAccel) {
- if (!xf86LoadSubModule(pScrn, "xaa")) {
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Falling back to shadwwfb\n");
- pNv->NoAccel = 1;
- pNv->ShadowFB = 1;
+ if (!xf86LoadSubModule(pScrn, pNv->useEXA ? "exa" : "xaa")) {
+ xf86FreeInt10(pNv->pInt);
+ NVFreeRec(pScrn);
+ return FALSE;
}
}
@@ -2584,15 +2600,26 @@ NVScreenInit(SCREEN_INIT_ARGS_DECL)
if(offscreenHeight > 32767)
offscreenHeight = 32767;
+ if (!pNv->useEXA) {
AvailFBArea.x1 = 0;
AvailFBArea.y1 = 0;
AvailFBArea.x2 = pScrn->displayWidth;
AvailFBArea.y2 = offscreenHeight;
xf86InitFBManager(pScreen, &AvailFBArea);
-
- if (!pNv->NoAccel)
- NVAccelInit(pScreen);
-
+ }
+
+ if (!pNv->NoAccel) {
+ if (pNv->useEXA) {
+ if(!NVExaInit(pScreen, pScrn)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "EXA hardware acceleration initialization failed\n");
+ return FALSE;
+ }
+ } else /* XAA */
+ NVAccelInit(pScreen);
+ }
+ NVResetGraphics(pScrn);
+
xf86SetBackingStore(pScreen);
xf86SetSilkenMouse(pScreen);
Index: nv_exa.c
===================================================================
RCS file: nv_exa.c
diff -N nv_exa.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ nv_exa.c 10 Dec 2015 18:31:09 -0000
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2003 NVIDIA, Corporation
+ *
+ * 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 THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "nv_include.h"
+#include "exa.h"
+#include "nv_dma.h"
+
+Bool
+NVAccelGetCtxSurf2DFormatFromPixmap(PixmapPtr pPix, int *fmt_ret)
+{
+ switch (pPix->drawable.bitsPerPixel) {
+ case 32:
+ *fmt_ret = SURFACE_FORMAT_A8R8G8B8;
+ break;
+ case 24:
+ *fmt_ret = SURFACE_FORMAT_X8R8G8B8;
+ break;
+ case 16:
+ *fmt_ret = SURFACE_FORMAT_R5G6B5;
+ break;
+ case 8:
+ *fmt_ret = SURFACE_FORMAT_Y8;
+ break;
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+Bool
+NVAccelGetCtxSurf2DFormatFromPicture(PicturePtr pPict, int *fmt_ret)
+{
+ switch (pPict->format) {
+ case PICT_a8r8g8b8:
+ *fmt_ret = SURFACE_FORMAT_A8R8G8B8;
+ break;
+ case PICT_x8r8g8b8:
+ *fmt_ret = SURFACE_FORMAT_X8R8G8B8;
+ break;
+ case PICT_r5g6b5:
+ *fmt_ret = SURFACE_FORMAT_R5G6B5;
+ break;
+ case PICT_a8:
+ *fmt_ret = SURFACE_FORMAT_Y8;
+ break;
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+Bool
+NVAccelSetCtxSurf2D(NVPtr pNv, PixmapPtr psPix, PixmapPtr pdPix, int format)
+{
+ NVDmaStart(pNv, SURFACE_FORMAT, 4);
+ NVDmaNext(pNv, format);
+ NVDmaNext(pNv, ((uint32_t)exaGetPixmapPitch(pdPix) << 16) |
+ (uint32_t)exaGetPixmapPitch(psPix));
+ NVDmaNext(pNv, exaGetPixmapOffset(psPix));
+ NVDmaNext(pNv, exaGetPixmapOffset(pdPix));
+
+ return TRUE;
+}
+
+static CARD32
+rectFormat(DrawablePtr pDrawable)
+{
+ switch (pDrawable->bitsPerPixel) {
+ case 32:
+ case 24:
+ return RECT_FORMAT_DEPTH24;
+ break;
+ case 16:
+ return RECT_FORMAT_DEPTH16;
+ break;
+ default:
+ return RECT_FORMAT_DEPTH8;
+ break;
+ }
+}
+
+static void
+NVExaWaitMarker(ScreenPtr pScreen, int marker)
+{
+ NVSync(xf86ScreenToScrn(pScreen));
+}
+
+static Bool
+NVExaPrepareSolid(PixmapPtr pPix, int alu, Pixel planemask, Pixel fg)
+{
+ ScrnInfoPtr pScrn = xf86ScreenToScrn(pPix->drawable.pScreen);
+ NVPtr pNv = NVPTR(pScrn);
+ int fmt;
+
+ /* When SURFACE_FORMAT_A8R8G8B8 is used with GDI_RECTANGLE_TEXT, the
+ * alpha channel gets forced to 0xFF for some reason. We're using
+ * SURFACE_FORMAT_Y32 as a workaround
+ */
+ if (!NVAccelGetCtxSurf2DFormatFromPixmap(pPix, &fmt))
+ return FALSE;
+ if (fmt == SURFACE_FORMAT_A8R8G8B8)
+ fmt = 0xb;
+
+ planemask |= ~0 << pPix->drawable.bitsPerPixel;
+ if (planemask != ~0 || alu != GXcopy) {
+ if (pPix->drawable.bitsPerPixel == 32)
+ return FALSE;
+ NVSetRopSolid(pScrn, alu, planemask);
+ NVDmaStart(pNv, 0xC2FC, 1);
+ NVDmaNext(pNv, 1 /* ROP_AND */);
+ } else {
+ NVDmaStart(pNv, 0xC2FC, 1);
+ NVDmaNext(pNv, 3 /* SRCCOPY */);
+ }
+
+ if (!NVAccelSetCtxSurf2D(pNv, pPix, pPix, fmt))
+ return FALSE;
+
+ NVDmaStart(pNv, RECT_FORMAT, 1);
+ NVDmaNext(pNv, rectFormat(&pPix->drawable));
+ NVDmaStart(pNv, RECT_SOLID_COLOR, 1);
+ NVDmaNext(pNv, fg);
+
+ pNv->DMAKickoffCallback = NVDMAKickoffCallback;
+
+ return TRUE;
+}
+
+static void
+NVExaSolid(PixmapPtr pPix, int x1, int y1, int x2, int y2)
+{
+ ScrnInfoPtr pScrn = xf86ScreenToScrn(pPix->drawable.pScreen);
+ NVPtr pNv = NVPTR(pScrn);
+ int width = x2 - x1;
+ int height = y2 - y1;
+
+ NVDmaStart(pNv, RECT_SOLID_RECTS(0), 2);
+ NVDmaNext(pNv, (x1 << 16) | y1);
+ NVDmaNext(pNv, (width << 16) | height);
+
+ if ((width * height) >= 512)
+ NVDmaKickoff(pNv);
+}
+
+static void
+NVExaDoneSolid(PixmapPtr pPix)
+{
+}
+
+static Bool
+NVExaPrepareCopy(PixmapPtr psPix, PixmapPtr pdPix, int dx, int dy, int alu,
+ Pixel planemask)
+{
+ ScrnInfoPtr pScrn = xf86ScreenToScrn(psPix->drawable.pScreen);
+ NVPtr pNv = NVPTR(pScrn);
+ int fmt;
+
+ if (psPix->drawable.bitsPerPixel !=
+ pdPix->drawable.bitsPerPixel)
+ return FALSE;
+
+ if (!NVAccelGetCtxSurf2DFormatFromPixmap(pdPix, &fmt))
+ return FALSE;
+
+ planemask |= ~0 << pdPix->drawable.bitsPerPixel;
+ if (planemask != ~0 || alu != GXcopy) {
+ if (pdPix->drawable.bitsPerPixel == 32)
+ return FALSE;
+ NVSetRopSolid(pScrn, alu, planemask);
+ NVDmaStart(pNv, 0xA2FC, 1);
+ NVDmaNext(pNv, 1 /* ROP_AND */);
+ } else {
+ NVDmaStart(pNv, 0xA2FC, 1);
+ NVDmaNext(pNv, 3 /* SRCCOPY */);
+ }
+
+ if (!NVAccelSetCtxSurf2D(pNv, psPix, pdPix, fmt))
+ return FALSE;
+
+ pNv->DMAKickoffCallback = NVDMAKickoffCallback;
+ return TRUE;
+}
+
+static void
+NVExaCopy(PixmapPtr pdPix, int srcX, int srcY, int dstX, int dstY, int width,
+ int height)
+{
+ ScrnInfoPtr pScrn = xf86ScreenToScrn(pdPix->drawable.pScreen);
+ NVPtr pNv = NVPTR(pScrn);
+
+ NVDmaStart(pNv, BLIT_POINT_SRC, 3);
+ NVDmaNext(pNv, (srcY << 16) | srcX);
+ NVDmaNext(pNv, (dstY << 16) | dstX);
+ NVDmaNext(pNv, (height << 16) | width);
+
+ if ((width * height) >= 512)
+ NVDmaKickoff(pNv);
+}
+
+static void
+NVExaDoneCopy(PixmapPtr pdPix)
+{
+}
+
+Bool
+NVExaInit(ScreenPtr pScreen, ScrnInfoPtr pScrn)
+{
+ NVPtr pNv = NVPTR(pScrn);
+
+ if (!(pNv->EXADriverPtr = exaDriverAlloc())) {
+ pNv->NoAccel = TRUE;
+ return FALSE;
+ }
+
+ pNv->EXADriverPtr->exa_major = EXA_VERSION_MAJOR;
+ pNv->EXADriverPtr->exa_minor = EXA_VERSION_MINOR;
+
+ pNv->EXADriverPtr->memoryBase = pNv->FbStart;
+ pNv->EXADriverPtr->memorySize = pNv->ScratchBufferStart;
+
+ pNv->EXADriverPtr->offScreenBase = 0;
+
+ pNv->EXADriverPtr->pixmapOffsetAlign = 256;
+ pNv->EXADriverPtr->pixmapPitchAlign = 64;
+
+ pNv->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
+
+ pNv->EXADriverPtr->maxX = 32768;
+ pNv->EXADriverPtr->maxY = 32768;
+
+ pNv->EXADriverPtr->WaitMarker = NVExaWaitMarker;
+
+ pNv->EXADriverPtr->PrepareCopy = NVExaPrepareCopy;
+ pNv->EXADriverPtr->Copy = NVExaCopy;
+ pNv->EXADriverPtr->DoneCopy = NVExaDoneCopy;
+
+ pNv->EXADriverPtr->PrepareSolid = NVExaPrepareSolid;
+ pNv->EXADriverPtr->Solid = NVExaSolid;
+ pNv->EXADriverPtr->DoneSolid = NVExaDoneSolid;
+
+ return exaDriverInit(pScreen, pNv->EXADriverPtr);
+}
Index: nv_video.c
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-nv/src/nv_video.c,v
retrieving revision 1.4
diff -u -p -r1.4 nv_video.c
--- nv_video.c 16 Aug 2012 16:35:27 -0000 1.4
+++ nv_video.c 10 Dec 2015 18:31:09 -0000
@@ -534,10 +534,44 @@ NVPutOverlayImage (
}
+#ifndef ExaOffscreenMarkUsed
+extern void ExaOffscreenMarkUsed(PixmapPtr);
+#endif
+#ifndef exaGetDrawablePixmap
+extern PixmapPtr exaGetDrawablePixmap(DrawablePtr);
+#endif
+#ifndef exaPixmapIsOffscreen
+extern Bool exaPixmapIsOffscreen(PixmapPtr p);
+#endif
+/* To support EXA 2.0, 2.1 has this in the header */
+#ifndef exaMoveInPixmap
+extern void exaMoveInPixmap(PixmapPtr pPixmap);
+#endif
+/**
+ * NVPutBlitImage
+ *
+ * @param pScrn screen
+ * @param src_offset
+ * @param id colorspace of image
+ * @param src_pitch
+ * @param dstBox
+ * @param x1
+ * @param y1
+ * @param x2
+ * @param y2
+ * @param width
+ * @param height
+ * @param src_w
+ * @param src_h
+ * @param drw_w
+ * @param drw_h
+ * @param clipBoxes
+ * @param pDraw
+ */
static void
NVPutBlitImage (
- ScrnInfoPtr pScrnInfo,
+ ScrnInfoPtr pScrn,
int offset,
int id,
int dstPitch,
@@ -552,15 +586,59 @@ NVPutBlitImage (
short src_h,
short drw_w,
short drw_h,
- RegionPtr clipBoxes
+ RegionPtr clipBoxes,
+ DrawablePtr pDraw
)
{
- NVPtr pNv = NVPTR(pScrnInfo);
+ NVPtr pNv = NVPTR(pScrn);
NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
- BoxPtr pbox = REGION_RECTS(clipBoxes);
- int nbox = REGION_NUM_RECTS(clipBoxes);
+ BoxPtr pbox;
+ int nbox;
CARD32 dsdx, dtdy, size, point, srcpoint, format;
+ if (pNv->useEXA) {
+ ScreenPtr pScreen = pScrn->pScreen;
+ PixmapPtr pPix = exaGetDrawablePixmap(pDraw);
+ int dst_format;
+
+ /* Try to get the dest drawable into vram */
+ if (!exaPixmapIsOffscreen(pPix)) {
+ exaMoveInPixmap(pPix);
+ ExaOffscreenMarkUsed(pPix);
+ }
+
+ /* If we failed, draw directly onto the screen pixmap.
+ * Not sure if this is the best approach, maybe failing
+ * with BadAlloc would be better?
+ */
+ if (!exaPixmapIsOffscreen(pPix)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "XV: couldn't move dst surface into vram\n");
+ pPix = pScreen->GetScreenPixmap(pScreen);
+ }
+
+ NVAccelGetCtxSurf2DFormatFromPixmap(pPix, &dst_format);
+ NVAccelSetCtxSurf2D(pNv, pPix, pPix, dst_format);
+
+#ifdef COMPOSITE
+ /* Adjust coordinates if drawing to an offscreen pixmap */
+ if (pPix->screen_x || pPix->screen_y) {
+ REGION_TRANSLATE(pScrn->pScreen, clipBoxes,
+ -pPix->screen_x,
+ -pPix->screen_y);
+ dstBox->x1 -= pPix->screen_x;
+ dstBox->x2 -= pPix->screen_x;
+ dstBox->y1 -= pPix->screen_y;
+ dstBox->y2 -= pPix->screen_y;
+ }
+
+ DamageDamageRegion((DrawablePtr)pPix, clipBoxes);
+#endif
+ }
+
+ pbox = REGION_RECTS(clipBoxes);
+ nbox = REGION_NUM_RECTS(clipBoxes);
+
dsdx = (src_w << 20) / drw_w;
dtdy = (src_h << 20) / drw_h;
@@ -623,12 +701,17 @@ NVPutBlitImage (
pbox++;
}
- if(pNv->CurrentLayout.depth == 15) {
- NVDmaStart(pNv, SURFACE_FORMAT, 1);
- NVDmaNext (pNv, SURFACE_FORMAT_DEPTH16);
+ if (!pNv->useEXA) {
+ if(pNv->CurrentLayout.depth == 15) {
+ NVDmaStart(pNv, SURFACE_FORMAT, 1);
+ NVDmaNext (pNv, SURFACE_FORMAT_DEPTH16);
+ }
}
NVDmaKickoff(pNv);
+ if (pNv->useEXA)
+ exaMarkSync(pScrn->pScreen);
+ else
#ifdef HAVE_XAA_H
SET_SYNC_FLAG(pNv->AccelInfoRec);
#endif
@@ -1185,7 +1268,7 @@ static int NVPutImage
NVPutBlitImage(pScrnInfo, offset, id, dstPitch, &dstBox,
xa, ya, xb, yb,
width, height, src_w, src_h, drw_w, drw_h,
- clipBoxes);
+ clipBoxes, pDraw);
} else {
NVPutOverlayImage(pScrnInfo, offset, id, dstPitch, &dstBox,
xa, ya, xb, yb,
Index: nv_xaa.c
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-nv/src/nv_xaa.c,v
retrieving revision 1.3
diff -u -p -r1.3 nv_xaa.c
--- nv_xaa.c 16 Aug 2012 16:35:27 -0000 1.3
+++ nv_xaa.c 10 Dec 2015 18:31:09 -0000
@@ -176,7 +176,7 @@ NVSetPattern(
NVDmaNext (pNv, pat1);
}
-static void
+void
NVSetRopSolid(ScrnInfoPtr pScrn, CARD32 rop, CARD32 planemask)
{
NVPtr pNv = NVPTR(pScrn);
@@ -270,13 +270,15 @@ void NVResetGraphics(ScrnInfoPtr pScrn)
NVDmaStart(pNv, RECT_FORMAT, 1);
NVDmaNext (pNv, rectFormat);
- NVDmaStart(pNv, LINE_FORMAT, 1);
- NVDmaNext (pNv, lineFormat);
+ if (!pNv->useEXA) {
+ NVDmaStart(pNv, LINE_FORMAT, 1);
+ NVDmaNext (pNv, lineFormat);
+ }
pNv->currentRop = ~0; /* set to something invalid */
NVSetRopSolid(pScrn, GXcopy, ~0);
- NVDmaKickoff(pNv);
+ /*NVDmaKickoff(pNv);*/
}
void NVSync(ScrnInfoPtr pScrn)
@@ -291,7 +293,7 @@ void NVSync(ScrnInfoPtr pScrn)
while(pNv->PGRAPH[0x0700/4]);
}
-static void
+void
NVDMAKickoffCallback (ScrnInfoPtr pScrn)
{
NVPtr pNv = NVPTR(pScrn);
Index: nv_dma.h
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-nv/src/nv_dma.h,v
retrieving revision 1.2
diff -u -p -r1.2 nv_dma.h
--- nv_dma.h 29 Jul 2008 20:04:57 -0000 1.2
+++ nv_dma.h 10 Dec 2015 18:31:09 -0000
@@ -21,17 +21,40 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
+#ifndef NV_DMA_H
+#define NV_DMA_H
+
+#define NVDmaNext(pNv, data) do { \
+ (pNv)->dmaBase[(pNv)->dmaCurrent++] = (data); \
+} while(0)
+
+#define NVDmaStart(pNv, tag, size) do { \
+ if((pNv)->dmaFree <= (size)) \
+ NVDmaWait(pNv, size); \
+ NVDmaNext(pNv, ((size) << 18) | (tag)); \
+ (pNv)->dmaFree -= ((size) + 1); \
+} while(0)
+
+
#define SURFACE_FORMAT 0x00000300
-#define SURFACE_FORMAT_DEPTH8 0x00000001
-#define SURFACE_FORMAT_DEPTH15 0x00000002
-#define SURFACE_FORMAT_DEPTH16 0x00000004
-#define SURFACE_FORMAT_DEPTH24 0x00000006
+#define SURFACE_FORMAT_Y8 0x00000001
+#define SURFACE_FORMAT_X1R5G5B5 0x00000002
+#define SURFACE_FORMAT_R5G6B5 0x00000004
+#define SURFACE_FORMAT_X8R8G8B8 0x00000006
+#define SURFACE_FORMAT_A8R8G8B8 0x0000000a
#define SURFACE_PITCH 0x00000304
#define SURFACE_PITCH_SRC 15:0
#define SURFACE_PITCH_DST 31:16
#define SURFACE_OFFSET_SRC 0x00000308
#define SURFACE_OFFSET_DST 0x0000030C
+/* compat */
+#define SURFACE_FORMAT_DEPTH8 SURFACE_FORMAT_Y8
+#define SURFACE_FORMAT_DEPTH15 SURFACE_FORMAT_X1R5G5B5
+#define SURFACE_FORMAT_DEPTH16 SURFACE_FORMAT_R5G6B5
+#define SURFACE_FORMAT_DEPTH24 SURFACE_FORMAT_X8R8G8B8
+#define SURFACE_FORMAT_DEPTH32 SURFACE_FORMAT_A8R8G8B8
+
#define ROP_SET 0x00002300
#define PATTERN_FORMAT 0x00004300
@@ -165,3 +188,5 @@
#define STRETCH_BLIT_SRC_POINT 0x0000E40C
#define STRETCH_BLIT_SRC_POINT_U 15:0
#define STRETCH_BLIT_SRC_POINT_V 31:16
+
+#endif /* NV_DMA_H */
Index: nv_include.h
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-nv/src/nv_include.h,v
retrieving revision 1.4
diff -u -p -r1.4 nv_include.h
--- nv_include.h 12 May 2013 13:06:25 -0000 1.4
+++ nv_include.h 10 Dec 2015 18:31:09 -0000
@@ -40,6 +40,8 @@
#ifdef HAVE_XAA_H
#include "xaa.h"
#endif
+#include "exa.h"
+
#include "xf86fbman.h"
#include "xf86cmap.h"
#include "shadowfb.h"
Index: nv_local.h
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-nv/src/nv_local.h,v
retrieving revision 1.3
diff -u -p -r1.3 nv_local.h
--- nv_local.h 18 Nov 2013 19:45:41 -0000 1.3
+++ nv_local.h 10 Dec 2015 18:31:09 -0000
@@ -54,16 +54,6 @@ typedef unsigned int U032;
#define VGA_WR08(p,i,d) NV_WR08(p,i,d)
#define VGA_RD08(p,i) NV_RD08(p,i)
-#define NVDmaNext(pNv, data) \
- (pNv)->dmaBase[(pNv)->dmaCurrent++] = (data)
-
-#define NVDmaStart(pNv, tag, size) { \
- if((pNv)->dmaFree <= (size)) \
- NVDmaWait(pNv, size); \
- NVDmaNext(pNv, ((size) << 18) | (tag)); \
- (pNv)->dmaFree -= ((size) + 1); \
-}
-
#if defined(__i386__)
#define _NV_FENCE() outb(0x3D0, 0);
#else
Index: nv_proto.h
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-nv/src/nv_proto.h,v
retrieving revision 1.3
diff -u -p -r1.3 nv_proto.h
--- nv_proto.h 18 Nov 2013 19:45:41 -0000 1.3
+++ nv_proto.h 10 Dec 2015 18:31:09 -0000
@@ -34,8 +34,17 @@ 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);
+
+/* int nv_exa.c */
+uint32_t NVAccelGetPixmapOffset(NVPtr pNv, PixmapPtr pPix);
+Bool NVAccelGetCtxSurf2DFormatFromPixmap(PixmapPtr pPix, int *fmt_ret);
+Bool NVAccelGetCtxSurf2DFormatFromPicture(PicturePtr pPix, int *fmt_ret);
+Bool NVAccelSetCtxSurf2D(NVPtr pNv, PixmapPtr psPix, PixmapPtr pdPix, int fmt);
+Bool NVExaInit(ScreenPtr pScreen, ScrnInfoPtr pScrn);
/* in nv_dga.c */
Bool NVDGAInit(ScreenPtr pScreen);
Index: nv_type.h
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-nv/src/nv_type.h,v
retrieving revision 1.4
diff -u -p -r1.4 nv_type.h
--- nv_type.h 18 Nov 2013 19:45:41 -0000 1.4
+++ nv_type.h 10 Dec 2015 18:31:09 -0000
@@ -12,6 +12,39 @@
#define NV_ARCH_30 0x30
#define NV_ARCH_40 0x40
+#define CHIPSET_NV03 0x0010
+#define CHIPSET_NV04 0x0020
+#define CHIPSET_NV10 0x0100
+#define CHIPSET_NV11 0x0110
+#define CHIPSET_NV15 0x0150
+#define CHIPSET_NV17 0x0170
+#define CHIPSET_NV18 0x0180
+#define CHIPSET_NFORCE 0x01A0
+#define CHIPSET_NFORCE2 0x01F0
+#define CHIPSET_NV20 0x0200
+#define CHIPSET_NV25 0x0250
+#define CHIPSET_NV28 0x0280
+#define CHIPSET_NV30 0x0300
+#define CHIPSET_NV31 0x0310
+#define CHIPSET_NV34 0x0320
+#define CHIPSET_NV35 0x0330
+#define CHIPSET_NV36 0x0340
+#define CHIPSET_NV40 0x0040
+#define CHIPSET_NV41 0x00C0
+#define CHIPSET_NV43 0x0140
+#define CHIPSET_NV44 0x0160
+#define CHIPSET_NV44A 0x0220
+#define CHIPSET_NV45 0x0210
+#define CHIPSET_MISC_BRIDGED 0x00F0
+#define CHIPSET_G70 0x0090
+#define CHIPSET_G71 0x0290
+#define CHIPSET_G72 0x01D0
+#define CHIPSET_G73 0x0390
+// integrated GeForces (6100, 6150)
+#define CHIPSET_C51 0x0240
+// variant of C51, seems based on a G70 design
+#define CHIPSET_C512 0x03D0
+#define CHIPSET_G73_BRIDGED 0x02E0
#define NV_BITMASK(t,b) (((unsigned)(1U << (((t)-(b)+1)))-1) << (b))
#define NV_MASKEXPAND(mask) NV_BITMASK(1?mask,0?mask)
@@ -77,6 +110,7 @@ typedef struct {
RIVA_HW_STATE *CurrentState;
CARD32 Architecture;
CARD32 CursorStart;
+ int offscreenHeight;
EntityInfoPtr pEnt;
#if XSERVER_LIBPCIACCESS
struct pci_device *PciInfo;
@@ -125,9 +159,16 @@ typedef struct {
volatile U008 *PDIO0;
volatile U008 *PDIO;
volatile U032 *PRAMDAC;
+
+ /* XAA */
#ifdef HAVE_XAA_H
XAAInfoRecPtr AccelInfoRec;
#endif
+
+ /* EXA */
+ ExaDriverPtr EXADriverPtr;
+ Bool useEXA;
+
xf86CursorInfoPtr CursorInfoRec;
DGAModePtr DGAModes;
int numDGAModes;
Index: Makefile.am
===================================================================
RCS file: /cvs/xenocara/driver/xf86-video-nv/src/Makefile.am,v
retrieving revision 1.4
diff -u -p -r1.4 Makefile.am
--- Makefile.am 16 Aug 2012 16:35:27 -0000 1.4
+++ Makefile.am 10 Dec 2015 18:31:09 -0000
@@ -46,6 +46,7 @@ nv_sources = \
nv_shadow.c \
nv_type.h \
nv_video.c \
+ nv_exa.c \
nv_xaa.c
riva_sources = \