Commit a1e47e76 authored by Tom Denis's avatar Tom Denis Committed by Michel Dänzer
Browse files

present: Fall back to modeset for unflip operation

Based on radeon commit: 802d33e474a82262d9cdf11b03568b0c4929cd0d

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: Tom Denis's avatarTom St Denis <>
Reviewed-by: Michel Dänzer's avatarMichel Dänzer <>
parent bac21dfc
......@@ -318,31 +318,51 @@ amdgpu_present_unflip(ScreenPtr screen, uint64_t event_id)
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
AMDGPUInfoPtr info = AMDGPUPTR(scrn);
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
struct amdgpu_present_vblank_event *event;
PixmapPtr pixmap = screen->GetScreenPixmap(screen);
struct amdgpu_buffer *bo;
Bool ret;
int i;
if (!amdgpu_present_check_flip(NULL, screen->root, pixmap, TRUE))
goto modeset;
bo = amdgpu_get_pixmap_bo(pixmap);
if (!bo)
if (!bo) {
ErrorF("%s: amdgpu_get_pixmap_bo failed, display might freeze\n", __func__);
goto modeset;
event = calloc(1, sizeof(struct amdgpu_present_vblank_event));
if (!event)
if (!event) {
ErrorF("%s: calloc failed, display might freeze\n", __func__);
goto modeset;
event->event_id = event_id;
ret = amdgpu_do_pageflip(scrn, AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, bo,
event_id, event, -1, amdgpu_present_flip_event,
if (!ret) {
xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present unflip failed\n");
info->drmmode.present_flipping = FALSE;
if (amdgpu_do_pageflip(scrn, AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, bo,
event_id, event, -1, amdgpu_present_flip_event,
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)
if (drmmode_crtc->dpms_mode == DPMSModeOn)
crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation,
crtc->x, crtc->y);
drmmode_crtc->need_modeset = TRUE;
present_event_notify(event_id, 0, 0);
info->drmmode.present_flipping = FALSE;
static present_screen_info_rec amdgpu_present_screen_info = {
......@@ -712,6 +712,9 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
if (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];
......@@ -1089,17 +1092,25 @@ static void drmmode_output_destroy(xf86OutputPtr output)
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 (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);
drmmode_do_crtc_dpms(output->crtc, mode);
static Bool drmmode_property_ignore(drmModePropertyPtr prop)
......@@ -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 {
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment