diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-05-07 11:21:11 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-05-07 11:21:11 +0200 |
commit | 2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47 (patch) | |
tree | 988e8c5b116dd0466244ae2fe5af8ee9be926d76 /Source/WebKit/chromium/tests/CCSchedulerTest.cpp | |
parent | dd91e772430dc294e3bf478c119ef8d43c0a3358 (diff) | |
download | qtwebkit-2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47.tar.gz |
Imported WebKit commit 7e538425aa020340619e927792f3d895061fb54b (http://svn.webkit.org/repository/webkit/trunk@116286)
Diffstat (limited to 'Source/WebKit/chromium/tests/CCSchedulerTest.cpp')
-rw-r--r-- | Source/WebKit/chromium/tests/CCSchedulerTest.cpp | 316 |
1 files changed, 279 insertions, 37 deletions
diff --git a/Source/WebKit/chromium/tests/CCSchedulerTest.cpp b/Source/WebKit/chromium/tests/CCSchedulerTest.cpp index 45f61b90b..41250884b 100644 --- a/Source/WebKit/chromium/tests/CCSchedulerTest.cpp +++ b/Source/WebKit/chromium/tests/CCSchedulerTest.cpp @@ -45,25 +45,56 @@ public: m_actions.clear(); m_hasMoreResourceUpdates = false; m_canDraw = true; + m_drawWillHappen = true; + m_swapWillHappenIfDrawHappens = true; + m_numDraws = 0; } void setHasMoreResourceUpdates(bool b) { m_hasMoreResourceUpdates = b; } void setCanDraw(bool b) { m_canDraw = b; } + int numDraws() const { return m_numDraws; } int numActions() const { return static_cast<int>(m_actions.size()); } const char* action(int i) const { return m_actions[i]; } - virtual bool canDraw() { return m_canDraw; } - virtual bool hasMoreResourceUpdates() const { return m_hasMoreResourceUpdates; } - virtual void scheduledActionBeginFrame() { m_actions.push_back("scheduledActionBeginFrame"); } - virtual void scheduledActionDrawAndSwap() { m_actions.push_back("scheduledActionDrawAndSwap"); } - virtual void scheduledActionUpdateMoreResources() { m_actions.push_back("scheduledActionUpdateMoreResources"); } - virtual void scheduledActionCommit() { m_actions.push_back("scheduledActionCommit"); } - virtual void scheduledActionBeginContextRecreation() { m_actions.push_back("scheduledActionBeginContextRecreation"); } + bool hasAction(const char* action) const + { + for (size_t i = 0; i < m_actions.size(); i++) + if (!strcmp(m_actions[i], action)) + return true; + return false; + } + + virtual bool canDraw() OVERRIDE { return m_canDraw; } + virtual bool hasMoreResourceUpdates() const OVERRIDE { return m_hasMoreResourceUpdates; } + virtual void scheduledActionBeginFrame() OVERRIDE { m_actions.push_back("scheduledActionBeginFrame"); } + virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapIfPossible() OVERRIDE + { + m_actions.push_back("scheduledActionDrawAndSwapIfPossible"); + m_numDraws++; + return CCScheduledActionDrawAndSwapResult(m_drawWillHappen, m_drawWillHappen && m_swapWillHappenIfDrawHappens); + } + + virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapForced() OVERRIDE + { + m_actions.push_back("scheduledActionDrawAndSwapForced"); + return CCScheduledActionDrawAndSwapResult(true, m_swapWillHappenIfDrawHappens); + } + + virtual void scheduledActionUpdateMoreResources() OVERRIDE { m_actions.push_back("scheduledActionUpdateMoreResources"); } + virtual void scheduledActionCommit() OVERRIDE { m_actions.push_back("scheduledActionCommit"); } + virtual void scheduledActionBeginContextRecreation() OVERRIDE { m_actions.push_back("scheduledActionBeginContextRecreation"); } + virtual void scheduledActionAcquireLayerTexturesForMainThread() OVERRIDE { m_actions.push_back("scheduledActionAcquireLayerTexturesForMainThread"); } + + void setDrawWillHappen(bool drawWillHappen) { m_drawWillHappen = drawWillHappen; } + void setSwapWillHappenIfDrawHappens(bool swapWillHappenIfDrawHappens) { m_swapWillHappenIfDrawHappens = swapWillHappenIfDrawHappens; } protected: bool m_hasMoreResourceUpdates; bool m_canDraw; + bool m_drawWillHappen; + bool m_swapWillHappenIfDrawHappens; + int m_numDraws; std::vector<const char*> m_actions; }; @@ -72,6 +103,7 @@ TEST(CCSchedulerTest, RequestCommit) FakeCCSchedulerClient client; RefPtr<FakeCCTimeSource> timeSource = adoptRef(new FakeCCTimeSource()); OwnPtr<CCScheduler> scheduler = CCScheduler::create(&client, adoptPtr(new CCFrameRateController(timeSource))); + scheduler->setCanBeginFrame(true); scheduler->setVisible(true); // SetNeedsCommit should begin the frame. @@ -94,7 +126,7 @@ TEST(CCSchedulerTest, RequestCommit) // Tick should draw. timeSource->tick(); EXPECT_EQ(1, client.numActions()); - EXPECT_STREQ("scheduledActionDrawAndSwap", client.action(0)); + EXPECT_STREQ("scheduledActionDrawAndSwapIfPossible", client.action(0)); EXPECT_FALSE(timeSource->active()); client.reset(); @@ -107,6 +139,7 @@ TEST(CCSchedulerTest, RequestCommitAfterBeginFrame) FakeCCSchedulerClient client; RefPtr<FakeCCTimeSource> timeSource = adoptRef(new FakeCCTimeSource()); OwnPtr<CCScheduler> scheduler = CCScheduler::create(&client, adoptPtr(new CCFrameRateController(timeSource))); + scheduler->setCanBeginFrame(true); scheduler->setVisible(true); // SetNedsCommit should begin the frame. @@ -131,38 +164,104 @@ TEST(CCSchedulerTest, RequestCommitAfterBeginFrame) timeSource->tick(); EXPECT_FALSE(timeSource->active()); EXPECT_EQ(2, client.numActions()); - EXPECT_STREQ("scheduledActionDrawAndSwap", client.action(0)); + EXPECT_STREQ("scheduledActionDrawAndSwapIfPossible", client.action(0)); EXPECT_STREQ("scheduledActionBeginFrame", client.action(1)); client.reset(); } -class SchedulerClientThatSetNeedsDrawInsideDraw : public CCSchedulerClient { +TEST(CCSchedulerTest, TextureAcquisitionCollision) +{ + FakeCCSchedulerClient client; + RefPtr<FakeCCTimeSource> timeSource = adoptRef(new FakeCCTimeSource()); + OwnPtr<CCScheduler> scheduler = CCScheduler::create(&client, adoptPtr(new CCFrameRateController(timeSource))); + scheduler->setCanBeginFrame(true); + scheduler->setVisible(true); + + scheduler->setNeedsCommit(); + scheduler->setMainThreadNeedsLayerTextures(); + EXPECT_EQ(2, client.numActions()); + EXPECT_STREQ("scheduledActionBeginFrame", client.action(0)); + EXPECT_STREQ("scheduledActionAcquireLayerTexturesForMainThread", client.action(1)); + client.reset(); + + // Compositor not scheduled to draw because textures are locked by main thread + EXPECT_FALSE(timeSource->active()); + + // Trigger the commit + scheduler->beginFrameComplete(); + EXPECT_TRUE(timeSource->active()); + client.reset(); + + // Between commit and draw, texture acquisition for main thread delayed, + // and main thread blocks. + scheduler->setMainThreadNeedsLayerTextures(); + EXPECT_EQ(0, client.numActions()); + client.reset(); + + // Once compositor draw complete, the delayed texture acquisition fires. + timeSource->tick(); + EXPECT_EQ(3, client.numActions()); + EXPECT_STREQ("scheduledActionDrawAndSwapIfPossible", client.action(0)); + EXPECT_STREQ("scheduledActionAcquireLayerTexturesForMainThread", client.action(1)); + EXPECT_STREQ("scheduledActionBeginFrame", client.action(2)); + client.reset(); +} + +TEST(CCSchedulerTest, VisibilitySwitchWithTextureAcquisition) +{ + FakeCCSchedulerClient client; + RefPtr<FakeCCTimeSource> timeSource = adoptRef(new FakeCCTimeSource()); + OwnPtr<CCScheduler> scheduler = CCScheduler::create(&client, adoptPtr(new CCFrameRateController(timeSource))); + scheduler->setCanBeginFrame(true); + scheduler->setVisible(true); + + scheduler->setNeedsCommit(); + scheduler->beginFrameComplete(); + scheduler->setMainThreadNeedsLayerTextures(); + client.reset(); + // Verify that pending texture acquisition fires when visibility + // is lost in order to avoid a deadlock. + scheduler->setVisible(false); + EXPECT_EQ(1, client.numActions()); + EXPECT_STREQ("scheduledActionAcquireLayerTexturesForMainThread", client.action(0)); + client.reset(); + + // Regaining visibility with textures acquired by main thread while + // compositor is waiting for first draw should result in a request + // for a new frame in order to escape a deadlock. + scheduler->setVisible(true); + EXPECT_EQ(1, client.numActions()); + EXPECT_STREQ("scheduledActionBeginFrame", client.action(0)); + client.reset(); +} + +class SchedulerClientThatSetNeedsDrawInsideDraw : public FakeCCSchedulerClient { public: SchedulerClientThatSetNeedsDrawInsideDraw() - : m_numDraws(0) - , m_scheduler(0) { } + : m_scheduler(0) { } void setScheduler(CCScheduler* scheduler) { m_scheduler = scheduler; } - int numDraws() const { return m_numDraws; } - - virtual bool hasMoreResourceUpdates() const { return false; } - virtual bool canDraw() { return true; } - virtual void scheduledActionBeginFrame() { } - virtual void scheduledActionDrawAndSwap() + virtual void scheduledActionBeginFrame() OVERRIDE { } + virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapIfPossible() OVERRIDE { // Only setNeedsRedraw the first time this is called if (!m_numDraws) m_scheduler->setNeedsRedraw(); - m_numDraws++; + return FakeCCSchedulerClient::scheduledActionDrawAndSwapIfPossible(); } - virtual void scheduledActionUpdateMoreResources() { } - virtual void scheduledActionCommit() { } - virtual void scheduledActionBeginContextRecreation() { } + virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapForced() OVERRIDE + { + ASSERT_NOT_REACHED(); + return CCScheduledActionDrawAndSwapResult(true, true); + } + + virtual void scheduledActionUpdateMoreResources() OVERRIDE { } + virtual void scheduledActionCommit() OVERRIDE { } + virtual void scheduledActionBeginContextRecreation() OVERRIDE { } protected: - int m_numDraws; CCScheduler* m_scheduler; }; @@ -176,6 +275,7 @@ TEST(CCSchedulerTest, RequestRedrawInsideDraw) RefPtr<FakeCCTimeSource> timeSource = adoptRef(new FakeCCTimeSource()); OwnPtr<CCScheduler> scheduler = CCScheduler::create(&client, adoptPtr(new CCFrameRateController(timeSource))); client.setScheduler(scheduler.get()); + scheduler->setCanBeginFrame(true); scheduler->setVisible(true); scheduler->setNeedsRedraw(); @@ -194,33 +294,74 @@ TEST(CCSchedulerTest, RequestRedrawInsideDraw) EXPECT_FALSE(timeSource->active()); } -class SchedulerClientThatSetNeedsCommitInsideDraw : public CCSchedulerClient { +// Test that requesting redraw inside a failed draw doesn't lose the request. +TEST(CCSchedulerTest, RequestRedrawInsideFailedDraw) +{ + SchedulerClientThatSetNeedsDrawInsideDraw client; + RefPtr<FakeCCTimeSource> timeSource = adoptRef(new FakeCCTimeSource()); + OwnPtr<CCScheduler> scheduler = CCScheduler::create(&client, adoptPtr(new CCFrameRateController(timeSource))); + client.setScheduler(scheduler.get()); + scheduler->setCanBeginFrame(true); + scheduler->setVisible(true); + client.setDrawWillHappen(false); + + scheduler->setNeedsRedraw(); + EXPECT_TRUE(scheduler->redrawPending()); + EXPECT_TRUE(timeSource->active()); + EXPECT_EQ(0, client.numDraws()); + + // Fail the draw. + timeSource->tick(); + EXPECT_EQ(1, client.numDraws()); + + // We have a commit pending and the draw failed, and we didn't lose the redraw request. + EXPECT_TRUE(scheduler->commitPending()); + EXPECT_TRUE(scheduler->redrawPending()); + EXPECT_TRUE(timeSource->active()); + + // Fail the draw again. + timeSource->tick(); + EXPECT_EQ(2, client.numDraws()); + EXPECT_TRUE(scheduler->commitPending()); + EXPECT_TRUE(scheduler->redrawPending()); + EXPECT_TRUE(timeSource->active()); + + // Draw successfully. + client.setDrawWillHappen(true); + timeSource->tick(); + EXPECT_EQ(3, client.numDraws()); + EXPECT_TRUE(scheduler->commitPending()); + EXPECT_FALSE(scheduler->redrawPending()); + EXPECT_FALSE(timeSource->active()); +} + +class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeCCSchedulerClient { public: SchedulerClientThatSetNeedsCommitInsideDraw() - : m_numDraws(0) - , m_scheduler(0) { } + : m_scheduler(0) { } void setScheduler(CCScheduler* scheduler) { m_scheduler = scheduler; } - int numDraws() const { return m_numDraws; } - - virtual bool hasMoreResourceUpdates() const { return false; } - virtual bool canDraw() { return true; } - virtual void scheduledActionBeginFrame() { } - virtual void scheduledActionDrawAndSwap() + virtual void scheduledActionBeginFrame() OVERRIDE { } + virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapIfPossible() OVERRIDE { // Only setNeedsCommit the first time this is called if (!m_numDraws) m_scheduler->setNeedsCommit(); - m_numDraws++; + return FakeCCSchedulerClient::scheduledActionDrawAndSwapIfPossible(); + } + + virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapForced() OVERRIDE + { + ASSERT_NOT_REACHED(); + return CCScheduledActionDrawAndSwapResult(true, true); } - virtual void scheduledActionUpdateMoreResources() { } - virtual void scheduledActionCommit() { } - virtual void scheduledActionBeginContextRecreation() { } + virtual void scheduledActionUpdateMoreResources() OVERRIDE { } + virtual void scheduledActionCommit() OVERRIDE { } + virtual void scheduledActionBeginContextRecreation() OVERRIDE { } protected: - int m_numDraws; CCScheduler* m_scheduler; }; @@ -232,6 +373,7 @@ TEST(CCSchedulerTest, RequestCommitInsideDraw) RefPtr<FakeCCTimeSource> timeSource = adoptRef(new FakeCCTimeSource()); OwnPtr<CCScheduler> scheduler = CCScheduler::create(&client, adoptPtr(new CCFrameRateController(timeSource))); client.setScheduler(scheduler.get()); + scheduler->setCanBeginFrame(true); scheduler->setVisible(true); scheduler->setNeedsRedraw(); @@ -251,4 +393,104 @@ TEST(CCSchedulerTest, RequestCommitInsideDraw) EXPECT_FALSE(scheduler->redrawPending()); } +// Tests that when a draw fails then the pending commit should not be dropped. +TEST(CCSchedulerTest, RequestCommitInsideFailedDraw) +{ + SchedulerClientThatSetNeedsDrawInsideDraw client; + RefPtr<FakeCCTimeSource> timeSource = adoptRef(new FakeCCTimeSource()); + OwnPtr<CCScheduler> scheduler = CCScheduler::create(&client, adoptPtr(new CCFrameRateController(timeSource))); + client.setScheduler(scheduler.get()); + scheduler->setCanBeginFrame(true); + scheduler->setVisible(true); + client.setDrawWillHappen(false); + + scheduler->setNeedsRedraw(); + EXPECT_TRUE(scheduler->redrawPending()); + EXPECT_TRUE(timeSource->active()); + EXPECT_EQ(0, client.numDraws()); + + // Fail the draw. + timeSource->tick(); + EXPECT_EQ(1, client.numDraws()); + + // We have a commit pending and the draw failed, and we didn't lose the commit request. + EXPECT_TRUE(scheduler->commitPending()); + EXPECT_TRUE(scheduler->redrawPending()); + EXPECT_TRUE(timeSource->active()); + + // Fail the draw again. + timeSource->tick(); + EXPECT_EQ(2, client.numDraws()); + EXPECT_TRUE(scheduler->commitPending()); + EXPECT_TRUE(scheduler->redrawPending()); + EXPECT_TRUE(timeSource->active()); + + // Draw successfully. + client.setDrawWillHappen(true); + timeSource->tick(); + EXPECT_EQ(3, client.numDraws()); + EXPECT_TRUE(scheduler->commitPending()); + EXPECT_FALSE(scheduler->redrawPending()); + EXPECT_FALSE(timeSource->active()); +} + +TEST(CCSchedulerTest, NoBeginFrameWhenDrawFails) +{ + RefPtr<FakeCCTimeSource> timeSource = adoptRef(new FakeCCTimeSource()); + SchedulerClientThatSetNeedsCommitInsideDraw client; + OwnPtr<FakeCCFrameRateController> controller = adoptPtr(new FakeCCFrameRateController(timeSource)); + FakeCCFrameRateController* controllerPtr = controller.get(); + OwnPtr<CCScheduler> scheduler = CCScheduler::create(&client, controller.release()); + client.setScheduler(scheduler.get()); + scheduler->setCanBeginFrame(true); + scheduler->setVisible(true); + + EXPECT_EQ(0, controllerPtr->numFramesPending()); + + scheduler->setNeedsRedraw(); + EXPECT_TRUE(scheduler->redrawPending()); + EXPECT_TRUE(timeSource->active()); + EXPECT_EQ(0, client.numDraws()); + + // Draw successfully, this starts a new frame. + timeSource->tick(); + EXPECT_EQ(1, client.numDraws()); + EXPECT_EQ(1, controllerPtr->numFramesPending()); + scheduler->didSwapBuffersComplete(); + EXPECT_EQ(0, controllerPtr->numFramesPending()); + + scheduler->setNeedsRedraw(); + EXPECT_TRUE(scheduler->redrawPending()); + EXPECT_TRUE(timeSource->active()); + + // Fail to draw, this should not start a frame. + client.setDrawWillHappen(false); + timeSource->tick(); + EXPECT_EQ(2, client.numDraws()); + EXPECT_EQ(0, controllerPtr->numFramesPending()); +} + +TEST(CCSchedulerTest, NoBeginFrameWhenSwapFailsDuringForcedCommit) +{ + RefPtr<FakeCCTimeSource> timeSource = adoptRef(new FakeCCTimeSource()); + FakeCCSchedulerClient client; + OwnPtr<FakeCCFrameRateController> controller = adoptPtr(new FakeCCFrameRateController(timeSource)); + FakeCCFrameRateController* controllerPtr = controller.get(); + OwnPtr<CCScheduler> scheduler = CCScheduler::create(&client, controller.release()); + + EXPECT_EQ(0, controllerPtr->numFramesPending()); + + // Tell the client that it will fail to swap. + client.setDrawWillHappen(true); + client.setSwapWillHappenIfDrawHappens(false); + + // Get the compositor to do a scheduledActionDrawAndSwapForced. + scheduler->setNeedsRedraw(); + scheduler->setNeedsForcedRedraw(); + EXPECT_TRUE(client.hasAction("scheduledActionDrawAndSwapForced")); + + // We should not have told the frame rate controller that we began a frame. + EXPECT_EQ(0, controllerPtr->numFramesPending()); +} + } |