diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2015-05-19 12:14:24 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2015-05-19 12:44:26 +0100 |
commit | e617c1941c4e5ee90b69221013aab799eace925d (patch) | |
tree | 89f4cff1861ad2993535511020f548e4921fd9ef /src | |
parent | 276a628827c126a36f66e5f1b572aff2ff61de04 (diff) |
sna: Force restoration of SW cursor after HW cursor fails
In order to reset the SW cursor, we need to call xf86CursorSetCursor.
However, the parameters we need to call SetCursor with are not exposed
we need to be a little tricky and call a pair of functions that will
save and then restore the cursor.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src')
-rw-r--r-- | src/sna/sna.h | 3 | ||||
-rw-r--r-- | src/sna/sna_display.c | 38 |
2 files changed, 39 insertions, 2 deletions
diff --git a/src/sna/sna.h b/src/sna/sna.h index 374754b4..8a405800 100644 --- a/src/sna/sna.h +++ b/src/sna/sna.h @@ -322,7 +322,8 @@ struct sna { uint32_t fg, bg; int size; - int active; + bool disable; + bool active; int last_x; int last_y; diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index e62c6bec..daa14029 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -5215,6 +5215,28 @@ static inline void sigio_unblock(int was_blocked) } #endif +static void __restore_swcursor(ScrnInfoPtr scrn) +{ + DBG(("%s: attempting to restore SW cursor\n", __FUNCTION__)); + scrn->EnableDisableFBAccess(scrn, FALSE); + scrn->EnableDisableFBAccess(scrn, TRUE); + + RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)__restore_swcursor, + (WakeupHandlerProcPtr)NoopDDA, + scrn); +} + +static void restore_swcursor(struct sna *sna) +{ + /* XXX Force the cursor to be restored (avoiding recursion) */ + FreeCursor(sna->cursor.ref, None); + sna->cursor.ref = NULL; + + RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)__restore_swcursor, + (WakeupHandlerProcPtr)NoopDDA, + sna->scrn); +} + static void sna_show_cursors(ScrnInfoPtr scrn) { @@ -5268,10 +5290,17 @@ sna_show_cursors(ScrnInfoPtr scrn) cursor->ref++; sna_crtc->cursor = cursor; sna_crtc->last_cursor_size = cursor->size; + } else { + ERR(("%s: failed to show cursor on CRTC:%d [pipe=%d], disabling hwcursor\n", + __FUNCTION__, sna_crtc_id(crtc), sna_crtc_pipe(crtc))); + sna->cursor.disable = true; } } sigio_unblock(sigio); sna->cursor.active = true; + + if (unlikely(sna->cursor.disable)) + restore_swcursor(sna); } static void @@ -5493,14 +5522,17 @@ disable: } else { ERR(("%s: failed to update cursor on CRTC:%d [pipe=%d], disabling hwcursor\n", __FUNCTION__, sna_crtc_id(crtc), sna_crtc_pipe(crtc))); - sna_crtc->hwcursor = false; /* XXX How to force switch back to SW cursor? * Right now we just want until the next cursor image * change, which is fairly frequent. */ + sna->cursor.disable = true; } } sigio_unblock(sigio); + + if (unlikely(sna->cursor.disable)) + restore_swcursor(sna); } #if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,902,2) @@ -5596,6 +5628,9 @@ sna_use_hw_cursor(ScreenPtr screen, CursorPtr cursor) DBG(("%s (%dx%d)?\n", __FUNCTION__, cursor->bits->width, cursor->bits->height)); + if (sna->cursor.disable) + return FALSE; + /* cursors are invariant */ if (cursor == sna->cursor.ref) return TRUE; @@ -6453,6 +6488,7 @@ sna_crtc_config_notify(ScreenPtr screen) } update_flush_interval(sna); + sna->cursor.disable = false; /* Reset HW cursor until the next fail */ sna_cursors_reload(sna); probe_capabilities(sna); |