Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2011 The Chromium Authors. All rights reserved. | 1 // Copyright 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "cc/layer_tree_host_impl.h" | 5 #include "cc/layer_tree_host_impl.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 43 #include "cc/solid_color_draw_quad.h" | 43 #include "cc/solid_color_draw_quad.h" |
| 44 #include "cc/texture_uploader.h" | 44 #include "cc/texture_uploader.h" |
| 45 #include "cc/top_controls_manager.h" | 45 #include "cc/top_controls_manager.h" |
| 46 #include "cc/tree_synchronizer.h" | 46 #include "cc/tree_synchronizer.h" |
| 47 #include "cc/util.h" | 47 #include "cc/util.h" |
| 48 #include "ui/gfx/size_conversions.h" | 48 #include "ui/gfx/size_conversions.h" |
| 49 #include "ui/gfx/vector2d_conversions.h" | 49 #include "ui/gfx/vector2d_conversions.h" |
| 50 | 50 |
| 51 namespace { | 51 namespace { |
| 52 | 52 |
| 53 void didVisibilityChange(cc::LayerTreeHostImpl* id, bool visible) | 53 void DidVisibilityChange(cc::LayerTreeHostImpl* id, bool visible) { |
| 54 { | 54 if (visible) { |
| 55 if (visible) { | 55 TRACE_EVENT_ASYNC_BEGIN1("webkit", |
| 56 TRACE_EVENT_ASYNC_BEGIN1("webkit", "LayerTreeHostImpl::setVisible", id, "LayerTreeHostImpl", id); | 56 "LayerTreeHostImpl::setVisible", |
| 57 return; | 57 id, |
| 58 "LayerTreeHostImpl", | |
| 59 id); | |
| 60 return; | |
| 61 } | |
| 62 | |
| 63 TRACE_EVENT_ASYNC_END0("webkit", "LayerTreeHostImpl::setVisible", id); | |
| 64 } | |
| 65 | |
| 66 std::string ValueToString(scoped_ptr<base::Value> value) { | |
| 67 std::string str; | |
| 68 base::JSONWriter::Write(value.get(), &str); | |
| 69 return str; | |
| 70 } | |
| 71 | |
| 72 } // namespace | |
| 73 | |
| 74 namespace cc { | |
| 75 | |
| 76 class LayerTreeHostImplTimeSourceAdapter : public TimeSourceClient { | |
| 77 public: | |
| 78 static scoped_ptr<LayerTreeHostImplTimeSourceAdapter> Create( | |
| 79 LayerTreeHostImpl* layer_tree_host_impl, | |
| 80 scoped_refptr<DelayBasedTimeSource> time_source) { | |
| 81 return make_scoped_ptr( | |
| 82 new LayerTreeHostImplTimeSourceAdapter(layer_tree_host_impl, | |
| 83 time_source)); | |
| 84 } | |
| 85 virtual ~LayerTreeHostImplTimeSourceAdapter() { | |
| 86 time_source_->setClient(NULL); | |
| 87 time_source_->setActive(false); | |
| 88 } | |
| 89 | |
| 90 virtual void onTimerTick() OVERRIDE { | |
| 91 // In single threaded mode we attempt to simulate changing the current | |
| 92 // thread by maintaining a fake thread id. When we switch from one | |
| 93 // thread to another, we construct DebugScopedSetXXXThread objects that | |
| 94 // update the thread id. This lets DCHECKS that ensure we're on the | |
| 95 // right thread to work correctly in single threaded mode. The problem | |
| 96 // here is that the timer tasks are run via the message loop, and when | |
| 97 // they run, we've had no chance to construct a DebugScopedSetXXXThread | |
| 98 // object. The result is that we report that we're running on the main | |
| 99 // thread. In multi-threaded mode, this timer is run on the compositor | |
| 100 // thread, so to keep this consistent in single-threaded mode, we'll | |
| 101 // construct a DebugScopedSetImplThread object. There is no need to do | |
| 102 // this in multi-threaded mode since the real thread id's will be | |
| 103 // correct. In fact, setting fake thread id's interferes with the real | |
| 104 // thread id's and causes breakage. | |
| 105 scoped_ptr<DebugScopedSetImplThread> set_impl_thread; | |
| 106 if (!layer_tree_host_impl_->proxy()->HasImplThread()) { | |
| 107 set_impl_thread.reset( | |
| 108 new DebugScopedSetImplThread(layer_tree_host_impl_->proxy())); | |
| 58 } | 109 } |
| 59 | 110 |
| 60 TRACE_EVENT_ASYNC_END0("webkit", "LayerTreeHostImpl::setVisible", id); | 111 layer_tree_host_impl_->ActivatePendingTreeIfNeeded(); |
| 61 } | 112 layer_tree_host_impl_->Animate(base::TimeTicks::Now(), base::Time::Now()); |
| 62 | 113 layer_tree_host_impl_->BeginNextFrame(); |
| 63 std::string ValueToString(scoped_ptr<base::Value> value) | 114 } |
| 64 { | 115 |
| 65 std::string str; | 116 void SetActive(bool active) { |
| 66 base::JSONWriter::Write(value.get(), &str); | 117 if (active != time_source_->active()) |
| 67 return str; | 118 time_source_->setActive(active); |
| 68 } | 119 } |
| 69 | 120 |
| 70 } // namespace | 121 private: |
| 71 | 122 LayerTreeHostImplTimeSourceAdapter( |
| 72 namespace cc { | 123 LayerTreeHostImpl* layer_tree_host_impl, |
| 73 | 124 scoped_refptr<DelayBasedTimeSource> time_source) |
| 74 class LayerTreeHostImplTimeSourceAdapter : public TimeSourceClient { | 125 : layer_tree_host_impl_(layer_tree_host_impl), |
| 75 public: | 126 time_source_(time_source) { |
| 76 static scoped_ptr<LayerTreeHostImplTimeSourceAdapter> Create(LayerTreeHostIm pl* layerTreeHostImpl, scoped_refptr<DelayBasedTimeSource> timeSource) | 127 time_source_->setClient(this); |
| 77 { | 128 } |
| 78 return make_scoped_ptr(new LayerTreeHostImplTimeSourceAdapter(layerTreeH ostImpl, timeSource)); | 129 |
| 79 } | 130 LayerTreeHostImpl* layer_tree_host_impl_; |
| 80 virtual ~LayerTreeHostImplTimeSourceAdapter() | 131 scoped_refptr<DelayBasedTimeSource> time_source_; |
| 81 { | 132 |
| 82 m_timeSource->setClient(0); | 133 DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImplTimeSourceAdapter); |
| 83 m_timeSource->setActive(false); | |
| 84 } | |
| 85 | |
| 86 virtual void onTimerTick() OVERRIDE | |
| 87 { | |
| 88 // In single threaded mode we attempt to simulate changing the current | |
| 89 // thread by maintaining a fake thread id. When we switch from one | |
| 90 // thread to another, we construct DebugScopedSetXXXThread objects that | |
| 91 // update the thread id. This lets DCHECKS that ensure we're on the | |
| 92 // right thread to work correctly in single threaded mode. The problem | |
| 93 // here is that the timer tasks are run via the message loop, and when | |
| 94 // they run, we've had no chance to construct a DebugScopedSetXXXThread | |
| 95 // object. The result is that we report that we're running on the main | |
| 96 // thread. In multi-threaded mode, this timer is run on the compositor | |
| 97 // thread, so to keep this consistent in single-threaded mode, we'll | |
| 98 // construct a DebugScopedSetImplThread object. There is no need to do | |
| 99 // this in multi-threaded mode since the real thread id's will be | |
| 100 // correct. In fact, setting fake thread id's interferes with the real | |
| 101 // thread id's and causes breakage. | |
| 102 scoped_ptr<DebugScopedSetImplThread> setImplThread; | |
| 103 if (!m_layerTreeHostImpl->proxy()->HasImplThread()) | |
| 104 setImplThread.reset(new DebugScopedSetImplThread(m_layerTreeHostImpl ->proxy())); | |
| 105 | |
| 106 m_layerTreeHostImpl->activatePendingTreeIfNeeded(); | |
| 107 m_layerTreeHostImpl->animate(base::TimeTicks::Now(), base::Time::Now()); | |
| 108 m_layerTreeHostImpl->beginNextFrame(); | |
| 109 } | |
| 110 | |
| 111 void setActive(bool active) | |
| 112 { | |
| 113 if (active != m_timeSource->active()) | |
| 114 m_timeSource->setActive(active); | |
| 115 } | |
| 116 | |
| 117 private: | |
| 118 LayerTreeHostImplTimeSourceAdapter(LayerTreeHostImpl* layerTreeHostImpl, sco ped_refptr<DelayBasedTimeSource> timeSource) | |
| 119 : m_layerTreeHostImpl(layerTreeHostImpl) | |
| 120 , m_timeSource(timeSource) | |
| 121 { | |
| 122 m_timeSource->setClient(this); | |
| 123 } | |
| 124 | |
| 125 LayerTreeHostImpl* m_layerTreeHostImpl; | |
| 126 scoped_refptr<DelayBasedTimeSource> m_timeSource; | |
| 127 | |
| 128 DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImplTimeSourceAdapter); | |
| 129 }; | 134 }; |
| 130 | 135 |
| 131 LayerTreeHostImpl::FrameData::FrameData() | 136 LayerTreeHostImpl::FrameData::FrameData() |
| 132 : containsIncompleteTile(false) | 137 : contains_incomplete_tile(false) {} |
| 133 { | 138 |
| 134 } | 139 LayerTreeHostImpl::FrameData::~FrameData() {} |
| 135 | 140 |
| 136 LayerTreeHostImpl::FrameData::~FrameData() | 141 scoped_ptr<LayerTreeHostImpl> LayerTreeHostImpl::Create( |
| 137 { | 142 const LayerTreeSettings& settings, |
| 138 } | 143 LayerTreeHostImplClient* client, |
| 139 | 144 Proxy* proxy) { |
| 140 scoped_ptr<LayerTreeHostImpl> LayerTreeHostImpl::create(const LayerTreeSettings& settings, LayerTreeHostImplClient* client, Proxy* proxy) | 145 return make_scoped_ptr(new LayerTreeHostImpl(settings, client, proxy)); |
| 141 { | 146 } |
| 142 return make_scoped_ptr(new LayerTreeHostImpl(settings, client, proxy)); | 147 |
| 143 } | 148 LayerTreeHostImpl::LayerTreeHostImpl(const LayerTreeSettings& settings, |
| 144 | 149 LayerTreeHostImplClient* client, |
| 145 LayerTreeHostImpl::LayerTreeHostImpl(const LayerTreeSettings& settings, LayerTre eHostImplClient* client, Proxy* proxy) | 150 Proxy* proxy) |
| 146 : m_client(client) | 151 : client_(client), |
| 147 , m_proxy(proxy) | 152 proxy_(proxy), |
| 148 , m_didLockScrollingLayer(false) | 153 did_lock_scrolling_layer_(false), |
| 149 , m_shouldBubbleScrolls(false) | 154 should_bubble_scrolls_(false), |
| 150 , m_wheelScrolling(false) | 155 wheel_scrolling_(false), |
| 151 , m_settings(settings) | 156 settings_(settings), |
| 152 , m_deviceScaleFactor(1) | 157 device_scale_factor_(1.f), |
| 153 , m_visible(true) | 158 visible_(true), |
| 154 , m_managedMemoryPolicy(PrioritizedResourceManager::defaultMemoryAllocationL imit(), | 159 managed_memory_policy_( |
| 155 ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING, | 160 PrioritizedResourceManager::defaultMemoryAllocationLimit(), |
| 156 0, | 161 ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING, |
| 157 ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING) | 162 0, |
| 158 , m_pinchGestureActive(false) | 163 ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING), |
| 159 , m_fpsCounter(FrameRateCounter::create(m_proxy->HasImplThread())) | 164 pinch_gesture_active_(false), |
| 160 , m_paintTimeCounter(PaintTimeCounter::create()) | 165 fps_counter_(FrameRateCounter::create(proxy_->HasImplThread())), |
| 161 , m_memoryHistory(MemoryHistory::Create()) | 166 paint_time_counter_(PaintTimeCounter::create()), |
| 162 , m_debugRectHistory(DebugRectHistory::create()) | 167 memory_history_(MemoryHistory::Create()), |
| 163 , m_numImplThreadScrolls(0) | 168 debug_rect_history_(DebugRectHistory::create()), |
| 164 , m_numMainThreadScrolls(0) | 169 num_impl_thread_scrolls_(0), |
| 165 , m_cumulativeNumLayersDrawn(0) | 170 num_main_thread_scrolls_(0), |
| 166 , m_cumulativeNumMissingTiles(0) | 171 cumulative_num_layers_drawn_(0), |
| 167 , m_lastSentMemoryVisibleBytes(0) | 172 cumulative_num_missing_tiles_(0), |
| 168 , m_lastSentMemoryVisibleAndNearbyBytes(0) | 173 last_sent_memory_visible_bytes_(0), |
| 169 , m_lastSentMemoryUseBytes(0) | 174 last_sent_memory_visible_and_nearby_bytes_(0), |
| 170 , m_animationRegistrar(AnimationRegistrar::create()) | 175 last_sent_memory_use_bytes_(0), |
| 171 { | 176 animation_registrar_(AnimationRegistrar::create()) { |
| 172 DCHECK(m_proxy->IsImplThread()); | 177 DCHECK(proxy_->IsImplThread()); |
| 173 didVisibilityChange(this, m_visible); | 178 DidVisibilityChange(this, visible_); |
| 174 | 179 |
| 175 setDebugState(settings.initialDebugState); | 180 SetDebugState(settings.initialDebugState); |
| 176 | 181 |
| 177 if (settings.calculateTopControlsPosition) { | 182 if (settings.calculateTopControlsPosition) { |
| 178 m_topControlsManager = TopControlsManager::Create(this, | 183 top_controls_manager_ = |
| 179 settings.topControlsHe ight, | 184 TopControlsManager::Create(this, |
| 180 settings.topControlsSh owThreshold, | 185 settings.topControlsHeight, |
| 181 settings.topControlsHi deThreshold); | 186 settings.topControlsShowThreshold, |
| 182 } | 187 settings.topControlsHideThreshold); |
| 183 | 188 } |
| 184 setDebugState(settings.initialDebugState); | 189 |
| 185 | 190 SetDebugState(settings.initialDebugState); |
| 186 // LTHI always has an active tree. | 191 |
| 187 m_activeTree = LayerTreeImpl::create(this); | 192 // LTHI always has an active tree. |
| 188 } | 193 active_tree_ = LayerTreeImpl::create(this); |
| 189 | 194 } |
| 190 LayerTreeHostImpl::~LayerTreeHostImpl() | 195 |
| 191 { | 196 LayerTreeHostImpl::~LayerTreeHostImpl() { |
| 192 DCHECK(m_proxy->IsImplThread()); | 197 DCHECK(proxy_->IsImplThread()); |
| 193 TRACE_EVENT0("cc", "LayerTreeHostImpl::~LayerTreeHostImpl()"); | 198 TRACE_EVENT0("cc", "LayerTreeHostImpl::~LayerTreeHostImpl()"); |
| 194 | 199 |
| 195 if (rootLayer()) { | 200 if (active_tree_->root_layer()) { |
| 196 clearRenderSurfaces(); | 201 ClearRenderSurfaces(); |
| 197 // The layer trees must be destroyed before the layer tree host. We've | 202 // The layer trees must be destroyed before the layer tree host. We've |
| 198 // made a contract with our animation controllers that the registrar | 203 // made a contract with our animation controllers that the registrar |
| 199 // will outlive them, and we must make good. | 204 // will outlive them, and we must make good. |
| 200 m_recycleTree.reset(); | 205 recycle_tree_.reset(); |
| 201 m_pendingTree.reset(); | 206 pending_tree_.reset(); |
| 202 m_activeTree.reset(); | 207 active_tree_.reset(); |
| 203 } | 208 } |
| 204 } | 209 } |
| 205 | 210 |
| 206 void LayerTreeHostImpl::beginCommit() | 211 void LayerTreeHostImpl::BeginCommit() {} |
| 207 { | 212 |
| 208 } | 213 void LayerTreeHostImpl::CommitComplete() { |
| 209 | 214 TRACE_EVENT0("cc", "LayerTreeHostImpl::commitComplete"); |
| 210 void LayerTreeHostImpl::commitComplete() | 215 |
| 211 { | 216 // Impl-side painting needs an update immediately post-commit to have the |
| 212 TRACE_EVENT0("cc", "LayerTreeHostImpl::commitComplete"); | 217 // opportunity to create tilings. Other paths can call updateDrawProperties |
|
enne (OOO)
2013/03/13 05:22:05
UpdateDrawProperties
danakj
2013/03/13 15:49:11
Done.
| |
| 213 | 218 // more lazily when needed prior to drawing. |
| 214 // Impl-side painting needs an update immediately post-commit to have the | 219 if (settings_.implSidePainting) { |
| 215 // opportunity to create tilings. Other paths can call updateDrawProperties | 220 pending_tree_->set_needs_update_draw_properties(); |
| 216 // more lazily when needed prior to drawing. | 221 pending_tree_->UpdateDrawProperties(LayerTreeImpl::UPDATE_PENDING_TREE); |
| 217 if (m_settings.implSidePainting) { | 222 } else { |
| 218 pendingTree()->set_needs_update_draw_properties(); | 223 active_tree_->set_needs_update_draw_properties(); |
| 219 pendingTree()->UpdateDrawProperties(LayerTreeImpl::UPDATE_PENDING_TREE); | 224 } |
| 220 } else { | 225 |
| 221 activeTree()->set_needs_update_draw_properties(); | 226 client_->SendManagedMemoryStats(); |
| 222 } | 227 } |
| 223 | 228 |
| 224 m_client->sendManagedMemoryStats(); | 229 bool LayerTreeHostImpl::CanDraw() { |
| 225 } | 230 // Note: If you are changing this function or any other function that might |
| 226 | 231 // affect the result of CanDraw, make sure to call |
| 227 bool LayerTreeHostImpl::canDraw() | 232 // client_->OnCanDrawStateChanged in the proper places and update the |
| 228 { | 233 // NotifyIfCanDrawChanged test. |
| 229 // Note: If you are changing this function or any other function that might | 234 |
| 230 // affect the result of canDraw, make sure to call m_client->onCanDrawStateC hanged | 235 if (!active_tree_->root_layer()) { |
| 231 // in the proper places and update the notifyIfCanDrawChanged test. | 236 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw no root layer"); |
|
enne (OOO)
2013/03/13 05:22:05
CanDraw
danakj
2013/03/13 15:49:11
Done.
| |
| 232 | |
| 233 if (!rootLayer()) { | |
| 234 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw no root layer"); | |
| 235 return false; | |
| 236 } | |
| 237 if (DeviceViewportSize().IsEmpty()) { | |
| 238 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw empty viewport"); | |
| 239 return false; | |
| 240 } | |
| 241 if (m_activeTree->ViewportSizeInvalid()) { | |
| 242 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw viewport size rec ently changed"); | |
| 243 return false; | |
| 244 } | |
| 245 if (!m_renderer) { | |
| 246 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw no renderer"); | |
| 247 return false; | |
| 248 } | |
| 249 if (m_activeTree->ContentsTexturesPurged()) { | |
| 250 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw contents textures purged"); | |
| 251 return false; | |
| 252 } | |
| 253 return true; | |
| 254 } | |
| 255 | |
| 256 OutputSurface* LayerTreeHostImpl::outputSurface() const | |
| 257 { | |
| 258 return m_outputSurface.get(); | |
| 259 } | |
| 260 | |
| 261 void LayerTreeHostImpl::animate(base::TimeTicks monotonicTime, base::Time wallCl ockTime) | |
| 262 { | |
| 263 animatePageScale(monotonicTime); | |
| 264 animateLayers(monotonicTime, wallClockTime); | |
| 265 animateScrollbars(monotonicTime); | |
| 266 if (m_topControlsManager) | |
| 267 m_topControlsManager->Animate(monotonicTime); | |
| 268 } | |
| 269 | |
| 270 void LayerTreeHostImpl::manageTiles() | |
| 271 { | |
| 272 DCHECK(m_tileManager); | |
| 273 m_tileManager->ManageTiles(); | |
| 274 | |
| 275 size_t memoryRequiredBytes; | |
| 276 size_t memoryNiceToHaveBytes; | |
| 277 size_t memoryUsedBytes; | |
| 278 m_tileManager->GetMemoryStats(&memoryRequiredBytes, | |
| 279 &memoryNiceToHaveBytes, | |
| 280 &memoryUsedBytes); | |
| 281 sendManagedMemoryStats(memoryRequiredBytes, | |
| 282 memoryNiceToHaveBytes, | |
| 283 memoryUsedBytes); | |
| 284 } | |
| 285 | |
| 286 void LayerTreeHostImpl::startPageScaleAnimation(gfx::Vector2d targetOffset, bool anchorPoint, float pageScale, base::TimeTicks startTime, base::TimeDelta durati on) | |
| 287 { | |
| 288 if (!rootScrollLayer()) | |
| 289 return; | |
| 290 | |
| 291 gfx::Vector2dF scrollTotal = rootScrollLayer()->scroll_offset() + rootScroll Layer()->scroll_delta(); | |
| 292 gfx::SizeF scaledScrollableSize = activeTree()->ScrollableSize(); | |
| 293 gfx::SizeF viewportSize = gfx::ScaleSize(m_deviceViewportSize, 1 / m_deviceS caleFactor); | |
| 294 | |
| 295 double startTimeSeconds = (startTime - base::TimeTicks()).InSecondsF(); | |
| 296 m_pageScaleAnimation = PageScaleAnimation::Create(scrollTotal, activeTree()- >total_page_scale_factor(), viewportSize, scaledScrollableSize, startTimeSeconds ); | |
| 297 | |
| 298 if (anchorPoint) { | |
| 299 gfx::Vector2dF anchor(targetOffset); | |
| 300 m_pageScaleAnimation->ZoomWithAnchor(anchor, pageScale, duration.InSecon dsF()); | |
| 301 } else { | |
| 302 gfx::Vector2dF scaledTargetOffset = targetOffset; | |
| 303 m_pageScaleAnimation->ZoomTo(scaledTargetOffset, pageScale, duration.InS econdsF()); | |
| 304 } | |
| 305 | |
| 306 m_client->setNeedsRedrawOnImplThread(); | |
| 307 m_client->setNeedsCommitOnImplThread(); | |
| 308 m_client->renewTreePriority(); | |
| 309 } | |
| 310 | |
| 311 void LayerTreeHostImpl::scheduleAnimation() | |
| 312 { | |
| 313 m_client->setNeedsRedrawOnImplThread(); | |
| 314 } | |
| 315 | |
| 316 bool LayerTreeHostImpl::haveTouchEventHandlersAt(const gfx::Point& viewportPoint ) | |
| 317 { | |
| 318 if (!ensureRenderSurfaceLayerList()) | |
| 319 return false; | |
| 320 | |
| 321 gfx::PointF deviceViewportPoint = gfx::ScalePoint(viewportPoint, m_deviceSca leFactor); | |
| 322 | |
| 323 // First find out which layer was hit from the saved list of visible layers | |
| 324 // in the most recent frame. | |
| 325 LayerImpl* layerImpl = LayerTreeHostCommon::findLayerThatIsHitByPoint(device ViewportPoint, activeTree()->RenderSurfaceLayerList()); | |
| 326 | |
| 327 // Walk up the hierarchy and look for a layer with a touch event handler reg ion that the given point hits. | |
| 328 for (; layerImpl; layerImpl = layerImpl->parent()) { | |
| 329 if (LayerTreeHostCommon::layerHasTouchEventHandlersAt(deviceViewportPoint, layerImpl)) | |
| 330 return true; | |
| 331 } | |
| 332 | |
| 333 return false; | 237 return false; |
| 334 } | 238 } |
| 335 | 239 if (device_viewport_size_.IsEmpty()) { |
| 336 void LayerTreeHostImpl::trackDamageForAllSurfaces(LayerImpl* rootDrawLayer, cons t LayerList& renderSurfaceLayerList) | 240 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw empty viewport"); |
|
enne (OOO)
2013/03/13 05:22:05
CanDraw
danakj
2013/03/13 15:49:11
Done.
| |
| 337 { | 241 return false; |
| 338 // For now, we use damage tracking to compute a global scissor. To do this, we must | 242 } |
| 339 // compute all damage tracking before drawing anything, so that we know the root | 243 if (active_tree_->ViewportSizeInvalid()) { |
| 340 // damage rect. The root damage rect is then used to scissor each surface. | 244 TRACE_EVENT_INSTANT0( |
| 341 | 245 "cc", "LayerTreeHostImpl::canDraw viewport size recently changed"); |
|
enne (OOO)
2013/03/13 05:22:05
CanDraw
danakj
2013/03/13 15:49:11
Done.
| |
| 342 for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) { | 246 return false; |
| 343 LayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex]; | 247 } |
| 344 RenderSurfaceImpl* renderSurface = renderSurfaceLayer->render_surface(); | 248 if (!renderer_) { |
| 345 DCHECK(renderSurface); | 249 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw no renderer"); |
|
enne (OOO)
2013/03/13 05:22:05
CanDraw
danakj
2013/03/13 15:49:11
Done.
| |
| 346 renderSurface->damage_tracker()->UpdateDamageTrackingState(renderSurface ->layer_list(), renderSurfaceLayer->id(), renderSurface->SurfacePropertyChangedO nlyFromDescendant(), renderSurface->content_rect(), renderSurfaceLayer->mask_lay er(), renderSurfaceLayer->filters(), renderSurfaceLayer->filter().get()); | 250 return false; |
| 347 } | 251 } |
| 348 } | 252 if (active_tree_->ContentsTexturesPurged()) { |
| 349 | 253 TRACE_EVENT_INSTANT0( |
| 350 void LayerTreeHostImpl::FrameData::appendRenderPass(scoped_ptr<RenderPass> rende rPass) | 254 "cc", "LayerTreeHostImpl::canDraw contents textures purged"); |
|
enne (OOO)
2013/03/13 05:22:05
CanDraw
danakj
2013/03/13 15:49:11
Done.
| |
| 351 { | 255 return false; |
| 352 renderPassesById[renderPass->id] = renderPass.get(); | 256 } |
| 353 renderPasses.push_back(renderPass.Pass()); | 257 return true; |
| 354 } | 258 } |
| 355 | 259 |
| 356 static void appendQuadsForLayer(RenderPass* targetRenderPass, LayerImpl* layer, OcclusionTrackerImpl& occlusionTracker, AppendQuadsData& appendQuadsData) | 260 void LayerTreeHostImpl::Animate(base::TimeTicks monotonic_time, |
| 357 { | 261 base::Time wall_clock_time) { |
| 358 bool forSurface = false; | 262 AnimatePageScale(monotonic_time); |
| 359 QuadCuller quadCuller(targetRenderPass->quad_list, | 263 AnimateLayers(monotonic_time, wall_clock_time); |
| 360 targetRenderPass->shared_quad_state_list, | 264 AnimateScrollbars(monotonic_time); |
| 361 layer, | 265 if (top_controls_manager_) |
| 362 occlusionTracker, | 266 top_controls_manager_->Animate(monotonic_time); |
| 363 layer->ShowDebugBorders(), | 267 } |
| 364 forSurface); | 268 |
| 365 layer->AppendQuads(&quadCuller, &appendQuadsData); | 269 void LayerTreeHostImpl::ManageTiles() { |
| 366 } | 270 DCHECK(tile_manager_); |
| 367 | 271 tile_manager_->ManageTiles(); |
| 368 static void appendQuadsForRenderSurfaceLayer(RenderPass* targetRenderPass, Layer Impl* layer, const RenderPass* contributingRenderPass, OcclusionTrackerImpl& occ lusionTracker, AppendQuadsData& appendQuadsData) | 272 |
| 369 { | 273 size_t memory_required_bytes; |
| 370 bool forSurface = true; | 274 size_t memory_nice_to_have_bytes; |
| 371 QuadCuller quadCuller(targetRenderPass->quad_list, | 275 size_t memory_used_bytes; |
| 372 targetRenderPass->shared_quad_state_list, | 276 tile_manager_->GetMemoryStats(&memory_required_bytes, |
| 373 layer, | 277 &memory_nice_to_have_bytes, |
| 374 occlusionTracker, | 278 &memory_used_bytes); |
| 375 layer->ShowDebugBorders(), | 279 SendManagedMemoryStats(memory_required_bytes, |
| 376 forSurface); | 280 memory_nice_to_have_bytes, |
| 377 | 281 memory_used_bytes); |
| 378 bool isReplica = false; | 282 } |
| 283 | |
| 284 void LayerTreeHostImpl::StartPageScaleAnimation(gfx::Vector2d target_offset, | |
| 285 bool anchor_point, | |
| 286 float page_scale, | |
| 287 base::TimeTicks start_time, | |
| 288 base::TimeDelta duration) { | |
| 289 if (!RootScrollLayer()) | |
| 290 return; | |
| 291 | |
| 292 gfx::Vector2dF scroll_total = | |
| 293 RootScrollLayer()->scroll_offset() + RootScrollLayer()->scroll_delta(); | |
| 294 gfx::SizeF scaled_scrollable_size = active_tree_->ScrollableSize(); | |
| 295 gfx::SizeF viewport_size = | |
| 296 gfx::ScaleSize(device_viewport_size_, 1.f / device_scale_factor_); | |
| 297 | |
| 298 double start_time_seconds = (start_time - base::TimeTicks()).InSecondsF(); | |
| 299 page_scale_animation_ = | |
| 300 PageScaleAnimation::Create(scroll_total, | |
| 301 active_tree_->total_page_scale_factor(), | |
| 302 viewport_size, | |
| 303 scaled_scrollable_size, | |
| 304 start_time_seconds); | |
| 305 | |
| 306 if (anchor_point) { | |
| 307 gfx::Vector2dF anchor(target_offset); | |
| 308 page_scale_animation_->ZoomWithAnchor(anchor, | |
| 309 page_scale, | |
| 310 duration.InSecondsF()); | |
| 311 } else { | |
| 312 gfx::Vector2dF scaled_target_offset = target_offset; | |
| 313 page_scale_animation_->ZoomTo(scaled_target_offset, | |
| 314 page_scale, | |
| 315 duration.InSecondsF()); | |
| 316 } | |
| 317 | |
| 318 client_->SetNeedsRedrawOnImplThread(); | |
| 319 client_->SetNeedsCommitOnImplThread(); | |
| 320 client_->RenewTreePriority(); | |
| 321 } | |
| 322 | |
| 323 void LayerTreeHostImpl::ScheduleAnimation() { | |
| 324 client_->SetNeedsRedrawOnImplThread(); | |
| 325 } | |
| 326 | |
| 327 bool LayerTreeHostImpl::HaveTouchEventHandlersAt(gfx::Point viewport_point) { | |
| 328 if (!EnsureRenderSurfaceLayerList()) | |
| 329 return false; | |
| 330 | |
| 331 gfx::PointF device_viewport_point = | |
| 332 gfx::ScalePoint(viewport_point, device_scale_factor_); | |
| 333 | |
| 334 // First find out which layer was hit from the saved list of visible layers | |
| 335 // in the most recent frame. | |
| 336 LayerImpl* layer_impl = LayerTreeHostCommon::findLayerThatIsHitByPoint( | |
| 337 device_viewport_point, | |
| 338 active_tree_->RenderSurfaceLayerList()); | |
| 339 | |
| 340 // Walk up the hierarchy and look for a layer with a touch event handler | |
| 341 // region that the given point hits. | |
| 342 for (; layer_impl; layer_impl = layer_impl->parent()) { | |
| 343 if (LayerTreeHostCommon::layerHasTouchEventHandlersAt(device_viewport_point, | |
| 344 layer_impl)) | |
| 345 return true; | |
| 346 } | |
| 347 | |
| 348 return false; | |
| 349 } | |
| 350 | |
| 351 void LayerTreeHostImpl::TrackDamageForAllSurfaces( | |
| 352 LayerImpl* root_draw_layer, | |
| 353 const LayerList& render_surface_layer_list) { | |
| 354 // For now, we use damage tracking to compute a global scissor. To do this, we | |
| 355 // must compute all damage tracking before drawing anything, so that we know | |
| 356 // the root damage rect. The root damage rect is then used to scissor each | |
| 357 // surface. | |
| 358 | |
| 359 for (int surfaceIndex = render_surface_layer_list.size() - 1; | |
| 360 surfaceIndex >= 0 ; | |
| 361 --surfaceIndex) { | |
| 362 LayerImpl* render_surface_layer = render_surface_layer_list[surfaceIndex]; | |
| 363 RenderSurfaceImpl* render_surface = render_surface_layer->render_surface(); | |
| 364 DCHECK(render_surface); | |
| 365 render_surface->damage_tracker()->UpdateDamageTrackingState( | |
| 366 render_surface->layer_list(), | |
| 367 render_surface_layer->id(), | |
| 368 render_surface->SurfacePropertyChangedOnlyFromDescendant(), | |
| 369 render_surface->content_rect(), | |
| 370 render_surface_layer->mask_layer(), | |
| 371 render_surface_layer->filters(), | |
| 372 render_surface_layer->filter().get()); | |
| 373 } | |
| 374 } | |
| 375 | |
| 376 void LayerTreeHostImpl::FrameData::AppendRenderPass( | |
| 377 scoped_ptr<RenderPass> render_pass) { | |
| 378 render_passes_by_id[render_pass->id] = render_pass.get(); | |
| 379 render_passes.push_back(render_pass.Pass()); | |
| 380 } | |
| 381 | |
| 382 static void AppendQuadsForLayer(RenderPass* target_render_pass, | |
| 383 LayerImpl* layer, | |
| 384 const OcclusionTrackerImpl& occlusion_tracker, | |
| 385 AppendQuadsData* append_quads_data) { | |
| 386 bool for_surface = false; | |
| 387 QuadCuller quadCuller(target_render_pass->quad_list, | |
| 388 target_render_pass->shared_quad_state_list, | |
| 389 layer, | |
| 390 occlusion_tracker, | |
| 391 layer->ShowDebugBorders(), | |
| 392 for_surface); | |
| 393 layer->AppendQuads(&quadCuller, append_quads_data); | |
| 394 } | |
| 395 | |
| 396 static void AppendQuadsForRenderSurfaceLayer( | |
| 397 RenderPass* target_render_pass, | |
| 398 LayerImpl* layer, | |
| 399 const RenderPass* contributing_render_pass, | |
| 400 const OcclusionTrackerImpl& occlusion_tracker, | |
| 401 AppendQuadsData* append_quads_data) { | |
| 402 bool for_surface = true; | |
| 403 QuadCuller quadCuller(target_render_pass->quad_list, | |
| 404 target_render_pass->shared_quad_state_list, | |
| 405 layer, | |
| 406 occlusion_tracker, | |
| 407 layer->ShowDebugBorders(), | |
| 408 for_surface); | |
| 409 | |
| 410 bool is_replica = false; | |
| 411 layer->render_surface()->AppendQuads(&quadCuller, | |
| 412 append_quads_data, | |
| 413 is_replica, | |
| 414 contributing_render_pass->id); | |
| 415 | |
| 416 // Add replica after the surface so that it appears below the surface. | |
| 417 if (layer->has_replica()) { | |
| 418 is_replica = true; | |
| 379 layer->render_surface()->AppendQuads(&quadCuller, | 419 layer->render_surface()->AppendQuads(&quadCuller, |
| 380 &appendQuadsData, | 420 append_quads_data, |
| 381 isReplica, | 421 is_replica, |
| 382 contributingRenderPass->id); | 422 contributing_render_pass->id); |
| 383 | 423 } |
| 384 // Add replica after the surface so that it appears below the surface. | 424 } |
| 385 if (layer->has_replica()) { | 425 |
| 386 isReplica = true; | 426 static void AppendQuadsToFillScreen( |
| 387 layer->render_surface()->AppendQuads(&quadCuller, | 427 RenderPass* target_render_pass, |
| 388 &appendQuadsData, | 428 LayerImpl* root_layer, |
| 389 isReplica, | 429 SkColor screen_background_color, |
| 390 contributingRenderPass->id); | 430 const OcclusionTrackerImpl& occlusion_tracker) { |
| 391 } | 431 if (!root_layer || !SkColorGetA(screen_background_color)) |
| 392 } | 432 return; |
| 393 | 433 |
| 394 static void appendQuadsToFillScreen(RenderPass* targetRenderPass, LayerImpl* roo tLayer, SkColor screenBackgroundColor, const OcclusionTrackerImpl& occlusionTrac ker) | 434 Region fill_region = occlusion_tracker.ComputeVisibleRegionInScreen(); |
| 395 { | 435 if (fill_region.IsEmpty()) |
| 396 if (!rootLayer || !SkColorGetA(screenBackgroundColor)) | 436 return; |
| 397 return; | 437 |
| 398 | 438 bool for_surface = false; |
| 399 Region fillRegion = occlusionTracker.ComputeVisibleRegionInScreen(); | 439 QuadCuller quadCuller(target_render_pass->quad_list, |
| 400 if (fillRegion.IsEmpty()) | 440 target_render_pass->shared_quad_state_list, |
| 401 return; | 441 root_layer, |
| 402 | 442 occlusion_tracker, |
| 403 bool forSurface = false; | 443 root_layer->ShowDebugBorders(), |
| 404 QuadCuller quadCuller(targetRenderPass->quad_list, | 444 for_surface); |
| 405 targetRenderPass->shared_quad_state_list, | 445 |
| 406 rootLayer, | 446 // Manually create the quad state for the gutter quads, as the root layer |
| 407 occlusionTracker, | 447 // doesn't have any bounds and so can't generate this itself. |
| 408 rootLayer->ShowDebugBorders(), | 448 // TODO(danakj): Make the gutter quads generated by the solid color layer |
| 409 forSurface); | 449 // (make it smarter about generating quads to fill unoccluded areas). |
| 410 | 450 |
| 411 // Manually create the quad state for the gutter quads, as the root layer | 451 gfx::Rect root_target_rect = root_layer->render_surface()->content_rect(); |
| 412 // doesn't have any bounds and so can't generate this itself. | 452 float opacity = 1; |
|
enne (OOO)
2013/03/13 05:22:05
1.f
danakj
2013/03/13 15:49:11
Done.
| |
| 413 // FIXME: Make the gutter quads generated by the solid color layer (make it smarter about generating quads to fill unoccluded areas). | 453 SharedQuadState* shared_quad_state = |
| 414 | 454 quadCuller.useSharedQuadState(SharedQuadState::Create()); |
| 415 gfx::Rect rootTargetRect = rootLayer->render_surface()->content_rect(); | 455 shared_quad_state->SetAll(root_layer->draw_transform(), |
| 416 float opacity = 1; | 456 root_target_rect.size(), |
| 417 SharedQuadState* sharedQuadState = quadCuller.useSharedQuadState(SharedQuadS tate::Create()); | 457 root_target_rect, |
| 418 sharedQuadState->SetAll(rootLayer->draw_transform(), | 458 root_target_rect, |
| 419 rootTargetRect.size(), | |
| 420 rootTargetRect, | |
| 421 rootTargetRect, | |
| 422 false, | 459 false, |
| 423 opacity); | 460 opacity); |
| 424 | 461 |
| 425 AppendQuadsData appendQuadsData; | 462 AppendQuadsData append_quads_data; |
| 426 | 463 |
| 427 gfx::Transform transformToLayerSpace(gfx::Transform::kSkipInitialization); | 464 gfx::Transform transform_to_layer_space(gfx::Transform::kSkipInitialization); |
| 428 bool didInvert = rootLayer->screen_space_transform().GetInverse(&transformTo LayerSpace); | 465 bool did_invert = root_layer->screen_space_transform().GetInverse( |
| 429 DCHECK(didInvert); | 466 &transform_to_layer_space); |
| 430 for (Region::Iterator fillRects(fillRegion); fillRects.has_rect(); fillRects .next()) { | 467 DCHECK(did_invert); |
| 431 // The root layer transform is composed of translations and scales only, | 468 for (Region::Iterator fillRects(fill_region); |
| 432 // no perspective, so mapping is sufficient (as opposed to projecting). | 469 fillRects.has_rect(); |
| 433 gfx::Rect layerRect = MathUtil::mapClippedRect(transformToLayerSpace, fi llRects.rect()); | 470 fillRects.next()) { |
| 434 // Skip the quad culler and just append the quads directly to avoid | 471 // The root layer transform is composed of translations and scales only, |
| 435 // occlusion checks. | 472 // no perspective, so mapping is sufficient (as opposed to projecting). |
| 436 scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create(); | 473 gfx::Rect layer_rect = |
| 437 quad->SetNew(sharedQuadState, layerRect, screenBackgroundColor); | 474 MathUtil::mapClippedRect(transform_to_layer_space, fillRects.rect()); |
| 438 quadCuller.append(quad.PassAs<DrawQuad>(), &appendQuadsData); | 475 // Skip the quad culler and just append the quads directly to avoid |
| 476 // occlusion checks. | |
| 477 scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create(); | |
| 478 quad->SetNew(shared_quad_state, layer_rect, screen_background_color); | |
| 479 quadCuller.append(quad.PassAs<DrawQuad>(), &append_quads_data); | |
| 480 } | |
| 481 } | |
| 482 | |
| 483 bool LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) { | |
| 484 DCHECK(frame->render_passes.empty()); | |
| 485 | |
| 486 if (!CanDraw() || !active_tree_->root_layer()) | |
| 487 return false; | |
| 488 | |
| 489 TrackDamageForAllSurfaces(active_tree_->root_layer(), | |
| 490 *frame->render_surface_layer_list); | |
| 491 | |
| 492 TRACE_EVENT1("cc", | |
| 493 "LayerTreeHostImpl::calculateRenderPasses", | |
|
enne (OOO)
2013/03/13 05:22:05
CalculateRenderPasses
danakj
2013/03/13 15:49:11
Done.
| |
| 494 "render_surface_layer_list.size()", | |
| 495 static_cast<long long unsigned>( | |
| 496 frame->render_surface_layer_list->size())); | |
| 497 | |
| 498 // Create the render passes in dependency order. | |
| 499 for (int surfaceIndex = frame->render_surface_layer_list->size() - 1; | |
| 500 surfaceIndex >= 0 ; | |
| 501 --surfaceIndex) { | |
| 502 LayerImpl* render_surface_layer = | |
| 503 (*frame->render_surface_layer_list)[surfaceIndex]; | |
| 504 render_surface_layer->render_surface()->AppendRenderPasses(frame); | |
| 505 } | |
| 506 | |
| 507 bool record_metrics_for_frame = | |
| 508 settings_.showOverdrawInTracing && | |
| 509 base::debug::TraceLog::GetInstance() && | |
| 510 base::debug::TraceLog::GetInstance()->IsEnabled(); | |
| 511 OcclusionTrackerImpl occlusion_tracker( | |
| 512 active_tree_->root_layer()->render_surface()->content_rect(), | |
| 513 record_metrics_for_frame); | |
| 514 occlusion_tracker.set_minimum_tracking_size( | |
| 515 settings_.minimumOcclusionTrackingSize); | |
| 516 | |
| 517 if (debug_state_.showOccludingRects) { | |
| 518 occlusion_tracker.set_occluding_screen_space_rects_container( | |
| 519 &frame->occluding_screen_space_rects); | |
| 520 } | |
| 521 if (debug_state_.showNonOccludingRects) { | |
| 522 occlusion_tracker.set_non_occluding_screen_space_rects_container( | |
| 523 &frame->non_occluding_screen_space_rects); | |
| 524 } | |
| 525 | |
| 526 // Add quads to the Render passes in FrontToBack order to allow for testing | |
| 527 // occlusion and performing culling during the tree walk. | |
| 528 typedef LayerIterator<LayerImpl, | |
| 529 std::vector<LayerImpl*>, | |
| 530 RenderSurfaceImpl, | |
| 531 LayerIteratorActions::FrontToBack> LayerIteratorType; | |
| 532 | |
| 533 // Typically when we are missing a texture and use a checkerboard quad, we | |
| 534 // still draw the frame. However when the layer being checkerboarded is moving | |
| 535 // due to an impl-animation, we drop the frame to avoid flashing due to the | |
| 536 // texture suddenly appearing in the future. | |
| 537 bool draw_frame = true; | |
| 538 | |
| 539 LayerIteratorType end = | |
| 540 LayerIteratorType::end(frame->render_surface_layer_list); | |
| 541 for (LayerIteratorType it = | |
| 542 LayerIteratorType::begin(frame->render_surface_layer_list); | |
| 543 it != end; | |
| 544 ++it) { | |
| 545 RenderPass::Id target_render_pass_id = | |
| 546 it.targetRenderSurfaceLayer()->render_surface()->RenderPassId(); | |
| 547 RenderPass* target_render_pass = | |
| 548 frame->render_passes_by_id[target_render_pass_id]; | |
| 549 | |
| 550 occlusion_tracker.EnterLayer(it); | |
| 551 | |
| 552 AppendQuadsData append_quads_data(target_render_pass->id); | |
| 553 | |
| 554 if (it.representsContributingRenderSurface()) { | |
| 555 RenderPass::Id contributing_render_pass_id = | |
| 556 it->render_surface()->RenderPassId(); | |
| 557 RenderPass* contributing_render_pass = | |
| 558 frame->render_passes_by_id[contributing_render_pass_id]; | |
| 559 AppendQuadsForRenderSurfaceLayer(target_render_pass, | |
| 560 *it, | |
| 561 contributing_render_pass, | |
| 562 occlusion_tracker, | |
| 563 &append_quads_data); | |
| 564 } else if (it.representsItself() && !it->visible_content_rect().IsEmpty()) { | |
| 565 bool has_occlusion_from_outside_target_surface; | |
| 566 bool impl_draw_transform_is_unknown = false; | |
| 567 if (occlusion_tracker.Occluded( | |
| 568 it->render_target(), | |
| 569 it->visible_content_rect(), | |
| 570 it->draw_transform(), | |
| 571 impl_draw_transform_is_unknown, | |
| 572 it->is_clipped(), | |
| 573 it->clip_rect(), | |
| 574 &has_occlusion_from_outside_target_surface)) { | |
| 575 append_quads_data.hadOcclusionFromOutsideTargetSurface |= | |
| 576 has_occlusion_from_outside_target_surface; | |
| 577 } else { | |
| 578 DCHECK_EQ(active_tree_, it->layer_tree_impl()); | |
| 579 it->WillDraw(resource_provider_.get()); | |
| 580 frame->will_draw_layers.push_back(*it); | |
| 581 | |
| 582 if (it->HasContributingDelegatedRenderPasses()) { | |
| 583 RenderPass::Id contributing_render_pass_id = | |
| 584 it->FirstContributingRenderPassId(); | |
| 585 while (frame->render_passes_by_id.find(contributing_render_pass_id) != | |
| 586 frame->render_passes_by_id.end()) { | |
| 587 RenderPass* render_pass = | |
| 588 frame->render_passes_by_id[contributing_render_pass_id]; | |
| 589 | |
| 590 AppendQuadsData append_quads_data(render_pass->id); | |
| 591 AppendQuadsForLayer(render_pass, | |
| 592 *it, | |
| 593 occlusion_tracker, | |
| 594 &append_quads_data); | |
| 595 | |
| 596 contributing_render_pass_id = | |
| 597 it->NextContributingRenderPassId(contributing_render_pass_id); | |
| 598 } | |
| 599 } | |
| 600 | |
| 601 AppendQuadsForLayer(target_render_pass, | |
| 602 *it, | |
| 603 occlusion_tracker, | |
| 604 &append_quads_data); | |
| 605 } | |
| 606 | |
| 607 ++cumulative_num_layers_drawn_; | |
| 439 } | 608 } |
| 440 } | 609 |
| 441 | 610 if (append_quads_data.hadOcclusionFromOutsideTargetSurface) |
| 442 bool LayerTreeHostImpl::calculateRenderPasses(FrameData& frame) | 611 target_render_pass->has_occlusion_from_outside_target_surface = true; |
| 443 { | 612 |
| 444 DCHECK(frame.renderPasses.empty()); | 613 if (append_quads_data.numMissingTiles) { |
| 445 | 614 cumulative_num_missing_tiles_ += append_quads_data.numMissingTiles; |
| 446 if (!canDraw() || !rootLayer()) | 615 bool layer_has_animating_transform = |
| 616 it->screen_space_transform_is_animating() || | |
| 617 it->draw_transform_is_animating(); | |
| 618 if (layer_has_animating_transform) | |
| 619 draw_frame = false; | |
| 620 } | |
| 621 | |
| 622 if (append_quads_data.hadIncompleteTile) | |
| 623 frame->contains_incomplete_tile = true; | |
| 624 | |
| 625 occlusion_tracker.LeaveLayer(it); | |
| 626 } | |
| 627 | |
| 628 #ifndef NDEBUG | |
| 629 for (size_t i = 0; i < frame->render_passes.size(); ++i) { | |
| 630 for (size_t j = 0; j < frame->render_passes[i]->quad_list.size(); ++j) | |
| 631 DCHECK(frame->render_passes[i]->quad_list[j]->shared_quad_state); | |
| 632 DCHECK(frame->render_passes_by_id.find(frame->render_passes[i]->id) | |
| 633 != frame->render_passes_by_id.end()); | |
| 634 } | |
| 635 #endif | |
| 636 DCHECK(frame->render_passes.back()->output_rect.origin().IsOrigin()); | |
| 637 | |
| 638 if (!active_tree_->has_transparent_background()) { | |
| 639 frame->render_passes.back()->has_transparent_background = false; | |
| 640 AppendQuadsToFillScreen(frame->render_passes.back(), | |
| 641 active_tree_->root_layer(), | |
| 642 active_tree_->background_color(), | |
| 643 occlusion_tracker); | |
| 644 } | |
| 645 | |
| 646 if (draw_frame) | |
| 647 occlusion_tracker.overdraw_metrics()->RecordMetrics(this); | |
| 648 | |
| 649 RemoveRenderPasses(CullRenderPassesWithNoQuads(), frame); | |
| 650 renderer_->DecideRenderPassAllocationsForFrame(frame->render_passes); | |
| 651 RemoveRenderPasses(CullRenderPassesWithCachedTextures(*renderer_), frame); | |
| 652 | |
| 653 return draw_frame; | |
| 654 } | |
| 655 | |
| 656 void LayerTreeHostImpl::SetBackgroundTickingEnabled(bool enabled) { | |
| 657 // Lazily create the time_source adapter so that we can vary the interval for | |
| 658 // testing. | |
| 659 if (!time_source_client_adapter_) | |
|
enne (OOO)
2013/03/13 05:22:05
{}
danakj
2013/03/13 15:49:11
Done.
| |
| 660 time_source_client_adapter_ = LayerTreeHostImplTimeSourceAdapter::Create( | |
| 661 this, | |
| 662 DelayBasedTimeSource::create(LowFrequencyAnimationInterval(), | |
| 663 proxy_->CurrentThread())); | |
| 664 | |
| 665 time_source_client_adapter_->SetActive(enabled); | |
| 666 } | |
| 667 | |
| 668 static inline RenderPass* FindRenderPassById( | |
| 669 RenderPass::Id render_pass_id, | |
| 670 const LayerTreeHostImpl::FrameData& frame) { | |
| 671 RenderPassIdHashMap::const_iterator it = | |
| 672 frame.render_passes_by_id.find(render_pass_id); | |
| 673 return it != frame.render_passes_by_id.end() ? it->second : NULL; | |
| 674 } | |
| 675 | |
| 676 static void RemoveRenderPassesRecursive(RenderPass::Id remove_render_pass_id, | |
| 677 LayerTreeHostImpl::FrameData* frame) { | |
| 678 RenderPass* remove_render_pass = | |
| 679 FindRenderPassById(remove_render_pass_id, *frame); | |
| 680 // The pass was already removed by another quad - probably the original, and | |
| 681 // we are the replica. | |
| 682 if (!remove_render_pass) | |
| 683 return; | |
| 684 RenderPassList& render_passes = frame->render_passes; | |
| 685 RenderPassList::iterator to_remove = std::find(render_passes.begin(), | |
| 686 render_passes.end(), | |
| 687 remove_render_pass); | |
| 688 | |
| 689 DCHECK(to_remove != render_passes.end()); | |
| 690 | |
| 691 scoped_ptr<RenderPass> removed_pass = render_passes.take(to_remove); | |
| 692 frame->render_passes.erase(to_remove); | |
| 693 frame->render_passes_by_id.erase(remove_render_pass_id); | |
| 694 | |
| 695 // Now follow up for all RenderPass quads and remove their RenderPasses | |
| 696 // recursively. | |
| 697 const QuadList& quad_list = removed_pass->quad_list; | |
| 698 QuadList::constBackToFrontIterator quad_list_iterator = | |
| 699 quad_list.backToFrontBegin(); | |
| 700 for (; quad_list_iterator != quad_list.backToFrontEnd(); | |
| 701 ++quad_list_iterator) { | |
| 702 DrawQuad* current_quad = (*quad_list_iterator); | |
| 703 if (current_quad->material != DrawQuad::RENDER_PASS) | |
| 704 continue; | |
| 705 | |
| 706 RenderPass::Id next_remove_render_pass_id = | |
| 707 RenderPassDrawQuad::MaterialCast(current_quad)->render_pass_id; | |
| 708 RemoveRenderPassesRecursive(next_remove_render_pass_id, frame); | |
| 709 } | |
| 710 } | |
| 711 | |
| 712 bool LayerTreeHostImpl::CullRenderPassesWithCachedTextures:: | |
| 713 ShouldRemoveRenderPass(const RenderPassDrawQuad& quad, | |
| 714 const FrameData& frame) const { | |
| 715 bool quad_has_damage = !quad.contents_changed_since_last_frame.IsEmpty(); | |
| 716 bool quad_has_cached_resource = | |
| 717 renderer_.HaveCachedResourcesForRenderPassId(quad.render_pass_id); | |
| 718 if (quad_has_damage) { | |
| 719 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures have damage"); | |
| 720 return false; | |
| 721 } else if (!quad_has_cached_resource) { | |
| 722 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures have no texture"); | |
| 723 return false; | |
| 724 } | |
| 725 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures dropped!"); | |
| 726 return true; | |
| 727 } | |
| 728 | |
| 729 bool LayerTreeHostImpl::CullRenderPassesWithNoQuads::ShouldRemoveRenderPass( | |
| 730 const RenderPassDrawQuad& quad, const FrameData& frame) const { | |
| 731 const RenderPass* render_pass = | |
| 732 FindRenderPassById(quad.render_pass_id, frame); | |
| 733 if (!render_pass) | |
| 734 return false; | |
| 735 | |
| 736 // If any quad or RenderPass draws into this RenderPass, then keep it. | |
| 737 const QuadList& quad_list = render_pass->quad_list; | |
| 738 for (QuadList::constBackToFrontIterator quad_list_iterator = | |
| 739 quad_list.backToFrontBegin(); | |
| 740 quad_list_iterator != quad_list.backToFrontEnd(); | |
| 741 ++quad_list_iterator) { | |
| 742 DrawQuad* current_quad = *quad_list_iterator; | |
| 743 | |
| 744 if (current_quad->material != DrawQuad::RENDER_PASS) | |
| 447 return false; | 745 return false; |
| 448 | 746 |
| 449 trackDamageForAllSurfaces(rootLayer(), *frame.renderSurfaceLayerList); | 747 const RenderPass* contributing_pass = FindRenderPassById( |
| 450 | 748 RenderPassDrawQuad::MaterialCast(current_quad)->render_pass_id, frame); |
| 451 TRACE_EVENT1("cc", "LayerTreeHostImpl::calculateRenderPasses", "renderSurfac eLayerList.size()", static_cast<long long unsigned>(frame.renderSurfaceLayerList ->size())); | 749 if (contributing_pass) |
| 452 | 750 return false; |
| 453 // Create the render passes in dependency order. | 751 } |
| 454 for (int surfaceIndex = frame.renderSurfaceLayerList->size() - 1; surfaceInd ex >= 0 ; --surfaceIndex) { | 752 return true; |
| 455 LayerImpl* renderSurfaceLayer = (*frame.renderSurfaceLayerList)[surfaceI ndex]; | 753 } |
| 456 renderSurfaceLayer->render_surface()->AppendRenderPasses(&frame); | 754 |
| 755 // Defined for linking tests. | |
| 756 template CC_EXPORT void LayerTreeHostImpl::RemoveRenderPasses< | |
| 757 LayerTreeHostImpl::CullRenderPassesWithCachedTextures>( | |
| 758 CullRenderPassesWithCachedTextures culler, FrameData* frame); | |
| 759 template CC_EXPORT void LayerTreeHostImpl::RemoveRenderPasses< | |
| 760 LayerTreeHostImpl::CullRenderPassesWithNoQuads>( | |
| 761 CullRenderPassesWithNoQuads culler, FrameData*); | |
| 762 | |
| 763 // static | |
| 764 template <typename RenderPassCuller> | |
| 765 void LayerTreeHostImpl::RemoveRenderPasses(RenderPassCuller culler, | |
| 766 FrameData* frame) { | |
| 767 for (size_t it = culler.RenderPassListBegin(frame->render_passes); | |
| 768 it != culler.RenderPassListEnd(frame->render_passes); | |
| 769 it = culler.RenderPassListNext(it)) { | |
| 770 const RenderPass* current_pass = frame->render_passes[it]; | |
| 771 const QuadList& quad_list = current_pass->quad_list; | |
| 772 QuadList::constBackToFrontIterator quad_list_iterator = | |
| 773 quad_list.backToFrontBegin(); | |
| 774 | |
| 775 for (; quad_list_iterator != quad_list.backToFrontEnd(); | |
| 776 ++quad_list_iterator) { | |
| 777 DrawQuad* current_quad = *quad_list_iterator; | |
| 778 | |
| 779 if (current_quad->material != DrawQuad::RENDER_PASS) | |
| 780 continue; | |
| 781 | |
| 782 const RenderPassDrawQuad* render_pass_quad = | |
| 783 RenderPassDrawQuad::MaterialCast(current_quad); | |
| 784 if (!culler.ShouldRemoveRenderPass(*render_pass_quad, *frame)) | |
| 785 continue; | |
| 786 | |
| 787 // We are changing the vector in the middle of iteration. Because we | |
| 788 // delete render passes that draw into the current pass, we are | |
| 789 // guaranteed that any data from the iterator to the end will not | |
| 790 // change. So, capture the iterator position from the end of the | |
| 791 // list, and restore it after the change. | |
| 792 size_t position_from_end = frame->render_passes.size() - it; | |
| 793 RemoveRenderPassesRecursive(render_pass_quad->render_pass_id, frame); | |
| 794 it = frame->render_passes.size() - position_from_end; | |
| 795 DCHECK_GE(frame->render_passes.size(), position_from_end); | |
| 457 } | 796 } |
| 458 | 797 } |
| 459 bool recordMetricsForFrame = m_settings.showOverdrawInTracing && base::debug ::TraceLog::GetInstance() && base::debug::TraceLog::GetInstance()->IsEnabled(); | 798 } |
| 460 OcclusionTrackerImpl occlusionTracker(rootLayer()->render_surface()->content _rect(), recordMetricsForFrame); | 799 |
| 461 occlusionTracker.set_minimum_tracking_size(m_settings.minimumOcclusionTracki ngSize); | 800 bool LayerTreeHostImpl::PrepareToDraw(FrameData* frame) { |
| 462 | 801 TRACE_EVENT0("cc", "LayerTreeHostImpl::prepareToDraw"); |
|
enne (OOO)
2013/03/13 05:22:05
PrepareToDraw
danakj
2013/03/13 15:49:11
Done.
| |
| 463 if (m_debugState.showOccludingRects) | 802 |
| 464 occlusionTracker.set_occluding_screen_space_rects_container(&frame.occlu dingScreenSpaceRects); | 803 active_tree_->UpdateDrawProperties( |
| 465 if (m_debugState.showNonOccludingRects) | 804 LayerTreeImpl::UPDATE_ACTIVE_TREE_FOR_DRAW); |
| 466 occlusionTracker.set_non_occluding_screen_space_rects_container(&frame.n onOccludingScreenSpaceRects); | 805 |
| 467 | 806 frame->render_surface_layer_list = &active_tree_->RenderSurfaceLayerList(); |
| 468 // Add quads to the Render passes in FrontToBack order to allow for testing occlusion and performing culling during the tree walk. | 807 frame->render_passes.clear(); |
| 469 typedef LayerIterator<LayerImpl, std::vector<LayerImpl*>, RenderSurfaceImpl, LayerIteratorActions::FrontToBack> LayerIteratorType; | 808 frame->render_passes_by_id.clear(); |
| 470 | 809 frame->will_draw_layers.clear(); |
| 471 // Typically when we are missing a texture and use a checkerboard quad, we s till draw the frame. However when the layer being | 810 |
| 472 // checkerboarded is moving due to an impl-animation, we drop the frame to a void flashing due to the texture suddenly appearing | 811 if (!CalculateRenderPasses(frame)) |
| 473 // in the future. | 812 return false; |
| 474 bool drawFrame = true; | 813 |
| 475 | 814 // If we return true, then we expect DrawLayers() to be called before this |
| 476 LayerIteratorType end = LayerIteratorType::end(frame.renderSurfaceLayerList) ; | 815 // function is called again. |
| 477 for (LayerIteratorType it = LayerIteratorType::begin(frame.renderSurfaceLaye rList); it != end; ++it) { | 816 return true; |
| 478 RenderPass::Id targetRenderPassId = it.targetRenderSurfaceLayer()->rende r_surface()->RenderPassId(); | 817 } |
| 479 RenderPass* targetRenderPass = frame.renderPassesById[targetRenderPassId ]; | 818 |
| 480 | 819 void LayerTreeHostImpl::EnforceManagedMemoryPolicy( |
| 481 occlusionTracker.EnterLayer(it); | 820 const ManagedMemoryPolicy& policy) { |
| 482 | 821 bool evicted_resources = client_->ReduceContentsTextureMemoryOnImplThread( |
| 483 AppendQuadsData appendQuadsData(targetRenderPass->id); | 822 visible_ ? policy.bytesLimitWhenVisible : policy.bytesLimitWhenNotVisible, |
| 484 | 823 ManagedMemoryPolicy::priorityCutoffToValue( |
| 485 if (it.representsContributingRenderSurface()) { | 824 visible_ ? |
| 486 RenderPass::Id contributingRenderPassId = it->render_surface()->Rend erPassId(); | 825 policy.priorityCutoffWhenVisible : |
| 487 RenderPass* contributingRenderPass = frame.renderPassesById[contribu tingRenderPassId]; | 826 policy.priorityCutoffWhenNotVisible)); |
| 488 appendQuadsForRenderSurfaceLayer(targetRenderPass, *it, contributing RenderPass, occlusionTracker, appendQuadsData); | 827 if (evicted_resources) { |
| 489 } else if (it.representsItself() && !it->visible_content_rect().IsEmpty( )) { | 828 active_tree_->SetContentsTexturesPurged(); |
| 490 bool hasOcclusionFromOutsideTargetSurface; | 829 if (pending_tree_) |
| 491 bool implDrawTransformIsUnknown = false; | 830 pending_tree_->SetContentsTexturesPurged(); |
| 492 if (occlusionTracker.Occluded(it->render_target(), it->visible_conte nt_rect(), it->draw_transform(), implDrawTransformIsUnknown, it->is_clipped(), i t->clip_rect(), &hasOcclusionFromOutsideTargetSurface)) | 831 client_->SetNeedsCommitOnImplThread(); |
| 493 appendQuadsData.hadOcclusionFromOutsideTargetSurface |= hasOcclu sionFromOutsideTargetSurface; | 832 client_->OnCanDrawStateChanged(CanDraw()); |
| 494 else { | 833 client_->RenewTreePriority(); |
| 495 DCHECK_EQ(activeTree(), it->layer_tree_impl()); | 834 } |
| 496 it->WillDraw(m_resourceProvider.get()); | 835 client_->SendManagedMemoryStats(); |
| 497 frame.willDrawLayers.push_back(*it); | 836 |
| 498 | 837 if (tile_manager_) { |
| 499 if (it->HasContributingDelegatedRenderPasses()) { | 838 GlobalStateThatImpactsTilePriority new_state(tile_manager_->GlobalState()); |
| 500 RenderPass::Id contributingRenderPassId = it->FirstContribut ingRenderPassId(); | 839 new_state.memory_limit_in_bytes = visible_ ? |
| 501 while (frame.renderPassesById.find(contributingRenderPassId) != frame.renderPassesById.end()) { | 840 policy.bytesLimitWhenVisible : |
| 502 RenderPass* renderPass = frame.renderPassesById[contribu tingRenderPassId]; | 841 policy.bytesLimitWhenNotVisible; |
| 503 | 842 new_state.memory_limit_policy = |
| 504 AppendQuadsData appendQuadsData(renderPass->id); | 843 ManagedMemoryPolicy::priorityCutoffToTileMemoryLimitPolicy( |
| 505 appendQuadsForLayer(renderPass, *it, occlusionTracker, a ppendQuadsData); | 844 visible_ ? |
| 506 | 845 policy.priorityCutoffWhenVisible : |
| 507 contributingRenderPassId = it->NextContributingRenderPas sId(contributingRenderPassId); | 846 policy.priorityCutoffWhenNotVisible); |
| 508 } | 847 tile_manager_->SetGlobalState(new_state); |
| 509 } | 848 } |
| 510 | 849 } |
| 511 appendQuadsForLayer(targetRenderPass, *it, occlusionTracker, app endQuadsData); | 850 |
| 512 } | 851 bool LayerTreeHostImpl::HasImplThread() const { |
| 513 | 852 return proxy_->HasImplThread(); |
| 514 ++m_cumulativeNumLayersDrawn; | 853 } |
| 515 } | 854 |
| 516 | 855 void LayerTreeHostImpl::ScheduleManageTiles() { |
| 517 if (appendQuadsData.hadOcclusionFromOutsideTargetSurface) | 856 if (client_) |
| 518 targetRenderPass->has_occlusion_from_outside_target_surface = true; | 857 client_->SetNeedsManageTilesOnImplThread(); |
| 519 | 858 } |
| 520 if (appendQuadsData.numMissingTiles) { | 859 |
| 521 m_cumulativeNumMissingTiles += appendQuadsData.numMissingTiles; | 860 void LayerTreeHostImpl::DidUploadVisibleHighResolutionTile() { |
| 522 bool layerHasAnimatingTransform = it->screen_space_transform_is_anim ating() || it->draw_transform_is_animating(); | 861 if (client_) |
| 523 if (layerHasAnimatingTransform) | 862 client_->DidUploadVisibleHighResolutionTileOnImplThread(); |
| 524 drawFrame = false; | 863 } |
| 525 } | 864 |
| 526 | 865 bool LayerTreeHostImpl::ShouldClearRootRenderPass() const { |
| 527 if (appendQuadsData.hadIncompleteTile) | 866 return settings_.shouldClearRootRenderPass; |
| 528 frame.containsIncompleteTile = true; | 867 } |
| 529 | 868 |
| 530 occlusionTracker.LeaveLayer(it); | 869 void LayerTreeHostImpl::SetManagedMemoryPolicy( |
| 531 } | 870 const ManagedMemoryPolicy& policy) { |
| 532 | 871 if (managed_memory_policy_ == policy) |
| 533 #ifndef NDEBUG | 872 return; |
| 534 for (size_t i = 0; i < frame.renderPasses.size(); ++i) { | 873 |
| 535 for (size_t j = 0; j < frame.renderPasses[i]->quad_list.size(); ++j) | 874 managed_memory_policy_ = policy; |
| 536 DCHECK(frame.renderPasses[i]->quad_list[j]->shared_quad_state); | 875 if (!proxy_->HasImplThread()) { |
| 537 DCHECK(frame.renderPassesById.find(frame.renderPasses[i]->id) | 876 // TODO(ccameron): In single-thread mode, this can be called on the main |
| 538 != frame.renderPassesById.end()); | 877 // thread by GLRenderer::OnMemoryAllocationChanged. |
| 539 } | 878 DebugScopedSetImplThread impl_thread(proxy_); |
| 540 #endif | 879 EnforceManagedMemoryPolicy(managed_memory_policy_); |
| 541 DCHECK(frame.renderPasses.back()->output_rect.origin().IsOrigin()); | 880 } else { |
| 542 | 881 DCHECK(proxy_->IsImplThread()); |
| 543 if (!activeTree()->has_transparent_background()) { | 882 EnforceManagedMemoryPolicy(managed_memory_policy_); |
| 544 frame.renderPasses.back()->has_transparent_background = false; | 883 } |
| 545 appendQuadsToFillScreen(frame.renderPasses.back(), rootLayer(), activeTr ee()->background_color(), occlusionTracker); | 884 // We always need to commit after changing the memory policy because the new |
| 546 } | 885 // limit can result in more or less content having texture allocated for it. |
| 547 | 886 client_->SetNeedsCommitOnImplThread(); |
| 548 if (drawFrame) | 887 } |
| 549 occlusionTracker.overdraw_metrics()->RecordMetrics(this); | 888 |
| 550 | 889 void LayerTreeHostImpl::OnVSyncParametersChanged(base::TimeTicks timebase, |
| 551 removeRenderPasses(CullRenderPassesWithNoQuads(), frame); | 890 base::TimeDelta interval) { |
| 552 m_renderer->DecideRenderPassAllocationsForFrame(frame.renderPasses); | 891 client_->OnVSyncParametersChanged(timebase, interval); |
| 553 removeRenderPasses(CullRenderPassesWithCachedTextures(*m_renderer), frame); | 892 } |
| 554 | 893 |
| 555 return drawFrame; | 894 void LayerTreeHostImpl::OnSendFrameToParentCompositorAck( |
| 556 } | 895 const CompositorFrameAck& ack) { |
| 557 | 896 if (!renderer_) |
| 558 void LayerTreeHostImpl::setBackgroundTickingEnabled(bool enabled) | 897 return; |
| 559 { | 898 |
| 560 // Lazily create the timeSource adapter so that we can vary the interval for testing. | 899 // TODO(piman): We may need to do some validation on this ack before |
| 561 if (!m_timeSourceClientAdapter) | 900 // processing it. |
| 562 m_timeSourceClientAdapter = LayerTreeHostImplTimeSourceAdapter::Create(t his, DelayBasedTimeSource::create(lowFrequencyAnimationInterval(), m_proxy->Curr entThread())); | 901 renderer_->ReceiveCompositorFrameAck(ack); |
| 563 | 902 } |
| 564 m_timeSourceClientAdapter->setActive(enabled); | 903 |
| 565 } | 904 void LayerTreeHostImpl::OnCanDrawStateChangedForTree() { |
| 566 | 905 client_->OnCanDrawStateChanged(CanDraw()); |
| 567 static inline RenderPass* findRenderPassById(RenderPass::Id renderPassId, const LayerTreeHostImpl::FrameData& frame) | 906 } |
| 568 { | 907 |
| 569 RenderPassIdHashMap::const_iterator it = frame.renderPassesById.find(renderP assId); | 908 CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() const { |
| 570 return it != frame.renderPassesById.end() ? it->second : NULL; | 909 CompositorFrameMetadata metadata; |
| 571 } | 910 metadata.device_scale_factor = device_scale_factor_; |
| 572 | 911 metadata.page_scale_factor = active_tree_->total_page_scale_factor(); |
| 573 static void removeRenderPassesRecursive(RenderPass::Id removeRenderPassId, Layer TreeHostImpl::FrameData& frame) | 912 metadata.viewport_size = active_tree_->ScrollableViewportSize(); |
| 574 { | 913 metadata.root_layer_size = active_tree_->ScrollableSize(); |
| 575 RenderPass* removeRenderPass = findRenderPassById(removeRenderPassId, frame) ; | 914 metadata.min_page_scale_factor = active_tree_->min_page_scale_factor(); |
| 576 // The pass was already removed by another quad - probably the original, and we are the replica. | 915 metadata.max_page_scale_factor = active_tree_->max_page_scale_factor(); |
| 577 if (!removeRenderPass) | 916 if (top_controls_manager_) { |
| 578 return; | 917 metadata.location_bar_offset = |
| 579 RenderPassList& renderPasses = frame.renderPasses; | 918 gfx::Vector2dF(0.f, top_controls_manager_->controls_top_offset()); |
| 580 RenderPassList::iterator toRemove = std::find(renderPasses.begin(), renderPa sses.end(), removeRenderPass); | 919 metadata.location_bar_content_translation = |
| 581 | 920 gfx::Vector2dF(0.f, top_controls_manager_->content_top_offset()); |
| 582 DCHECK(toRemove != renderPasses.end()); | 921 } |
| 583 | 922 |
| 584 scoped_ptr<RenderPass> removedPass = renderPasses.take(toRemove); | 923 if (!RootScrollLayer()) |
| 585 frame.renderPasses.erase(toRemove); | |
| 586 frame.renderPassesById.erase(removeRenderPassId); | |
| 587 | |
| 588 // Now follow up for all RenderPass quads and remove their RenderPasses recu rsively. | |
| 589 const QuadList& quadList = removedPass->quad_list; | |
| 590 QuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBe gin(); | |
| 591 for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) { | |
| 592 DrawQuad* currentQuad = (*quadListIterator); | |
| 593 if (currentQuad->material != DrawQuad::RENDER_PASS) | |
| 594 continue; | |
| 595 | |
| 596 RenderPass::Id nextRemoveRenderPassId = RenderPassDrawQuad::MaterialCast (currentQuad)->render_pass_id; | |
| 597 removeRenderPassesRecursive(nextRemoveRenderPassId, frame); | |
| 598 } | |
| 599 } | |
| 600 | |
| 601 bool LayerTreeHostImpl::CullRenderPassesWithCachedTextures::shouldRemoveRenderPa ss(const RenderPassDrawQuad& quad, const FrameData&) const | |
| 602 { | |
| 603 if (!quad.contents_changed_since_last_frame.IsEmpty()) { | |
| 604 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures have damage"); | |
| 605 return false; | |
| 606 } else if (!m_renderer.HaveCachedResourcesForRenderPassId(quad.render_pass_i d)) { | |
| 607 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures have no texture") ; | |
| 608 return false; | |
| 609 } | |
| 610 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures dropped!"); | |
| 611 return true; | |
| 612 } | |
| 613 | |
| 614 bool LayerTreeHostImpl::CullRenderPassesWithNoQuads::shouldRemoveRenderPass(cons t RenderPassDrawQuad& quad, const FrameData& frame) const | |
| 615 { | |
| 616 const RenderPass* renderPass = findRenderPassById(quad.render_pass_id, frame ); | |
| 617 if (!renderPass) | |
| 618 return false; | |
| 619 | |
| 620 // If any quad or RenderPass draws into this RenderPass, then keep it. | |
| 621 const QuadList& quadList = renderPass->quad_list; | |
| 622 for (QuadList::constBackToFrontIterator quadListIterator = quadList.backToFr ontBegin(); quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) { | |
| 623 DrawQuad* currentQuad = *quadListIterator; | |
| 624 | |
| 625 if (currentQuad->material != DrawQuad::RENDER_PASS) | |
| 626 return false; | |
| 627 | |
| 628 const RenderPass* contributingPass = findRenderPassById(RenderPassDrawQu ad::MaterialCast(currentQuad)->render_pass_id, frame); | |
| 629 if (contributingPass) | |
| 630 return false; | |
| 631 } | |
| 632 return true; | |
| 633 } | |
| 634 | |
| 635 // Defined for linking tests. | |
| 636 template CC_EXPORT void LayerTreeHostImpl::removeRenderPasses<LayerTreeHostImpl: :CullRenderPassesWithCachedTextures>(CullRenderPassesWithCachedTextures, FrameDa ta&); | |
| 637 template CC_EXPORT void LayerTreeHostImpl::removeRenderPasses<LayerTreeHostImpl: :CullRenderPassesWithNoQuads>(CullRenderPassesWithNoQuads, FrameData&); | |
| 638 | |
| 639 // static | |
| 640 template<typename RenderPassCuller> | |
| 641 void LayerTreeHostImpl::removeRenderPasses(RenderPassCuller culler, FrameData& f rame) | |
| 642 { | |
| 643 for (size_t it = culler.renderPassListBegin(frame.renderPasses); it != culle r.renderPassListEnd(frame.renderPasses); it = culler.renderPassListNext(it)) { | |
| 644 const RenderPass* currentPass = frame.renderPasses[it]; | |
| 645 const QuadList& quadList = currentPass->quad_list; | |
| 646 QuadList::constBackToFrontIterator quadListIterator = quadList.backToFro ntBegin(); | |
| 647 | |
| 648 for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator ) { | |
| 649 DrawQuad* currentQuad = *quadListIterator; | |
| 650 | |
| 651 if (currentQuad->material != DrawQuad::RENDER_PASS) | |
| 652 continue; | |
| 653 | |
| 654 RenderPassDrawQuad* renderPassQuad = static_cast<RenderPassDrawQuad* >(currentQuad); | |
| 655 if (!culler.shouldRemoveRenderPass(*renderPassQuad, frame)) | |
| 656 continue; | |
| 657 | |
| 658 // We are changing the vector in the middle of iteration. Because we | |
| 659 // delete render passes that draw into the current pass, we are | |
| 660 // guaranteed that any data from the iterator to the end will not | |
| 661 // change. So, capture the iterator position from the end of the | |
| 662 // list, and restore it after the change. | |
| 663 int positionFromEnd = frame.renderPasses.size() - it; | |
| 664 removeRenderPassesRecursive(renderPassQuad->render_pass_id, frame); | |
| 665 it = frame.renderPasses.size() - positionFromEnd; | |
| 666 DCHECK(frame.renderPasses.size() >= static_cast<size_t>(positionFrom End)); | |
| 667 } | |
| 668 } | |
| 669 } | |
| 670 | |
| 671 bool LayerTreeHostImpl::prepareToDraw(FrameData& frame) | |
| 672 { | |
| 673 TRACE_EVENT0("cc", "LayerTreeHostImpl::prepareToDraw"); | |
| 674 | |
| 675 activeTree()->UpdateDrawProperties(LayerTreeImpl::UPDATE_ACTIVE_TREE_FOR_DRA W); | |
| 676 | |
| 677 frame.renderSurfaceLayerList = &activeTree()->RenderSurfaceLayerList(); | |
| 678 frame.renderPasses.clear(); | |
| 679 frame.renderPassesById.clear(); | |
| 680 frame.willDrawLayers.clear(); | |
| 681 | |
| 682 if (!calculateRenderPasses(frame)) | |
| 683 return false; | |
| 684 | |
| 685 // If we return true, then we expect drawLayers() to be called before this f unction is called again. | |
| 686 return true; | |
| 687 } | |
| 688 | |
| 689 void LayerTreeHostImpl::EnforceManagedMemoryPolicy(const ManagedMemoryPolicy& po licy) | |
| 690 { | |
| 691 bool evictedResources = m_client->reduceContentsTextureMemoryOnImplThread( | |
| 692 m_visible ? policy.bytesLimitWhenVisible : policy.bytesLimitWhenNotVisib le, | |
| 693 ManagedMemoryPolicy::priorityCutoffToValue( | |
| 694 m_visible ? policy.priorityCutoffWhenVisible : policy.priorityCutoff WhenNotVisible)); | |
| 695 if (evictedResources) { | |
| 696 activeTree()->SetContentsTexturesPurged(); | |
| 697 if (pendingTree()) | |
| 698 pendingTree()->SetContentsTexturesPurged(); | |
| 699 m_client->setNeedsCommitOnImplThread(); | |
| 700 m_client->onCanDrawStateChanged(canDraw()); | |
| 701 m_client->renewTreePriority(); | |
| 702 } | |
| 703 m_client->sendManagedMemoryStats(); | |
| 704 | |
| 705 if (m_tileManager) { | |
| 706 GlobalStateThatImpactsTilePriority new_state(m_tileManager->GlobalState()) ; | |
| 707 new_state.memory_limit_in_bytes = m_visible ? policy.bytesLimitWhenVisible : policy.bytesLimitWhenNotVisible; | |
| 708 new_state.memory_limit_policy = ManagedMemoryPolicy::priorityCutoffToTileM emoryLimitPolicy( | |
| 709 m_visible ? policy.priorityCutoffWhenVisible : policy.priorityCutoffWh enNotVisible); | |
| 710 m_tileManager->SetGlobalState(new_state); | |
| 711 } | |
| 712 } | |
| 713 | |
| 714 bool LayerTreeHostImpl::HasImplThread() const | |
| 715 { | |
| 716 return m_proxy->HasImplThread(); | |
| 717 } | |
| 718 | |
| 719 void LayerTreeHostImpl::ScheduleManageTiles() | |
| 720 { | |
| 721 if (m_client) | |
| 722 m_client->setNeedsManageTilesOnImplThread(); | |
| 723 } | |
| 724 | |
| 725 void LayerTreeHostImpl::DidUploadVisibleHighResolutionTile() | |
| 726 { | |
| 727 if (m_client) | |
| 728 m_client->didUploadVisibleHighResolutionTileOnImplThread(); | |
| 729 } | |
| 730 | |
| 731 bool LayerTreeHostImpl::ShouldClearRootRenderPass() const | |
| 732 { | |
| 733 return m_settings.shouldClearRootRenderPass; | |
| 734 } | |
| 735 | |
| 736 void LayerTreeHostImpl::SetManagedMemoryPolicy(const ManagedMemoryPolicy& policy ) | |
| 737 { | |
| 738 if (m_managedMemoryPolicy == policy) | |
| 739 return; | |
| 740 | |
| 741 m_managedMemoryPolicy = policy; | |
| 742 if (!m_proxy->HasImplThread()) { | |
| 743 // FIXME: In single-thread mode, this can be called on the main thread | |
| 744 // by GLRenderer::onMemoryAllocationChanged. | |
| 745 DebugScopedSetImplThread implThread(m_proxy); | |
| 746 EnforceManagedMemoryPolicy(m_managedMemoryPolicy); | |
| 747 } else { | |
| 748 DCHECK(m_proxy->IsImplThread()); | |
| 749 EnforceManagedMemoryPolicy(m_managedMemoryPolicy); | |
| 750 } | |
| 751 // We always need to commit after changing the memory policy because the new | |
| 752 // limit can result in more or less content having texture allocated for it. | |
| 753 m_client->setNeedsCommitOnImplThread(); | |
| 754 } | |
| 755 | |
| 756 void LayerTreeHostImpl::OnVSyncParametersChanged(base::TimeTicks timebase, base: :TimeDelta interval) | |
| 757 { | |
| 758 m_client->onVSyncParametersChanged(timebase, interval); | |
| 759 } | |
| 760 | |
| 761 void LayerTreeHostImpl::OnSendFrameToParentCompositorAck(const CompositorFrameAc k& ack) | |
| 762 { | |
| 763 if (!m_renderer) | |
| 764 return; | |
| 765 | |
| 766 // TODO(piman): We may need to do some validation on this ack before process ing it. | |
| 767 m_renderer->ReceiveCompositorFrameAck(ack); | |
| 768 } | |
| 769 | |
| 770 void LayerTreeHostImpl::OnCanDrawStateChangedForTree(LayerTreeImpl*) | |
| 771 { | |
| 772 m_client->onCanDrawStateChanged(canDraw()); | |
| 773 } | |
| 774 | |
| 775 CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() const | |
| 776 { | |
| 777 CompositorFrameMetadata metadata; | |
| 778 metadata.device_scale_factor = m_deviceScaleFactor; | |
| 779 metadata.page_scale_factor = activeTree()->total_page_scale_factor(); | |
| 780 metadata.viewport_size = activeTree()->ScrollableViewportSize(); | |
| 781 metadata.root_layer_size = activeTree()->ScrollableSize(); | |
| 782 metadata.min_page_scale_factor = activeTree()->min_page_scale_factor(); | |
| 783 metadata.max_page_scale_factor = activeTree()->max_page_scale_factor(); | |
| 784 if (m_topControlsManager) { | |
| 785 metadata.location_bar_offset = gfx::Vector2dF(0.f, m_topControlsManager- >controls_top_offset()); | |
| 786 metadata.location_bar_content_translation = gfx::Vector2dF(0.f, m_topCon trolsManager->content_top_offset()); | |
| 787 } | |
| 788 | |
| 789 if (!rootScrollLayer()) | |
| 790 return metadata; | |
| 791 | |
| 792 metadata.root_scroll_offset = rootScrollLayer()->scroll_offset() + rootScrol lLayer()->scroll_delta(); | |
| 793 | |
| 794 return metadata; | 924 return metadata; |
| 795 } | 925 |
| 796 | 926 metadata.root_scroll_offset = RootScrollLayer()->scroll_offset() + |
| 797 void LayerTreeHostImpl::drawLayers(FrameData& frame) | 927 RootScrollLayer()->scroll_delta(); |
| 798 { | 928 |
| 799 TRACE_EVENT0("cc", "LayerTreeHostImpl::drawLayers"); | 929 return metadata; |
| 800 DCHECK(canDraw()); | 930 } |
| 801 DCHECK(!frame.renderPasses.empty()); | 931 |
| 802 | 932 void LayerTreeHostImpl::DrawLayers(FrameData* frame) { |
| 803 // FIXME: use the frame begin time from the overall compositor scheduler. | 933 TRACE_EVENT0("cc", "LayerTreeHostImpl::drawLayers"); |
|
enne (OOO)
2013/03/13 05:22:05
DrawLayers
danakj
2013/03/13 15:49:11
Done.
| |
| 804 // This value is currently inaccessible because it is up in Chromium's | 934 DCHECK(CanDraw()); |
| 805 // RenderWidget. | 935 DCHECK(!frame->render_passes.empty()); |
| 806 m_fpsCounter->saveTimeStamp(base::TimeTicks::Now()); | 936 |
| 807 | 937 // FIXME: use the frame begin time from the overall compositor scheduler. |
| 808 if (m_tileManager) { | 938 // This value is currently inaccessible because it is up in Chromium's |
| 809 m_memoryHistory->SaveEntry( | 939 // RenderWidget. |
| 810 m_tileManager->memory_stats_from_last_assign()); | 940 fps_counter_->saveTimeStamp(base::TimeTicks::Now()); |
| 811 } | 941 |
| 812 | 942 if (tile_manager_) { |
| 813 if (m_debugState.showHudRects()) | 943 memory_history_->SaveEntry( |
| 814 m_debugRectHistory->saveDebugRectsForCurrentFrame(rootLayer(), *frame.re nderSurfaceLayerList, frame.occludingScreenSpaceRects, frame.nonOccludingScreenS paceRects, m_debugState); | 944 tile_manager_->memory_stats_from_last_assign()); |
| 815 | 945 } |
| 816 if (m_debugState.traceAllRenderedFrames) { | 946 |
| 817 TRACE_EVENT_INSTANT1("cc.debug", "Frame", | 947 if (debug_state_.showHudRects()) { |
| 818 "frame", ValueToString(frameStateAsValue())); | 948 debug_rect_history_->saveDebugRectsForCurrentFrame( |
| 819 } | 949 active_tree_->root_layer(), |
| 820 | 950 *frame->render_surface_layer_list, |
| 821 // Because the contents of the HUD depend on everything else in the frame, t he contents | 951 frame->occluding_screen_space_rects, |
| 822 // of its texture are updated as the last thing before the frame is drawn. | 952 frame->non_occluding_screen_space_rects, |
| 823 if (m_activeTree->hud_layer()) | 953 debug_state_); |
| 824 m_activeTree->hud_layer()->updateHudTexture(m_resourceProvider.get()); | 954 } |
| 825 | 955 |
| 826 m_renderer->DrawFrame(frame.renderPasses); | 956 if (debug_state_.traceAllRenderedFrames) { |
| 827 // The render passes should be consumed by the renderer. | 957 TRACE_EVENT_INSTANT1("cc.debug", "Frame", |
| 828 DCHECK(frame.renderPasses.empty()); | 958 "frame", ValueToString(FrameStateAsValue())); |
| 829 frame.renderPassesById.clear(); | 959 } |
| 830 | 960 |
| 831 // The next frame should start by assuming nothing has changed, and changes are noted as they occur. | 961 // Because the contents of the HUD depend on everything else in the frame, the |
| 832 for (unsigned int i = 0; i < frame.renderSurfaceLayerList->size(); i++) | 962 // contents of its texture are updated as the last thing before the frame is |
| 833 (*frame.renderSurfaceLayerList)[i]->render_surface()->damage_tracker()-> DidDrawDamagedArea(); | 963 // drawn. |
| 834 rootLayer()->ResetAllChangeTrackingForSubtree(); | 964 if (active_tree_->hud_layer()) |
| 835 updateAnimationState(); | 965 active_tree_->hud_layer()->updateHudTexture(resource_provider_.get()); |
| 836 } | 966 |
| 837 | 967 renderer_->DrawFrame(frame->render_passes); |
| 838 void LayerTreeHostImpl::didDrawAllLayers(const FrameData& frame) | 968 // The render passes should be consumed by the renderer. |
| 839 { | 969 DCHECK(frame->render_passes.empty()); |
| 840 for (size_t i = 0; i < frame.willDrawLayers.size(); ++i) | 970 frame->render_passes_by_id.clear(); |
| 841 frame.willDrawLayers[i]->DidDraw(m_resourceProvider.get()); | 971 |
| 842 | 972 // The next frame should start by assuming nothing has changed, and changes |
| 843 // Once all layers have been drawn, pending texture uploads should no | 973 // are noted as they occur. |
| 844 // longer block future uploads. | 974 for (unsigned int i = 0; i < frame->render_surface_layer_list->size(); i++) { |
| 845 m_resourceProvider->MarkPendingUploadsAsNonBlocking(); | 975 (*frame->render_surface_layer_list)[i]->render_surface()->damage_tracker()-> |
| 846 } | 976 DidDrawDamagedArea(); |
| 847 | 977 } |
| 848 void LayerTreeHostImpl::finishAllRendering() | 978 active_tree_->root_layer()->ResetAllChangeTrackingForSubtree(); |
| 849 { | 979 UpdateAnimationState(); |
| 850 if (m_renderer) | 980 } |
| 851 m_renderer->Finish(); | 981 |
| 852 } | 982 void LayerTreeHostImpl::DidDrawAllLayers(const FrameData& frame) { |
| 853 | 983 for (size_t i = 0; i < frame.will_draw_layers.size(); ++i) |
| 854 bool LayerTreeHostImpl::isContextLost() | 984 frame.will_draw_layers[i]->DidDraw(resource_provider_.get()); |
| 855 { | 985 |
| 856 DCHECK(m_proxy->IsImplThread()); | 986 // Once all layers have been drawn, pending texture uploads should no |
| 857 return m_renderer && m_renderer->IsContextLost(); | 987 // longer block future uploads. |
| 858 } | 988 resource_provider_->MarkPendingUploadsAsNonBlocking(); |
| 859 | 989 } |
| 860 const RendererCapabilities& LayerTreeHostImpl::rendererCapabilities() const | 990 |
| 861 { | 991 void LayerTreeHostImpl::FinishAllRendering() { |
| 862 return m_renderer->Capabilities(); | 992 if (renderer_) |
| 863 } | 993 renderer_->Finish(); |
| 864 | 994 } |
| 865 bool LayerTreeHostImpl::swapBuffers() | 995 |
| 866 { | 996 bool LayerTreeHostImpl::IsContextLost() { |
| 867 if (m_tileManager) | 997 DCHECK(proxy_->IsImplThread()); |
| 868 m_tileManager->DidCompleteFrame(); | 998 return renderer_ && renderer_->IsContextLost(); |
| 869 return m_renderer->SwapBuffers(); | 999 } |
| 870 } | 1000 |
| 871 | 1001 const RendererCapabilities& LayerTreeHostImpl::GetRendererCapabilities() const { |
| 872 gfx::Size LayerTreeHostImpl::DeviceViewportSize() const | 1002 return renderer_->Capabilities(); |
| 873 { | 1003 } |
| 874 return m_deviceViewportSize; | 1004 |
| 875 } | 1005 bool LayerTreeHostImpl::SwapBuffers() { |
| 876 | 1006 if (tile_manager_) |
| 877 const LayerTreeSettings& LayerTreeHostImpl::Settings() const | 1007 tile_manager_->DidCompleteFrame(); |
| 878 { | 1008 return renderer_->SwapBuffers(); |
| 879 return m_settings; | 1009 } |
| 880 } | 1010 |
| 881 | 1011 gfx::Size LayerTreeHostImpl::DeviceViewportSize() const { |
| 882 void LayerTreeHostImpl::DidLoseOutputSurface() | 1012 return device_viewport_size(); |
| 883 { | 1013 } |
| 884 m_client->didLoseOutputSurfaceOnImplThread(); | 1014 |
| 885 } | 1015 const LayerTreeSettings& LayerTreeHostImpl::Settings() const { |
| 886 | 1016 return settings(); |
| 887 void LayerTreeHostImpl::OnSwapBuffersComplete() | 1017 } |
| 888 { | 1018 |
| 889 m_client->onSwapBuffersCompleteOnImplThread(); | 1019 void LayerTreeHostImpl::DidLoseOutputSurface() { |
| 890 } | 1020 client_->DidLoseOutputSurfaceOnImplThread(); |
| 891 | 1021 } |
| 892 void LayerTreeHostImpl::readback(void* pixels, | 1022 |
| 893 gfx::Rect rect_in_device_viewport) | 1023 void LayerTreeHostImpl::OnSwapBuffersComplete() { |
| 894 { | 1024 client_->OnSwapBuffersCompleteOnImplThread(); |
| 895 DCHECK(m_renderer); | 1025 } |
| 896 m_renderer->GetFramebufferPixels(pixels, rect_in_device_viewport); | 1026 |
| 1027 void LayerTreeHostImpl::Readback(void* pixels, | |
| 1028 gfx::Rect rect_in_device_viewport) { | |
| 1029 DCHECK(renderer_); | |
| 1030 renderer_->GetFramebufferPixels(pixels, rect_in_device_viewport); | |
| 897 } | 1031 } |
| 898 | 1032 |
| 899 bool LayerTreeHostImpl::haveRootScrollLayer() const { | 1033 bool LayerTreeHostImpl::haveRootScrollLayer() const { |
| 900 return rootScrollLayer(); | 1034 return RootScrollLayer(); |
| 901 } | 1035 } |
| 902 | 1036 |
| 903 float LayerTreeHostImpl::rootScrollLayerTotalScrollY() const { | 1037 float LayerTreeHostImpl::rootScrollLayerTotalScrollY() const { |
| 904 if (LayerImpl* layer = rootScrollLayer()) | 1038 if (LayerImpl* layer = RootScrollLayer()) |
| 905 return layer->scroll_offset().y() + layer->scroll_delta().y(); | 1039 return layer->scroll_offset().y() + layer->scroll_delta().y(); |
| 906 return 0.0f; | 1040 return 0.0f; |
| 907 } | 1041 } |
| 908 | 1042 |
| 909 LayerImpl* LayerTreeHostImpl::rootLayer() const | 1043 LayerImpl* LayerTreeHostImpl::RootLayer() const { |
| 910 { | 1044 return active_tree_->root_layer(); |
| 911 return m_activeTree->RootLayer(); | 1045 } |
| 912 } | 1046 |
| 913 | 1047 LayerImpl* LayerTreeHostImpl::RootScrollLayer() const { |
| 914 LayerImpl* LayerTreeHostImpl::rootScrollLayer() const | 1048 return active_tree_->RootScrollLayer(); |
| 915 { | 1049 } |
| 916 return m_activeTree->RootScrollLayer(); | 1050 |
| 917 } | 1051 LayerImpl* LayerTreeHostImpl::CurrentlyScrollingLayer() const { |
| 918 | 1052 return active_tree_->CurrentlyScrollingLayer(); |
| 919 LayerImpl* LayerTreeHostImpl::currentlyScrollingLayer() const | |
| 920 { | |
| 921 return m_activeTree->CurrentlyScrollingLayer(); | |
| 922 } | 1053 } |
| 923 | 1054 |
| 924 // Content layers can be either directly scrollable or contained in an outer | 1055 // Content layers can be either directly scrollable or contained in an outer |
| 925 // scrolling layer which applies the scroll transform. Given a content layer, | 1056 // scrolling layer which applies the scroll transform. Given a content layer, |
| 926 // this function returns the associated scroll layer if any. | 1057 // this function returns the associated scroll layer if any. |
| 927 static LayerImpl* findScrollLayerForContentLayer(LayerImpl* layerImpl) | 1058 static LayerImpl* FindScrollLayerForContentLayer(LayerImpl* layer_impl) { |
| 928 { | 1059 if (!layer_impl) |
| 929 if (!layerImpl) | |
| 930 return 0; | |
| 931 | |
| 932 if (layerImpl->scrollable()) | |
| 933 return layerImpl; | |
| 934 | |
| 935 if (layerImpl->DrawsContent() && layerImpl->parent() && layerImpl->parent()- >scrollable()) | |
| 936 return layerImpl->parent(); | |
| 937 | |
| 938 return 0; | 1060 return 0; |
| 939 } | 1061 |
| 940 | 1062 if (layer_impl->scrollable()) |
| 941 void LayerTreeHostImpl::createPendingTree() | 1063 return layer_impl; |
| 942 { | 1064 |
| 943 CHECK(!m_pendingTree); | 1065 if (layer_impl->DrawsContent() && |
| 944 if (m_recycleTree) | 1066 layer_impl->parent() && |
| 945 m_recycleTree.swap(m_pendingTree); | 1067 layer_impl->parent()->scrollable()) |
| 946 else | 1068 return layer_impl->parent(); |
| 947 m_pendingTree = LayerTreeImpl::create(this); | 1069 |
| 948 m_client->onCanDrawStateChanged(canDraw()); | 1070 return 0; |
| 949 m_client->onHasPendingTreeStateChanged(pendingTree()); | 1071 } |
| 950 TRACE_EVENT_ASYNC_BEGIN0("cc", "PendingTree", m_pendingTree.get()); | 1072 |
| 951 TRACE_EVENT_ASYNC_STEP0("cc", | 1073 void LayerTreeHostImpl::CreatePendingTree() { |
| 952 "PendingTree", m_pendingTree.get(), "waiting"); | 1074 CHECK(!pending_tree_); |
| 953 } | 1075 if (recycle_tree_) |
| 954 | 1076 recycle_tree_.swap(pending_tree_); |
| 955 void LayerTreeHostImpl::checkForCompletedTileUploads() | 1077 else |
| 956 { | 1078 pending_tree_ = LayerTreeImpl::create(this); |
| 957 DCHECK(!m_client->isInsideDraw()) << "Checking for completed uploads within a draw may trigger spurious redraws."; | 1079 client_->OnCanDrawStateChanged(CanDraw()); |
| 958 if (m_tileManager) | 1080 client_->OnHasPendingTreeStateChanged(pending_tree_); |
| 959 m_tileManager->CheckForCompletedTileUploads(); | 1081 TRACE_EVENT_ASYNC_BEGIN0("cc", "PendingTree", pending_tree_.get()); |
| 960 } | 1082 TRACE_EVENT_ASYNC_STEP0("cc", |
| 961 | 1083 "PendingTree", pending_tree_.get(), "waiting"); |
| 962 bool LayerTreeHostImpl::activatePendingTreeIfNeeded() | 1084 } |
| 963 { | 1085 |
| 964 if (!pendingTree()) | 1086 void LayerTreeHostImpl::CheckForCompletedTileUploads() { |
| 965 return false; | 1087 DCHECK(!client_->IsInsideDraw()) << |
| 966 | 1088 "Checking for completed uploads within a draw may trigger " |
| 967 CHECK(m_tileManager); | 1089 "spurious redraws."; |
| 968 | 1090 if (tile_manager_) |
| 969 pendingTree()->UpdateDrawProperties(LayerTreeImpl::UPDATE_PENDING_TREE); | 1091 tile_manager_->CheckForCompletedTileUploads(); |
| 970 | 1092 } |
| 971 TRACE_EVENT_ASYNC_STEP1("cc", | 1093 |
| 972 "PendingTree", m_pendingTree.get(), "activate", | 1094 bool LayerTreeHostImpl::ActivatePendingTreeIfNeeded() { |
| 973 "state", ValueToString(activationStateAsValue())); | 1095 if (!pending_tree_) |
| 974 | 1096 return false; |
| 975 // It's always fine to activate to an empty tree. Otherwise, only | 1097 |
| 976 // activate once all visible resources in pending tree are ready | 1098 CHECK(tile_manager_); |
| 977 // or tile manager has no work scheduled for pending tree. | 1099 |
| 978 if (activeTree()->RootLayer() && | 1100 pending_tree_->UpdateDrawProperties(LayerTreeImpl::UPDATE_PENDING_TREE); |
| 979 !pendingTree()->AreVisibleResourcesReady()) { | 1101 |
| 980 // In smoothness takes priority mode, the pending tree's priorities are | 1102 TRACE_EVENT_ASYNC_STEP1("cc", |
| 981 // ignored, so the tile manager may not have work for it even though it | 1103 "PendingTree", pending_tree_.get(), "activate", |
| 982 // is simultaneously not ready to be activated. | 1104 "state", ValueToString(ActivationStateAsValue())); |
| 983 if (m_tileManager->GlobalState().tree_priority == | 1105 |
| 984 SMOOTHNESS_TAKES_PRIORITY || | 1106 // It's always fine to activate to an empty tree. Otherwise, only |
| 985 m_tileManager->HasPendingWorkScheduled(PENDING_TREE)) { | 1107 // activate once all visible resources in pending tree are ready |
| 986 TRACE_EVENT_ASYNC_STEP0("cc", | 1108 // or tile manager has no work scheduled for pending tree. |
| 987 "PendingTree", | 1109 if (active_tree_->root_layer() && |
| 988 m_pendingTree.get(), | 1110 !pending_tree_->AreVisibleResourcesReady()) { |
| 989 "waiting"); | 1111 // In smoothness takes priority mode, the pending tree's priorities are |
| 990 return false; | 1112 // ignored, so the tile manager may not have work for it even though it |
| 991 } | 1113 // is simultaneously not ready to be activated. |
| 1114 if (tile_manager_->GlobalState().tree_priority == | |
| 1115 SMOOTHNESS_TAKES_PRIORITY || | |
| 1116 tile_manager_->HasPendingWorkScheduled(PENDING_TREE)) { | |
| 1117 TRACE_EVENT_ASYNC_STEP0("cc", | |
| 1118 "PendingTree", | |
| 1119 pending_tree_.get(), | |
| 1120 "waiting"); | |
| 1121 return false; | |
| 992 } | 1122 } |
| 993 | 1123 } |
| 994 activatePendingTree(); | 1124 |
| 995 return true; | 1125 ActivatePendingTree(); |
| 996 } | 1126 return true; |
| 997 | 1127 } |
| 998 void LayerTreeHostImpl::activatePendingTree() | 1128 |
| 999 { | 1129 void LayerTreeHostImpl::ActivatePendingTree() { |
| 1000 CHECK(m_pendingTree); | 1130 CHECK(pending_tree_); |
| 1001 TRACE_EVENT_ASYNC_END0("cc", "PendingTree", m_pendingTree.get()); | 1131 TRACE_EVENT_ASYNC_END0("cc", "PendingTree", pending_tree_.get()); |
| 1002 | 1132 |
| 1003 m_activeTree->PushPersistedState(m_pendingTree.get()); | 1133 active_tree_->PushPersistedState(pending_tree_.get()); |
| 1004 if (m_pendingTree->needs_full_tree_sync()) | 1134 if (pending_tree_->needs_full_tree_sync()) { |
| 1005 m_activeTree->SetRootLayer(TreeSynchronizer::synchronizeTrees(m_pendingT ree->RootLayer(), m_activeTree->DetachLayerTree(), m_activeTree.get())); | 1135 active_tree_->SetRootLayer( |
| 1006 TreeSynchronizer::pushProperties(m_pendingTree->RootLayer(), m_activeTree->R ootLayer()); | 1136 TreeSynchronizer::synchronizeTrees(pending_tree_->root_layer(), |
| 1007 DCHECK(!m_recycleTree); | 1137 active_tree_->DetachLayerTree(), |
| 1008 | 1138 active_tree_.get())); |
| 1009 m_pendingTree->PushPropertiesTo(m_activeTree.get()); | 1139 } |
| 1010 | 1140 TreeSynchronizer::pushProperties(pending_tree_->root_layer(), |
| 1011 // Now that we've synced everything from the pending tree to the active | 1141 active_tree_->root_layer()); |
| 1012 // tree, rename the pending tree the recycle tree so we can reuse it on the | 1142 DCHECK(!recycle_tree_); |
| 1013 // next sync. | 1143 |
| 1014 m_pendingTree.swap(m_recycleTree); | 1144 pending_tree_->PushPropertiesTo(active_tree_.get()); |
| 1015 m_recycleTree->ClearRenderSurfaces(); | 1145 |
| 1016 | 1146 // Now that we've synced everything from the pending tree to the active |
| 1017 m_activeTree->DidBecomeActive(); | 1147 // tree, rename the pending tree the recycle tree so we can reuse it on the |
| 1018 | 1148 // next sync. |
| 1019 // Reduce wasted memory now that unlinked resources are guaranteed not | 1149 pending_tree_.swap(recycle_tree_); |
| 1020 // to be used. | 1150 recycle_tree_->ClearRenderSurfaces(); |
| 1021 m_client->reduceWastedContentsTextureMemoryOnImplThread(); | 1151 |
| 1022 | 1152 active_tree_->DidBecomeActive(); |
| 1023 m_client->onCanDrawStateChanged(canDraw()); | 1153 |
| 1024 m_client->onHasPendingTreeStateChanged(pendingTree()); | 1154 // Reduce wasted memory now that unlinked resources are guaranteed not |
| 1025 m_client->setNeedsRedrawOnImplThread(); | 1155 // to be used. |
| 1026 m_client->renewTreePriority(); | 1156 client_->ReduceWastedContentsTextureMemoryOnImplThread(); |
| 1027 | 1157 |
| 1028 if (m_tileManager && m_debugState.continuousPainting) { | 1158 client_->OnCanDrawStateChanged(CanDraw()); |
| 1029 RenderingStats stats; | 1159 client_->OnHasPendingTreeStateChanged(pending_tree_); |
| 1030 m_tileManager->GetRenderingStats(&stats); | 1160 client_->SetNeedsRedrawOnImplThread(); |
| 1031 m_paintTimeCounter->SaveRasterizeTime(stats.totalRasterizeTimeForNowBins OnPendingTree, m_activeTree->source_frame_number()); | 1161 client_->RenewTreePriority(); |
| 1162 | |
| 1163 if (tile_manager_ && debug_state_.continuousPainting) { | |
| 1164 RenderingStats stats; | |
| 1165 tile_manager_->GetRenderingStats(&stats); | |
| 1166 paint_time_counter_->SaveRasterizeTime( | |
| 1167 stats.totalRasterizeTimeForNowBinsOnPendingTree, | |
| 1168 active_tree_->source_frame_number()); | |
| 1169 } | |
| 1170 } | |
| 1171 | |
| 1172 void LayerTreeHostImpl::SetVisible(bool visible) { | |
| 1173 DCHECK(proxy_->IsImplThread()); | |
| 1174 | |
| 1175 if (visible_ == visible) | |
| 1176 return; | |
| 1177 visible_ = visible; | |
| 1178 DidVisibilityChange(this, visible_); | |
| 1179 EnforceManagedMemoryPolicy(managed_memory_policy_); | |
| 1180 | |
| 1181 if (!renderer_) | |
| 1182 return; | |
| 1183 | |
| 1184 renderer_->SetVisible(visible); | |
| 1185 | |
| 1186 SetBackgroundTickingEnabled( | |
| 1187 !visible_ && | |
| 1188 !animation_registrar_->active_animation_controllers().empty()); | |
| 1189 } | |
| 1190 | |
| 1191 bool LayerTreeHostImpl::InitializeRenderer( | |
| 1192 scoped_ptr<OutputSurface> output_surface) { | |
| 1193 // Since we will create a new resource provider, we cannot continue to use | |
| 1194 // the old resources (i.e. render_surfaces and texture IDs). Clear them | |
| 1195 // before we destroy the old resource provider. | |
| 1196 if (active_tree_->root_layer()) | |
| 1197 ClearRenderSurfaces(); | |
| 1198 if (active_tree_->root_layer()) | |
| 1199 SendDidLoseOutputSurfaceRecursive(active_tree_->root_layer()); | |
| 1200 if (pending_tree_ && pending_tree_->root_layer()) | |
| 1201 SendDidLoseOutputSurfaceRecursive(pending_tree_->root_layer()); | |
| 1202 if (recycle_tree_ && recycle_tree_->root_layer()) | |
| 1203 SendDidLoseOutputSurfaceRecursive(recycle_tree_->root_layer()); | |
| 1204 | |
| 1205 // Note: order is important here. | |
| 1206 renderer_.reset(); | |
| 1207 tile_manager_.reset(); | |
| 1208 resource_provider_.reset(); | |
| 1209 output_surface_.reset(); | |
| 1210 | |
| 1211 if (!output_surface->BindToClient(this)) | |
| 1212 return false; | |
| 1213 | |
| 1214 scoped_ptr<ResourceProvider> resource_provider = | |
| 1215 ResourceProvider::Create(output_surface.get()); | |
| 1216 if (!resource_provider) | |
| 1217 return false; | |
| 1218 | |
| 1219 if (settings_.implSidePainting) { | |
| 1220 tile_manager_.reset(new TileManager(this, | |
| 1221 resource_provider.get(), | |
| 1222 settings_.numRasterThreads, | |
| 1223 settings_.useCheapnessEstimator, | |
| 1224 settings_.useColorEstimator, | |
| 1225 settings_.predictionBenchmarking)); | |
| 1226 tile_manager_->SetRecordRenderingStats(debug_state_.recordRenderingStats()); | |
| 1227 } | |
| 1228 | |
| 1229 if (output_surface->capabilities().has_parent_compositor) { | |
| 1230 renderer_ = DelegatingRenderer::Create(this, | |
| 1231 output_surface.get(), | |
| 1232 resource_provider.get()); | |
| 1233 } else if (output_surface->context3d()) { | |
| 1234 renderer_ = GLRenderer::create(this, | |
| 1235 output_surface.get(), | |
| 1236 resource_provider.get()); | |
| 1237 } else if (output_surface->software_device()) { | |
| 1238 renderer_ = SoftwareRenderer::Create(this, | |
| 1239 output_surface.get(), | |
| 1240 resource_provider.get()); | |
| 1241 } | |
| 1242 if (!renderer_) | |
| 1243 return false; | |
| 1244 | |
| 1245 resource_provider_ = resource_provider.Pass(); | |
| 1246 output_surface_ = output_surface.Pass(); | |
| 1247 | |
| 1248 if (!visible_) | |
| 1249 renderer_->SetVisible(visible_); | |
| 1250 | |
| 1251 client_->OnCanDrawStateChanged(CanDraw()); | |
| 1252 | |
| 1253 // See note in LayerTreeImpl::UpdateDrawProperties. Renderer needs | |
| 1254 // to be initialized to get max texture size. | |
| 1255 active_tree_->set_needs_update_draw_properties(); | |
| 1256 if (pending_tree_) | |
| 1257 pending_tree_->set_needs_update_draw_properties(); | |
| 1258 | |
| 1259 return true; | |
| 1260 } | |
| 1261 | |
| 1262 void LayerTreeHostImpl::SetViewportSize(gfx::Size layout_viewport_size, | |
| 1263 gfx::Size device_viewport_size) { | |
| 1264 if (layout_viewport_size == layout_viewport_size_ && | |
| 1265 device_viewport_size == device_viewport_size_) | |
| 1266 return; | |
| 1267 | |
| 1268 if (pending_tree_ && device_viewport_size_ != device_viewport_size) | |
| 1269 active_tree_->SetViewportSizeInvalid(); | |
| 1270 | |
| 1271 layout_viewport_size_ = layout_viewport_size; | |
| 1272 device_viewport_size_ = device_viewport_size; | |
| 1273 | |
| 1274 UpdateMaxScrollOffset(); | |
| 1275 | |
| 1276 if (renderer_) | |
| 1277 renderer_->ViewportChanged(); | |
| 1278 | |
| 1279 client_->OnCanDrawStateChanged(CanDraw()); | |
| 1280 } | |
| 1281 | |
| 1282 static void AdjustScrollsForPageScaleChange(LayerImpl* layer_impl, | |
| 1283 float page_scale_change) { | |
| 1284 if (!layer_impl) | |
| 1285 return; | |
| 1286 | |
| 1287 if (layer_impl->scrollable()) { | |
| 1288 // We need to convert impl-side scroll deltas to page_scale space. | |
| 1289 gfx::Vector2dF scroll_delta = layer_impl->scroll_delta(); | |
| 1290 scroll_delta.Scale(page_scale_change); | |
| 1291 layer_impl->SetScrollDelta(scroll_delta); | |
| 1292 } | |
| 1293 | |
| 1294 for (size_t i = 0; i < layer_impl->children().size(); ++i) | |
| 1295 AdjustScrollsForPageScaleChange(layer_impl->children()[i], | |
| 1296 page_scale_change); | |
| 1297 } | |
| 1298 | |
| 1299 void LayerTreeHostImpl::SetDeviceScaleFactor(float device_scale_factor) { | |
| 1300 if (device_scale_factor == device_scale_factor_) | |
| 1301 return; | |
| 1302 device_scale_factor_ = device_scale_factor; | |
| 1303 | |
| 1304 UpdateMaxScrollOffset(); | |
| 1305 } | |
| 1306 | |
| 1307 void LayerTreeHostImpl::UpdateMaxScrollOffset() { | |
| 1308 active_tree_->UpdateMaxScrollOffset(); | |
| 1309 } | |
| 1310 | |
| 1311 void LayerTreeHostImpl::setActiveTreeNeedsUpdateDrawProperties() { | |
| 1312 active_tree_->set_needs_update_draw_properties(); | |
| 1313 } | |
| 1314 | |
| 1315 void LayerTreeHostImpl::setNeedsRedraw() { | |
| 1316 client_->SetNeedsRedrawOnImplThread(); | |
| 1317 } | |
| 1318 | |
| 1319 bool LayerTreeHostImpl::EnsureRenderSurfaceLayerList() { | |
| 1320 active_tree_->UpdateDrawProperties(LayerTreeImpl::UPDATE_ACTIVE_TREE); | |
| 1321 return active_tree_->RenderSurfaceLayerList().size(); | |
| 1322 } | |
| 1323 | |
| 1324 InputHandlerClient::ScrollStatus LayerTreeHostImpl::ScrollBegin( | |
| 1325 gfx::Point viewport_point, InputHandlerClient::ScrollInputType type) { | |
| 1326 TRACE_EVENT0("cc", "LayerTreeHostImpl::scrollBegin"); | |
| 1327 | |
| 1328 if (top_controls_manager_) | |
| 1329 top_controls_manager_->ScrollBegin(); | |
| 1330 | |
| 1331 DCHECK(!CurrentlyScrollingLayer()); | |
| 1332 ClearCurrentlyScrollingLayer(); | |
| 1333 | |
| 1334 if (!EnsureRenderSurfaceLayerList()) | |
| 1335 return ScrollIgnored; | |
| 1336 | |
| 1337 gfx::PointF device_viewport_point = gfx::ScalePoint(viewport_point, | |
| 1338 device_scale_factor_); | |
| 1339 | |
| 1340 // First find out which layer was hit from the saved list of visible layers | |
| 1341 // in the most recent frame. | |
| 1342 LayerImpl* layer_impl = LayerTreeHostCommon::findLayerThatIsHitByPoint( | |
| 1343 device_viewport_point, active_tree_->RenderSurfaceLayerList()); | |
| 1344 | |
| 1345 // Walk up the hierarchy and look for a scrollable layer. | |
| 1346 LayerImpl* potentially_scrolling_layer_impl = 0; | |
| 1347 for (; layer_impl; layer_impl = layer_impl->parent()) { | |
| 1348 // The content layer can also block attempts to scroll outside the main | |
| 1349 // thread. | |
| 1350 ScrollStatus status = layer_impl->TryScroll(device_viewport_point, type); | |
| 1351 if (status == ScrollOnMainThread) { | |
| 1352 num_main_thread_scrolls_++; | |
| 1353 UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", true); | |
| 1354 return ScrollOnMainThread; | |
| 1032 } | 1355 } |
| 1033 } | 1356 |
| 1034 | 1357 LayerImpl* scroll_layer_impl = FindScrollLayerForContentLayer(layer_impl); |
| 1035 void LayerTreeHostImpl::setVisible(bool visible) | 1358 if (!scroll_layer_impl) |
| 1036 { | 1359 continue; |
| 1037 DCHECK(m_proxy->IsImplThread()); | 1360 |
| 1038 | 1361 status = scroll_layer_impl->TryScroll(device_viewport_point, type); |
| 1039 if (m_visible == visible) | 1362 |
| 1040 return; | 1363 // If any layer wants to divert the scroll event to the main thread, abort. |
| 1041 m_visible = visible; | 1364 if (status == ScrollOnMainThread) { |
| 1042 didVisibilityChange(this, m_visible); | 1365 num_main_thread_scrolls_++; |
| 1043 EnforceManagedMemoryPolicy(m_managedMemoryPolicy); | 1366 UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", true); |
| 1044 | 1367 return ScrollOnMainThread; |
| 1045 if (!m_renderer) | |
| 1046 return; | |
| 1047 | |
| 1048 m_renderer->SetVisible(visible); | |
| 1049 | |
| 1050 setBackgroundTickingEnabled(!m_visible && !m_animationRegistrar->active_anim ation_controllers().empty()); | |
| 1051 } | |
| 1052 | |
| 1053 bool LayerTreeHostImpl::initializeRenderer(scoped_ptr<OutputSurface> outputSurfa ce) | |
| 1054 { | |
| 1055 // Since we will create a new resource provider, we cannot continue to use | |
| 1056 // the old resources (i.e. renderSurfaces and texture IDs). Clear them | |
| 1057 // before we destroy the old resource provider. | |
| 1058 if (rootLayer()) | |
| 1059 clearRenderSurfaces(); | |
| 1060 if (activeTree()->RootLayer()) | |
| 1061 sendDidLoseOutputSurfaceRecursive(activeTree()->RootLayer()); | |
| 1062 if (pendingTree() && pendingTree()->RootLayer()) | |
| 1063 sendDidLoseOutputSurfaceRecursive(pendingTree()->RootLayer()); | |
| 1064 if (m_recycleTree && m_recycleTree->RootLayer()) | |
| 1065 sendDidLoseOutputSurfaceRecursive(m_recycleTree->RootLayer()); | |
| 1066 | |
| 1067 // Note: order is important here. | |
| 1068 m_renderer.reset(); | |
| 1069 m_tileManager.reset(); | |
| 1070 m_resourceProvider.reset(); | |
| 1071 m_outputSurface.reset(); | |
| 1072 | |
| 1073 if (!outputSurface->BindToClient(this)) | |
| 1074 return false; | |
| 1075 | |
| 1076 scoped_ptr<ResourceProvider> resourceProvider = ResourceProvider::Create(out putSurface.get()); | |
| 1077 if (!resourceProvider) | |
| 1078 return false; | |
| 1079 | |
| 1080 if (m_settings.implSidePainting) { | |
| 1081 m_tileManager.reset(new TileManager(this, | |
| 1082 resourceProvider.get(), | |
| 1083 m_settings.numRasterThreads, | |
| 1084 m_settings.useCheapnessEstimator, | |
| 1085 m_settings.useColorEstimator, | |
| 1086 m_settings.predictionBenchmarking)); | |
| 1087 m_tileManager->SetRecordRenderingStats(m_debugState.recordRenderingStats ()); | |
| 1088 } | 1368 } |
| 1089 | 1369 |
| 1090 if (outputSurface->capabilities().has_parent_compositor) | 1370 if (status == ScrollStarted && !potentially_scrolling_layer_impl) |
| 1091 m_renderer = DelegatingRenderer::Create(this, outputSurface.get(), resou rceProvider.get()); | 1371 potentially_scrolling_layer_impl = scroll_layer_impl; |
| 1092 else if (outputSurface->context3d()) | 1372 } |
| 1093 m_renderer = GLRenderer::create(this, outputSurface.get(), resourceProvi der.get()); | 1373 |
| 1094 else if (outputSurface->software_device()) | 1374 // When hiding top controls is enabled and the controls are hidden or |
| 1095 m_renderer = SoftwareRenderer::Create(this, outputSurface.get(), resourc eProvider.get()); | 1375 // overlaying the content, force scrolls to be enabled on the root layer to |
| 1096 if (!m_renderer) | 1376 // allow bringing the top controls back into view. |
| 1097 return false; | 1377 if (!potentially_scrolling_layer_impl && top_controls_manager_ && |
| 1098 | 1378 top_controls_manager_->content_top_offset() != |
| 1099 m_resourceProvider = resourceProvider.Pass(); | 1379 settings_.topControlsHeight) { |
| 1100 m_outputSurface = outputSurface.Pass(); | 1380 potentially_scrolling_layer_impl = RootScrollLayer(); |
| 1101 | 1381 } |
| 1102 if (!m_visible) | 1382 |
| 1103 m_renderer->SetVisible(m_visible); | 1383 if (potentially_scrolling_layer_impl) { |
| 1104 | 1384 active_tree_->set_currently_scrolling_layer( |
| 1105 m_client->onCanDrawStateChanged(canDraw()); | 1385 potentially_scrolling_layer_impl); |
| 1106 | 1386 should_bubble_scrolls_ = (type != NonBubblingGesture); |
| 1107 // See note in LayerTreeImpl::UpdateDrawProperties. Renderer needs | 1387 wheel_scrolling_ = (type == Wheel); |
| 1108 // to be initialized to get max texture size. | 1388 num_impl_thread_scrolls_++; |
| 1109 activeTree()->set_needs_update_draw_properties(); | 1389 client_->RenewTreePriority(); |
| 1110 if (pendingTree()) | 1390 UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", false); |
| 1111 pendingTree()->set_needs_update_draw_properties(); | 1391 return ScrollStarted; |
| 1112 | 1392 } |
| 1113 return true; | 1393 return ScrollIgnored; |
| 1114 } | 1394 } |
| 1115 | 1395 |
| 1116 void LayerTreeHostImpl::setViewportSize(const gfx::Size& layoutViewportSize, con st gfx::Size& deviceViewportSize) | 1396 gfx::Vector2dF LayerTreeHostImpl::ScrollLayerWithViewportSpaceDelta( |
| 1117 { | 1397 LayerImpl* layer_impl, |
| 1118 if (layoutViewportSize == m_layoutViewportSize && deviceViewportSize == m_de viceViewportSize) | 1398 float scale_from_viewport_to_screen_space, |
| 1119 return; | 1399 gfx::PointF viewport_point, |
| 1120 | 1400 gfx::Vector2dF viewport_delta) { |
| 1121 if (pendingTree() && m_deviceViewportSize != deviceViewportSize) | 1401 // Layers with non-invertible screen space transforms should not have passed |
| 1122 activeTree()->SetViewportSizeInvalid(); | 1402 // the scroll hit test in the first place. |
| 1123 | 1403 DCHECK(layer_impl->screen_space_transform().IsInvertible()); |
| 1124 m_layoutViewportSize = layoutViewportSize; | 1404 gfx::Transform inverse_screen_space_transform( |
| 1125 m_deviceViewportSize = deviceViewportSize; | 1405 gfx::Transform::kSkipInitialization); |
| 1126 | 1406 bool did_invert = layer_impl->screen_space_transform().GetInverse( |
| 1127 updateMaxScrollOffset(); | 1407 &inverse_screen_space_transform); |
| 1128 | 1408 // TODO: With the advent of impl-side crolling for non-root layers, we may |
| 1129 if (m_renderer) | 1409 // need to explicitly handle uninvertible transforms here. |
| 1130 m_renderer->ViewportChanged(); | 1410 DCHECK(did_invert); |
| 1131 | 1411 |
| 1132 m_client->onCanDrawStateChanged(canDraw()); | 1412 gfx::PointF screen_space_point = |
| 1133 } | 1413 gfx::ScalePoint(viewport_point, scale_from_viewport_to_screen_space); |
| 1134 | 1414 |
| 1135 static void adjustScrollsForPageScaleChange(LayerImpl* layerImpl, float pageScal eChange) | 1415 gfx::Vector2dF screen_space_delta = viewport_delta; |
| 1136 { | 1416 screen_space_delta.Scale(scale_from_viewport_to_screen_space); |
| 1137 if (!layerImpl) | 1417 |
| 1138 return; | 1418 // First project the scroll start and end points to local layer space to find |
| 1139 | 1419 // the scroll delta in layer coordinates. |
| 1140 if (layerImpl->scrollable()) { | 1420 bool start_clipped, end_clipped; |
| 1141 // We need to convert impl-side scroll deltas to pageScale space. | 1421 gfx::PointF screen_space_end_point = screen_space_point + screen_space_delta; |
| 1142 gfx::Vector2dF scrollDelta = layerImpl->scroll_delta(); | 1422 gfx::PointF local_start_point = |
| 1143 scrollDelta.Scale(pageScaleChange); | 1423 MathUtil::projectPoint(inverse_screen_space_transform, |
| 1144 layerImpl->SetScrollDelta(scrollDelta); | 1424 screen_space_point, |
| 1425 start_clipped); | |
| 1426 gfx::PointF local_end_point = | |
| 1427 MathUtil::projectPoint(inverse_screen_space_transform, | |
| 1428 screen_space_end_point, | |
| 1429 end_clipped); | |
| 1430 | |
| 1431 // In general scroll point coordinates should not get clipped. | |
| 1432 DCHECK(!start_clipped); | |
| 1433 DCHECK(!end_clipped); | |
| 1434 if (start_clipped || end_clipped) | |
| 1435 return gfx::Vector2dF(); | |
| 1436 | |
| 1437 // local_start_point and local_end_point are in content space but we want to | |
| 1438 // move them to layer space for scrolling. | |
| 1439 float width_scale = 1.f / layer_impl->contents_scale_x(); | |
| 1440 float height_scale = 1.f / layer_impl->contents_scale_y(); | |
| 1441 local_start_point.Scale(width_scale, height_scale); | |
| 1442 local_end_point.Scale(width_scale, height_scale); | |
| 1443 | |
| 1444 // Apply the scroll delta. | |
| 1445 gfx::Vector2dF previous_delta = layer_impl->scroll_delta(); | |
| 1446 layer_impl->ScrollBy(local_end_point - local_start_point); | |
| 1447 | |
| 1448 // Get the end point in the layer's content space so we can apply its | |
| 1449 // screenSpaceTransform. | |
| 1450 gfx::PointF actual_local_end_point = local_start_point + | |
| 1451 layer_impl->scroll_delta() - | |
| 1452 previous_delta; | |
| 1453 gfx::PointF actual_local_content_end_point = | |
| 1454 gfx::ScalePoint(actual_local_end_point, | |
| 1455 1.f / width_scale, | |
| 1456 1.f / height_scale); | |
| 1457 | |
| 1458 // Calculate the applied scroll delta in viewport space coordinates. | |
| 1459 gfx::PointF actual_screen_space_end_point = | |
| 1460 MathUtil::mapPoint(layer_impl->screen_space_transform(), | |
| 1461 actual_local_content_end_point, | |
| 1462 end_clipped); | |
| 1463 DCHECK(!end_clipped); | |
| 1464 if (end_clipped) | |
| 1465 return gfx::Vector2dF(); | |
| 1466 gfx::PointF actual_viewport_end_point = | |
| 1467 gfx::ScalePoint(actual_screen_space_end_point, | |
| 1468 1.f / scale_from_viewport_to_screen_space); | |
| 1469 return actual_viewport_end_point - viewport_point; | |
| 1470 } | |
| 1471 | |
| 1472 static gfx::Vector2dF ScrollLayerWithLocalDelta(LayerImpl* layer_impl, | |
| 1473 gfx::Vector2dF localDelta) { | |
| 1474 gfx::Vector2dF previous_delta(layer_impl->scroll_delta()); | |
| 1475 layer_impl->ScrollBy(localDelta); | |
| 1476 return layer_impl->scroll_delta() - previous_delta; | |
| 1477 } | |
| 1478 | |
| 1479 bool LayerTreeHostImpl::ScrollBy(gfx::Point viewport_point, | |
| 1480 gfx::Vector2dF scroll_delta) { | |
| 1481 TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollBy"); | |
| 1482 if (!CurrentlyScrollingLayer()) | |
| 1483 return false; | |
| 1484 | |
| 1485 gfx::Vector2dF pending_delta = scroll_delta; | |
| 1486 bool did_scroll = false; | |
| 1487 | |
| 1488 for (LayerImpl* layer_impl = CurrentlyScrollingLayer(); | |
| 1489 layer_impl; | |
| 1490 layer_impl = layer_impl->parent()) { | |
| 1491 if (!layer_impl->scrollable()) | |
| 1492 continue; | |
| 1493 | |
| 1494 gfx::Vector2dF applied_delta; | |
| 1495 if (top_controls_manager_ && layer_impl == RootScrollLayer()) | |
| 1496 pending_delta = top_controls_manager_->ScrollBy(pending_delta); | |
| 1497 | |
| 1498 // Gesture events need to be transformed from viewport coordinates to local | |
| 1499 // layer coordinates so that the scrolling contents exactly follow the | |
| 1500 // user's finger. In contrast, wheel events represent a fixed amount of | |
| 1501 // scrolling so we can just apply them directly. | |
| 1502 if (!wheel_scrolling_) { | |
| 1503 float scale_from_viewport_to_screen_space = device_scale_factor_; | |
| 1504 applied_delta = | |
| 1505 ScrollLayerWithViewportSpaceDelta(layer_impl, | |
| 1506 scale_from_viewport_to_screen_space, | |
| 1507 viewport_point, pending_delta); | |
| 1508 } else | |
|
enne (OOO)
2013/03/13 05:22:05
{}
danakj
2013/03/13 15:49:11
Done.
| |
| 1509 applied_delta = ScrollLayerWithLocalDelta(layer_impl, pending_delta); | |
| 1510 | |
| 1511 // If the layer wasn't able to move, try the next one in the hierarchy. | |
| 1512 float move_threshold_squared = 0.1f * 0.1f; | |
| 1513 if (applied_delta.LengthSquared() < move_threshold_squared) { | |
| 1514 if (should_bubble_scrolls_ || !did_lock_scrolling_layer_) | |
| 1515 continue; | |
| 1516 else | |
| 1517 break; | |
| 1145 } | 1518 } |
| 1146 | 1519 did_scroll = true; |
| 1147 for (size_t i = 0; i < layerImpl->children().size(); ++i) | 1520 did_lock_scrolling_layer_ = true; |
| 1148 adjustScrollsForPageScaleChange(layerImpl->children()[i], pageScaleChang e); | 1521 if (!should_bubble_scrolls_) { |
| 1149 } | 1522 active_tree_->set_currently_scrolling_layer(layer_impl); |
| 1150 | 1523 break; |
| 1151 void LayerTreeHostImpl::setDeviceScaleFactor(float deviceScaleFactor) | |
| 1152 { | |
| 1153 if (deviceScaleFactor == m_deviceScaleFactor) | |
| 1154 return; | |
| 1155 m_deviceScaleFactor = deviceScaleFactor; | |
| 1156 | |
| 1157 updateMaxScrollOffset(); | |
| 1158 } | |
| 1159 | |
| 1160 void LayerTreeHostImpl::updateMaxScrollOffset() | |
| 1161 { | |
| 1162 activeTree()->UpdateMaxScrollOffset(); | |
| 1163 } | |
| 1164 | |
| 1165 void LayerTreeHostImpl::setActiveTreeNeedsUpdateDrawProperties() | |
| 1166 { | |
| 1167 activeTree()->set_needs_update_draw_properties(); | |
| 1168 } | |
| 1169 | |
| 1170 void LayerTreeHostImpl::setNeedsRedraw() | |
| 1171 { | |
| 1172 m_client->setNeedsRedrawOnImplThread(); | |
| 1173 } | |
| 1174 | |
| 1175 bool LayerTreeHostImpl::ensureRenderSurfaceLayerList() | |
| 1176 { | |
| 1177 activeTree()->UpdateDrawProperties(LayerTreeImpl::UPDATE_ACTIVE_TREE); | |
| 1178 return activeTree()->RenderSurfaceLayerList().size(); | |
| 1179 } | |
| 1180 | |
| 1181 InputHandlerClient::ScrollStatus LayerTreeHostImpl::scrollBegin(gfx::Point viewp ortPoint, InputHandlerClient::ScrollInputType type) | |
| 1182 { | |
| 1183 TRACE_EVENT0("cc", "LayerTreeHostImpl::scrollBegin"); | |
| 1184 | |
| 1185 if (m_topControlsManager) | |
| 1186 m_topControlsManager->ScrollBegin(); | |
| 1187 | |
| 1188 DCHECK(!currentlyScrollingLayer()); | |
| 1189 clearCurrentlyScrollingLayer(); | |
| 1190 | |
| 1191 if (!ensureRenderSurfaceLayerList()) | |
| 1192 return ScrollIgnored; | |
| 1193 | |
| 1194 gfx::PointF deviceViewportPoint = gfx::ScalePoint(viewportPoint, m_deviceSca leFactor); | |
| 1195 | |
| 1196 // First find out which layer was hit from the saved list of visible layers | |
| 1197 // in the most recent frame. | |
| 1198 LayerImpl* layerImpl = LayerTreeHostCommon::findLayerThatIsHitByPoint(device ViewportPoint, activeTree()->RenderSurfaceLayerList()); | |
| 1199 | |
| 1200 // Walk up the hierarchy and look for a scrollable layer. | |
| 1201 LayerImpl* potentiallyScrollingLayerImpl = 0; | |
| 1202 for (; layerImpl; layerImpl = layerImpl->parent()) { | |
| 1203 // The content layer can also block attempts to scroll outside the main thread. | |
| 1204 if (layerImpl->TryScroll(deviceViewportPoint, type) == ScrollOnMainThrea d) { | |
| 1205 m_numMainThreadScrolls++; | |
| 1206 UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", true); | |
| 1207 return ScrollOnMainThread; | |
| 1208 } | |
| 1209 | |
| 1210 LayerImpl* scrollLayerImpl = findScrollLayerForContentLayer(layerImpl); | |
| 1211 if (!scrollLayerImpl) | |
| 1212 continue; | |
| 1213 | |
| 1214 ScrollStatus status = scrollLayerImpl->TryScroll(deviceViewportPoint, ty pe); | |
| 1215 | |
| 1216 // If any layer wants to divert the scroll event to the main thread, abo rt. | |
| 1217 if (status == ScrollOnMainThread) { | |
| 1218 m_numMainThreadScrolls++; | |
| 1219 UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", true); | |
| 1220 return ScrollOnMainThread; | |
| 1221 } | |
| 1222 | |
| 1223 if (status == ScrollStarted && !potentiallyScrollingLayerImpl) | |
| 1224 potentiallyScrollingLayerImpl = scrollLayerImpl; | |
| 1225 } | 1524 } |
| 1226 | 1525 |
| 1227 // When hiding top controls is enabled and the controls are hidden or | 1526 // If the applied delta is within 45 degrees of the input delta, bail out to |
| 1228 // overlaying the content, force scrolls to be enabled on the root layer to | 1527 // make it easier to scroll just one layer in one direction without |
| 1229 // allow bringing the top controls back into view. | 1528 // affecting any of its parents. |
| 1230 if (!potentiallyScrollingLayerImpl && m_topControlsManager && | 1529 float angle_threshold = 45; |
| 1231 m_topControlsManager->content_top_offset() != m_settings.topControls Height) { | 1530 if (MathUtil::smallestAngleBetweenVectors( |
| 1232 potentiallyScrollingLayerImpl = rootScrollLayer(); | 1531 applied_delta, pending_delta) < angle_threshold) { |
| 1532 pending_delta = gfx::Vector2d(); | |
| 1533 break; | |
| 1233 } | 1534 } |
| 1234 | 1535 |
| 1235 if (potentiallyScrollingLayerImpl) { | 1536 // Allow further movement only on an axis perpendicular to the direction in |
| 1236 m_activeTree->set_currently_scrolling_layer(potentiallyScrollingLayerImp l); | 1537 // which the layer moved. |
| 1237 m_shouldBubbleScrolls = (type != NonBubblingGesture); | 1538 gfx::Vector2dF perpendicularAxis(-applied_delta.y(), applied_delta.x()); |
|
enne (OOO)
2013/03/13 05:22:05
perpendicular_axis
danakj
2013/03/13 15:49:11
Done.
| |
| 1238 m_wheelScrolling = (type == Wheel); | 1539 pending_delta = MathUtil::projectVector(pending_delta, perpendicularAxis); |
| 1239 m_numImplThreadScrolls++; | 1540 |
| 1240 m_client->renewTreePriority(); | 1541 if (gfx::ToFlooredVector2d(pending_delta).IsZero()) |
| 1241 UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", false); | 1542 break; |
| 1242 return ScrollStarted; | 1543 } |
| 1243 } | 1544 |
| 1244 return ScrollIgnored; | 1545 if (did_scroll) { |
| 1245 } | 1546 client_->SetNeedsCommitOnImplThread(); |
| 1246 | 1547 client_->SetNeedsRedrawOnImplThread(); |
| 1247 gfx::Vector2dF LayerTreeHostImpl::scrollLayerWithViewportSpaceDelta(LayerImpl* l ayerImpl, float scaleFromViewportToScreenSpace, gfx::PointF viewportPoint, gfx:: Vector2dF viewportDelta) | 1548 client_->RenewTreePriority(); |
| 1248 { | 1549 } |
| 1249 // Layers with non-invertible screen space transforms should not have passed the scroll hit | 1550 return did_scroll; |
| 1250 // test in the first place. | 1551 } |
| 1251 DCHECK(layerImpl->screen_space_transform().IsInvertible()); | 1552 |
| 1252 gfx::Transform inverseScreenSpaceTransform(gfx::Transform::kSkipInitializati on); | 1553 void LayerTreeHostImpl::ClearCurrentlyScrollingLayer() { |
| 1253 bool didInvert = layerImpl->screen_space_transform().GetInverse(&inverseScre enSpaceTransform); | 1554 active_tree_->ClearCurrentlyScrollingLayer(); |
| 1254 // TODO: With the advent of impl-side crolling for non-root layers, we may | 1555 did_lock_scrolling_layer_ = false; |
| 1255 // need to explicitly handle uninvertible transforms here. | 1556 } |
| 1256 DCHECK(didInvert); | 1557 |
| 1257 | 1558 void LayerTreeHostImpl::ScrollEnd() { |
| 1258 gfx::PointF screenSpacePoint = gfx::ScalePoint(viewportPoint, scaleFromViewp ortToScreenSpace); | 1559 if (top_controls_manager_) |
| 1259 | 1560 top_controls_manager_->ScrollEnd(); |
| 1260 gfx::Vector2dF screenSpaceDelta = viewportDelta; | 1561 ClearCurrentlyScrollingLayer(); |
| 1261 screenSpaceDelta.Scale(scaleFromViewportToScreenSpace); | 1562 } |
| 1262 | 1563 |
| 1263 // First project the scroll start and end points to local layer space to fin d the scroll delta | 1564 void LayerTreeHostImpl::PinchGestureBegin() { |
| 1264 // in layer coordinates. | 1565 pinch_gesture_active_ = true; |
| 1265 bool startClipped, endClipped; | 1566 previous_pinch_anchor_ = gfx::Point(); |
| 1266 gfx::PointF screenSpaceEndPoint = screenSpacePoint + screenSpaceDelta; | 1567 client_->RenewTreePriority(); |
| 1267 gfx::PointF localStartPoint = MathUtil::projectPoint(inverseScreenSpaceTrans form, screenSpacePoint, startClipped); | 1568 } |
| 1268 gfx::PointF localEndPoint = MathUtil::projectPoint(inverseScreenSpaceTransfo rm, screenSpaceEndPoint, endClipped); | 1569 |
| 1269 | 1570 void LayerTreeHostImpl::PinchGestureUpdate(float magnify_delta, |
| 1270 // In general scroll point coordinates should not get clipped. | 1571 gfx::Point anchor) { |
| 1271 DCHECK(!startClipped); | 1572 TRACE_EVENT0("cc", "LayerTreeHostImpl::pinchGestureUpdate"); |
|
enne (OOO)
2013/03/13 05:22:05
PinchGestureUpdate
danakj
2013/03/13 15:49:11
Done.
| |
| 1272 DCHECK(!endClipped); | 1573 |
| 1273 if (startClipped || endClipped) | 1574 if (!RootScrollLayer()) |
| 1274 return gfx::Vector2dF(); | 1575 return; |
| 1275 | 1576 |
| 1276 // localStartPoint and localEndPoint are in content space but we want to mov e them to layer space for scrolling. | 1577 // Keep the center-of-pinch anchor specified by (x, y) in a stable |
| 1277 float widthScale = 1.f / layerImpl->contents_scale_x(); | 1578 // position over the course of the magnify. |
| 1278 float heightScale = 1.f / layerImpl->contents_scale_y(); | 1579 float page_scale_delta = active_tree_->page_scale_delta(); |
| 1279 localStartPoint.Scale(widthScale, heightScale); | 1580 gfx::PointF previous_scale_anchor = |
| 1280 localEndPoint.Scale(widthScale, heightScale); | 1581 gfx::ScalePoint(anchor, 1 / page_scale_delta); |
| 1281 | 1582 active_tree_->SetPageScaleDelta(page_scale_delta * magnify_delta); |
| 1282 // Apply the scroll delta. | 1583 page_scale_delta = active_tree_->page_scale_delta(); |
| 1283 gfx::Vector2dF previousDelta = layerImpl->scroll_delta(); | 1584 gfx::PointF new_scale_anchor = |
| 1284 layerImpl->ScrollBy(localEndPoint - localStartPoint); | 1585 gfx::ScalePoint(anchor, 1 / page_scale_delta); |
| 1285 | 1586 gfx::Vector2dF move = previous_scale_anchor - new_scale_anchor; |
| 1286 // Get the end point in the layer's content space so we can apply its screen SpaceTransform. | 1587 |
| 1287 gfx::PointF actualLocalEndPoint = localStartPoint + layerImpl->scroll_delta( ) - previousDelta; | 1588 previous_pinch_anchor_ = anchor; |
| 1288 gfx::PointF actualLocalContentEndPoint = gfx::ScalePoint(actualLocalEndPoint , 1 / widthScale, 1 / heightScale); | 1589 |
| 1289 | 1590 move.Scale(1 / active_tree_->page_scale_factor()); |
| 1290 // Calculate the applied scroll delta in viewport space coordinates. | 1591 |
| 1291 gfx::PointF actualScreenSpaceEndPoint = MathUtil::mapPoint(layerImpl->screen _space_transform(), actualLocalContentEndPoint, endClipped); | 1592 RootScrollLayer()->ScrollBy(move); |
| 1292 DCHECK(!endClipped); | 1593 |
| 1293 if (endClipped) | 1594 if (RootScrollLayer()->scrollbar_animation_controller()) { |
| 1294 return gfx::Vector2dF(); | 1595 RootScrollLayer()->scrollbar_animation_controller()-> |
| 1295 gfx::PointF actualViewportEndPoint = gfx::ScalePoint(actualScreenSpaceEndPoi nt, 1 / scaleFromViewportToScreenSpace); | 1596 didPinchGestureUpdate(base::TimeTicks::Now()); |
| 1296 return actualViewportEndPoint - viewportPoint; | 1597 } |
| 1297 } | 1598 |
| 1298 | 1599 client_->SetNeedsCommitOnImplThread(); |
| 1299 static gfx::Vector2dF scrollLayerWithLocalDelta(LayerImpl& layerImpl, gfx::Vecto r2dF localDelta) | 1600 client_->SetNeedsRedrawOnImplThread(); |
| 1300 { | 1601 client_->RenewTreePriority(); |
| 1301 gfx::Vector2dF previousDelta(layerImpl.scroll_delta()); | 1602 } |
| 1302 layerImpl.ScrollBy(localDelta); | 1603 |
| 1303 return layerImpl.scroll_delta() - previousDelta; | 1604 void LayerTreeHostImpl::PinchGestureEnd() { |
| 1304 } | 1605 pinch_gesture_active_ = false; |
| 1305 | 1606 |
| 1306 bool LayerTreeHostImpl::scrollBy(const gfx::Point& viewportPoint, | 1607 if (RootScrollLayer() && |
| 1307 const gfx::Vector2dF& scrollDelta) | 1608 RootScrollLayer()->scrollbar_animation_controller()) { |
| 1308 { | 1609 RootScrollLayer()->scrollbar_animation_controller()-> |
| 1309 TRACE_EVENT0("cc", "LayerTreeHostImpl::scrollBy"); | 1610 didPinchGestureEnd(base::TimeTicks::Now()); |
| 1310 if (!currentlyScrollingLayer()) | 1611 } |
| 1311 return false; | 1612 |
| 1312 | 1613 client_->SetNeedsCommitOnImplThread(); |
| 1313 gfx::Vector2dF pendingDelta = scrollDelta; | 1614 } |
| 1314 bool didScroll = false; | 1615 |
| 1315 | 1616 static void CollectScrollDeltas(ScrollAndScaleSet* scroll_info, |
| 1316 for (LayerImpl* layerImpl = currentlyScrollingLayer(); layerImpl; layerImpl = layerImpl->parent()) { | 1617 LayerImpl* layer_impl) { |
| 1317 if (!layerImpl->scrollable()) | 1618 if (!layer_impl) |
| 1318 continue; | 1619 return; |
| 1319 | 1620 |
| 1320 gfx::Vector2dF appliedDelta; | 1621 gfx::Vector2d scroll_delta = |
| 1321 if (m_topControlsManager && layerImpl == rootScrollLayer()) | 1622 gfx::ToFlooredVector2d(layer_impl->scroll_delta()); |
| 1322 pendingDelta = m_topControlsManager->ScrollBy(pendingDelta); | 1623 if (!scroll_delta.IsZero()) { |
| 1323 | 1624 LayerTreeHostCommon::ScrollUpdateInfo scroll; |
| 1324 // Gesture events need to be transformed from viewport coordinates to lo cal layer coordinates | 1625 scroll.layerId = layer_impl->id(); |
| 1325 // so that the scrolling contents exactly follow the user's finger. In c ontrast, wheel | 1626 scroll.scrollDelta = scroll_delta; |
| 1326 // events represent a fixed amount of scrolling so we can just apply the m directly. | 1627 scroll_info->scrolls.push_back(scroll); |
| 1327 if (!m_wheelScrolling) { | 1628 layer_impl->SetSentScrollDelta(scroll_delta); |
| 1328 float scaleFromViewportToScreenSpace = m_deviceScaleFactor; | 1629 } |
| 1329 appliedDelta = scrollLayerWithViewportSpaceDelta(layerImpl, scaleFro mViewportToScreenSpace, viewportPoint, pendingDelta); | 1630 |
| 1330 } else | 1631 for (size_t i = 0; i < layer_impl->children().size(); ++i) |
| 1331 appliedDelta = scrollLayerWithLocalDelta(*layerImpl, pendingDelta); | 1632 CollectScrollDeltas(scroll_info, layer_impl->children()[i]); |
| 1332 | 1633 } |
| 1333 // If the layer wasn't able to move, try the next one in the hierarchy. | 1634 |
| 1334 float moveThresholdSquared = 0.1f * 0.1f; | 1635 scoped_ptr<ScrollAndScaleSet> LayerTreeHostImpl::ProcessScrollDeltas() { |
| 1335 if (appliedDelta.LengthSquared() < moveThresholdSquared) { | 1636 scoped_ptr<ScrollAndScaleSet> scroll_info(new ScrollAndScaleSet()); |
| 1336 if (m_shouldBubbleScrolls || !m_didLockScrollingLayer) | 1637 |
| 1337 continue; | 1638 CollectScrollDeltas(scroll_info.get(), active_tree_->root_layer()); |
| 1338 else | 1639 scroll_info->pageScaleDelta = active_tree_->page_scale_delta(); |
| 1339 break; | 1640 active_tree_->set_sent_page_scale_delta(scroll_info->pageScaleDelta); |
| 1340 } | 1641 |
| 1341 didScroll = true; | 1642 return scroll_info.Pass(); |
| 1342 m_didLockScrollingLayer = true; | 1643 } |
| 1343 if (!m_shouldBubbleScrolls) { | 1644 |
| 1344 m_activeTree->set_currently_scrolling_layer(layerImpl); | 1645 void LayerTreeHostImpl::SetFullRootLayerDamage() { |
| 1345 break; | 1646 if (active_tree_->root_layer()) { |
| 1346 } | 1647 RenderSurfaceImpl* render_surface = |
| 1347 | 1648 active_tree_->root_layer()->render_surface(); |
| 1348 // If the applied delta is within 45 degrees of the input delta, bail ou t to make it easier | 1649 if (render_surface) |
| 1349 // to scroll just one layer in one direction without affecting any of it s parents. | 1650 render_surface->damage_tracker()->ForceFullDamageNextUpdate(); |
| 1350 float angleThreshold = 45; | 1651 } |
| 1351 if (MathUtil::smallestAngleBetweenVectors(appliedDelta, pendingDelta) < angleThreshold) { | 1652 } |
| 1352 pendingDelta = gfx::Vector2d(); | 1653 |
| 1353 break; | 1654 void LayerTreeHostImpl::AnimatePageScale(base::TimeTicks time) { |
| 1354 } | 1655 if (!page_scale_animation_ || !RootScrollLayer()) |
| 1355 | 1656 return; |
| 1356 // Allow further movement only on an axis perpendicular to the direction in which the layer | 1657 |
| 1357 // moved. | 1658 double monotonic_time = (time - base::TimeTicks()).InSecondsF(); |
| 1358 gfx::Vector2dF perpendicularAxis(-appliedDelta.y(), appliedDelta.x()); | 1659 gfx::Vector2dF scroll_total = RootScrollLayer()->scroll_offset() + |
| 1359 pendingDelta = MathUtil::projectVector(pendingDelta, perpendicularAxis); | 1660 RootScrollLayer()->scroll_delta(); |
| 1360 | 1661 |
| 1361 if (gfx::ToFlooredVector2d(pendingDelta).IsZero()) | 1662 active_tree_->SetPageScaleDelta( |
| 1362 break; | 1663 page_scale_animation_->PageScaleFactorAtTime(monotonic_time) / |
| 1363 } | 1664 active_tree_->page_scale_factor()); |
| 1364 | 1665 gfx::Vector2dF next_scroll = |
| 1365 if (didScroll) { | 1666 page_scale_animation_->ScrollOffsetAtTime(monotonic_time); |
| 1366 m_client->setNeedsCommitOnImplThread(); | 1667 |
| 1367 m_client->setNeedsRedrawOnImplThread(); | 1668 RootScrollLayer()->ScrollBy(next_scroll - scroll_total); |
| 1368 m_client->renewTreePriority(); | 1669 client_->SetNeedsRedrawOnImplThread(); |
| 1369 } | 1670 |
| 1370 return didScroll; | 1671 if (page_scale_animation_->IsAnimationCompleteAtTime(monotonic_time)) { |
| 1371 } | 1672 page_scale_animation_.reset(); |
| 1372 | 1673 client_->SetNeedsCommitOnImplThread(); |
| 1373 void LayerTreeHostImpl::clearCurrentlyScrollingLayer() | 1674 client_->RenewTreePriority(); |
| 1374 { | 1675 } |
| 1375 m_activeTree->ClearCurrentlyScrollingLayer(); | 1676 } |
| 1376 m_didLockScrollingLayer = false; | 1677 |
| 1377 } | 1678 void LayerTreeHostImpl::AnimateLayers(base::TimeTicks monotonic_time, |
| 1378 | 1679 base::Time wall_clock_time) { |
| 1379 void LayerTreeHostImpl::scrollEnd() | 1680 if (!settings_.acceleratedAnimationEnabled || |
| 1380 { | 1681 animation_registrar_->active_animation_controllers().empty() || |
| 1381 if (m_topControlsManager) | 1682 !active_tree_->root_layer()) |
| 1382 m_topControlsManager->ScrollEnd(); | 1683 return; |
| 1383 clearCurrentlyScrollingLayer(); | 1684 |
| 1384 } | 1685 TRACE_EVENT0("cc", "LayerTreeHostImpl::animateLayers"); |
|
enne (OOO)
2013/03/13 05:22:05
AnimateLayers
danakj
2013/03/13 15:49:11
Done.
| |
| 1385 | 1686 |
| 1386 void LayerTreeHostImpl::pinchGestureBegin() | 1687 last_animation_time_ = wall_clock_time; |
| 1387 { | 1688 double monotonic_seconds = (monotonic_time - base::TimeTicks()).InSecondsF(); |
| 1388 m_pinchGestureActive = true; | 1689 |
| 1389 m_previousPinchAnchor = gfx::Point(); | 1690 AnimationRegistrar::AnimationControllerMap copy = |
| 1390 m_client->renewTreePriority(); | 1691 animation_registrar_->active_animation_controllers(); |
| 1391 } | 1692 for (AnimationRegistrar::AnimationControllerMap::iterator iter = copy.begin(); |
| 1392 | 1693 iter != copy.end(); |
| 1393 void LayerTreeHostImpl::pinchGestureUpdate(float magnifyDelta, gfx::Point anchor ) | 1694 ++iter) |
| 1394 { | 1695 (*iter).second->Animate(monotonic_seconds); |
| 1395 TRACE_EVENT0("cc", "LayerTreeHostImpl::pinchGestureUpdate"); | 1696 |
| 1396 | 1697 client_->SetNeedsRedrawOnImplThread(); |
| 1397 if (!rootScrollLayer()) | 1698 SetBackgroundTickingEnabled( |
| 1398 return; | 1699 !visible_ && |
| 1399 | 1700 !animation_registrar_->active_animation_controllers().empty()); |
| 1400 // Keep the center-of-pinch anchor specified by (x, y) in a stable | 1701 } |
| 1401 // position over the course of the magnify. | 1702 |
| 1402 float pageScaleDelta = activeTree()->page_scale_delta(); | 1703 void LayerTreeHostImpl::UpdateAnimationState() { |
| 1403 gfx::PointF previousScaleAnchor = gfx::ScalePoint(anchor, 1 / pageScaleDelta ); | 1704 if (!settings_.acceleratedAnimationEnabled || |
| 1404 activeTree()->SetPageScaleDelta(pageScaleDelta * magnifyDelta); | 1705 animation_registrar_->active_animation_controllers().empty() || |
| 1405 pageScaleDelta = activeTree()->page_scale_delta(); | 1706 !active_tree_->root_layer()) |
| 1406 gfx::PointF newScaleAnchor = gfx::ScalePoint(anchor, 1 / pageScaleDelta); | 1707 return; |
| 1407 gfx::Vector2dF move = previousScaleAnchor - newScaleAnchor; | 1708 |
| 1408 | 1709 TRACE_EVENT0("cc", "LayerTreeHostImpl::updateAnimationState"); |
|
enne (OOO)
2013/03/13 05:22:05
UpdateAnimationState
danakj
2013/03/13 15:49:11
Done.
| |
| 1409 m_previousPinchAnchor = anchor; | 1710 scoped_ptr<AnimationEventsVector> events = |
| 1410 | 1711 make_scoped_ptr(new AnimationEventsVector); |
| 1411 move.Scale(1 / activeTree()->page_scale_factor()); | 1712 AnimationRegistrar::AnimationControllerMap copy = |
| 1412 | 1713 animation_registrar_->active_animation_controllers(); |
| 1413 rootScrollLayer()->ScrollBy(move); | 1714 for (AnimationRegistrar::AnimationControllerMap::iterator iter = copy.begin(); |
| 1414 | 1715 iter != copy.end(); |
| 1415 if (rootScrollLayer()->scrollbar_animation_controller()) | 1716 ++iter) |
| 1416 rootScrollLayer()->scrollbar_animation_controller()->didPinchGestureUpda te(base::TimeTicks::Now()); | 1717 (*iter).second->UpdateState(events.get()); |
| 1417 | 1718 |
| 1418 m_client->setNeedsCommitOnImplThread(); | 1719 if (!events->empty()) { |
| 1419 m_client->setNeedsRedrawOnImplThread(); | 1720 client_->PostAnimationEventsToMainThreadOnImplThread(events.Pass(), |
| 1420 m_client->renewTreePriority(); | 1721 last_animation_time_); |
| 1421 } | 1722 } |
| 1422 | 1723 } |
| 1423 void LayerTreeHostImpl::pinchGestureEnd() | 1724 |
| 1424 { | 1725 base::TimeDelta LayerTreeHostImpl::LowFrequencyAnimationInterval() const { |
| 1425 m_pinchGestureActive = false; | 1726 return base::TimeDelta::FromSeconds(1); |
| 1426 | 1727 } |
| 1427 if (rootScrollLayer() && rootScrollLayer()->scrollbar_animation_controller() ) | 1728 |
| 1428 rootScrollLayer()->scrollbar_animation_controller()->didPinchGestureEnd( base::TimeTicks::Now()); | 1729 void LayerTreeHostImpl::SendDidLoseOutputSurfaceRecursive(LayerImpl* current) { |
| 1429 | 1730 DCHECK(current); |
| 1430 m_client->setNeedsCommitOnImplThread(); | 1731 current->DidLoseOutputSurface(); |
| 1431 } | 1732 if (current->mask_layer()) |
| 1432 | 1733 SendDidLoseOutputSurfaceRecursive(current->mask_layer()); |
| 1433 static void collectScrollDeltas(ScrollAndScaleSet* scrollInfo, LayerImpl* layerI mpl) | 1734 if (current->replica_layer()) |
| 1434 { | 1735 SendDidLoseOutputSurfaceRecursive(current->replica_layer()); |
| 1435 if (!layerImpl) | 1736 for (size_t i = 0; i < current->children().size(); ++i) |
| 1436 return; | 1737 SendDidLoseOutputSurfaceRecursive(current->children()[i]); |
| 1437 | 1738 } |
| 1438 gfx::Vector2d scrollDelta = gfx::ToFlooredVector2d(layerImpl->scroll_delta() ); | 1739 |
| 1439 if (!scrollDelta.IsZero()) { | 1740 void LayerTreeHostImpl::ClearRenderSurfaces() { |
| 1440 LayerTreeHostCommon::ScrollUpdateInfo scroll; | 1741 active_tree_->ClearRenderSurfaces(); |
| 1441 scroll.layerId = layerImpl->id(); | 1742 if (pending_tree_) |
| 1442 scroll.scrollDelta = scrollDelta; | 1743 pending_tree_->ClearRenderSurfaces(); |
| 1443 scrollInfo->scrolls.push_back(scroll); | 1744 } |
| 1444 layerImpl->SetSentScrollDelta(scrollDelta); | 1745 |
| 1445 } | 1746 std::string LayerTreeHostImpl::LayerTreeAsText() const { |
| 1446 | 1747 std::string str; |
| 1447 for (size_t i = 0; i < layerImpl->children().size(); ++i) | 1748 if (active_tree_->root_layer()) { |
| 1448 collectScrollDeltas(scrollInfo, layerImpl->children()[i]); | 1749 str = active_tree_->root_layer()->LayerTreeAsText(); |
| 1449 } | 1750 str += "RenderSurfaces:\n"; |
| 1450 | 1751 DumpRenderSurfaces(&str, 1, active_tree_->root_layer()); |
| 1451 scoped_ptr<ScrollAndScaleSet> LayerTreeHostImpl::processScrollDeltas() | 1752 } |
| 1452 { | 1753 return str; |
| 1453 scoped_ptr<ScrollAndScaleSet> scrollInfo(new ScrollAndScaleSet()); | 1754 } |
| 1454 | 1755 |
| 1455 collectScrollDeltas(scrollInfo.get(), rootLayer()); | 1756 std::string LayerTreeHostImpl::LayerTreeAsJson() const { |
| 1456 scrollInfo->pageScaleDelta = activeTree()->page_scale_delta(); | 1757 std::string str; |
| 1457 activeTree()->set_sent_page_scale_delta(scrollInfo->pageScaleDelta); | 1758 if (active_tree_->root_layer()) { |
| 1458 | 1759 scoped_ptr<base::Value> json(active_tree_->root_layer()->LayerTreeAsJson()); |
| 1459 return scrollInfo.Pass(); | 1760 base::JSONWriter::WriteWithOptions( |
| 1460 } | 1761 json.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &str); |
| 1461 | 1762 } |
| 1462 void LayerTreeHostImpl::SetFullRootLayerDamage() | 1763 return str; |
| 1463 { | 1764 } |
| 1464 if (rootLayer()) { | 1765 |
| 1465 RenderSurfaceImpl* renderSurface = rootLayer()->render_surface(); | 1766 void LayerTreeHostImpl::DumpRenderSurfaces(std::string* str, |
| 1466 if (renderSurface) | 1767 int indent, |
| 1467 renderSurface->damage_tracker()->ForceFullDamageNextUpdate(); | 1768 const LayerImpl* layer) const { |
| 1468 } | 1769 if (layer->render_surface()) |
| 1469 } | 1770 layer->render_surface()->DumpSurface(str, indent); |
| 1470 | 1771 |
| 1471 void LayerTreeHostImpl::animatePageScale(base::TimeTicks time) | 1772 for (size_t i = 0; i < layer->children().size(); ++i) |
| 1472 { | 1773 DumpRenderSurfaces(str, indent, layer->children()[i]); |
| 1473 if (!m_pageScaleAnimation || !rootScrollLayer()) | 1774 } |
| 1474 return; | 1775 |
| 1475 | 1776 int LayerTreeHostImpl::SourceAnimationFrameNumber() const { |
| 1476 double monotonicTime = (time - base::TimeTicks()).InSecondsF(); | 1777 return fps_counter_->currentFrameNumber(); |
| 1477 gfx::Vector2dF scrollTotal = rootScrollLayer()->scroll_offset() + rootScroll Layer()->scroll_delta(); | 1778 } |
| 1478 | 1779 |
| 1479 activeTree()->SetPageScaleDelta(m_pageScaleAnimation->PageScaleFactorAtTime( monotonicTime) / activeTree()->page_scale_factor()); | 1780 void LayerTreeHostImpl::CollectRenderingStats(RenderingStats* stats) const { |
| 1480 gfx::Vector2dF nextScroll = m_pageScaleAnimation->ScrollOffsetAtTime(monoton icTime); | 1781 stats->numFramesSentToScreen = fps_counter_->currentFrameNumber(); |
| 1481 | 1782 stats->droppedFrameCount = fps_counter_->droppedFrameCount(); |
| 1482 rootScrollLayer()->ScrollBy(nextScroll - scrollTotal); | 1783 stats->numImplThreadScrolls = num_impl_thread_scrolls_; |
| 1483 m_client->setNeedsRedrawOnImplThread(); | 1784 stats->numMainThreadScrolls = num_main_thread_scrolls_; |
| 1484 | 1785 stats->numLayersDrawn = cumulative_num_layers_drawn_; |
| 1485 if (m_pageScaleAnimation->IsAnimationCompleteAtTime(monotonicTime)) { | 1786 stats->numMissingTiles = cumulative_num_missing_tiles_; |
| 1486 m_pageScaleAnimation.reset(); | 1787 |
| 1487 m_client->setNeedsCommitOnImplThread(); | 1788 if (tile_manager_) |
| 1488 m_client->renewTreePriority(); | 1789 tile_manager_->GetRenderingStats(stats); |
| 1489 } | 1790 } |
| 1490 } | 1791 |
| 1491 | 1792 void LayerTreeHostImpl::SendManagedMemoryStats( |
| 1492 void LayerTreeHostImpl::animateLayers(base::TimeTicks monotonicTime, base::Time wallClockTime) | 1793 size_t memory_visible_bytes, |
| 1493 { | 1794 size_t memory_visible_and_nearby_bytes, |
| 1494 if (!m_settings.acceleratedAnimationEnabled || m_animationRegistrar->active_ animation_controllers().empty() || !rootLayer()) | 1795 size_t memoryUseBytes) { |
|
enne (OOO)
2013/03/13 05:22:05
memory_use_bytes
danakj
2013/03/13 15:49:11
Done.
| |
| 1495 return; | 1796 if (!renderer_) |
| 1496 | 1797 return; |
| 1497 TRACE_EVENT0("cc", "LayerTreeHostImpl::animateLayers"); | 1798 |
| 1498 | 1799 // Round the numbers being sent up to the next 8MB, to throttle the rate |
| 1499 m_lastAnimationTime = wallClockTime; | 1800 // at which we spam the GPU process. |
| 1500 double monotonicSeconds = (monotonicTime - base::TimeTicks()).InSecondsF(); | 1801 static const size_t rounding_step = 8 * 1024 * 1024; |
| 1501 | 1802 memory_visible_bytes = RoundUp(memory_visible_bytes, rounding_step); |
| 1502 AnimationRegistrar::AnimationControllerMap copy = m_animationRegistrar->acti ve_animation_controllers(); | 1803 memory_visible_and_nearby_bytes = RoundUp(memory_visible_and_nearby_bytes, |
| 1503 for (AnimationRegistrar::AnimationControllerMap::iterator iter = copy.begin( ); iter != copy.end(); ++iter) | 1804 rounding_step); |
| 1504 (*iter).second->Animate(monotonicSeconds); | 1805 memoryUseBytes = RoundUp(memoryUseBytes, rounding_step); |
| 1505 | 1806 if (last_sent_memory_visible_bytes_ == memory_visible_bytes && |
| 1506 m_client->setNeedsRedrawOnImplThread(); | 1807 last_sent_memory_visible_and_nearby_bytes_ == |
| 1507 setBackgroundTickingEnabled(!m_visible && !m_animationRegistrar->active_anim ation_controllers().empty()); | 1808 memory_visible_and_nearby_bytes && |
| 1508 } | 1809 last_sent_memory_use_bytes_ == memoryUseBytes) { |
| 1509 | 1810 return; |
| 1510 void LayerTreeHostImpl::updateAnimationState() | 1811 } |
| 1511 { | 1812 last_sent_memory_visible_bytes_ = memory_visible_bytes; |
| 1512 if (!m_settings.acceleratedAnimationEnabled || m_animationRegistrar->active_ animation_controllers().empty() || !rootLayer()) | 1813 last_sent_memory_visible_and_nearby_bytes_ = memory_visible_and_nearby_bytes; |
| 1513 return; | 1814 last_sent_memory_use_bytes_ = memoryUseBytes; |
| 1514 | 1815 |
| 1515 TRACE_EVENT0("cc", "LayerTreeHostImpl::updateAnimationState"); | 1816 renderer_->SendManagedMemoryStats(last_sent_memory_visible_bytes_, |
| 1516 scoped_ptr<AnimationEventsVector> events(make_scoped_ptr(new AnimationEvents Vector)); | 1817 last_sent_memory_visible_and_nearby_bytes_, |
| 1517 AnimationRegistrar::AnimationControllerMap copy = m_animationRegistrar->acti ve_animation_controllers(); | 1818 last_sent_memory_use_bytes_); |
| 1518 for (AnimationRegistrar::AnimationControllerMap::iterator iter = copy.begin( ); iter != copy.end(); ++iter) | 1819 } |
| 1519 (*iter).second->UpdateState(events.get()); | 1820 |
| 1520 | 1821 void LayerTreeHostImpl::AnimateScrollbars(base::TimeTicks time) { |
| 1521 if (!events->empty()) | 1822 AnimateScrollbarsRecursive(active_tree_->root_layer(), time); |
| 1522 m_client->postAnimationEventsToMainThreadOnImplThread(events.Pass(), m_l astAnimationTime); | 1823 } |
| 1523 } | 1824 |
| 1524 | 1825 void LayerTreeHostImpl::AnimateScrollbarsRecursive(LayerImpl* layer, |
| 1525 base::TimeDelta LayerTreeHostImpl::lowFrequencyAnimationInterval() const | 1826 base::TimeTicks time) { |
| 1526 { | 1827 if (!layer) |
| 1527 return base::TimeDelta::FromSeconds(1); | 1828 return; |
| 1528 } | 1829 |
| 1529 | 1830 ScrollbarAnimationController* scrollbar_controller = |
| 1530 void LayerTreeHostImpl::sendDidLoseOutputSurfaceRecursive(LayerImpl* current) | 1831 layer->scrollbar_animation_controller(); |
| 1531 { | 1832 if (scrollbar_controller && scrollbar_controller->animate(time)) |
| 1532 DCHECK(current); | 1833 client_->SetNeedsRedrawOnImplThread(); |
| 1533 current->DidLoseOutputSurface(); | 1834 |
| 1534 if (current->mask_layer()) | 1835 for (size_t i = 0; i < layer->children().size(); ++i) |
| 1535 sendDidLoseOutputSurfaceRecursive(current->mask_layer()); | 1836 AnimateScrollbarsRecursive(layer->children()[i], time); |
| 1536 if (current->replica_layer()) | 1837 } |
| 1537 sendDidLoseOutputSurfaceRecursive(current->replica_layer()); | 1838 |
| 1538 for (size_t i = 0; i < current->children().size(); ++i) | 1839 void LayerTreeHostImpl::SetTreePriority(TreePriority priority) { |
| 1539 sendDidLoseOutputSurfaceRecursive(current->children()[i]); | 1840 if (!tile_manager_) |
| 1540 } | 1841 return; |
| 1541 | 1842 |
| 1542 void LayerTreeHostImpl::clearRenderSurfaces() | 1843 GlobalStateThatImpactsTilePriority new_state(tile_manager_->GlobalState()); |
| 1543 { | 1844 if (new_state.tree_priority == priority) |
| 1544 activeTree()->ClearRenderSurfaces(); | 1845 return; |
| 1545 if (pendingTree()) | 1846 |
| 1546 pendingTree()->ClearRenderSurfaces(); | 1847 new_state.tree_priority = priority; |
| 1547 } | 1848 tile_manager_->SetGlobalState(new_state); |
| 1548 | 1849 } |
| 1549 std::string LayerTreeHostImpl::layerTreeAsText() const | 1850 |
| 1550 { | 1851 void LayerTreeHostImpl::BeginNextFrame() { |
| 1551 std::string str; | 1852 current_frame_time_ = base::TimeTicks(); |
| 1552 if (rootLayer()) { | 1853 } |
| 1553 str = rootLayer()->LayerTreeAsText(); | 1854 |
| 1554 str += "RenderSurfaces:\n"; | 1855 base::TimeTicks LayerTreeHostImpl::CurrentFrameTime() { |
| 1555 dumpRenderSurfaces(&str, 1, rootLayer()); | 1856 if (current_frame_time_.is_null()) |
| 1556 } | 1857 current_frame_time_ = base::TimeTicks::Now(); |
| 1557 return str; | 1858 return current_frame_time_; |
| 1558 } | 1859 } |
| 1559 | 1860 |
| 1560 std::string LayerTreeHostImpl::layerTreeAsJson() const | 1861 scoped_ptr<base::Value> LayerTreeHostImpl::AsValue() const { |
| 1561 { | 1862 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); |
| 1562 std::string str; | 1863 state->Set("activation_state", ActivationStateAsValue().release()); |
| 1563 if (rootLayer()) { | 1864 state->Set("frame_state", FrameStateAsValue().release()); |
| 1564 scoped_ptr<base::Value> json(rootLayer()->LayerTreeAsJson()); | 1865 return state.PassAs<base::Value>(); |
| 1565 base::JSONWriter::WriteWithOptions( | 1866 } |
| 1566 json.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &str); | 1867 |
| 1567 } | 1868 scoped_ptr<base::Value> LayerTreeHostImpl::ActivationStateAsValue() const { |
| 1568 return str; | 1869 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); |
| 1569 } | 1870 state->SetString("lthi_id", StringPrintf("%p", this)); |
| 1570 | 1871 state->SetBoolean("visible_resources_ready", |
| 1571 void LayerTreeHostImpl::dumpRenderSurfaces(std::string* str, int indent, const L ayerImpl* layer) const | 1872 pending_tree_->AreVisibleResourcesReady()); |
| 1572 { | 1873 state->Set("tile_manager", tile_manager_->BasicStateAsValue().release()); |
| 1573 if (layer->render_surface()) | 1874 return state.PassAs<base::Value>(); |
| 1574 layer->render_surface()->DumpSurface(str, indent); | 1875 } |
| 1575 | 1876 |
| 1576 for (size_t i = 0; i < layer->children().size(); ++i) | 1877 scoped_ptr<base::Value> LayerTreeHostImpl::FrameStateAsValue() const { |
| 1577 dumpRenderSurfaces(str, indent, layer->children()[i]); | 1878 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); |
| 1578 } | 1879 state->SetString("lthi_id", StringPrintf("%p", this)); |
| 1579 | 1880 state->Set("device_viewport_size", |
| 1580 int LayerTreeHostImpl::sourceAnimationFrameNumber() const | 1881 MathUtil::asValue(device_viewport_size_).release()); |
| 1581 { | 1882 if (tile_manager_) |
| 1582 return fpsCounter()->currentFrameNumber(); | 1883 state->Set("tiles", tile_manager_->AllTilesAsValue().release()); |
| 1583 } | 1884 state->Set("active_tree", active_tree_->AsValue().release()); |
| 1584 | 1885 return state.PassAs<base::Value>(); |
| 1585 void LayerTreeHostImpl::renderingStats(RenderingStats* stats) const | |
| 1586 { | |
| 1587 stats->numFramesSentToScreen = fpsCounter()->currentFrameNumber(); | |
| 1588 stats->droppedFrameCount = fpsCounter()->droppedFrameCount(); | |
| 1589 stats->numImplThreadScrolls = m_numImplThreadScrolls; | |
| 1590 stats->numMainThreadScrolls = m_numMainThreadScrolls; | |
| 1591 stats->numLayersDrawn = m_cumulativeNumLayersDrawn; | |
| 1592 stats->numMissingTiles = m_cumulativeNumMissingTiles; | |
| 1593 | |
| 1594 if (m_tileManager) | |
| 1595 m_tileManager->GetRenderingStats(stats); | |
| 1596 } | |
| 1597 | |
| 1598 void LayerTreeHostImpl::sendManagedMemoryStats( | |
| 1599 size_t memoryVisibleBytes, | |
| 1600 size_t memoryVisibleAndNearbyBytes, | |
| 1601 size_t memoryUseBytes) | |
| 1602 { | |
| 1603 if (!renderer()) | |
| 1604 return; | |
| 1605 | |
| 1606 // Round the numbers being sent up to the next 8MB, to throttle the rate | |
| 1607 // at which we spam the GPU process. | |
| 1608 static const size_t roundingStep = 8 * 1024 * 1024; | |
| 1609 memoryVisibleBytes = RoundUp(memoryVisibleBytes, roundingStep); | |
| 1610 memoryVisibleAndNearbyBytes = RoundUp(memoryVisibleAndNearbyBytes, roundingS tep); | |
| 1611 memoryUseBytes = RoundUp(memoryUseBytes, roundingStep); | |
| 1612 if (m_lastSentMemoryVisibleBytes == memoryVisibleBytes && | |
| 1613 m_lastSentMemoryVisibleAndNearbyBytes == memoryVisibleAndNearbyBytes && | |
| 1614 m_lastSentMemoryUseBytes == memoryUseBytes) { | |
| 1615 return; | |
| 1616 } | |
| 1617 m_lastSentMemoryVisibleBytes = memoryVisibleBytes; | |
| 1618 m_lastSentMemoryVisibleAndNearbyBytes = memoryVisibleAndNearbyBytes; | |
| 1619 m_lastSentMemoryUseBytes = memoryUseBytes; | |
| 1620 | |
| 1621 renderer()->SendManagedMemoryStats(m_lastSentMemoryVisibleBytes, | |
| 1622 m_lastSentMemoryVisibleAndNearbyBytes, | |
| 1623 m_lastSentMemoryUseBytes); | |
| 1624 } | |
| 1625 | |
| 1626 void LayerTreeHostImpl::animateScrollbars(base::TimeTicks time) | |
| 1627 { | |
| 1628 animateScrollbarsRecursive(rootLayer(), time); | |
| 1629 } | |
| 1630 | |
| 1631 void LayerTreeHostImpl::animateScrollbarsRecursive(LayerImpl* layer, base::TimeT icks time) | |
| 1632 { | |
| 1633 if (!layer) | |
| 1634 return; | |
| 1635 | |
| 1636 ScrollbarAnimationController* scrollbarController = layer->scrollbar_animati on_controller(); | |
| 1637 if (scrollbarController && scrollbarController->animate(time)) | |
| 1638 m_client->setNeedsRedrawOnImplThread(); | |
| 1639 | |
| 1640 for (size_t i = 0; i < layer->children().size(); ++i) | |
| 1641 animateScrollbarsRecursive(layer->children()[i], time); | |
| 1642 } | |
| 1643 | |
| 1644 void LayerTreeHostImpl::setTreePriority(TreePriority priority) | |
| 1645 { | |
| 1646 if (!m_tileManager) | |
| 1647 return; | |
| 1648 | |
| 1649 GlobalStateThatImpactsTilePriority new_state(m_tileManager->GlobalState()); | |
| 1650 if (new_state.tree_priority == priority) | |
| 1651 return; | |
| 1652 | |
| 1653 new_state.tree_priority = priority; | |
| 1654 m_tileManager->SetGlobalState(new_state); | |
| 1655 } | |
| 1656 | |
| 1657 void LayerTreeHostImpl::beginNextFrame() | |
| 1658 { | |
| 1659 m_currentFrameTime = base::TimeTicks(); | |
| 1660 } | |
| 1661 | |
| 1662 base::TimeTicks LayerTreeHostImpl::currentFrameTime() | |
| 1663 { | |
| 1664 if (m_currentFrameTime.is_null()) | |
| 1665 m_currentFrameTime = base::TimeTicks::Now(); | |
| 1666 return m_currentFrameTime; | |
| 1667 } | |
| 1668 | |
| 1669 scoped_ptr<base::Value> LayerTreeHostImpl::asValue() const | |
| 1670 { | |
| 1671 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); | |
| 1672 state->Set("activation_state", activationStateAsValue().release()); | |
| 1673 state->Set("frame_state", frameStateAsValue().release()); | |
| 1674 return state.PassAs<base::Value>(); | |
| 1675 } | |
| 1676 | |
| 1677 scoped_ptr<base::Value> LayerTreeHostImpl::activationStateAsValue() const | |
| 1678 { | |
| 1679 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); | |
| 1680 state->SetString("lthi_id", StringPrintf("%p", this)); | |
| 1681 state->SetBoolean("visible_resources_ready", pendingTree()->AreVisibleResour cesReady()); | |
| 1682 state->Set("tile_manager", m_tileManager->BasicStateAsValue().release()); | |
| 1683 return state.PassAs<base::Value>(); | |
| 1684 } | |
| 1685 | |
| 1686 scoped_ptr<base::Value> LayerTreeHostImpl::frameStateAsValue() const | |
| 1687 { | |
| 1688 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); | |
| 1689 state->SetString("lthi_id", StringPrintf("%p", this)); | |
| 1690 state->Set("device_viewport_size", MathUtil::asValue(m_deviceViewportSize).r elease()); | |
| 1691 if (m_tileManager) | |
| 1692 state->Set("tiles", m_tileManager->AllTilesAsValue().release()); | |
| 1693 state->Set("active_tree", activeTree()->AsValue().release()); | |
| 1694 return state.PassAs<base::Value>(); | |
| 1695 } | 1886 } |
| 1696 | 1887 |
| 1697 // static | 1888 // static |
| 1698 LayerImpl* LayerTreeHostImpl::getNonCompositedContentLayerRecursive(LayerImpl* l ayer) | 1889 LayerImpl* LayerTreeHostImpl::GetNonCompositedContentLayerRecursive( |
| 1699 { | 1890 LayerImpl* layer) { |
| 1700 if (!layer) | 1891 if (!layer) |
| 1701 return NULL; | |
| 1702 | |
| 1703 if (layer->DrawsContent()) | |
| 1704 return layer; | |
| 1705 | |
| 1706 for (LayerImpl::LayerList::const_iterator it = layer->children().begin(); | |
| 1707 it != layer->children().end(); ++it) { | |
| 1708 LayerImpl* nccr = getNonCompositedContentLayerRecursive(*it); | |
| 1709 if (nccr) | |
| 1710 return nccr; | |
| 1711 } | |
| 1712 | |
| 1713 return NULL; | 1892 return NULL; |
| 1714 } | 1893 |
| 1715 | 1894 if (layer->DrawsContent()) |
| 1716 skia::RefPtr<SkPicture> LayerTreeHostImpl::capturePicture() | 1895 return layer; |
| 1717 { | 1896 |
| 1718 LayerTreeImpl* tree = pendingTree() ? pendingTree() : activeTree(); | 1897 for (LayerImpl::LayerList::const_iterator it = layer->children().begin(); |
| 1719 LayerImpl* layer = getNonCompositedContentLayerRecursive(tree->RootLayer()); | 1898 it != layer->children().end(); ++it) { |
| 1720 return layer ? layer->GetPicture() : skia::RefPtr<SkPicture>(); | 1899 LayerImpl* nccr = GetNonCompositedContentLayerRecursive(*it); |
| 1721 } | 1900 if (nccr) |
| 1722 | 1901 return nccr; |
| 1723 void LayerTreeHostImpl::setDebugState(const LayerTreeDebugState& debugState) | 1902 } |
| 1724 { | 1903 |
| 1725 if (m_debugState.continuousPainting != debugState.continuousPainting) | 1904 return NULL; |
| 1726 m_paintTimeCounter->ClearHistory(); | 1905 } |
| 1727 | 1906 |
| 1728 m_debugState = debugState; | 1907 skia::RefPtr<SkPicture> LayerTreeHostImpl::CapturePicture() { |
| 1729 | 1908 LayerTreeImpl* tree = |
| 1730 if (m_tileManager) | 1909 pending_tree_ ? pending_tree_.get() : active_tree_.get(); |
| 1731 m_tileManager->SetRecordRenderingStats(m_debugState.recordRenderingStats ()); | 1910 LayerImpl* layer = GetNonCompositedContentLayerRecursive(tree->root_layer()); |
| 1732 } | 1911 return layer ? layer->GetPicture() : skia::RefPtr<SkPicture>(); |
| 1733 | 1912 } |
| 1734 void LayerTreeHostImpl::savePaintTime(const base::TimeDelta& totalPaintTime, int commitNumber) | 1913 |
| 1735 { | 1914 void LayerTreeHostImpl::SetDebugState(const LayerTreeDebugState& debug_state) { |
| 1736 DCHECK(m_debugState.continuousPainting); | 1915 if (debug_state_.continuousPainting != debug_state.continuousPainting) |
| 1737 m_paintTimeCounter->SavePaintTime(totalPaintTime, commitNumber); | 1916 paint_time_counter_->ClearHistory(); |
| 1917 | |
| 1918 debug_state_ = debug_state; | |
| 1919 | |
| 1920 if (tile_manager_) | |
| 1921 tile_manager_->SetRecordRenderingStats(debug_state_.recordRenderingStats()); | |
| 1922 } | |
| 1923 | |
| 1924 void LayerTreeHostImpl::SavePaintTime(const base::TimeDelta& total_paint_time, | |
| 1925 int commit_number) { | |
| 1926 DCHECK(debug_state_.continuousPainting); | |
| 1927 paint_time_counter_->SavePaintTime(total_paint_time, commit_number); | |
| 1738 } | 1928 } |
| 1739 | 1929 |
| 1740 } // namespace cc | 1930 } // namespace cc |
| OLD | NEW |