[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