[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