Title: [110464] trunk/Source
Revision
110464
Author
[email protected]
Date
2012-03-12 13:08:20 -0700 (Mon, 12 Mar 2012)

Log Message

[Chromium] Force compositeAndReadback through regular scheduling flow
https://bugs.webkit.org/show_bug.cgi?id=77049

Reviewed by James Robinson.

Source/WebCore:

* platform/graphics/chromium/cc/CCFrameRateController.cpp:
(WebCore::CCFrameRateController::onTimerTick):
* platform/graphics/chromium/cc/CCFrameRateController.h:
(CCFrameRateControllerClient):
* platform/graphics/chromium/cc/CCScheduler.cpp:
(WebCore::CCScheduler::setNeedsForcedCommit):
(WebCore):
(WebCore::CCScheduler::vsyncTick):
* platform/graphics/chromium/cc/CCScheduler.h:
(CCScheduler):
* platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp:
(WebCore::CCSchedulerStateMachine::CCSchedulerStateMachine):
(WebCore::CCSchedulerStateMachine::nextAction):
(WebCore::CCSchedulerStateMachine::updateState):
(WebCore::CCSchedulerStateMachine::setNeedsForcedCommit):
(WebCore):
* platform/graphics/chromium/cc/CCSchedulerStateMachine.h:
(CCSchedulerStateMachine):
* platform/graphics/chromium/cc/CCThreadProxy.cpp:
(WebCore::CCThreadProxy::CCThreadProxy):
(WebCore::CCThreadProxy::compositeAndReadback):
(WebCore::CCThreadProxy::requestReadbackOnImplThread):
(WebCore::CCThreadProxy::forceBeginFrameOnImplThread):
(WebCore::CCThreadProxy::scheduledActionBeginFrame):
(WebCore::CCThreadProxy::beginFrame):
* platform/graphics/chromium/cc/CCThreadProxy.h:
(CCThreadProxy):
(WebCore::CCThreadProxy::BeginFrameAndCommitState::BeginFrameAndCommitState):
(BeginFrameAndCommitState):

Source/WebKit/chromium:

* tests/CCFrameRateControllerTest.cpp:
(WebKitTests::FakeCCFrameRateControllerClient::reset):
(WebKitTests::FakeCCFrameRateControllerClient::vsyncTicked):
(WebKitTests::FakeCCFrameRateControllerClient::vsyncTick):
(FakeCCFrameRateControllerClient):
(WebKitTests::TEST):
* tests/CCLayerTreeHostTest.cpp:
(WTF):
(CCLayerTreeHostTestCompositeAndReadbackWhileInvisible):
(WTF::CCLayerTreeHostTestCompositeAndReadbackWhileInvisible::CCLayerTreeHostTestCompositeAndReadbackWhileInvisible):
(WTF::CCLayerTreeHostTestCompositeAndReadbackWhileInvisible::beginTest):
(WTF::CCLayerTreeHostTestCompositeAndReadbackWhileInvisible::didCommitAndDrawFrame):
(WTF::CCLayerTreeHostTestCompositeAndReadbackWhileInvisible::afterTest):
(WTF::TEST_F):
* tests/CCSchedulerStateMachineTest.cpp:
(WebCore::StateMachine::setNeedsForcedCommit):
(WebCore::StateMachine::needsForcedCommit):
(StateMachine):
(WebCore::TEST):
(WebCore):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (110463 => 110464)


--- trunk/Source/WebCore/ChangeLog	2012-03-12 19:57:00 UTC (rev 110463)
+++ trunk/Source/WebCore/ChangeLog	2012-03-12 20:08:20 UTC (rev 110464)
@@ -1,3 +1,40 @@
+2012-03-12  Nat Duca  <[email protected]>
+
+        [Chromium] Force compositeAndReadback through regular scheduling flow
+        https://bugs.webkit.org/show_bug.cgi?id=77049
+
+        Reviewed by James Robinson.
+
+        * platform/graphics/chromium/cc/CCFrameRateController.cpp:
+        (WebCore::CCFrameRateController::onTimerTick):
+        * platform/graphics/chromium/cc/CCFrameRateController.h:
+        (CCFrameRateControllerClient):
+        * platform/graphics/chromium/cc/CCScheduler.cpp:
+        (WebCore::CCScheduler::setNeedsForcedCommit):
+        (WebCore):
+        (WebCore::CCScheduler::vsyncTick):
+        * platform/graphics/chromium/cc/CCScheduler.h:
+        (CCScheduler):
+        * platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp:
+        (WebCore::CCSchedulerStateMachine::CCSchedulerStateMachine):
+        (WebCore::CCSchedulerStateMachine::nextAction):
+        (WebCore::CCSchedulerStateMachine::updateState):
+        (WebCore::CCSchedulerStateMachine::setNeedsForcedCommit):
+        (WebCore):
+        * platform/graphics/chromium/cc/CCSchedulerStateMachine.h:
+        (CCSchedulerStateMachine):
+        * platform/graphics/chromium/cc/CCThreadProxy.cpp:
+        (WebCore::CCThreadProxy::CCThreadProxy):
+        (WebCore::CCThreadProxy::compositeAndReadback):
+        (WebCore::CCThreadProxy::requestReadbackOnImplThread):
+        (WebCore::CCThreadProxy::forceBeginFrameOnImplThread):
+        (WebCore::CCThreadProxy::scheduledActionBeginFrame):
+        (WebCore::CCThreadProxy::beginFrame):
+        * platform/graphics/chromium/cc/CCThreadProxy.h:
+        (CCThreadProxy):
+        (WebCore::CCThreadProxy::BeginFrameAndCommitState::BeginFrameAndCommitState):
+        (BeginFrameAndCommitState):
+
 2012-03-12  Joshua Bell  <[email protected]>
 
         IndexedDB: Handle LevelDB database corruption

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.cpp (110463 => 110464)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.cpp	2012-03-12 19:57:00 UTC (rev 110463)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.cpp	2012-03-12 20:08:20 UTC (rev 110464)
@@ -87,7 +87,7 @@
     }
 
     if (m_client)
-        m_client->beginFrame();
+        m_client->vsyncTick();
 }
 
 void CCFrameRateController::didBeginFrame()

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.h (110463 => 110464)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.h	2012-03-12 19:57:00 UTC (rev 110463)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCFrameRateController.h	2012-03-12 20:08:20 UTC (rev 110464)
@@ -35,7 +35,7 @@
 
 class CCFrameRateControllerClient {
 public:
-    virtual void beginFrame() = 0;
+    virtual void vsyncTick() = 0;
 
 protected:
     virtual ~CCFrameRateControllerClient() { }

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.cpp (110463 => 110464)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.cpp	2012-03-12 19:57:00 UTC (rev 110463)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.cpp	2012-03-12 20:08:20 UTC (rev 110464)
@@ -56,6 +56,12 @@
     processScheduledActions();
 }
 
+void CCScheduler::setNeedsForcedCommit()
+{
+    m_stateMachine.setNeedsForcedCommit();
+    processScheduledActions();
+}
+
 void CCScheduler::setNeedsRedraw()
 {
     m_stateMachine.setNeedsRedraw();
@@ -101,13 +107,13 @@
     processScheduledActions();
 }
 
-void CCScheduler::beginFrame()
+void CCScheduler::vsyncTick()
 {
     if (m_updateMoreResourcesPending) {
         m_updateMoreResourcesPending = false;
         m_stateMachine.beginUpdateMoreResourcesComplete(m_client->hasMoreResourceUpdates());
     }
-    TRACE_EVENT("CCScheduler::beginFrame", this, 0);
+    TRACE_EVENT("CCScheduler::vsyncTick", this, 0);
 
     m_stateMachine.didEnterVSync();
     processScheduledActions();

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.h (110463 => 110464)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.h	2012-03-12 19:57:00 UTC (rev 110463)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.h	2012-03-12 20:08:20 UTC (rev 110464)
@@ -63,9 +63,13 @@
     void setVisible(bool);
 
     void setNeedsCommit();
+
+    // Like setNeedsCommit(), but ensures a commit will definitely happen even if we are not visible.
+    void setNeedsForcedCommit();
+
     void setNeedsRedraw();
 
-    // As setNeedsRedraw(), but ensures the draw will definitely happen even if we are not visible.
+    // Like setNeedsRedraw(), but ensures the draw will definitely happen even if we are not visible.
     void setNeedsForcedRedraw();
 
     void beginFrameComplete();
@@ -80,7 +84,7 @@
     bool redrawPending() const { return m_stateMachine.redrawPending(); }
 
     // CCFrameRateControllerClient implementation
-    virtual void beginFrame();
+    virtual void vsyncTick();
 
 private:
     CCScheduler(CCSchedulerClient*, PassOwnPtr<CCFrameRateController>);

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp (110463 => 110464)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp	2012-03-12 19:57:00 UTC (rev 110463)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp	2012-03-12 20:08:20 UTC (rev 110464)
@@ -35,6 +35,7 @@
     , m_needsRedraw(false)
     , m_needsForcedRedraw(false)
     , m_needsCommit(false)
+    , m_needsForcedCommit(false)
     , m_updateMoreResourcesPending(false)
     , m_insideVSync(false)
     , m_visible(false)
@@ -75,13 +76,15 @@
     case COMMIT_STATE_IDLE:
         if (m_contextState != CONTEXT_ACTIVE && m_needsForcedRedraw)
             return ACTION_DRAW;
+        if (m_contextState != CONTEXT_ACTIVE && m_needsForcedCommit)
+            return ACTION_BEGIN_FRAME;
         if (m_contextState == CONTEXT_LOST)
             return ACTION_BEGIN_CONTEXT_RECREATION;
         if (m_contextState == CONTEXT_RECREATING)
             return ACTION_NONE;
         if (shouldDraw())
             return ACTION_DRAW;
-        if (m_needsCommit && m_visible)
+        if (m_needsCommit && (m_visible || m_needsForcedCommit))
             return ACTION_BEGIN_FRAME;
         return ACTION_NONE;
 
@@ -105,7 +108,7 @@
             return ACTION_DRAW;
         // COMMIT_STATE_WAITING_FOR_FIRST_DRAW wants to enforce a draw. If m_canDraw is false,
         // proceed to the next step (similar as in COMMIT_STATE_IDLE).
-        if (!m_canDraw && m_needsCommit && m_visible)
+        if (!m_canDraw && m_needsCommit && (m_visible || m_needsForcedCommit))
             return ACTION_BEGIN_FRAME;
         return ACTION_NONE;
     }
@@ -120,9 +123,10 @@
         return;
 
     case ACTION_BEGIN_FRAME:
-        ASSERT(m_visible);
+        ASSERT(m_visible || m_needsForcedCommit);
         m_commitState = COMMIT_STATE_FRAME_IN_PROGRESS;
         m_needsCommit = false;
+        m_needsForcedCommit = false;
         return;
 
     case ACTION_BEGIN_UPDATE_MORE_RESOURCES:
@@ -131,7 +135,7 @@
         return;
 
     case ACTION_COMMIT:
-        if (m_needsCommit || !m_visible)
+        if ((m_needsCommit || !m_visible) && !m_needsForcedCommit)
             m_commitState = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
         else
             m_commitState = COMMIT_STATE_IDLE;
@@ -200,6 +204,11 @@
     m_needsCommit = true;
 }
 
+void CCSchedulerStateMachine::setNeedsForcedCommit()
+{
+    m_needsForcedCommit = true;
+}
+
 void CCSchedulerStateMachine::beginFrameComplete()
 {
     ASSERT(m_commitState == COMMIT_STATE_FRAME_IN_PROGRESS);

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h (110463 => 110464)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h	2012-03-12 19:57:00 UTC (rev 110463)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h	2012-03-12 20:08:20 UTC (rev 110464)
@@ -56,6 +56,7 @@
         CONTEXT_LOST,
         CONTEXT_RECREATING,
     };
+
     bool commitPending() const
     {
         return m_commitState != COMMIT_STATE_IDLE;
@@ -99,6 +100,10 @@
     // thread to main.
     void setNeedsCommit();
 
+    // As setNeedsCommit(), but ensures the beginFrame will definitely happen even if
+    // we are not visible.
+    void setNeedsForcedCommit();
+
     // Call this only in response to receiving an ACTION_BEGIN_FRAME
     // from nextState. Indicates that all painting is complete and that
     // updating of compositor resources can begin.
@@ -127,6 +132,7 @@
     bool m_needsRedraw;
     bool m_needsForcedRedraw;
     bool m_needsCommit;
+    bool m_needsForcedCommit;
     bool m_updateMoreResourcesPending;
     bool m_insideVSync;
     bool m_visible;

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp (110463 => 110464)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp	2012-03-12 19:57:00 UTC (rev 110463)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp	2012-03-12 20:08:20 UTC (rev 110464)
@@ -64,9 +64,8 @@
     , m_compositorIdentifier(-1)
     , m_layerRendererInitialized(false)
     , m_started(false)
-    , m_lastExecutedBeginFrameAndCommitSequenceNumber(-1)
-    , m_numBeginFrameAndCommitsIssuedOnImplThread(0)
     , m_mainThreadProxy(CCScopedThreadProxy::create(CCProxy::mainThread()))
+    , m_beginFrameCompletionEventOnImplThread(0)
     , m_readbackRequestOnImplThread(0)
     , m_finishAllRenderingCompletionEventOnImplThread(0)
     , m_commitCompletionEventOnImplThread(0)
@@ -94,25 +93,14 @@
         return false;
     }
 
-    // If a commit is pending, perform the commit first.
-    if (m_commitRequested)  {
-        // This bit of code is uglier than it should be because returning
-        // pointers via the CCThread task model is really messy. Effectively, we
-        // are making a blocking call to createBeginFrameAndCommitTaskOnImplThread,
-        // and trying to get the CCMainThread::Task it returns so we can run it.
-        OwnPtr<CCThread::Task> beginFrameAndCommitTask;
-        {
-            CCThread::Task* taskPtr = 0;
-            CCCompletionEvent completion;
-            CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::obtainBeginFrameAndCommitTaskFromCCThread, AllowCrossThreadAccess(&completion), AllowCrossThreadAccess(&taskPtr)));
-            completion.wait();
-            beginFrameAndCommitTask = adoptPtr(taskPtr);
-        }
 
-        beginFrameAndCommitTask->performTask();
-    }
+    // Perform a synchronous commit.
+    CCCompletionEvent beginFrameCompletion;
+    CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::forceBeginFrameOnImplThread, AllowCrossThreadAccess(&beginFrameCompletion)));
+    beginFrameCompletion.wait();
+    beginFrame();
 
-    // Draw using the new tree and read back the results.
+    // Perform a synchronous readback.
     ReadbackRequest request;
     request.rect = rect;
     request.pixels = pixels;
@@ -131,6 +119,7 @@
         return;
     }
     m_readbackRequestOnImplThread = request;
+    m_schedulerOnImplThread->setNeedsRedraw();
     m_schedulerOnImplThread->setNeedsForcedRedraw();
 }
 
@@ -385,55 +374,51 @@
     m_schedulerOnImplThread->setNeedsForcedRedraw();
 }
 
-void CCThreadProxy::scheduledActionBeginFrame()
+void CCThreadProxy::forceBeginFrameOnImplThread(CCCompletionEvent* completion)
 {
-    TRACE_EVENT("CCThreadProxy::scheduledActionBeginFrame", this, 0);
-    m_mainThreadProxy->postTask(createBeginFrameAndCommitTaskOnImplThread());
-}
+    TRACE_EVENT0("cc", "CCThreadProxy::forceBeginFrameOnImplThread");
+    ASSERT(!m_beginFrameCompletionEventOnImplThread);
 
-void CCThreadProxy::obtainBeginFrameAndCommitTaskFromCCThread(CCCompletionEvent* completion, CCThread::Task** taskPtr)
-{
-    OwnPtr<CCThread::Task> task = createBeginFrameAndCommitTaskOnImplThread();
-    *taskPtr = task.leakPtr();
-    completion->signal();
+    if (m_schedulerOnImplThread->commitPending()) {
+        completion->signal();
+        return;
+    }
+
+    m_beginFrameCompletionEventOnImplThread = completion;
+    m_schedulerOnImplThread->setNeedsCommit();
+    m_schedulerOnImplThread->setNeedsForcedCommit();
 }
 
-PassOwnPtr<CCThread::Task> CCThreadProxy::createBeginFrameAndCommitTaskOnImplThread()
+void CCThreadProxy::scheduledActionBeginFrame()
 {
-    TRACE_EVENT("CCThreadProxy::createBeginFrameAndCommitTaskOnImplThread", this, 0);
-    ASSERT(isImplThread());
-    double frameBeginTime = currentTime();
+    TRACE_EVENT0("cc", "CCThreadProxy::scheduledActionBeginFrame");
+    ASSERT(!m_pendingBeginFrameRequest);
+    m_pendingBeginFrameRequest = adoptPtr(new BeginFrameAndCommitState());
+    m_pendingBeginFrameRequest->frameBeginTime = 0;
+    m_pendingBeginFrameRequest->scrollInfo = m_layerTreeHostImpl->processScrollDeltas();
 
-    // NOTE, it is possible to receieve a request for a
-    // beginFrameAndCommitOnImplThread from finishAllRendering while a
-    // beginFrameAndCommitOnImplThread is enqueued. Since CCThread doesn't
-    // provide a threadsafe way to cancel tasks, it is important that
-    // beginFrameAndCommit be structured to understand that it may get called at
-    // a point that it shouldn't. We do this by assigning a sequence number to
-    // every new beginFrameAndCommit task. Then, beginFrameAndCommit tracks the
-    // last executed sequence number, dropping beginFrameAndCommit with sequence
-    // numbers below the last executed one.
-    int thisTaskSequenceNumber = m_numBeginFrameAndCommitsIssuedOnImplThread;
-    m_numBeginFrameAndCommitsIssuedOnImplThread++;
-    OwnPtr<CCScrollAndScaleSet> scrollInfo = m_layerTreeHostImpl->processScrollDeltas();
-    return createCCThreadTask(this, &CCThreadProxy::beginFrameAndCommit, thisTaskSequenceNumber, frameBeginTime, scrollInfo.release());
+    m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::beginFrame));
+
+    if (m_beginFrameCompletionEventOnImplThread) {
+        m_beginFrameCompletionEventOnImplThread->signal();
+        m_beginFrameCompletionEventOnImplThread = 0;
+    }
 }
 
-void CCThreadProxy::beginFrameAndCommit(int sequenceNumber, double frameBeginTime, PassOwnPtr<CCScrollAndScaleSet> scrollInfo)
+void CCThreadProxy::beginFrame()
 {
-    TRACE_EVENT("CCThreadProxy::beginFrameAndCommit", this, 0);
+    TRACE_EVENT0("cc", "CCThreadProxy::beginFrame");
     ASSERT(isMainThread());
     if (!m_layerTreeHost)
         return;
 
-    // Drop beginFrameAndCommit calls that occur out of sequence. See createBeginFrameAndCommitTaskOnImplThread for
-    // an explanation of how out-of-sequence beginFrameAndCommit tasks can occur.
-    if (sequenceNumber < m_lastExecutedBeginFrameAndCommitSequenceNumber) {
-        TRACE_EVENT("EarlyOut_StaleBeginFrameAndCommit", this, 0);
+    if (!m_pendingBeginFrameRequest) {
+        TRACE_EVENT0("cc", "EarlyOut_StaleBeginFrameMessage");
         return;
     }
-    m_lastExecutedBeginFrameAndCommitSequenceNumber = sequenceNumber;
 
+    OwnPtr<BeginFrameAndCommitState> request(m_pendingBeginFrameRequest.release());
+
     // Do not notify the impl thread of commit requests that occur during
     // the apply/animate/layout part of the beginFrameAndCommit process since
     // those commit requests will get painted immediately. Once we have done
@@ -448,14 +433,12 @@
 
     // FIXME: technically, scroll deltas need to be applied for dropped commits as well.
     // Re-do the commit flow so that we don't send the scrollInfo on the BFAC message.
-    m_layerTreeHost->applyScrollAndScale(*scrollInfo);
+    m_layerTreeHost->applyScrollAndScale(*request->scrollInfo);
 
     // FIXME: recreate the context if it was requested by the impl thread.
-    m_layerTreeHost->updateAnimations(frameBeginTime);
+    m_layerTreeHost->updateAnimations(request->frameBeginTime);
     m_layerTreeHost->layout();
 
-    ASSERT(m_lastExecutedBeginFrameAndCommitSequenceNumber == sequenceNumber);
-
     // Clear the commit flag after updating animations and layout here --- objects that only
     // layout when painted will trigger another setNeedsCommit inside
     // updateLayers.
@@ -482,8 +465,6 @@
     }
 
     m_layerTreeHost->commitComplete();
-
-    ASSERT(m_lastExecutedBeginFrameAndCommitSequenceNumber == sequenceNumber);
 }
 
 void CCThreadProxy::beginFrameCompleteOnImplThread(CCCompletionEvent* completion)

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.h (110463 => 110464)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.h	2012-03-12 19:57:00 UTC (rev 110463)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.h	2012-03-12 20:08:20 UTC (rev 110464)
@@ -90,8 +90,16 @@
     explicit CCThreadProxy(CCLayerTreeHost*);
     friend class CCThreadProxyContextRecreationTimer;
 
+    // Set on impl thread, read on main thread.
+    struct BeginFrameAndCommitState {
+        BeginFrameAndCommitState() : frameBeginTime(0) { }
+        double frameBeginTime;
+        OwnPtr<CCScrollAndScaleSet> scrollInfo;
+    };
+    OwnPtr<BeginFrameAndCommitState> m_pendingBeginFrameRequest;
+
     // Called on main thread
-    void beginFrameAndCommit(int sequenceNumber, double frameBeginTime, PassOwnPtr<CCScrollAndScaleSet>);
+    void beginFrame();
     void didCommitAndDrawFrame();
     void didCompleteSwapBuffers();
     void setAnimationEvents(PassOwnPtr<CCAnimationEventsVector>, double wallClockTime);
@@ -105,8 +113,7 @@
         void* pixels;
         IntRect rect;
     };
-    PassOwnPtr<CCThread::Task> createBeginFrameAndCommitTaskOnImplThread();
-    void obtainBeginFrameAndCommitTaskFromCCThread(CCCompletionEvent*, CCThread::Task**);
+    void forceBeginFrameOnImplThread(CCCompletionEvent*);
     void beginFrameCompleteOnImplThread(CCCompletionEvent*);
     void requestReadbackOnImplThread(ReadbackRequest*);
     void requestStartPageScaleAnimationOnImplThread(IntSize targetPosition, bool useAnchor, float scale, double durationSec);
@@ -129,11 +136,9 @@
     bool m_layerRendererInitialized;
     LayerRendererCapabilities m_layerRendererCapabilitiesMainThreadCopy;
     bool m_started;
-    int m_lastExecutedBeginFrameAndCommitSequenceNumber;
 
     // Used on the CCThread only.
     OwnPtr<CCLayerTreeHostImpl> m_layerTreeHostImpl;
-    int m_numBeginFrameAndCommitsIssuedOnImplThread;
 
     OwnPtr<CCInputHandler> m_inputHandlerOnImplThread;
 
@@ -145,6 +150,9 @@
     // and initializeLayerRenderer() calls.
     RefPtr<GraphicsContext3D> m_contextBeforeInitializationOnImplThread;
 
+    // Set when the main thread is waiting on a scheduledActionBeginFrame to be issued.
+    CCCompletionEvent* m_beginFrameCompletionEventOnImplThread;
+
     // Set when the main thread is waiing on a readback.
     ReadbackRequest* m_readbackRequestOnImplThread;
 

Modified: trunk/Source/WebKit/chromium/ChangeLog (110463 => 110464)


--- trunk/Source/WebKit/chromium/ChangeLog	2012-03-12 19:57:00 UTC (rev 110463)
+++ trunk/Source/WebKit/chromium/ChangeLog	2012-03-12 20:08:20 UTC (rev 110464)
@@ -1,3 +1,31 @@
+2012-03-12  Nat Duca  <[email protected]>
+
+        [Chromium] Force compositeAndReadback through regular scheduling flow
+        https://bugs.webkit.org/show_bug.cgi?id=77049
+
+        Reviewed by James Robinson.
+
+        * tests/CCFrameRateControllerTest.cpp:
+        (WebKitTests::FakeCCFrameRateControllerClient::reset):
+        (WebKitTests::FakeCCFrameRateControllerClient::vsyncTicked):
+        (WebKitTests::FakeCCFrameRateControllerClient::vsyncTick):
+        (FakeCCFrameRateControllerClient):
+        (WebKitTests::TEST):
+        * tests/CCLayerTreeHostTest.cpp:
+        (WTF):
+        (CCLayerTreeHostTestCompositeAndReadbackWhileInvisible):
+        (WTF::CCLayerTreeHostTestCompositeAndReadbackWhileInvisible::CCLayerTreeHostTestCompositeAndReadbackWhileInvisible):
+        (WTF::CCLayerTreeHostTestCompositeAndReadbackWhileInvisible::beginTest):
+        (WTF::CCLayerTreeHostTestCompositeAndReadbackWhileInvisible::didCommitAndDrawFrame):
+        (WTF::CCLayerTreeHostTestCompositeAndReadbackWhileInvisible::afterTest):
+        (WTF::TEST_F):
+        * tests/CCSchedulerStateMachineTest.cpp:
+        (WebCore::StateMachine::setNeedsForcedCommit):
+        (WebCore::StateMachine::needsForcedCommit):
+        (StateMachine):
+        (WebCore::TEST):
+        (WebCore):
+
 2012-03-12  Joshua Bell  <[email protected]>
 
         IndexedDB: Handle LevelDB database corruption

Modified: trunk/Source/WebKit/chromium/tests/CCFrameRateControllerTest.cpp (110463 => 110464)


--- trunk/Source/WebKit/chromium/tests/CCFrameRateControllerTest.cpp	2012-03-12 19:57:00 UTC (rev 110463)
+++ trunk/Source/WebKit/chromium/tests/CCFrameRateControllerTest.cpp	2012-03-12 20:08:20 UTC (rev 110464)
@@ -39,13 +39,13 @@
 public:
     FakeCCFrameRateControllerClient() { reset(); }
 
-    void reset() { m_frameBegun = false; }
-    bool frameBegun() const { return m_frameBegun; }
+    void reset() { m_vsyncTicked = false; }
+    bool vsyncTicked() const { return m_vsyncTicked; }
 
-    virtual void beginFrame() { m_frameBegun = true; }
+    virtual void vsyncTick() { m_vsyncTicked = true; }
 
 protected:
-    bool m_frameBegun;
+    bool m_vsyncTicked;
 };
 
 
@@ -65,7 +65,7 @@
     elapsed += thread.pendingDelay();
     timeSource->setMonotonicallyIncreasingTimeMs(elapsed);
     thread.runPendingTask();
-    EXPECT_TRUE(client.frameBegun());
+    EXPECT_TRUE(client.vsyncTicked());
     client.reset();
 
     // Tell the controller we drew
@@ -80,7 +80,7 @@
     EXPECT_TRUE(elapsed >= timeSource->monotonicallyIncreasingTimeMs()); // Sanity check that previous code didn't move time backward.
     timeSource->setMonotonicallyIncreasingTimeMs(elapsed);
     thread.runPendingTask();
-    EXPECT_TRUE(client.frameBegun());
+    EXPECT_TRUE(client.vsyncTicked());
 }
 
 TEST(CCFrameRateControllerTest, TestFrameThrottling_TwoFramesInFlight)
@@ -100,7 +100,7 @@
     elapsed += thread.pendingDelay();
     timeSource->setMonotonicallyIncreasingTimeMs(elapsed);
     thread.runPendingTask();
-    EXPECT_TRUE(client.frameBegun());
+    EXPECT_TRUE(client.vsyncTicked());
     client.reset();
 
     // Tell the controller we drew
@@ -111,7 +111,7 @@
     EXPECT_TRUE(elapsed >= timeSource->monotonicallyIncreasingTimeMs()); // Sanity check that previous code didn't move time backward.
     timeSource->setMonotonicallyIncreasingTimeMs(elapsed);
     thread.runPendingTask();
-    EXPECT_TRUE(client.frameBegun());
+    EXPECT_TRUE(client.vsyncTicked());
     client.reset();
 
     // Tell the controller we drew, again.
@@ -122,21 +122,21 @@
     EXPECT_TRUE(elapsed >= timeSource->monotonicallyIncreasingTimeMs()); // Sanity check that previous code didn't move time backward.
     timeSource->setMonotonicallyIncreasingTimeMs(elapsed);
     thread.runPendingTask();
-    EXPECT_FALSE(client.frameBegun());
+    EXPECT_FALSE(client.vsyncTicked());
 
     // Tell the controller the first frame ended 5ms later
     timeSource->setMonotonicallyIncreasingTimeMs(timeSource->monotonicallyIncreasingTimeMs() + 5);
     controller.didFinishFrame();
 
     // Tick should not have been called
-    EXPECT_FALSE(client.frameBegun());
+    EXPECT_FALSE(client.vsyncTicked());
 
     // Trigger yet another frame. Since one frames is pending, another vsync callback should run.
     elapsed += thread.pendingDelay();
     EXPECT_TRUE(elapsed >= timeSource->monotonicallyIncreasingTimeMs()); // Sanity check that previous code didn't move time backward.
     timeSource->setMonotonicallyIncreasingTimeMs(elapsed);
     thread.runPendingTask();
-    EXPECT_TRUE(client.frameBegun());
+    EXPECT_TRUE(client.vsyncTicked());
 }
 
 }

Modified: trunk/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp (110463 => 110464)


--- trunk/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp	2012-03-12 19:57:00 UTC (rev 110463)
+++ trunk/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp	2012-03-12 20:08:20 UTC (rev 110464)
@@ -806,6 +806,46 @@
     runTestThreaded();
 }
 
+// A compositeAndReadback while invisible should force a normal commit without assertion.
+class CCLayerTreeHostTestCompositeAndReadbackWhileInvisible : public CCLayerTreeHostTestThreadOnly {
+public:
+    CCLayerTreeHostTestCompositeAndReadbackWhileInvisible()
+        : m_numCommits(0)
+    {
+    }
+
+    virtual void beginTest()
+    {
+    }
+
+    virtual void didCommitAndDrawFrame()
+    {
+        m_numCommits++;
+        if (m_numCommits == 1) {
+            m_layerTreeHost->setVisible(false);
+            m_layerTreeHost->setNeedsCommit();
+            m_layerTreeHost->setNeedsCommit();
+            OwnArrayPtr<char> pixels(adoptArrayPtr(new char[4]));
+            m_layerTreeHost->compositeAndReadback(static_cast<void*>(pixels.get()), IntRect(0, 0, 1, 1));
+        } else
+            endTest();
+
+    }
+
+    virtual void afterTest()
+    {
+    }
+
+private:
+    int m_numCommits;
+};
+
+TEST_F(CCLayerTreeHostTestCompositeAndReadbackWhileInvisible, runMultiThread)
+{
+    runTestThreaded();
+}
+
+
 // Trigger a frame with setNeedsCommit. Then, inside the resulting animate
 // callback, requet another frame using setNeedsAnimate. End the test when
 // animate gets called yet-again, indicating that the proxy is correctly

Modified: trunk/Source/WebKit/chromium/tests/CCSchedulerStateMachineTest.cpp (110463 => 110464)


--- trunk/Source/WebKit/chromium/tests/CCSchedulerStateMachineTest.cpp	2012-03-12 19:57:00 UTC (rev 110463)
+++ trunk/Source/WebKit/chromium/tests/CCSchedulerStateMachineTest.cpp	2012-03-12 20:08:20 UTC (rev 110464)
@@ -52,6 +52,9 @@
     void setNeedsCommit(bool b) { m_needsCommit = b; }
     bool needsCommit() const { return m_needsCommit; }
 
+    void setNeedsForcedCommit(bool b) { m_needsForcedCommit = b; }
+    bool needsForcedCommit() const { return m_needsForcedCommit; }
+
     void setNeedsRedraw(bool b) { m_needsRedraw = b; }
     bool needsRedraw() const { return m_needsRedraw; }
 
@@ -778,4 +781,44 @@
     state.didLeaveVSync();
 }
 
+TEST(CCSchedulerStateMachineTest, TestBeginFrameWhenInvisibleAndForceCommit)
+{
+    StateMachine state;
+    state.setVisible(true);
+    state.setNeedsCommit(true);
+    state.setNeedsForcedCommit(true);
+    EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
 }
+
+TEST(CCSchedulerStateMachineTest, TestBeginFrameWhenCommitInProgress)
+{
+    StateMachine state;
+    state.setVisible(false);
+    state.setCommitState(CCSchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS);
+    state.setNeedsCommit(true);
+    state.setNeedsForcedCommit(true);
+
+    state.beginFrameComplete();
+    EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
+    state.updateState(state.nextAction());
+    EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
+    state.beginUpdateMoreResourcesComplete(false);
+    EXPECT_EQ(CCSchedulerStateMachine::ACTION_COMMIT, state.nextAction());
+    state.updateState(state.nextAction());
+
+    EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_IDLE, state.commitState());
+
+    EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
+}
+
+TEST(CCSchedulerStateMachineTest, TestBeginFrameWhenContextLost)
+{
+    StateMachine state;
+    state.setVisible(true);
+    state.setNeedsCommit(true);
+    state.setNeedsForcedCommit(true);
+    state.didLoseContext();
+    EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
+}
+
+}
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to