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
