diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index 83b221a8ccdfa6c97ce7ff15e347da9d0252d548..b5bdbde3ad85cf766daaacea114cc03cbca36c39 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -162,7 +162,6 @@ public:
         , m_vsync(0)
         , m_mode(VSyncMode)
         , m_bad(0)
-        , m_reallyBad(0)
         , m_good(0)
     {
         QScreen *screen = QGuiApplication::primaryScreen();
@@ -185,6 +184,7 @@ public:
     {
         m_time = 0;
         m_timer.start();
+        m_wallTime.restart();
         QAnimationDriver::start();
     }
 
@@ -192,7 +192,7 @@ public:
     {
         return m_mode == VSyncMode
                 ? qint64(m_time)
-                : QAnimationDriver::elapsed();
+                : qint64(m_time) + m_wallTime.elapsed();
     }
 
     void advance() Q_DECL_OVERRIDE
@@ -217,25 +217,22 @@ public:
 
             m_time += m_vsync;
 
-            if (delta > m_vsync * 5) {
-                ++m_reallyBad;
-                ++m_bad;
-            } else if (delta > m_vsync * 1.25) {
-                ++m_bad;
+            if (delta > m_vsync * 1.25) {
+                m_lag += (delta / m_vsync);
+                m_bad++;
+               // We tolerate one bad frame without resorting to timer based. This is
+                // done to cope with a slow loader frame followed by smooth animation.
+                // However, on the second frame with massive lag, we switch.
+                if (m_lag > 10 && m_bad > 2) {
+                    m_mode = TimerMode;
+                    qCDebug(QSG_LOG_INFO, "animation driver switched to timer mode");
+                    m_wallTime.restart();
+                }
             } else {
-                // reset counters on a good frame.
-                m_reallyBad = 0;
+                m_lag = 0;
                 m_bad = 0;
             }
 
-            // rational for the 3 and 50. If we have several really bad frames
-            // in a row, that would indicate a huge performance problem and we should
-            // switch right away. For the case of m_bad, we're a bit more tolerant.
-            if (m_reallyBad > 3 || m_bad > 50) {
-                m_mode = TimerMode;
-                qCDebug(QSG_LOG_INFO, "animation driver switched to timer mode");
-            }
-
         } else {
             if (delta < 1.25 * m_vsync) {
                 ++m_good;
@@ -249,6 +246,8 @@ public:
             if (m_good > 10 && !qsg_useConsistentTiming()) {
                 m_time = elapsed();
                 m_mode = VSyncMode;
+                m_bad = 0;
+                m_lag = 0;
                 qCDebug(QSG_LOG_INFO, "animation driver switched to vsync mode");
             }
         }
@@ -260,8 +259,9 @@ public:
     float m_vsync;
     Mode m_mode;
     QElapsedTimer m_timer;
+    QElapsedTimer m_wallTime;
+    float m_lag;
     int m_bad;
-    int m_reallyBad;
     int m_good;
 };