From: Michel Dänzer <michel.daen...@amd.com>

If we set a mode while a flip is pending, the kernel driver may program
the flip to the hardware after the modeset. If that happens, the hardware
will display the BO from the flip, whereas we will assume it displays the
BO from the modeset. In other words, the display will most likely freeze,
at least until another modeset.

Prevent this condition by waiting for a pending flip to finish before
setting a mode.

Fixes display freezing when setting rotation or a transform with
TearFree enabled.

Signed-off-by: Michel Dänzer <michel.daen...@amd.com>
---
 src/drmmode_display.c | 13 +++++++++++++
 src/drmmode_display.h |  6 +++++-
 src/radeon_kms.c      |  2 ++
 3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 24430a2..f1ca02c 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -760,6 +760,12 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr 
mode,
                                radeon_bo_wait(drmmode_crtc->scanout[0].bo);
                        }
                }
+
+               /* Wait for any pending flip to finish */
+               do {} while (drmmode_crtc->flip_pending &&
+                            drmHandleEvent(drmmode->fd,
+                                           &drmmode->event_context) > 0);
+
                if (drmModeSetCrtc(drmmode->fd,
                                   drmmode_crtc->mode_crtc->crtc_id,
                                   fb_id, x, y, output_ids,
@@ -2024,6 +2030,7 @@ static const xf86CrtcConfigFuncsRec 
drmmode_xf86crtc_config_funcs = {
 static void
 drmmode_flip_abort(xf86CrtcPtr crtc, void *event_data)
 {
+       drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
        drmmode_flipdata_ptr flipdata = event_data;
 
        if (--flipdata->flip_count == 0) {
@@ -2032,11 +2039,14 @@ drmmode_flip_abort(xf86CrtcPtr crtc, void *event_data)
                flipdata->abort(crtc, flipdata->event_data);
                free(flipdata);
        }
+
+       drmmode_crtc->flip_pending = FALSE;
 }
 
 static void
 drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void 
*event_data)
 {
+       drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
        RADEONInfoPtr info = RADEONPTR(crtc->scrn);
        drmmode_flipdata_ptr flipdata = event_data;
 
@@ -2059,6 +2069,8 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, 
uint64_t usec, void *even
 
                free(flipdata);
        }
+
+       drmmode_crtc->flip_pending = FALSE;
 }
 
 
@@ -2582,6 +2594,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr 
client,
                                   "flip queue failed: %s\n", strerror(errno));
                        goto error;
                }
+               drmmode_crtc->flip_pending = TRUE;
                drm_queue = NULL;
        }
 
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 99c6c91..c295735 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -95,8 +95,12 @@ typedef struct {
     uint16_t lut_r[256], lut_g[256], lut_b[256];
     int prime_pixmap_x;
 
-    /* Modeset needed for DPMS on */
+    /* Modeset needed (for DPMS on or after a page flip crossing with a
+     * modeset)
+     */
     Bool need_modeset;
+    /* A flip is pending for this CRTC */
+    Bool flip_pending;
 } drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
 
 typedef struct {
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 3768983..44fe71e 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -483,6 +483,7 @@ radeon_scanout_flip_abort(xf86CrtcPtr crtc, void 
*event_data)
     drmmode_crtc_private_ptr drmmode_crtc = event_data;
 
     drmmode_crtc->scanout_update_pending = FALSE;
+    drmmode_crtc->flip_pending = FALSE;
 }
 
 static void
@@ -523,6 +524,7 @@ radeon_scanout_flip(ScreenPtr pScreen, RADEONInfoPtr info,
 
     drmmode_crtc->scanout_id = scanout_id;
     drmmode_crtc->scanout_update_pending = TRUE;
+    drmmode_crtc->flip_pending = TRUE;
 }
 
 static void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
-- 
2.7.0

_______________________________________________
xorg-driver-ati mailing list
xorg-driver-ati@lists.x.org
https://lists.x.org/mailman/listinfo/xorg-driver-ati

Reply via email to