When a video driver changed the availability of hw cursor inside the
xf86SetCursor() call, f86CursorSetCursor() still assumes the hw
cursor and clears SWCursor flag of the screen unconditionally.  This
results in the inconsistent state, typically the invisible cursor
pointer.  For example, the problem is seen with modesetting driver
with Cirrus or MGA KMS where the hw cursor isn't always available.

This patch adds the check of availability of hw cursor again after the
call of xf86SetCursor(), and proceeds only when it passes the test
after the call.

Signed-off-by: Takashi Iwai <[email protected]>
---
 hw/xfree86/ramdac/xf86Cursor.c | 47 ++++++++++++++++++++++++++++--------------
 1 file changed, 31 insertions(+), 16 deletions(-)

diff --git a/hw/xfree86/ramdac/xf86Cursor.c b/hw/xfree86/ramdac/xf86Cursor.c
index 860704e1c387..10c130e3edf2 100644
--- a/hw/xfree86/ramdac/xf86Cursor.c
+++ b/hw/xfree86/ramdac/xf86Cursor.c
@@ -295,6 +295,28 @@ xf86CursorUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr 
pScreen, CursorPtr pCurs)
     return (*ScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCurs);
 }
 
+static Bool
+useHwCursor(ScreenPtr pScreen, xf86CursorScreenPtr ScreenPriv,
+            xf86CursorInfoPtr infoPtr, CursorPtr cursor)
+{
+    if (ScreenPriv->ForceHWCursorCount)
+        return TRUE;
+
+#ifdef ARGB_CURSOR
+    if (cursor->bits->argb &&
+        infoPtr->UseHWCursorARGB &&
+        (*infoPtr->UseHWCursorARGB)(pScreen, cursor))
+        return TRUE;
+    if (cursor->bits->argb != 0)
+        return FALSE;
+#endif
+    if ((cursor->bits->height <= infoPtr->MaxHeight) &&
+        (cursor->bits->width <= infoPtr->MaxWidth) &&
+        (!infoPtr->UseHWCursor || (*infoPtr->UseHWCursor) (pScreen, cursor)))
+        return TRUE;
+    return FALSE;
+}
+
 static void
 xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs,
                     int x, int y)
@@ -336,28 +358,21 @@ xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
CursorPtr pCurs,
             ScreenPriv->SavedCursor = cursor;
 
         if (infoPtr->pScrn->vtSema && 
xorg_list_is_empty(&pScreen->pixmap_dirty_list) &&
-            (ScreenPriv->ForceHWCursorCount ||
-             ((
-#ifdef ARGB_CURSOR
-               cursor->bits->argb &&
-               infoPtr->UseHWCursorARGB &&
-               (*infoPtr->UseHWCursorARGB)(pScreen, cursor)) ||
-              (cursor->bits->argb == 0 &&
-#endif
-               (cursor->bits->height <= infoPtr->MaxHeight) &&
-               (cursor->bits->width <= infoPtr->MaxWidth) &&
-               (!infoPtr->UseHWCursor || (*infoPtr->UseHWCursor) (pScreen, 
cursor)))))) {
-            
+            useHwCursor(pScreen, ScreenPriv, infoPtr, cursor)) {
             if (ScreenPriv->SWCursor)   /* remove the SW cursor */
                 (*ScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen,
                                                        NullCursor, x, y);
 
             xf86SetCursor(pScreen, cursor, x, y);
-            ScreenPriv->SWCursor = FALSE;
-            ScreenPriv->isUp = TRUE;
 
-            miPointerSetWaitForUpdate(pScreen, !infoPtr->pScrn->silkenMouse);
-            return;
+            /* Check again in case the hwcursor is disabled in callbacks */
+            if (useHwCursor(pScreen, ScreenPriv, infoPtr, cursor)) {
+                ScreenPriv->SWCursor = FALSE;
+                ScreenPriv->isUp = TRUE;
+
+                miPointerSetWaitForUpdate(pScreen, 
!infoPtr->pScrn->silkenMouse);
+                return;
+            }
         }
 
         miPointerSetWaitForUpdate(pScreen, TRUE);
-- 
1.9.0

_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to