[PATCH xf86-video-ati 2/2] Deal with modesets and page flips crossing on a CRTC
Alex Deucher
alexdeucher at gmail.com
Mon Feb 29 15:12:31 UTC 2016
On Mon, Feb 29, 2016 at 4:58 AM, Michel Dänzer <michel at daenzer.net> wrote:
> From: Michel Dänzer <michel.daenzer at 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.daenzer at amd.com>
For the series:
Reviewed-by: Alex Deucher <alexander.deucher at 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 at lists.x.org
> https://lists.x.org/mailman/listinfo/xorg-driver-ati
More information about the xorg-driver-ati
mailing list