summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cc/layer_impl_unittest.cc2
-rw-r--r--cc/layer_tree_host.cc31
-rw-r--r--cc/layer_tree_host_impl.cc72
-rw-r--r--cc/layer_tree_host_impl.h4
-rw-r--r--cc/layer_tree_host_impl_unittest.cc3
-rw-r--r--cc/picture_layer.cc7
-rw-r--r--cc/picture_layer_impl.cc17
-rw-r--r--cc/picture_layer_tiling.cc5
-rw-r--r--cc/picture_layer_tiling.h14
-rw-r--r--cc/picture_layer_tiling_set.cc14
-rw-r--r--cc/picture_layer_tiling_set.h16
-rw-r--r--cc/scheduler.cc6
-rw-r--r--cc/scheduler.h1
-rw-r--r--cc/scheduler_state_machine.cc26
-rw-r--r--cc/scheduler_state_machine.h11
-rw-r--r--cc/single_thread_proxy.cc6
-rw-r--r--cc/single_thread_proxy.h1
-rw-r--r--cc/test/fake_layer_tree_host_impl_client.h1
-rw-r--r--cc/thread_proxy.cc7
-rw-r--r--cc/thread_proxy.h1
20 files changed, 199 insertions, 46 deletions
diff --git a/cc/layer_impl_unittest.cc b/cc/layer_impl_unittest.cc
index a8b14cf..2cd7f6b 100644
--- a/cc/layer_impl_unittest.cc
+++ b/cc/layer_impl_unittest.cc
@@ -55,12 +55,14 @@ namespace {
#define VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(codeToTest) \
root->resetAllChangeTrackingForSubtree(); \
hostImpl.forcePrepareToDraw(); \
+ EXPECT_FALSE(hostImpl.needsUpdateDrawProperties()); \
codeToTest; \
EXPECT_TRUE(hostImpl.needsUpdateDrawProperties());
#define VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(codeToTest) \
root->resetAllChangeTrackingForSubtree(); \
hostImpl.forcePrepareToDraw(); \
+ EXPECT_FALSE(hostImpl.needsUpdateDrawProperties()); \
codeToTest; \
EXPECT_FALSE(hostImpl.needsUpdateDrawProperties());
diff --git a/cc/layer_tree_host.cc b/cc/layer_tree_host.cc
index 3ec9c82..4a228f4 100644
--- a/cc/layer_tree_host.cc
+++ b/cc/layer_tree_host.cc
@@ -281,20 +281,39 @@ void LayerTreeHost::finishCommitOnImplThread(LayerTreeHostImpl* hostImpl)
m_contentsTextureManager->updateBackingsInDrawingImplTree();
m_contentsTextureManager->reduceMemory(hostImpl->resourceProvider());
- if (m_needsFullTreeSync) {
- hostImpl->setRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), hostImpl->detachLayerTree(), hostImpl->activeTree()));
+ // In impl-side painting, synchronize to the pending tree so that it has
+ // time to raster before being displayed. If no pending tree is needed,
+ // synchronization can happen directly to the active tree.
+ LayerTreeImpl* syncTree;
+ bool needsFullTreeSync = false;
+ if (m_settings.implSidePainting) {
+ // Commits should not occur while there is already a pending tree.
+ DCHECK(!hostImpl->pendingTree());
+ hostImpl->createPendingTree();
+ syncTree = hostImpl->pendingTree();
+ // TODO(enne): we could recycle old active trees and keep track for
+ // multiple main thread frames whether a sync is needed
+ needsFullTreeSync = true;
+ } else {
+ syncTree = hostImpl->activeTree();
+ needsFullTreeSync = m_needsFullTreeSync;
+ }
+
+ if (needsFullTreeSync) {
+ syncTree->SetRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), syncTree->DetachLayerTree(), syncTree));
} else {
TRACE_EVENT0("cc", "LayerTreeHost::pushPropertiesRecursive");
- pushPropertiesRecursive(rootLayer(), hostImpl->rootLayer());
+ pushPropertiesRecursive(rootLayer(), syncTree->RootLayer());
}
m_needsFullTreeSync = false;
if (m_rootLayer && m_hudLayer)
- hostImpl->activeTree()->set_hud_layer(static_cast<HeadsUpDisplayLayerImpl*>(LayerTreeHostCommon::findLayerInSubtree(hostImpl->rootLayer(), m_hudLayer->id())));
+ syncTree->set_hud_layer(static_cast<HeadsUpDisplayLayerImpl*>(LayerTreeHostCommon::findLayerInSubtree(syncTree->RootLayer(), m_hudLayer->id())));
else
- hostImpl->activeTree()->set_hud_layer(0);
+ syncTree->set_hud_layer(0);
- hostImpl->activeTree()->set_source_frame_number(commitNumber());
+ // TODO(enne): Do these need to be moved to layer tree as well?
+ syncTree->set_source_frame_number(commitNumber());
hostImpl->setViewportSize(layoutViewportSize(), deviceViewportSize());
hostImpl->setDeviceScaleFactor(deviceScaleFactor());
hostImpl->setPageScaleFactorAndLimits(m_pageScaleFactor, m_minPageScaleFactor, m_maxPageScaleFactor);
diff --git a/cc/layer_tree_host_impl.cc b/cc/layer_tree_host_impl.cc
index 907bf1b..d58600a 100644
--- a/cc/layer_tree_host_impl.cc
+++ b/cc/layer_tree_host_impl.cc
@@ -237,8 +237,7 @@ LayerTreeHostImpl::LayerTreeHostImpl(const LayerTreeSettings& settings, LayerTre
DCHECK(m_proxy->isImplThread());
didVisibilityChange(this, m_visible);
- // TODO(nduca): For now, assume we have an active tree. This will be removed
- // in future patches.
+ // LTHI always has an active tree.
m_activeTree = LayerTreeImpl::create(this);
}
@@ -284,6 +283,14 @@ bool LayerTreeHostImpl::canDraw()
// affect the result of canDraw, make sure to call m_client->onCanDrawStateChanged
// in the proper places and update the notifyIfCanDrawChanged test.
+ // TODO(enne): Since prepareToDraw is the only place that currently does
+ // tree activiation, this allows prepareToDraw to be entered even if the
+ // active tree can't draw. This could cause flashing, though. This should
+ // probably be refactored such that the scheduler handles the tree
+ // activation rather than prepareToDrwa.
+ if (pendingTree())
+ return true;
+
if (!rootLayer()) {
TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw no root layer");
return false;
@@ -413,6 +420,16 @@ void LayerTreeHostImpl::updateDrawProperties()
float pageScaleFactor = m_pinchZoomViewport.pageScaleFactor();
LayerTreeHostCommon::calculateDrawProperties(rootLayer(), deviceViewportSize(), m_deviceScaleFactor, pageScaleFactor, rendererCapabilities().maxTextureSize, m_settings.canUseLCDText, m_renderSurfaceLayerList);
}
+
+ // TODO(nduca): Move this to LayerTreeImpl
+ // Note: pending tree calcDrawProperties must follow the active tree one,
+ // as some properties are synced from active -> pending.
+ if (pendingTree() && pendingTree()->RootLayer())
+ {
+ float pageScaleFactor = m_pinchZoomViewport.pageScaleFactor();
+ LayerList dummyList;
+ LayerTreeHostCommon::calculateDrawProperties(pendingTree()->RootLayer(), deviceViewportSize(), m_deviceScaleFactor, pageScaleFactor, rendererCapabilities().maxTextureSize, m_settings.canUseLCDText, dummyList);
+ }
}
void LayerTreeHostImpl::FrameData::appendRenderPass(scoped_ptr<RenderPass> renderPass)
@@ -512,7 +529,7 @@ bool LayerTreeHostImpl::calculateRenderPasses(FrameData& frame)
DCHECK(frame.renderPasses.empty());
updateDrawProperties();
- if (!canDraw())
+ if (!canDraw() || !rootLayer())
return false;
trackDamageForAllSurfaces(rootLayer(), *frame.renderSurfaceLayerList);
@@ -561,7 +578,7 @@ bool LayerTreeHostImpl::calculateRenderPasses(FrameData& frame)
if (occlusionTracker.occluded(it->renderTarget(), it->visibleContentRect(), it->drawTransform(), implDrawTransformIsUnknown, it->drawableContentRect(), &hasOcclusionFromOutsideTargetSurface))
appendQuadsData.hadOcclusionFromOutsideTargetSurface |= hasOcclusionFromOutsideTargetSurface;
else {
- DCHECK_EQ(this->activeTree(), it->layerTreeImpl());
+ DCHECK_EQ(activeTree(), it->layerTreeImpl());
it->willDraw(m_resourceProvider.get());
frame.willDrawLayers.push_back(*it);
@@ -752,6 +769,8 @@ bool LayerTreeHostImpl::prepareToDraw(FrameData& frame)
if (m_tileManager)
m_tileManager->CheckForCompletedSetPixels();
+ activatePendingTreeIfNeeded();
+
frame.renderSurfaceLayerList = &m_renderSurfaceLayerList;
frame.renderPasses.clear();
frame.renderPassesById.clear();
@@ -1000,6 +1019,51 @@ void LayerTreeHostImpl::setRootLayer(scoped_ptr<LayerImpl> layer)
setNeedsUpdateDrawProperties();
}
+void LayerTreeHostImpl::createPendingTree()
+{
+ CHECK(!m_pendingTree);
+ m_pendingTree = LayerTreeImpl::create(this);
+ m_client->onCanDrawStateChanged(canDraw());
+ m_client->onHasPendingTreeStateChanged(pendingTree());
+}
+
+void LayerTreeHostImpl::activatePendingTreeIfNeeded()
+{
+ if (!pendingTree())
+ return;
+
+ int total_pending = m_tileManager->GetTilesInBinCount(NOW_BIN, PENDING_TREE);
+ int total_active = m_tileManager->GetTilesInBinCount(NOW_BIN, ACTIVE_TREE);
+ int drawable_pending = m_tileManager->GetDrawableTilesInBinCount(NOW_BIN, PENDING_TREE);
+ int drawable_active = m_tileManager->GetDrawableTilesInBinCount(NOW_BIN, ACTIVE_TREE);
+
+ if (total_pending && total_active) {
+ float percent_pending = drawable_pending / static_cast<float>(total_pending);
+ float percent_active = drawable_active / static_cast<float>(total_active);
+ if (percent_pending < percent_active)
+ return;
+ }
+
+ // If there are no pending total tiles (i.e. an empty tree), we should
+ // commit immediately. Similarly, if there are no active tree tiles.
+ activatePendingTree();
+}
+
+void LayerTreeHostImpl::activatePendingTree()
+{
+ CHECK(m_pendingTree);
+ m_activeTree.swap(m_pendingTree);
+ // TODO(enne): consider recycling this tree to prevent layer churn
+ m_pendingTree.reset();
+ m_client->onCanDrawStateChanged(canDraw());
+ m_client->onHasPendingTreeStateChanged(pendingTree());
+
+ // TODO(nduca): Once render surface layer list moves to the tree so
+ // that updateDrawProperties() affects both trees, this will be
+ // unnecessary.
+ setNeedsUpdateDrawProperties();
+}
+
scoped_ptr<LayerImpl> LayerTreeHostImpl::detachLayerTree()
{
scoped_ptr<LayerImpl> layer = m_activeTree->DetachLayerTree();
diff --git a/cc/layer_tree_host_impl.h b/cc/layer_tree_host_impl.h
index d56a550..f9d69a8 100644
--- a/cc/layer_tree_host_impl.h
+++ b/cc/layer_tree_host_impl.h
@@ -42,6 +42,7 @@ public:
virtual void onSwapBuffersCompleteOnImplThread() = 0;
virtual void onVSyncParametersChanged(base::TimeTicks timebase, base::TimeDelta interval) = 0;
virtual void onCanDrawStateChanged(bool canDraw) = 0;
+ virtual void onHasPendingTreeStateChanged(bool hasPendingTree) = 0;
virtual void setNeedsRedrawOnImplThread() = 0;
virtual void setNeedsCommitOnImplThread() = 0;
virtual void setNeedsManageTilesOnImplThread() = 0;
@@ -208,6 +209,8 @@ public:
LayerTreeImpl* activeTree() { return m_activeTree.get(); }
LayerTreeImpl* pendingTree() { return m_pendingTree.get(); }
+ void createPendingTree();
+ void activatePendingTreeIfNeeded();
// TODO(nduca): Remove these in favor of LayerTreeImpl.
void setRootLayer(scoped_ptr<LayerImpl>);
@@ -308,6 +311,7 @@ public:
protected:
LayerTreeHostImpl(const LayerTreeSettings&, LayerTreeHostImplClient*, Proxy*);
+ void activatePendingTree();
// Virtual for testing.
virtual void animateLayers(base::TimeTicks monotonicTime, base::Time wallClockTime);
diff --git a/cc/layer_tree_host_impl_unittest.cc b/cc/layer_tree_host_impl_unittest.cc
index 876847b..92c4371 100644
--- a/cc/layer_tree_host_impl_unittest.cc
+++ b/cc/layer_tree_host_impl_unittest.cc
@@ -66,6 +66,7 @@ public:
, m_alwaysImplThread(&m_proxy)
, m_alwaysMainThreadBlocked(&m_proxy)
, m_onCanDrawStateChangedCalled(false)
+ , m_hasPendingTree(false)
, m_didRequestCommit(false)
, m_didRequestRedraw(false)
, m_reduceMemoryResult(true)
@@ -92,6 +93,7 @@ public:
virtual void onSwapBuffersCompleteOnImplThread() OVERRIDE { }
virtual void onVSyncParametersChanged(base::TimeTicks, base::TimeDelta) OVERRIDE { }
virtual void onCanDrawStateChanged(bool canDraw) OVERRIDE { m_onCanDrawStateChangedCalled = true; }
+ virtual void onHasPendingTreeStateChanged(bool hasPendingTree) OVERRIDE { m_hasPendingTree = hasPendingTree; }
virtual void setNeedsRedrawOnImplThread() OVERRIDE { m_didRequestRedraw = true; }
virtual void setNeedsCommitOnImplThread() OVERRIDE { m_didRequestCommit = true; }
virtual void setNeedsManageTilesOnImplThread() OVERRIDE { }
@@ -219,6 +221,7 @@ protected:
scoped_ptr<LayerTreeHostImpl> m_hostImpl;
bool m_onCanDrawStateChangedCalled;
+ bool m_hasPendingTree;
bool m_didRequestCommit;
bool m_didRequestRedraw;
bool m_reduceMemoryResult;
diff --git a/cc/picture_layer.cc b/cc/picture_layer.cc
index b1fe87c..241aff4 100644
--- a/cc/picture_layer.cc
+++ b/cc/picture_layer.cc
@@ -38,13 +38,6 @@ void PictureLayer::pushPropertiesTo(LayerImpl* base_layer) {
layer_impl->invalidation_.Swap(pile_invalidation_);
pile_.PushPropertiesTo(layer_impl->pile_);
- // TODO(enne): Remove this once syncing happens to the pending tree rather
- // than the active one.
- if (layer_impl->layerTreeImpl()->IsActiveTree()) {
- layer_impl->tilings_.Invalidate(layer_impl->invalidation_);
- return;
- }
-
layer_impl->SyncFromActiveLayer();
}
diff --git a/cc/picture_layer_impl.cc b/cc/picture_layer_impl.cc
index e844f67..245ade0 100644
--- a/cc/picture_layer_impl.cc
+++ b/cc/picture_layer_impl.cc
@@ -151,12 +151,15 @@ void PictureLayerImpl::didUpdateTransforms() {
last_content_scale_y_ == contentsScaleY()) {
time_delta = current_time - last_update_time_;
}
- tilings_.UpdateTilePriorities(layerTreeImpl()->device_viewport_size(),
- contentsScaleX(),
- contentsScaleY(),
- last_screen_space_transform_,
- current_screen_space_transform,
- time_delta);
+ WhichTree tree = layerTreeImpl()->IsActiveTree() ? ACTIVE_TREE : PENDING_TREE;
+ tilings_.UpdateTilePriorities(
+ tree,
+ layerTreeImpl()->device_viewport_size(),
+ contentsScaleX(),
+ contentsScaleY(),
+ last_screen_space_transform_,
+ current_screen_space_transform,
+ time_delta);
last_screen_space_transform_ = current_screen_space_transform;
last_update_time_ = current_time;
@@ -214,7 +217,7 @@ void PictureLayerImpl::AddTiling(float contents_scale, gfx::Size tile_size) {
// If a new tiling is created on the active tree, sync it to the pending tree
// so that it can share the same tiles.
- if (layerTreeImpl()->IsActiveTree())
+ if (layerTreeImpl()->IsPendingTree())
return;
PictureLayerImpl* pending_twin = static_cast<PictureLayerImpl*>(
diff --git a/cc/picture_layer_tiling.cc b/cc/picture_layer_tiling.cc
index de3717c..62a39b3 100644
--- a/cc/picture_layer_tiling.cc
+++ b/cc/picture_layer_tiling.cc
@@ -269,6 +269,7 @@ gfx::Size PictureLayerTiling::Iterator::texture_size() const {
}
void PictureLayerTiling::UpdateTilePriorities(
+ WhichTree tree,
const gfx::Size& device_viewport,
float layer_content_scale_x,
float layer_content_scale_y,
@@ -290,7 +291,7 @@ void PictureLayerTiling::UpdateTilePriorities(
priority.time_to_visible_in_seconds =
TilePriority::kMaxTimeToVisibleInSeconds;
// TODO(qinmin): pass the correct tree to this function.
- it->second->set_priority(ACTIVE_TREE, priority);
+ it->second->set_priority(tree, priority);
continue;
}
@@ -312,7 +313,7 @@ void PictureLayerTiling::UpdateTilePriorities(
priority.distance_to_visible_in_pixels =
TilePriority::manhattanDistance(screen_rect, view_rect);
// TODO(qinmin): pass the correct tree to this function.
- it->second->set_priority(ACTIVE_TREE, priority);
+ it->second->set_priority(tree, priority);
}
}
diff --git a/cc/picture_layer_tiling.h b/cc/picture_layer_tiling.h
index 5d46c2f..b6c7b7d 100644
--- a/cc/picture_layer_tiling.h
+++ b/cc/picture_layer_tiling.h
@@ -86,12 +86,14 @@ class CC_EXPORT PictureLayerTiling {
void Reset() { return tiles_.clear(); }
- void UpdateTilePriorities(const gfx::Size& device_viewport,
- float layer_content_scale_x,
- float layer_content_scale_y,
- const gfx::Transform& last_screen_transform,
- const gfx::Transform& current_screen_transform,
- double time_delta);
+ void UpdateTilePriorities(
+ WhichTree tree,
+ const gfx::Size& device_viewport,
+ float layer_content_scale_x,
+ float layer_content_scale_y,
+ const gfx::Transform& last_screen_transform,
+ const gfx::Transform& current_screen_transform,
+ double time_delta);
protected:
typedef std::pair<int, int> TileMapKey;
diff --git a/cc/picture_layer_tiling_set.cc b/cc/picture_layer_tiling_set.cc
index e2ccc29..b0744b8 100644
--- a/cc/picture_layer_tiling_set.cc
+++ b/cc/picture_layer_tiling_set.cc
@@ -17,11 +17,12 @@ PictureLayerTilingSet::~PictureLayerTilingSet() {
void PictureLayerTilingSet::CloneAll(
const PictureLayerTilingSet& other,
const Region& invalidation) {
- layer_bounds_ = other.layer_bounds_;
tilings_.clear();
tilings_.reserve(other.tilings_.size());
for (size_t i = 0; i < other.tilings_.size(); ++i) {
tilings_.append(other.tilings_[i]->Clone());
+ tilings_.last()->SetLayerBounds(LayerBounds());
+ tilings_.last()->SetClient(client_);
tilings_.last()->Invalidate(invalidation);
}
}
@@ -34,6 +35,7 @@ void PictureLayerTilingSet::Clone(
DCHECK_NE(tilings_[i]->contents_scale(), tiling->contents_scale());
tilings_.append(tiling->Clone());
+ tilings_.last()->SetClient(client_);
tilings_.last()->Invalidate(invalidation);
}
@@ -181,6 +183,7 @@ PictureLayerTilingSet::Iterator::operator bool() const {
}
void PictureLayerTilingSet::UpdateTilePriorities(
+ WhichTree tree,
const gfx::Size& device_viewport,
float layer_content_scale_x,
float layer_content_scale_y,
@@ -189,8 +192,13 @@ void PictureLayerTilingSet::UpdateTilePriorities(
double time_delta) {
for (size_t i = 0; i < tilings_.size(); ++i) {
tilings_[i]->UpdateTilePriorities(
- device_viewport, layer_content_scale_x, layer_content_scale_y,
- last_screen_transform, current_screen_transform, time_delta);
+ tree,
+ device_viewport,
+ layer_content_scale_x,
+ layer_content_scale_y,
+ last_screen_transform,
+ current_screen_transform,
+ time_delta);
}
}
diff --git a/cc/picture_layer_tiling_set.h b/cc/picture_layer_tiling_set.h
index 29ad92f..55bf71e 100644
--- a/cc/picture_layer_tiling_set.h
+++ b/cc/picture_layer_tiling_set.h
@@ -17,7 +17,7 @@ class CC_EXPORT PictureLayerTilingSet {
PictureLayerTilingSet(PictureLayerTilingClient* client);
~PictureLayerTilingSet();
- // Shallow copies all data (except client) from other.
+ // Shallow copies all data (except client and bounds from other).
void CloneAll(
const PictureLayerTilingSet& other,
const Region& invalidation);
@@ -36,12 +36,14 @@ class CC_EXPORT PictureLayerTilingSet {
void Reset();
- void UpdateTilePriorities(const gfx::Size& device_viewport,
- float layer_content_scale_x,
- float layer_content_scale_y,
- const gfx::Transform& last_screen_transform,
- const gfx::Transform& current_screen_transform,
- double time_delta);
+ void UpdateTilePriorities(
+ WhichTree tree,
+ const gfx::Size& device_viewport,
+ float layer_content_scale_x,
+ float layer_content_scale_y,
+ const gfx::Transform& last_screen_transform,
+ const gfx::Transform& current_screen_transform,
+ double time_delta);
// For a given rect, iterates through tiles that can fill it. If no
// set of tiles with resources can fill the rect, then it will iterate
diff --git a/cc/scheduler.cc b/cc/scheduler.cc
index 099708a..630d25b 100644
--- a/cc/scheduler.cc
+++ b/cc/scheduler.cc
@@ -43,6 +43,12 @@ void Scheduler::setCanDraw(bool canDraw)
processScheduledActions();
}
+void Scheduler::setHasPendingTree(bool hasPendingTree)
+{
+ m_stateMachine.setHasPendingTree(hasPendingTree);
+ processScheduledActions();
+}
+
void Scheduler::setNeedsCommit()
{
m_stateMachine.setNeedsCommit();
diff --git a/cc/scheduler.h b/cc/scheduler.h
index 9beffc5..93cd100 100644
--- a/cc/scheduler.h
+++ b/cc/scheduler.h
@@ -59,6 +59,7 @@ public:
void setVisible(bool);
void setCanDraw(bool);
+ void setHasPendingTree(bool);
void setNeedsCommit();
diff --git a/cc/scheduler_state_machine.cc b/cc/scheduler_state_machine.cc
index 143efb3..c4087e78 100644
--- a/cc/scheduler_state_machine.cc
+++ b/cc/scheduler_state_machine.cc
@@ -26,6 +26,7 @@ SchedulerStateMachine::SchedulerStateMachine()
, m_visible(false)
, m_canBeginFrame(false)
, m_canDraw(false)
+ , m_hasPendingTree(false)
, m_drawIfPossibleFailed(false)
, m_textureState(LAYER_TEXTURE_STATE_UNLOCKED)
, m_outputSurfaceState(OUTPUT_SURFACE_ACTIVE)
@@ -52,6 +53,7 @@ std::string SchedulerStateMachine::toString()
base::StringAppendF(&str, "m_canBeginFrame = %d; ", m_canBeginFrame);
base::StringAppendF(&str, "m_canDraw = %d; ", m_canDraw);
base::StringAppendF(&str, "m_drawIfPossibleFailed = %d; ", m_drawIfPossibleFailed);
+ base::StringAppendF(&str, "m_hasPendingTree = %d; ", m_hasPendingTree);
base::StringAppendF(&str, "m_textureState = %d; ", m_textureState);
base::StringAppendF(&str, "m_outputSurfaceState = %d; ", m_outputSurfaceState);
return str;
@@ -123,7 +125,8 @@ SchedulerStateMachine::Action SchedulerStateMachine::nextAction() const
if (m_outputSurfaceState != OUTPUT_SURFACE_ACTIVE && m_needsForcedRedraw)
return ACTION_DRAW_FORCED;
if (m_outputSurfaceState != OUTPUT_SURFACE_ACTIVE && m_needsForcedCommit)
- return ACTION_BEGIN_FRAME;
+ // TODO(enne): Should probably drop the active tree on force commit
+ return m_hasPendingTree ? ACTION_NONE : ACTION_BEGIN_FRAME;
if (m_outputSurfaceState == OUTPUT_SURFACE_LOST)
return ACTION_BEGIN_OUTPUT_SURFACE_RECREATION;
if (m_outputSurfaceState == OUTPUT_SURFACE_RECREATING)
@@ -131,7 +134,8 @@ SchedulerStateMachine::Action SchedulerStateMachine::nextAction() const
if (shouldDraw())
return m_needsForcedRedraw ? ACTION_DRAW_FORCED : ACTION_DRAW_IF_POSSIBLE;
if (m_needsCommit && ((m_visible && m_canBeginFrame) || m_needsForcedCommit))
- return ACTION_BEGIN_FRAME;
+ // TODO(enne): Should probably drop the active tree on force commit
+ return m_hasPendingTree ? ACTION_NONE : ACTION_BEGIN_FRAME;
return ACTION_NONE;
case COMMIT_STATE_FRAME_IN_PROGRESS:
@@ -149,7 +153,7 @@ SchedulerStateMachine::Action SchedulerStateMachine::nextAction() const
// or textures are not available, proceed to the next step (similar as in COMMIT_STATE_IDLE).
bool canCommit = m_visible || m_needsForcedCommit;
if (m_needsCommit && canCommit && drawSuspendedUntilCommit())
- return ACTION_BEGIN_FRAME;
+ return m_hasPendingTree ? ACTION_NONE : ACTION_BEGIN_FRAME;
return ACTION_NONE;
}
@@ -169,6 +173,7 @@ void SchedulerStateMachine::updateState(Action action)
return;
case ACTION_BEGIN_FRAME:
+ DCHECK(!m_hasPendingTree);
DCHECK(m_visible || m_needsForcedCommit);
m_commitState = COMMIT_STATE_FRAME_IN_PROGRESS;
m_needsCommit = false;
@@ -233,6 +238,11 @@ void SchedulerStateMachine::setMainThreadNeedsLayerTextures()
bool SchedulerStateMachine::vsyncCallbackNeeded() const
{
+ // If we have a pending tree, need to keep getting notifications until
+ // the tree is ready to be swapped.
+ if (m_hasPendingTree)
+ return true;
+
// If we can't draw, don't tick until we are notified that we can draw again.
if (!m_canDraw)
return false;
@@ -322,6 +332,16 @@ void SchedulerStateMachine::didLoseOutputSurface()
m_outputSurfaceState = OUTPUT_SURFACE_LOST;
}
+void SchedulerStateMachine::setHasPendingTree(bool hasPendingTree)
+{
+ m_hasPendingTree = hasPendingTree;
+}
+
+void SchedulerStateMachine::setCanDraw(bool can)
+{
+ m_canDraw = can;
+}
+
void SchedulerStateMachine::didRecreateOutputSurface()
{
DCHECK(m_outputSurfaceState == OUTPUT_SURFACE_RECREATING);
diff --git a/cc/scheduler_state_machine.h b/cc/scheduler_state_machine.h
index 1c39058..10df4df 100644
--- a/cc/scheduler_state_machine.h
+++ b/cc/scheduler_state_machine.h
@@ -120,7 +120,15 @@ public:
// Indicates whether drawing would, at this time, make sense.
// canDraw can be used to supress flashes or checkerboarding
// when such behavior would be undesirable.
- void setCanDraw(bool can) { m_canDraw = can; }
+ void setCanDraw(bool can);
+
+ // Indicates whether or not there is a pending tree. This influences
+ // whether or not we can succesfully commit at this time. If the
+ // last commit is still being processed (but not blocking), it may not
+ // be possible to take another commit yet. This overrides force commit,
+ // as a commit is already still in flight.
+ void setHasPendingTree(bool hasPendingTree);
+ bool hasPendingTree() const { return m_hasPendingTree; }
void didLoseOutputSurface();
void didRecreateOutputSurface();
@@ -155,6 +163,7 @@ protected:
bool m_visible;
bool m_canBeginFrame;
bool m_canDraw;
+ bool m_hasPendingTree;
bool m_drawIfPossibleFailed;
TextureState m_textureState;
OutputSurfaceState m_outputSurfaceState;
diff --git a/cc/single_thread_proxy.cc b/cc/single_thread_proxy.cc
index 296bbf4..c4c63bf 100644
--- a/cc/single_thread_proxy.cc
+++ b/cc/single_thread_proxy.cc
@@ -230,6 +230,12 @@ void SingleThreadProxy::setNeedsRedraw()
setNeedsCommit();
}
+void SingleThreadProxy::onHasPendingTreeStateChanged(bool havePendingTree)
+{
+ // Thread-only feature.
+ NOTREACHED();
+}
+
void SingleThreadProxy::setDeferCommits(bool deferCommits)
{
// Thread-only feature.
diff --git a/cc/single_thread_proxy.h b/cc/single_thread_proxy.h
index 40f2b1b..6be5e97 100644
--- a/cc/single_thread_proxy.h
+++ b/cc/single_thread_proxy.h
@@ -52,6 +52,7 @@ public:
virtual void onSwapBuffersCompleteOnImplThread() OVERRIDE;
virtual void onVSyncParametersChanged(base::TimeTicks timebase, base::TimeDelta interval) OVERRIDE { }
virtual void onCanDrawStateChanged(bool canDraw) OVERRIDE { }
+ virtual void onHasPendingTreeStateChanged(bool havePendingTree) OVERRIDE;
virtual void setNeedsRedrawOnImplThread() OVERRIDE;
virtual void setNeedsCommitOnImplThread() OVERRIDE;
virtual void setNeedsManageTilesOnImplThread() OVERRIDE;
diff --git a/cc/test/fake_layer_tree_host_impl_client.h b/cc/test/fake_layer_tree_host_impl_client.h
index fdeb7ea..be6be66 100644
--- a/cc/test/fake_layer_tree_host_impl_client.h
+++ b/cc/test/fake_layer_tree_host_impl_client.h
@@ -18,6 +18,7 @@ class FakeLayerTreeHostImplClient : public LayerTreeHostImplClient {
base::TimeTicks,
base::TimeDelta) OVERRIDE { }
virtual void onCanDrawStateChanged(bool) OVERRIDE { }
+ virtual void onHasPendingTreeStateChanged(bool) OVERRIDE { }
virtual void setNeedsRedrawOnImplThread() OVERRIDE { }
virtual void setNeedsCommitOnImplThread() OVERRIDE { }
virtual void setNeedsManageTilesOnImplThread() OVERRIDE { }
diff --git a/cc/thread_proxy.cc b/cc/thread_proxy.cc
index e759bcf..38ad4a1 100644
--- a/cc/thread_proxy.cc
+++ b/cc/thread_proxy.cc
@@ -327,6 +327,13 @@ void ThreadProxy::onCanDrawStateChanged(bool canDraw)
m_schedulerOnImplThread->setCanDraw(canDraw);
}
+void ThreadProxy::onHasPendingTreeStateChanged(bool hasPendingTree)
+{
+ DCHECK(isImplThread());
+ TRACE_EVENT1("cc", "ThreadProxy::onHasPendingTreeStateChanged", "hasPendingTree", hasPendingTree);
+ m_schedulerOnImplThread->setHasPendingTree(hasPendingTree);
+}
+
void ThreadProxy::setNeedsCommitOnImplThread()
{
DCHECK(isImplThread());
diff --git a/cc/thread_proxy.h b/cc/thread_proxy.h
index 8c8feea..5320ee2 100644
--- a/cc/thread_proxy.h
+++ b/cc/thread_proxy.h
@@ -61,6 +61,7 @@ public:
virtual void onSwapBuffersCompleteOnImplThread() OVERRIDE;
virtual void onVSyncParametersChanged(base::TimeTicks timebase, base::TimeDelta interval) OVERRIDE;
virtual void onCanDrawStateChanged(bool canDraw) OVERRIDE;
+ virtual void onHasPendingTreeStateChanged(bool hasPendingTree) OVERRIDE;
virtual void setNeedsRedrawOnImplThread() OVERRIDE;
virtual void setNeedsCommitOnImplThread() OVERRIDE;
virtual void setNeedsManageTilesOnImplThread() OVERRIDE;