diff options
author | Mario Kleiner <mario.kleiner.de@gmail.com> | 2014-08-12 11:08:24 +0200 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2014-08-17 07:34:27 +1000 |
commit | 16c885ce9c7bebcfa1252a5d500956dd5f551043 (patch) | |
tree | 75ca2150f4ffe81246c67ec007c1f3e25b6f5593 /src | |
parent | 7eab6806927ea8938b9bd143d1702e87fde2f2cc (diff) |
Fix event handling on multi-x-screen configs.
Only register the wakeup handler and event socket
once per card fd and server generation, as the fd
and device file is shared between all x-screens for
a given card during a given server generation.
Without this fix, vblank and kms-pageflip completion
event processing don't work properly, as the server
doesn't kick the wakeup handler for gpu events, and
therefore the desktop will freeze, unless the user
manually kicks the wakeup handler by moving the mouse
or hitting the keyboard.
Add proper reference counting and checks to make it so.
This fix is derived from a similar and proven fix in
the ati ddx for the same problem.
Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/drmmode_display.c | 30 | ||||
-rw-r--r-- | src/nv_type.h | 2 |
2 files changed, 24 insertions, 8 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c index dc15221..6d225cb 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -1596,6 +1596,7 @@ drmmode_screen_init(ScreenPtr pScreen) { ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); drmmode_ptr drmmode = drmmode_from_scrn(scrn); + NVEntPtr pNVEnt = NVEntPriv(scrn); /* Setup handler for DRM events */ drmmode_event_init(scrn); @@ -1603,10 +1604,17 @@ drmmode_screen_init(ScreenPtr pScreen) /* Setup handler for udevevents */ drmmode_uevent_init(scrn); - /* Register a wakeup handler to get informed on DRM events */ - AddGeneralSocket(drmmode->fd); - RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, - drmmode_wakeup_handler, scrn); + /* Register wakeup handler only once per servergen, so ZaphodHeads work */ + if (pNVEnt->fd_wakeup_registered != serverGeneration) { + /* Register a wakeup handler to get informed on DRM events */ + AddGeneralSocket(drmmode->fd); + RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, + drmmode_wakeup_handler, scrn); + pNVEnt->fd_wakeup_registered = serverGeneration; + pNVEnt->fd_wakeup_ref = 1; + } + else + pNVEnt->fd_wakeup_ref++; } void @@ -1614,11 +1622,17 @@ drmmode_screen_fini(ScreenPtr pScreen) { ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); drmmode_ptr drmmode = drmmode_from_scrn(scrn); + NVEntPtr pNVEnt = NVEntPriv(scrn); - /* Unregister wakeup handler */ - RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, - drmmode_wakeup_handler, scrn); - RemoveGeneralSocket(drmmode->fd); + /* Unregister wakeup handler after last x-screen for this servergen dies. */ + if (pNVEnt->fd_wakeup_registered == serverGeneration && + !--pNVEnt->fd_wakeup_ref) { + + /* Unregister wakeup handler */ + RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, + drmmode_wakeup_handler, scrn); + RemoveGeneralSocket(drmmode->fd); + } /* Tear down udev event handler */ drmmode_uevent_fini(scrn); diff --git a/src/nv_type.h b/src/nv_type.h index 3e7c234..c0517c6 100644 --- a/src/nv_type.h +++ b/src/nv_type.h @@ -34,6 +34,8 @@ typedef struct { unsigned long reinitGeneration; struct xf86_platform_device *platform_dev; unsigned int assigned_crtcs; + unsigned long fd_wakeup_registered; + int fd_wakeup_ref; } NVEntRec, *NVEntPtr; NVEntPtr NVEntPriv(ScrnInfoPtr pScrn); |