[PATCH] xf86/cursor: Check hw cursor after xf86SeCursor() call, too

Takashi Iwai tiwai at suse.de
Thu Mar 20 09:53:42 PDT 2014


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 <tiwai at suse.de>
---
 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



More information about the xorg-devel mailing list