0

Roll cc snapshot up to 127605

TBR=nduca@chromium.org
BUG=

Review URL: https://chromiumcodereview.appspot.com/10907075

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@155034 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
jamesr@chromium.org
2012-09-05 22:08:21 +00:00
parent 24302549a7
commit 8db2213c07
21 changed files with 289 additions and 67 deletions

@ -11,6 +11,14 @@
#include "TraceEvent.h"
#include <wtf/CurrentTime.h>
namespace {
// This will be the maximum number of pending frames unless
// CCFrameRateController::setMaxFramesPending is called.
const int defaultMaxFramesPending = 2;
}
namespace WebCore {
class CCFrameRateControllerTimeSourceAdapter : public CCTimeSourceClient {
@ -32,9 +40,10 @@ private:
CCFrameRateController::CCFrameRateController(PassRefPtr<CCTimeSource> timer)
: m_client(0)
, m_numFramesPending(0)
, m_maxFramesPending(0)
, m_maxFramesPending(defaultMaxFramesPending)
, m_timeSource(timer)
, m_active(false)
, m_swapBuffersCompleteSupported(true)
, m_isTimeSourceThrottling(true)
{
m_timeSourceClientAdapter = CCFrameRateControllerTimeSourceAdapter::create(this);
@ -44,8 +53,9 @@ CCFrameRateController::CCFrameRateController(PassRefPtr<CCTimeSource> timer)
CCFrameRateController::CCFrameRateController(CCThread* thread)
: m_client(0)
, m_numFramesPending(0)
, m_maxFramesPending(0)
, m_maxFramesPending(defaultMaxFramesPending)
, m_active(false)
, m_swapBuffersCompleteSupported(true)
, m_isTimeSourceThrottling(false)
{
m_manualTicker = adoptPtr(new CCTimer(thread, this));
@ -76,6 +86,7 @@ void CCFrameRateController::setActive(bool active)
void CCFrameRateController::setMaxFramesPending(int maxFramesPending)
{
ASSERT(maxFramesPending > 0);
m_maxFramesPending = maxFramesPending;
}
@ -85,12 +96,17 @@ void CCFrameRateController::setTimebaseAndInterval(double timebase, double inter
m_timeSource->setTimebaseAndInterval(timebase, intervalSeconds);
}
void CCFrameRateController::setSwapBuffersCompleteSupported(bool supported)
{
m_swapBuffersCompleteSupported = supported;
}
void CCFrameRateController::onTimerTick()
{
ASSERT(m_active);
// Don't forward the tick if we have too many frames in flight.
if (m_maxFramesPending && m_numFramesPending >= m_maxFramesPending) {
if (m_numFramesPending >= m_maxFramesPending) {
TRACE_EVENT0("cc", "CCFrameRateController::onTimerTickButMaxFramesPending");
return;
}
@ -98,8 +114,7 @@ void CCFrameRateController::onTimerTick()
if (m_client)
m_client->vsyncTick();
if (!m_isTimeSourceThrottling
&& (!m_maxFramesPending || m_numFramesPending < m_maxFramesPending))
if (m_swapBuffersCompleteSupported && !m_isTimeSourceThrottling && m_numFramesPending < m_maxFramesPending)
postManualTick();
}
@ -116,11 +131,16 @@ void CCFrameRateController::onTimerFired()
void CCFrameRateController::didBeginFrame()
{
m_numFramesPending++;
if (m_swapBuffersCompleteSupported)
m_numFramesPending++;
else if (!m_isTimeSourceThrottling)
postManualTick();
}
void CCFrameRateController::didFinishFrame()
{
ASSERT(m_swapBuffersCompleteSupported);
m_numFramesPending--;
if (!m_isTimeSourceThrottling)
postManualTick();

@ -50,6 +50,7 @@ public:
double nextTickTimeIfActivated();
void setTimebaseAndInterval(double timebase, double intervalSeconds);
void setSwapBuffersCompleteSupported(bool);
protected:
friend class CCFrameRateControllerTimeSourceAdapter;
@ -66,6 +67,7 @@ protected:
RefPtr<CCTimeSource> m_timeSource;
OwnPtr<CCFrameRateControllerTimeSourceAdapter> m_timeSourceClientAdapter;
bool m_active;
bool m_swapBuffersCompleteSupported;
// Members for unthrottled frame-rate.
bool m_isTimeSourceThrottling;

@ -638,7 +638,7 @@ void CCLayerTreeHost::applyScrollAndScale(const CCScrollAndScaleSet& info)
if (layer == rootScrollLayer)
rootScrollDelta += info.scrolls[i].scrollDelta;
else
layer->scrollBy(info.scrolls[i].scrollDelta);
layer->setScrollPosition(layer->scrollPosition() + info.scrolls[i].scrollDelta);
}
if (!rootScrollDelta.isZero() || info.pageScaleDelta != 1)
m_client->applyScrollAndScale(rootScrollDelta, info.pageScaleDelta);

@ -148,6 +148,10 @@ void CCLayerTreeHostImpl::commitComplete()
bool CCLayerTreeHostImpl::canDraw()
{
// Note: If you are changing this function or any other function that might
// affect the result of canDraw, make sure to call m_client->onCanDrawStateChanged
// in the proper places and update the notifyIfCanDrawChanged test.
if (!m_rootLayerImpl) {
TRACE_EVENT_INSTANT0("cc", "CCLayerTreeHostImpl::canDraw no root layer");
return false;
@ -510,6 +514,7 @@ void CCLayerTreeHostImpl::releaseContentsTextures()
m_resourceProvider->deleteOwnedResources(CCRenderer::ContentPool);
m_contentsTexturesPurged = true;
m_client->setNeedsCommitOnImplThread();
m_client->onCanDrawStateChanged(canDraw());
}
void CCLayerTreeHostImpl::setMemoryAllocationLimitBytes(size_t bytes)
@ -649,6 +654,8 @@ void CCLayerTreeHostImpl::setRootLayer(PassOwnPtr<CCLayerImpl> layer)
m_currentlyScrollingLayerImpl = CCLayerTreeHostCommon::findLayerInSubtree(m_rootLayerImpl.get(), m_scrollingLayerIdFromPreviousTree);
m_scrollingLayerIdFromPreviousTree = -1;
m_client->onCanDrawStateChanged(canDraw());
}
PassOwnPtr<CCLayerImpl> CCLayerTreeHostImpl::detachLayerTree()
@ -711,9 +718,17 @@ bool CCLayerTreeHostImpl::initializeRenderer(PassOwnPtr<CCGraphicsContext> conte
if (!m_visible && m_renderer)
m_renderer->setVisible(m_visible);
m_client->onCanDrawStateChanged(canDraw());
return m_renderer;
}
void CCLayerTreeHostImpl::resetContentsTexturesPurged()
{
m_contentsTexturesPurged = false;
m_client->onCanDrawStateChanged(canDraw());
}
void CCLayerTreeHostImpl::setViewportSize(const IntSize& layoutViewportSize, const IntSize& deviceViewportSize)
{
if (layoutViewportSize == m_layoutViewportSize && deviceViewportSize == m_deviceViewportSize)
@ -726,6 +741,8 @@ void CCLayerTreeHostImpl::setViewportSize(const IntSize& layoutViewportSize, con
if (m_renderer)
m_renderer->viewportChanged();
m_client->onCanDrawStateChanged(canDraw());
}
static void adjustScrollsForPageScaleChange(CCLayerImpl* layerImpl, float pageScaleChange)

@ -37,6 +37,7 @@ public:
virtual void didLoseContextOnImplThread() = 0;
virtual void onSwapBuffersCompleteOnImplThread() = 0;
virtual void onVSyncParametersChanged(double monotonicTimebase, double intervalInSeconds) = 0;
virtual void onCanDrawStateChanged(bool canDraw) = 0;
virtual void setNeedsRedrawOnImplThread() = 0;
virtual void setNeedsCommitOnImplThread() = 0;
virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>, double wallClockTime) = 0;
@ -140,7 +141,7 @@ public:
void setSourceFrameNumber(int frameNumber) { m_sourceFrameNumber = frameNumber; }
bool contentsTexturesPurged() const { return m_contentsTexturesPurged; }
void resetContentsTexturesPurged() { m_contentsTexturesPurged = false; }
void resetContentsTexturesPurged();
size_t memoryAllocationLimitBytes() const { return m_memoryAllocationLimitBytes; }
void setViewportSize(const IntSize& layoutViewportSize, const IntSize& deviceViewportSize);

@ -50,7 +50,8 @@ namespace {
class CCLayerTreeHostImplTest : public testing::Test, public CCLayerTreeHostImplClient {
public:
CCLayerTreeHostImplTest()
: m_didRequestCommit(false)
: m_onCanDrawStateChangedCalled(false)
, m_didRequestCommit(false)
, m_didRequestRedraw(false)
{
CCLayerTreeSettings settings;
@ -64,6 +65,7 @@ public:
virtual void didLoseContextOnImplThread() OVERRIDE { }
virtual void onSwapBuffersCompleteOnImplThread() OVERRIDE { }
virtual void onVSyncParametersChanged(double, double) OVERRIDE { }
virtual void onCanDrawStateChanged(bool canDraw) OVERRIDE { m_onCanDrawStateChangedCalled = true; }
virtual void setNeedsRedrawOnImplThread() OVERRIDE { m_didRequestRedraw = true; }
virtual void setNeedsCommitOnImplThread() OVERRIDE { m_didRequestCommit = true; }
virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>, double wallClockTime) OVERRIDE { }
@ -165,6 +167,7 @@ protected:
DebugScopedSetMainThreadBlocked m_alwaysMainThreadBlocked;
OwnPtr<CCLayerTreeHostImpl> m_hostImpl;
bool m_onCanDrawStateChangedCalled;
bool m_didRequestCommit;
bool m_didRequestRedraw;
CCScopedSettings m_scopedSettings;
@ -175,6 +178,53 @@ public:
virtual bool makeContextCurrent() { return false; }
};
TEST_F(CCLayerTreeHostImplTest, notifyIfCanDrawChanged)
{
// Note: It is not possible to disable the renderer once it has been set,
// so we do not need to test that disabling the renderer notifies us
// that canDraw changed.
EXPECT_FALSE(m_hostImpl->canDraw());
m_onCanDrawStateChangedCalled = false;
setupScrollAndContentsLayers(IntSize(100, 100));
EXPECT_TRUE(m_hostImpl->canDraw());
EXPECT_TRUE(m_onCanDrawStateChangedCalled);
m_onCanDrawStateChangedCalled = false;
// Toggle the root layer to make sure it toggles canDraw
m_hostImpl->setRootLayer(adoptPtr<CCLayerImpl>(0));
EXPECT_FALSE(m_hostImpl->canDraw());
EXPECT_TRUE(m_onCanDrawStateChangedCalled);
m_onCanDrawStateChangedCalled = false;
setupScrollAndContentsLayers(IntSize(100, 100));
EXPECT_TRUE(m_hostImpl->canDraw());
EXPECT_TRUE(m_onCanDrawStateChangedCalled);
m_onCanDrawStateChangedCalled = false;
// Toggle the device viewport size to make sure it toggles canDraw.
m_hostImpl->setViewportSize(IntSize(100, 100), IntSize(0, 0));
EXPECT_FALSE(m_hostImpl->canDraw());
EXPECT_TRUE(m_onCanDrawStateChangedCalled);
m_onCanDrawStateChangedCalled = false;
m_hostImpl->setViewportSize(IntSize(100, 100), IntSize(100, 100));
EXPECT_TRUE(m_hostImpl->canDraw());
EXPECT_TRUE(m_onCanDrawStateChangedCalled);
m_onCanDrawStateChangedCalled = false;
// Toggle contents textures purged to make sure it toggles canDraw
m_hostImpl->releaseContentsTextures();
EXPECT_FALSE(m_hostImpl->canDraw());
EXPECT_TRUE(m_onCanDrawStateChangedCalled);
m_onCanDrawStateChangedCalled = false;
m_hostImpl->resetContentsTexturesPurged();
EXPECT_TRUE(m_hostImpl->canDraw());
EXPECT_TRUE(m_onCanDrawStateChangedCalled);
m_onCanDrawStateChangedCalled = false;
}
TEST_F(CCLayerTreeHostImplTest, scrollDeltaNoLayers)
{
ASSERT_FALSE(m_hostImpl->rootLayer());

@ -21,6 +21,8 @@
#include "FakeWebCompositorOutputSurface.h"
#include <gmock/gmock.h>
#include <public/Platform.h>
#include <public/WebLayerScrollClient.h>
#include <public/WebSize.h>
#include <wtf/MainThread.h>
#include <wtf/OwnArrayPtr.h>
@ -2192,7 +2194,7 @@ private:
SINGLE_AND_MULTI_THREAD_TEST_F(CCLayerTreeHostTestLayerAddedWithAnimation)
class CCLayerTreeHostTestScrollChildLayer : public CCLayerTreeHostTest, public LayerChromiumScrollDelegate {
class CCLayerTreeHostTestScrollChildLayer : public CCLayerTreeHostTest, public WebLayerScrollClient {
public:
CCLayerTreeHostTestScrollChildLayer()
: m_scrollAmount(2, 1)
@ -2215,7 +2217,7 @@ public:
m_rootScrollLayer->setMaxScrollPosition(IntSize(100, 100));
m_layerTreeHost->rootLayer()->addChild(m_rootScrollLayer);
m_childLayer = ContentLayerChromium::create(&m_mockDelegate);
m_childLayer->setLayerScrollDelegate(this);
m_childLayer->setLayerScrollClient(this);
m_childLayer->setBounds(IntSize(50, 50));
m_childLayer->setIsDrawable(true);
m_childLayer->setScrollable(true);
@ -2228,9 +2230,9 @@ public:
postSetNeedsCommitToMainThread();
}
virtual void didScroll(const IntSize& scrollDelta) OVERRIDE
virtual void didScroll() OVERRIDE
{
m_reportedScrollAmount = scrollDelta;
m_finalScrollPosition = m_childLayer->scrollPosition();
}
virtual void applyScrollAndScale(const IntSize& scrollDelta, float) OVERRIDE
@ -2260,12 +2262,12 @@ public:
virtual void afterTest() OVERRIDE
{
EXPECT_EQ(m_scrollAmount, m_reportedScrollAmount);
EXPECT_EQ(IntPoint(m_scrollAmount), m_finalScrollPosition);
}
private:
const IntSize m_scrollAmount;
IntSize m_reportedScrollAmount;
IntPoint m_finalScrollPosition;
MockContentLayerChromiumClient m_mockDelegate;
RefPtr<LayerChromium> m_childLayer;
RefPtr<LayerChromium> m_rootScrollLayer;

@ -37,6 +37,16 @@ void CCScheduler::setVisible(bool visible)
processScheduledActions();
}
void CCScheduler::setCanDraw(bool canDraw)
{
m_stateMachine.setCanDraw(canDraw);
// Defer processScheduleActions so we don't recurse and commit/draw
// multiple frames. We can call processScheduledActions directly
// once it is no longer re-entrant.
m_frameRateController->setActive(m_stateMachine.vsyncCallbackNeeded());
}
void CCScheduler::setNeedsCommit()
{
m_stateMachine.setNeedsCommit();
@ -86,6 +96,11 @@ void CCScheduler::setMaxFramesPending(int maxFramesPending)
m_frameRateController->setMaxFramesPending(maxFramesPending);
}
void CCScheduler::setSwapBuffersCompleteSupported(bool supported)
{
m_frameRateController->setSwapBuffersCompleteSupported(supported);
}
void CCScheduler::didSwapBuffersComplete()
{
TRACE_EVENT0("cc", "CCScheduler::didSwapBuffersComplete");
@ -125,16 +140,10 @@ void CCScheduler::vsyncTick()
m_stateMachine.didLeaveVSync();
}
CCSchedulerStateMachine::Action CCScheduler::nextAction()
{
m_stateMachine.setCanDraw(m_client->canDraw());
return m_stateMachine.nextAction();
}
void CCScheduler::processScheduledActions()
{
// Early out so we don't spam TRACE_EVENTS with useless processScheduledActions.
if (nextAction() == CCSchedulerStateMachine::ACTION_NONE) {
if (m_stateMachine.nextAction() == CCSchedulerStateMachine::ACTION_NONE) {
m_frameRateController->setActive(m_stateMachine.vsyncCallbackNeeded());
return;
}
@ -143,7 +152,7 @@ void CCScheduler::processScheduledActions()
// setNeedsCommit. Proceeed with caution.
CCSchedulerStateMachine::Action action;
do {
action = nextAction();
action = m_stateMachine.nextAction();
m_stateMachine.updateState(action);
TRACE_EVENT1("cc", "CCScheduler::processScheduledActions()", "action", action);

@ -32,7 +32,6 @@ struct CCScheduledActionDrawAndSwapResult {
class CCSchedulerClient {
public:
virtual bool canDraw() = 0;
virtual bool hasMoreResourceUpdates() const = 0;
virtual void scheduledActionBeginFrame() = 0;
@ -60,6 +59,7 @@ public:
void setCanBeginFrame(bool);
void setVisible(bool);
void setCanDraw(bool);
void setNeedsCommit();
@ -77,6 +77,7 @@ public:
void beginFrameAborted();
void setMaxFramesPending(int);
void setSwapBuffersCompleteSupported(bool);
void didSwapBuffersComplete();
void didLoseContext();
@ -93,7 +94,6 @@ public:
private:
CCScheduler(CCSchedulerClient*, PassOwnPtr<CCFrameRateController>);
CCSchedulerStateMachine::Action nextAction();
void processScheduledActions();
CCSchedulerClient* m_client;

@ -5,6 +5,8 @@
#include "config.h"
#include "CCSchedulerStateMachine.h"
#include "TextStream.h"
namespace WebCore {
@ -24,13 +26,38 @@ CCSchedulerStateMachine::CCSchedulerStateMachine()
, m_insideVSync(false)
, m_visible(false)
, m_canBeginFrame(false)
, m_canDraw(true)
, m_canDraw(false)
, m_drawIfPossibleFailed(false)
, m_textureState(LAYER_TEXTURE_STATE_UNLOCKED)
, m_contextState(CONTEXT_ACTIVE)
{
}
String CCSchedulerStateMachine::toString()
{
TextStream ts;
ts << "m_commitState = " << m_commitState << "; ";
ts << "m_currentFrameNumber = " << m_currentFrameNumber << "; ";
ts << "m_lastFrameNumberWhereDrawWasCalled = " << m_lastFrameNumberWhereDrawWasCalled << "; ";
ts << "m_consecutiveFailedDraws = " << m_consecutiveFailedDraws << "; ";
ts << "m_maximumNumberOfFailedDrawsBeforeDrawIsForced = " << m_maximumNumberOfFailedDrawsBeforeDrawIsForced << "; ";
ts << "m_needsRedraw = " << m_needsRedraw << "; ";
ts << "m_needsForcedRedraw = " << m_needsForcedRedraw << "; ";
ts << "m_needsForcedRedrawAfterNextCommit = " << m_needsForcedRedrawAfterNextCommit << "; ";
ts << "m_needsCommit = " << m_needsCommit << "; ";
ts << "m_needsForcedCommit = " << m_needsForcedCommit << "; ";
ts << "m_mainThreadNeedsLayerTextures = " << m_mainThreadNeedsLayerTextures << "; ";
ts << "m_updateMoreResourcesPending = " << m_updateMoreResourcesPending << "; ";
ts << "m_insideVSync = " << m_insideVSync << "; ";
ts << "m_visible = " << m_visible << "; ";
ts << "m_canBeginFrame = " << m_canBeginFrame << "; ";
ts << "m_canDraw = " << m_canDraw << "; ";
ts << "m_drawIfPossibleFailed = " << m_drawIfPossibleFailed << "; ";
ts << "m_textureState = " << m_textureState << "; ";
ts << "m_contextState = " << m_contextState << "; ";
return ts.release();
}
bool CCSchedulerStateMachine::hasDrawnThisFrame() const
{
return m_currentFrameNumber == m_lastFrameNumberWhereDrawWasCalled;
@ -210,14 +237,18 @@ void CCSchedulerStateMachine::setMainThreadNeedsLayerTextures()
bool CCSchedulerStateMachine::vsyncCallbackNeeded() const
{
if (!m_visible || m_contextState != CONTEXT_ACTIVE) {
if (m_needsForcedRedraw || m_commitState == COMMIT_STATE_UPDATING_RESOURCES)
return true;
// To prevent live-lock, we must always tick when updating resources.
if (m_updateMoreResourcesPending || m_commitState == COMMIT_STATE_UPDATING_RESOURCES)
return true;
// If we can't draw, don't tick until we are notified that we can draw again.
if (!m_canDraw)
return false;
}
return m_needsRedraw || m_needsForcedRedraw || m_commitState == COMMIT_STATE_UPDATING_RESOURCES;
if (m_needsForcedRedraw)
return true;
return m_needsRedraw && m_visible && m_contextState == CONTEXT_ACTIVE;
}
void CCSchedulerStateMachine::didEnterVSync()

@ -6,6 +6,7 @@
#define CCSchedulerStateMachine_h
#include <wtf/Noncopyable.h>
#include <wtf/text/WTFString.h>
namespace WebCore {
@ -128,6 +129,8 @@ public:
// Exposed for testing purposes.
void setMaximumNumberOfFailedDrawsBeforeDrawIsForced(int);
String toString();
protected:
bool shouldDrawForced() const;
bool drawSuspendedUntilCommit() const;

@ -116,6 +116,7 @@ TEST(CCSchedulerStateMachineTest, TestNextActionBeginsFrameIfNeeded)
TEST(CCSchedulerStateMachineTest, TestSetForcedRedrawDoesNotSetsNormalRedraw)
{
CCSchedulerStateMachine state;
state.setCanDraw(true);
state.setNeedsForcedRedraw();
EXPECT_FALSE(state.redrawPending());
EXPECT_TRUE(state.vsyncCallbackNeeded());
@ -126,6 +127,7 @@ TEST(CCSchedulerStateMachineTest, TestFailedDrawSetsNeedsCommitAndDoesNotDrawAga
CCSchedulerStateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.setCanDraw(true);
state.setNeedsRedraw();
EXPECT_TRUE(state.redrawPending());
EXPECT_TRUE(state.vsyncCallbackNeeded());
@ -151,6 +153,7 @@ TEST(CCSchedulerStateMachineTest, TestSetNeedsRedrawDuringFailedDrawDoesNotRemov
CCSchedulerStateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.setCanDraw(true);
state.setNeedsRedraw();
EXPECT_TRUE(state.redrawPending());
EXPECT_TRUE(state.vsyncCallbackNeeded());
@ -179,6 +182,7 @@ TEST(CCSchedulerStateMachineTest, TestCommitAfterFailedDrawAllowsDrawInSameFrame
CCSchedulerStateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.setCanDraw(true);
// Start a commit.
state.setNeedsCommit();
@ -219,6 +223,7 @@ TEST(CCSchedulerStateMachineTest, TestCommitAfterFailedAndSuccessfulDrawDoesNotA
CCSchedulerStateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.setCanDraw(true);
// Start a commit.
state.setNeedsCommit();
@ -270,6 +275,7 @@ TEST(CCSchedulerStateMachineTest, TestFailedDrawsWillEventuallyForceADrawAfterTh
CCSchedulerStateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.setCanDraw(true);
state.setMaximumNumberOfFailedDrawsBeforeDrawIsForced(1);
// Start a commit.
@ -312,6 +318,7 @@ TEST(CCSchedulerStateMachineTest, TestFailedDrawIsRetriedNextVSync)
CCSchedulerStateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.setCanDraw(true);
// Start a draw.
state.setNeedsRedraw();
@ -341,6 +348,7 @@ TEST(CCSchedulerStateMachineTest, TestDoestDrawTwiceInSameFrame)
{
CCSchedulerStateMachine state;
state.setVisible(true);
state.setCanDraw(true);
state.setNeedsRedraw();
EXPECT_TRUE(state.vsyncCallbackNeeded());
state.didEnterVSync();
@ -393,6 +401,7 @@ TEST(CCSchedulerStateMachineTest, TestNextActionDrawsOnVSync)
for (size_t i = 0; i < numCommitStates; ++i) {
for (unsigned j = 0; j < 2; ++j) {
StateMachine state;
state.setCanDraw(true);
state.setCommitState(allCommitStates[i]);
bool forcedDraw = j;
if (!forcedDraw) {
@ -505,6 +514,28 @@ TEST(CCSchedulerStateMachineTest, TestCanRedrawWithWaitingForFirstDrawMakesProgr
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
}
TEST(CCSchedulerStateMachineTest, TestVsyncCallbackNeededOnCanDrawAndResourceUpdates)
{
StateMachine state;
state.setCommitState(CCSchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
state.setCanBeginFrame(true);
state.setNeedsCommit(true);
state.setNeedsRedraw(true);
state.setUpdateMoreResourcesPending(false);
state.setVisible(true);
state.setCanDraw(false);
EXPECT_FALSE(state.vsyncCallbackNeeded());
state.setUpdateMoreResourcesPending(true);
EXPECT_TRUE(state.vsyncCallbackNeeded());
state.setUpdateMoreResourcesPending(false);
EXPECT_FALSE(state.vsyncCallbackNeeded());
state.setCanDraw(true);
EXPECT_TRUE(state.vsyncCallbackNeeded());
}
TEST(CCSchedulerStateMachineTest, TestUpdates_NoRedraw_OneRoundOfUpdates)
{
StateMachine state;
@ -512,6 +543,7 @@ TEST(CCSchedulerStateMachineTest, TestUpdates_NoRedraw_OneRoundOfUpdates)
state.setNeedsRedraw(false);
state.setUpdateMoreResourcesPending(false);
state.setVisible(true);
state.setCanDraw(true);
// Verify we begin update, both for vsync and not vsync.
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
@ -540,6 +572,7 @@ TEST(CCSchedulerStateMachineTest, TestUpdates_NoRedraw_TwoRoundsOfUpdates)
state.setNeedsRedraw(false);
state.setUpdateMoreResourcesPending(false);
state.setVisible(true);
state.setCanDraw(true);
// Verify the update begins, both for vsync and not vsync.
state.didEnterVSync();
@ -579,6 +612,7 @@ TEST(CCSchedulerStateMachineTest, TestUpdates_NoRedraw_TwoRoundsOfUpdates)
TEST(CCSchedulerStateMachineTest, TestVSyncNeededWhenUpdatesPendingButInvisible)
{
StateMachine state;
state.setCanDraw(true);
state.setCommitState(CCSchedulerStateMachine::COMMIT_STATE_UPDATING_RESOURCES);
state.setNeedsRedraw(false);
state.setVisible(false);
@ -596,6 +630,7 @@ TEST(CCSchedulerStateMachineTest, TestUpdates_WithRedraw_OneRoundOfUpdates)
state.setNeedsRedraw(true);
state.setUpdateMoreResourcesPending(false);
state.setVisible(true);
state.setCanDraw(true);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
// Begin an update.
@ -643,6 +678,7 @@ TEST(CCSchedulerStateMachineTest, TestSetNeedsCommitIsNotLost)
state.setCanBeginFrame(true);
state.setNeedsCommit(true);
state.setVisible(true);
state.setCanDraw(true);
// Begin the frame.
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
@ -685,6 +721,7 @@ TEST(CCSchedulerStateMachineTest, TestFullCycle)
StateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.setCanDraw(true);
// Start clean and set commit.
state.setNeedsCommit(true);
@ -733,6 +770,7 @@ TEST(CCSchedulerStateMachineTest, TestFullCycleWithCommitRequestInbetween)
StateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.setCanDraw(true);
// Start clean and set commit.
state.setNeedsCommit(true);
@ -792,6 +830,7 @@ TEST(CCSchedulerStateMachineTest, TestGoesInvisibleBeforeBeginFrameCompletes)
StateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.setCanDraw(true);
// Start clean and set commit.
state.setNeedsCommit(true);
@ -830,6 +869,7 @@ TEST(CCSchedulerStateMachineTest, TestContextLostWhenCompletelyIdle)
StateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.setCanDraw(true);
state.didLoseContext();
@ -852,6 +892,7 @@ TEST(CCSchedulerStateMachineTest, TestContextLostWhenIdleAndCommitRequestedWhile
StateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.setCanDraw(true);
state.didLoseContext();
@ -888,6 +929,7 @@ TEST(CCSchedulerStateMachineTest, TestContextLostWhileCommitInProgress)
StateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.setCanDraw(true);
// Get a commit in flight.
state.setNeedsCommit(true);
@ -929,6 +971,7 @@ TEST(CCSchedulerStateMachineTest, TestContextLostWhileCommitInProgressAndAnother
StateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.setCanDraw(true);
// Get a commit in flight.
state.setNeedsCommit(true);
@ -979,6 +1022,7 @@ TEST(CCSchedulerStateMachineTest, TestFinishAllRenderingWhileContextLost)
{
StateMachine state;
state.setVisible(true);
state.setCanDraw(true);
// Cause a lost context lost.
state.didLoseContext();
@ -1017,6 +1061,7 @@ TEST(CCSchedulerStateMachineTest, TestBeginFrameWhenCanBeginFrameFalseAndForceCo
{
StateMachine state;
state.setVisible(true);
state.setCanDraw(true);
state.setNeedsCommit(true);
state.setNeedsForcedCommit(true);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
@ -1049,6 +1094,7 @@ TEST(CCSchedulerStateMachineTest, TestBeginFrameWhenContextLost)
StateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.setCanDraw(true);
state.setNeedsCommit(true);
state.setNeedsForcedCommit(true);
state.didLoseContext();

@ -24,14 +24,12 @@ 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()); }
@ -45,8 +43,8 @@ public:
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
{
@ -71,7 +69,6 @@ public:
protected:
bool m_hasMoreResourceUpdates;
bool m_canDraw;
bool m_drawWillHappen;
bool m_swapWillHappenIfDrawHappens;
int m_numDraws;
@ -85,6 +82,7 @@ TEST(CCSchedulerTest, RequestCommit)
OwnPtr<CCScheduler> scheduler = CCScheduler::create(&client, adoptPtr(new CCFrameRateController(timeSource)));
scheduler->setCanBeginFrame(true);
scheduler->setVisible(true);
scheduler->setCanDraw(true);
// SetNeedsCommit should begin the frame.
scheduler->setNeedsCommit();
@ -119,6 +117,7 @@ TEST(CCSchedulerTest, RequestCommitAfterBeginFrame)
OwnPtr<CCScheduler> scheduler = CCScheduler::create(&client, adoptPtr(new CCFrameRateController(timeSource)));
scheduler->setCanBeginFrame(true);
scheduler->setVisible(true);
scheduler->setCanDraw(true);
// SetNedsCommit should begin the frame.
scheduler->setNeedsCommit();
@ -152,6 +151,7 @@ TEST(CCSchedulerTest, TextureAcquisitionCollision)
OwnPtr<CCScheduler> scheduler = CCScheduler::create(&client, adoptPtr(new CCFrameRateController(timeSource)));
scheduler->setCanBeginFrame(true);
scheduler->setVisible(true);
scheduler->setCanDraw(true);
scheduler->setNeedsCommit();
scheduler->setMainThreadNeedsLayerTextures();
@ -190,6 +190,7 @@ TEST(CCSchedulerTest, VisibilitySwitchWithTextureAcquisition)
OwnPtr<CCScheduler> scheduler = CCScheduler::create(&client, adoptPtr(new CCFrameRateController(timeSource)));
scheduler->setCanBeginFrame(true);
scheduler->setVisible(true);
scheduler->setCanDraw(true);
scheduler->setNeedsCommit();
scheduler->beginFrameComplete();
@ -253,6 +254,7 @@ TEST(CCSchedulerTest, RequestRedrawInsideDraw)
client.setScheduler(scheduler.get());
scheduler->setCanBeginFrame(true);
scheduler->setVisible(true);
scheduler->setCanDraw(true);
scheduler->setNeedsRedraw();
EXPECT_TRUE(scheduler->redrawPending());
@ -279,6 +281,7 @@ TEST(CCSchedulerTest, RequestRedrawInsideFailedDraw)
client.setScheduler(scheduler.get());
scheduler->setCanBeginFrame(true);
scheduler->setVisible(true);
scheduler->setCanDraw(true);
client.setDrawWillHappen(false);
scheduler->setNeedsRedraw();
@ -351,6 +354,7 @@ TEST(CCSchedulerTest, RequestCommitInsideDraw)
client.setScheduler(scheduler.get());
scheduler->setCanBeginFrame(true);
scheduler->setVisible(true);
scheduler->setCanDraw(true);
scheduler->setNeedsRedraw();
EXPECT_TRUE(scheduler->redrawPending());
@ -378,6 +382,7 @@ TEST(CCSchedulerTest, RequestCommitInsideFailedDraw)
client.setScheduler(scheduler.get());
scheduler->setCanBeginFrame(true);
scheduler->setVisible(true);
scheduler->setCanDraw(true);
client.setDrawWillHappen(false);
scheduler->setNeedsRedraw();
@ -420,6 +425,7 @@ TEST(CCSchedulerTest, NoBeginFrameWhenDrawFails)
client.setScheduler(scheduler.get());
scheduler->setCanBeginFrame(true);
scheduler->setVisible(true);
scheduler->setCanDraw(true);
EXPECT_EQ(0, controllerPtr->numFramesPending());

@ -49,6 +49,7 @@ public:
virtual void didLoseContextOnImplThread() OVERRIDE { }
virtual void onSwapBuffersCompleteOnImplThread() OVERRIDE { ASSERT_NOT_REACHED(); }
virtual void onVSyncParametersChanged(double monotonicTimebase, double intervalInSeconds) OVERRIDE { }
virtual void onCanDrawStateChanged(bool canDraw) OVERRIDE { }
virtual void setNeedsRedrawOnImplThread() OVERRIDE { m_layerTreeHost->scheduleComposite(); }
virtual void setNeedsCommitOnImplThread() OVERRIDE { m_layerTreeHost->scheduleComposite(); }
virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>, double wallClockTime) OVERRIDE;

@ -332,6 +332,13 @@ void CCThreadProxy::onVSyncParametersChanged(double monotonicTimebase, double in
m_schedulerOnImplThread->setTimebaseAndInterval(monotonicTimebase, intervalInSeconds);
}
void CCThreadProxy::onCanDrawStateChanged(bool canDraw)
{
ASSERT(isImplThread());
TRACE_EVENT1("cc", "CCThreadProxy::onCanDrawStateChanged", "canDraw", canDraw);
m_schedulerOnImplThread->setCanDraw(canDraw);
}
void CCThreadProxy::setNeedsCommitOnImplThread()
{
ASSERT(isImplThread());
@ -522,8 +529,10 @@ void CCThreadProxy::beginFrame()
m_commitRequestSentToImplThread = false;
m_forcedCommitRequested = false;
if (!m_layerTreeHost->initializeRendererIfNeeded())
if (!m_layerTreeHost->initializeRendererIfNeeded()) {
TRACE_EVENT0("cc", "EarlyOut_InitializeFailed");
return;
}
if (request->contentsTexturesWereDeleted)
m_layerTreeHost->evictAllContentTextures();
@ -573,6 +582,7 @@ void CCThreadProxy::beginFrameCompleteOnImplThread(CCCompletionEvent* completion
ASSERT(m_schedulerOnImplThread->commitPending());
if (!m_layerTreeHostImpl) {
TRACE_EVENT0("cc", "EarlyOut_NoLayerTree");
completion->signal();
return;
}
@ -610,14 +620,6 @@ bool CCThreadProxy::hasMoreResourceUpdates() const
return m_currentTextureUpdateControllerOnImplThread->hasMoreUpdates();
}
bool CCThreadProxy::canDraw()
{
ASSERT(isImplThread());
if (!m_layerTreeHostImpl)
return false;
return m_layerTreeHostImpl->canDraw();
}
void CCThreadProxy::scheduledActionUpdateMoreResources(double monotonicTimeLimit)
{
TRACE_EVENT0("cc", "CCThreadProxy::scheduledActionUpdateMoreResources");
@ -868,8 +870,8 @@ void CCThreadProxy::initializeRendererOnImplThread(CCCompletionEvent* completion
*initializeSucceeded = m_layerTreeHostImpl->initializeRenderer(m_contextBeforeInitializationOnImplThread.release(), textureUploader);
if (*initializeSucceeded) {
*capabilities = m_layerTreeHostImpl->rendererCapabilities();
if (capabilities->usingSwapCompleteCallback)
m_schedulerOnImplThread->setMaxFramesPending(2);
m_schedulerOnImplThread->setSwapBuffersCompleteSupported(
capabilities->usingSwapCompleteCallback);
}
completion->signal();

@ -58,13 +58,14 @@ public:
virtual void didLoseContextOnImplThread() OVERRIDE;
virtual void onSwapBuffersCompleteOnImplThread() OVERRIDE;
virtual void onVSyncParametersChanged(double monotonicTimebase, double intervalInSeconds) OVERRIDE;
virtual void onCanDrawStateChanged(bool canDraw) OVERRIDE;
virtual void setNeedsRedrawOnImplThread() OVERRIDE;
virtual void setNeedsCommitOnImplThread() OVERRIDE;
virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>, double wallClockTime) OVERRIDE;
// CCSchedulerClient implementation
virtual bool canDraw() OVERRIDE;
virtual bool hasMoreResourceUpdates() const OVERRIDE;
virtual void scheduledActionBeginFrame() OVERRIDE;
virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapIfPossible() OVERRIDE;
virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapForced() OVERRIDE;

@ -16,6 +16,8 @@
#include "TextStream.h"
#include <public/WebAnimationDelegate.h>
#include <public/WebLayerScrollClient.h>
#include <public/WebSize.h>
using namespace std;
using WebKit::WebTransformationMatrix;
@ -65,7 +67,7 @@ LayerChromium::LayerChromium()
, m_screenSpaceTransformIsAnimating(false)
, m_contentsScale(1.0)
, m_layerAnimationDelegate(0)
, m_layerScrollDelegate(0)
, m_layerScrollClient(0)
{
if (m_layerId < 0) {
s_nextLayerId = 1;
@ -369,6 +371,8 @@ void LayerChromium::setScrollPosition(const IntPoint& scrollPosition)
if (m_scrollPosition == scrollPosition)
return;
m_scrollPosition = scrollPosition;
if (m_layerScrollClient)
m_layerScrollClient->didScroll();
setNeedsCommit();
}
@ -413,13 +417,6 @@ void LayerChromium::setNonFastScrollableRegion(const Region& region)
setNeedsCommit();
}
void LayerChromium::scrollBy(const IntSize& scrollDelta)
{
setScrollPosition(scrollPosition() + scrollDelta);
if (m_layerScrollDelegate)
m_layerScrollDelegate->didScroll(scrollDelta);
}
void LayerChromium::setDrawCheckerboardForMissingTiles(bool checkerboard)
{
if (m_drawCheckerboardForMissingTiles == checkerboard)

@ -28,6 +28,7 @@
namespace WebKit {
class WebAnimationDelegate;
class WebLayerScrollClient;
}
namespace WebCore {
@ -42,15 +43,6 @@ class ScrollbarLayerChromium;
struct CCAnimationEvent;
struct CCRenderingStats;
// Delegate for handling scroll input for a LayerChromium.
class LayerChromiumScrollDelegate {
public:
virtual void didScroll(const IntSize&) = 0;
protected:
virtual ~LayerChromiumScrollDelegate() { }
};
// Base class for composited layers. Special layer types are derived from
// this class.
class LayerChromium : public RefCounted<LayerChromium>, public CCLayerAnimationControllerClient {
@ -149,8 +141,7 @@ public:
const Region& nonFastScrollableRegion() { return m_nonFastScrollableRegion; }
void setNonFastScrollableRegion(const Region&);
void setNonFastScrollableRegionChanged() { m_nonFastScrollableRegionChanged = true; }
void setLayerScrollDelegate(LayerChromiumScrollDelegate* layerScrollDelegate) { m_layerScrollDelegate = layerScrollDelegate; }
void scrollBy(const IntSize&);
void setLayerScrollClient(WebKit::WebLayerScrollClient* layerScrollClient) { m_layerScrollClient = layerScrollClient; }
void setDrawCheckerboardForMissingTiles(bool);
bool drawCheckerboardForMissingTiles() const { return m_drawCheckerboardForMissingTiles; }
@ -370,7 +361,7 @@ private:
float m_contentsScale;
WebKit::WebAnimationDelegate* m_layerAnimationDelegate;
LayerChromiumScrollDelegate* m_layerScrollDelegate;
WebKit::WebLayerScrollClient* m_layerScrollClient;
};
void sortLayers(Vector<RefPtr<LayerChromium> >::iterator, Vector<RefPtr<LayerChromium> >::iterator, void*);

@ -334,6 +334,16 @@ void WebLayerImpl::setScrollPosition(WebPoint position)
m_layer->setScrollPosition(position);
}
WebPoint WebLayerImpl::scrollPosition() const
{
return m_layer->scrollPosition();
}
void WebLayerImpl::setMaxScrollPosition(WebSize maxScrollPosition)
{
m_layer->setMaxScrollPosition(maxScrollPosition);
}
void WebLayerImpl::setScrollable(bool scrollable)
{
m_layer->setScrollable(scrollable);
@ -370,6 +380,11 @@ void WebLayerImpl::setFixedToContainerLayer(bool enable)
m_layer->setFixedToContainerLayer(enable);
}
void WebLayerImpl::setScrollClient(WebLayerScrollClient* scrollClient)
{
m_layer->setLayerScrollClient(scrollClient);
}
LayerChromium* WebLayerImpl::layer() const
{
return m_layer.get();

@ -73,12 +73,15 @@ public:
virtual void transferAnimationsTo(WebLayer*) OVERRIDE;
virtual void setForceRenderSurface(bool) OVERRIDE;
virtual void setScrollPosition(WebPoint) OVERRIDE;
virtual WebPoint scrollPosition() const OVERRIDE;
virtual void setMaxScrollPosition(WebSize) OVERRIDE;
virtual void setScrollable(bool) OVERRIDE;
virtual void setHaveWheelEventHandlers(bool) OVERRIDE;
virtual void setShouldScrollOnMainThread(bool) OVERRIDE;
virtual void setNonFastScrollableRegion(const WebVector<WebRect>&) OVERRIDE;
virtual void setIsContainerForFixedPositionLayers(bool) OVERRIDE;
virtual void setFixedToContainerLayer(bool) OVERRIDE;
virtual void setScrollClient(WebLayerScrollClient*) OVERRIDE;
WebCore::LayerChromium* layer() const;

@ -14,6 +14,7 @@
#include <public/WebExternalTextureLayer.h>
#include <public/WebFloatPoint.h>
#include <public/WebFloatRect.h>
#include <public/WebLayerScrollClient.h>
#include <public/WebLayerTreeView.h>
#include <public/WebLayerTreeViewClient.h>
#include <public/WebRect.h>
@ -152,4 +153,28 @@ TEST_F(WebLayerTest, Client)
EXPECT_FALSE(contentLayer->layer()->drawsContent());
}
class MockScrollClient : public WebLayerScrollClient {
public:
MOCK_METHOD0(didScroll, void());
};
TEST_F(WebLayerTest, notifyScrollClient)
{
MockScrollClient scrollClient;
EXPECT_CALL(scrollClient, didScroll()).Times(0);
m_rootLayer->setScrollClient(&scrollClient);
Mock::VerifyAndClearExpectations(&scrollClient);
EXPECT_CALL(scrollClient, didScroll()).Times(1);
m_rootLayer->setScrollPosition(WebPoint(14, 19));
Mock::VerifyAndClearExpectations(&scrollClient);
EXPECT_CALL(scrollClient, didScroll()).Times(0);
m_rootLayer->setScrollPosition(WebPoint(14, 19));
Mock::VerifyAndClearExpectations(&scrollClient);
m_rootLayer->setScrollClient(0);
}
}