[PATCH] Don't attempt a DRI2/Present page flip while the other one is flipping

Alex Deucher alexdeucher at gmail.com
Thu Jun 11 07:12:30 PDT 2015


On Thu, Jun 11, 2015 at 5:59 AM, Michel Dänzer <michel at daenzer.net> wrote:
> From: Michel Dänzer <michel.daenzer at amd.com>
>
> Fixes corrupted display and hangs when switching between DRI2 and DRI3
> fullscreen apps, e.g. a compositor using DRI3 and a fullscreen app using
> DRI2 or vice versa.
>
> Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>

Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

> ---
>  src/drmmode_display.h |  3 +++
>  src/radeon_dri2.c     | 23 +++++++++++++++++------
>  src/radeon_present.c  | 17 ++++++++++++++++-
>  3 files changed, 36 insertions(+), 7 deletions(-)
>
> diff --git a/src/drmmode_display.h b/src/drmmode_display.h
> index 2fdd3e0..ca42c7d 100644
> --- a/src/drmmode_display.h
> +++ b/src/drmmode_display.h
> @@ -54,6 +54,9 @@ typedef struct {
>    int count_crtcs;
>
>    Bool delete_dp_12_displays;
> +
> +  Bool dri2_flipping;
> +  Bool present_flipping;
>  } drmmode_rec, *drmmode_ptr;
>
>  typedef struct {
> diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
> index a1f0145..7587a0c 100644
> --- a/src/radeon_dri2.c
> +++ b/src/radeon_dri2.c
> @@ -584,6 +584,7 @@ static void
>  radeon_dri2_flip_event_handler(ScrnInfoPtr scrn, uint32_t frame, uint64_t usec,
>                                void *event_data)
>  {
> +    RADEONInfoPtr info = RADEONPTR(scrn);
>      DRI2FrameEventPtr flip = event_data;
>      unsigned tv_sec, tv_usec;
>      DrawablePtr drawable;
> @@ -627,6 +628,7 @@ radeon_dri2_flip_event_handler(ScrnInfoPtr scrn, uint32_t frame, uint64_t usec,
>         DRI2SwapComplete(flip->client, drawable, frame, tv_sec, tv_usec,
>                          DRI2_FLIP_COMPLETE, flip->event_complete,
>                          flip->event_data);
> +       info->drmmode.dri2_flipping = FALSE;
>         break;
>      default:
>         xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%s: unknown vblank event received\n", __func__);
> @@ -644,6 +646,7 @@ radeon_dri2_schedule_flip(ScrnInfoPtr scrn, ClientPtr client,
>                           DRI2BufferPtr back, DRI2SwapEventPtr func,
>                           void *data, unsigned int target_msc)
>  {
> +    RADEONInfoPtr info = RADEONPTR(scrn);
>      struct dri2_buffer_priv *back_priv;
>      struct radeon_bo *bo;
>      DRI2FrameEventPtr flip_info;
> @@ -670,11 +673,16 @@ radeon_dri2_schedule_flip(ScrnInfoPtr scrn, ClientPtr client,
>      back_priv = back->driverPrivate;
>      bo = radeon_get_pixmap_bo(back_priv->pixmap);
>
> -    return radeon_do_pageflip(scrn, client, bo->handle,
> -                             RADEON_DRM_QUEUE_ID_DEFAULT, flip_info,
> -                             ref_crtc_hw_id,
> -                             radeon_dri2_flip_event_handler,
> -                             radeon_dri2_flip_event_abort);
> +    if (radeon_do_pageflip(scrn, client, bo->handle,
> +                          RADEON_DRM_QUEUE_ID_DEFAULT, flip_info,
> +                          ref_crtc_hw_id,
> +                          radeon_dri2_flip_event_handler,
> +                          radeon_dri2_flip_event_abort)) {
> +       info->drmmode.dri2_flipping = TRUE;
> +       return TRUE;
> +    }
> +
> +    return FALSE;
>  }
>
>  static Bool
> @@ -742,8 +750,11 @@ static Bool
>  can_flip(ScrnInfoPtr pScrn, DrawablePtr draw,
>          DRI2BufferPtr front, DRI2BufferPtr back)
>  {
> +    RADEONInfoPtr info = RADEONPTR(pScrn);
> +
>      return draw->type == DRAWABLE_WINDOW &&
> -          RADEONPTR(pScrn)->allowPageFlip &&
> +          info->allowPageFlip &&
> +          !info->drmmode.present_flipping &&
>            pScrn->vtSema &&
>            DRI2CanFlip(draw) &&
>            can_exchange(pScrn, draw, front, back);
> diff --git a/src/radeon_present.c b/src/radeon_present.c
> index 2626044..c48df13 100644
> --- a/src/radeon_present.c
> +++ b/src/radeon_present.c
> @@ -50,6 +50,7 @@
>
>  struct radeon_present_vblank_event {
>      uint64_t event_id;
> +    xf86CrtcPtr crtc;
>  };
>
>  static uint32_t crtc_select(int crtc_id)
> @@ -238,6 +239,9 @@ radeon_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap,
>      if (!sync_flip)
>         return FALSE;
>
> +    if (info->drmmode.dri2_flipping)
> +       return FALSE;
> +
>      /* The kernel driver doesn't handle flipping between BOs with different
>       * tiling parameters correctly yet
>       */
> @@ -266,8 +270,12 @@ radeon_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap,
>  static void
>  radeon_present_flip_event(ScrnInfoPtr scrn, uint32_t msc, uint64_t ust, void *pageflip_data)
>  {
> +    RADEONInfoPtr info = RADEONPTR(scrn);
>      struct radeon_present_vblank_event *event = pageflip_data;
>
> +    if (!event->crtc)
> +       info->drmmode.present_flipping = FALSE;
> +
>      present_event_notify(event->event_id, ust, msc);
>      free(event);
>  }
> @@ -293,6 +301,7 @@ radeon_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc,
>  {
>      ScreenPtr screen = crtc->pScreen;
>      ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
> +    RADEONInfoPtr info = RADEONPTR(scrn);
>      struct radeon_present_vblank_event *event;
>      xf86CrtcPtr xf86_crtc = crtc->devPrivate;
>      int crtc_id = xf86_crtc ? drmmode_get_crtc_id(xf86_crtc) : -1;
> @@ -310,6 +319,7 @@ radeon_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc,
>         return FALSE;
>
>      event->event_id = event_id;
> +    event->crtc = xf86_crtc;
>
>      ret = radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, handle,
>                              event_id, event, crtc_id,
> @@ -317,6 +327,8 @@ radeon_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc,
>                              radeon_present_flip_abort);
>      if (!ret)
>         xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present flip failed\n");
> +    else
> +       info->drmmode.present_flipping = TRUE;
>
>      return ret;
>  }
> @@ -328,6 +340,7 @@ static void
>  radeon_present_unflip(ScreenPtr screen, uint64_t event_id)
>  {
>      ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
> +    RADEONInfoPtr info = RADEONPTR(scrn);
>      struct radeon_present_vblank_event *event;
>      PixmapPtr pixmap = screen->GetScreenPixmap(screen);
>      uint32_t handle;
> @@ -348,8 +361,10 @@ radeon_present_unflip(ScreenPtr screen, uint64_t event_id)
>      ret = radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, handle,
>                              event_id, event, -1, radeon_present_flip_event,
>                              radeon_present_flip_abort);
> -    if (!ret)
> +    if (!ret) {
>         xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present unflip failed\n");
> +       info->drmmode.present_flipping = FALSE;
> +    }
>  }
>
>  static present_screen_info_rec radeon_present_screen_info = {
> --
> 2.1.4
>
> _______________________________________________
> xorg-driver-ati mailing list
> xorg-driver-ati at lists.x.org
> http://lists.x.org/mailman/listinfo/xorg-driver-ati


More information about the xorg-driver-ati mailing list