[Intel-gfx] [PATCH xf86-video-intel] sna: Use correct struct sna in sna_mode_wakeup

Thomas Preston thomas.preston at codethink.co.uk
Tue Jan 21 10:28:58 UTC 2020


When deciding if we should defer_vblanks we should reference the event's
struct sna, rather than the caller's struct sna. In order to do this, we
must grab a new struct sna for each event in the buffer. Move this logic
out of `case DRM_EVENT_FLIP_COMPLETE` and create a new variable
sna_event, so that it is clear which struct sna we are referring to.
Also add another ZaphodHead comment by the struct sna argument, in case
someone misses the comment below.

Fixes issue #184 with ZaphodHead and TearFree, introduced in this commit:

	12db28ab sna: Reorder vblank/flip event handling to avoid TearFree recursion

Signed-off-by: Thomas Preston <thomas.preston at codethink.co.uk>
---
 src/sna/sna_display.c | 48 +++++++++++++++++++++++--------------------
 1 file changed, 26 insertions(+), 22 deletions(-)

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 874292bc..b40a6c4a 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -9711,9 +9711,12 @@ fixup_flip:
 	RegionEmpty(region);
 }
 
+/* In the case of ZaphodHead, there is only one event queue in the main
+ * struct sna. Only refer to this struct sna when dealing with the event queue.
+ * Otherwise, extract the struct sna from the event user_data.
+ */
 int sna_mode_wakeup(struct sna *sna)
 {
-	bool defer_vblanks = sna->mode.flip_active && sna->mode.shadow_enabled;
 	char buffer[1024];
 	int len, i;
 	int ret = 0;
@@ -9733,34 +9736,35 @@ again:
 	if (len < (int)sizeof(struct drm_event))
 		goto done;
 
-	/* Note that we cannot rely on the passed in struct sna matching
-	 * the struct sna used for the vblank event (in case it was submitted
-	 * by a different ZaphodHead). When processing the event, we must
-	 * ensure that we only use the pointer passed along with the event.
-	 */
-
 	DBG(("%s: len=%d\n", __FUNCTION__, len));
 
 	i = 0;
 	while (i < len) {
 		struct drm_event *e = (struct drm_event *)&buffer[i];
+
+		/* Note that we cannot rely on the passed in struct sna
+		 * matching the struct sna used for the vblank event (in case
+		 * it was submitted by a different ZaphodHead). When processing
+		 * the event, we must ensure that we only use the pointer
+		 * passed along with the event.
+		 */
+		struct drm_event_vblank *vbl = (struct drm_event_vblank *)e;
+		struct sna_crtc *crtc = (void *)(uintptr_t)vbl->user_data;
+		struct sna *sna_event = to_sna(crtc->base->scrn);
+
 		switch (e->type) {
 		case DRM_EVENT_VBLANK:
-			if (defer_vblanks)
+			if (sna_event->mode.flip_active && sna_event->mode.shadow_enabled)
 				defer_event(sna, e);
-			else if (((uintptr_t)((struct drm_event_vblank *)e)->user_data) & 2)
-				sna_present_vblank_handler((struct drm_event_vblank *)e);
+			else if (((uintptr_t)crtc) & 2)
+				sna_present_vblank_handler(vbl);
 			else
-				sna_dri2_vblank_handler((struct drm_event_vblank *)e);
+				sna_dri2_vblank_handler(vbl);
 			break;
 		case DRM_EVENT_FLIP_COMPLETE:
 			{
-				struct drm_event_vblank *vbl = (struct drm_event_vblank *)e;
-				struct sna_crtc *crtc = (void *)(uintptr_t)vbl->user_data;
 				uint64_t msc;
 
-				/* Beware Zaphod! */
-				sna = to_sna(crtc->base->scrn);
 
 				if (msc64(crtc, vbl->sequence, &msc)) {
 					DBG(("%s: recording last swap on pipe=%d, frame %d [%08llx], time %d.%06d\n",
@@ -9784,26 +9788,26 @@ again:
 					assert(crtc->bo->refcnt >= crtc->bo->active_scanout);
 
 					crtc->bo->active_scanout--;
-					kgem_bo_destroy(&sna->kgem, crtc->bo);
+					kgem_bo_destroy(&sna_event->kgem, crtc->bo);
 
 					if (crtc->shadow_bo) {
-						kgem_bo_destroy(&sna->kgem, crtc->shadow_bo);
+						kgem_bo_destroy(&sna_event->kgem, crtc->shadow_bo);
 						crtc->shadow_bo = NULL;
 					}
 
 					crtc->bo = crtc->flip_bo;
 					crtc->flip_bo = NULL;
 
-					assert_crtc_fb(sna, crtc);
+					assert_crtc_fb(sna_event, crtc);
 				} else {
 					crtc->flip_bo->active_scanout--;
-					kgem_bo_destroy(&sna->kgem, crtc->flip_bo);
+					kgem_bo_destroy(&sna_event->kgem, crtc->flip_bo);
 					crtc->flip_bo = NULL;
 				}
 
-				DBG(("%s: flip complete, pending? %d\n", __FUNCTION__, sna->mode.flip_active));
-				assert(sna->mode.flip_active);
-				if (--sna->mode.flip_active == 0) {
+				DBG(("%s: flip complete, pending? %d\n", __FUNCTION__, sna_event->mode.flip_active));
+				assert(sna_event->mode.flip_active);
+				if (--sna_event->mode.flip_active == 0) {
 					assert(crtc->flip_handler);
 					crtc->flip_handler(vbl, crtc->flip_data);
 				}
-- 
2.24.1



More information about the Intel-gfx mailing list