| 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 |
| 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"); |
| 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"); |
| 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"); |
| 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"); |
| 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"); |
| 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 } |
| 379 layer->render_surface()->AppendQuads(&quadCuller, | 283 |
| 380 &appendQuadsData, | 284 void LayerTreeHostImpl::StartPageScaleAnimation(gfx::Vector2d target_offset, |
| 381 isReplica, | 285 bool anchor_point, |
| 382 contributingRenderPass->id); | 286 float page_scale, |
| 383 | 287 base::TimeTicks start_time, |
| 384 // Add replica after the surface so that it appears below the surface. | 288 base::TimeDelta duration) { |
| 385 if (layer->has_replica()) { | 289 if (!RootScrollLayer()) |
| 386 isReplica = true; | 290 return; |
| 387 layer->render_surface()->AppendQuads(&quadCuller, | 291 |
| 388 &appendQuadsData, | 292 gfx::Vector2dF scroll_total = |
| 389 isReplica, | 293 RootScrollLayer()->scroll_offset() + RootScrollLayer()->scroll_delta(); |
| 390 contributingRenderPass->id); | 294 gfx::SizeF scaled_scrollable_size = active_tree_->ScrollableSize(); |
| 391 } | 295 gfx::SizeF viewport_size = |
| 392 } | 296 gfx::ScaleSize(device_viewport_size_, 1.f / device_scale_factor_); |
| 393 | 297 |
| 394 static void appendQuadsToFillScreen(RenderPass* targetRenderPass, LayerImpl* roo
tLayer, SkColor screenBackgroundColor, const OcclusionTrackerImpl& occlusionTrac
ker) | 298 double start_time_seconds = (start_time - base::TimeTicks()).InSecondsF(); |
| 395 { | 299 page_scale_animation_ = |
| 396 if (!rootLayer || !SkColorGetA(screenBackgroundColor)) | 300 PageScaleAnimation::Create(scroll_total, |
| 397 return; | 301 active_tree_->total_page_scale_factor(), |
| 398 | 302 viewport_size, |
| 399 Region fillRegion = occlusionTracker.ComputeVisibleRegionInScreen(); | 303 scaled_scrollable_size, |
| 400 if (fillRegion.IsEmpty()) | 304 start_time_seconds); |
| 401 return; | 305 |
| 402 | 306 if (anchor_point) { |
| 403 bool forSurface = false; | 307 gfx::Vector2dF anchor(target_offset); |
| 404 QuadCuller quadCuller(targetRenderPass->quad_list, | 308 page_scale_animation_->ZoomWithAnchor(anchor, |
| 405 targetRenderPass->shared_quad_state_list, | 309 page_scale, |
| 406 rootLayer, | 310 duration.InSecondsF()); |
| 407 occlusionTracker, | 311 } else { |
| 408 rootLayer->ShowDebugBorders(), | 312 gfx::Vector2dF scaled_target_offset = target_offset; |
| 409 forSurface); | 313 page_scale_animation_->ZoomTo(scaled_target_offset, |
| 410 | 314 page_scale, |
| 411 // Manually create the quad state for the gutter quads, as the root layer | 315 duration.InSecondsF()); |
| 412 // doesn't have any bounds and so can't generate this itself. | 316 } |
| 413 // FIXME: Make the gutter quads generated by the solid color layer (make it
smarter about generating quads to fill unoccluded areas). | 317 |
| 414 | 318 client_->SetNeedsRedrawOnImplThread(); |
| 415 gfx::Rect rootTargetRect = rootLayer->render_surface()->content_rect(); | 319 client_->SetNeedsCommitOnImplThread(); |
| 416 float opacity = 1; | 320 client_->RenewTreePriority(); |
| 417 SharedQuadState* sharedQuadState = quadCuller.useSharedQuadState(SharedQuadS
tate::Create()); | 321 } |
| 418 sharedQuadState->SetAll(rootLayer->draw_transform(), | 322 |
| 419 rootTargetRect.size(), | 323 void LayerTreeHostImpl::ScheduleAnimation() { |
| 420 rootTargetRect, | 324 client_->SetNeedsRedrawOnImplThread(); |
| 421 rootTargetRect, | 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 surface_index = render_surface_layer_list.size() - 1; |
| 360 surface_index >= 0 ; |
| 361 --surface_index) { |
| 362 LayerImpl* render_surface_layer = render_surface_layer_list[surface_index]; |
| 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 quad_culler(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(&quad_culler, 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 quad_culler(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(&quad_culler, |
| 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; |
| 419 layer->render_surface()->AppendQuads(&quad_culler, |
| 420 append_quads_data, |
| 421 is_replica, |
| 422 contributing_render_pass->id); |
| 423 } |
| 424 } |
| 425 |
| 426 static void AppendQuadsToFillScreen( |
| 427 RenderPass* target_render_pass, |
| 428 LayerImpl* root_layer, |
| 429 SkColor screen_background_color, |
| 430 const OcclusionTrackerImpl& occlusion_tracker) { |
| 431 if (!root_layer || !SkColorGetA(screen_background_color)) |
| 432 return; |
| 433 |
| 434 Region fill_region = occlusion_tracker.ComputeVisibleRegionInScreen(); |
| 435 if (fill_region.IsEmpty()) |
| 436 return; |
| 437 |
| 438 bool for_surface = false; |
| 439 QuadCuller quad_culler(target_render_pass->quad_list, |
| 440 target_render_pass->shared_quad_state_list, |
| 441 root_layer, |
| 442 occlusion_tracker, |
| 443 root_layer->ShowDebugBorders(), |
| 444 for_surface); |
| 445 |
| 446 // Manually create the quad state for the gutter quads, as the root layer |
| 447 // doesn't have any bounds and so can't generate this itself. |
| 448 // TODO(danakj): Make the gutter quads generated by the solid color layer |
| 449 // (make it smarter about generating quads to fill unoccluded areas). |
| 450 |
| 451 gfx::Rect root_target_rect = root_layer->render_surface()->content_rect(); |
| 452 float opacity = 1.f; |
| 453 SharedQuadState* shared_quad_state = |
| 454 quad_culler.useSharedQuadState(SharedQuadState::Create()); |
| 455 shared_quad_state->SetAll(root_layer->draw_transform(), |
| 456 root_target_rect.size(), |
| 457 root_target_rect, |
| 458 root_target_rect, |
| 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 fill_rects(fill_region); |
| 432 // no perspective, so mapping is sufficient (as opposed to projecting). | 469 fill_rects.has_rect(); |
| 433 gfx::Rect layerRect = MathUtil::mapClippedRect(transformToLayerSpace, fi
llRects.rect()); | 470 fill_rects.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, fill_rects.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 quad_culler.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", |
| 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 surface_index = frame->render_surface_layer_list->size() - 1; |
| 500 surface_index >= 0 ; |
| 501 --surface_index) { |
| 502 LayerImpl* render_surface_layer = |
| 503 (*frame->render_surface_layer_list)[surface_index]; |
| 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_) { |
| 660 time_source_client_adapter_ = LayerTreeHostImplTimeSourceAdapter::Create( |
| 661 this, |
| 662 DelayBasedTimeSource::create(LowFrequencyAnimationInterval(), |
| 663 proxy_->CurrentThread())); |
| 664 } |
| 665 |
| 666 time_source_client_adapter_->SetActive(enabled); |
| 667 } |
| 668 |
| 669 static inline RenderPass* FindRenderPassById( |
| 670 RenderPass::Id render_pass_id, |
| 671 const LayerTreeHostImpl::FrameData& frame) { |
| 672 RenderPassIdHashMap::const_iterator it = |
| 673 frame.render_passes_by_id.find(render_pass_id); |
| 674 return it != frame.render_passes_by_id.end() ? it->second : NULL; |
| 675 } |
| 676 |
| 677 static void RemoveRenderPassesRecursive(RenderPass::Id remove_render_pass_id, |
| 678 LayerTreeHostImpl::FrameData* frame) { |
| 679 RenderPass* remove_render_pass = |
| 680 FindRenderPassById(remove_render_pass_id, *frame); |
| 681 // The pass was already removed by another quad - probably the original, and |
| 682 // we are the replica. |
| 683 if (!remove_render_pass) |
| 684 return; |
| 685 RenderPassList& render_passes = frame->render_passes; |
| 686 RenderPassList::iterator to_remove = std::find(render_passes.begin(), |
| 687 render_passes.end(), |
| 688 remove_render_pass); |
| 689 |
| 690 DCHECK(to_remove != render_passes.end()); |
| 691 |
| 692 scoped_ptr<RenderPass> removed_pass = render_passes.take(to_remove); |
| 693 frame->render_passes.erase(to_remove); |
| 694 frame->render_passes_by_id.erase(remove_render_pass_id); |
| 695 |
| 696 // Now follow up for all RenderPass quads and remove their RenderPasses |
| 697 // recursively. |
| 698 const QuadList& quad_list = removed_pass->quad_list; |
| 699 QuadList::constBackToFrontIterator quad_list_iterator = |
| 700 quad_list.backToFrontBegin(); |
| 701 for (; quad_list_iterator != quad_list.backToFrontEnd(); |
| 702 ++quad_list_iterator) { |
| 703 DrawQuad* current_quad = (*quad_list_iterator); |
| 704 if (current_quad->material != DrawQuad::RENDER_PASS) |
| 705 continue; |
| 706 |
| 707 RenderPass::Id next_remove_render_pass_id = |
| 708 RenderPassDrawQuad::MaterialCast(current_quad)->render_pass_id; |
| 709 RemoveRenderPassesRecursive(next_remove_render_pass_id, frame); |
| 710 } |
| 711 } |
| 712 |
| 713 bool LayerTreeHostImpl::CullRenderPassesWithCachedTextures:: |
| 714 ShouldRemoveRenderPass(const RenderPassDrawQuad& quad, |
| 715 const FrameData& frame) const { |
| 716 bool quad_has_damage = !quad.contents_changed_since_last_frame.IsEmpty(); |
| 717 bool quad_has_cached_resource = |
| 718 renderer_.HaveCachedResourcesForRenderPassId(quad.render_pass_id); |
| 719 if (quad_has_damage) { |
| 720 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures have damage"); |
| 721 return false; |
| 722 } else if (!quad_has_cached_resource) { |
| 723 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures have no texture"); |
| 724 return false; |
| 725 } |
| 726 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures dropped!"); |
| 727 return true; |
| 728 } |
| 729 |
| 730 bool LayerTreeHostImpl::CullRenderPassesWithNoQuads::ShouldRemoveRenderPass( |
| 731 const RenderPassDrawQuad& quad, const FrameData& frame) const { |
| 732 const RenderPass* render_pass = |
| 733 FindRenderPassById(quad.render_pass_id, frame); |
| 734 if (!render_pass) |
| 735 return false; |
| 736 |
| 737 // If any quad or RenderPass draws into this RenderPass, then keep it. |
| 738 const QuadList& quad_list = render_pass->quad_list; |
| 739 for (QuadList::constBackToFrontIterator quad_list_iterator = |
| 740 quad_list.backToFrontBegin(); |
| 741 quad_list_iterator != quad_list.backToFrontEnd(); |
| 742 ++quad_list_iterator) { |
| 743 DrawQuad* current_quad = *quad_list_iterator; |
| 744 |
| 745 if (current_quad->material != DrawQuad::RENDER_PASS) |
| 447 return false; | 746 return false; |
| 448 | 747 |
| 449 trackDamageForAllSurfaces(rootLayer(), *frame.renderSurfaceLayerList); | 748 const RenderPass* contributing_pass = FindRenderPassById( |
| 450 | 749 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())); | 750 if (contributing_pass) |
| 452 | 751 return false; |
| 453 // Create the render passes in dependency order. | 752 } |
| 454 for (int surfaceIndex = frame.renderSurfaceLayerList->size() - 1; surfaceInd
ex >= 0 ; --surfaceIndex) { | 753 return true; |
| 455 LayerImpl* renderSurfaceLayer = (*frame.renderSurfaceLayerList)[surfaceI
ndex]; | 754 } |
| 456 renderSurfaceLayer->render_surface()->AppendRenderPasses(&frame); | 755 |
| 756 // Defined for linking tests. |
| 757 template CC_EXPORT void LayerTreeHostImpl::RemoveRenderPasses< |
| 758 LayerTreeHostImpl::CullRenderPassesWithCachedTextures>( |
| 759 CullRenderPassesWithCachedTextures culler, FrameData* frame); |
| 760 template CC_EXPORT void LayerTreeHostImpl::RemoveRenderPasses< |
| 761 LayerTreeHostImpl::CullRenderPassesWithNoQuads>( |
| 762 CullRenderPassesWithNoQuads culler, FrameData*); |
| 763 |
| 764 // static |
| 765 template <typename RenderPassCuller> |
| 766 void LayerTreeHostImpl::RemoveRenderPasses(RenderPassCuller culler, |
| 767 FrameData* frame) { |
| 768 for (size_t it = culler.RenderPassListBegin(frame->render_passes); |
| 769 it != culler.RenderPassListEnd(frame->render_passes); |
| 770 it = culler.RenderPassListNext(it)) { |
| 771 const RenderPass* current_pass = frame->render_passes[it]; |
| 772 const QuadList& quad_list = current_pass->quad_list; |
| 773 QuadList::constBackToFrontIterator quad_list_iterator = |
| 774 quad_list.backToFrontBegin(); |
| 775 |
| 776 for (; quad_list_iterator != quad_list.backToFrontEnd(); |
| 777 ++quad_list_iterator) { |
| 778 DrawQuad* current_quad = *quad_list_iterator; |
| 779 |
| 780 if (current_quad->material != DrawQuad::RENDER_PASS) |
| 781 continue; |
| 782 |
| 783 const RenderPassDrawQuad* render_pass_quad = |
| 784 RenderPassDrawQuad::MaterialCast(current_quad); |
| 785 if (!culler.ShouldRemoveRenderPass(*render_pass_quad, *frame)) |
| 786 continue; |
| 787 |
| 788 // We are changing the vector in the middle of iteration. Because we |
| 789 // delete render passes that draw into the current pass, we are |
| 790 // guaranteed that any data from the iterator to the end will not |
| 791 // change. So, capture the iterator position from the end of the |
| 792 // list, and restore it after the change. |
| 793 size_t position_from_end = frame->render_passes.size() - it; |
| 794 RemoveRenderPassesRecursive(render_pass_quad->render_pass_id, frame); |
| 795 it = frame->render_passes.size() - position_from_end; |
| 796 DCHECK_GE(frame->render_passes.size(), position_from_end); |
| 457 } | 797 } |
| 458 | 798 } |
| 459 bool recordMetricsForFrame = m_settings.showOverdrawInTracing && base::debug
::TraceLog::GetInstance() && base::debug::TraceLog::GetInstance()->IsEnabled(); | 799 } |
| 460 OcclusionTrackerImpl occlusionTracker(rootLayer()->render_surface()->content
_rect(), recordMetricsForFrame); | 800 |
| 461 occlusionTracker.set_minimum_tracking_size(m_settings.minimumOcclusionTracki
ngSize); | 801 bool LayerTreeHostImpl::PrepareToDraw(FrameData* frame) { |
| 462 | 802 TRACE_EVENT0("cc", "LayerTreeHostImpl::PrepareToDraw"); |
| 463 if (m_debugState.showOccludingRects) | 803 |
| 464 occlusionTracker.set_occluding_screen_space_rects_container(&frame.occlu
dingScreenSpaceRects); | 804 active_tree_->UpdateDrawProperties( |
| 465 if (m_debugState.showNonOccludingRects) | 805 LayerTreeImpl::UPDATE_ACTIVE_TREE_FOR_DRAW); |
| 466 occlusionTracker.set_non_occluding_screen_space_rects_container(&frame.n
onOccludingScreenSpaceRects); | 806 |
| 467 | 807 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. | 808 frame->render_passes.clear(); |
| 469 typedef LayerIterator<LayerImpl, std::vector<LayerImpl*>, RenderSurfaceImpl,
LayerIteratorActions::FrontToBack> LayerIteratorType; | 809 frame->render_passes_by_id.clear(); |
| 470 | 810 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 | 811 |
| 472 // checkerboarded is moving due to an impl-animation, we drop the frame to a
void flashing due to the texture suddenly appearing | 812 if (!CalculateRenderPasses(frame)) |
| 473 // in the future. | 813 return false; |
| 474 bool drawFrame = true; | 814 |
| 475 | 815 // If we return true, then we expect DrawLayers() to be called before this |
| 476 LayerIteratorType end = LayerIteratorType::end(frame.renderSurfaceLayerList)
; | 816 // function is called again. |
| 477 for (LayerIteratorType it = LayerIteratorType::begin(frame.renderSurfaceLaye
rList); it != end; ++it) { | 817 return true; |
| 478 RenderPass::Id targetRenderPassId = it.targetRenderSurfaceLayer()->rende
r_surface()->RenderPassId(); | 818 } |
| 479 RenderPass* targetRenderPass = frame.renderPassesById[targetRenderPassId
]; | 819 |
| 480 | 820 void LayerTreeHostImpl::EnforceManagedMemoryPolicy( |
| 481 occlusionTracker.EnterLayer(it); | 821 const ManagedMemoryPolicy& policy) { |
| 482 | 822 bool evicted_resources = client_->ReduceContentsTextureMemoryOnImplThread( |
| 483 AppendQuadsData appendQuadsData(targetRenderPass->id); | 823 visible_ ? policy.bytesLimitWhenVisible : policy.bytesLimitWhenNotVisible, |
| 484 | 824 ManagedMemoryPolicy::priorityCutoffToValue( |
| 485 if (it.representsContributingRenderSurface()) { | 825 visible_ ? |
| 486 RenderPass::Id contributingRenderPassId = it->render_surface()->Rend
erPassId(); | 826 policy.priorityCutoffWhenVisible : |
| 487 RenderPass* contributingRenderPass = frame.renderPassesById[contribu
tingRenderPassId]; | 827 policy.priorityCutoffWhenNotVisible)); |
| 488 appendQuadsForRenderSurfaceLayer(targetRenderPass, *it, contributing
RenderPass, occlusionTracker, appendQuadsData); | 828 if (evicted_resources) { |
| 489 } else if (it.representsItself() && !it->visible_content_rect().IsEmpty(
)) { | 829 active_tree_->SetContentsTexturesPurged(); |
| 490 bool hasOcclusionFromOutsideTargetSurface; | 830 if (pending_tree_) |
| 491 bool implDrawTransformIsUnknown = false; | 831 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)) | 832 client_->SetNeedsCommitOnImplThread(); |
| 493 appendQuadsData.hadOcclusionFromOutsideTargetSurface |= hasOcclu
sionFromOutsideTargetSurface; | 833 client_->OnCanDrawStateChanged(CanDraw()); |
| 494 else { | 834 client_->RenewTreePriority(); |
| 495 DCHECK_EQ(activeTree(), it->layer_tree_impl()); | 835 } |
| 496 it->WillDraw(m_resourceProvider.get()); | 836 client_->SendManagedMemoryStats(); |
| 497 frame.willDrawLayers.push_back(*it); | 837 |
| 498 | 838 if (tile_manager_) { |
| 499 if (it->HasContributingDelegatedRenderPasses()) { | 839 GlobalStateThatImpactsTilePriority new_state(tile_manager_->GlobalState()); |
| 500 RenderPass::Id contributingRenderPassId = it->FirstContribut
ingRenderPassId(); | 840 new_state.memory_limit_in_bytes = visible_ ? |
| 501 while (frame.renderPassesById.find(contributingRenderPassId)
!= frame.renderPassesById.end()) { | 841 policy.bytesLimitWhenVisible : |
| 502 RenderPass* renderPass = frame.renderPassesById[contribu
tingRenderPassId]; | 842 policy.bytesLimitWhenNotVisible; |
| 503 | 843 new_state.memory_limit_policy = |
| 504 AppendQuadsData appendQuadsData(renderPass->id); | 844 ManagedMemoryPolicy::priorityCutoffToTileMemoryLimitPolicy( |
| 505 appendQuadsForLayer(renderPass, *it, occlusionTracker, a
ppendQuadsData); | 845 visible_ ? |
| 506 | 846 policy.priorityCutoffWhenVisible : |
| 507 contributingRenderPassId = it->NextContributingRenderPas
sId(contributingRenderPassId); | 847 policy.priorityCutoffWhenNotVisible); |
| 508 } | 848 tile_manager_->SetGlobalState(new_state); |
| 509 } | 849 } |
| 510 | 850 } |
| 511 appendQuadsForLayer(targetRenderPass, *it, occlusionTracker, app
endQuadsData); | 851 |
| 512 } | 852 bool LayerTreeHostImpl::HasImplThread() const { |
| 513 | 853 return proxy_->HasImplThread(); |
| 514 ++m_cumulativeNumLayersDrawn; | 854 } |
| 515 } | 855 |
| 516 | 856 void LayerTreeHostImpl::ScheduleManageTiles() { |
| 517 if (appendQuadsData.hadOcclusionFromOutsideTargetSurface) | 857 if (client_) |
| 518 targetRenderPass->has_occlusion_from_outside_target_surface = true; | 858 client_->SetNeedsManageTilesOnImplThread(); |
| 519 | 859 } |
| 520 if (appendQuadsData.numMissingTiles) { | 860 |
| 521 m_cumulativeNumMissingTiles += appendQuadsData.numMissingTiles; | 861 void LayerTreeHostImpl::DidUploadVisibleHighResolutionTile() { |
| 522 bool layerHasAnimatingTransform = it->screen_space_transform_is_anim
ating() || it->draw_transform_is_animating(); | 862 if (client_) |
| 523 if (layerHasAnimatingTransform) | 863 client_->DidUploadVisibleHighResolutionTileOnImplThread(); |
| 524 drawFrame = false; | 864 } |
| 525 } | 865 |
| 526 | 866 bool LayerTreeHostImpl::ShouldClearRootRenderPass() const { |
| 527 if (appendQuadsData.hadIncompleteTile) | 867 return settings_.shouldClearRootRenderPass; |
| 528 frame.containsIncompleteTile = true; | 868 } |
| 529 | 869 |
| 530 occlusionTracker.LeaveLayer(it); | 870 void LayerTreeHostImpl::SetManagedMemoryPolicy( |
| 531 } | 871 const ManagedMemoryPolicy& policy) { |
| 532 | 872 if (managed_memory_policy_ == policy) |
| 533 #ifndef NDEBUG | 873 return; |
| 534 for (size_t i = 0; i < frame.renderPasses.size(); ++i) { | 874 |
| 535 for (size_t j = 0; j < frame.renderPasses[i]->quad_list.size(); ++j) | 875 managed_memory_policy_ = policy; |
| 536 DCHECK(frame.renderPasses[i]->quad_list[j]->shared_quad_state); | 876 if (!proxy_->HasImplThread()) { |
| 537 DCHECK(frame.renderPassesById.find(frame.renderPasses[i]->id) | 877 // TODO(ccameron): In single-thread mode, this can be called on the main |
| 538 != frame.renderPassesById.end()); | 878 // thread by GLRenderer::OnMemoryAllocationChanged. |
| 539 } | 879 DebugScopedSetImplThread impl_thread(proxy_); |
| 540 #endif | 880 EnforceManagedMemoryPolicy(managed_memory_policy_); |
| 541 DCHECK(frame.renderPasses.back()->output_rect.origin().IsOrigin()); | 881 } else { |
| 542 | 882 DCHECK(proxy_->IsImplThread()); |
| 543 if (!activeTree()->has_transparent_background()) { | 883 EnforceManagedMemoryPolicy(managed_memory_policy_); |
| 544 frame.renderPasses.back()->has_transparent_background = false; | 884 } |
| 545 appendQuadsToFillScreen(frame.renderPasses.back(), rootLayer(), activeTr
ee()->background_color(), occlusionTracker); | 885 // We always need to commit after changing the memory policy because the new |
| 546 } | 886 // limit can result in more or less content having texture allocated for it. |
| 547 | 887 client_->SetNeedsCommitOnImplThread(); |
| 548 if (drawFrame) | 888 } |
| 549 occlusionTracker.overdraw_metrics()->RecordMetrics(this); | 889 |
| 550 | 890 void LayerTreeHostImpl::OnVSyncParametersChanged(base::TimeTicks timebase, |
| 551 removeRenderPasses(CullRenderPassesWithNoQuads(), frame); | 891 base::TimeDelta interval) { |
| 552 m_renderer->DecideRenderPassAllocationsForFrame(frame.renderPasses); | 892 client_->OnVSyncParametersChanged(timebase, interval); |
| 553 removeRenderPasses(CullRenderPassesWithCachedTextures(*m_renderer), frame); | 893 } |
| 554 | 894 |
| 555 return drawFrame; | 895 void LayerTreeHostImpl::OnSendFrameToParentCompositorAck( |
| 556 } | 896 const CompositorFrameAck& ack) { |
| 557 | 897 if (!renderer_) |
| 558 void LayerTreeHostImpl::setBackgroundTickingEnabled(bool enabled) | 898 return; |
| 559 { | 899 |
| 560 // Lazily create the timeSource adapter so that we can vary the interval for
testing. | 900 // TODO(piman): We may need to do some validation on this ack before |
| 561 if (!m_timeSourceClientAdapter) | 901 // processing it. |
| 562 m_timeSourceClientAdapter = LayerTreeHostImplTimeSourceAdapter::Create(t
his, DelayBasedTimeSource::create(lowFrequencyAnimationInterval(), m_proxy->Curr
entThread())); | 902 renderer_->ReceiveCompositorFrameAck(ack); |
| 563 | 903 } |
| 564 m_timeSourceClientAdapter->setActive(enabled); | 904 |
| 565 } | 905 void LayerTreeHostImpl::OnCanDrawStateChangedForTree() { |
| 566 | 906 client_->OnCanDrawStateChanged(CanDraw()); |
| 567 static inline RenderPass* findRenderPassById(RenderPass::Id renderPassId, const
LayerTreeHostImpl::FrameData& frame) | 907 } |
| 568 { | 908 |
| 569 RenderPassIdHashMap::const_iterator it = frame.renderPassesById.find(renderP
assId); | 909 CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() const { |
| 570 return it != frame.renderPassesById.end() ? it->second : NULL; | 910 CompositorFrameMetadata metadata; |
| 571 } | 911 metadata.device_scale_factor = device_scale_factor_; |
| 572 | 912 metadata.page_scale_factor = active_tree_->total_page_scale_factor(); |
| 573 static void removeRenderPassesRecursive(RenderPass::Id removeRenderPassId, Layer
TreeHostImpl::FrameData& frame) | 913 metadata.viewport_size = active_tree_->ScrollableViewportSize(); |
| 574 { | 914 metadata.root_layer_size = active_tree_->ScrollableSize(); |
| 575 RenderPass* removeRenderPass = findRenderPassById(removeRenderPassId, frame)
; | 915 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. | 916 metadata.max_page_scale_factor = active_tree_->max_page_scale_factor(); |
| 577 if (!removeRenderPass) | 917 if (top_controls_manager_) { |
| 578 return; | 918 metadata.location_bar_offset = |
| 579 RenderPassList& renderPasses = frame.renderPasses; | 919 gfx::Vector2dF(0.f, top_controls_manager_->controls_top_offset()); |
| 580 RenderPassList::iterator toRemove = std::find(renderPasses.begin(), renderPa
sses.end(), removeRenderPass); | 920 metadata.location_bar_content_translation = |
| 581 | 921 gfx::Vector2dF(0.f, top_controls_manager_->content_top_offset()); |
| 582 DCHECK(toRemove != renderPasses.end()); | 922 } |
| 583 | 923 |
| 584 scoped_ptr<RenderPass> removedPass = renderPasses.take(toRemove); | 924 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; | 925 return metadata; |
| 795 } | 926 |
| 796 | 927 metadata.root_scroll_offset = RootScrollLayer()->scroll_offset() + |
| 797 void LayerTreeHostImpl::drawLayers(FrameData& frame) | 928 RootScrollLayer()->scroll_delta(); |
| 798 { | 929 |
| 799 TRACE_EVENT0("cc", "LayerTreeHostImpl::drawLayers"); | 930 return metadata; |
| 800 DCHECK(canDraw()); | 931 } |
| 801 DCHECK(!frame.renderPasses.empty()); | 932 |
| 802 | 933 void LayerTreeHostImpl::DrawLayers(FrameData* frame) { |
| 803 // FIXME: use the frame begin time from the overall compositor scheduler. | 934 TRACE_EVENT0("cc", "LayerTreeHostImpl::DrawLayers"); |
| 804 // This value is currently inaccessible because it is up in Chromium's | 935 DCHECK(CanDraw()); |
| 805 // RenderWidget. | 936 DCHECK(!frame->render_passes.empty()); |
| 806 m_fpsCounter->saveTimeStamp(base::TimeTicks::Now()); | 937 |
| 807 | 938 // FIXME: use the frame begin time from the overall compositor scheduler. |
| 808 if (m_tileManager) { | 939 // This value is currently inaccessible because it is up in Chromium's |
| 809 m_memoryHistory->SaveEntry( | 940 // RenderWidget. |
| 810 m_tileManager->memory_stats_from_last_assign()); | 941 fps_counter_->saveTimeStamp(base::TimeTicks::Now()); |
| 811 } | 942 |
| 812 | 943 if (tile_manager_) { |
| 813 if (m_debugState.showHudRects()) | 944 memory_history_->SaveEntry( |
| 814 m_debugRectHistory->saveDebugRectsForCurrentFrame(rootLayer(), *frame.re
nderSurfaceLayerList, frame.occludingScreenSpaceRects, frame.nonOccludingScreenS
paceRects, m_debugState); | 945 tile_manager_->memory_stats_from_last_assign()); |
| 815 | 946 } |
| 816 if (m_debugState.traceAllRenderedFrames) { | 947 |
| 817 TRACE_EVENT_INSTANT1("cc.debug", "Frame", | 948 if (debug_state_.showHudRects()) { |
| 818 "frame", ValueToString(frameStateAsValue())); | 949 debug_rect_history_->saveDebugRectsForCurrentFrame( |
| 819 } | 950 active_tree_->root_layer(), |
| 820 | 951 *frame->render_surface_layer_list, |
| 821 // Because the contents of the HUD depend on everything else in the frame, t
he contents | 952 frame->occluding_screen_space_rects, |
| 822 // of its texture are updated as the last thing before the frame is drawn. | 953 frame->non_occluding_screen_space_rects, |
| 823 if (m_activeTree->hud_layer()) | 954 debug_state_); |
| 824 m_activeTree->hud_layer()->updateHudTexture(m_resourceProvider.get()); | 955 } |
| 825 | 956 |
| 826 m_renderer->DrawFrame(frame.renderPasses); | 957 if (debug_state_.traceAllRenderedFrames) { |
| 827 // The render passes should be consumed by the renderer. | 958 TRACE_EVENT_INSTANT1("cc.debug", "Frame", |
| 828 DCHECK(frame.renderPasses.empty()); | 959 "frame", ValueToString(FrameStateAsValue())); |
| 829 frame.renderPassesById.clear(); | 960 } |
| 830 | 961 |
| 831 // The next frame should start by assuming nothing has changed, and changes
are noted as they occur. | 962 // 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++) | 963 // contents of its texture are updated as the last thing before the frame is |
| 833 (*frame.renderSurfaceLayerList)[i]->render_surface()->damage_tracker()->
DidDrawDamagedArea(); | 964 // drawn. |
| 834 rootLayer()->ResetAllChangeTrackingForSubtree(); | 965 if (active_tree_->hud_layer()) |
| 835 updateAnimationState(); | 966 active_tree_->hud_layer()->updateHudTexture(resource_provider_.get()); |
| 836 } | 967 |
| 837 | 968 renderer_->DrawFrame(frame->render_passes); |
| 838 void LayerTreeHostImpl::didDrawAllLayers(const FrameData& frame) | 969 // The render passes should be consumed by the renderer. |
| 839 { | 970 DCHECK(frame->render_passes.empty()); |
| 840 for (size_t i = 0; i < frame.willDrawLayers.size(); ++i) | 971 frame->render_passes_by_id.clear(); |
| 841 frame.willDrawLayers[i]->DidDraw(m_resourceProvider.get()); | 972 |
| 842 | 973 // The next frame should start by assuming nothing has changed, and changes |
| 843 // Once all layers have been drawn, pending texture uploads should no | 974 // are noted as they occur. |
| 844 // longer block future uploads. | 975 for (unsigned int i = 0; i < frame->render_surface_layer_list->size(); i++) { |
| 845 m_resourceProvider->MarkPendingUploadsAsNonBlocking(); | 976 (*frame->render_surface_layer_list)[i]->render_surface()->damage_tracker()-> |
| 846 } | 977 DidDrawDamagedArea(); |
| 847 | 978 } |
| 848 void LayerTreeHostImpl::finishAllRendering() | 979 active_tree_->root_layer()->ResetAllChangeTrackingForSubtree(); |
| 849 { | 980 UpdateAnimationState(); |
| 850 if (m_renderer) | 981 } |
| 851 m_renderer->Finish(); | 982 |
| 852 } | 983 void LayerTreeHostImpl::DidDrawAllLayers(const FrameData& frame) { |
| 853 | 984 for (size_t i = 0; i < frame.will_draw_layers.size(); ++i) |
| 854 bool LayerTreeHostImpl::isContextLost() | 985 frame.will_draw_layers[i]->DidDraw(resource_provider_.get()); |
| 855 { | 986 |
| 856 DCHECK(m_proxy->IsImplThread()); | 987 // Once all layers have been drawn, pending texture uploads should no |
| 857 return m_renderer && m_renderer->IsContextLost(); | 988 // longer block future uploads. |
| 858 } | 989 resource_provider_->MarkPendingUploadsAsNonBlocking(); |
| 859 | 990 } |
| 860 const RendererCapabilities& LayerTreeHostImpl::rendererCapabilities() const | 991 |
| 861 { | 992 void LayerTreeHostImpl::FinishAllRendering() { |
| 862 return m_renderer->Capabilities(); | 993 if (renderer_) |
| 863 } | 994 renderer_->Finish(); |
| 864 | 995 } |
| 865 bool LayerTreeHostImpl::swapBuffers() | 996 |
| 866 { | 997 bool LayerTreeHostImpl::IsContextLost() { |
| 867 if (m_tileManager) | 998 DCHECK(proxy_->IsImplThread()); |
| 868 m_tileManager->DidCompleteFrame(); | 999 return renderer_ && renderer_->IsContextLost(); |
| 869 return m_renderer->SwapBuffers(); | 1000 } |
| 870 } | 1001 |
| 871 | 1002 const RendererCapabilities& LayerTreeHostImpl::GetRendererCapabilities() const { |
| 872 gfx::Size LayerTreeHostImpl::DeviceViewportSize() const | 1003 return renderer_->Capabilities(); |
| 873 { | 1004 } |
| 874 return m_deviceViewportSize; | 1005 |
| 875 } | 1006 bool LayerTreeHostImpl::SwapBuffers() { |
| 876 | 1007 if (tile_manager_) |
| 877 const LayerTreeSettings& LayerTreeHostImpl::Settings() const | 1008 tile_manager_->DidCompleteFrame(); |
| 878 { | 1009 return renderer_->SwapBuffers(); |
| 879 return m_settings; | 1010 } |
| 880 } | 1011 |
| 881 | 1012 gfx::Size LayerTreeHostImpl::DeviceViewportSize() const { |
| 882 void LayerTreeHostImpl::DidLoseOutputSurface() | 1013 return device_viewport_size(); |
| 883 { | 1014 } |
| 884 m_client->didLoseOutputSurfaceOnImplThread(); | 1015 |
| 885 } | 1016 const LayerTreeSettings& LayerTreeHostImpl::Settings() const { |
| 886 | 1017 return settings(); |
| 887 void LayerTreeHostImpl::OnSwapBuffersComplete() | 1018 } |
| 888 { | 1019 |
| 889 m_client->onSwapBuffersCompleteOnImplThread(); | 1020 void LayerTreeHostImpl::DidLoseOutputSurface() { |
| 890 } | 1021 client_->DidLoseOutputSurfaceOnImplThread(); |
| 891 | 1022 } |
| 892 void LayerTreeHostImpl::readback(void* pixels, | 1023 |
| 893 gfx::Rect rect_in_device_viewport) | 1024 void LayerTreeHostImpl::OnSwapBuffersComplete() { |
| 894 { | 1025 client_->OnSwapBuffersCompleteOnImplThread(); |
| 895 DCHECK(m_renderer); | 1026 } |
| 896 m_renderer->GetFramebufferPixels(pixels, rect_in_device_viewport); | 1027 |
| 1028 void LayerTreeHostImpl::Readback(void* pixels, |
| 1029 gfx::Rect rect_in_device_viewport) { |
| 1030 DCHECK(renderer_); |
| 1031 renderer_->GetFramebufferPixels(pixels, rect_in_device_viewport); |
| 897 } | 1032 } |
| 898 | 1033 |
| 899 bool LayerTreeHostImpl::haveRootScrollLayer() const { | 1034 bool LayerTreeHostImpl::haveRootScrollLayer() const { |
| 900 return rootScrollLayer(); | 1035 return RootScrollLayer(); |
| 901 } | 1036 } |
| 902 | 1037 |
| 903 float LayerTreeHostImpl::rootScrollLayerTotalScrollY() const { | 1038 float LayerTreeHostImpl::rootScrollLayerTotalScrollY() const { |
| 904 if (LayerImpl* layer = rootScrollLayer()) | 1039 if (LayerImpl* layer = RootScrollLayer()) |
| 905 return layer->scroll_offset().y() + layer->scroll_delta().y(); | 1040 return layer->scroll_offset().y() + layer->scroll_delta().y(); |
| 906 return 0.0f; | 1041 return 0.0f; |
| 907 } | 1042 } |
| 908 | 1043 |
| 909 LayerImpl* LayerTreeHostImpl::rootLayer() const | 1044 LayerImpl* LayerTreeHostImpl::RootLayer() const { |
| 910 { | 1045 return active_tree_->root_layer(); |
| 911 return m_activeTree->RootLayer(); | 1046 } |
| 912 } | 1047 |
| 913 | 1048 LayerImpl* LayerTreeHostImpl::RootScrollLayer() const { |
| 914 LayerImpl* LayerTreeHostImpl::rootScrollLayer() const | 1049 return active_tree_->RootScrollLayer(); |
| 915 { | 1050 } |
| 916 return m_activeTree->RootScrollLayer(); | 1051 |
| 917 } | 1052 LayerImpl* LayerTreeHostImpl::CurrentlyScrollingLayer() const { |
| 918 | 1053 return active_tree_->CurrentlyScrollingLayer(); |
| 919 LayerImpl* LayerTreeHostImpl::currentlyScrollingLayer() const | |
| 920 { | |
| 921 return m_activeTree->CurrentlyScrollingLayer(); | |
| 922 } | 1054 } |
| 923 | 1055 |
| 924 // Content layers can be either directly scrollable or contained in an outer | 1056 // Content layers can be either directly scrollable or contained in an outer |
| 925 // scrolling layer which applies the scroll transform. Given a content layer, | 1057 // scrolling layer which applies the scroll transform. Given a content layer, |
| 926 // this function returns the associated scroll layer if any. | 1058 // this function returns the associated scroll layer if any. |
| 927 static LayerImpl* findScrollLayerForContentLayer(LayerImpl* layerImpl) | 1059 static LayerImpl* FindScrollLayerForContentLayer(LayerImpl* layer_impl) { |
| 928 { | 1060 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; | 1061 return 0; |
| 939 } | 1062 |
| 940 | 1063 if (layer_impl->scrollable()) |
| 941 void LayerTreeHostImpl::createPendingTree() | 1064 return layer_impl; |
| 942 { | 1065 |
| 943 CHECK(!m_pendingTree); | 1066 if (layer_impl->DrawsContent() && |
| 944 if (m_recycleTree) | 1067 layer_impl->parent() && |
| 945 m_recycleTree.swap(m_pendingTree); | 1068 layer_impl->parent()->scrollable()) |
| 946 else | 1069 return layer_impl->parent(); |
| 947 m_pendingTree = LayerTreeImpl::create(this); | 1070 |
| 948 m_client->onCanDrawStateChanged(canDraw()); | 1071 return 0; |
| 949 m_client->onHasPendingTreeStateChanged(pendingTree()); | 1072 } |
| 950 TRACE_EVENT_ASYNC_BEGIN0("cc", "PendingTree", m_pendingTree.get()); | 1073 |
| 951 TRACE_EVENT_ASYNC_STEP0("cc", | 1074 void LayerTreeHostImpl::CreatePendingTree() { |
| 952 "PendingTree", m_pendingTree.get(), "waiting"); | 1075 CHECK(!pending_tree_); |
| 953 } | 1076 if (recycle_tree_) |
| 954 | 1077 recycle_tree_.swap(pending_tree_); |
| 955 void LayerTreeHostImpl::checkForCompletedTileUploads() | 1078 else |
| 956 { | 1079 pending_tree_ = LayerTreeImpl::create(this); |
| 957 DCHECK(!m_client->isInsideDraw()) << "Checking for completed uploads within
a draw may trigger spurious redraws."; | 1080 client_->OnCanDrawStateChanged(CanDraw()); |
| 958 if (m_tileManager) | 1081 client_->OnHasPendingTreeStateChanged(pending_tree_); |
| 959 m_tileManager->CheckForCompletedTileUploads(); | 1082 TRACE_EVENT_ASYNC_BEGIN0("cc", "PendingTree", pending_tree_.get()); |
| 960 } | 1083 TRACE_EVENT_ASYNC_STEP0("cc", |
| 961 | 1084 "PendingTree", pending_tree_.get(), "waiting"); |
| 962 bool LayerTreeHostImpl::activatePendingTreeIfNeeded() | 1085 } |
| 963 { | 1086 |
| 964 if (!pendingTree()) | 1087 void LayerTreeHostImpl::CheckForCompletedTileUploads() { |
| 965 return false; | 1088 DCHECK(!client_->IsInsideDraw()) << |
| 966 | 1089 "Checking for completed uploads within a draw may trigger " |
| 967 CHECK(m_tileManager); | 1090 "spurious redraws."; |
| 968 | 1091 if (tile_manager_) |
| 969 pendingTree()->UpdateDrawProperties(LayerTreeImpl::UPDATE_PENDING_TREE); | 1092 tile_manager_->CheckForCompletedTileUploads(); |
| 970 | 1093 } |
| 971 TRACE_EVENT_ASYNC_STEP1("cc", | 1094 |
| 972 "PendingTree", m_pendingTree.get(), "activate", | 1095 bool LayerTreeHostImpl::ActivatePendingTreeIfNeeded() { |
| 973 "state", ValueToString(activationStateAsValue())); | 1096 if (!pending_tree_) |
| 974 | 1097 return false; |
| 975 // It's always fine to activate to an empty tree. Otherwise, only | 1098 |
| 976 // activate once all visible resources in pending tree are ready | 1099 CHECK(tile_manager_); |
| 977 // or tile manager has no work scheduled for pending tree. | 1100 |
| 978 if (activeTree()->RootLayer() && | 1101 pending_tree_->UpdateDrawProperties(LayerTreeImpl::UPDATE_PENDING_TREE); |
| 979 !pendingTree()->AreVisibleResourcesReady()) { | 1102 |
| 980 // In smoothness takes priority mode, the pending tree's priorities are | 1103 TRACE_EVENT_ASYNC_STEP1("cc", |
| 981 // ignored, so the tile manager may not have work for it even though it | 1104 "PendingTree", pending_tree_.get(), "activate", |
| 982 // is simultaneously not ready to be activated. | 1105 "state", ValueToString(ActivationStateAsValue())); |
| 983 if (m_tileManager->GlobalState().tree_priority == | 1106 |
| 984 SMOOTHNESS_TAKES_PRIORITY || | 1107 // It's always fine to activate to an empty tree. Otherwise, only |
| 985 m_tileManager->HasPendingWorkScheduled(PENDING_TREE)) { | 1108 // activate once all visible resources in pending tree are ready |
| 986 TRACE_EVENT_ASYNC_STEP0("cc", | 1109 // or tile manager has no work scheduled for pending tree. |
| 987 "PendingTree", | 1110 if (active_tree_->root_layer() && |
| 988 m_pendingTree.get(), | 1111 !pending_tree_->AreVisibleResourcesReady()) { |
| 989 "waiting"); | 1112 // In smoothness takes priority mode, the pending tree's priorities are |
| 990 return false; | 1113 // ignored, so the tile manager may not have work for it even though it |
| 991 } | 1114 // is simultaneously not ready to be activated. |
| 1115 if (tile_manager_->GlobalState().tree_priority == |
| 1116 SMOOTHNESS_TAKES_PRIORITY || |
| 1117 tile_manager_->HasPendingWorkScheduled(PENDING_TREE)) { |
| 1118 TRACE_EVENT_ASYNC_STEP0("cc", |
| 1119 "PendingTree", |
| 1120 pending_tree_.get(), |
| 1121 "waiting"); |
| 1122 return false; |
| 992 } | 1123 } |
| 993 | 1124 } |
| 994 activatePendingTree(); | 1125 |
| 995 return true; | 1126 ActivatePendingTree(); |
| 996 } | 1127 return true; |
| 997 | 1128 } |
| 998 void LayerTreeHostImpl::activatePendingTree() | 1129 |
| 999 { | 1130 void LayerTreeHostImpl::ActivatePendingTree() { |
| 1000 CHECK(m_pendingTree); | 1131 CHECK(pending_tree_); |
| 1001 TRACE_EVENT_ASYNC_END0("cc", "PendingTree", m_pendingTree.get()); | 1132 TRACE_EVENT_ASYNC_END0("cc", "PendingTree", pending_tree_.get()); |
| 1002 | 1133 |
| 1003 m_activeTree->PushPersistedState(m_pendingTree.get()); | 1134 active_tree_->PushPersistedState(pending_tree_.get()); |
| 1004 if (m_pendingTree->needs_full_tree_sync()) | 1135 if (pending_tree_->needs_full_tree_sync()) { |
| 1005 m_activeTree->SetRootLayer(TreeSynchronizer::synchronizeTrees(m_pendingT
ree->RootLayer(), m_activeTree->DetachLayerTree(), m_activeTree.get())); | 1136 active_tree_->SetRootLayer( |
| 1006 TreeSynchronizer::pushProperties(m_pendingTree->RootLayer(), m_activeTree->R
ootLayer()); | 1137 TreeSynchronizer::synchronizeTrees(pending_tree_->root_layer(), |
| 1007 DCHECK(!m_recycleTree); | 1138 active_tree_->DetachLayerTree(), |
| 1008 | 1139 active_tree_.get())); |
| 1009 m_pendingTree->PushPropertiesTo(m_activeTree.get()); | 1140 } |
| 1010 | 1141 TreeSynchronizer::pushProperties(pending_tree_->root_layer(), |
| 1011 // Now that we've synced everything from the pending tree to the active | 1142 active_tree_->root_layer()); |
| 1012 // tree, rename the pending tree the recycle tree so we can reuse it on the | 1143 DCHECK(!recycle_tree_); |
| 1013 // next sync. | 1144 |
| 1014 m_pendingTree.swap(m_recycleTree); | 1145 pending_tree_->PushPropertiesTo(active_tree_.get()); |
| 1015 m_recycleTree->ClearRenderSurfaces(); | 1146 |
| 1016 | 1147 // Now that we've synced everything from the pending tree to the active |
| 1017 m_activeTree->DidBecomeActive(); | 1148 // tree, rename the pending tree the recycle tree so we can reuse it on the |
| 1018 | 1149 // next sync. |
| 1019 // Reduce wasted memory now that unlinked resources are guaranteed not | 1150 pending_tree_.swap(recycle_tree_); |
| 1020 // to be used. | 1151 recycle_tree_->ClearRenderSurfaces(); |
| 1021 m_client->reduceWastedContentsTextureMemoryOnImplThread(); | 1152 |
| 1022 | 1153 active_tree_->DidBecomeActive(); |
| 1023 m_client->onCanDrawStateChanged(canDraw()); | 1154 |
| 1024 m_client->onHasPendingTreeStateChanged(pendingTree()); | 1155 // Reduce wasted memory now that unlinked resources are guaranteed not |
| 1025 m_client->setNeedsRedrawOnImplThread(); | 1156 // to be used. |
| 1026 m_client->renewTreePriority(); | 1157 client_->ReduceWastedContentsTextureMemoryOnImplThread(); |
| 1027 | 1158 |
| 1028 if (m_tileManager && m_debugState.continuousPainting) { | 1159 client_->OnCanDrawStateChanged(CanDraw()); |
| 1029 RenderingStats stats; | 1160 client_->OnHasPendingTreeStateChanged(pending_tree_); |
| 1030 m_tileManager->GetRenderingStats(&stats); | 1161 client_->SetNeedsRedrawOnImplThread(); |
| 1031 m_paintTimeCounter->SaveRasterizeTime(stats.totalRasterizeTimeForNowBins
OnPendingTree, m_activeTree->source_frame_number()); | 1162 client_->RenewTreePriority(); |
| 1163 |
| 1164 if (tile_manager_ && debug_state_.continuousPainting) { |
| 1165 RenderingStats stats; |
| 1166 tile_manager_->GetRenderingStats(&stats); |
| 1167 paint_time_counter_->SaveRasterizeTime( |
| 1168 stats.totalRasterizeTimeForNowBinsOnPendingTree, |
| 1169 active_tree_->source_frame_number()); |
| 1170 } |
| 1171 } |
| 1172 |
| 1173 void LayerTreeHostImpl::SetVisible(bool visible) { |
| 1174 DCHECK(proxy_->IsImplThread()); |
| 1175 |
| 1176 if (visible_ == visible) |
| 1177 return; |
| 1178 visible_ = visible; |
| 1179 DidVisibilityChange(this, visible_); |
| 1180 EnforceManagedMemoryPolicy(managed_memory_policy_); |
| 1181 |
| 1182 if (!renderer_) |
| 1183 return; |
| 1184 |
| 1185 renderer_->SetVisible(visible); |
| 1186 |
| 1187 SetBackgroundTickingEnabled( |
| 1188 !visible_ && |
| 1189 !animation_registrar_->active_animation_controllers().empty()); |
| 1190 } |
| 1191 |
| 1192 bool LayerTreeHostImpl::InitializeRenderer( |
| 1193 scoped_ptr<OutputSurface> output_surface) { |
| 1194 // Since we will create a new resource provider, we cannot continue to use |
| 1195 // the old resources (i.e. render_surfaces and texture IDs). Clear them |
| 1196 // before we destroy the old resource provider. |
| 1197 if (active_tree_->root_layer()) |
| 1198 ClearRenderSurfaces(); |
| 1199 if (active_tree_->root_layer()) |
| 1200 SendDidLoseOutputSurfaceRecursive(active_tree_->root_layer()); |
| 1201 if (pending_tree_ && pending_tree_->root_layer()) |
| 1202 SendDidLoseOutputSurfaceRecursive(pending_tree_->root_layer()); |
| 1203 if (recycle_tree_ && recycle_tree_->root_layer()) |
| 1204 SendDidLoseOutputSurfaceRecursive(recycle_tree_->root_layer()); |
| 1205 |
| 1206 // Note: order is important here. |
| 1207 renderer_.reset(); |
| 1208 tile_manager_.reset(); |
| 1209 resource_provider_.reset(); |
| 1210 output_surface_.reset(); |
| 1211 |
| 1212 if (!output_surface->BindToClient(this)) |
| 1213 return false; |
| 1214 |
| 1215 scoped_ptr<ResourceProvider> resource_provider = |
| 1216 ResourceProvider::Create(output_surface.get()); |
| 1217 if (!resource_provider) |
| 1218 return false; |
| 1219 |
| 1220 if (settings_.implSidePainting) { |
| 1221 tile_manager_.reset(new TileManager(this, |
| 1222 resource_provider.get(), |
| 1223 settings_.numRasterThreads, |
| 1224 settings_.useCheapnessEstimator, |
| 1225 settings_.useColorEstimator, |
| 1226 settings_.predictionBenchmarking)); |
| 1227 tile_manager_->SetRecordRenderingStats(debug_state_.recordRenderingStats()); |
| 1228 } |
| 1229 |
| 1230 if (output_surface->capabilities().has_parent_compositor) { |
| 1231 renderer_ = DelegatingRenderer::Create(this, 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 local_delta) { |
| 1474 gfx::Vector2dF previous_delta(layer_impl->scroll_delta()); |
| 1475 layer_impl->ScrollBy(local_delta); |
| 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 { |
| 1509 applied_delta = ScrollLayerWithLocalDelta(layer_impl, pending_delta); |
| 1145 } | 1510 } |
| 1146 | 1511 |
| 1147 for (size_t i = 0; i < layerImpl->children().size(); ++i) | 1512 // If the layer wasn't able to move, try the next one in the hierarchy. |
| 1148 adjustScrollsForPageScaleChange(layerImpl->children()[i], pageScaleChang
e); | 1513 float move_threshold_squared = 0.1f * 0.1f; |
| 1149 } | 1514 if (applied_delta.LengthSquared() < move_threshold_squared) { |
| 1150 | 1515 if (should_bubble_scrolls_ || !did_lock_scrolling_layer_) |
| 1151 void LayerTreeHostImpl::setDeviceScaleFactor(float deviceScaleFactor) | 1516 continue; |
| 1152 { | 1517 else |
| 1153 if (deviceScaleFactor == m_deviceScaleFactor) | 1518 break; |
| 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 } | 1519 } |
| 1226 | 1520 did_scroll = true; |
| 1227 // When hiding top controls is enabled and the controls are hidden or | 1521 did_lock_scrolling_layer_ = true; |
| 1228 // overlaying the content, force scrolls to be enabled on the root layer to | 1522 if (!should_bubble_scrolls_) { |
| 1229 // allow bringing the top controls back into view. | 1523 active_tree_->set_currently_scrolling_layer(layer_impl); |
| 1230 if (!potentiallyScrollingLayerImpl && m_topControlsManager && | 1524 break; |
| 1231 m_topControlsManager->content_top_offset() != m_settings.topControls
Height) { | |
| 1232 potentiallyScrollingLayerImpl = rootScrollLayer(); | |
| 1233 } | 1525 } |
| 1234 | 1526 |
| 1235 if (potentiallyScrollingLayerImpl) { | 1527 // If the applied delta is within 45 degrees of the input delta, bail out to |
| 1236 m_activeTree->set_currently_scrolling_layer(potentiallyScrollingLayerImp
l); | 1528 // make it easier to scroll just one layer in one direction without |
| 1237 m_shouldBubbleScrolls = (type != NonBubblingGesture); | 1529 // affecting any of its parents. |
| 1238 m_wheelScrolling = (type == Wheel); | 1530 float angle_threshold = 45; |
| 1239 m_numImplThreadScrolls++; | 1531 if (MathUtil::smallestAngleBetweenVectors( |
| 1240 m_client->renewTreePriority(); | 1532 applied_delta, pending_delta) < angle_threshold) { |
| 1241 UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", false); | 1533 pending_delta = gfx::Vector2d(); |
| 1242 return ScrollStarted; | 1534 break; |
| 1243 } | 1535 } |
| 1244 return ScrollIgnored; | 1536 |
| 1245 } | 1537 // Allow further movement only on an axis perpendicular to the direction in |
| 1246 | 1538 // which the layer moved. |
| 1247 gfx::Vector2dF LayerTreeHostImpl::scrollLayerWithViewportSpaceDelta(LayerImpl* l
ayerImpl, float scaleFromViewportToScreenSpace, gfx::PointF viewportPoint, gfx::
Vector2dF viewportDelta) | 1539 gfx::Vector2dF perpendicular_axis(-applied_delta.y(), applied_delta.x()); |
| 1248 { | 1540 pending_delta = MathUtil::projectVector(pending_delta, perpendicular_axis); |
| 1249 // Layers with non-invertible screen space transforms should not have passed
the scroll hit | 1541 |
| 1250 // test in the first place. | 1542 if (gfx::ToFlooredVector2d(pending_delta).IsZero()) |
| 1251 DCHECK(layerImpl->screen_space_transform().IsInvertible()); | 1543 break; |
| 1252 gfx::Transform inverseScreenSpaceTransform(gfx::Transform::kSkipInitializati
on); | 1544 } |
| 1253 bool didInvert = layerImpl->screen_space_transform().GetInverse(&inverseScre
enSpaceTransform); | 1545 |
| 1254 // TODO: With the advent of impl-side crolling for non-root layers, we may | 1546 if (did_scroll) { |
| 1255 // need to explicitly handle uninvertible transforms here. | 1547 client_->SetNeedsCommitOnImplThread(); |
| 1256 DCHECK(didInvert); | 1548 client_->SetNeedsRedrawOnImplThread(); |
| 1257 | 1549 client_->RenewTreePriority(); |
| 1258 gfx::PointF screenSpacePoint = gfx::ScalePoint(viewportPoint, scaleFromViewp
ortToScreenSpace); | 1550 } |
| 1259 | 1551 return did_scroll; |
| 1260 gfx::Vector2dF screenSpaceDelta = viewportDelta; | 1552 } |
| 1261 screenSpaceDelta.Scale(scaleFromViewportToScreenSpace); | 1553 |
| 1262 | 1554 void LayerTreeHostImpl::ClearCurrentlyScrollingLayer() { |
| 1263 // First project the scroll start and end points to local layer space to fin
d the scroll delta | 1555 active_tree_->ClearCurrentlyScrollingLayer(); |
| 1264 // in layer coordinates. | 1556 did_lock_scrolling_layer_ = false; |
| 1265 bool startClipped, endClipped; | 1557 } |
| 1266 gfx::PointF screenSpaceEndPoint = screenSpacePoint + screenSpaceDelta; | 1558 |
| 1267 gfx::PointF localStartPoint = MathUtil::projectPoint(inverseScreenSpaceTrans
form, screenSpacePoint, startClipped); | 1559 void LayerTreeHostImpl::ScrollEnd() { |
| 1268 gfx::PointF localEndPoint = MathUtil::projectPoint(inverseScreenSpaceTransfo
rm, screenSpaceEndPoint, endClipped); | 1560 if (top_controls_manager_) |
| 1269 | 1561 top_controls_manager_->ScrollEnd(); |
| 1270 // In general scroll point coordinates should not get clipped. | 1562 ClearCurrentlyScrollingLayer(); |
| 1271 DCHECK(!startClipped); | 1563 } |
| 1272 DCHECK(!endClipped); | 1564 |
| 1273 if (startClipped || endClipped) | 1565 void LayerTreeHostImpl::PinchGestureBegin() { |
| 1274 return gfx::Vector2dF(); | 1566 pinch_gesture_active_ = true; |
| 1275 | 1567 previous_pinch_anchor_ = gfx::Point(); |
| 1276 // localStartPoint and localEndPoint are in content space but we want to mov
e them to layer space for scrolling. | 1568 client_->RenewTreePriority(); |
| 1277 float widthScale = 1.f / layerImpl->contents_scale_x(); | 1569 } |
| 1278 float heightScale = 1.f / layerImpl->contents_scale_y(); | 1570 |
| 1279 localStartPoint.Scale(widthScale, heightScale); | 1571 void LayerTreeHostImpl::PinchGestureUpdate(float magnify_delta, |
| 1280 localEndPoint.Scale(widthScale, heightScale); | 1572 gfx::Point anchor) { |
| 1281 | 1573 TRACE_EVENT0("cc", "LayerTreeHostImpl::PinchGestureUpdate"); |
| 1282 // Apply the scroll delta. | 1574 |
| 1283 gfx::Vector2dF previousDelta = layerImpl->scroll_delta(); | 1575 if (!RootScrollLayer()) |
| 1284 layerImpl->ScrollBy(localEndPoint - localStartPoint); | 1576 return; |
| 1285 | 1577 |
| 1286 // Get the end point in the layer's content space so we can apply its screen
SpaceTransform. | 1578 // Keep the center-of-pinch anchor specified by (x, y) in a stable |
| 1287 gfx::PointF actualLocalEndPoint = localStartPoint + layerImpl->scroll_delta(
) - previousDelta; | 1579 // position over the course of the magnify. |
| 1288 gfx::PointF actualLocalContentEndPoint = gfx::ScalePoint(actualLocalEndPoint
, 1 / widthScale, 1 / heightScale); | 1580 float page_scale_delta = active_tree_->page_scale_delta(); |
| 1289 | 1581 gfx::PointF previous_scale_anchor = |
| 1290 // Calculate the applied scroll delta in viewport space coordinates. | 1582 gfx::ScalePoint(anchor, 1.f / page_scale_delta); |
| 1291 gfx::PointF actualScreenSpaceEndPoint = MathUtil::mapPoint(layerImpl->screen
_space_transform(), actualLocalContentEndPoint, endClipped); | 1583 active_tree_->SetPageScaleDelta(page_scale_delta * magnify_delta); |
| 1292 DCHECK(!endClipped); | 1584 page_scale_delta = active_tree_->page_scale_delta(); |
| 1293 if (endClipped) | 1585 gfx::PointF new_scale_anchor = |
| 1294 return gfx::Vector2dF(); | 1586 gfx::ScalePoint(anchor, 1.f / page_scale_delta); |
| 1295 gfx::PointF actualViewportEndPoint = gfx::ScalePoint(actualScreenSpaceEndPoi
nt, 1 / scaleFromViewportToScreenSpace); | 1587 gfx::Vector2dF move = previous_scale_anchor - new_scale_anchor; |
| 1296 return actualViewportEndPoint - viewportPoint; | 1588 |
| 1297 } | 1589 previous_pinch_anchor_ = anchor; |
| 1298 | 1590 |
| 1299 static gfx::Vector2dF scrollLayerWithLocalDelta(LayerImpl& layerImpl, gfx::Vecto
r2dF localDelta) | 1591 move.Scale(1 / active_tree_->page_scale_factor()); |
| 1300 { | 1592 |
| 1301 gfx::Vector2dF previousDelta(layerImpl.scroll_delta()); | 1593 RootScrollLayer()->ScrollBy(move); |
| 1302 layerImpl.ScrollBy(localDelta); | 1594 |
| 1303 return layerImpl.scroll_delta() - previousDelta; | 1595 if (RootScrollLayer()->scrollbar_animation_controller()) { |
| 1304 } | 1596 RootScrollLayer()->scrollbar_animation_controller()-> |
| 1305 | 1597 didPinchGestureUpdate(base::TimeTicks::Now()); |
| 1306 bool LayerTreeHostImpl::scrollBy(const gfx::Point& viewportPoint, | 1598 } |
| 1307 const gfx::Vector2dF& scrollDelta) | 1599 |
| 1308 { | 1600 client_->SetNeedsCommitOnImplThread(); |
| 1309 TRACE_EVENT0("cc", "LayerTreeHostImpl::scrollBy"); | 1601 client_->SetNeedsRedrawOnImplThread(); |
| 1310 if (!currentlyScrollingLayer()) | 1602 client_->RenewTreePriority(); |
| 1311 return false; | 1603 } |
| 1312 | 1604 |
| 1313 gfx::Vector2dF pendingDelta = scrollDelta; | 1605 void LayerTreeHostImpl::PinchGestureEnd() { |
| 1314 bool didScroll = false; | 1606 pinch_gesture_active_ = false; |
| 1315 | 1607 |
| 1316 for (LayerImpl* layerImpl = currentlyScrollingLayer(); layerImpl; layerImpl
= layerImpl->parent()) { | 1608 if (RootScrollLayer() && |
| 1317 if (!layerImpl->scrollable()) | 1609 RootScrollLayer()->scrollbar_animation_controller()) { |
| 1318 continue; | 1610 RootScrollLayer()->scrollbar_animation_controller()-> |
| 1319 | 1611 didPinchGestureEnd(base::TimeTicks::Now()); |
| 1320 gfx::Vector2dF appliedDelta; | 1612 } |
| 1321 if (m_topControlsManager && layerImpl == rootScrollLayer()) | 1613 |
| 1322 pendingDelta = m_topControlsManager->ScrollBy(pendingDelta); | 1614 client_->SetNeedsCommitOnImplThread(); |
| 1323 | 1615 } |
| 1324 // Gesture events need to be transformed from viewport coordinates to lo
cal layer coordinates | 1616 |
| 1325 // so that the scrolling contents exactly follow the user's finger. In c
ontrast, wheel | 1617 static void CollectScrollDeltas(ScrollAndScaleSet* scroll_info, |
| 1326 // events represent a fixed amount of scrolling so we can just apply the
m directly. | 1618 LayerImpl* layer_impl) { |
| 1327 if (!m_wheelScrolling) { | 1619 if (!layer_impl) |
| 1328 float scaleFromViewportToScreenSpace = m_deviceScaleFactor; | 1620 return; |
| 1329 appliedDelta = scrollLayerWithViewportSpaceDelta(layerImpl, scaleFro
mViewportToScreenSpace, viewportPoint, pendingDelta); | 1621 |
| 1330 } else | 1622 gfx::Vector2d scroll_delta = |
| 1331 appliedDelta = scrollLayerWithLocalDelta(*layerImpl, pendingDelta); | 1623 gfx::ToFlooredVector2d(layer_impl->scroll_delta()); |
| 1332 | 1624 if (!scroll_delta.IsZero()) { |
| 1333 // If the layer wasn't able to move, try the next one in the hierarchy. | 1625 LayerTreeHostCommon::ScrollUpdateInfo scroll; |
| 1334 float moveThresholdSquared = 0.1f * 0.1f; | 1626 scroll.layerId = layer_impl->id(); |
| 1335 if (appliedDelta.LengthSquared() < moveThresholdSquared) { | 1627 scroll.scrollDelta = scroll_delta; |
| 1336 if (m_shouldBubbleScrolls || !m_didLockScrollingLayer) | 1628 scroll_info->scrolls.push_back(scroll); |
| 1337 continue; | 1629 layer_impl->SetSentScrollDelta(scroll_delta); |
| 1338 else | 1630 } |
| 1339 break; | 1631 |
| 1340 } | 1632 for (size_t i = 0; i < layer_impl->children().size(); ++i) |
| 1341 didScroll = true; | 1633 CollectScrollDeltas(scroll_info, layer_impl->children()[i]); |
| 1342 m_didLockScrollingLayer = true; | 1634 } |
| 1343 if (!m_shouldBubbleScrolls) { | 1635 |
| 1344 m_activeTree->set_currently_scrolling_layer(layerImpl); | 1636 scoped_ptr<ScrollAndScaleSet> LayerTreeHostImpl::ProcessScrollDeltas() { |
| 1345 break; | 1637 scoped_ptr<ScrollAndScaleSet> scroll_info(new ScrollAndScaleSet()); |
| 1346 } | 1638 |
| 1347 | 1639 CollectScrollDeltas(scroll_info.get(), active_tree_->root_layer()); |
| 1348 // If the applied delta is within 45 degrees of the input delta, bail ou
t to make it easier | 1640 scroll_info->pageScaleDelta = active_tree_->page_scale_delta(); |
| 1349 // to scroll just one layer in one direction without affecting any of it
s parents. | 1641 active_tree_->set_sent_page_scale_delta(scroll_info->pageScaleDelta); |
| 1350 float angleThreshold = 45; | 1642 |
| 1351 if (MathUtil::smallestAngleBetweenVectors(appliedDelta, pendingDelta) <
angleThreshold) { | 1643 return scroll_info.Pass(); |
| 1352 pendingDelta = gfx::Vector2d(); | 1644 } |
| 1353 break; | 1645 |
| 1354 } | 1646 void LayerTreeHostImpl::SetFullRootLayerDamage() { |
| 1355 | 1647 if (active_tree_->root_layer()) { |
| 1356 // Allow further movement only on an axis perpendicular to the direction
in which the layer | 1648 RenderSurfaceImpl* render_surface = |
| 1357 // moved. | 1649 active_tree_->root_layer()->render_surface(); |
| 1358 gfx::Vector2dF perpendicularAxis(-appliedDelta.y(), appliedDelta.x()); | 1650 if (render_surface) |
| 1359 pendingDelta = MathUtil::projectVector(pendingDelta, perpendicularAxis); | 1651 render_surface->damage_tracker()->ForceFullDamageNextUpdate(); |
| 1360 | 1652 } |
| 1361 if (gfx::ToFlooredVector2d(pendingDelta).IsZero()) | 1653 } |
| 1362 break; | 1654 |
| 1363 } | 1655 void LayerTreeHostImpl::AnimatePageScale(base::TimeTicks time) { |
| 1364 | 1656 if (!page_scale_animation_ || !RootScrollLayer()) |
| 1365 if (didScroll) { | 1657 return; |
| 1366 m_client->setNeedsCommitOnImplThread(); | 1658 |
| 1367 m_client->setNeedsRedrawOnImplThread(); | 1659 double monotonic_time = (time - base::TimeTicks()).InSecondsF(); |
| 1368 m_client->renewTreePriority(); | 1660 gfx::Vector2dF scroll_total = RootScrollLayer()->scroll_offset() + |
| 1369 } | 1661 RootScrollLayer()->scroll_delta(); |
| 1370 return didScroll; | 1662 |
| 1371 } | 1663 active_tree_->SetPageScaleDelta( |
| 1372 | 1664 page_scale_animation_->PageScaleFactorAtTime(monotonic_time) / |
| 1373 void LayerTreeHostImpl::clearCurrentlyScrollingLayer() | 1665 active_tree_->page_scale_factor()); |
| 1374 { | 1666 gfx::Vector2dF next_scroll = |
| 1375 m_activeTree->ClearCurrentlyScrollingLayer(); | 1667 page_scale_animation_->ScrollOffsetAtTime(monotonic_time); |
| 1376 m_didLockScrollingLayer = false; | 1668 |
| 1377 } | 1669 RootScrollLayer()->ScrollBy(next_scroll - scroll_total); |
| 1378 | 1670 client_->SetNeedsRedrawOnImplThread(); |
| 1379 void LayerTreeHostImpl::scrollEnd() | 1671 |
| 1380 { | 1672 if (page_scale_animation_->IsAnimationCompleteAtTime(monotonic_time)) { |
| 1381 if (m_topControlsManager) | 1673 page_scale_animation_.reset(); |
| 1382 m_topControlsManager->ScrollEnd(); | 1674 client_->SetNeedsCommitOnImplThread(); |
| 1383 clearCurrentlyScrollingLayer(); | 1675 client_->RenewTreePriority(); |
| 1384 } | 1676 } |
| 1385 | 1677 } |
| 1386 void LayerTreeHostImpl::pinchGestureBegin() | 1678 |
| 1387 { | 1679 void LayerTreeHostImpl::AnimateLayers(base::TimeTicks monotonic_time, |
| 1388 m_pinchGestureActive = true; | 1680 base::Time wall_clock_time) { |
| 1389 m_previousPinchAnchor = gfx::Point(); | 1681 if (!settings_.acceleratedAnimationEnabled || |
| 1390 m_client->renewTreePriority(); | 1682 animation_registrar_->active_animation_controllers().empty() || |
| 1391 } | 1683 !active_tree_->root_layer()) |
| 1392 | 1684 return; |
| 1393 void LayerTreeHostImpl::pinchGestureUpdate(float magnifyDelta, gfx::Point anchor
) | 1685 |
| 1394 { | 1686 TRACE_EVENT0("cc", "LayerTreeHostImpl::AnimateLayers"); |
| 1395 TRACE_EVENT0("cc", "LayerTreeHostImpl::pinchGestureUpdate"); | 1687 |
| 1396 | 1688 last_animation_time_ = wall_clock_time; |
| 1397 if (!rootScrollLayer()) | 1689 double monotonic_seconds = (monotonic_time - base::TimeTicks()).InSecondsF(); |
| 1398 return; | 1690 |
| 1399 | 1691 AnimationRegistrar::AnimationControllerMap copy = |
| 1400 // Keep the center-of-pinch anchor specified by (x, y) in a stable | 1692 animation_registrar_->active_animation_controllers(); |
| 1401 // position over the course of the magnify. | 1693 for (AnimationRegistrar::AnimationControllerMap::iterator iter = copy.begin(); |
| 1402 float pageScaleDelta = activeTree()->page_scale_delta(); | 1694 iter != copy.end(); |
| 1403 gfx::PointF previousScaleAnchor = gfx::ScalePoint(anchor, 1 / pageScaleDelta
); | 1695 ++iter) |
| 1404 activeTree()->SetPageScaleDelta(pageScaleDelta * magnifyDelta); | 1696 (*iter).second->Animate(monotonic_seconds); |
| 1405 pageScaleDelta = activeTree()->page_scale_delta(); | 1697 |
| 1406 gfx::PointF newScaleAnchor = gfx::ScalePoint(anchor, 1 / pageScaleDelta); | 1698 client_->SetNeedsRedrawOnImplThread(); |
| 1407 gfx::Vector2dF move = previousScaleAnchor - newScaleAnchor; | 1699 SetBackgroundTickingEnabled( |
| 1408 | 1700 !visible_ && |
| 1409 m_previousPinchAnchor = anchor; | 1701 !animation_registrar_->active_animation_controllers().empty()); |
| 1410 | 1702 } |
| 1411 move.Scale(1 / activeTree()->page_scale_factor()); | 1703 |
| 1412 | 1704 void LayerTreeHostImpl::UpdateAnimationState() { |
| 1413 rootScrollLayer()->ScrollBy(move); | 1705 if (!settings_.acceleratedAnimationEnabled || |
| 1414 | 1706 animation_registrar_->active_animation_controllers().empty() || |
| 1415 if (rootScrollLayer()->scrollbar_animation_controller()) | 1707 !active_tree_->root_layer()) |
| 1416 rootScrollLayer()->scrollbar_animation_controller()->didPinchGestureUpda
te(base::TimeTicks::Now()); | 1708 return; |
| 1417 | 1709 |
| 1418 m_client->setNeedsCommitOnImplThread(); | 1710 TRACE_EVENT0("cc", "LayerTreeHostImpl::UpdateAnimationState"); |
| 1419 m_client->setNeedsRedrawOnImplThread(); | 1711 scoped_ptr<AnimationEventsVector> events = |
| 1420 m_client->renewTreePriority(); | 1712 make_scoped_ptr(new AnimationEventsVector); |
| 1421 } | 1713 AnimationRegistrar::AnimationControllerMap copy = |
| 1422 | 1714 animation_registrar_->active_animation_controllers(); |
| 1423 void LayerTreeHostImpl::pinchGestureEnd() | 1715 for (AnimationRegistrar::AnimationControllerMap::iterator iter = copy.begin(); |
| 1424 { | 1716 iter != copy.end(); |
| 1425 m_pinchGestureActive = false; | 1717 ++iter) |
| 1426 | 1718 (*iter).second->UpdateState(events.get()); |
| 1427 if (rootScrollLayer() && rootScrollLayer()->scrollbar_animation_controller()
) | 1719 |
| 1428 rootScrollLayer()->scrollbar_animation_controller()->didPinchGestureEnd(
base::TimeTicks::Now()); | 1720 if (!events->empty()) { |
| 1429 | 1721 client_->PostAnimationEventsToMainThreadOnImplThread(events.Pass(), |
| 1430 m_client->setNeedsCommitOnImplThread(); | 1722 last_animation_time_); |
| 1431 } | 1723 } |
| 1432 | 1724 } |
| 1433 static void collectScrollDeltas(ScrollAndScaleSet* scrollInfo, LayerImpl* layerI
mpl) | 1725 |
| 1434 { | 1726 base::TimeDelta LayerTreeHostImpl::LowFrequencyAnimationInterval() const { |
| 1435 if (!layerImpl) | 1727 return base::TimeDelta::FromSeconds(1); |
| 1436 return; | 1728 } |
| 1437 | 1729 |
| 1438 gfx::Vector2d scrollDelta = gfx::ToFlooredVector2d(layerImpl->scroll_delta()
); | 1730 void LayerTreeHostImpl::SendDidLoseOutputSurfaceRecursive(LayerImpl* current) { |
| 1439 if (!scrollDelta.IsZero()) { | 1731 DCHECK(current); |
| 1440 LayerTreeHostCommon::ScrollUpdateInfo scroll; | 1732 current->DidLoseOutputSurface(); |
| 1441 scroll.layerId = layerImpl->id(); | 1733 if (current->mask_layer()) |
| 1442 scroll.scrollDelta = scrollDelta; | 1734 SendDidLoseOutputSurfaceRecursive(current->mask_layer()); |
| 1443 scrollInfo->scrolls.push_back(scroll); | 1735 if (current->replica_layer()) |
| 1444 layerImpl->SetSentScrollDelta(scrollDelta); | 1736 SendDidLoseOutputSurfaceRecursive(current->replica_layer()); |
| 1445 } | 1737 for (size_t i = 0; i < current->children().size(); ++i) |
| 1446 | 1738 SendDidLoseOutputSurfaceRecursive(current->children()[i]); |
| 1447 for (size_t i = 0; i < layerImpl->children().size(); ++i) | 1739 } |
| 1448 collectScrollDeltas(scrollInfo, layerImpl->children()[i]); | 1740 |
| 1449 } | 1741 void LayerTreeHostImpl::ClearRenderSurfaces() { |
| 1450 | 1742 active_tree_->ClearRenderSurfaces(); |
| 1451 scoped_ptr<ScrollAndScaleSet> LayerTreeHostImpl::processScrollDeltas() | 1743 if (pending_tree_) |
| 1452 { | 1744 pending_tree_->ClearRenderSurfaces(); |
| 1453 scoped_ptr<ScrollAndScaleSet> scrollInfo(new ScrollAndScaleSet()); | 1745 } |
| 1454 | 1746 |
| 1455 collectScrollDeltas(scrollInfo.get(), rootLayer()); | 1747 std::string LayerTreeHostImpl::LayerTreeAsText() const { |
| 1456 scrollInfo->pageScaleDelta = activeTree()->page_scale_delta(); | 1748 std::string str; |
| 1457 activeTree()->set_sent_page_scale_delta(scrollInfo->pageScaleDelta); | 1749 if (active_tree_->root_layer()) { |
| 1458 | 1750 str = active_tree_->root_layer()->LayerTreeAsText(); |
| 1459 return scrollInfo.Pass(); | 1751 str += "RenderSurfaces:\n"; |
| 1460 } | 1752 DumpRenderSurfaces(&str, 1, active_tree_->root_layer()); |
| 1461 | 1753 } |
| 1462 void LayerTreeHostImpl::SetFullRootLayerDamage() | 1754 return str; |
| 1463 { | 1755 } |
| 1464 if (rootLayer()) { | 1756 |
| 1465 RenderSurfaceImpl* renderSurface = rootLayer()->render_surface(); | 1757 std::string LayerTreeHostImpl::LayerTreeAsJson() const { |
| 1466 if (renderSurface) | 1758 std::string str; |
| 1467 renderSurface->damage_tracker()->ForceFullDamageNextUpdate(); | 1759 if (active_tree_->root_layer()) { |
| 1468 } | 1760 scoped_ptr<base::Value> json(active_tree_->root_layer()->LayerTreeAsJson()); |
| 1469 } | 1761 base::JSONWriter::WriteWithOptions( |
| 1470 | 1762 json.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &str); |
| 1471 void LayerTreeHostImpl::animatePageScale(base::TimeTicks time) | 1763 } |
| 1472 { | 1764 return str; |
| 1473 if (!m_pageScaleAnimation || !rootScrollLayer()) | 1765 } |
| 1474 return; | 1766 |
| 1475 | 1767 void LayerTreeHostImpl::DumpRenderSurfaces(std::string* str, |
| 1476 double monotonicTime = (time - base::TimeTicks()).InSecondsF(); | 1768 int indent, |
| 1477 gfx::Vector2dF scrollTotal = rootScrollLayer()->scroll_offset() + rootScroll
Layer()->scroll_delta(); | 1769 const LayerImpl* layer) const { |
| 1478 | 1770 if (layer->render_surface()) |
| 1479 activeTree()->SetPageScaleDelta(m_pageScaleAnimation->PageScaleFactorAtTime(
monotonicTime) / activeTree()->page_scale_factor()); | 1771 layer->render_surface()->DumpSurface(str, indent); |
| 1480 gfx::Vector2dF nextScroll = m_pageScaleAnimation->ScrollOffsetAtTime(monoton
icTime); | 1772 |
| 1481 | 1773 for (size_t i = 0; i < layer->children().size(); ++i) |
| 1482 rootScrollLayer()->ScrollBy(nextScroll - scrollTotal); | 1774 DumpRenderSurfaces(str, indent, layer->children()[i]); |
| 1483 m_client->setNeedsRedrawOnImplThread(); | 1775 } |
| 1484 | 1776 |
| 1485 if (m_pageScaleAnimation->IsAnimationCompleteAtTime(monotonicTime)) { | 1777 int LayerTreeHostImpl::SourceAnimationFrameNumber() const { |
| 1486 m_pageScaleAnimation.reset(); | 1778 return fps_counter_->currentFrameNumber(); |
| 1487 m_client->setNeedsCommitOnImplThread(); | 1779 } |
| 1488 m_client->renewTreePriority(); | 1780 |
| 1489 } | 1781 void LayerTreeHostImpl::CollectRenderingStats(RenderingStats* stats) const { |
| 1490 } | 1782 stats->numFramesSentToScreen = fps_counter_->currentFrameNumber(); |
| 1491 | 1783 stats->droppedFrameCount = fps_counter_->droppedFrameCount(); |
| 1492 void LayerTreeHostImpl::animateLayers(base::TimeTicks monotonicTime, base::Time
wallClockTime) | 1784 stats->numImplThreadScrolls = num_impl_thread_scrolls_; |
| 1493 { | 1785 stats->numMainThreadScrolls = num_main_thread_scrolls_; |
| 1494 if (!m_settings.acceleratedAnimationEnabled || m_animationRegistrar->active_
animation_controllers().empty() || !rootLayer()) | 1786 stats->numLayersDrawn = cumulative_num_layers_drawn_; |
| 1495 return; | 1787 stats->numMissingTiles = cumulative_num_missing_tiles_; |
| 1496 | 1788 |
| 1497 TRACE_EVENT0("cc", "LayerTreeHostImpl::animateLayers"); | 1789 if (tile_manager_) |
| 1498 | 1790 tile_manager_->GetRenderingStats(stats); |
| 1499 m_lastAnimationTime = wallClockTime; | 1791 } |
| 1500 double monotonicSeconds = (monotonicTime - base::TimeTicks()).InSecondsF(); | 1792 |
| 1501 | 1793 void LayerTreeHostImpl::SendManagedMemoryStats( |
| 1502 AnimationRegistrar::AnimationControllerMap copy = m_animationRegistrar->acti
ve_animation_controllers(); | 1794 size_t memory_visible_bytes, |
| 1503 for (AnimationRegistrar::AnimationControllerMap::iterator iter = copy.begin(
); iter != copy.end(); ++iter) | 1795 size_t memory_visible_and_nearby_bytes, |
| 1504 (*iter).second->Animate(monotonicSeconds); | 1796 size_t memory_use_bytes) { |
| 1505 | 1797 if (!renderer_) |
| 1506 m_client->setNeedsRedrawOnImplThread(); | 1798 return; |
| 1507 setBackgroundTickingEnabled(!m_visible && !m_animationRegistrar->active_anim
ation_controllers().empty()); | 1799 |
| 1508 } | 1800 // Round the numbers being sent up to the next 8MB, to throttle the rate |
| 1509 | 1801 // at which we spam the GPU process. |
| 1510 void LayerTreeHostImpl::updateAnimationState() | 1802 static const size_t rounding_step = 8 * 1024 * 1024; |
| 1511 { | 1803 memory_visible_bytes = RoundUp(memory_visible_bytes, rounding_step); |
| 1512 if (!m_settings.acceleratedAnimationEnabled || m_animationRegistrar->active_
animation_controllers().empty() || !rootLayer()) | 1804 memory_visible_and_nearby_bytes = RoundUp(memory_visible_and_nearby_bytes, |
| 1513 return; | 1805 rounding_step); |
| 1514 | 1806 memory_use_bytes = RoundUp(memory_use_bytes, rounding_step); |
| 1515 TRACE_EVENT0("cc", "LayerTreeHostImpl::updateAnimationState"); | 1807 if (last_sent_memory_visible_bytes_ == memory_visible_bytes && |
| 1516 scoped_ptr<AnimationEventsVector> events(make_scoped_ptr(new AnimationEvents
Vector)); | 1808 last_sent_memory_visible_and_nearby_bytes_ == |
| 1517 AnimationRegistrar::AnimationControllerMap copy = m_animationRegistrar->acti
ve_animation_controllers(); | 1809 memory_visible_and_nearby_bytes && |
| 1518 for (AnimationRegistrar::AnimationControllerMap::iterator iter = copy.begin(
); iter != copy.end(); ++iter) | 1810 last_sent_memory_use_bytes_ == memory_use_bytes) { |
| 1519 (*iter).second->UpdateState(events.get()); | 1811 return; |
| 1520 | 1812 } |
| 1521 if (!events->empty()) | 1813 last_sent_memory_visible_bytes_ = memory_visible_bytes; |
| 1522 m_client->postAnimationEventsToMainThreadOnImplThread(events.Pass(), m_l
astAnimationTime); | 1814 last_sent_memory_visible_and_nearby_bytes_ = memory_visible_and_nearby_bytes; |
| 1523 } | 1815 last_sent_memory_use_bytes_ = memory_use_bytes; |
| 1524 | 1816 |
| 1525 base::TimeDelta LayerTreeHostImpl::lowFrequencyAnimationInterval() const | 1817 renderer_->SendManagedMemoryStats(last_sent_memory_visible_bytes_, |
| 1526 { | 1818 last_sent_memory_visible_and_nearby_bytes_, |
| 1527 return base::TimeDelta::FromSeconds(1); | 1819 last_sent_memory_use_bytes_); |
| 1528 } | 1820 } |
| 1529 | 1821 |
| 1530 void LayerTreeHostImpl::sendDidLoseOutputSurfaceRecursive(LayerImpl* current) | 1822 void LayerTreeHostImpl::AnimateScrollbars(base::TimeTicks time) { |
| 1531 { | 1823 AnimateScrollbarsRecursive(active_tree_->root_layer(), time); |
| 1532 DCHECK(current); | 1824 } |
| 1533 current->DidLoseOutputSurface(); | 1825 |
| 1534 if (current->mask_layer()) | 1826 void LayerTreeHostImpl::AnimateScrollbarsRecursive(LayerImpl* layer, |
| 1535 sendDidLoseOutputSurfaceRecursive(current->mask_layer()); | 1827 base::TimeTicks time) { |
| 1536 if (current->replica_layer()) | 1828 if (!layer) |
| 1537 sendDidLoseOutputSurfaceRecursive(current->replica_layer()); | 1829 return; |
| 1538 for (size_t i = 0; i < current->children().size(); ++i) | 1830 |
| 1539 sendDidLoseOutputSurfaceRecursive(current->children()[i]); | 1831 ScrollbarAnimationController* scrollbar_controller = |
| 1540 } | 1832 layer->scrollbar_animation_controller(); |
| 1541 | 1833 if (scrollbar_controller && scrollbar_controller->animate(time)) |
| 1542 void LayerTreeHostImpl::clearRenderSurfaces() | 1834 client_->SetNeedsRedrawOnImplThread(); |
| 1543 { | 1835 |
| 1544 activeTree()->ClearRenderSurfaces(); | 1836 for (size_t i = 0; i < layer->children().size(); ++i) |
| 1545 if (pendingTree()) | 1837 AnimateScrollbarsRecursive(layer->children()[i], time); |
| 1546 pendingTree()->ClearRenderSurfaces(); | 1838 } |
| 1547 } | 1839 |
| 1548 | 1840 void LayerTreeHostImpl::SetTreePriority(TreePriority priority) { |
| 1549 std::string LayerTreeHostImpl::layerTreeAsText() const | 1841 if (!tile_manager_) |
| 1550 { | 1842 return; |
| 1551 std::string str; | 1843 |
| 1552 if (rootLayer()) { | 1844 GlobalStateThatImpactsTilePriority new_state(tile_manager_->GlobalState()); |
| 1553 str = rootLayer()->LayerTreeAsText(); | 1845 if (new_state.tree_priority == priority) |
| 1554 str += "RenderSurfaces:\n"; | 1846 return; |
| 1555 dumpRenderSurfaces(&str, 1, rootLayer()); | 1847 |
| 1556 } | 1848 new_state.tree_priority = priority; |
| 1557 return str; | 1849 tile_manager_->SetGlobalState(new_state); |
| 1558 } | 1850 } |
| 1559 | 1851 |
| 1560 std::string LayerTreeHostImpl::layerTreeAsJson() const | 1852 void LayerTreeHostImpl::BeginNextFrame() { |
| 1561 { | 1853 current_frame_time_ = base::TimeTicks(); |
| 1562 std::string str; | 1854 } |
| 1563 if (rootLayer()) { | 1855 |
| 1564 scoped_ptr<base::Value> json(rootLayer()->LayerTreeAsJson()); | 1856 base::TimeTicks LayerTreeHostImpl::CurrentFrameTime() { |
| 1565 base::JSONWriter::WriteWithOptions( | 1857 if (current_frame_time_.is_null()) |
| 1566 json.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &str); | 1858 current_frame_time_ = base::TimeTicks::Now(); |
| 1567 } | 1859 return current_frame_time_; |
| 1568 return str; | 1860 } |
| 1569 } | 1861 |
| 1570 | 1862 scoped_ptr<base::Value> LayerTreeHostImpl::AsValue() const { |
| 1571 void LayerTreeHostImpl::dumpRenderSurfaces(std::string* str, int indent, const L
ayerImpl* layer) const | 1863 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); |
| 1572 { | 1864 state->Set("activation_state", ActivationStateAsValue().release()); |
| 1573 if (layer->render_surface()) | 1865 state->Set("frame_state", FrameStateAsValue().release()); |
| 1574 layer->render_surface()->DumpSurface(str, indent); | 1866 return state.PassAs<base::Value>(); |
| 1575 | 1867 } |
| 1576 for (size_t i = 0; i < layer->children().size(); ++i) | 1868 |
| 1577 dumpRenderSurfaces(str, indent, layer->children()[i]); | 1869 scoped_ptr<base::Value> LayerTreeHostImpl::ActivationStateAsValue() const { |
| 1578 } | 1870 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); |
| 1579 | 1871 state->SetString("lthi_id", StringPrintf("%p", this)); |
| 1580 int LayerTreeHostImpl::sourceAnimationFrameNumber() const | 1872 state->SetBoolean("visible_resources_ready", |
| 1581 { | 1873 pending_tree_->AreVisibleResourcesReady()); |
| 1582 return fpsCounter()->currentFrameNumber(); | 1874 state->Set("tile_manager", tile_manager_->BasicStateAsValue().release()); |
| 1583 } | 1875 return state.PassAs<base::Value>(); |
| 1584 | 1876 } |
| 1585 void LayerTreeHostImpl::renderingStats(RenderingStats* stats) const | 1877 |
| 1586 { | 1878 scoped_ptr<base::Value> LayerTreeHostImpl::FrameStateAsValue() const { |
| 1587 stats->numFramesSentToScreen = fpsCounter()->currentFrameNumber(); | 1879 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); |
| 1588 stats->droppedFrameCount = fpsCounter()->droppedFrameCount(); | 1880 state->SetString("lthi_id", StringPrintf("%p", this)); |
| 1589 stats->numImplThreadScrolls = m_numImplThreadScrolls; | 1881 state->Set("device_viewport_size", |
| 1590 stats->numMainThreadScrolls = m_numMainThreadScrolls; | 1882 MathUtil::asValue(device_viewport_size_).release()); |
| 1591 stats->numLayersDrawn = m_cumulativeNumLayersDrawn; | 1883 if (tile_manager_) |
| 1592 stats->numMissingTiles = m_cumulativeNumMissingTiles; | 1884 state->Set("tiles", tile_manager_->AllTilesAsValue().release()); |
| 1593 | 1885 state->Set("active_tree", active_tree_->AsValue().release()); |
| 1594 if (m_tileManager) | 1886 return state.PassAs<base::Value>(); |
| 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 } | 1887 } |
| 1696 | 1888 |
| 1697 // static | 1889 // static |
| 1698 LayerImpl* LayerTreeHostImpl::getNonCompositedContentLayerRecursive(LayerImpl* l
ayer) | 1890 LayerImpl* LayerTreeHostImpl::GetNonCompositedContentLayerRecursive( |
| 1699 { | 1891 LayerImpl* layer) { |
| 1700 if (!layer) | 1892 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; | 1893 return NULL; |
| 1714 } | 1894 |
| 1715 | 1895 if (layer->DrawsContent()) |
| 1716 skia::RefPtr<SkPicture> LayerTreeHostImpl::capturePicture() | 1896 return layer; |
| 1717 { | 1897 |
| 1718 LayerTreeImpl* tree = pendingTree() ? pendingTree() : activeTree(); | 1898 for (LayerImpl::LayerList::const_iterator it = layer->children().begin(); |
| 1719 LayerImpl* layer = getNonCompositedContentLayerRecursive(tree->RootLayer()); | 1899 it != layer->children().end(); ++it) { |
| 1720 return layer ? layer->GetPicture() : skia::RefPtr<SkPicture>(); | 1900 LayerImpl* nccr = GetNonCompositedContentLayerRecursive(*it); |
| 1721 } | 1901 if (nccr) |
| 1722 | 1902 return nccr; |
| 1723 void LayerTreeHostImpl::setDebugState(const LayerTreeDebugState& debugState) | 1903 } |
| 1724 { | 1904 |
| 1725 if (m_debugState.continuousPainting != debugState.continuousPainting) | 1905 return NULL; |
| 1726 m_paintTimeCounter->ClearHistory(); | 1906 } |
| 1727 | 1907 |
| 1728 m_debugState = debugState; | 1908 skia::RefPtr<SkPicture> LayerTreeHostImpl::CapturePicture() { |
| 1729 | 1909 LayerTreeImpl* tree = |
| 1730 if (m_tileManager) | 1910 pending_tree_ ? pending_tree_.get() : active_tree_.get(); |
| 1731 m_tileManager->SetRecordRenderingStats(m_debugState.recordRenderingStats
()); | 1911 LayerImpl* layer = GetNonCompositedContentLayerRecursive(tree->root_layer()); |
| 1732 } | 1912 return layer ? layer->GetPicture() : skia::RefPtr<SkPicture>(); |
| 1733 | 1913 } |
| 1734 void LayerTreeHostImpl::savePaintTime(const base::TimeDelta& totalPaintTime, int
commitNumber) | 1914 |
| 1735 { | 1915 void LayerTreeHostImpl::SetDebugState(const LayerTreeDebugState& debug_state) { |
| 1736 DCHECK(m_debugState.continuousPainting); | 1916 if (debug_state_.continuousPainting != debug_state.continuousPainting) |
| 1737 m_paintTimeCounter->SavePaintTime(totalPaintTime, commitNumber); | 1917 paint_time_counter_->ClearHistory(); |
| 1918 |
| 1919 debug_state_ = debug_state; |
| 1920 |
| 1921 if (tile_manager_) |
| 1922 tile_manager_->SetRecordRenderingStats(debug_state_.recordRenderingStats()); |
| 1923 } |
| 1924 |
| 1925 void LayerTreeHostImpl::SavePaintTime(const base::TimeDelta& total_paint_time, |
| 1926 int commit_number) { |
| 1927 DCHECK(debug_state_.continuousPainting); |
| 1928 paint_time_counter_->SavePaintTime(total_paint_time, commit_number); |
| 1738 } | 1929 } |
| 1739 | 1930 |
| 1740 } // namespace cc | 1931 } // namespace cc |
| OLD | NEW |