mirror of
https://github.com/X11Libre/xf86-video-ati.git
synced 2026-03-24 01:24:43 +00:00
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>
This commit is contained in:
committed by
Michel Dänzer
parent
ef2a6b818f
commit
740f0850f1
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user