diff options
author | Ville Syrjala <syrjala@sci.fi> | 2011-05-04 23:51:27 +0300 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2011-08-01 09:53:46 -0400 |
commit | d29bab632e9ecccba518d4107d52620bf75eb1cf (patch) | |
tree | f7511225f302dd59b79675888ced783fc2d5770b /src | |
parent | 9493563c1ef4b51af0ee8a44cb4e7c5bb280347e (diff) |
kms: Move flip_count and co. to a per swap structure
If multiple drawables are doing page flipping, the global drmmode
structure can't be used to keep per swap information. For example
flip_count can increase prematurely due to another swap request,
and then the previous swap request never gets completed, leading to a
stuck client. Move the relevant pieces of data to a strucuture that
gets allocated once per swap request and shared by all involved CRTCs.
Signed-off-by: Ville Syrjala <syrjala@sci.fi>
Diffstat (limited to 'src')
-rw-r--r-- | src/drmmode_display.c | 45 | ||||
-rw-r--r-- | src/drmmode_display.h | 10 |
2 files changed, 33 insertions, 22 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c index afa4c268..7f6ce181 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -1331,31 +1331,34 @@ drmmode_flip_handler(int fd, unsigned int frame, unsigned int tv_sec, unsigned int tv_usec, void *event_data) { drmmode_flipevtcarrier_ptr flipcarrier = event_data; - drmmode_ptr drmmode = flipcarrier->drmmode; + drmmode_flipdata_ptr flipdata = flipcarrier->flipdata; + drmmode_ptr drmmode = flipdata->drmmode; /* Is this the event whose info shall be delivered to higher level? */ if (flipcarrier->dispatch_me) { /* Yes: Cache msc, ust for later delivery. */ - drmmode->fe_frame = frame; - drmmode->fe_tv_sec = tv_sec; - drmmode->fe_tv_usec = tv_usec; + flipdata->fe_frame = frame; + flipdata->fe_tv_sec = tv_sec; + flipdata->fe_tv_usec = tv_usec; } free(flipcarrier); /* Last crtc completed flip? */ - drmmode->flip_count--; - if (drmmode->flip_count > 0) + flipdata->flip_count--; + if (flipdata->flip_count > 0) return; /* Release framebuffer */ - drmModeRmFB(drmmode->fd, drmmode->old_fb_id); + drmModeRmFB(drmmode->fd, flipdata->old_fb_id); - if (drmmode->event_data == NULL) + if (flipdata->event_data == NULL) return; /* Deliver cached msc, ust from reference crtc to flip event handler */ - radeon_dri2_flip_event_handler(drmmode->fe_frame, drmmode->fe_tv_sec, - drmmode->fe_tv_usec, drmmode->event_data); + radeon_dri2_flip_event_handler(flipdata->fe_frame, flipdata->fe_tv_sec, + flipdata->fe_tv_usec, flipdata->event_data); + + free(flipdata); } @@ -1399,12 +1402,10 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) xf86InitialConfiguration(pScrn, TRUE); - drmmode->flip_count = 0; drmmode->event_context.version = DRM_EVENT_CONTEXT_VERSION; drmmode->event_context.vblank_handler = drmmode_vblank_handler; drmmode->event_context.page_flip_handler = drmmode_flip_handler; if (!pRADEONEnt->fd_wakeup_registered && info->dri->pKernelDRMVersion->version_minor >= 4) { - drmmode->flip_count = 0; AddGeneralSocket(drmmode->fd); RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, drm_wakeup_handler, drmmode); @@ -1654,6 +1655,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat int i, old_fb_id; uint32_t tiling_flags = 0; int height; + drmmode_flipdata_ptr flipdata; drmmode_flipevtcarrier_ptr flipcarrier; if (info->allowColorTiling) { @@ -1676,6 +1678,12 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat new_front->handle, &drmmode->fb_id)) goto error_out; + flipdata = calloc(1, sizeof(drmmode_flipdata_rec)); + if (!flipdata) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "flip queue: data alloc failed.\n"); + goto error_undo; + } /* * Queue flips on all enabled CRTCs * Note that if/when we get per-CRTC buffers, we'll have to update this. @@ -1685,16 +1693,15 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat * Also, flips queued on disabled or incorrectly configured displays * may never complete; this is a configuration error. */ - drmmode->fe_frame = 0; - drmmode->fe_tv_sec = 0; - drmmode->fe_tv_usec = 0; + + flipdata->event_data = data; + flipdata->drmmode = drmmode; for (i = 0; i < config->num_crtc; i++) { if (!config->crtc[i]->enabled) continue; - drmmode->event_data = data; - drmmode->flip_count++; + flipdata->flip_count++; drmmode_crtc = config->crtc[i]->driver_private; flipcarrier = calloc(1, sizeof(drmmode_flipevtcarrier_rec)); @@ -1708,7 +1715,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat * completion event. All other crtc's events will be discarded. */ flipcarrier->dispatch_me = (drmmode_crtc->hw_id == ref_crtc_hw_id); - flipcarrier->drmmode = drmmode; + flipcarrier->flipdata = flipdata; if (drmModePageFlip(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, drmmode->fb_id, DRM_MODE_PAGE_FLIP_EVENT, flipcarrier)) { @@ -1719,7 +1726,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat } } - drmmode->old_fb_id = old_fb_id; + flipdata->old_fb_id = old_fb_id; return TRUE; error_undo: diff --git a/src/drmmode_display.h b/src/drmmode_display.h index 548907bb..eb271f5f 100644 --- a/src/drmmode_display.h +++ b/src/drmmode_display.h @@ -39,7 +39,6 @@ typedef struct { int fd; unsigned fb_id; - unsigned old_fb_id; drmModeResPtr mode_res; drmModeFBPtr mode_fb; int cpp; @@ -50,15 +49,20 @@ typedef struct { InputHandlerProc uevent_handler; #endif drmEventContext event_context; +} drmmode_rec, *drmmode_ptr; + +typedef struct { + drmmode_ptr drmmode; + unsigned old_fb_id; int flip_count; void *event_data; unsigned int fe_frame; unsigned int fe_tv_sec; unsigned int fe_tv_usec; -} drmmode_rec, *drmmode_ptr; +} drmmode_flipdata_rec, *drmmode_flipdata_ptr; typedef struct { - drmmode_ptr drmmode; + drmmode_flipdata_ptr flipdata; Bool dispatch_me; } drmmode_flipevtcarrier_rec, *drmmode_flipevtcarrier_ptr; |