- Revision
- 120634
- Author
- [email protected]
- Date
- 2012-06-18 15:17:30 -0700 (Mon, 18 Jun 2012)
Log Message
[chromium] Ensure that skipping frames during an accelerated animation doesn't cause starvation
https://bugs.webkit.org/show_bug.cgi?id=87766
Patch by Ian Vollick <[email protected]> on 2012-06-18
Reviewed by James Robinson.
Source/WebCore:
Unit tests:
CCLayerTreeHostTestCheckerboardDoesNotStarveDraws.runMultiThread
CCSchedulerStateMachineTest.TestFailedDrawsWillEventuallyForceADrawAfterTheNextCommit
* platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp:
(WebCore::CCSchedulerStateMachine::CCSchedulerStateMachine):
(WebCore::CCSchedulerStateMachine::updateState):
(WebCore::CCSchedulerStateMachine::didDrawIfPossibleCompleted):
(WebCore::CCSchedulerStateMachine::setMaximumNumberOfFailedDrawsBeforeDrawIsForced):
(WebCore):
* platform/graphics/chromium/cc/CCSchedulerStateMachine.h:
(CCSchedulerStateMachine):
Source/WebKit/chromium:
* tests/CCLayerTreeHostTest.cpp:
(WTF):
(CCLayerTreeHostTestCheckerboardDoesNotStarveDraws):
(WTF::CCLayerTreeHostTestCheckerboardDoesNotStarveDraws::CCLayerTreeHostTestCheckerboardDoesNotStarveDraws):
(WTF::CCLayerTreeHostTestCheckerboardDoesNotStarveDraws::beginTest):
(WTF::CCLayerTreeHostTestCheckerboardDoesNotStarveDraws::afterTest):
(WTF::CCLayerTreeHostTestCheckerboardDoesNotStarveDraws::animateLayers):
(WTF::CCLayerTreeHostTestCheckerboardDoesNotStarveDraws::drawLayersOnCCThread):
(WTF::CCLayerTreeHostTestCheckerboardDoesNotStarveDraws::prepareToDrawOnCCThread):
(WTF::TEST_F):
* tests/CCSchedulerStateMachineTest.cpp:
(WebCore::TEST):
(WebCore):
* tests/CCThreadedTest.cpp:
(WebKitTests::MockLayerTreeHostImpl::prepareToDraw):
* tests/CCThreadedTest.h:
(WebKitTests::TestHooks::prepareToDrawOnCCThread):
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (120633 => 120634)
--- trunk/Source/WebCore/ChangeLog 2012-06-18 22:16:36 UTC (rev 120633)
+++ trunk/Source/WebCore/ChangeLog 2012-06-18 22:17:30 UTC (rev 120634)
@@ -1,3 +1,23 @@
+2012-06-18 Ian Vollick <[email protected]>
+
+ [chromium] Ensure that skipping frames during an accelerated animation doesn't cause starvation
+ https://bugs.webkit.org/show_bug.cgi?id=87766
+
+ Reviewed by James Robinson.
+
+ Unit tests:
+ CCLayerTreeHostTestCheckerboardDoesNotStarveDraws.runMultiThread
+ CCSchedulerStateMachineTest.TestFailedDrawsWillEventuallyForceADrawAfterTheNextCommit
+
+ * platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp:
+ (WebCore::CCSchedulerStateMachine::CCSchedulerStateMachine):
+ (WebCore::CCSchedulerStateMachine::updateState):
+ (WebCore::CCSchedulerStateMachine::didDrawIfPossibleCompleted):
+ (WebCore::CCSchedulerStateMachine::setMaximumNumberOfFailedDrawsBeforeDrawIsForced):
+ (WebCore):
+ * platform/graphics/chromium/cc/CCSchedulerStateMachine.h:
+ (CCSchedulerStateMachine):
+
2012-06-18 Nico Weber <[email protected]>
[chromium/mac] Unbreak smooth scrolling.
Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp (120633 => 120634)
--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp 2012-06-18 22:16:36 UTC (rev 120633)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp 2012-06-18 22:17:30 UTC (rev 120634)
@@ -32,8 +32,11 @@
: m_commitState(COMMIT_STATE_IDLE)
, m_currentFrameNumber(0)
, m_lastFrameNumberWhereDrawWasCalled(-1)
+ , m_consecutiveFailedDraws(0)
+ , m_maximumNumberOfFailedDrawsBeforeDrawIsForced(3)
, m_needsRedraw(false)
, m_needsForcedRedraw(false)
+ , m_needsForcedRedrawAfterNextCommit(false)
, m_needsCommit(false)
, m_needsForcedCommit(false)
, m_mainThreadNeedsLayerTextures(false)
@@ -177,9 +180,16 @@
m_commitState = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
else
m_commitState = COMMIT_STATE_IDLE;
+
m_needsRedraw = true;
if (m_drawIfPossibleFailed)
m_lastFrameNumberWhereDrawWasCalled = -1;
+
+ if (m_needsForcedRedrawAfterNextCommit) {
+ m_needsForcedRedrawAfterNextCommit = false;
+ m_needsForcedRedraw = true;
+ }
+
m_textureState = LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD;
return;
@@ -262,7 +272,15 @@
if (m_drawIfPossibleFailed) {
m_needsRedraw = true;
m_needsCommit = true;
- }
+ m_consecutiveFailedDraws++;
+ if (m_consecutiveFailedDraws >= m_maximumNumberOfFailedDrawsBeforeDrawIsForced) {
+ m_consecutiveFailedDraws = 0;
+ // We need to force a draw, but it doesn't make sense to do this until
+ // we've committed and have new textures.
+ m_needsForcedRedrawAfterNextCommit = true;
+ }
+ } else
+ m_consecutiveFailedDraws = 0;
}
void CCSchedulerStateMachine::setNeedsCommit()
@@ -304,4 +322,9 @@
setNeedsCommit();
}
+void CCSchedulerStateMachine::setMaximumNumberOfFailedDrawsBeforeDrawIsForced(int numDraws)
+{
+ m_maximumNumberOfFailedDrawsBeforeDrawIsForced = numDraws;
}
+
+}
Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h (120633 => 120634)
--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h 2012-06-18 22:16:36 UTC (rev 120633)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h 2012-06-18 22:17:30 UTC (rev 120634)
@@ -141,6 +141,9 @@
void didLoseContext();
void didRecreateContext();
+ // Exposed for testing purposes.
+ void setMaximumNumberOfFailedDrawsBeforeDrawIsForced(int);
+
protected:
bool shouldDrawForced() const;
bool drawSuspendedUntilCommit() const;
@@ -153,8 +156,11 @@
int m_currentFrameNumber;
int m_lastFrameNumberWhereDrawWasCalled;
+ int m_consecutiveFailedDraws;
+ int m_maximumNumberOfFailedDrawsBeforeDrawIsForced;
bool m_needsRedraw;
bool m_needsForcedRedraw;
+ bool m_needsForcedRedrawAfterNextCommit;
bool m_needsCommit;
bool m_needsForcedCommit;
bool m_mainThreadNeedsLayerTextures;
Modified: trunk/Source/WebKit/chromium/ChangeLog (120633 => 120634)
--- trunk/Source/WebKit/chromium/ChangeLog 2012-06-18 22:16:36 UTC (rev 120633)
+++ trunk/Source/WebKit/chromium/ChangeLog 2012-06-18 22:17:30 UTC (rev 120634)
@@ -1,3 +1,28 @@
+2012-06-18 Ian Vollick <[email protected]>
+
+ [chromium] Ensure that skipping frames during an accelerated animation doesn't cause starvation
+ https://bugs.webkit.org/show_bug.cgi?id=87766
+
+ Reviewed by James Robinson.
+
+ * tests/CCLayerTreeHostTest.cpp:
+ (WTF):
+ (CCLayerTreeHostTestCheckerboardDoesNotStarveDraws):
+ (WTF::CCLayerTreeHostTestCheckerboardDoesNotStarveDraws::CCLayerTreeHostTestCheckerboardDoesNotStarveDraws):
+ (WTF::CCLayerTreeHostTestCheckerboardDoesNotStarveDraws::beginTest):
+ (WTF::CCLayerTreeHostTestCheckerboardDoesNotStarveDraws::afterTest):
+ (WTF::CCLayerTreeHostTestCheckerboardDoesNotStarveDraws::animateLayers):
+ (WTF::CCLayerTreeHostTestCheckerboardDoesNotStarveDraws::drawLayersOnCCThread):
+ (WTF::CCLayerTreeHostTestCheckerboardDoesNotStarveDraws::prepareToDrawOnCCThread):
+ (WTF::TEST_F):
+ * tests/CCSchedulerStateMachineTest.cpp:
+ (WebCore::TEST):
+ (WebCore):
+ * tests/CCThreadedTest.cpp:
+ (WebKitTests::MockLayerTreeHostImpl::prepareToDraw):
+ * tests/CCThreadedTest.h:
+ (WebKitTests::TestHooks::prepareToDrawOnCCThread):
+
2012-06-18 Xianzhu Wang <[email protected]>
[Chromium] Change back "linuxish" to "linux" and include WebFontRendering.cpp on Android
Modified: trunk/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp (120633 => 120634)
--- trunk/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp 2012-06-18 22:16:36 UTC (rev 120633)
+++ trunk/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp 2012-06-18 22:17:30 UTC (rev 120634)
@@ -582,6 +582,50 @@
runTestThreaded();
}
+// Add a layer animation to a layer, but continually fail to draw. Confirm that after
+// a while, we do eventually force a draw.
+class CCLayerTreeHostTestCheckerboardDoesNotStarveDraws : public CCLayerTreeHostTestThreadOnly {
+public:
+ CCLayerTreeHostTestCheckerboardDoesNotStarveDraws()
+ : m_startedAnimating(false)
+ {
+ }
+
+ virtual void beginTest()
+ {
+ postAddAnimationToMainThread();
+ }
+
+ virtual void afterTest()
+ {
+ }
+
+ virtual void animateLayers(CCLayerTreeHostImpl* layerTreeHostImpl, double monotonicTime)
+ {
+ m_startedAnimating = true;
+ }
+
+ virtual void drawLayersOnCCThread(CCLayerTreeHostImpl*)
+ {
+ if (m_startedAnimating)
+ endTest();
+ }
+
+ virtual bool prepareToDrawOnCCThread(CCLayerTreeHostImpl*)
+ {
+ return false;
+ }
+
+private:
+ bool m_startedAnimating;
+};
+
+// Starvation can only be an issue with the MT compositor.
+TEST_F(CCLayerTreeHostTestCheckerboardDoesNotStarveDraws, runMultiThread)
+{
+ runTestThreaded();
+}
+
// Ensures that animations continue to be ticked when we are backgrounded.
class CCLayerTreeHostTestTickAnimationWhileBackgrounded : public CCLayerTreeHostTestThreadOnly {
public:
Modified: trunk/Source/WebKit/chromium/tests/CCSchedulerStateMachineTest.cpp (120633 => 120634)
--- trunk/Source/WebKit/chromium/tests/CCSchedulerStateMachineTest.cpp 2012-06-18 22:16:36 UTC (rev 120633)
+++ trunk/Source/WebKit/chromium/tests/CCSchedulerStateMachineTest.cpp 2012-06-18 22:17:30 UTC (rev 120634)
@@ -285,6 +285,48 @@
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
}
+TEST(CCSchedulerStateMachineTest, TestFailedDrawsWillEventuallyForceADrawAfterTheNextCommit)
+{
+ CCSchedulerStateMachine state;
+ state.setCanBeginFrame(true);
+ state.setVisible(true);
+ state.setMaximumNumberOfFailedDrawsBeforeDrawIsForced(1);
+
+ // Start a commit.
+ state.setNeedsCommit();
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
+ state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_FRAME);
+ EXPECT_TRUE(state.commitPending());
+
+ // Then initiate a draw.
+ state.setNeedsRedraw();
+ EXPECT_TRUE(state.vsyncCallbackNeeded());
+ state.didEnterVSync();
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
+ EXPECT_TRUE(state.redrawPending());
+
+ // Fail the draw.
+ state.updateState(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
+ state.didDrawIfPossibleCompleted(false);
+ EXPECT_TRUE(state.redrawPending());
+ // But the commit is ongoing.
+ EXPECT_TRUE(state.commitPending());
+
+ // Finish the commit. Note, we should not yet be forcing a draw, but should
+ // continue the commit as usual.
+ state.beginFrameComplete();
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
+ state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES);
+ state.beginUpdateMoreResourcesComplete(false);
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_COMMIT, state.nextAction());
+ state.updateState(CCSchedulerStateMachine::ACTION_COMMIT);
+ EXPECT_TRUE(state.redrawPending());
+
+ // The redraw should be forced in this case.
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_FORCED, state.nextAction());
+}
+
TEST(CCSchedulerStateMachineTest, TestFailedDrawIsRetriedNextVSync)
{
CCSchedulerStateMachine state;
Modified: trunk/Source/WebKit/chromium/tests/CCThreadedTest.cpp (120633 => 120634)
--- trunk/Source/WebKit/chromium/tests/CCThreadedTest.cpp 2012-06-18 22:16:36 UTC (rev 120633)
+++ trunk/Source/WebKit/chromium/tests/CCThreadedTest.cpp 2012-06-18 22:17:30 UTC (rev 120634)
@@ -133,7 +133,8 @@
bool MockLayerTreeHostImpl::prepareToDraw(FrameData& frame)
{
bool result = CCLayerTreeHostImpl::prepareToDraw(frame);
- m_testHooks->prepareToDrawOnCCThread(this);
+ if (!m_testHooks->prepareToDrawOnCCThread(this))
+ result = false;
return result;
}
Modified: trunk/Source/WebKit/chromium/tests/CCThreadedTest.h (120633 => 120634)
--- trunk/Source/WebKit/chromium/tests/CCThreadedTest.h 2012-06-18 22:16:36 UTC (rev 120633)
+++ trunk/Source/WebKit/chromium/tests/CCThreadedTest.h 2012-06-18 22:17:30 UTC (rev 120634)
@@ -51,7 +51,7 @@
public:
virtual void beginCommitOnCCThread(WebCore::CCLayerTreeHostImpl*) { }
virtual void commitCompleteOnCCThread(WebCore::CCLayerTreeHostImpl*) { }
- virtual void prepareToDrawOnCCThread(WebCore::CCLayerTreeHostImpl*) { }
+ virtual bool prepareToDrawOnCCThread(WebCore::CCLayerTreeHostImpl*) { return true; }
virtual void drawLayersOnCCThread(WebCore::CCLayerTreeHostImpl*) { }
virtual void animateLayers(WebCore::CCLayerTreeHostImpl*, double monotonicTime) { }
virtual void willAnimateLayers(WebCore::CCLayerTreeHostImpl*, double monotonicTime) { }