Blame SOURCES/nouveau-1.0.13-fix-pageflipping-with-atomic.patch

2ae2ca
From 924083938c8f209d8f6ff472caf8692a644f7e78 Mon Sep 17 00:00:00 2001
2ae2ca
From: Lyude <lyude@redhat.com>
2ae2ca
Date: Fri, 3 Mar 2017 18:27:42 -0500
2ae2ca
Subject: [PATCH] Consider CRTCs disabled when DPMS is off
2ae2ca
2ae2ca
It turns out there's a difference in X between a CRTC being "disabled"
2ae2ca
and simply having it's DPMS turned off. This is problematic though,
2ae2ca
because if DPMS is turned off you can't really use the CRTC as a normal
2ae2ca
CRTC anyway since page flipping and vblanks will be non-functional. As a
2ae2ca
result, we've been considering DPMS-on CRTCs as enabled and attempt to
2ae2ca
perform pageflips, vblank waits, etc. on them which inevitably fails. and
2ae2ca
usually breaks the display the first time any of the CRTCs have their
2ae2ca
DPMS turned on.
2ae2ca
2ae2ca
This was a problem that didn't really show itself until kernel 4.10 when
2ae2ca
atomic modesetting was added which caused nouveau to stop trying to
2ae2ca
fulfill pageflips and vblank waits on disabled CRTCs. I'm not sure how
2ae2ca
pageflipping disabled CRTCs ever worked in the first place, but since
2ae2ca
not doing so is the proper behavior anyway I haven't investigated any
2ae2ca
further.
2ae2ca
2ae2ca
So, copy the ms_crtc_on() function from the modesetting driver and add
2ae2ca
it here as drmmode_crtc_on(), then use that in all of the places where
2ae2ca
we should be checking for both DPMS off and disabled CRTCs.
2ae2ca
2ae2ca
This fixes issues with the X ceasing to function (usually) after the
2ae2ca
first time a CRTC has it's DPMS turned on. Reproduction recipe:
2ae2ca
2ae2ca
- Load up gnome-shell on a machine
2ae2ca
- Wait for the display to timeout from inactivity and turn itself off
2ae2ca
- Shake the cursor or press something on the keyboard. Chances are the
2ae2ca
  monitor will come back on, but the display remains black until the
2ae2ca
  next time the X server is restarted.
2ae2ca
2ae2ca
Signed-off-by: Lyude <lyude@redhat.com>
2ae2ca
Reviewed-by: Adam Jackson <ajax@redhat.com>
2ae2ca
---
2ae2ca
 src/drmmode_display.c | 14 ++++++++++++--
2ae2ca
 src/nouveau_dri2.c    | 14 +++++++++-----
2ae2ca
 src/nouveau_present.c |  6 +++---
2ae2ca
 src/nouveau_xv.c      |  2 +-
2ae2ca
 src/nv_proto.h        |  1 +
2ae2ca
 5 files changed, 26 insertions(+), 11 deletions(-)
2ae2ca
2ae2ca
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
2ae2ca
index b6c9bb9..dd9fa27 100644
2ae2ca
--- a/src/drmmode_display.c
2ae2ca
+++ b/src/drmmode_display.c
2ae2ca
@@ -65,6 +65,7 @@ typedef struct {
2ae2ca
     uint32_t rotate_fb_id;
2ae2ca
     Bool cursor_visible;
2ae2ca
     int scanout_pixmap_x;
2ae2ca
+    int dpms_mode;
2ae2ca
 } drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
2ae2ca
 
2ae2ca
 typedef struct {
2ae2ca
@@ -114,6 +115,14 @@ drmmode_crtc(xf86CrtcPtr crtc)
2ae2ca
 	return drmmode_crtc->mode_crtc->crtc_id;
2ae2ca
 }
2ae2ca
 
2ae2ca
+Bool
2ae2ca
+drmmode_crtc_on(xf86CrtcPtr crtc)
2ae2ca
+{
2ae2ca
+    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
2ae2ca
+
2ae2ca
+    return crtc->enabled && drmmode_crtc->dpms_mode == DPMSModeOn;
2ae2ca
+}
2ae2ca
+
2ae2ca
 int
2ae2ca
 drmmode_head(xf86CrtcPtr crtc)
2ae2ca
 {
2ae2ca
@@ -313,9 +322,10 @@ drmmode_ConvertToKMode(ScrnInfoPtr scrn, drmModeModeInfo *kmode,
2ae2ca
 }
2ae2ca
 
2ae2ca
 static void
2ae2ca
-drmmode_crtc_dpms(xf86CrtcPtr drmmode_crtc, int mode)
2ae2ca
+drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
2ae2ca
 {
2ae2ca
-
2ae2ca
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
2ae2ca
+	drmmode_crtc->dpms_mode = mode;
2ae2ca
 }
2ae2ca
 
2ae2ca
 void
2ae2ca
diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c
2ae2ca
index 81ee9be..cbb7b2a 100644
2ae2ca
--- a/src/nouveau_dri2.c
2ae2ca
+++ b/src/nouveau_dri2.c
2ae2ca
@@ -279,23 +279,27 @@ can_exchange(DrawablePtr draw, PixmapPtr dst_pix, PixmapPtr src_pix)
2ae2ca
 	ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen);
2ae2ca
 	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
2ae2ca
 	NVPtr pNv = NVPTR(scrn);
2ae2ca
-	int i;
2ae2ca
+	int i, active_crtc_count = 0;
2ae2ca
 
2ae2ca
 	if (!xf86_config->num_crtc)
2ae2ca
 		return FALSE;
2ae2ca
 
2ae2ca
 	for (i = 0; i < xf86_config->num_crtc; i++) {
2ae2ca
 		xf86CrtcPtr crtc = xf86_config->crtc[i];
2ae2ca
-		if (crtc->enabled && crtc->rotatedData)
2ae2ca
-			return FALSE;
2ae2ca
+		if (drmmode_crtc_on(crtc)) {
2ae2ca
+			if (crtc->rotatedData)
2ae2ca
+				return FALSE;
2ae2ca
 
2ae2ca
+			active_crtc_count++;
2ae2ca
+		}
2ae2ca
 	}
2ae2ca
 
2ae2ca
 	return ((DRI2CanFlip(draw) && pNv->has_pageflip)) &&
2ae2ca
 		dst_pix->drawable.width == src_pix->drawable.width &&
2ae2ca
 		dst_pix->drawable.height == src_pix->drawable.height &&
2ae2ca
 		dst_pix->drawable.bitsPerPixel == src_pix->drawable.bitsPerPixel &&
2ae2ca
-		dst_pix->devKind == src_pix->devKind;
2ae2ca
+		dst_pix->devKind == src_pix->devKind &&
2ae2ca
+		active_crtc_count;
2ae2ca
 }
2ae2ca
 
2ae2ca
 static Bool
2ae2ca
@@ -475,7 +479,7 @@ dri2_page_flip(DrawablePtr draw, PixmapPtr back, void *priv,
2ae2ca
 		int head = drmmode_crtc(config->crtc[i]);
2ae2ca
 		void *token;
2ae2ca
 
2ae2ca
-		if (!config->crtc[i]->enabled)
2ae2ca
+		if (!drmmode_crtc_on(config->crtc[i]))
2ae2ca
 			continue;
2ae2ca
 
2ae2ca
 		flipdata->flip_count++;
2ae2ca
diff --git a/src/nouveau_present.c b/src/nouveau_present.c
2ae2ca
index 482ac6e..ebd5fcf 100644
2ae2ca
--- a/src/nouveau_present.c
2ae2ca
+++ b/src/nouveau_present.c
2ae2ca
@@ -152,7 +152,7 @@ nouveau_present_flip_check(RRCrtcPtr rrcrtc, WindowPtr window,
2ae2ca
 	ScrnInfoPtr scrn = xf86ScreenToScrn(window->drawable.pScreen);
2ae2ca
 	xf86CrtcPtr crtc = rrcrtc->devPrivate;
2ae2ca
 
2ae2ca
-	if (!scrn->vtSema || !crtc->enabled)
2ae2ca
+	if (!scrn->vtSema || !drmmode_crtc_on(crtc))
2ae2ca
 		return FALSE;
2ae2ca
 
2ae2ca
 	return TRUE;
2ae2ca
@@ -199,7 +199,7 @@ nouveau_present_flip_exec(ScrnInfoPtr scrn, uint64_t event_id, int sync,
2ae2ca
 			flip->msc = target_msc;
2ae2ca
 
2ae2ca
 			for (i = 0; i < config->num_crtc; i++) {
2ae2ca
-				if (config->crtc[i]->enabled)
2ae2ca
+				if (drmmode_crtc_on(config->crtc[i]))
2ae2ca
 					last = i;
2ae2ca
 			}
2ae2ca
 
2ae2ca
@@ -208,7 +208,7 @@ nouveau_present_flip_exec(ScrnInfoPtr scrn, uint64_t event_id, int sync,
2ae2ca
 				int crtc = drmmode_crtc(config->crtc[i]);
2ae2ca
 				void *user = NULL;
2ae2ca
 
2ae2ca
-				if (!config->crtc[i]->enabled)
2ae2ca
+				if (!drmmode_crtc_on(config->crtc[i]))
2ae2ca
 					continue;
2ae2ca
 
2ae2ca
 				if (token && ((crtc == sync) || (i == last))) {
2ae2ca
diff --git a/src/nouveau_xv.c b/src/nouveau_xv.c
2ae2ca
index 716b18d..4b939f7 100644
2ae2ca
--- a/src/nouveau_xv.c
2ae2ca
+++ b/src/nouveau_xv.c
2ae2ca
@@ -299,7 +299,7 @@ nv_window_belongs_to_crtc(ScrnInfoPtr pScrn, int x, int y, int w, int h)
2ae2ca
 	for (i = 0; i < xf86_config->num_crtc; i++) {
2ae2ca
 		xf86CrtcPtr crtc = xf86_config->crtc[i];
2ae2ca
 
2ae2ca
-		if (!crtc->enabled)
2ae2ca
+		if (!drmmode_crtc_on(crtc))
2ae2ca
 			continue;
2ae2ca
 
2ae2ca
 		if ((x < (crtc->x + crtc->mode.HDisplay)) &&
2ae2ca
diff --git a/src/nv_proto.h b/src/nv_proto.h
2ae2ca
index 122ede5..4a57406 100644
2ae2ca
--- a/src/nv_proto.h
2ae2ca
+++ b/src/nv_proto.h
2ae2ca
@@ -13,6 +13,7 @@ void drmmode_screen_init(ScreenPtr pScreen);
2ae2ca
 void drmmode_screen_fini(ScreenPtr pScreen);
2ae2ca
 
2ae2ca
 int  drmmode_crtc(xf86CrtcPtr crtc);
2ae2ca
+Bool drmmode_crtc_on(xf86CrtcPtr crtc);
2ae2ca
 int  drmmode_head(xf86CrtcPtr crtc);
2ae2ca
 void drmmode_swap(ScrnInfoPtr, uint32_t, uint32_t *);
2ae2ca
 
2ae2ca
-- 
2ae2ca
2.9.3
2ae2ca