diff options
-rw-r--r-- | cc/layer_impl_unittest.cc | 2 | ||||
-rw-r--r-- | cc/layer_tree_host.cc | 31 | ||||
-rw-r--r-- | cc/layer_tree_host_impl.cc | 72 | ||||
-rw-r--r-- | cc/layer_tree_host_impl.h | 4 | ||||
-rw-r--r-- | cc/layer_tree_host_impl_unittest.cc | 3 | ||||
-rw-r--r-- | cc/picture_layer.cc | 7 | ||||
-rw-r--r-- | cc/picture_layer_impl.cc | 17 | ||||
-rw-r--r-- | cc/picture_layer_tiling.cc | 5 | ||||
-rw-r--r-- | cc/picture_layer_tiling.h | 14 | ||||
-rw-r--r-- | cc/picture_layer_tiling_set.cc | 14 | ||||
-rw-r--r-- | cc/picture_layer_tiling_set.h | 16 | ||||
-rw-r--r-- | cc/scheduler.cc | 6 | ||||
-rw-r--r-- | cc/scheduler.h | 1 | ||||
-rw-r--r-- | cc/scheduler_state_machine.cc | 26 | ||||
-rw-r--r-- | cc/scheduler_state_machine.h | 11 | ||||
-rw-r--r-- | cc/single_thread_proxy.cc | 6 | ||||
-rw-r--r-- | cc/single_thread_proxy.h | 1 | ||||
-rw-r--r-- | cc/test/fake_layer_tree_host_impl_client.h | 1 | ||||
-rw-r--r-- | cc/thread_proxy.cc | 7 | ||||
-rw-r--r-- | cc/thread_proxy.h | 1 |
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; |