diff options
author | Mario Kleiner <mario.kleiner.de@gmail.com> | 2018-12-18 11:40:35 +0100 |
---|---|---|
committer | Michel Dänzer <michel.daenzer@amd.com> | 2018-12-18 15:28:42 +0100 |
commit | 0058fd2ebf4c900b12f129984e98886a7ac84b2f (patch) | |
tree | 96acefb9914f7645c8e0df3f46710011d949463a /src/drmmode_display.c | |
parent | b559fd83b2b026b50fe39a2b69bdc0901fd3330c (diff) |
Fix crash when page flipping in multi-X-Screen/Zaphod mode
radeon_do_pageflip() indexed the flipdata->fb[] array
indexing over config->num_crtc, but the flip completion
routines, e.g., drmmode_flip_handler(), index that array
via the crtc hw id from drmmode_get_crtc_id(crtc).
This is mismatched and causes indexing into the wrong
array slot at flip completion -> Server crash.
Always use drmmode_get_crtc_id(crtc) for indexing into
the array to fix this.
Tested on a dual-X-Screen setup with one video output
assigned to each X-Screen, page-flipping an OpenGL app
on either of both X-Screens. This used to crash when
flipping on X-Screen 1, now it doesn't anymore.
Fixes: 740f0850f1e4 "Store FB for each CRTC in drmmode_flipdata_rec"
Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
Diffstat (limited to 'src/drmmode_display.c')
-rw-r--r-- | src/drmmode_display.c | 16 |
1 files changed, 9 insertions, 7 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c index fbdf5e6d..00d94449 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -3297,6 +3297,7 @@ 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 crtc_id; uint32_t flip_flags = flip_sync == FLIP_ASYNC ? DRM_MODE_PAGE_FLIP_ASYNC : 0; drmmode_flipdata_ptr flipdata; Bool handle_deferred = FALSE; @@ -3304,7 +3305,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, struct drmmode_fb *fb; int i = 0; - flipdata = calloc(1, sizeof(*flipdata) + config->num_crtc * + flipdata = calloc(1, sizeof(*flipdata) + drmmode_crtc->drmmode->count_crtcs * sizeof(flipdata->fb[0])); if (!flipdata) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, @@ -3336,6 +3337,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, for (i = 0; i < config->num_crtc; i++) { crtc = config->crtc[i]; drmmode_crtc = crtc->driver_private; + crtc_id = drmmode_get_crtc_id(crtc); if (!drmmode_crtc_can_flip(crtc) || (drmmode_crtc->tear_free && crtc != ref_crtc)) @@ -3369,9 +3371,9 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, goto next; } - drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb[i], + drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb[crtc_id], radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap)); - if (!flipdata->fb[i]) { + if (!flipdata->fb[crtc_id]) { ErrorF("Failed to get FB for TearFree flip\n"); goto error; } @@ -3387,13 +3389,13 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, drmmode_crtc->scanout_update_pending = 0; } } else { - drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb[i], fb); + drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb[crtc_id], fb); } if (crtc == ref_crtc) { if (drmmode_page_flip_target_absolute(pRADEONEnt, drmmode_crtc, - flipdata->fb[i]->handle, + flipdata->fb[crtc_id]->handle, flip_flags, drm_queue_seq, target_msc) != 0) @@ -3401,7 +3403,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, } else { if (drmmode_page_flip_target_relative(pRADEONEnt, drmmode_crtc, - flipdata->fb[i]->handle, + flipdata->fb[crtc_id]->handle, flip_flags, drm_queue_seq, 0) != 0) goto flip_error; @@ -3414,7 +3416,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, next: drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, - flipdata->fb[i]); + flipdata->fb[crtc_id]); drm_queue_seq = 0; } |