From a8f8ecdde495fb2a6ecdeca306b55c22b5fd3a6d Mon Sep 17 00:00:00 2001
From: Adam Jackson <ajax@redhat.com>
Date: Tue, 9 Jan 2018 10:54:05 -0500
Subject: [PATCH xserver 5/6] animcur: Fix transitions between animated cursors

We weren't cancelling the old timer when changing cursors, making things
go all crashy. Logically we could always cancel the timer first, but
then we'd have to call TimerSet to re-arm ourselves, and GetTimeInMillis
is potentially expensive.

Reported-by: https://devtalk.nvidia.com/default/topic/1028172/linux/titan-v-ubuntu-16-04lts-and-387-34-driver-crashes-badly/post/5230967/#5230967
Signed-off-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Aaron Plattner <aplattner@nvidia.com>
Tested-by: Aaron Plattner <aplattner@nvidia.com>
(cherry picked from commit de60245e05c0d2528d4ff42557a044387e53315c)
---
 render/animcur.c | 25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/render/animcur.c b/render/animcur.c
index 9393b4018..e585a8f23 100644
--- a/render/animcur.c
+++ b/render/animcur.c
@@ -152,11 +152,20 @@ AnimCurTimerNotify(OsTimerPtr timer, CARD32 now, void *arg)
     return ac->elts[elt].delay;
 }

+static void
+AnimCurCancelTimer(DeviceIntPtr pDev)
+{
+    CursorPtr cur = pDev->spriteInfo->anim.pCursor;
+
+    if (IsAnimCur(cur))
+        TimerCancel(GetAnimCur(cur)->timer);
+}
+
 static Bool
 AnimCurDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
 {
     AnimCurScreenPtr as = GetAnimCurScreen(pScreen);
-    Bool ret;
+    Bool ret = TRUE;

     if (IsFloating(pDev))
         return FALSE;
@@ -166,8 +175,10 @@ AnimCurDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
         if (pCursor != pDev->spriteInfo->anim.pCursor) {
             AnimCurPtr ac = GetAnimCur(pCursor);

-            ret = (*pScreen->DisplayCursor)
-                (pDev, pScreen, ac->elts[0].pCursor);
+            AnimCurCancelTimer(pDev);
+            ret = (*pScreen->DisplayCursor) (pDev, pScreen,
+                                             ac->elts[0].pCursor);
+
             if (ret) {
                 pDev->spriteInfo->anim.elt = 0;
                 pDev->spriteInfo->anim.time =
@@ -179,15 +190,9 @@ AnimCurDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
                                      AnimCurTimerNotify, pDev);
             }
         }
-        else
-            ret = TRUE;
     }
     else {
-        CursorPtr old = pDev->spriteInfo->anim.pCursor;
-
-        if (old && IsAnimCur(old))
-            TimerCancel(GetAnimCur(old)->timer);
-
+        AnimCurCancelTimer(pDev);
         pDev->spriteInfo->anim.pCursor = 0;
         pDev->spriteInfo->anim.pScreen = 0;
         ret = (*pScreen->DisplayCursor) (pDev, pScreen, pCursor);
--
2.14.3
