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 <[email protected]>
---
 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

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to