diff options
author | Michel Dänzer <michel.daenzer@amd.com> | 2018-08-02 18:49:48 +0200 |
---|---|---|
committer | Michel Dänzer <michel@daenzer.net> | 2018-08-03 18:24:01 +0200 |
commit | 740f0850f1e40403c8dd727e074eae36caeb1f63 (patch) | |
tree | 7de8a7e84484dc83c3bd2ca1cbae1ec15fa9aa4f | |
parent | ef2a6b818fa47ad571bb0bc105aa8193d51a2190 (diff) |
Store FB for each CRTC in drmmode_flipdata_rec
We were only storing the FB provided by the client, but on CRTCs with
TearFree enabled, we use a separate FB. This could cause
drmmode_flip_handler to fail to clear drmmode_crtc->flip_pending, which
could result in a hang when waiting for the pending flip to complete. We
were trying to avoid that by always clearing drmmode_crtc->flip_pending
when TearFree is enabled, but that wasn't reliable, because
drmmode_crtc->tear_free can already be FALSE at this point when
disabling TearFree.
Now that we're keeping track of each CRTC's flip FB separately,
drmmode_flip_handler can reliably clear flip_pending, and we no longer
need the TearFree hack.
(Ported from amdgpu commit 9b6782c821e0bdc53336d98f87ddde752faf7902)
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r-- | src/drmmode_display.c | 47 | ||||
-rw-r--r-- | src/drmmode_display.h | 2 |
2 files changed, 27 insertions, 22 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 6a0dba2c..0b92b70c 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -2536,17 +2536,21 @@ drmmode_flip_abort(xf86CrtcPtr crtc, void *event_data) drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); drmmode_flipdata_ptr flipdata = event_data; + int crtc_id = drmmode_get_crtc_id(crtc); + struct drmmode_fb **fb = &flipdata->fb[crtc_id]; + + if (drmmode_crtc->flip_pending == *fb) { + drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, + NULL); + } + drmmode_fb_reference(pRADEONEnt->fd, fb, NULL); if (--flipdata->flip_count == 0) { if (!flipdata->fe_crtc) flipdata->fe_crtc = crtc; flipdata->abort(flipdata->fe_crtc, flipdata->event_data); - drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb, NULL); free(flipdata); } - - drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, - NULL); } static void @@ -2555,6 +2559,8 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); drmmode_flipdata_ptr flipdata = event_data; + int crtc_id = drmmode_get_crtc_id(crtc); + struct drmmode_fb **fb = &flipdata->fb[crtc_id]; /* Is this the event whose info shall be delivered to higher level? */ if (crtc == flipdata->fe_crtc) { @@ -2563,13 +2569,12 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even flipdata->fe_usec = usec; } - drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, - flipdata->fb); - if (drmmode_crtc->tear_free || - drmmode_crtc->flip_pending == flipdata->fb) { + if (drmmode_crtc->flip_pending == *fb) { drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, NULL); } + drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, *fb); + drmmode_fb_reference(pRADEONEnt->fd, fb, NULL); if (--flipdata->flip_count == 0) { /* Deliver MSC & UST from reference/current CRTC to flip event @@ -2581,7 +2586,6 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even else flipdata->handler(crtc, frame, usec, flipdata->event_data); - drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb, NULL); free(flipdata); } } @@ -3287,21 +3291,22 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); xf86CrtcPtr crtc = NULL; drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private; - int i; uint32_t flip_flags = flip_sync == FLIP_ASYNC ? DRM_MODE_PAGE_FLIP_ASYNC : 0; drmmode_flipdata_ptr flipdata; uintptr_t drm_queue_seq = 0; + struct drmmode_fb *fb; + int i = 0; - flipdata = calloc(1, sizeof(drmmode_flipdata_rec)); + flipdata = calloc(1, sizeof(*flipdata) + config->num_crtc * + sizeof(flipdata->fb[0])); if (!flipdata) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue: data alloc failed.\n"); goto error; } - drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb, - radeon_pixmap_get_fb(new_front)); - if (!flipdata->fb) { + fb = radeon_pixmap_get_fb(new_front); + if (!fb) { ErrorF("Failed to get FB for flip\n"); goto error; } @@ -3322,8 +3327,6 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, flipdata->fe_crtc = ref_crtc; for (i = 0; i < config->num_crtc; i++) { - struct drmmode_fb *fb = flipdata->fb; - crtc = config->crtc[i]; drmmode_crtc = crtc->driver_private; @@ -3359,8 +3362,9 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, goto next; } - fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap); - if (!fb) { + drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb[i], + radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap)); + if (!flipdata->fb[i]) { ErrorF("Failed to get FB for TearFree flip\n"); goto error; } @@ -3375,6 +3379,8 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, radeon_drm_abort_entry(drmmode_crtc->scanout_update_pending); drmmode_crtc->scanout_update_pending = 0; } + } else { + drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb[i], fb); } if (crtc == ref_crtc) { @@ -3400,8 +3406,8 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, } next: - drmmode_fb_reference(pRADEONEnt->fd, - &drmmode_crtc->flip_pending, fb); + drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, + flipdata->fb[i]); drm_queue_seq = 0; } @@ -3419,7 +3425,6 @@ error: drmmode_flip_abort(crtc, flipdata); else { abort(NULL, data); - drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb, NULL); free(flipdata); } diff --git a/src/drmmode_display.h b/src/drmmode_display.h index c5a55891..46449c8e 100644 --- a/src/drmmode_display.h +++ b/src/drmmode_display.h @@ -56,7 +56,6 @@ typedef struct { } drmmode_rec, *drmmode_ptr; typedef struct { - struct drmmode_fb *fb; void *event_data; int flip_count; unsigned int fe_frame; @@ -64,6 +63,7 @@ typedef struct { xf86CrtcPtr fe_crtc; radeon_drm_handler_proc handler; radeon_drm_abort_proc abort; + struct drmmode_fb *fb[0]; } drmmode_flipdata_rec, *drmmode_flipdata_ptr; struct drmmode_fb { |