[xf86-video-nouveau] dri2, present: move in pixmap before getting addresses

Submitted by Ilia Mirkin on Oct. 13, 2019, 12:27 a.m.

Details

Message ID 20191013002717.3678-1-imirkin@alum.mit.edu
State New
Headers show
Series "dri2, present: move in pixmap before getting addresses" ( rev: 1 ) in Nouveau

Not browsing as part of any series.

Commit Message

Ilia Mirkin Oct. 13, 2019, 12:27 a.m.
First of all, we were not forcing the pixmap to be moved in before
attempting to present it. Secondly, in certain configurations, we avoid
ever backing pixmaps with vram (in GPUs with 32MB of VRAM or less).

This fixes the observed cases where we ended up assuming that a bo was
backing a pixmap without doing the explicit move-in.

Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
---

This fixes some crashes on a NV5 with 32MB VRAM + xfwm4 --vblank=present,
however the failure modes (e.g. pixmap doesn't have backing) can happen
anywhere I believe, just much less likely.

 src/nouveau_dri2.c    | 18 +++++++++++++++---
 src/nouveau_present.c | 15 ++++++++++++++-
 2 files changed, 29 insertions(+), 4 deletions(-)

Patch hide | download patch | download mbox

diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c
index ce0a573..8c29eca 100644
--- a/src/nouveau_dri2.c
+++ b/src/nouveau_dri2.c
@@ -248,9 +248,13 @@  static uint64_t dri2_sequence;
 static Bool
 update_front(DrawablePtr draw, DRI2BufferPtr front)
 {
-	int r;
-	PixmapPtr pixmap;
+	ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen);
+	NVPtr pNv = NVPTR(scrn);
 	struct nouveau_dri2_buffer *nvbuf = nouveau_dri2_buffer(front);
+	struct nouveau_bo *pixmap_bo;
+
+	PixmapPtr pixmap;
+	int r;
 
 	if (draw->type == DRAWABLE_PIXMAP)
 		pixmap = (PixmapPtr)draw;
@@ -259,8 +263,16 @@  update_front(DrawablePtr draw, DRI2BufferPtr front)
 
 	pixmap->refcnt++;
 
+	pNv->exa_force_cp = TRUE;
 	exaMoveInPixmap(pixmap);
-	r = nouveau_bo_name_get(nouveau_pixmap_bo(pixmap), &front->name);
+	pNv->exa_force_cp = FALSE;
+	pixmap_bo = nouveau_pixmap_bo(pixmap);
+
+	if (!pixmap_bo)
+		r = -1;
+	else
+		r = nouveau_bo_name_get(pixmap_bo, &front->name);
+
 	if (r) {
 		(*draw->pScreen->DestroyPixmap)(pixmap);
 		return FALSE;
diff --git a/src/nouveau_present.c b/src/nouveau_present.c
index 936475e..8167fd8 100644
--- a/src/nouveau_present.c
+++ b/src/nouveau_present.c
@@ -147,12 +147,25 @@  nouveau_present_flip_check(RRCrtcPtr rrcrtc, WindowPtr window,
 			   PixmapPtr pixmap, Bool sync_flip)
 {
 	ScrnInfoPtr scrn = xf86ScreenToScrn(window->drawable.pScreen);
+	NVPtr pNv = NVPTR(scrn);
 	xf86CrtcPtr crtc = rrcrtc->devPrivate;
+	struct nouveau_pixmap *priv = nouveau_pixmap(pixmap);
 
 	if (!scrn->vtSema || !drmmode_crtc_on(crtc) || crtc->rotatedData)
 		return FALSE;
 
-	return TRUE;
+	if (!priv) {
+		/* The pixmap may not have had backing for low-memory GPUs, or
+		 * if we ran out of VRAM. Make sure it's properly backed for
+		 * flipping.
+		 */
+		pNv->exa_force_cp = TRUE;
+		exaMoveInPixmap(pixmap);
+		pNv->exa_force_cp = FALSE;
+		priv = nouveau_pixmap(pixmap);
+	}
+
+	return priv ? TRUE : FALSE;
 }
 
 static void