| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "cc/trees/layer_tree_impl.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 #include <limits> | |
| 9 #include <set> | |
| 10 | |
| 11 #include "base/trace_event/trace_event.h" | |
| 12 #include "base/trace_event/trace_event_argument.h" | |
| 13 #include "cc/animation/keyframed_animation_curve.h" | |
| 14 #include "cc/animation/scrollbar_animation_controller.h" | |
| 15 #include "cc/animation/scrollbar_animation_controller_linear_fade.h" | |
| 16 #include "cc/animation/scrollbar_animation_controller_thinning.h" | |
| 17 #include "cc/base/math_util.h" | |
| 18 #include "cc/base/synced_property.h" | |
| 19 #include "cc/base/util.h" | |
| 20 #include "cc/debug/devtools_instrumentation.h" | |
| 21 #include "cc/debug/traced_value.h" | |
| 22 #include "cc/input/page_scale_animation.h" | |
| 23 #include "cc/layers/heads_up_display_layer_impl.h" | |
| 24 #include "cc/layers/layer.h" | |
| 25 #include "cc/layers/layer_iterator.h" | |
| 26 #include "cc/layers/render_surface_impl.h" | |
| 27 #include "cc/layers/scrollbar_layer_impl_base.h" | |
| 28 #include "cc/resources/ui_resource_request.h" | |
| 29 #include "cc/trees/layer_tree_host_common.h" | |
| 30 #include "cc/trees/layer_tree_host_impl.h" | |
| 31 #include "cc/trees/occlusion_tracker.h" | |
| 32 #include "ui/gfx/geometry/point_conversions.h" | |
| 33 #include "ui/gfx/geometry/size_conversions.h" | |
| 34 #include "ui/gfx/geometry/vector2d_conversions.h" | |
| 35 | |
| 36 namespace cc { | |
| 37 | |
| 38 // This class exists to split the LayerScrollOffsetDelegate between the | |
| 39 // InnerViewportScrollLayer and the OuterViewportScrollLayer in a manner | |
| 40 // that never requires the embedder or LayerImpl to know about. | |
| 41 class LayerScrollOffsetDelegateProxy : public LayerImpl::ScrollOffsetDelegate { | |
| 42 public: | |
| 43 LayerScrollOffsetDelegateProxy(LayerImpl* layer, | |
| 44 LayerScrollOffsetDelegate* delegate, | |
| 45 LayerTreeImpl* layer_tree) | |
| 46 : layer_(layer), delegate_(delegate), layer_tree_impl_(layer_tree) {} | |
| 47 virtual ~LayerScrollOffsetDelegateProxy() {} | |
| 48 | |
| 49 gfx::ScrollOffset last_set_scroll_offset() const { | |
| 50 return last_set_scroll_offset_; | |
| 51 } | |
| 52 | |
| 53 // LayerScrollOffsetDelegate implementation. | |
| 54 void SetCurrentScrollOffset(const gfx::ScrollOffset& new_offset) override { | |
| 55 last_set_scroll_offset_ = new_offset; | |
| 56 } | |
| 57 | |
| 58 gfx::ScrollOffset GetCurrentScrollOffset() override { | |
| 59 return layer_tree_impl_->GetDelegatedScrollOffset(layer_); | |
| 60 } | |
| 61 | |
| 62 bool IsExternalFlingActive() const override { | |
| 63 return delegate_->IsExternalFlingActive(); | |
| 64 } | |
| 65 | |
| 66 void Update() const override { | |
| 67 layer_tree_impl_->UpdateScrollOffsetDelegate(); | |
| 68 } | |
| 69 | |
| 70 private: | |
| 71 LayerImpl* layer_; | |
| 72 LayerScrollOffsetDelegate* delegate_; | |
| 73 LayerTreeImpl* layer_tree_impl_; | |
| 74 gfx::ScrollOffset last_set_scroll_offset_; | |
| 75 }; | |
| 76 | |
| 77 LayerTreeImpl::LayerTreeImpl( | |
| 78 LayerTreeHostImpl* layer_tree_host_impl, | |
| 79 scoped_refptr<SyncedProperty<ScaleGroup>> page_scale_factor, | |
| 80 scoped_refptr<SyncedTopControls> top_controls_shown_ratio, | |
| 81 scoped_refptr<SyncedElasticOverscroll> elastic_overscroll) | |
| 82 : layer_tree_host_impl_(layer_tree_host_impl), | |
| 83 source_frame_number_(-1), | |
| 84 hud_layer_(0), | |
| 85 currently_scrolling_layer_(NULL), | |
| 86 root_layer_scroll_offset_delegate_(NULL), | |
| 87 background_color_(0), | |
| 88 has_transparent_background_(false), | |
| 89 overscroll_elasticity_layer_(NULL), | |
| 90 page_scale_layer_(NULL), | |
| 91 inner_viewport_scroll_layer_(NULL), | |
| 92 outer_viewport_scroll_layer_(NULL), | |
| 93 page_scale_factor_(page_scale_factor), | |
| 94 min_page_scale_factor_(0), | |
| 95 max_page_scale_factor_(0), | |
| 96 elastic_overscroll_(elastic_overscroll), | |
| 97 scrolling_layer_id_from_previous_tree_(0), | |
| 98 contents_textures_purged_(false), | |
| 99 viewport_size_invalid_(false), | |
| 100 needs_update_draw_properties_(true), | |
| 101 needs_full_tree_sync_(true), | |
| 102 next_activation_forces_redraw_(false), | |
| 103 has_ever_been_drawn_(false), | |
| 104 render_surface_layer_list_id_(0), | |
| 105 top_controls_shrink_blink_size_(false), | |
| 106 top_controls_height_(0), | |
| 107 top_controls_shown_ratio_(top_controls_shown_ratio) { | |
| 108 } | |
| 109 | |
| 110 LayerTreeImpl::~LayerTreeImpl() { | |
| 111 BreakSwapPromises(SwapPromise::SWAP_FAILS); | |
| 112 | |
| 113 // Need to explicitly clear the tree prior to destroying this so that | |
| 114 // the LayerTreeImpl pointer is still valid in the LayerImpl dtor. | |
| 115 DCHECK(!root_layer_); | |
| 116 DCHECK(layers_with_copy_output_request_.empty()); | |
| 117 } | |
| 118 | |
| 119 void LayerTreeImpl::Shutdown() { | |
| 120 root_layer_ = nullptr; | |
| 121 } | |
| 122 | |
| 123 void LayerTreeImpl::ReleaseResources() { | |
| 124 if (root_layer_) { | |
| 125 LayerTreeHostCommon::CallFunctionForSubtree( | |
| 126 root_layer_.get(), [](LayerImpl* layer) { layer->ReleaseResources(); }); | |
| 127 } | |
| 128 } | |
| 129 | |
| 130 void LayerTreeImpl::RecreateResources() { | |
| 131 if (root_layer_) { | |
| 132 LayerTreeHostCommon::CallFunctionForSubtree( | |
| 133 root_layer_.get(), | |
| 134 [](LayerImpl* layer) { layer->RecreateResources(); }); | |
| 135 } | |
| 136 } | |
| 137 | |
| 138 void LayerTreeImpl::SetRootLayer(scoped_ptr<LayerImpl> layer) { | |
| 139 if (inner_viewport_scroll_layer_) | |
| 140 inner_viewport_scroll_layer_->SetScrollOffsetDelegate(NULL); | |
| 141 if (outer_viewport_scroll_layer_) | |
| 142 outer_viewport_scroll_layer_->SetScrollOffsetDelegate(NULL); | |
| 143 inner_viewport_scroll_delegate_proxy_ = nullptr; | |
| 144 outer_viewport_scroll_delegate_proxy_ = nullptr; | |
| 145 | |
| 146 root_layer_ = layer.Pass(); | |
| 147 currently_scrolling_layer_ = NULL; | |
| 148 inner_viewport_scroll_layer_ = NULL; | |
| 149 outer_viewport_scroll_layer_ = NULL; | |
| 150 page_scale_layer_ = NULL; | |
| 151 | |
| 152 layer_tree_host_impl_->OnCanDrawStateChangedForTree(); | |
| 153 } | |
| 154 | |
| 155 LayerImpl* LayerTreeImpl::InnerViewportScrollLayer() const { | |
| 156 return inner_viewport_scroll_layer_; | |
| 157 } | |
| 158 | |
| 159 LayerImpl* LayerTreeImpl::OuterViewportScrollLayer() const { | |
| 160 return outer_viewport_scroll_layer_; | |
| 161 } | |
| 162 | |
| 163 gfx::ScrollOffset LayerTreeImpl::TotalScrollOffset() const { | |
| 164 gfx::ScrollOffset offset; | |
| 165 | |
| 166 if (inner_viewport_scroll_layer_) | |
| 167 offset += inner_viewport_scroll_layer_->CurrentScrollOffset(); | |
| 168 | |
| 169 if (outer_viewport_scroll_layer_) | |
| 170 offset += outer_viewport_scroll_layer_->CurrentScrollOffset(); | |
| 171 | |
| 172 return offset; | |
| 173 } | |
| 174 | |
| 175 gfx::ScrollOffset LayerTreeImpl::TotalMaxScrollOffset() const { | |
| 176 gfx::ScrollOffset offset; | |
| 177 | |
| 178 if (inner_viewport_scroll_layer_) | |
| 179 offset += inner_viewport_scroll_layer_->MaxScrollOffset(); | |
| 180 | |
| 181 if (outer_viewport_scroll_layer_) | |
| 182 offset += outer_viewport_scroll_layer_->MaxScrollOffset(); | |
| 183 | |
| 184 return offset; | |
| 185 } | |
| 186 | |
| 187 scoped_ptr<LayerImpl> LayerTreeImpl::DetachLayerTree() { | |
| 188 // Clear all data structures that have direct references to the layer tree. | |
| 189 scrolling_layer_id_from_previous_tree_ = | |
| 190 currently_scrolling_layer_ ? currently_scrolling_layer_->id() : 0; | |
| 191 if (inner_viewport_scroll_layer_) | |
| 192 inner_viewport_scroll_layer_->SetScrollOffsetDelegate(NULL); | |
| 193 if (outer_viewport_scroll_layer_) | |
| 194 outer_viewport_scroll_layer_->SetScrollOffsetDelegate(NULL); | |
| 195 inner_viewport_scroll_delegate_proxy_ = nullptr; | |
| 196 outer_viewport_scroll_delegate_proxy_ = nullptr; | |
| 197 inner_viewport_scroll_layer_ = NULL; | |
| 198 outer_viewport_scroll_layer_ = NULL; | |
| 199 page_scale_layer_ = NULL; | |
| 200 currently_scrolling_layer_ = NULL; | |
| 201 | |
| 202 render_surface_layer_list_.clear(); | |
| 203 set_needs_update_draw_properties(); | |
| 204 return root_layer_.Pass(); | |
| 205 } | |
| 206 | |
| 207 void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) { | |
| 208 // The request queue should have been processed and does not require a push. | |
| 209 DCHECK_EQ(ui_resource_request_queue_.size(), 0u); | |
| 210 | |
| 211 if (next_activation_forces_redraw_) { | |
| 212 target_tree->ForceRedrawNextActivation(); | |
| 213 next_activation_forces_redraw_ = false; | |
| 214 } | |
| 215 | |
| 216 target_tree->PassSwapPromises(&swap_promise_list_); | |
| 217 | |
| 218 target_tree->set_top_controls_shrink_blink_size( | |
| 219 top_controls_shrink_blink_size_); | |
| 220 target_tree->set_top_controls_height(top_controls_height_); | |
| 221 target_tree->PushTopControls(nullptr); | |
| 222 | |
| 223 // Active tree already shares the page_scale_factor object with pending | |
| 224 // tree so only the limits need to be provided. | |
| 225 target_tree->PushPageScaleFactorAndLimits(nullptr, min_page_scale_factor(), | |
| 226 max_page_scale_factor()); | |
| 227 target_tree->elastic_overscroll()->PushPendingToActive(); | |
| 228 | |
| 229 target_tree->pending_page_scale_animation_ = | |
| 230 pending_page_scale_animation_.Pass(); | |
| 231 | |
| 232 if (page_scale_layer_ && inner_viewport_scroll_layer_) { | |
| 233 target_tree->SetViewportLayersFromIds( | |
| 234 overscroll_elasticity_layer_ ? overscroll_elasticity_layer_->id() | |
| 235 : Layer::INVALID_ID, | |
| 236 page_scale_layer_->id(), inner_viewport_scroll_layer_->id(), | |
| 237 outer_viewport_scroll_layer_ ? outer_viewport_scroll_layer_->id() | |
| 238 : Layer::INVALID_ID); | |
| 239 } else { | |
| 240 target_tree->ClearViewportLayers(); | |
| 241 } | |
| 242 | |
| 243 target_tree->RegisterSelection(selection_start_, selection_end_); | |
| 244 | |
| 245 // This should match the property synchronization in | |
| 246 // LayerTreeHost::finishCommitOnImplThread(). | |
| 247 target_tree->set_source_frame_number(source_frame_number()); | |
| 248 target_tree->set_background_color(background_color()); | |
| 249 target_tree->set_has_transparent_background(has_transparent_background()); | |
| 250 | |
| 251 if (ContentsTexturesPurged()) | |
| 252 target_tree->SetContentsTexturesPurged(); | |
| 253 else | |
| 254 target_tree->ResetContentsTexturesPurged(); | |
| 255 | |
| 256 if (ViewportSizeInvalid()) | |
| 257 target_tree->SetViewportSizeInvalid(); | |
| 258 else | |
| 259 target_tree->ResetViewportSizeInvalid(); | |
| 260 | |
| 261 if (hud_layer()) | |
| 262 target_tree->set_hud_layer(static_cast<HeadsUpDisplayLayerImpl*>( | |
| 263 LayerTreeHostCommon::FindLayerInSubtree( | |
| 264 target_tree->root_layer(), hud_layer()->id()))); | |
| 265 else | |
| 266 target_tree->set_hud_layer(NULL); | |
| 267 | |
| 268 target_tree->has_ever_been_drawn_ = false; | |
| 269 } | |
| 270 | |
| 271 LayerImpl* LayerTreeImpl::InnerViewportContainerLayer() const { | |
| 272 return inner_viewport_scroll_layer_ | |
| 273 ? inner_viewport_scroll_layer_->scroll_clip_layer() | |
| 274 : NULL; | |
| 275 } | |
| 276 | |
| 277 LayerImpl* LayerTreeImpl::OuterViewportContainerLayer() const { | |
| 278 return outer_viewport_scroll_layer_ | |
| 279 ? outer_viewport_scroll_layer_->scroll_clip_layer() | |
| 280 : NULL; | |
| 281 } | |
| 282 | |
| 283 LayerImpl* LayerTreeImpl::CurrentlyScrollingLayer() const { | |
| 284 DCHECK(IsActiveTree()); | |
| 285 return currently_scrolling_layer_; | |
| 286 } | |
| 287 | |
| 288 void LayerTreeImpl::SetCurrentlyScrollingLayer(LayerImpl* layer) { | |
| 289 if (currently_scrolling_layer_ == layer) | |
| 290 return; | |
| 291 | |
| 292 if (currently_scrolling_layer_ && | |
| 293 currently_scrolling_layer_->scrollbar_animation_controller()) | |
| 294 currently_scrolling_layer_->scrollbar_animation_controller() | |
| 295 ->DidScrollEnd(); | |
| 296 currently_scrolling_layer_ = layer; | |
| 297 if (layer && layer->scrollbar_animation_controller()) | |
| 298 layer->scrollbar_animation_controller()->DidScrollBegin(); | |
| 299 } | |
| 300 | |
| 301 void LayerTreeImpl::ClearCurrentlyScrollingLayer() { | |
| 302 SetCurrentlyScrollingLayer(NULL); | |
| 303 scrolling_layer_id_from_previous_tree_ = 0; | |
| 304 } | |
| 305 | |
| 306 namespace { | |
| 307 | |
| 308 void ForceScrollbarParameterUpdateAfterScaleChange(LayerImpl* current_layer) { | |
| 309 if (!current_layer) | |
| 310 return; | |
| 311 | |
| 312 while (current_layer) { | |
| 313 current_layer->ScrollbarParametersDidChange(false); | |
| 314 current_layer = current_layer->parent(); | |
| 315 } | |
| 316 } | |
| 317 | |
| 318 } // namespace | |
| 319 | |
| 320 float LayerTreeImpl::ClampPageScaleFactorToLimits( | |
| 321 float page_scale_factor) const { | |
| 322 if (min_page_scale_factor_ && page_scale_factor < min_page_scale_factor_) | |
| 323 page_scale_factor = min_page_scale_factor_; | |
| 324 else if (max_page_scale_factor_ && page_scale_factor > max_page_scale_factor_) | |
| 325 page_scale_factor = max_page_scale_factor_; | |
| 326 return page_scale_factor; | |
| 327 } | |
| 328 | |
| 329 void LayerTreeImpl::SetPageScaleOnActiveTree(float active_page_scale) { | |
| 330 DCHECK(IsActiveTree()); | |
| 331 if (page_scale_factor()->SetCurrent( | |
| 332 ClampPageScaleFactorToLimits(active_page_scale))) | |
| 333 DidUpdatePageScale(); | |
| 334 } | |
| 335 | |
| 336 void LayerTreeImpl::PushPageScaleFromMainThread(float page_scale_factor, | |
| 337 float min_page_scale_factor, | |
| 338 float max_page_scale_factor) { | |
| 339 PushPageScaleFactorAndLimits(&page_scale_factor, min_page_scale_factor, | |
| 340 max_page_scale_factor); | |
| 341 } | |
| 342 | |
| 343 void LayerTreeImpl::PushPageScaleFactorAndLimits(const float* page_scale_factor, | |
| 344 float min_page_scale_factor, | |
| 345 float max_page_scale_factor) { | |
| 346 DCHECK(page_scale_factor || IsActiveTree()); | |
| 347 bool changed_page_scale = false; | |
| 348 if (page_scale_factor) { | |
| 349 DCHECK(!IsActiveTree() || !layer_tree_host_impl_->pending_tree()); | |
| 350 changed_page_scale |= | |
| 351 page_scale_factor_->PushFromMainThread(*page_scale_factor); | |
| 352 } | |
| 353 if (IsActiveTree()) | |
| 354 changed_page_scale |= page_scale_factor_->PushPendingToActive(); | |
| 355 changed_page_scale |= | |
| 356 SetPageScaleFactorLimits(min_page_scale_factor, max_page_scale_factor); | |
| 357 | |
| 358 if (changed_page_scale) | |
| 359 DidUpdatePageScale(); | |
| 360 } | |
| 361 | |
| 362 void LayerTreeImpl::set_top_controls_shrink_blink_size(bool shrink) { | |
| 363 if (top_controls_shrink_blink_size_ == shrink) | |
| 364 return; | |
| 365 | |
| 366 top_controls_shrink_blink_size_ = shrink; | |
| 367 if (IsActiveTree()) | |
| 368 layer_tree_host_impl_->UpdateViewportContainerSizes(); | |
| 369 } | |
| 370 | |
| 371 void LayerTreeImpl::set_top_controls_height(float top_controls_height) { | |
| 372 if (top_controls_height_ == top_controls_height) | |
| 373 return; | |
| 374 | |
| 375 top_controls_height_ = top_controls_height; | |
| 376 if (IsActiveTree()) | |
| 377 layer_tree_host_impl_->UpdateViewportContainerSizes(); | |
| 378 } | |
| 379 | |
| 380 bool LayerTreeImpl::SetCurrentTopControlsShownRatio(float ratio) { | |
| 381 ratio = std::max(ratio, 0.f); | |
| 382 ratio = std::min(ratio, 1.f); | |
| 383 return top_controls_shown_ratio_->SetCurrent(ratio); | |
| 384 } | |
| 385 | |
| 386 void LayerTreeImpl::PushTopControlsFromMainThread( | |
| 387 float top_controls_shown_ratio) { | |
| 388 PushTopControls(&top_controls_shown_ratio); | |
| 389 } | |
| 390 | |
| 391 void LayerTreeImpl::PushTopControls(const float* top_controls_shown_ratio) { | |
| 392 DCHECK(top_controls_shown_ratio || IsActiveTree()); | |
| 393 | |
| 394 if (top_controls_shown_ratio) { | |
| 395 DCHECK(!IsActiveTree() || !layer_tree_host_impl_->pending_tree()); | |
| 396 top_controls_shown_ratio_->PushFromMainThread(*top_controls_shown_ratio); | |
| 397 } | |
| 398 if (IsActiveTree()) { | |
| 399 if (top_controls_shown_ratio_->PushPendingToActive()) | |
| 400 layer_tree_host_impl_->DidChangeTopControlsPosition(); | |
| 401 } | |
| 402 } | |
| 403 | |
| 404 bool LayerTreeImpl::SetPageScaleFactorLimits(float min_page_scale_factor, | |
| 405 float max_page_scale_factor) { | |
| 406 if (min_page_scale_factor == min_page_scale_factor_ && | |
| 407 max_page_scale_factor == max_page_scale_factor_) | |
| 408 return false; | |
| 409 | |
| 410 min_page_scale_factor_ = min_page_scale_factor; | |
| 411 max_page_scale_factor_ = max_page_scale_factor; | |
| 412 | |
| 413 return true; | |
| 414 } | |
| 415 | |
| 416 void LayerTreeImpl::DidUpdatePageScale() { | |
| 417 if (IsActiveTree()) | |
| 418 page_scale_factor()->SetCurrent( | |
| 419 ClampPageScaleFactorToLimits(current_page_scale_factor())); | |
| 420 | |
| 421 set_needs_update_draw_properties(); | |
| 422 | |
| 423 if (root_layer_scroll_offset_delegate_) { | |
| 424 root_layer_scroll_offset_delegate_->UpdateRootLayerState( | |
| 425 TotalScrollOffset(), TotalMaxScrollOffset(), ScrollableSize(), | |
| 426 current_page_scale_factor(), min_page_scale_factor_, | |
| 427 max_page_scale_factor_); | |
| 428 } | |
| 429 | |
| 430 ForceScrollbarParameterUpdateAfterScaleChange(page_scale_layer()); | |
| 431 | |
| 432 HideInnerViewportScrollbarsIfNearMinimumScale(); | |
| 433 } | |
| 434 | |
| 435 void LayerTreeImpl::HideInnerViewportScrollbarsIfNearMinimumScale() { | |
| 436 if (!InnerViewportContainerLayer()) | |
| 437 return; | |
| 438 | |
| 439 LayerImpl::ScrollbarSet* scrollbars = | |
| 440 InnerViewportContainerLayer()->scrollbars(); | |
| 441 | |
| 442 if (!scrollbars) | |
| 443 return; | |
| 444 | |
| 445 for (LayerImpl::ScrollbarSet::iterator it = scrollbars->begin(); | |
| 446 it != scrollbars->end(); | |
| 447 ++it) { | |
| 448 ScrollbarLayerImplBase* scrollbar = *it; | |
| 449 float minimum_scale_to_show_at = | |
| 450 min_page_scale_factor() * settings().scrollbar_show_scale_threshold; | |
| 451 scrollbar->SetHideLayerAndSubtree( | |
| 452 current_page_scale_factor() < minimum_scale_to_show_at); | |
| 453 } | |
| 454 } | |
| 455 | |
| 456 SyncedProperty<ScaleGroup>* LayerTreeImpl::page_scale_factor() { | |
| 457 return page_scale_factor_.get(); | |
| 458 } | |
| 459 | |
| 460 const SyncedProperty<ScaleGroup>* LayerTreeImpl::page_scale_factor() const { | |
| 461 return page_scale_factor_.get(); | |
| 462 } | |
| 463 | |
| 464 gfx::SizeF LayerTreeImpl::ScrollableViewportSize() const { | |
| 465 if (!InnerViewportContainerLayer()) | |
| 466 return gfx::SizeF(); | |
| 467 | |
| 468 return gfx::ScaleSize(InnerViewportContainerLayer()->BoundsForScrolling(), | |
| 469 1.0f / current_page_scale_factor()); | |
| 470 } | |
| 471 | |
| 472 gfx::Rect LayerTreeImpl::RootScrollLayerDeviceViewportBounds() const { | |
| 473 LayerImpl* root_scroll_layer = OuterViewportScrollLayer() | |
| 474 ? OuterViewportScrollLayer() | |
| 475 : InnerViewportScrollLayer(); | |
| 476 if (!root_scroll_layer || root_scroll_layer->children().empty()) | |
| 477 return gfx::Rect(); | |
| 478 LayerImpl* layer = root_scroll_layer->children()[0]; | |
| 479 return MathUtil::MapEnclosingClippedRect(layer->screen_space_transform(), | |
| 480 gfx::Rect(layer->content_bounds())); | |
| 481 } | |
| 482 | |
| 483 void LayerTreeImpl::ApplySentScrollAndScaleDeltasFromAbortedCommit() { | |
| 484 DCHECK(IsActiveTree()); | |
| 485 | |
| 486 page_scale_factor()->AbortCommit(); | |
| 487 top_controls_shown_ratio()->AbortCommit(); | |
| 488 elastic_overscroll()->AbortCommit(); | |
| 489 | |
| 490 if (!root_layer()) | |
| 491 return; | |
| 492 | |
| 493 LayerTreeHostCommon::CallFunctionForSubtree( | |
| 494 root_layer(), [](LayerImpl* layer) { | |
| 495 layer->ApplySentScrollDeltasFromAbortedCommit(); | |
| 496 }); | |
| 497 } | |
| 498 | |
| 499 void LayerTreeImpl::SetViewportLayersFromIds( | |
| 500 int overscroll_elasticity_layer_id, | |
| 501 int page_scale_layer_id, | |
| 502 int inner_viewport_scroll_layer_id, | |
| 503 int outer_viewport_scroll_layer_id) { | |
| 504 overscroll_elasticity_layer_ = LayerById(overscroll_elasticity_layer_id); | |
| 505 page_scale_layer_ = LayerById(page_scale_layer_id); | |
| 506 DCHECK(page_scale_layer_); | |
| 507 | |
| 508 inner_viewport_scroll_layer_ = | |
| 509 LayerById(inner_viewport_scroll_layer_id); | |
| 510 DCHECK(inner_viewport_scroll_layer_); | |
| 511 | |
| 512 outer_viewport_scroll_layer_ = | |
| 513 LayerById(outer_viewport_scroll_layer_id); | |
| 514 DCHECK(outer_viewport_scroll_layer_ || | |
| 515 outer_viewport_scroll_layer_id == Layer::INVALID_ID); | |
| 516 | |
| 517 HideInnerViewportScrollbarsIfNearMinimumScale(); | |
| 518 | |
| 519 if (!root_layer_scroll_offset_delegate_) | |
| 520 return; | |
| 521 | |
| 522 inner_viewport_scroll_delegate_proxy_ = make_scoped_ptr( | |
| 523 new LayerScrollOffsetDelegateProxy(inner_viewport_scroll_layer_, | |
| 524 root_layer_scroll_offset_delegate_, | |
| 525 this)); | |
| 526 | |
| 527 if (outer_viewport_scroll_layer_) | |
| 528 outer_viewport_scroll_delegate_proxy_ = make_scoped_ptr( | |
| 529 new LayerScrollOffsetDelegateProxy(outer_viewport_scroll_layer_, | |
| 530 root_layer_scroll_offset_delegate_, | |
| 531 this)); | |
| 532 } | |
| 533 | |
| 534 void LayerTreeImpl::ClearViewportLayers() { | |
| 535 page_scale_layer_ = NULL; | |
| 536 inner_viewport_scroll_layer_ = NULL; | |
| 537 outer_viewport_scroll_layer_ = NULL; | |
| 538 } | |
| 539 | |
| 540 bool LayerTreeImpl::UpdateDrawProperties(bool update_lcd_text) { | |
| 541 if (!needs_update_draw_properties_) | |
| 542 return true; | |
| 543 | |
| 544 // Calling UpdateDrawProperties must clear this flag, so there can be no | |
| 545 // early outs before this. | |
| 546 needs_update_draw_properties_ = false; | |
| 547 | |
| 548 // For max_texture_size. When the renderer is re-created in | |
| 549 // CreateAndSetRenderer, the needs update draw properties flag is set | |
| 550 // again. | |
| 551 if (!layer_tree_host_impl_->renderer()) | |
| 552 return false; | |
| 553 | |
| 554 // Clear this after the renderer early out, as it should still be | |
| 555 // possible to hit test even without a renderer. | |
| 556 render_surface_layer_list_.clear(); | |
| 557 | |
| 558 if (!root_layer()) | |
| 559 return false; | |
| 560 | |
| 561 { | |
| 562 TRACE_EVENT2( | |
| 563 "cc", "LayerTreeImpl::UpdateDrawProperties::CalculateDrawProperties", | |
| 564 "IsActive", IsActiveTree(), "SourceFrameNumber", source_frame_number_); | |
| 565 LayerImpl* page_scale_layer = | |
| 566 page_scale_layer_ ? page_scale_layer_ : InnerViewportContainerLayer(); | |
| 567 bool can_render_to_separate_surface = | |
| 568 (layer_tree_host_impl_->GetDrawMode() != | |
| 569 DRAW_MODE_RESOURCELESS_SOFTWARE); | |
| 570 | |
| 571 ++render_surface_layer_list_id_; | |
| 572 LayerTreeHostCommon::CalcDrawPropsImplInputs inputs( | |
| 573 root_layer(), DrawViewportSize(), | |
| 574 layer_tree_host_impl_->DrawTransform(), device_scale_factor(), | |
| 575 current_page_scale_factor(), page_scale_layer, | |
| 576 elastic_overscroll()->Current(IsActiveTree()), | |
| 577 overscroll_elasticity_layer_, resource_provider()->max_texture_size(), | |
| 578 settings().can_use_lcd_text, settings().layers_always_allowed_lcd_text, | |
| 579 can_render_to_separate_surface, | |
| 580 settings().layer_transforms_should_scale_layer_contents, | |
| 581 settings().verify_property_trees, | |
| 582 &render_surface_layer_list_, render_surface_layer_list_id_); | |
| 583 LayerTreeHostCommon::CalculateDrawProperties(&inputs); | |
| 584 } | |
| 585 | |
| 586 { | |
| 587 TRACE_EVENT2("cc", "LayerTreeImpl::UpdateDrawProperties::Occlusion", | |
| 588 "IsActive", IsActiveTree(), "SourceFrameNumber", | |
| 589 source_frame_number_); | |
| 590 OcclusionTracker<LayerImpl> occlusion_tracker( | |
| 591 root_layer()->render_surface()->content_rect()); | |
| 592 occlusion_tracker.set_minimum_tracking_size( | |
| 593 settings().minimum_occlusion_tracking_size); | |
| 594 | |
| 595 // LayerIterator is used here instead of CallFunctionForSubtree to only | |
| 596 // UpdateTilePriorities on layers that will be visible (and thus have valid | |
| 597 // draw properties) and not because any ordering is required. | |
| 598 auto end = LayerIterator<LayerImpl>::End(&render_surface_layer_list_); | |
| 599 for (auto it = LayerIterator<LayerImpl>::Begin(&render_surface_layer_list_); | |
| 600 it != end; ++it) { | |
| 601 occlusion_tracker.EnterLayer(it); | |
| 602 | |
| 603 // There are very few render targets so this should be cheap to do for | |
| 604 // each layer instead of something more complicated. | |
| 605 bool inside_replica = false; | |
| 606 LayerImpl* layer = it->render_target(); | |
| 607 while (layer && !inside_replica) { | |
| 608 if (layer->render_target()->has_replica()) | |
| 609 inside_replica = true; | |
| 610 layer = layer->render_target()->parent(); | |
| 611 } | |
| 612 | |
| 613 // Don't use occlusion if a layer will appear in a replica, since the | |
| 614 // tile raster code does not know how to look for the replica and would | |
| 615 // consider it occluded even though the replica is visible. | |
| 616 // Since occlusion is only used for browser compositor (i.e. | |
| 617 // use_occlusion_for_tile_prioritization) and it won't use replicas, | |
| 618 // this should matter not. | |
| 619 | |
| 620 if (it.represents_itself()) { | |
| 621 Occlusion occlusion = | |
| 622 inside_replica ? Occlusion() | |
| 623 : occlusion_tracker.GetCurrentOcclusionForLayer( | |
| 624 it->draw_transform()); | |
| 625 it->draw_properties().occlusion_in_content_space = occlusion; | |
| 626 } | |
| 627 | |
| 628 if (it.represents_contributing_render_surface()) { | |
| 629 // Surfaces aren't used by the tile raster code, so they can have | |
| 630 // occlusion regardless of replicas. | |
| 631 Occlusion occlusion = | |
| 632 occlusion_tracker.GetCurrentOcclusionForContributingSurface( | |
| 633 it->render_surface()->draw_transform()); | |
| 634 it->render_surface()->set_occlusion_in_content_space(occlusion); | |
| 635 // Masks are used to draw the contributing surface, so should have | |
| 636 // the same occlusion as the surface (nothing inside the surface | |
| 637 // occludes them). | |
| 638 if (LayerImpl* mask = it->mask_layer()) { | |
| 639 Occlusion mask_occlusion = | |
| 640 inside_replica | |
| 641 ? Occlusion() | |
| 642 : occlusion_tracker.GetCurrentOcclusionForContributingSurface( | |
| 643 it->render_surface()->draw_transform() * | |
| 644 it->draw_transform()); | |
| 645 mask->draw_properties().occlusion_in_content_space = mask_occlusion; | |
| 646 } | |
| 647 if (LayerImpl* replica = it->replica_layer()) { | |
| 648 if (LayerImpl* mask = replica->mask_layer()) | |
| 649 mask->draw_properties().occlusion_in_content_space = Occlusion(); | |
| 650 } | |
| 651 } | |
| 652 | |
| 653 occlusion_tracker.LeaveLayer(it); | |
| 654 } | |
| 655 | |
| 656 unoccluded_screen_space_region_ = | |
| 657 occlusion_tracker.ComputeVisibleRegionInScreen(); | |
| 658 } | |
| 659 | |
| 660 // It'd be ideal if this could be done earlier, but when the raster source | |
| 661 // is updated from the main thread during push properties, update draw | |
| 662 // properties has not occurred yet and so it's not clear whether or not the | |
| 663 // layer can or cannot use lcd text. So, this is the cleanup pass to | |
| 664 // determine if the raster source needs to be replaced with a non-lcd | |
| 665 // raster source due to draw properties. | |
| 666 if (update_lcd_text) { | |
| 667 // TODO(enne): Make LTHI::sync_tree return this value. | |
| 668 LayerTreeImpl* sync_tree = | |
| 669 layer_tree_host_impl_->proxy()->CommitToActiveTree() | |
| 670 ? layer_tree_host_impl_->active_tree() | |
| 671 : layer_tree_host_impl_->pending_tree(); | |
| 672 // If this is not the sync tree, then it is not safe to update lcd text | |
| 673 // as it causes invalidations and the tiles may be in use. | |
| 674 DCHECK_EQ(this, sync_tree); | |
| 675 for (const auto& layer : picture_layers_) | |
| 676 layer->UpdateCanUseLCDTextAfterCommit(); | |
| 677 } | |
| 678 | |
| 679 { | |
| 680 TRACE_EVENT_BEGIN2("cc", "LayerTreeImpl::UpdateDrawProperties::UpdateTiles", | |
| 681 "IsActive", IsActiveTree(), "SourceFrameNumber", | |
| 682 source_frame_number_); | |
| 683 const bool resourceless_software_draw = | |
| 684 (layer_tree_host_impl_->GetDrawMode() == | |
| 685 DRAW_MODE_RESOURCELESS_SOFTWARE); | |
| 686 size_t layers_updated_count = 0; | |
| 687 bool tile_priorities_updated = false; | |
| 688 for (PictureLayerImpl* layer : picture_layers_) { | |
| 689 if (!layer->IsDrawnRenderSurfaceLayerListMember()) | |
| 690 continue; | |
| 691 ++layers_updated_count; | |
| 692 tile_priorities_updated |= layer->UpdateTiles(resourceless_software_draw); | |
| 693 } | |
| 694 | |
| 695 if (tile_priorities_updated) | |
| 696 DidModifyTilePriorities(); | |
| 697 | |
| 698 TRACE_EVENT_END1("cc", "LayerTreeImpl::UpdateTilePriorities", | |
| 699 "layers_updated_count", layers_updated_count); | |
| 700 } | |
| 701 | |
| 702 DCHECK(!needs_update_draw_properties_) << | |
| 703 "CalcDrawProperties should not set_needs_update_draw_properties()"; | |
| 704 return true; | |
| 705 } | |
| 706 | |
| 707 const LayerImplList& LayerTreeImpl::RenderSurfaceLayerList() const { | |
| 708 // If this assert triggers, then the list is dirty. | |
| 709 DCHECK(!needs_update_draw_properties_); | |
| 710 return render_surface_layer_list_; | |
| 711 } | |
| 712 | |
| 713 const Region& LayerTreeImpl::UnoccludedScreenSpaceRegion() const { | |
| 714 // If this assert triggers, then the render_surface_layer_list_ is dirty, so | |
| 715 // the unoccluded_screen_space_region_ is not valid anymore. | |
| 716 DCHECK(!needs_update_draw_properties_); | |
| 717 return unoccluded_screen_space_region_; | |
| 718 } | |
| 719 | |
| 720 gfx::Size LayerTreeImpl::ScrollableSize() const { | |
| 721 LayerImpl* root_scroll_layer = OuterViewportScrollLayer() | |
| 722 ? OuterViewportScrollLayer() | |
| 723 : InnerViewportScrollLayer(); | |
| 724 if (!root_scroll_layer || root_scroll_layer->children().empty()) | |
| 725 return gfx::Size(); | |
| 726 return root_scroll_layer->children()[0]->bounds(); | |
| 727 } | |
| 728 | |
| 729 LayerImpl* LayerTreeImpl::LayerById(int id) { | |
| 730 LayerIdMap::iterator iter = layer_id_map_.find(id); | |
| 731 return iter != layer_id_map_.end() ? iter->second : NULL; | |
| 732 } | |
| 733 | |
| 734 void LayerTreeImpl::RegisterLayer(LayerImpl* layer) { | |
| 735 DCHECK(!LayerById(layer->id())); | |
| 736 layer_id_map_[layer->id()] = layer; | |
| 737 } | |
| 738 | |
| 739 void LayerTreeImpl::UnregisterLayer(LayerImpl* layer) { | |
| 740 DCHECK(LayerById(layer->id())); | |
| 741 layer_id_map_.erase(layer->id()); | |
| 742 } | |
| 743 | |
| 744 size_t LayerTreeImpl::NumLayers() { | |
| 745 return layer_id_map_.size(); | |
| 746 } | |
| 747 | |
| 748 void LayerTreeImpl::PushPersistedState(LayerTreeImpl* pending_tree) { | |
| 749 pending_tree->SetCurrentlyScrollingLayer( | |
| 750 LayerTreeHostCommon::FindLayerInSubtree(pending_tree->root_layer(), | |
| 751 currently_scrolling_layer_ ? currently_scrolling_layer_->id() : 0)); | |
| 752 } | |
| 753 | |
| 754 void LayerTreeImpl::DidBecomeActive() { | |
| 755 if (next_activation_forces_redraw_) { | |
| 756 layer_tree_host_impl_->SetFullRootLayerDamage(); | |
| 757 next_activation_forces_redraw_ = false; | |
| 758 } | |
| 759 | |
| 760 if (scrolling_layer_id_from_previous_tree_) { | |
| 761 currently_scrolling_layer_ = LayerTreeHostCommon::FindLayerInSubtree( | |
| 762 root_layer(), scrolling_layer_id_from_previous_tree_); | |
| 763 } | |
| 764 | |
| 765 // Always reset this flag on activation, as we would only have activated | |
| 766 // if we were in a good state. | |
| 767 layer_tree_host_impl_->ResetRequiresHighResToDraw(); | |
| 768 | |
| 769 if (root_layer()) { | |
| 770 LayerTreeHostCommon::CallFunctionForSubtree( | |
| 771 root_layer(), [](LayerImpl* layer) { layer->DidBecomeActive(); }); | |
| 772 } | |
| 773 | |
| 774 devtools_instrumentation::DidActivateLayerTree(layer_tree_host_impl_->id(), | |
| 775 source_frame_number_); | |
| 776 } | |
| 777 | |
| 778 bool LayerTreeImpl::ContentsTexturesPurged() const { | |
| 779 return contents_textures_purged_; | |
| 780 } | |
| 781 | |
| 782 void LayerTreeImpl::SetContentsTexturesPurged() { | |
| 783 if (contents_textures_purged_) | |
| 784 return; | |
| 785 contents_textures_purged_ = true; | |
| 786 layer_tree_host_impl_->OnCanDrawStateChangedForTree(); | |
| 787 } | |
| 788 | |
| 789 void LayerTreeImpl::ResetContentsTexturesPurged() { | |
| 790 if (!contents_textures_purged_) | |
| 791 return; | |
| 792 contents_textures_purged_ = false; | |
| 793 layer_tree_host_impl_->OnCanDrawStateChangedForTree(); | |
| 794 } | |
| 795 | |
| 796 bool LayerTreeImpl::RequiresHighResToDraw() const { | |
| 797 return layer_tree_host_impl_->RequiresHighResToDraw(); | |
| 798 } | |
| 799 | |
| 800 bool LayerTreeImpl::ViewportSizeInvalid() const { | |
| 801 return viewport_size_invalid_; | |
| 802 } | |
| 803 | |
| 804 void LayerTreeImpl::SetViewportSizeInvalid() { | |
| 805 viewport_size_invalid_ = true; | |
| 806 layer_tree_host_impl_->OnCanDrawStateChangedForTree(); | |
| 807 } | |
| 808 | |
| 809 void LayerTreeImpl::ResetViewportSizeInvalid() { | |
| 810 viewport_size_invalid_ = false; | |
| 811 layer_tree_host_impl_->OnCanDrawStateChangedForTree(); | |
| 812 } | |
| 813 | |
| 814 Proxy* LayerTreeImpl::proxy() const { | |
| 815 return layer_tree_host_impl_->proxy(); | |
| 816 } | |
| 817 | |
| 818 const LayerTreeSettings& LayerTreeImpl::settings() const { | |
| 819 return layer_tree_host_impl_->settings(); | |
| 820 } | |
| 821 | |
| 822 const LayerTreeDebugState& LayerTreeImpl::debug_state() const { | |
| 823 return layer_tree_host_impl_->debug_state(); | |
| 824 } | |
| 825 | |
| 826 const RendererCapabilitiesImpl& LayerTreeImpl::GetRendererCapabilities() const { | |
| 827 return layer_tree_host_impl_->GetRendererCapabilities(); | |
| 828 } | |
| 829 | |
| 830 ContextProvider* LayerTreeImpl::context_provider() const { | |
| 831 return output_surface()->context_provider(); | |
| 832 } | |
| 833 | |
| 834 OutputSurface* LayerTreeImpl::output_surface() const { | |
| 835 return layer_tree_host_impl_->output_surface(); | |
| 836 } | |
| 837 | |
| 838 ResourceProvider* LayerTreeImpl::resource_provider() const { | |
| 839 return layer_tree_host_impl_->resource_provider(); | |
| 840 } | |
| 841 | |
| 842 TileManager* LayerTreeImpl::tile_manager() const { | |
| 843 return layer_tree_host_impl_->tile_manager(); | |
| 844 } | |
| 845 | |
| 846 FrameRateCounter* LayerTreeImpl::frame_rate_counter() const { | |
| 847 return layer_tree_host_impl_->fps_counter(); | |
| 848 } | |
| 849 | |
| 850 PaintTimeCounter* LayerTreeImpl::paint_time_counter() const { | |
| 851 return layer_tree_host_impl_->paint_time_counter(); | |
| 852 } | |
| 853 | |
| 854 MemoryHistory* LayerTreeImpl::memory_history() const { | |
| 855 return layer_tree_host_impl_->memory_history(); | |
| 856 } | |
| 857 | |
| 858 gfx::Size LayerTreeImpl::device_viewport_size() const { | |
| 859 return layer_tree_host_impl_->device_viewport_size(); | |
| 860 } | |
| 861 | |
| 862 float LayerTreeImpl::device_scale_factor() const { | |
| 863 return layer_tree_host_impl_->device_scale_factor(); | |
| 864 } | |
| 865 | |
| 866 DebugRectHistory* LayerTreeImpl::debug_rect_history() const { | |
| 867 return layer_tree_host_impl_->debug_rect_history(); | |
| 868 } | |
| 869 | |
| 870 bool LayerTreeImpl::IsActiveTree() const { | |
| 871 return layer_tree_host_impl_->active_tree() == this; | |
| 872 } | |
| 873 | |
| 874 bool LayerTreeImpl::IsPendingTree() const { | |
| 875 return layer_tree_host_impl_->pending_tree() == this; | |
| 876 } | |
| 877 | |
| 878 bool LayerTreeImpl::IsRecycleTree() const { | |
| 879 return layer_tree_host_impl_->recycle_tree() == this; | |
| 880 } | |
| 881 | |
| 882 bool LayerTreeImpl::IsSyncTree() const { | |
| 883 return layer_tree_host_impl_->sync_tree() == this; | |
| 884 } | |
| 885 | |
| 886 LayerImpl* LayerTreeImpl::FindActiveTreeLayerById(int id) { | |
| 887 LayerTreeImpl* tree = layer_tree_host_impl_->active_tree(); | |
| 888 if (!tree) | |
| 889 return NULL; | |
| 890 return tree->LayerById(id); | |
| 891 } | |
| 892 | |
| 893 LayerImpl* LayerTreeImpl::FindPendingTreeLayerById(int id) { | |
| 894 LayerTreeImpl* tree = layer_tree_host_impl_->pending_tree(); | |
| 895 if (!tree) | |
| 896 return NULL; | |
| 897 return tree->LayerById(id); | |
| 898 } | |
| 899 | |
| 900 bool LayerTreeImpl::PinchGestureActive() const { | |
| 901 return layer_tree_host_impl_->pinch_gesture_active(); | |
| 902 } | |
| 903 | |
| 904 BeginFrameArgs LayerTreeImpl::CurrentBeginFrameArgs() const { | |
| 905 return layer_tree_host_impl_->CurrentBeginFrameArgs(); | |
| 906 } | |
| 907 | |
| 908 base::TimeDelta LayerTreeImpl::begin_impl_frame_interval() const { | |
| 909 return layer_tree_host_impl_->begin_impl_frame_interval(); | |
| 910 } | |
| 911 | |
| 912 void LayerTreeImpl::SetNeedsCommit() { | |
| 913 layer_tree_host_impl_->SetNeedsCommit(); | |
| 914 } | |
| 915 | |
| 916 gfx::Rect LayerTreeImpl::DeviceViewport() const { | |
| 917 return layer_tree_host_impl_->DeviceViewport(); | |
| 918 } | |
| 919 | |
| 920 gfx::Size LayerTreeImpl::DrawViewportSize() const { | |
| 921 return layer_tree_host_impl_->DrawViewportSize(); | |
| 922 } | |
| 923 | |
| 924 const gfx::Rect LayerTreeImpl::ViewportRectForTilePriority() const { | |
| 925 return layer_tree_host_impl_->ViewportRectForTilePriority(); | |
| 926 } | |
| 927 | |
| 928 scoped_ptr<ScrollbarAnimationController> | |
| 929 LayerTreeImpl::CreateScrollbarAnimationController(LayerImpl* scrolling_layer) { | |
| 930 DCHECK(settings().scrollbar_fade_delay_ms); | |
| 931 DCHECK(settings().scrollbar_fade_duration_ms); | |
| 932 base::TimeDelta delay = | |
| 933 base::TimeDelta::FromMilliseconds(settings().scrollbar_fade_delay_ms); | |
| 934 base::TimeDelta resize_delay = base::TimeDelta::FromMilliseconds( | |
| 935 settings().scrollbar_fade_resize_delay_ms); | |
| 936 base::TimeDelta duration = | |
| 937 base::TimeDelta::FromMilliseconds(settings().scrollbar_fade_duration_ms); | |
| 938 switch (settings().scrollbar_animator) { | |
| 939 case LayerTreeSettings::LINEAR_FADE: { | |
| 940 return ScrollbarAnimationControllerLinearFade::Create( | |
| 941 scrolling_layer, | |
| 942 layer_tree_host_impl_, | |
| 943 delay, | |
| 944 resize_delay, | |
| 945 duration); | |
| 946 } | |
| 947 case LayerTreeSettings::THINNING: { | |
| 948 return ScrollbarAnimationControllerThinning::Create(scrolling_layer, | |
| 949 layer_tree_host_impl_, | |
| 950 delay, | |
| 951 resize_delay, | |
| 952 duration); | |
| 953 } | |
| 954 case LayerTreeSettings::NO_ANIMATOR: | |
| 955 NOTREACHED(); | |
| 956 break; | |
| 957 } | |
| 958 return nullptr; | |
| 959 } | |
| 960 | |
| 961 void LayerTreeImpl::DidAnimateScrollOffset() { | |
| 962 layer_tree_host_impl_->DidAnimateScrollOffset(); | |
| 963 } | |
| 964 | |
| 965 bool LayerTreeImpl::use_gpu_rasterization() const { | |
| 966 return layer_tree_host_impl_->use_gpu_rasterization(); | |
| 967 } | |
| 968 | |
| 969 GpuRasterizationStatus LayerTreeImpl::GetGpuRasterizationStatus() const { | |
| 970 return layer_tree_host_impl_->gpu_rasterization_status(); | |
| 971 } | |
| 972 | |
| 973 bool LayerTreeImpl::create_low_res_tiling() const { | |
| 974 return layer_tree_host_impl_->create_low_res_tiling(); | |
| 975 } | |
| 976 | |
| 977 void LayerTreeImpl::SetNeedsRedraw() { | |
| 978 layer_tree_host_impl_->SetNeedsRedraw(); | |
| 979 } | |
| 980 | |
| 981 AnimationRegistrar* LayerTreeImpl::GetAnimationRegistrar() const { | |
| 982 return layer_tree_host_impl_->animation_registrar(); | |
| 983 } | |
| 984 | |
| 985 void LayerTreeImpl::GetAllTilesAndPrioritiesForTracing( | |
| 986 std::map<const Tile*, TilePriority>* tile_map) const { | |
| 987 typedef LayerIterator<LayerImpl> LayerIteratorType; | |
| 988 LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list_); | |
| 989 for (LayerIteratorType it = | |
| 990 LayerIteratorType::Begin(&render_surface_layer_list_); | |
| 991 it != end; | |
| 992 ++it) { | |
| 993 if (!it.represents_itself()) | |
| 994 continue; | |
| 995 LayerImpl* layer_impl = *it; | |
| 996 layer_impl->GetAllTilesAndPrioritiesForTracing(tile_map); | |
| 997 } | |
| 998 } | |
| 999 | |
| 1000 void LayerTreeImpl::AsValueInto(base::trace_event::TracedValue* state) const { | |
| 1001 TracedValue::MakeDictIntoImplicitSnapshot(state, "cc::LayerTreeImpl", this); | |
| 1002 state->SetInteger("source_frame_number", source_frame_number_); | |
| 1003 | |
| 1004 state->BeginDictionary("root_layer"); | |
| 1005 root_layer_->AsValueInto(state); | |
| 1006 state->EndDictionary(); | |
| 1007 | |
| 1008 state->BeginArray("render_surface_layer_list"); | |
| 1009 typedef LayerIterator<LayerImpl> LayerIteratorType; | |
| 1010 LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list_); | |
| 1011 for (LayerIteratorType it = LayerIteratorType::Begin( | |
| 1012 &render_surface_layer_list_); it != end; ++it) { | |
| 1013 if (!it.represents_itself()) | |
| 1014 continue; | |
| 1015 TracedValue::AppendIDRef(*it, state); | |
| 1016 } | |
| 1017 state->EndArray(); | |
| 1018 | |
| 1019 state->BeginArray("swap_promise_trace_ids"); | |
| 1020 for (size_t i = 0; i < swap_promise_list_.size(); i++) | |
| 1021 state->AppendDouble(swap_promise_list_[i]->TraceId()); | |
| 1022 state->EndArray(); | |
| 1023 } | |
| 1024 | |
| 1025 void LayerTreeImpl::SetRootLayerScrollOffsetDelegate( | |
| 1026 LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate) { | |
| 1027 if (root_layer_scroll_offset_delegate_ == root_layer_scroll_offset_delegate) | |
| 1028 return; | |
| 1029 | |
| 1030 if (!root_layer_scroll_offset_delegate) { | |
| 1031 // Make sure we remove the proxies from their layers before | |
| 1032 // releasing them. | |
| 1033 if (InnerViewportScrollLayer()) | |
| 1034 InnerViewportScrollLayer()->SetScrollOffsetDelegate(NULL); | |
| 1035 if (OuterViewportScrollLayer()) | |
| 1036 OuterViewportScrollLayer()->SetScrollOffsetDelegate(NULL); | |
| 1037 inner_viewport_scroll_delegate_proxy_ = nullptr; | |
| 1038 outer_viewport_scroll_delegate_proxy_ = nullptr; | |
| 1039 } | |
| 1040 | |
| 1041 root_layer_scroll_offset_delegate_ = root_layer_scroll_offset_delegate; | |
| 1042 | |
| 1043 if (root_layer_scroll_offset_delegate_) { | |
| 1044 root_layer_scroll_offset_delegate_->UpdateRootLayerState( | |
| 1045 TotalScrollOffset(), TotalMaxScrollOffset(), ScrollableSize(), | |
| 1046 current_page_scale_factor(), min_page_scale_factor(), | |
| 1047 max_page_scale_factor()); | |
| 1048 | |
| 1049 if (inner_viewport_scroll_layer_) { | |
| 1050 inner_viewport_scroll_delegate_proxy_ = make_scoped_ptr( | |
| 1051 new LayerScrollOffsetDelegateProxy(InnerViewportScrollLayer(), | |
| 1052 root_layer_scroll_offset_delegate_, | |
| 1053 this)); | |
| 1054 inner_viewport_scroll_layer_->SetScrollOffsetDelegate( | |
| 1055 inner_viewport_scroll_delegate_proxy_.get()); | |
| 1056 } | |
| 1057 | |
| 1058 if (outer_viewport_scroll_layer_) { | |
| 1059 outer_viewport_scroll_delegate_proxy_ = make_scoped_ptr( | |
| 1060 new LayerScrollOffsetDelegateProxy(OuterViewportScrollLayer(), | |
| 1061 root_layer_scroll_offset_delegate_, | |
| 1062 this)); | |
| 1063 outer_viewport_scroll_layer_->SetScrollOffsetDelegate( | |
| 1064 outer_viewport_scroll_delegate_proxy_.get()); | |
| 1065 } | |
| 1066 | |
| 1067 if (inner_viewport_scroll_layer_) | |
| 1068 inner_viewport_scroll_layer_->RefreshFromScrollDelegate(); | |
| 1069 if (outer_viewport_scroll_layer_) | |
| 1070 outer_viewport_scroll_layer_->RefreshFromScrollDelegate(); | |
| 1071 | |
| 1072 if (inner_viewport_scroll_layer_) | |
| 1073 UpdateScrollOffsetDelegate(); | |
| 1074 } | |
| 1075 } | |
| 1076 | |
| 1077 void LayerTreeImpl::OnRootLayerDelegatedScrollOffsetChanged() { | |
| 1078 DCHECK(root_layer_scroll_offset_delegate_); | |
| 1079 if (inner_viewport_scroll_layer_) { | |
| 1080 inner_viewport_scroll_layer_->RefreshFromScrollDelegate(); | |
| 1081 } | |
| 1082 if (outer_viewport_scroll_layer_) { | |
| 1083 outer_viewport_scroll_layer_->RefreshFromScrollDelegate(); | |
| 1084 } | |
| 1085 } | |
| 1086 | |
| 1087 void LayerTreeImpl::UpdateScrollOffsetDelegate() { | |
| 1088 DCHECK(InnerViewportScrollLayer()); | |
| 1089 DCHECK(!OuterViewportScrollLayer() || outer_viewport_scroll_delegate_proxy_); | |
| 1090 DCHECK(root_layer_scroll_offset_delegate_); | |
| 1091 | |
| 1092 gfx::ScrollOffset offset = | |
| 1093 inner_viewport_scroll_delegate_proxy_->last_set_scroll_offset(); | |
| 1094 | |
| 1095 if (OuterViewportScrollLayer()) | |
| 1096 offset += outer_viewport_scroll_delegate_proxy_->last_set_scroll_offset(); | |
| 1097 | |
| 1098 root_layer_scroll_offset_delegate_->UpdateRootLayerState( | |
| 1099 offset, TotalMaxScrollOffset(), ScrollableSize(), | |
| 1100 current_page_scale_factor(), min_page_scale_factor(), | |
| 1101 max_page_scale_factor()); | |
| 1102 } | |
| 1103 | |
| 1104 gfx::ScrollOffset LayerTreeImpl::GetDelegatedScrollOffset(LayerImpl* layer) { | |
| 1105 DCHECK(root_layer_scroll_offset_delegate_); | |
| 1106 DCHECK(InnerViewportScrollLayer()); | |
| 1107 if (layer == InnerViewportScrollLayer() && !OuterViewportScrollLayer()) | |
| 1108 return root_layer_scroll_offset_delegate_->GetTotalScrollOffset(); | |
| 1109 | |
| 1110 // If we get here, we have both inner/outer viewports, and need to distribute | |
| 1111 // the scroll offset between them. | |
| 1112 DCHECK(inner_viewport_scroll_delegate_proxy_); | |
| 1113 DCHECK(outer_viewport_scroll_delegate_proxy_); | |
| 1114 gfx::ScrollOffset inner_viewport_offset = | |
| 1115 inner_viewport_scroll_delegate_proxy_->last_set_scroll_offset(); | |
| 1116 gfx::ScrollOffset outer_viewport_offset = | |
| 1117 outer_viewport_scroll_delegate_proxy_->last_set_scroll_offset(); | |
| 1118 | |
| 1119 // It may be nothing has changed. | |
| 1120 gfx::ScrollOffset delegate_offset = | |
| 1121 root_layer_scroll_offset_delegate_->GetTotalScrollOffset(); | |
| 1122 if (inner_viewport_offset + outer_viewport_offset == delegate_offset) { | |
| 1123 if (layer == InnerViewportScrollLayer()) | |
| 1124 return inner_viewport_offset; | |
| 1125 else | |
| 1126 return outer_viewport_offset; | |
| 1127 } | |
| 1128 | |
| 1129 gfx::ScrollOffset max_outer_viewport_scroll_offset = | |
| 1130 OuterViewportScrollLayer()->MaxScrollOffset(); | |
| 1131 | |
| 1132 outer_viewport_offset = delegate_offset - inner_viewport_offset; | |
| 1133 outer_viewport_offset.SetToMin(max_outer_viewport_scroll_offset); | |
| 1134 outer_viewport_offset.SetToMax(gfx::ScrollOffset()); | |
| 1135 | |
| 1136 if (layer == OuterViewportScrollLayer()) | |
| 1137 return outer_viewport_offset; | |
| 1138 | |
| 1139 inner_viewport_offset = delegate_offset - outer_viewport_offset; | |
| 1140 | |
| 1141 return inner_viewport_offset; | |
| 1142 } | |
| 1143 | |
| 1144 void LayerTreeImpl::QueueSwapPromise(scoped_ptr<SwapPromise> swap_promise) { | |
| 1145 DCHECK(swap_promise); | |
| 1146 swap_promise_list_.push_back(swap_promise.Pass()); | |
| 1147 } | |
| 1148 | |
| 1149 void LayerTreeImpl::PassSwapPromises( | |
| 1150 ScopedPtrVector<SwapPromise>* new_swap_promise) { | |
| 1151 swap_promise_list_.insert_and_take(swap_promise_list_.end(), | |
| 1152 new_swap_promise); | |
| 1153 new_swap_promise->clear(); | |
| 1154 } | |
| 1155 | |
| 1156 void LayerTreeImpl::FinishSwapPromises(CompositorFrameMetadata* metadata) { | |
| 1157 for (size_t i = 0; i < swap_promise_list_.size(); i++) | |
| 1158 swap_promise_list_[i]->DidSwap(metadata); | |
| 1159 swap_promise_list_.clear(); | |
| 1160 } | |
| 1161 | |
| 1162 void LayerTreeImpl::BreakSwapPromises(SwapPromise::DidNotSwapReason reason) { | |
| 1163 for (size_t i = 0; i < swap_promise_list_.size(); i++) | |
| 1164 swap_promise_list_[i]->DidNotSwap(reason); | |
| 1165 swap_promise_list_.clear(); | |
| 1166 } | |
| 1167 | |
| 1168 void LayerTreeImpl::DidModifyTilePriorities() { | |
| 1169 layer_tree_host_impl_->DidModifyTilePriorities(); | |
| 1170 } | |
| 1171 | |
| 1172 void LayerTreeImpl::set_ui_resource_request_queue( | |
| 1173 const UIResourceRequestQueue& queue) { | |
| 1174 ui_resource_request_queue_ = queue; | |
| 1175 } | |
| 1176 | |
| 1177 ResourceProvider::ResourceId LayerTreeImpl::ResourceIdForUIResource( | |
| 1178 UIResourceId uid) const { | |
| 1179 return layer_tree_host_impl_->ResourceIdForUIResource(uid); | |
| 1180 } | |
| 1181 | |
| 1182 bool LayerTreeImpl::IsUIResourceOpaque(UIResourceId uid) const { | |
| 1183 return layer_tree_host_impl_->IsUIResourceOpaque(uid); | |
| 1184 } | |
| 1185 | |
| 1186 void LayerTreeImpl::ProcessUIResourceRequestQueue() { | |
| 1187 for (const auto& req : ui_resource_request_queue_) { | |
| 1188 switch (req.GetType()) { | |
| 1189 case UIResourceRequest::UI_RESOURCE_CREATE: | |
| 1190 layer_tree_host_impl_->CreateUIResource(req.GetId(), req.GetBitmap()); | |
| 1191 break; | |
| 1192 case UIResourceRequest::UI_RESOURCE_DELETE: | |
| 1193 layer_tree_host_impl_->DeleteUIResource(req.GetId()); | |
| 1194 break; | |
| 1195 case UIResourceRequest::UI_RESOURCE_INVALID_REQUEST: | |
| 1196 NOTREACHED(); | |
| 1197 break; | |
| 1198 } | |
| 1199 } | |
| 1200 ui_resource_request_queue_.clear(); | |
| 1201 | |
| 1202 // If all UI resource evictions were not recreated by processing this queue, | |
| 1203 // then another commit is required. | |
| 1204 if (layer_tree_host_impl_->EvictedUIResourcesExist()) | |
| 1205 layer_tree_host_impl_->SetNeedsCommit(); | |
| 1206 } | |
| 1207 | |
| 1208 void LayerTreeImpl::RegisterPictureLayerImpl(PictureLayerImpl* layer) { | |
| 1209 DCHECK(std::find(picture_layers_.begin(), picture_layers_.end(), layer) == | |
| 1210 picture_layers_.end()); | |
| 1211 picture_layers_.push_back(layer); | |
| 1212 } | |
| 1213 | |
| 1214 void LayerTreeImpl::UnregisterPictureLayerImpl(PictureLayerImpl* layer) { | |
| 1215 std::vector<PictureLayerImpl*>::iterator it = | |
| 1216 std::find(picture_layers_.begin(), picture_layers_.end(), layer); | |
| 1217 DCHECK(it != picture_layers_.end()); | |
| 1218 picture_layers_.erase(it); | |
| 1219 } | |
| 1220 | |
| 1221 void LayerTreeImpl::AddLayerWithCopyOutputRequest(LayerImpl* layer) { | |
| 1222 // Only the active tree needs to know about layers with copy requests, as | |
| 1223 // they are aborted if not serviced during draw. | |
| 1224 DCHECK(IsActiveTree()); | |
| 1225 | |
| 1226 // DCHECK(std::find(layers_with_copy_output_request_.begin(), | |
| 1227 // layers_with_copy_output_request_.end(), | |
| 1228 // layer) == layers_with_copy_output_request_.end()); | |
| 1229 // TODO(danakj): Remove this once crash is found crbug.com/309777 | |
| 1230 for (size_t i = 0; i < layers_with_copy_output_request_.size(); ++i) { | |
| 1231 CHECK(layers_with_copy_output_request_[i] != layer) | |
| 1232 << i << " of " << layers_with_copy_output_request_.size(); | |
| 1233 } | |
| 1234 layers_with_copy_output_request_.push_back(layer); | |
| 1235 } | |
| 1236 | |
| 1237 void LayerTreeImpl::RemoveLayerWithCopyOutputRequest(LayerImpl* layer) { | |
| 1238 // Only the active tree needs to know about layers with copy requests, as | |
| 1239 // they are aborted if not serviced during draw. | |
| 1240 DCHECK(IsActiveTree()); | |
| 1241 | |
| 1242 std::vector<LayerImpl*>::iterator it = std::find( | |
| 1243 layers_with_copy_output_request_.begin(), | |
| 1244 layers_with_copy_output_request_.end(), | |
| 1245 layer); | |
| 1246 DCHECK(it != layers_with_copy_output_request_.end()); | |
| 1247 layers_with_copy_output_request_.erase(it); | |
| 1248 | |
| 1249 // TODO(danakj): Remove this once crash is found crbug.com/309777 | |
| 1250 for (size_t i = 0; i < layers_with_copy_output_request_.size(); ++i) { | |
| 1251 CHECK(layers_with_copy_output_request_[i] != layer) | |
| 1252 << i << " of " << layers_with_copy_output_request_.size(); | |
| 1253 } | |
| 1254 } | |
| 1255 | |
| 1256 const std::vector<LayerImpl*>& LayerTreeImpl::LayersWithCopyOutputRequest() | |
| 1257 const { | |
| 1258 // Only the active tree needs to know about layers with copy requests, as | |
| 1259 // they are aborted if not serviced during draw. | |
| 1260 DCHECK(IsActiveTree()); | |
| 1261 | |
| 1262 return layers_with_copy_output_request_; | |
| 1263 } | |
| 1264 | |
| 1265 template <typename LayerType> | |
| 1266 static inline bool LayerClipsSubtree(LayerType* layer) { | |
| 1267 return layer->masks_to_bounds() || layer->mask_layer(); | |
| 1268 } | |
| 1269 | |
| 1270 static bool PointHitsRect( | |
| 1271 const gfx::PointF& screen_space_point, | |
| 1272 const gfx::Transform& local_space_to_screen_space_transform, | |
| 1273 const gfx::RectF& local_space_rect, | |
| 1274 float* distance_to_camera) { | |
| 1275 // If the transform is not invertible, then assume that this point doesn't hit | |
| 1276 // this rect. | |
| 1277 gfx::Transform inverse_local_space_to_screen_space( | |
| 1278 gfx::Transform::kSkipInitialization); | |
| 1279 if (!local_space_to_screen_space_transform.GetInverse( | |
| 1280 &inverse_local_space_to_screen_space)) | |
| 1281 return false; | |
| 1282 | |
| 1283 // Transform the hit test point from screen space to the local space of the | |
| 1284 // given rect. | |
| 1285 bool clipped = false; | |
| 1286 gfx::Point3F planar_point = MathUtil::ProjectPoint3D( | |
| 1287 inverse_local_space_to_screen_space, screen_space_point, &clipped); | |
| 1288 gfx::PointF hit_test_point_in_local_space = | |
| 1289 gfx::PointF(planar_point.x(), planar_point.y()); | |
| 1290 | |
| 1291 // If ProjectPoint could not project to a valid value, then we assume that | |
| 1292 // this point doesn't hit this rect. | |
| 1293 if (clipped) | |
| 1294 return false; | |
| 1295 | |
| 1296 if (!local_space_rect.Contains(hit_test_point_in_local_space)) | |
| 1297 return false; | |
| 1298 | |
| 1299 if (distance_to_camera) { | |
| 1300 // To compute the distance to the camera, we have to take the planar point | |
| 1301 // and pull it back to world space and compute the displacement along the | |
| 1302 // z-axis. | |
| 1303 gfx::Point3F planar_point_in_screen_space(planar_point); | |
| 1304 local_space_to_screen_space_transform.TransformPoint( | |
| 1305 &planar_point_in_screen_space); | |
| 1306 *distance_to_camera = planar_point_in_screen_space.z(); | |
| 1307 } | |
| 1308 | |
| 1309 return true; | |
| 1310 } | |
| 1311 | |
| 1312 static bool PointHitsRegion(const gfx::PointF& screen_space_point, | |
| 1313 const gfx::Transform& screen_space_transform, | |
| 1314 const Region& layer_space_region, | |
| 1315 float layer_content_scale_x, | |
| 1316 float layer_content_scale_y) { | |
| 1317 // If the transform is not invertible, then assume that this point doesn't hit | |
| 1318 // this region. | |
| 1319 gfx::Transform inverse_screen_space_transform( | |
| 1320 gfx::Transform::kSkipInitialization); | |
| 1321 if (!screen_space_transform.GetInverse(&inverse_screen_space_transform)) | |
| 1322 return false; | |
| 1323 | |
| 1324 // Transform the hit test point from screen space to the local space of the | |
| 1325 // given region. | |
| 1326 bool clipped = false; | |
| 1327 gfx::PointF hit_test_point_in_content_space = MathUtil::ProjectPoint( | |
| 1328 inverse_screen_space_transform, screen_space_point, &clipped); | |
| 1329 gfx::PointF hit_test_point_in_layer_space = | |
| 1330 gfx::ScalePoint(hit_test_point_in_content_space, | |
| 1331 1.f / layer_content_scale_x, | |
| 1332 1.f / layer_content_scale_y); | |
| 1333 | |
| 1334 // If ProjectPoint could not project to a valid value, then we assume that | |
| 1335 // this point doesn't hit this region. | |
| 1336 if (clipped) | |
| 1337 return false; | |
| 1338 | |
| 1339 return layer_space_region.Contains( | |
| 1340 gfx::ToRoundedPoint(hit_test_point_in_layer_space)); | |
| 1341 } | |
| 1342 | |
| 1343 static const LayerImpl* GetNextClippingLayer(const LayerImpl* layer) { | |
| 1344 if (layer->scroll_parent()) | |
| 1345 return layer->scroll_parent(); | |
| 1346 if (layer->clip_parent()) | |
| 1347 return layer->clip_parent(); | |
| 1348 return layer->parent(); | |
| 1349 } | |
| 1350 | |
| 1351 static bool PointIsClippedBySurfaceOrClipRect( | |
| 1352 const gfx::PointF& screen_space_point, | |
| 1353 const LayerImpl* layer) { | |
| 1354 // Walk up the layer tree and hit-test any render_surfaces and any layer | |
| 1355 // clip rects that are active. | |
| 1356 for (; layer; layer = GetNextClippingLayer(layer)) { | |
| 1357 if (layer->render_surface() && | |
| 1358 !PointHitsRect(screen_space_point, | |
| 1359 layer->render_surface()->screen_space_transform(), | |
| 1360 layer->render_surface()->content_rect(), | |
| 1361 NULL)) | |
| 1362 return true; | |
| 1363 | |
| 1364 if (LayerClipsSubtree(layer) && | |
| 1365 !PointHitsRect(screen_space_point, | |
| 1366 layer->screen_space_transform(), | |
| 1367 gfx::Rect(layer->content_bounds()), | |
| 1368 NULL)) | |
| 1369 return true; | |
| 1370 } | |
| 1371 | |
| 1372 // If we have finished walking all ancestors without having already exited, | |
| 1373 // then the point is not clipped by any ancestors. | |
| 1374 return false; | |
| 1375 } | |
| 1376 | |
| 1377 static bool PointHitsLayer(const LayerImpl* layer, | |
| 1378 const gfx::PointF& screen_space_point, | |
| 1379 float* distance_to_intersection) { | |
| 1380 gfx::RectF content_rect(layer->content_bounds()); | |
| 1381 if (!PointHitsRect(screen_space_point, | |
| 1382 layer->screen_space_transform(), | |
| 1383 content_rect, | |
| 1384 distance_to_intersection)) | |
| 1385 return false; | |
| 1386 | |
| 1387 // At this point, we think the point does hit the layer, but we need to walk | |
| 1388 // up the parents to ensure that the layer was not clipped in such a way | |
| 1389 // that the hit point actually should not hit the layer. | |
| 1390 if (PointIsClippedBySurfaceOrClipRect(screen_space_point, layer)) | |
| 1391 return false; | |
| 1392 | |
| 1393 // Skip the HUD layer. | |
| 1394 if (layer == layer->layer_tree_impl()->hud_layer()) | |
| 1395 return false; | |
| 1396 | |
| 1397 return true; | |
| 1398 } | |
| 1399 | |
| 1400 struct FindClosestMatchingLayerDataForRecursion { | |
| 1401 FindClosestMatchingLayerDataForRecursion() | |
| 1402 : closest_match(NULL), | |
| 1403 closest_distance(-std::numeric_limits<float>::infinity()) {} | |
| 1404 LayerImpl* closest_match; | |
| 1405 // Note that the positive z-axis points towards the camera, so bigger means | |
| 1406 // closer in this case, counterintuitively. | |
| 1407 float closest_distance; | |
| 1408 }; | |
| 1409 | |
| 1410 template <typename Functor> | |
| 1411 static void FindClosestMatchingLayer( | |
| 1412 const gfx::PointF& screen_space_point, | |
| 1413 LayerImpl* layer, | |
| 1414 const Functor& func, | |
| 1415 FindClosestMatchingLayerDataForRecursion* data_for_recursion) { | |
| 1416 for (int i = layer->children().size() - 1; i >= 0; --i) { | |
| 1417 FindClosestMatchingLayer( | |
| 1418 screen_space_point, layer->children()[i], func, data_for_recursion); | |
| 1419 } | |
| 1420 | |
| 1421 float distance_to_intersection = 0.f; | |
| 1422 if (func(layer) && | |
| 1423 PointHitsLayer(layer, screen_space_point, &distance_to_intersection) && | |
| 1424 ((!data_for_recursion->closest_match || | |
| 1425 distance_to_intersection > data_for_recursion->closest_distance))) { | |
| 1426 data_for_recursion->closest_distance = distance_to_intersection; | |
| 1427 data_for_recursion->closest_match = layer; | |
| 1428 } | |
| 1429 } | |
| 1430 | |
| 1431 static bool ScrollsAnyDrawnRenderSurfaceLayerListMember(LayerImpl* layer) { | |
| 1432 if (!layer->scrollable()) | |
| 1433 return false; | |
| 1434 if (layer->draw_properties().layer_or_descendant_is_drawn) | |
| 1435 return true; | |
| 1436 | |
| 1437 if (!layer->scroll_children()) | |
| 1438 return false; | |
| 1439 for (std::set<LayerImpl*>::const_iterator it = | |
| 1440 layer->scroll_children()->begin(); | |
| 1441 it != layer->scroll_children()->end(); | |
| 1442 ++it) { | |
| 1443 if ((*it)->draw_properties().layer_or_descendant_is_drawn) | |
| 1444 return true; | |
| 1445 } | |
| 1446 return false; | |
| 1447 } | |
| 1448 | |
| 1449 struct FindScrollingLayerFunctor { | |
| 1450 bool operator()(LayerImpl* layer) const { | |
| 1451 return ScrollsAnyDrawnRenderSurfaceLayerListMember(layer); | |
| 1452 } | |
| 1453 }; | |
| 1454 | |
| 1455 LayerImpl* LayerTreeImpl::FindFirstScrollingLayerThatIsHitByPoint( | |
| 1456 const gfx::PointF& screen_space_point) { | |
| 1457 FindClosestMatchingLayerDataForRecursion data_for_recursion; | |
| 1458 FindClosestMatchingLayer(screen_space_point, | |
| 1459 root_layer(), | |
| 1460 FindScrollingLayerFunctor(), | |
| 1461 &data_for_recursion); | |
| 1462 return data_for_recursion.closest_match; | |
| 1463 } | |
| 1464 | |
| 1465 struct HitTestVisibleScrollableOrTouchableFunctor { | |
| 1466 bool operator()(LayerImpl* layer) const { | |
| 1467 return layer->IsDrawnRenderSurfaceLayerListMember() || | |
| 1468 ScrollsAnyDrawnRenderSurfaceLayerListMember(layer) || | |
| 1469 !layer->touch_event_handler_region().IsEmpty() || | |
| 1470 layer->have_wheel_event_handlers(); | |
| 1471 } | |
| 1472 }; | |
| 1473 | |
| 1474 LayerImpl* LayerTreeImpl::FindLayerThatIsHitByPoint( | |
| 1475 const gfx::PointF& screen_space_point) { | |
| 1476 if (!root_layer()) | |
| 1477 return NULL; | |
| 1478 bool update_lcd_text = false; | |
| 1479 if (!UpdateDrawProperties(update_lcd_text)) | |
| 1480 return NULL; | |
| 1481 FindClosestMatchingLayerDataForRecursion data_for_recursion; | |
| 1482 FindClosestMatchingLayer(screen_space_point, | |
| 1483 root_layer(), | |
| 1484 HitTestVisibleScrollableOrTouchableFunctor(), | |
| 1485 &data_for_recursion); | |
| 1486 return data_for_recursion.closest_match; | |
| 1487 } | |
| 1488 | |
| 1489 static bool LayerHasTouchEventHandlersAt(const gfx::PointF& screen_space_point, | |
| 1490 LayerImpl* layer_impl) { | |
| 1491 if (layer_impl->touch_event_handler_region().IsEmpty()) | |
| 1492 return false; | |
| 1493 | |
| 1494 if (!PointHitsRegion(screen_space_point, | |
| 1495 layer_impl->screen_space_transform(), | |
| 1496 layer_impl->touch_event_handler_region(), | |
| 1497 layer_impl->contents_scale_x(), | |
| 1498 layer_impl->contents_scale_y())) | |
| 1499 return false; | |
| 1500 | |
| 1501 // At this point, we think the point does hit the touch event handler region | |
| 1502 // on the layer, but we need to walk up the parents to ensure that the layer | |
| 1503 // was not clipped in such a way that the hit point actually should not hit | |
| 1504 // the layer. | |
| 1505 if (PointIsClippedBySurfaceOrClipRect(screen_space_point, layer_impl)) | |
| 1506 return false; | |
| 1507 | |
| 1508 return true; | |
| 1509 } | |
| 1510 | |
| 1511 struct FindWheelEventLayerFunctor { | |
| 1512 bool operator()(LayerImpl* layer) const { | |
| 1513 return layer->have_wheel_event_handlers(); | |
| 1514 } | |
| 1515 }; | |
| 1516 | |
| 1517 LayerImpl* LayerTreeImpl::FindLayerWithWheelHandlerThatIsHitByPoint( | |
| 1518 const gfx::PointF& screen_space_point) { | |
| 1519 if (!root_layer()) | |
| 1520 return NULL; | |
| 1521 bool update_lcd_text = false; | |
| 1522 if (!UpdateDrawProperties(update_lcd_text)) | |
| 1523 return NULL; | |
| 1524 FindWheelEventLayerFunctor func; | |
| 1525 FindClosestMatchingLayerDataForRecursion data_for_recursion; | |
| 1526 FindClosestMatchingLayer(screen_space_point, root_layer(), func, | |
| 1527 &data_for_recursion); | |
| 1528 return data_for_recursion.closest_match; | |
| 1529 } | |
| 1530 | |
| 1531 struct FindTouchEventLayerFunctor { | |
| 1532 bool operator()(LayerImpl* layer) const { | |
| 1533 return LayerHasTouchEventHandlersAt(screen_space_point, layer); | |
| 1534 } | |
| 1535 const gfx::PointF screen_space_point; | |
| 1536 }; | |
| 1537 | |
| 1538 LayerImpl* LayerTreeImpl::FindLayerThatIsHitByPointInTouchHandlerRegion( | |
| 1539 const gfx::PointF& screen_space_point) { | |
| 1540 if (!root_layer()) | |
| 1541 return NULL; | |
| 1542 bool update_lcd_text = false; | |
| 1543 if (!UpdateDrawProperties(update_lcd_text)) | |
| 1544 return NULL; | |
| 1545 FindTouchEventLayerFunctor func = {screen_space_point}; | |
| 1546 FindClosestMatchingLayerDataForRecursion data_for_recursion; | |
| 1547 FindClosestMatchingLayer( | |
| 1548 screen_space_point, root_layer(), func, &data_for_recursion); | |
| 1549 return data_for_recursion.closest_match; | |
| 1550 } | |
| 1551 | |
| 1552 void LayerTreeImpl::RegisterSelection(const LayerSelectionBound& start, | |
| 1553 const LayerSelectionBound& end) { | |
| 1554 selection_start_ = start; | |
| 1555 selection_end_ = end; | |
| 1556 } | |
| 1557 | |
| 1558 static ViewportSelectionBound ComputeViewportSelection( | |
| 1559 const LayerSelectionBound& layer_bound, | |
| 1560 LayerImpl* layer, | |
| 1561 float device_scale_factor) { | |
| 1562 ViewportSelectionBound viewport_bound; | |
| 1563 viewport_bound.type = layer_bound.type; | |
| 1564 | |
| 1565 if (!layer || layer_bound.type == SELECTION_BOUND_EMPTY) | |
| 1566 return viewport_bound; | |
| 1567 | |
| 1568 gfx::PointF layer_scaled_top = gfx::ScalePoint(layer_bound.edge_top, | |
| 1569 layer->contents_scale_x(), | |
| 1570 layer->contents_scale_y()); | |
| 1571 gfx::PointF layer_scaled_bottom = gfx::ScalePoint(layer_bound.edge_bottom, | |
| 1572 layer->contents_scale_x(), | |
| 1573 layer->contents_scale_y()); | |
| 1574 | |
| 1575 bool clipped = false; | |
| 1576 gfx::PointF screen_top = MathUtil::MapPoint( | |
| 1577 layer->screen_space_transform(), layer_scaled_top, &clipped); | |
| 1578 gfx::PointF screen_bottom = MathUtil::MapPoint( | |
| 1579 layer->screen_space_transform(), layer_scaled_bottom, &clipped); | |
| 1580 | |
| 1581 const float inv_scale = 1.f / device_scale_factor; | |
| 1582 viewport_bound.edge_top = gfx::ScalePoint(screen_top, inv_scale); | |
| 1583 viewport_bound.edge_bottom = gfx::ScalePoint(screen_bottom, inv_scale); | |
| 1584 | |
| 1585 // The bottom edge point is used for visibility testing as it is the logical | |
| 1586 // focal point for bound selection handles (this may change in the future). | |
| 1587 // Shifting the visibility point fractionally inward ensures that neighboring | |
| 1588 // or logically coincident layers aligned to integral DPI coordinates will not | |
| 1589 // spuriously occlude the bound. | |
| 1590 gfx::Vector2dF visibility_offset = layer_scaled_top - layer_scaled_bottom; | |
| 1591 visibility_offset.Scale(device_scale_factor / visibility_offset.Length()); | |
| 1592 gfx::PointF visibility_point = layer_scaled_bottom + visibility_offset; | |
| 1593 if (visibility_point.x() <= 0) | |
| 1594 visibility_point.set_x(visibility_point.x() + device_scale_factor); | |
| 1595 visibility_point = MathUtil::MapPoint( | |
| 1596 layer->screen_space_transform(), visibility_point, &clipped); | |
| 1597 | |
| 1598 float intersect_distance = 0.f; | |
| 1599 viewport_bound.visible = | |
| 1600 PointHitsLayer(layer, visibility_point, &intersect_distance); | |
| 1601 | |
| 1602 return viewport_bound; | |
| 1603 } | |
| 1604 | |
| 1605 void LayerTreeImpl::GetViewportSelection(ViewportSelectionBound* start, | |
| 1606 ViewportSelectionBound* end) { | |
| 1607 DCHECK(start); | |
| 1608 DCHECK(end); | |
| 1609 | |
| 1610 *start = ComputeViewportSelection( | |
| 1611 selection_start_, | |
| 1612 selection_start_.layer_id ? LayerById(selection_start_.layer_id) : NULL, | |
| 1613 device_scale_factor()); | |
| 1614 if (start->type == SELECTION_BOUND_CENTER || | |
| 1615 start->type == SELECTION_BOUND_EMPTY) { | |
| 1616 *end = *start; | |
| 1617 } else { | |
| 1618 *end = ComputeViewportSelection( | |
| 1619 selection_end_, | |
| 1620 selection_end_.layer_id ? LayerById(selection_end_.layer_id) : NULL, | |
| 1621 device_scale_factor()); | |
| 1622 } | |
| 1623 } | |
| 1624 | |
| 1625 void LayerTreeImpl::InputScrollAnimationFinished() { | |
| 1626 layer_tree_host_impl_->ScrollEnd(); | |
| 1627 } | |
| 1628 | |
| 1629 bool LayerTreeImpl::SmoothnessTakesPriority() const { | |
| 1630 return layer_tree_host_impl_->GetTreePriority() == SMOOTHNESS_TAKES_PRIORITY; | |
| 1631 } | |
| 1632 | |
| 1633 BlockingTaskRunner* LayerTreeImpl::BlockingMainThreadTaskRunner() const { | |
| 1634 return proxy()->blocking_main_thread_task_runner(); | |
| 1635 } | |
| 1636 | |
| 1637 void LayerTreeImpl::SetPendingPageScaleAnimation( | |
| 1638 scoped_ptr<PendingPageScaleAnimation> pending_animation) { | |
| 1639 pending_page_scale_animation_ = pending_animation.Pass(); | |
| 1640 } | |
| 1641 | |
| 1642 scoped_ptr<PendingPageScaleAnimation> | |
| 1643 LayerTreeImpl::TakePendingPageScaleAnimation() { | |
| 1644 return pending_page_scale_animation_.Pass(); | |
| 1645 } | |
| 1646 | |
| 1647 } // namespace cc | |
| OLD | NEW |