rpms/xorg-x11-drv-nouveau/devel nouveau-multiple-xserver.patch, NONE, 1.1 nouveau-nv50-fb-accel.patch, NONE, 1.1 nouveau-nv50-nva0-noaccel.patch, NONE, 1.1 nouveau-store-vbios.patch, NONE, 1.1 nouveau-transition-hack.patch, NONE, 1.1

Ben Skeggs bskeggs at fedoraproject.org
Mon Apr 13 10:47:02 UTC 2009


Author: bskeggs

Update of /cvs/pkgs/rpms/xorg-x11-drv-nouveau/devel
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv4731

Added Files:
	nouveau-multiple-xserver.patch nouveau-nv50-fb-accel.patch 
	nouveau-nv50-nva0-noaccel.patch nouveau-store-vbios.patch 
	nouveau-transition-hack.patch 
Log Message:
add new patches


nouveau-multiple-xserver.patch:

--- NEW FILE nouveau-multiple-xserver.patch ---
>From 5e1a05537d929b011bac973a36dfb17d5cbce85d Mon Sep 17 00:00:00 2001
From: Ben Skeggs <skeggsb at gmail.com>
Date: Mon, 13 Apr 2009 19:25:25 +1000
Subject: [PATCH 3/5] f11: hack to support multiple xserver instances

---
 src/nv_driver.c |  126 ++++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 98 insertions(+), 28 deletions(-)

diff --git a/src/nv_driver.c b/src/nv_driver.c
index 92232dd..9f4c96f 100644
--- a/src/nv_driver.c
+++ b/src/nv_driver.c
@@ -21,6 +21,7 @@
  */
 
 #include <stdio.h>
+#include <sys/ioctl.h>
 
 #include "nv_include.h"
 
@@ -654,14 +655,27 @@ NV50ReleaseDisplay(ScrnInfoPtr pScrn)
  */
 
 /* Mandatory */
+static void NVMapMemGART(ScrnInfoPtr);
 static Bool
 NVEnterVT(int scrnIndex, int flags)
 {
 	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
 	NVPtr pNv = NVPTR(pScrn);
+	int ret;
 
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVEnterVT is called.\n");
 
+	if (pNv->dev) {
+		ret = ioctl(nouveau_device(pNv->dev)->fd,
+			    DRM_IOCTL_SET_MASTER, NULL);
+		if (ret) {
+			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+				   "Unable to set master\n");
+		}
+
+		NVMapMemGART(pScrn);
+	}
+
 	if (!pNv->NoAccel)
 		NVAccelCommonInit(pScrn);
 
@@ -718,6 +732,12 @@ NVLeaveVT(int scrnIndex, int flags)
 
 	NVSync(pScrn);
 
+	if (pNv->dev) {
+		nouveau_bo_ref(NULL, &pNv->GART);
+
+		ioctl(nouveau_device(pNv->dev)->fd, DRM_IOCTL_DROP_MASTER, NULL);
+	}
+
 	if (!pNv->kms_enable) {
 		if (pNv->Architecture < NV_ARCH_50)
 			NVRestore(pScrn);
@@ -1629,11 +1649,81 @@ NVMapMemSW(ScrnInfoPtr pScrn)
 }
 
 static Bool
+NVMapMemSharedFB(ScrnInfoPtr pScrn)
+{
+	NVPtr pNv = NVPTR(pScrn);
+	uint64_t handle, size;
+	void *map;
+	int ret;
+
+	ret = nouveau_device_get_param(pNv->dev, 0xdeadcafe00000001, &handle);
+	if (ret)
+		return FALSE;
+
+	ret = nouveau_device_get_param(pNv->dev, 0xdeadcafe00000002, &size);
+	if (ret)
+		return FALSE;
+
+	if (nouveau_device(pNv->dev)->mm_enabled) {
+		ret = nouveau_bo_handle_ref(pNv->dev, handle, &pNv->FB);
+		if (ret) {
+			ErrorF("%d\n", ret);
+			return FALSE;
+		}
+
+		pNv->FB->size = size;
+		pNv->FB->tiled = (pNv->Architecture == NV_ARCH_50);
+		return TRUE;
+	}
+
+	ret = drmMap(nouveau_device(pNv->dev)->fd, handle >> 32, size, &map);
+	if (ret)
+		return FALSE;
+
+	ret = nouveau_bo_fake(pNv->dev, handle & 0xffffffff, NOUVEAU_BO_VRAM |
+			      NOUVEAU_BO_PIN, size, map, &pNv->FB);
+	if (ret)
+		return FALSE;
+
+	pNv->FB->tiled = (pNv->Architecture == NV_ARCH_50);
+	return TRUE;
+}
+
+static void
+NVMapMemGART(ScrnInfoPtr pScrn) {
+	NVPtr pNv = NVPTR(pScrn);
+	int size;
+
+	if (pNv->AGPSize) {
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			   "AGPGART: %dMiB available\n",
+			   (unsigned int)(pNv->AGPSize >> 20));
+		if (pNv->AGPSize > (16*1024*1024))
+			size = 16*1024*1024;
+		else
+			/* always leave 512kb for other things like the fifos */
+			size = pNv->AGPSize - 512*1024;
+	} else {
+		size = (4 << 20) - (1 << 18) ;
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			   "GART: PCI DMA - using %dKiB\n",
+			   size >> 10);
+	}
+
+	if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_GART | NOUVEAU_BO_PIN, 0,
+			   size, &pNv->GART)) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Unable to allocate GART memory\n");
+	}
+}
+
+static Bool
 NVMapMem(ScrnInfoPtr pScrn)
 {
 	NVPtr pNv = NVPTR(pScrn);
 	uint64_t res;
 	int size;
+	uint32_t flags;
 
 	if (!pNv->dev)
 		return NVMapMemSW(pScrn);
@@ -1650,46 +1740,26 @@ NVMapMem(ScrnInfoPtr pScrn)
 		size = size * (pScrn->bitsPerPixel >> 3);
 		size = size * pScrn->virtualY;
 	} else {
+		if (NVMapMemSharedFB(pScrn))
+			goto skip_fb;
 		size = pNv->VRAMPhysicalSize / 2;
 	}
 
-	if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_PIN,
-			   0, size, &pNv->FB)) {
+	flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_PIN;
+	if (pNv->Architecture >= NV_ARCH_50)
+		flags |= NOUVEAU_BO_TILED;
+
+	if (nouveau_bo_new(pNv->dev, flags, 0, size, &pNv->FB)) {
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 			   "Failed to allocate framebuffer memory\n");
 		return FALSE;
 	}
+skip_fb:
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		   "Allocated %dMiB VRAM for framebuffer + offscreen pixmaps, "
 		   "at offset 0x%X\n",
 		   (uint32_t)(pNv->FB->size >> 20), (uint32_t) pNv->FB->offset);
 
-	if (pNv->AGPSize) {
-		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-			   "AGPGART: %dMiB available\n",
-			   (unsigned int)(pNv->AGPSize >> 20));
-		if (pNv->AGPSize > (16*1024*1024))
-			size = 16*1024*1024;
-		else
-			/* always leave 512kb for other things like the fifos */
-			size = pNv->AGPSize - 512*1024;
-	} else {
-		size = (4 << 20) - (1 << 18) ;
-		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-			   "GART: PCI DMA - using %dKiB\n",
-			   size >> 10);
-	}
-
-	if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_GART | NOUVEAU_BO_PIN, 0,
-			   size, &pNv->GART)) {
-		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-			   "Unable to allocate GART memory\n");
-	}
-	if (pNv->GART) {
-		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-			   "GART: Allocated %dMiB as a scratch buffer\n",
-			   (unsigned int)(pNv->GART->size >> 20));
-	}
 
 	/* We don't need to allocate cursors / lut here if we're using
 	 * kernel modesetting
-- 
1.6.2.2


nouveau-nv50-fb-accel.patch:

--- NEW FILE nouveau-nv50-fb-accel.patch ---
>From ef28c68a7f4563b591e725d8d0119e2156a28f30 Mon Sep 17 00:00:00 2001
From: Ben Skeggs <skeggsb at gmail.com>
Date: Mon, 13 Apr 2009 19:30:38 +1000
Subject: [PATCH 4/5] nv50/f11: accelerate front-buffer rendering, linear shadow for scanout

---
 src/Makefile.am          |    1 +
 src/drmmode_display.c    |    8 +-
 src/nouveau_exa.c        |   37 +++++--
 src/nv50_randr.c         |    2 +-
 src/nv50_shadow_damage.c |  275 ++++++++++++++++++++++++++++++++++++++++++++++
 src/nv_dri.c             |    2 +-
 src/nv_driver.c          |   38 ++++++-
 src/nv_proto.h           |    4 +
 src/nv_shadow.c          |    8 +-
 src/nv_type.h            |    4 +
 10 files changed, 356 insertions(+), 23 deletions(-)
 create mode 100644 src/nv50_shadow_damage.c

diff --git a/src/Makefile.am b/src/Makefile.am
index 29253a6..0c9e4e9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -81,6 +81,7 @@ nouveau_drv_la_SOURCES = \
 			 nv50_xv.c \
 			 nv50_texture.h \
 			 nv50reg.h \
+			 nv50_shadow_damage.c \
 			 nouveau_crtc.h \
 			 nouveau_output.h \
 			 nouveau_connector.h \
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index c315a70..55f7468 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -214,8 +214,8 @@ drmmode_fb_copy_sw(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int dst_id,
 	}
 	src = (void *)req.vaddr;
 	
-	nouveau_bo_map(pNv->FB, NOUVEAU_BO_WR);
-	dst = pNv->FB->map;
+	nouveau_bo_map(pNv->scanout, NOUVEAU_BO_WR);
+	dst = pNv->scanout->map;
 	dst += (y * fb->pitch) + (x * (fb->bpp >> 3));
 
 	h = fb->height;
@@ -225,7 +225,7 @@ drmmode_fb_copy_sw(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int dst_id,
 		dst += pScrn->displayWidth * (pScrn->bitsPerPixel / 8);
 	}
 
-	nouveau_bo_unmap(pNv->FB);
+	nouveau_bo_unmap(pNv->scanout);
 	drmFree(fb);
 }
 
@@ -289,7 +289,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 		ret = drmModeAddFB(drmmode->fd,
 				   pScrn->virtualX, pScrn->virtualY,
 				   pScrn->depth, pScrn->bitsPerPixel,
-				   pitch, pNv->FB->handle, &drmmode->fb_id);
+				   pitch, pNv->scanout->handle, &drmmode->fb_id);
 		if (ret < 0) {
 			ErrorF("failed to add fb\n");
 			return FALSE;
diff --git a/src/nouveau_exa.c b/src/nouveau_exa.c
index b7bcc87..aee2794 100644
--- a/src/nouveau_exa.c
+++ b/src/nouveau_exa.c
@@ -265,7 +265,8 @@ nouveau_exa_wait_marker(ScreenPtr pScreen, int marker)
 static Bool
 nouveau_exa_prepare_access(PixmapPtr ppix, int index)
 {
-	ScrnInfoPtr pScrn = xf86Screens[ppix->drawable.pScreen->myNum];
+	ScreenPtr pScreen = ppix->drawable.pScreen;
+	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
 	NVPtr pNv = NVPTR(pScrn);
 
 	if (pNv->exa_driver_pixmaps) {
@@ -275,20 +276,33 @@ nouveau_exa_prepare_access(PixmapPtr ppix, int index)
 			return FALSE;
 
 		ppix->devPrivate.ptr = map;
-		return TRUE;
+	} else
+	if (ppix == pScreen->GetScreenPixmap(pScreen)) {
+		nouveau_bo_map(pNv->scanout, NOUVEAU_BO_RDWR);
+		ppix->devPrivate.ptr = pNv->scanout->map;
+	} else {
+		/* force migration */
+		return FALSE;
 	}
 
-	return FALSE;
+	return TRUE;
 }
 
 static void
 nouveau_exa_finish_access(PixmapPtr ppix, int index)
 {
-	ScrnInfoPtr pScrn = xf86Screens[ppix->drawable.pScreen->myNum];
+	ScreenPtr pScreen = ppix->drawable.pScreen;
+	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
 	NVPtr pNv = NVPTR(pScrn);
 
-	if (pNv->exa_driver_pixmaps)
+	if (pNv->exa_driver_pixmaps) {
 		nouveau_exa_pixmap_unmap(ppix);
+	} else
+	if (ppix == pScreen->GetScreenPixmap(pScreen)) {
+		ppix->devPrivate.ptr = NULL;
+		nouveau_bo_unmap(pNv->scanout);
+		nv50_shadow_damage_frontbuffer_fallback(pScrn);
+	}
 }
 
 static Bool
@@ -393,8 +407,7 @@ nouveau_exa_pixmap_is_tiled(PixmapPtr ppix)
 		if (!nouveau_pixmap_bo(ppix)->tiled)
 			return false;
 	} else
-	if (pNv->Architecture < NV_ARCH_50 ||
-	    exaGetPixmapOffset(ppix) < pNv->EXADriverPtr->offScreenBase)
+	if (pNv->Architecture < NV_ARCH_50)
 		return false;
 
 	return true;
@@ -406,7 +419,7 @@ nouveau_exa_pixmap_map(PixmapPtr ppix)
 	struct nouveau_bo *bo = nouveau_pixmap_bo(ppix);
 	unsigned delta = nouveau_pixmap_offset(ppix);
 
-	if (bo->tiled) {
+	if (NVPTR(xf86Screens[ppix->drawable.pScreen->myNum])->GART && bo->tiled) {
 		struct nouveau_pixmap *nvpix = nouveau_pixmap(ppix);
 
 		nvpix->map_refcount++;
@@ -432,7 +445,7 @@ nouveau_exa_pixmap_unmap(PixmapPtr ppix)
 {
 	struct nouveau_bo *bo = nouveau_pixmap_bo(ppix);
 
-	if (bo->tiled) {
+	if (NVPTR(xf86Screens[ppix->drawable.pScreen->myNum])->GART && bo->tiled) {
 		struct nouveau_pixmap *nvpix = nouveau_pixmap(ppix);
 
 		if (--nvpix->map_refcount)
@@ -616,6 +629,12 @@ nouveau_exa_init(ScreenPtr pScreen)
 		exa->maxY = 2048;
 	}
 
+	/* Needed for frontbuffer fallbacks (to ensure it accesses the linear fb). */
+	if (pNv->Architecture >= NV_ARCH_50) {
+		exa->PrepareAccess = nouveau_exa_prepare_access;
+		exa->FinishAccess = nouveau_exa_finish_access;
+	}
+
 	exa->MarkSync = nouveau_exa_mark_sync;
 	exa->WaitMarker = nouveau_exa_wait_marker;
 
diff --git a/src/nv50_randr.c b/src/nv50_randr.c
index 657e13a..6c19780 100644
--- a/src/nv50_randr.c
+++ b/src/nv50_randr.c
@@ -99,7 +99,7 @@ nv50_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr adjuste
 		nv_crtc->crtc->SetFB(nv_crtc->crtc, nv_crtc->shadow);
 		nv_crtc->crtc->SetFBOffset(nv_crtc->crtc, 0, 0);
 	} else {
-		nv_crtc->crtc->SetFB(nv_crtc->crtc, pNv->FB);
+		nv_crtc->crtc->SetFB(nv_crtc->crtc, pNv->scanout);
 		nv_crtc->crtc->SetFBOffset(nv_crtc->crtc, x, y);
 	}
 	nv_crtc->crtc->ModeSet(nv_crtc->crtc, mode);
diff --git a/src/nv50_shadow_damage.c b/src/nv50_shadow_damage.c
new file mode 100644
index 0000000..942aba3
--- /dev/null
+++ b/src/nv50_shadow_damage.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright 2009 Maarten Maathuis
+ *
+ * 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 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.
+ */
+
+/**
+ * This file serves to process all damage to the frontbuffer pixmap.
+ * This is needed until we can/have:
+ * - Tiled frontbufffer support.
+ * - Working wfb support.
+ * - Widespread wfb exa support.
+ */
+
+#include "nv_include.h"
+#include "damagestr.h"
+
+/* When driver allocated pixmaps are used we can easily fold this back into exa code. */
+static void nv50_shadow_damage_blit(PixmapPtr ppix, RegionPtr pRegion)
+{
+	ScrnInfoPtr pScrn = xf86Screens[ppix->drawable.pScreen->myNum];
+	NVPtr pNv = NVPTR(pScrn);
+	struct nouveau_channel *chan = pNv->chan;
+	struct nouveau_grobj *eng2d = pNv->Nv2D;
+	struct nouveau_bo *bo = nouveau_pixmap_bo(ppix);
+	unsigned delta = nouveau_pixmap_offset(ppix);
+	uint32_t fmt;
+	BoxPtr pbox;
+	int nbox;
+
+	pbox = REGION_RECTS(pRegion);
+	nbox = REGION_NUM_RECTS(pRegion);
+	if (!nbox)
+		return;
+
+	/* flush_notify is not needed, we check for all the ring space in advance. */
+	WAIT_RING (chan, 26 + nbox * 13);
+
+	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;
+	}
+
+	/* tiled source */
+	BEGIN_RING(chan, eng2d, NV50_2D_SRC_FORMAT, 5);
+	OUT_RING  (chan, fmt);
+	OUT_RING  (chan, 0);
+	OUT_RING  (chan, 0);
+	OUT_RING  (chan, 1);
+	OUT_RING  (chan, 0);
+
+	BEGIN_RING(chan, eng2d, NV50_2D_SRC_WIDTH, 4);
+	OUT_RING  (chan, ppix->drawable.width);
+	OUT_RING  (chan, ppix->drawable.height);
+	OUT_RELOCh(chan, bo, delta, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+	OUT_RELOCl(chan, bo, delta, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+	/* untiled destination */
+	BEGIN_RING(chan, eng2d, NV50_2D_DST_FORMAT, 2);
+	OUT_RING  (chan, fmt);
+	OUT_RING  (chan, 1);
+	BEGIN_RING(chan, eng2d, NV50_2D_DST_PITCH, 5);
+	OUT_RING  (chan, NOUVEAU_ALIGN(pScrn->virtualX, 64) *
+			 (pScrn->bitsPerPixel >> 3));
+	OUT_RING  (chan, ppix->drawable.width);
+	OUT_RING  (chan, ppix->drawable.height);
+	OUT_RELOCh(chan, pNv->scanout, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+	OUT_RELOCl(chan, pNv->scanout, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+	BEGIN_RING(chan, eng2d, NV50_2D_CLIP_X, 4);
+	OUT_RING  (chan, 0);
+	OUT_RING  (chan, 0);
+	OUT_RING  (chan, ppix->drawable.width);
+	OUT_RING  (chan, ppix->drawable.height);
+	BEGIN_RING(chan, eng2d, NV50_2D_OPERATION, 1);
+	OUT_RING  (chan, NV50_2D_OPERATION_SRCCOPY);
+
+	while (nbox--) {
+		BEGIN_RING(chan, eng2d, NV50_2D_BLIT_DST_X, 12);
+		OUT_RING  (chan, pbox->x1);
+		OUT_RING  (chan, pbox->y1);
+		OUT_RING  (chan, pbox->x2 - pbox->x1);
+		OUT_RING  (chan, pbox->y2 - pbox->y1);
+		OUT_RING  (chan, 0);
+		OUT_RING  (chan, 1);
+		OUT_RING  (chan, 0);
+		OUT_RING  (chan, 1);
+		OUT_RING  (chan, 0);
+		OUT_RING  (chan, pbox->x1);
+		OUT_RING  (chan, 0);
+		OUT_RING  (chan, pbox->y1);
+
+		pbox++;
+	}
+}
+
+/* For frontbuffer fallbacks. */
+static void nv50_shadow_damage_blit_back(PixmapPtr ppix, RegionPtr pRegion)
+{
+	ScrnInfoPtr pScrn = xf86Screens[ppix->drawable.pScreen->myNum];
+	NVPtr pNv = NVPTR(pScrn);
+	struct nouveau_channel *chan = pNv->chan;
+	struct nouveau_grobj *eng2d = pNv->Nv2D;
+	struct nouveau_bo *bo = nouveau_pixmap_bo(ppix);
+	unsigned delta = nouveau_pixmap_offset(ppix);
+	uint32_t fmt;
+	BoxPtr pbox;
+	int nbox;
+
+	pbox = REGION_RECTS(pRegion);
+	nbox = REGION_NUM_RECTS(pRegion);
+	if (!nbox)
+		return;
+
+	/* flush_notify is not needed, we check for all the ring space in advance. */
+	WAIT_RING (chan, 26 + nbox * 13);
+
+	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;
+	}
+
+	/* untiled source */
+	BEGIN_RING(chan, eng2d, NV50_2D_SRC_FORMAT, 2);
+	OUT_RING  (chan, fmt);
+	OUT_RING  (chan, 1);
+	BEGIN_RING(chan, eng2d, NV50_2D_SRC_PITCH, 5);
+	OUT_RING  (chan, NOUVEAU_ALIGN(pScrn->virtualX, 64) *
+			 (pScrn->bitsPerPixel >> 3));
+	OUT_RING  (chan, ppix->drawable.width);
+	OUT_RING  (chan, ppix->drawable.height);
+	OUT_RELOCh(chan, pNv->scanout, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+	OUT_RELOCl(chan, pNv->scanout, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+	/* tiled destination */
+	BEGIN_RING(chan, eng2d, NV50_2D_DST_FORMAT, 5);
+	OUT_RING  (chan, fmt);
+	OUT_RING  (chan, 0);
+	OUT_RING  (chan, 0);
+	OUT_RING  (chan, 1);
+	OUT_RING  (chan, 0);
+
+	BEGIN_RING(chan, eng2d, NV50_2D_DST_WIDTH, 4);
+	OUT_RING  (chan, ppix->drawable.width);
+	OUT_RING  (chan, ppix->drawable.height);
+	OUT_RELOCh(chan, bo, delta, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+	OUT_RELOCl(chan, bo, delta, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+	BEGIN_RING(chan, eng2d, NV50_2D_CLIP_X, 4);
+	OUT_RING  (chan, 0);
+	OUT_RING  (chan, 0);
+	OUT_RING  (chan, ppix->drawable.width);
+	OUT_RING  (chan, ppix->drawable.height);
+	BEGIN_RING(chan, eng2d, NV50_2D_OPERATION, 1);
+	OUT_RING  (chan, NV50_2D_OPERATION_SRCCOPY);
+
+	while (nbox--) {
+		BEGIN_RING(chan, eng2d, NV50_2D_BLIT_DST_X, 12);
+		OUT_RING  (chan, pbox->x1);
+		OUT_RING  (chan, pbox->y1);
+		OUT_RING  (chan, pbox->x2 - pbox->x1);
+		OUT_RING  (chan, pbox->y2 - pbox->y1);
+		OUT_RING  (chan, 0);
+		OUT_RING  (chan, 1);
+		OUT_RING  (chan, 0);
+		OUT_RING  (chan, 1);
+		OUT_RING  (chan, 0);
+		OUT_RING  (chan, pbox->x1);
+		OUT_RING  (chan, 0);
+		OUT_RING  (chan, pbox->y1);
+
+		pbox++;
+	}
+}
+
+static void nv50_shadow_damage_report(DamagePtr pDamage, RegionPtr pRegion, void *closure)
+{
+	PixmapPtr ppix = closure;
+
+	nv50_shadow_damage_blit(ppix, pRegion);
+}
+
+void nv50_shadow_damage_frontbuffer_fallback(ScrnInfoPtr pScrn)
+{
+	NVPtr pNv = NVPTR(pScrn);
+	ScreenPtr pScreen = pScrn->pScreen;
+	PixmapPtr ppix = NULL;
+	DamagePtr pDamage = pNv->screen_damage;
+
+	if (pNv->Architecture < NV_ARCH_50)
+		return;
+
+	ppix = pScreen->GetScreenPixmap(pScreen);
+	if (!ppix) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			"No screen pixmap.\n");
+		return;
+	}
+
+	/* Pending damage reflects the rendering currently being done. */
+	/* When exa calls finish access, damage hasn't flushed it yet. */
+	nv50_shadow_damage_blit_back(ppix, &pDamage->pendingDamage);
+}
+
+static void nv50_shadow_damage_destroy(DamagePtr pDamage, void *closure)
+{
+	PixmapPtr ppix = closure;
+	ScrnInfoPtr pScrn = xf86Screens[ppix->drawable.pScreen->myNum];
+	NVPtr pNv = NVPTR(pScrn);
+
+	pNv->screen_damage = NULL;
+}
+
+bool nv50_shadow_damage_create(ScrnInfoPtr pScrn)
+{
+	NVPtr pNv = NVPTR(pScrn);
+	ScreenPtr pScreen = pScrn->pScreen;
+	PixmapPtr ppix = NULL;
+
+	if (pNv->Architecture < NV_ARCH_50)
+		return false;
+
+	ppix = pScreen->GetScreenPixmap(pScreen);
+	if (!ppix) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			"No screen pixmap.\n");
+		return false;
+	}
+
+	pNv->screen_damage = DamageCreate(nv50_shadow_damage_report, nv50_shadow_damage_destroy, DamageReportRawRegion, true, pScreen, ppix);
+	if (!pNv->screen_damage) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			"No screen damage\n");
+		return false;
+	}
+
+	/* We want the notification after submission. */
+	DamageSetReportAfterOp(pNv->screen_damage, true);
+
+	DamageRegister(&ppix->drawable, pNv->screen_damage);
+
+	return true;
+}
diff --git a/src/nv_dri.c b/src/nv_dri.c
index bd3e5a9..dca6a40 100644
--- a/src/nv_dri.c
+++ b/src/nv_dri.c
@@ -337,7 +337,7 @@ Bool NVDRIFinishScreenInit(ScrnInfoPtr pScrn)
 	pNOUVEAUDRI->depth		= pScrn->depth;
 	pNOUVEAUDRI->bpp		= pScrn->bitsPerPixel;
 
-	ret = nouveau_bo_handle_get(pNv->FB, &pNOUVEAUDRI->front_offset);
+	ret = nouveau_bo_handle_get(pNv->scanout, &pNOUVEAUDRI->front_offset);
 	if (ret) {
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 			   "[dri] unable to reference front buffer: %d\n", ret);
diff --git a/src/nv_driver.c b/src/nv_driver.c
index 9f4c96f..d6391f3 100644
--- a/src/nv_driver.c
+++ b/src/nv_driver.c
@@ -686,10 +686,11 @@ NVEnterVT(int scrnIndex, int flags)
 		/* Clear the framebuffer, we don't want to see garbage
 		 * on-screen up until X decides to draw something
 		 */
-		nouveau_bo_map(pNv->FB, NOUVEAU_BO_WR);
-		memset(pNv->FB->map, 0, NOUVEAU_ALIGN(pScrn->virtualX, 64) *
-		       pScrn->virtualY * (pScrn->bitsPerPixel >> 3));
-		nouveau_bo_unmap(pNv->FB);
+		nouveau_bo_map(pNv->scanout, NOUVEAU_BO_WR);
+		memset(pNv->scanout->map, 0,
+		       NOUVEAU_ALIGN(pScrn->virtualX, 64) * pScrn->virtualY *
+		       (pScrn->bitsPerPixel >> 3));
+		nouveau_bo_unmap(pNv->scanout);
 
 		if (pNv->Architecture == NV_ARCH_50) {
 			if (!NV50AcquireDisplay(pScrn))
@@ -1609,6 +1610,8 @@ NVMapMemSW(ScrnInfoPtr pScrn)
 		return FALSE;
 	pNv->GART = NULL;
 
+	nouveau_bo_ref(pNv->FB, &pNv->scanout);
+
 	ret = nouveau_bo_fake(&dev, Cursor0Offset,
 			      NOUVEAU_BO_VRAM | NOUVEAU_BO_PIN,
 			      64 * 64 * 4, pNv->VRAMMap + Cursor0Offset,
@@ -1760,6 +1763,23 @@ skip_fb:
 		   "at offset 0x%X\n",
 		   (uint32_t)(pNv->FB->size >> 20), (uint32_t) pNv->FB->offset);
 
+	/* Allocate linear scanout. */
+	if (pNv->Architecture >= NV_ARCH_50) {
+		unsigned scanout_size;
+
+		scanout_size = NOUVEAU_ALIGN(pScrn->virtualX, 64);
+		scanout_size *= (pScrn->bitsPerPixel >> 3);
+		scanout_size *= pScrn->virtualY;
+
+		if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_PIN,
+				   0, scanout_size, &pNv->scanout)) {
+			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+				   "Failed to allocate scanout buffer\n");
+			return FALSE;
+		}
+	} else {
+		nouveau_bo_ref(pNv->FB, &pNv->scanout);
+	}
 
 	/* We don't need to allocate cursors / lut here if we're using
 	 * kernel modesetting
@@ -1832,6 +1852,7 @@ NVUnmapMem(ScrnInfoPtr pScrn)
 	}
 
 	nouveau_bo_ref(NULL, &pNv->FB);
+	nouveau_bo_ref(NULL, &pNv->scanout);
 	nouveau_bo_ref(NULL, &pNv->GART);
 	nouveau_bo_ref(NULL, &pNv->Cursor);
 	nouveau_bo_ref(NULL, &pNv->Cursor2);
@@ -2347,6 +2368,15 @@ NVSaveScreen(ScreenPtr pScreen, int mode)
 	bool on = xf86IsUnblank(mode);
 	int i;
 
+	/* This might seem strange, but we need an entry point after CreateScreenResources.
+	 * This happens to one of the few, if not the only place.
+	 * When we move to driver allocated pixmaps, we can move this.
+	 */
+	if (mode == SCREEN_SAVER_FORCER && pNv->Architecture == NV_ARCH_50 &&
+	    !pNv->NoAccel && !pNv->screen_damage &&
+	    !nv50_shadow_damage_create(pScrn))
+		return FALSE;
+
 	if (!pNv->randr12_enable)
 		return vgaHWSaveScreen(pScreen, mode);
 
diff --git a/src/nv_proto.h b/src/nv_proto.h
index 43fa62e..f06c757 100644
--- a/src/nv_proto.h
+++ b/src/nv_proto.h
@@ -267,6 +267,10 @@ void nv50_xv_video_stop(ScrnInfoPtr, pointer, Bool);
 int nv50_xv_port_attribute_set(ScrnInfoPtr, Atom, INT32, pointer);
 int nv50_xv_port_attribute_get(ScrnInfoPtr, Atom, INT32 *, pointer);
 
+/* nv50_shadow_damage.c */
+bool nv50_shadow_damage_create(ScrnInfoPtr pScrn);
+void nv50_shadow_damage_frontbuffer_fallback(ScrnInfoPtr pScrn);
+
 /* To support EXA 2.0, 2.1 has this in the header */
 #ifndef exaMoveInPixmap
 extern void exaMoveInPixmap(PixmapPtr pPixmap);
diff --git a/src/nv_shadow.c b/src/nv_shadow.c
index ea1ba35..e15051c 100644
--- a/src/nv_shadow.c
+++ b/src/nv_shadow.c
@@ -38,9 +38,9 @@ NVRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
    
 	cpp = pScrn->bitsPerPixel >> 3;
 	FBPitch = pScrn->displayWidth * cpp;
-	max_height = pNv->FB->size/FBPitch;
+	max_height = pNv->scanout->size/FBPitch;
 
-	nouveau_bo_map(pNv->FB, NOUVEAU_BO_WR);
+	nouveau_bo_map(pNv->scanout, NOUVEAU_BO_WR);
 	while(num--) {
 		x1 = MAX(pbox->x1, 0);
 		y1 = MAX(pbox->y1, 0);
@@ -51,7 +51,7 @@ NVRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
 
 		if (width > 0 && height > 0) {
 			src = pNv->ShadowPtr + (y1 * pNv->ShadowPitch) + (x1 * cpp);
-			dst = pNv->FB->map + (y1 * FBPitch) + (x1 * cpp);
+			dst = pNv->scanout->map + (y1 * FBPitch) + (x1 * cpp);
 
 			while(height--) {
 				memcpy(dst, src, width);
@@ -62,5 +62,5 @@ NVRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
 
 		pbox++;
 	}
-	nouveau_bo_unmap(pNv->FB);
+	nouveau_bo_unmap(pNv->scanout);
 } 
diff --git a/src/nv_type.h b/src/nv_type.h
index 2ec4fba..5396cc8 100644
--- a/src/nv_type.h
+++ b/src/nv_type.h
@@ -270,6 +270,7 @@ typedef struct _NVRec {
     /* Various pinned memory regions */
     struct nouveau_bo * FB;
     void *              FBMap;
+    struct nouveau_bo * scanout;
     //struct nouveau_bo * FB_old; /* for KMS */
     struct nouveau_bo * shadow[2]; /* for easy acces by exa */
     struct nouveau_bo * Cursor;
@@ -278,6 +279,9 @@ typedef struct _NVRec {
 
     struct nvbios	VBIOS;
     struct nouveau_bios_info	*vbios;
+
+    DamagePtr screen_damage; /* for NV50+ */
+
     Bool                NoAccel;
     Bool                HWCursor;
     Bool                FpScale;
-- 
1.6.2.2


nouveau-nv50-nva0-noaccel.patch:

--- NEW FILE nouveau-nv50-nva0-noaccel.patch ---
>From 30e4f6c24c167f03b8fb5e634904072be715dbc8 Mon Sep 17 00:00:00 2001
From: Ben Skeggs <skeggsb at gmail.com>
Date: Mon, 13 Apr 2009 20:20:39 +1000
Subject: [PATCH 5/5] nv50/f11: disable acceleration on NVAx chipsets

---
 src/nv_driver.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/src/nv_driver.c b/src/nv_driver.c
index d6391f3..b423cfd 100644
--- a/src/nv_driver.c
+++ b/src/nv_driver.c
@@ -1144,6 +1144,14 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
 		pNv->ShadowFB = TRUE;
 	}
 
+	if ((pNv->dev->chipset & 0xf0) == 0xa0) {
+		xf86DrvMsg(pScrn->scrnIndex, X_NOTICE,
+			   "Acceleration disabled, currently non-functional "
+			   "on this chipset\n");
+		pNv->NoAccel = TRUE;
+		pNv->ShadowFB = TRUE;
+	}
+
 	/* Save current console video mode */
 	if (pNv->Architecture >= NV_ARCH_50 && pNv->pInt10 && !pNv->kms_enable) {
 		const xf86Int10InfoPtr pInt10 = pNv->pInt10;
-- 
1.6.2.2


nouveau-store-vbios.patch:

--- NEW FILE nouveau-store-vbios.patch ---
>From 0b64ce0faefd2a87d46699ff1255e39d0051f115 Mon Sep 17 00:00:00 2001
From: Ben Skeggs <skeggsb at gmail.com>
Date: Mon, 13 Apr 2009 19:13:26 +1000
Subject: [PATCH 2/5] bios/f11: store a copy of used vbios image in /var/run

---
 src/nv_bios.c |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/src/nv_bios.c b/src/nv_bios.c
index ebf4027..ad4ff1f 100644
--- a/src/nv_bios.c
+++ b/src/nv_bios.c
@@ -22,6 +22,9 @@
  * SOFTWARE.
  */
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 #include "nv_include.h"
 
 #if defined(__FreeBSD__) || defined(__NetBSD__)
@@ -4492,7 +4495,10 @@ uint8_t * nouveau_bios_embedded_edid(ScrnInfoPtr pScrn)
 
 bool NVInitVBIOS(ScrnInfoPtr pScrn)
 {
+	NVPtr pNv = NVPTR(pScrn);
 	struct nvbios *bios = &NVPTR(pScrn)->VBIOS;
+	char img[128];
+	int fd;
 
 	memset(bios, 0, sizeof(struct nvbios));
 
@@ -4503,6 +4509,13 @@ bool NVInitVBIOS(ScrnInfoPtr pScrn)
 	if (bios->length > NV_PROM_SIZE)
 		bios->length = NV_PROM_SIZE;
 
+	sprintf(img, "/var/run/nv%02x_%04x.rom", pNv->NVArch, pNv->Chipset);
+	fd = open(img, O_CREAT|O_RDWR|O_EXCL, 0700);
+	if (fd >= 0) {
+		write(fd, bios->data, bios->length);
+		close(fd);
+	}
+
 	return true;
 }
 
-- 
1.6.2.2


nouveau-transition-hack.patch:

--- NEW FILE nouveau-transition-hack.patch ---
>From 0a328a89d65f3b6a98fbf49cefd3deb4f3521254 Mon Sep 17 00:00:00 2001
From: Ben Skeggs <skeggsb at gmail.com>
Date: Mon, 13 Apr 2009 19:12:25 +1000
Subject: [PATCH 1/5] kms/f11: hack in transition support without driver pixmaps

---
 src/drmmode_display.c |   53 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 51 insertions(+), 2 deletions(-)

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index aa8befe..c315a70 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -185,6 +185,51 @@ drmmode_fb_pixmap(ScrnInfoPtr pScrn, int id, int *w, int *h)
 }
 
 static void
+drmmode_fb_copy_sw(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int dst_id,
+		   int src_id, int x, int y)
+{
+	drmModeFBPtr fb;
+	NVPtr pNv = NVPTR(pScrn);
+	char *dst = NULL, *src = NULL;
+	struct drm_nouveau_gem_mmap req;
+	int ret, h;
+
+	/* This is not what this should look like.  Until we can do driver
+	 * pixmaps, this will be a nasty hack!
+	 */
+
+	fb = drmModeGetFB(nouveau_device(pNv->dev)->fd, src_id);
+	if (!fb) {
+		ErrorF("src fb\n");
+		return;
+	}
+
+	req.handle = fb->handle;
+	ret = drmCommandWriteRead(nouveau_device(pNv->dev)->fd,
+				  DRM_NOUVEAU_GEM_MMAP, &req, sizeof(req));
+	if (ret) {
+		ErrorF("src bo map: %d\n", ret);
+		drmFree(fb);
+		return;
+	}
+	src = (void *)req.vaddr;
+	
+	nouveau_bo_map(pNv->FB, NOUVEAU_BO_WR);
+	dst = pNv->FB->map;
+	dst += (y * fb->pitch) + (x * (fb->bpp >> 3));
+
+	h = fb->height;
+	while (h--) {
+		memcpy(dst, src, fb->width * (fb->bpp >> 3));
+		src += fb->pitch;
+		dst += pScrn->displayWidth * (pScrn->bitsPerPixel / 8);
+	}
+
+	nouveau_bo_unmap(pNv->FB);
+	drmFree(fb);
+}
+
+static void
 drmmode_fb_copy(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int dst_id, int src_id,
 		int x, int y)
 {
@@ -194,6 +239,11 @@ drmmode_fb_copy(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int dst_id, int src_id,
 	PixmapPtr pspix, pdpix;
 	int w, h;
 
+	if (!pNv->exa_driver_pixmaps) {
+		drmmode_fb_copy_sw(pScrn, drmmode, dst_id, src_id, x, y);
+		return;
+	}
+
 	pspix = drmmode_fb_pixmap(pScrn, src_id, NULL, NULL);
 	if (!pspix)
 		return;
@@ -292,8 +342,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 	if (drmmode_crtc->rotate_fb_id)
 		fb_id = drmmode_crtc->rotate_fb_id;
 	else
-	if (fb_id != drmmode_crtc->mode_crtc->buffer_id &&
-	    pNv->exa_driver_pixmaps) {
+	if (fb_id != drmmode_crtc->mode_crtc->buffer_id) {
 		drmmode_fb_copy(pScrn, drmmode, fb_id,
 				drmmode_crtc->mode_crtc->buffer_id, x, y);
 	}
-- 
1.6.2.2





More information about the scm-commits mailing list