summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2015-05-19 12:14:24 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2015-05-19 12:44:26 +0100
commite617c1941c4e5ee90b69221013aab799eace925d (patch)
tree89f4cff1861ad2993535511020f548e4921fd9ef
parent276a628827c126a36f66e5f1b572aff2ff61de04 (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>
-rw-r--r--src/sna/sna.h3
-rw-r--r--src/sna/sna_display.c38
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);