[PATCH 1/3] present: Fall back to modeset for unflip operation

Alex Deucher alexdeucher at gmail.com
Wed Jul 8 10:25:38 PDT 2015


On Wed, Jul 8, 2015 at 5:25 AM, Michel Dänzer <michel at daenzer.net> wrote:
> From: Michel Dänzer <michel.daenzer at amd.com>
>
> It's not always possible to use the page flip ioctl for this, e.g.
> during DPMS off. We were previously just skipping the unflip in that
> case, which could result in hangs when setting DPMS off while a
> fullscreen Present app is running, e.g. at the GNOME3 lock screen.
>
> Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>

Having to do a full modeset is pretty ugly, but I don't have a better
solution.  Series is:
Reviewed-by: Alex Deucher <alexander.deucher at amd.com>


> ---
>  src/drmmode_display.c | 19 +++++++++++++++----
>  src/drmmode_display.h |  3 +++
>  src/radeon_present.c  | 46 ++++++++++++++++++++++++++++++++++------------
>  3 files changed, 52 insertions(+), 16 deletions(-)
>
> diff --git a/src/drmmode_display.c b/src/drmmode_display.c
> index 8483909..ad2f48b 100644
> --- a/src/drmmode_display.c
> +++ b/src/drmmode_display.c
> @@ -769,6 +769,9 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
>
>                 if (crtc->scrn->pScreen)
>                         xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen);
> +
> +               drmmode_crtc->need_modeset = FALSE;
> +
>                 /* go through all the outputs and force DPMS them back on? */
>                 for (i = 0; i < xf86_config->num_output; i++) {
>                         xf86OutputPtr output = xf86_config->output[i];
> @@ -1153,20 +1156,28 @@ static void
>  drmmode_output_dpms(xf86OutputPtr output, int mode)
>  {
>         drmmode_output_private_ptr drmmode_output = output->driver_private;
> +       xf86CrtcPtr crtc = output->crtc;
>         drmModeConnectorPtr koutput = drmmode_output->mode_output;
>         drmmode_ptr drmmode = drmmode_output->drmmode;
>
>         if (!koutput)
>                 return;
>
> -       if (mode != DPMSModeOn && output->crtc)
> -               drmmode_do_crtc_dpms(output->crtc, mode);
> +       if (mode != DPMSModeOn && crtc)
> +               drmmode_do_crtc_dpms(crtc, mode);
>
>         drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id,
>                                     drmmode_output->dpms_enum_id, mode);
>
> -       if (mode == DPMSModeOn && output->crtc)
> -               drmmode_do_crtc_dpms(output->crtc, mode);
> +       if (mode == DPMSModeOn && crtc) {
> +           drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
> +
> +           if (drmmode_crtc->need_modeset)
> +               drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, crtc->x,
> +                                      crtc->y);
> +           else
> +               drmmode_do_crtc_dpms(crtc, mode);
> +       }
>  }
>
>
> diff --git a/src/drmmode_display.h b/src/drmmode_display.h
> index ca42c7d..ab6c590 100644
> --- a/src/drmmode_display.h
> +++ b/src/drmmode_display.h
> @@ -99,6 +99,9 @@ typedef struct {
>      uint32_t interpolated_vblanks;
>      uint16_t lut_r[256], lut_g[256], lut_b[256];
>      int prime_pixmap_x;
> +
> +    /* Modeset needed for DPMS on */
> +    Bool need_modeset;
>  } drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
>
>  typedef struct {
> diff --git a/src/radeon_present.c b/src/radeon_present.c
> index c48df13..bc1053e 100644
> --- a/src/radeon_present.c
> +++ b/src/radeon_present.c
> @@ -341,30 +341,52 @@ radeon_present_unflip(ScreenPtr screen, uint64_t event_id)
>  {
>      ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
>      RADEONInfoPtr info = RADEONPTR(scrn);
> +    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
>      struct radeon_present_vblank_event *event;
>      PixmapPtr pixmap = screen->GetScreenPixmap(screen);
>      uint32_t handle;
> -    Bool ret;
> +    int i;
>
>      if (!radeon_present_check_flip(NULL, screen->root, pixmap, TRUE))
> -       return;
> +       goto modeset;
>
> -    if (!radeon_get_pixmap_handle(pixmap, &handle))
> -       return;
> +    if (!radeon_get_pixmap_handle(pixmap, &handle)) {
> +       ErrorF("%s: radeon_get_pixmap_handle failed, display might freeze\n",
> +              __func__);
> +       goto modeset;
> +    }
>
>      event = calloc(1, sizeof(struct radeon_present_vblank_event));
> -    if (!event)
> -       return;
> +    if (!event) {
> +       ErrorF("%s: calloc failed, display might freeze\n", __func__);
> +       goto modeset;
> +    }
>
>      event->event_id = 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) {
> -       xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present unflip failed\n");
> -       info->drmmode.present_flipping = FALSE;
> +    if (radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, handle,
> +                          event_id, event, -1, radeon_present_flip_event,
> +                          radeon_present_flip_abort))
> +       return;
> +
> +modeset:
> +    for (i = 0; i < config->num_crtc; i++) {
> +       xf86CrtcPtr crtc = config->crtc[i];
> +       drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
> +
> +       if (!crtc->enabled)
> +           continue;
> +
> +       if (drmmode_crtc->dpms_mode == DPMSModeOn)
> +           crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation,
> +                                       crtc->x, crtc->y);
> +       else
> +           drmmode_crtc->need_modeset = TRUE;
>      }
> +
> +    present_event_notify(event_id, 0, 0);
> +
> +    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