Adding Peter Thatcher to the owners file.
[chromium-blink-merge.git] / cc / trees / layer_tree_impl.cc
blobb831bb38b504a22eb30c3c16606a2dcf0d0f7d04
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.
5 #include "cc/trees/layer_tree_impl.h"
7 #include <algorithm>
8 #include <limits>
9 #include <set>
11 #include "base/auto_reset.h"
12 #include "base/trace_event/trace_event.h"
13 #include "base/trace_event/trace_event_argument.h"
14 #include "cc/animation/keyframed_animation_curve.h"
15 #include "cc/animation/scrollbar_animation_controller.h"
16 #include "cc/animation/scrollbar_animation_controller_linear_fade.h"
17 #include "cc/animation/scrollbar_animation_controller_thinning.h"
18 #include "cc/base/math_util.h"
19 #include "cc/base/synced_property.h"
20 #include "cc/base/util.h"
21 #include "cc/debug/devtools_instrumentation.h"
22 #include "cc/debug/traced_value.h"
23 #include "cc/input/layer_scroll_offset_delegate.h"
24 #include "cc/input/page_scale_animation.h"
25 #include "cc/layers/heads_up_display_layer_impl.h"
26 #include "cc/layers/layer.h"
27 #include "cc/layers/layer_iterator.h"
28 #include "cc/layers/render_surface_impl.h"
29 #include "cc/layers/scrollbar_layer_impl_base.h"
30 #include "cc/resources/ui_resource_request.h"
31 #include "cc/trees/layer_tree_host_common.h"
32 #include "cc/trees/layer_tree_host_impl.h"
33 #include "cc/trees/occlusion_tracker.h"
34 #include "ui/gfx/geometry/point_conversions.h"
35 #include "ui/gfx/geometry/size_conversions.h"
36 #include "ui/gfx/geometry/vector2d_conversions.h"
38 namespace cc {
40 LayerTreeImpl::LayerTreeImpl(
41 LayerTreeHostImpl* layer_tree_host_impl,
42 scoped_refptr<SyncedProperty<ScaleGroup>> page_scale_factor,
43 scoped_refptr<SyncedTopControls> top_controls_shown_ratio,
44 scoped_refptr<SyncedElasticOverscroll> elastic_overscroll)
45 : layer_tree_host_impl_(layer_tree_host_impl),
46 source_frame_number_(-1),
47 hud_layer_(0),
48 currently_scrolling_layer_(NULL),
49 root_layer_scroll_offset_delegate_(NULL),
50 background_color_(0),
51 has_transparent_background_(false),
52 overscroll_elasticity_layer_(NULL),
53 page_scale_layer_(NULL),
54 inner_viewport_scroll_layer_(NULL),
55 outer_viewport_scroll_layer_(NULL),
56 page_scale_factor_(page_scale_factor),
57 min_page_scale_factor_(0),
58 max_page_scale_factor_(0),
59 elastic_overscroll_(elastic_overscroll),
60 scrolling_layer_id_from_previous_tree_(0),
61 contents_textures_purged_(false),
62 viewport_size_invalid_(false),
63 needs_update_draw_properties_(true),
64 needs_full_tree_sync_(true),
65 next_activation_forces_redraw_(false),
66 has_ever_been_drawn_(false),
67 render_surface_layer_list_id_(0),
68 top_controls_shrink_blink_size_(false),
69 top_controls_height_(0),
70 top_controls_shown_ratio_(top_controls_shown_ratio) {
73 LayerTreeImpl::~LayerTreeImpl() {
74 BreakSwapPromises(SwapPromise::SWAP_FAILS);
76 // Need to explicitly clear the tree prior to destroying this so that
77 // the LayerTreeImpl pointer is still valid in the LayerImpl dtor.
78 DCHECK(!root_layer_);
79 DCHECK(layers_with_copy_output_request_.empty());
82 void LayerTreeImpl::Shutdown() {
83 root_layer_ = nullptr;
86 void LayerTreeImpl::ReleaseResources() {
87 if (root_layer_) {
88 LayerTreeHostCommon::CallFunctionForSubtree(
89 root_layer_.get(), [](LayerImpl* layer) { layer->ReleaseResources(); });
93 void LayerTreeImpl::RecreateResources() {
94 if (root_layer_) {
95 LayerTreeHostCommon::CallFunctionForSubtree(
96 root_layer_.get(),
97 [](LayerImpl* layer) { layer->RecreateResources(); });
101 void LayerTreeImpl::GatherFrameTimingRequestIds(
102 std::vector<int64_t>* request_ids) {
103 if (!root_layer_)
104 return;
106 // TODO(vmpstr): Early out if there are no requests on any of the layers. For
107 // that, we need to inform LayerTreeImpl whenever there are requests when we
108 // get them.
109 LayerTreeHostCommon::CallFunctionForSubtree(
110 root_layer_.get(), [request_ids](LayerImpl* layer) {
111 layer->GatherFrameTimingRequestIds(request_ids);
115 bool LayerTreeImpl::IsExternalFlingActive() const {
116 return root_layer_scroll_offset_delegate_ &&
117 root_layer_scroll_offset_delegate_->IsExternalFlingActive();
120 void LayerTreeImpl::DidUpdateScrollOffset(int layer_id) {
121 int inner_layer_id = InnerViewportScrollLayer()
122 ? InnerViewportScrollLayer()->id()
123 : Layer::INVALID_ID;
124 int outer_layer_id = OuterViewportScrollLayer()
125 ? OuterViewportScrollLayer()->id()
126 : Layer::INVALID_ID;
127 if (layer_id != outer_layer_id && layer_id != inner_layer_id)
128 return;
130 if (!root_layer_scroll_offset_delegate_)
131 return;
133 UpdateRootScrollOffsetDelegate();
136 void LayerTreeImpl::SetRootLayer(scoped_ptr<LayerImpl> layer) {
137 root_layer_ = layer.Pass();
138 currently_scrolling_layer_ = NULL;
139 inner_viewport_scroll_layer_ = NULL;
140 outer_viewport_scroll_layer_ = NULL;
141 page_scale_layer_ = NULL;
143 layer_tree_host_impl_->OnCanDrawStateChangedForTree();
146 LayerImpl* LayerTreeImpl::InnerViewportScrollLayer() const {
147 return inner_viewport_scroll_layer_;
150 LayerImpl* LayerTreeImpl::OuterViewportScrollLayer() const {
151 return outer_viewport_scroll_layer_;
154 gfx::ScrollOffset LayerTreeImpl::TotalScrollOffset() const {
155 gfx::ScrollOffset offset;
157 if (inner_viewport_scroll_layer_)
158 offset += inner_viewport_scroll_layer_->CurrentScrollOffset();
160 if (outer_viewport_scroll_layer_)
161 offset += outer_viewport_scroll_layer_->CurrentScrollOffset();
163 return offset;
166 gfx::ScrollOffset LayerTreeImpl::TotalMaxScrollOffset() const {
167 gfx::ScrollOffset offset;
169 if (inner_viewport_scroll_layer_)
170 offset += inner_viewport_scroll_layer_->MaxScrollOffset();
172 if (outer_viewport_scroll_layer_)
173 offset += outer_viewport_scroll_layer_->MaxScrollOffset();
175 return offset;
178 scoped_ptr<LayerImpl> LayerTreeImpl::DetachLayerTree() {
179 // Clear all data structures that have direct references to the layer tree.
180 scrolling_layer_id_from_previous_tree_ =
181 currently_scrolling_layer_ ? currently_scrolling_layer_->id() : 0;
182 inner_viewport_scroll_layer_ = NULL;
183 outer_viewport_scroll_layer_ = NULL;
184 page_scale_layer_ = NULL;
185 currently_scrolling_layer_ = NULL;
187 render_surface_layer_list_.clear();
188 set_needs_update_draw_properties();
189 return root_layer_.Pass();
192 void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) {
193 // The request queue should have been processed and does not require a push.
194 DCHECK_EQ(ui_resource_request_queue_.size(), 0u);
196 if (next_activation_forces_redraw_) {
197 target_tree->ForceRedrawNextActivation();
198 next_activation_forces_redraw_ = false;
201 target_tree->PassSwapPromises(&swap_promise_list_);
203 target_tree->set_top_controls_shrink_blink_size(
204 top_controls_shrink_blink_size_);
205 target_tree->set_top_controls_height(top_controls_height_);
206 target_tree->PushTopControls(nullptr);
208 // Active tree already shares the page_scale_factor object with pending
209 // tree so only the limits need to be provided.
210 target_tree->PushPageScaleFactorAndLimits(nullptr, min_page_scale_factor(),
211 max_page_scale_factor());
212 target_tree->elastic_overscroll()->PushPendingToActive();
214 target_tree->pending_page_scale_animation_ =
215 pending_page_scale_animation_.Pass();
217 if (page_scale_layer_ && inner_viewport_scroll_layer_) {
218 target_tree->SetViewportLayersFromIds(
219 overscroll_elasticity_layer_ ? overscroll_elasticity_layer_->id()
220 : Layer::INVALID_ID,
221 page_scale_layer_->id(), inner_viewport_scroll_layer_->id(),
222 outer_viewport_scroll_layer_ ? outer_viewport_scroll_layer_->id()
223 : Layer::INVALID_ID);
224 } else {
225 target_tree->ClearViewportLayers();
228 target_tree->RegisterSelection(selection_start_, selection_end_);
230 // This should match the property synchronization in
231 // LayerTreeHost::finishCommitOnImplThread().
232 target_tree->set_source_frame_number(source_frame_number());
233 target_tree->set_background_color(background_color());
234 target_tree->set_has_transparent_background(has_transparent_background());
236 if (ContentsTexturesPurged())
237 target_tree->SetContentsTexturesPurged();
238 else
239 target_tree->ResetContentsTexturesPurged();
241 if (ViewportSizeInvalid())
242 target_tree->SetViewportSizeInvalid();
243 else
244 target_tree->ResetViewportSizeInvalid();
246 if (hud_layer())
247 target_tree->set_hud_layer(static_cast<HeadsUpDisplayLayerImpl*>(
248 LayerTreeHostCommon::FindLayerInSubtree(
249 target_tree->root_layer(), hud_layer()->id())));
250 else
251 target_tree->set_hud_layer(NULL);
253 target_tree->has_ever_been_drawn_ = false;
256 LayerImpl* LayerTreeImpl::InnerViewportContainerLayer() const {
257 return inner_viewport_scroll_layer_
258 ? inner_viewport_scroll_layer_->scroll_clip_layer()
259 : NULL;
262 LayerImpl* LayerTreeImpl::OuterViewportContainerLayer() const {
263 return outer_viewport_scroll_layer_
264 ? outer_viewport_scroll_layer_->scroll_clip_layer()
265 : NULL;
268 LayerImpl* LayerTreeImpl::CurrentlyScrollingLayer() const {
269 DCHECK(IsActiveTree());
270 return currently_scrolling_layer_;
273 void LayerTreeImpl::SetCurrentlyScrollingLayer(LayerImpl* layer) {
274 if (currently_scrolling_layer_ == layer)
275 return;
277 if (currently_scrolling_layer_ &&
278 currently_scrolling_layer_->scrollbar_animation_controller())
279 currently_scrolling_layer_->scrollbar_animation_controller()
280 ->DidScrollEnd();
281 currently_scrolling_layer_ = layer;
282 if (layer && layer->scrollbar_animation_controller())
283 layer->scrollbar_animation_controller()->DidScrollBegin();
286 void LayerTreeImpl::ClearCurrentlyScrollingLayer() {
287 SetCurrentlyScrollingLayer(NULL);
288 scrolling_layer_id_from_previous_tree_ = 0;
291 namespace {
293 void ForceScrollbarParameterUpdateAfterScaleChange(LayerImpl* current_layer) {
294 if (!current_layer)
295 return;
297 while (current_layer) {
298 current_layer->ScrollbarParametersDidChange(false);
299 current_layer = current_layer->parent();
303 } // namespace
305 float LayerTreeImpl::ClampPageScaleFactorToLimits(
306 float page_scale_factor) const {
307 if (min_page_scale_factor_ && page_scale_factor < min_page_scale_factor_)
308 page_scale_factor = min_page_scale_factor_;
309 else if (max_page_scale_factor_ && page_scale_factor > max_page_scale_factor_)
310 page_scale_factor = max_page_scale_factor_;
311 return page_scale_factor;
314 void LayerTreeImpl::SetPageScaleOnActiveTree(float active_page_scale) {
315 DCHECK(IsActiveTree());
316 if (page_scale_factor()->SetCurrent(
317 ClampPageScaleFactorToLimits(active_page_scale)))
318 DidUpdatePageScale();
321 void LayerTreeImpl::PushPageScaleFromMainThread(float page_scale_factor,
322 float min_page_scale_factor,
323 float max_page_scale_factor) {
324 PushPageScaleFactorAndLimits(&page_scale_factor, min_page_scale_factor,
325 max_page_scale_factor);
328 void LayerTreeImpl::PushPageScaleFactorAndLimits(const float* page_scale_factor,
329 float min_page_scale_factor,
330 float max_page_scale_factor) {
331 DCHECK(page_scale_factor || IsActiveTree());
332 bool changed_page_scale = false;
333 if (page_scale_factor) {
334 DCHECK(!IsActiveTree() || !layer_tree_host_impl_->pending_tree());
335 changed_page_scale |=
336 page_scale_factor_->PushFromMainThread(*page_scale_factor);
338 if (IsActiveTree())
339 changed_page_scale |= page_scale_factor_->PushPendingToActive();
340 changed_page_scale |=
341 SetPageScaleFactorLimits(min_page_scale_factor, max_page_scale_factor);
343 if (changed_page_scale)
344 DidUpdatePageScale();
347 void LayerTreeImpl::set_top_controls_shrink_blink_size(bool shrink) {
348 if (top_controls_shrink_blink_size_ == shrink)
349 return;
351 top_controls_shrink_blink_size_ = shrink;
352 if (IsActiveTree())
353 layer_tree_host_impl_->UpdateViewportContainerSizes();
356 void LayerTreeImpl::set_top_controls_height(float top_controls_height) {
357 if (top_controls_height_ == top_controls_height)
358 return;
360 top_controls_height_ = top_controls_height;
361 if (IsActiveTree())
362 layer_tree_host_impl_->UpdateViewportContainerSizes();
365 bool LayerTreeImpl::SetCurrentTopControlsShownRatio(float ratio) {
366 ratio = std::max(ratio, 0.f);
367 ratio = std::min(ratio, 1.f);
368 return top_controls_shown_ratio_->SetCurrent(ratio);
371 void LayerTreeImpl::PushTopControlsFromMainThread(
372 float top_controls_shown_ratio) {
373 PushTopControls(&top_controls_shown_ratio);
376 void LayerTreeImpl::PushTopControls(const float* top_controls_shown_ratio) {
377 DCHECK(top_controls_shown_ratio || IsActiveTree());
379 if (top_controls_shown_ratio) {
380 DCHECK(!IsActiveTree() || !layer_tree_host_impl_->pending_tree());
381 top_controls_shown_ratio_->PushFromMainThread(*top_controls_shown_ratio);
383 if (IsActiveTree()) {
384 if (top_controls_shown_ratio_->PushPendingToActive())
385 layer_tree_host_impl_->DidChangeTopControlsPosition();
389 bool LayerTreeImpl::SetPageScaleFactorLimits(float min_page_scale_factor,
390 float max_page_scale_factor) {
391 if (min_page_scale_factor == min_page_scale_factor_ &&
392 max_page_scale_factor == max_page_scale_factor_)
393 return false;
395 min_page_scale_factor_ = min_page_scale_factor;
396 max_page_scale_factor_ = max_page_scale_factor;
398 return true;
401 void LayerTreeImpl::DidUpdatePageScale() {
402 if (IsActiveTree())
403 page_scale_factor()->SetCurrent(
404 ClampPageScaleFactorToLimits(current_page_scale_factor()));
406 set_needs_update_draw_properties();
408 if (root_layer_scroll_offset_delegate_) {
409 root_layer_scroll_offset_delegate_->UpdateRootLayerState(
410 TotalScrollOffset(), TotalMaxScrollOffset(), ScrollableSize(),
411 current_page_scale_factor(), min_page_scale_factor_,
412 max_page_scale_factor_);
415 ForceScrollbarParameterUpdateAfterScaleChange(page_scale_layer());
417 HideInnerViewportScrollbarsIfNearMinimumScale();
420 void LayerTreeImpl::HideInnerViewportScrollbarsIfNearMinimumScale() {
421 if (!InnerViewportContainerLayer())
422 return;
424 LayerImpl::ScrollbarSet* scrollbars =
425 InnerViewportContainerLayer()->scrollbars();
427 if (!scrollbars)
428 return;
430 for (LayerImpl::ScrollbarSet::iterator it = scrollbars->begin();
431 it != scrollbars->end();
432 ++it) {
433 ScrollbarLayerImplBase* scrollbar = *it;
434 float minimum_scale_to_show_at =
435 min_page_scale_factor() * settings().scrollbar_show_scale_threshold;
436 scrollbar->SetHideLayerAndSubtree(
437 current_page_scale_factor() < minimum_scale_to_show_at);
441 SyncedProperty<ScaleGroup>* LayerTreeImpl::page_scale_factor() {
442 return page_scale_factor_.get();
445 const SyncedProperty<ScaleGroup>* LayerTreeImpl::page_scale_factor() const {
446 return page_scale_factor_.get();
449 gfx::SizeF LayerTreeImpl::ScrollableViewportSize() const {
450 if (!InnerViewportContainerLayer())
451 return gfx::SizeF();
453 return gfx::ScaleSize(InnerViewportContainerLayer()->BoundsForScrolling(),
454 1.0f / current_page_scale_factor());
457 gfx::Rect LayerTreeImpl::RootScrollLayerDeviceViewportBounds() const {
458 LayerImpl* root_scroll_layer = OuterViewportScrollLayer()
459 ? OuterViewportScrollLayer()
460 : InnerViewportScrollLayer();
461 if (!root_scroll_layer || root_scroll_layer->children().empty())
462 return gfx::Rect();
463 LayerImpl* layer = root_scroll_layer->children()[0];
464 return MathUtil::MapEnclosingClippedRect(layer->screen_space_transform(),
465 gfx::Rect(layer->content_bounds()));
468 void LayerTreeImpl::ApplySentScrollAndScaleDeltasFromAbortedCommit() {
469 DCHECK(IsActiveTree());
471 page_scale_factor()->AbortCommit();
472 top_controls_shown_ratio()->AbortCommit();
473 elastic_overscroll()->AbortCommit();
475 if (!root_layer())
476 return;
478 LayerTreeHostCommon::CallFunctionForSubtree(
479 root_layer(), [](LayerImpl* layer) {
480 layer->ApplySentScrollDeltasFromAbortedCommit();
484 void LayerTreeImpl::SetViewportLayersFromIds(
485 int overscroll_elasticity_layer_id,
486 int page_scale_layer_id,
487 int inner_viewport_scroll_layer_id,
488 int outer_viewport_scroll_layer_id) {
489 overscroll_elasticity_layer_ = LayerById(overscroll_elasticity_layer_id);
490 page_scale_layer_ = LayerById(page_scale_layer_id);
491 DCHECK(page_scale_layer_);
493 inner_viewport_scroll_layer_ =
494 LayerById(inner_viewport_scroll_layer_id);
495 DCHECK(inner_viewport_scroll_layer_);
497 outer_viewport_scroll_layer_ =
498 LayerById(outer_viewport_scroll_layer_id);
499 DCHECK(outer_viewport_scroll_layer_ ||
500 outer_viewport_scroll_layer_id == Layer::INVALID_ID);
502 HideInnerViewportScrollbarsIfNearMinimumScale();
504 if (!root_layer_scroll_offset_delegate_)
505 return;
508 void LayerTreeImpl::ClearViewportLayers() {
509 page_scale_layer_ = NULL;
510 inner_viewport_scroll_layer_ = NULL;
511 outer_viewport_scroll_layer_ = NULL;
514 bool LayerTreeImpl::UpdateDrawProperties(bool update_lcd_text) {
515 if (!needs_update_draw_properties_)
516 return true;
518 // Calling UpdateDrawProperties must clear this flag, so there can be no
519 // early outs before this.
520 needs_update_draw_properties_ = false;
522 // For max_texture_size. When the renderer is re-created in
523 // CreateAndSetRenderer, the needs update draw properties flag is set
524 // again.
525 if (!layer_tree_host_impl_->renderer())
526 return false;
528 // Clear this after the renderer early out, as it should still be
529 // possible to hit test even without a renderer.
530 render_surface_layer_list_.clear();
532 if (!root_layer())
533 return false;
536 TRACE_EVENT2(
537 "cc", "LayerTreeImpl::UpdateDrawProperties::CalculateDrawProperties",
538 "IsActive", IsActiveTree(), "SourceFrameNumber", source_frame_number_);
539 LayerImpl* page_scale_layer =
540 page_scale_layer_ ? page_scale_layer_ : InnerViewportContainerLayer();
541 bool can_render_to_separate_surface =
542 (layer_tree_host_impl_->GetDrawMode() !=
543 DRAW_MODE_RESOURCELESS_SOFTWARE);
545 ++render_surface_layer_list_id_;
546 LayerTreeHostCommon::CalcDrawPropsImplInputs inputs(
547 root_layer(), DrawViewportSize(),
548 layer_tree_host_impl_->DrawTransform(), device_scale_factor(),
549 current_page_scale_factor(), page_scale_layer,
550 elastic_overscroll()->Current(IsActiveTree()),
551 overscroll_elasticity_layer_, resource_provider()->max_texture_size(),
552 settings().can_use_lcd_text, settings().layers_always_allowed_lcd_text,
553 can_render_to_separate_surface,
554 settings().layer_transforms_should_scale_layer_contents,
555 settings().verify_property_trees,
556 &render_surface_layer_list_, render_surface_layer_list_id_);
557 LayerTreeHostCommon::CalculateDrawProperties(&inputs);
561 TRACE_EVENT2("cc", "LayerTreeImpl::UpdateDrawProperties::Occlusion",
562 "IsActive", IsActiveTree(), "SourceFrameNumber",
563 source_frame_number_);
564 OcclusionTracker<LayerImpl> occlusion_tracker(
565 root_layer()->render_surface()->content_rect());
566 occlusion_tracker.set_minimum_tracking_size(
567 settings().minimum_occlusion_tracking_size);
569 // LayerIterator is used here instead of CallFunctionForSubtree to only
570 // UpdateTilePriorities on layers that will be visible (and thus have valid
571 // draw properties) and not because any ordering is required.
572 auto end = LayerIterator<LayerImpl>::End(&render_surface_layer_list_);
573 for (auto it = LayerIterator<LayerImpl>::Begin(&render_surface_layer_list_);
574 it != end; ++it) {
575 occlusion_tracker.EnterLayer(it);
577 // There are very few render targets so this should be cheap to do for
578 // each layer instead of something more complicated.
579 bool inside_replica = false;
580 LayerImpl* layer = it->render_target();
581 while (layer && !inside_replica) {
582 if (layer->render_target()->has_replica())
583 inside_replica = true;
584 layer = layer->render_target()->parent();
587 // Don't use occlusion if a layer will appear in a replica, since the
588 // tile raster code does not know how to look for the replica and would
589 // consider it occluded even though the replica is visible.
590 // Since occlusion is only used for browser compositor (i.e.
591 // use_occlusion_for_tile_prioritization) and it won't use replicas,
592 // this should matter not.
594 if (it.represents_itself()) {
595 Occlusion occlusion =
596 inside_replica ? Occlusion()
597 : occlusion_tracker.GetCurrentOcclusionForLayer(
598 it->draw_transform());
599 it->draw_properties().occlusion_in_content_space = occlusion;
602 if (it.represents_contributing_render_surface()) {
603 // Surfaces aren't used by the tile raster code, so they can have
604 // occlusion regardless of replicas.
605 Occlusion occlusion =
606 occlusion_tracker.GetCurrentOcclusionForContributingSurface(
607 it->render_surface()->draw_transform());
608 it->render_surface()->set_occlusion_in_content_space(occlusion);
609 // Masks are used to draw the contributing surface, so should have
610 // the same occlusion as the surface (nothing inside the surface
611 // occludes them).
612 if (LayerImpl* mask = it->mask_layer()) {
613 Occlusion mask_occlusion =
614 inside_replica
615 ? Occlusion()
616 : occlusion_tracker.GetCurrentOcclusionForContributingSurface(
617 it->render_surface()->draw_transform() *
618 it->draw_transform());
619 mask->draw_properties().occlusion_in_content_space = mask_occlusion;
621 if (LayerImpl* replica = it->replica_layer()) {
622 if (LayerImpl* mask = replica->mask_layer())
623 mask->draw_properties().occlusion_in_content_space = Occlusion();
627 occlusion_tracker.LeaveLayer(it);
630 unoccluded_screen_space_region_ =
631 occlusion_tracker.ComputeVisibleRegionInScreen();
634 // It'd be ideal if this could be done earlier, but when the raster source
635 // is updated from the main thread during push properties, update draw
636 // properties has not occurred yet and so it's not clear whether or not the
637 // layer can or cannot use lcd text. So, this is the cleanup pass to
638 // determine if the raster source needs to be replaced with a non-lcd
639 // raster source due to draw properties.
640 if (update_lcd_text) {
641 // TODO(enne): Make LTHI::sync_tree return this value.
642 LayerTreeImpl* sync_tree =
643 layer_tree_host_impl_->proxy()->CommitToActiveTree()
644 ? layer_tree_host_impl_->active_tree()
645 : layer_tree_host_impl_->pending_tree();
646 // If this is not the sync tree, then it is not safe to update lcd text
647 // as it causes invalidations and the tiles may be in use.
648 DCHECK_EQ(this, sync_tree);
649 for (const auto& layer : picture_layers_)
650 layer->UpdateCanUseLCDTextAfterCommit();
654 TRACE_EVENT_BEGIN2("cc", "LayerTreeImpl::UpdateDrawProperties::UpdateTiles",
655 "IsActive", IsActiveTree(), "SourceFrameNumber",
656 source_frame_number_);
657 const bool resourceless_software_draw =
658 (layer_tree_host_impl_->GetDrawMode() ==
659 DRAW_MODE_RESOURCELESS_SOFTWARE);
660 size_t layers_updated_count = 0;
661 bool tile_priorities_updated = false;
662 for (PictureLayerImpl* layer : picture_layers_) {
663 if (!layer->IsDrawnRenderSurfaceLayerListMember())
664 continue;
665 ++layers_updated_count;
666 tile_priorities_updated |= layer->UpdateTiles(resourceless_software_draw);
669 if (tile_priorities_updated)
670 DidModifyTilePriorities();
672 TRACE_EVENT_END1("cc", "LayerTreeImpl::UpdateTilePriorities",
673 "layers_updated_count", layers_updated_count);
676 DCHECK(!needs_update_draw_properties_) <<
677 "CalcDrawProperties should not set_needs_update_draw_properties()";
678 return true;
681 const LayerImplList& LayerTreeImpl::RenderSurfaceLayerList() const {
682 // If this assert triggers, then the list is dirty.
683 DCHECK(!needs_update_draw_properties_);
684 return render_surface_layer_list_;
687 const Region& LayerTreeImpl::UnoccludedScreenSpaceRegion() const {
688 // If this assert triggers, then the render_surface_layer_list_ is dirty, so
689 // the unoccluded_screen_space_region_ is not valid anymore.
690 DCHECK(!needs_update_draw_properties_);
691 return unoccluded_screen_space_region_;
694 gfx::Size LayerTreeImpl::ScrollableSize() const {
695 LayerImpl* root_scroll_layer = OuterViewportScrollLayer()
696 ? OuterViewportScrollLayer()
697 : InnerViewportScrollLayer();
698 if (!root_scroll_layer || root_scroll_layer->children().empty())
699 return gfx::Size();
700 return root_scroll_layer->children()[0]->bounds();
703 LayerImpl* LayerTreeImpl::LayerById(int id) {
704 LayerIdMap::iterator iter = layer_id_map_.find(id);
705 return iter != layer_id_map_.end() ? iter->second : NULL;
708 void LayerTreeImpl::RegisterLayer(LayerImpl* layer) {
709 DCHECK(!LayerById(layer->id()));
710 layer_id_map_[layer->id()] = layer;
713 void LayerTreeImpl::UnregisterLayer(LayerImpl* layer) {
714 DCHECK(LayerById(layer->id()));
715 layer_id_map_.erase(layer->id());
718 size_t LayerTreeImpl::NumLayers() {
719 return layer_id_map_.size();
722 void LayerTreeImpl::PushPersistedState(LayerTreeImpl* pending_tree) {
723 pending_tree->SetCurrentlyScrollingLayer(
724 LayerTreeHostCommon::FindLayerInSubtree(pending_tree->root_layer(),
725 currently_scrolling_layer_ ? currently_scrolling_layer_->id() : 0));
728 void LayerTreeImpl::DidBecomeActive() {
729 if (next_activation_forces_redraw_) {
730 layer_tree_host_impl_->SetFullRootLayerDamage();
731 next_activation_forces_redraw_ = false;
734 if (scrolling_layer_id_from_previous_tree_) {
735 currently_scrolling_layer_ = LayerTreeHostCommon::FindLayerInSubtree(
736 root_layer(), scrolling_layer_id_from_previous_tree_);
739 // Always reset this flag on activation, as we would only have activated
740 // if we were in a good state.
741 layer_tree_host_impl_->ResetRequiresHighResToDraw();
743 if (root_layer()) {
744 LayerTreeHostCommon::CallFunctionForSubtree(
745 root_layer(), [](LayerImpl* layer) { layer->DidBecomeActive(); });
748 devtools_instrumentation::DidActivateLayerTree(layer_tree_host_impl_->id(),
749 source_frame_number_);
752 bool LayerTreeImpl::ContentsTexturesPurged() const {
753 return contents_textures_purged_;
756 void LayerTreeImpl::SetContentsTexturesPurged() {
757 if (contents_textures_purged_)
758 return;
759 contents_textures_purged_ = true;
760 layer_tree_host_impl_->OnCanDrawStateChangedForTree();
763 void LayerTreeImpl::ResetContentsTexturesPurged() {
764 if (!contents_textures_purged_)
765 return;
766 contents_textures_purged_ = false;
767 layer_tree_host_impl_->OnCanDrawStateChangedForTree();
770 bool LayerTreeImpl::RequiresHighResToDraw() const {
771 return layer_tree_host_impl_->RequiresHighResToDraw();
774 bool LayerTreeImpl::ViewportSizeInvalid() const {
775 return viewport_size_invalid_;
778 void LayerTreeImpl::SetViewportSizeInvalid() {
779 viewport_size_invalid_ = true;
780 layer_tree_host_impl_->OnCanDrawStateChangedForTree();
783 void LayerTreeImpl::ResetViewportSizeInvalid() {
784 viewport_size_invalid_ = false;
785 layer_tree_host_impl_->OnCanDrawStateChangedForTree();
788 Proxy* LayerTreeImpl::proxy() const {
789 return layer_tree_host_impl_->proxy();
792 const LayerTreeSettings& LayerTreeImpl::settings() const {
793 return layer_tree_host_impl_->settings();
796 const LayerTreeDebugState& LayerTreeImpl::debug_state() const {
797 return layer_tree_host_impl_->debug_state();
800 const RendererCapabilitiesImpl& LayerTreeImpl::GetRendererCapabilities() const {
801 return layer_tree_host_impl_->GetRendererCapabilities();
804 ContextProvider* LayerTreeImpl::context_provider() const {
805 return output_surface()->context_provider();
808 OutputSurface* LayerTreeImpl::output_surface() const {
809 return layer_tree_host_impl_->output_surface();
812 ResourceProvider* LayerTreeImpl::resource_provider() const {
813 return layer_tree_host_impl_->resource_provider();
816 TileManager* LayerTreeImpl::tile_manager() const {
817 return layer_tree_host_impl_->tile_manager();
820 FrameRateCounter* LayerTreeImpl::frame_rate_counter() const {
821 return layer_tree_host_impl_->fps_counter();
824 PaintTimeCounter* LayerTreeImpl::paint_time_counter() const {
825 return layer_tree_host_impl_->paint_time_counter();
828 MemoryHistory* LayerTreeImpl::memory_history() const {
829 return layer_tree_host_impl_->memory_history();
832 gfx::Size LayerTreeImpl::device_viewport_size() const {
833 return layer_tree_host_impl_->device_viewport_size();
836 float LayerTreeImpl::device_scale_factor() const {
837 return layer_tree_host_impl_->device_scale_factor();
840 DebugRectHistory* LayerTreeImpl::debug_rect_history() const {
841 return layer_tree_host_impl_->debug_rect_history();
844 bool LayerTreeImpl::IsActiveTree() const {
845 return layer_tree_host_impl_->active_tree() == this;
848 bool LayerTreeImpl::IsPendingTree() const {
849 return layer_tree_host_impl_->pending_tree() == this;
852 bool LayerTreeImpl::IsRecycleTree() const {
853 return layer_tree_host_impl_->recycle_tree() == this;
856 bool LayerTreeImpl::IsSyncTree() const {
857 return layer_tree_host_impl_->sync_tree() == this;
860 LayerImpl* LayerTreeImpl::FindActiveTreeLayerById(int id) {
861 LayerTreeImpl* tree = layer_tree_host_impl_->active_tree();
862 if (!tree)
863 return NULL;
864 return tree->LayerById(id);
867 LayerImpl* LayerTreeImpl::FindPendingTreeLayerById(int id) {
868 LayerTreeImpl* tree = layer_tree_host_impl_->pending_tree();
869 if (!tree)
870 return NULL;
871 return tree->LayerById(id);
874 bool LayerTreeImpl::PinchGestureActive() const {
875 return layer_tree_host_impl_->pinch_gesture_active();
878 BeginFrameArgs LayerTreeImpl::CurrentBeginFrameArgs() const {
879 return layer_tree_host_impl_->CurrentBeginFrameArgs();
882 base::TimeDelta LayerTreeImpl::begin_impl_frame_interval() const {
883 return layer_tree_host_impl_->begin_impl_frame_interval();
886 void LayerTreeImpl::SetNeedsCommit() {
887 layer_tree_host_impl_->SetNeedsCommit();
890 gfx::Rect LayerTreeImpl::DeviceViewport() const {
891 return layer_tree_host_impl_->DeviceViewport();
894 gfx::Size LayerTreeImpl::DrawViewportSize() const {
895 return layer_tree_host_impl_->DrawViewportSize();
898 const gfx::Rect LayerTreeImpl::ViewportRectForTilePriority() const {
899 return layer_tree_host_impl_->ViewportRectForTilePriority();
902 scoped_ptr<ScrollbarAnimationController>
903 LayerTreeImpl::CreateScrollbarAnimationController(LayerImpl* scrolling_layer) {
904 DCHECK(settings().scrollbar_fade_delay_ms);
905 DCHECK(settings().scrollbar_fade_duration_ms);
906 base::TimeDelta delay =
907 base::TimeDelta::FromMilliseconds(settings().scrollbar_fade_delay_ms);
908 base::TimeDelta resize_delay = base::TimeDelta::FromMilliseconds(
909 settings().scrollbar_fade_resize_delay_ms);
910 base::TimeDelta duration =
911 base::TimeDelta::FromMilliseconds(settings().scrollbar_fade_duration_ms);
912 switch (settings().scrollbar_animator) {
913 case LayerTreeSettings::LINEAR_FADE: {
914 return ScrollbarAnimationControllerLinearFade::Create(
915 scrolling_layer,
916 layer_tree_host_impl_,
917 delay,
918 resize_delay,
919 duration);
921 case LayerTreeSettings::THINNING: {
922 return ScrollbarAnimationControllerThinning::Create(scrolling_layer,
923 layer_tree_host_impl_,
924 delay,
925 resize_delay,
926 duration);
928 case LayerTreeSettings::NO_ANIMATOR:
929 NOTREACHED();
930 break;
932 return nullptr;
935 void LayerTreeImpl::DidAnimateScrollOffset() {
936 layer_tree_host_impl_->DidAnimateScrollOffset();
939 bool LayerTreeImpl::use_gpu_rasterization() const {
940 return layer_tree_host_impl_->use_gpu_rasterization();
943 GpuRasterizationStatus LayerTreeImpl::GetGpuRasterizationStatus() const {
944 return layer_tree_host_impl_->gpu_rasterization_status();
947 bool LayerTreeImpl::create_low_res_tiling() const {
948 return layer_tree_host_impl_->create_low_res_tiling();
951 void LayerTreeImpl::SetNeedsRedraw() {
952 layer_tree_host_impl_->SetNeedsRedraw();
955 AnimationRegistrar* LayerTreeImpl::GetAnimationRegistrar() const {
956 return layer_tree_host_impl_->animation_registrar();
959 void LayerTreeImpl::GetAllTilesAndPrioritiesForTracing(
960 std::map<const Tile*, TilePriority>* tile_map) const {
961 typedef LayerIterator<LayerImpl> LayerIteratorType;
962 LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list_);
963 for (LayerIteratorType it =
964 LayerIteratorType::Begin(&render_surface_layer_list_);
965 it != end;
966 ++it) {
967 if (!it.represents_itself())
968 continue;
969 LayerImpl* layer_impl = *it;
970 layer_impl->GetAllTilesAndPrioritiesForTracing(tile_map);
974 void LayerTreeImpl::AsValueInto(base::trace_event::TracedValue* state) const {
975 TracedValue::MakeDictIntoImplicitSnapshot(state, "cc::LayerTreeImpl", this);
976 state->SetInteger("source_frame_number", source_frame_number_);
978 state->BeginDictionary("root_layer");
979 root_layer_->AsValueInto(state);
980 state->EndDictionary();
982 state->BeginArray("render_surface_layer_list");
983 typedef LayerIterator<LayerImpl> LayerIteratorType;
984 LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list_);
985 for (LayerIteratorType it = LayerIteratorType::Begin(
986 &render_surface_layer_list_); it != end; ++it) {
987 if (!it.represents_itself())
988 continue;
989 TracedValue::AppendIDRef(*it, state);
991 state->EndArray();
993 state->BeginArray("swap_promise_trace_ids");
994 for (size_t i = 0; i < swap_promise_list_.size(); i++)
995 state->AppendDouble(swap_promise_list_[i]->TraceId());
996 state->EndArray();
999 void LayerTreeImpl::SetRootLayerScrollOffsetDelegate(
1000 LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate) {
1001 if (root_layer_scroll_offset_delegate_ == root_layer_scroll_offset_delegate)
1002 return;
1004 root_layer_scroll_offset_delegate_ = root_layer_scroll_offset_delegate;
1006 if (root_layer_scroll_offset_delegate_) {
1007 root_layer_scroll_offset_delegate_->UpdateRootLayerState(
1008 TotalScrollOffset(), TotalMaxScrollOffset(), ScrollableSize(),
1009 current_page_scale_factor(), min_page_scale_factor(),
1010 max_page_scale_factor());
1012 DistributeRootScrollOffset();
1016 void LayerTreeImpl::UpdateRootScrollOffsetDelegate() {
1017 DCHECK(root_layer_scroll_offset_delegate_);
1019 gfx::ScrollOffset offset = InnerViewportScrollLayer()->CurrentScrollOffset();
1021 if (OuterViewportScrollLayer())
1022 offset += OuterViewportScrollLayer()->CurrentScrollOffset();
1024 root_layer_scroll_offset_delegate_->UpdateRootLayerState(
1025 offset, TotalMaxScrollOffset(), ScrollableSize(),
1026 current_page_scale_factor(), min_page_scale_factor(),
1027 max_page_scale_factor());
1030 void LayerTreeImpl::DistributeRootScrollOffset() {
1031 if (!root_layer_scroll_offset_delegate_)
1032 return;
1034 gfx::ScrollOffset root_offset =
1035 root_layer_scroll_offset_delegate_->GetTotalScrollOffset();
1037 if (!InnerViewportScrollLayer())
1038 return;
1040 DCHECK(OuterViewportScrollLayer());
1042 // If we get here, we have both inner/outer viewports, and need to distribute
1043 // the scroll offset between them.
1044 gfx::ScrollOffset inner_viewport_offset =
1045 InnerViewportScrollLayer()->CurrentScrollOffset();
1046 gfx::ScrollOffset outer_viewport_offset =
1047 OuterViewportScrollLayer()->CurrentScrollOffset();
1049 // It may be nothing has changed.
1050 if (inner_viewport_offset + outer_viewport_offset == root_offset)
1051 return;
1053 gfx::ScrollOffset max_outer_viewport_scroll_offset =
1054 OuterViewportScrollLayer()->MaxScrollOffset();
1056 outer_viewport_offset = root_offset - inner_viewport_offset;
1057 outer_viewport_offset.SetToMin(max_outer_viewport_scroll_offset);
1058 outer_viewport_offset.SetToMax(gfx::ScrollOffset());
1060 OuterViewportScrollLayer()->SetCurrentScrollOffsetFromDelegate(
1061 outer_viewport_offset);
1062 inner_viewport_offset = root_offset - outer_viewport_offset;
1063 InnerViewportScrollLayer()->SetCurrentScrollOffsetFromDelegate(
1064 inner_viewport_offset);
1066 UpdateRootScrollOffsetDelegate();
1069 void LayerTreeImpl::QueueSwapPromise(scoped_ptr<SwapPromise> swap_promise) {
1070 DCHECK(swap_promise);
1071 swap_promise_list_.push_back(swap_promise.Pass());
1074 void LayerTreeImpl::PassSwapPromises(
1075 ScopedPtrVector<SwapPromise>* new_swap_promise) {
1076 swap_promise_list_.insert_and_take(swap_promise_list_.end(),
1077 new_swap_promise);
1078 new_swap_promise->clear();
1081 void LayerTreeImpl::FinishSwapPromises(CompositorFrameMetadata* metadata) {
1082 for (size_t i = 0; i < swap_promise_list_.size(); i++)
1083 swap_promise_list_[i]->DidSwap(metadata);
1084 swap_promise_list_.clear();
1087 void LayerTreeImpl::BreakSwapPromises(SwapPromise::DidNotSwapReason reason) {
1088 for (size_t i = 0; i < swap_promise_list_.size(); i++)
1089 swap_promise_list_[i]->DidNotSwap(reason);
1090 swap_promise_list_.clear();
1093 void LayerTreeImpl::DidModifyTilePriorities() {
1094 layer_tree_host_impl_->DidModifyTilePriorities();
1097 void LayerTreeImpl::set_ui_resource_request_queue(
1098 const UIResourceRequestQueue& queue) {
1099 ui_resource_request_queue_ = queue;
1102 ResourceProvider::ResourceId LayerTreeImpl::ResourceIdForUIResource(
1103 UIResourceId uid) const {
1104 return layer_tree_host_impl_->ResourceIdForUIResource(uid);
1107 bool LayerTreeImpl::IsUIResourceOpaque(UIResourceId uid) const {
1108 return layer_tree_host_impl_->IsUIResourceOpaque(uid);
1111 void LayerTreeImpl::ProcessUIResourceRequestQueue() {
1112 for (const auto& req : ui_resource_request_queue_) {
1113 switch (req.GetType()) {
1114 case UIResourceRequest::UI_RESOURCE_CREATE:
1115 layer_tree_host_impl_->CreateUIResource(req.GetId(), req.GetBitmap());
1116 break;
1117 case UIResourceRequest::UI_RESOURCE_DELETE:
1118 layer_tree_host_impl_->DeleteUIResource(req.GetId());
1119 break;
1120 case UIResourceRequest::UI_RESOURCE_INVALID_REQUEST:
1121 NOTREACHED();
1122 break;
1125 ui_resource_request_queue_.clear();
1127 // If all UI resource evictions were not recreated by processing this queue,
1128 // then another commit is required.
1129 if (layer_tree_host_impl_->EvictedUIResourcesExist())
1130 layer_tree_host_impl_->SetNeedsCommit();
1133 void LayerTreeImpl::RegisterPictureLayerImpl(PictureLayerImpl* layer) {
1134 DCHECK(std::find(picture_layers_.begin(), picture_layers_.end(), layer) ==
1135 picture_layers_.end());
1136 picture_layers_.push_back(layer);
1139 void LayerTreeImpl::UnregisterPictureLayerImpl(PictureLayerImpl* layer) {
1140 std::vector<PictureLayerImpl*>::iterator it =
1141 std::find(picture_layers_.begin(), picture_layers_.end(), layer);
1142 DCHECK(it != picture_layers_.end());
1143 picture_layers_.erase(it);
1146 void LayerTreeImpl::AddLayerWithCopyOutputRequest(LayerImpl* layer) {
1147 // Only the active tree needs to know about layers with copy requests, as
1148 // they are aborted if not serviced during draw.
1149 DCHECK(IsActiveTree());
1151 // DCHECK(std::find(layers_with_copy_output_request_.begin(),
1152 // layers_with_copy_output_request_.end(),
1153 // layer) == layers_with_copy_output_request_.end());
1154 // TODO(danakj): Remove this once crash is found crbug.com/309777
1155 for (size_t i = 0; i < layers_with_copy_output_request_.size(); ++i) {
1156 CHECK(layers_with_copy_output_request_[i] != layer)
1157 << i << " of " << layers_with_copy_output_request_.size();
1159 layers_with_copy_output_request_.push_back(layer);
1162 void LayerTreeImpl::RemoveLayerWithCopyOutputRequest(LayerImpl* layer) {
1163 // Only the active tree needs to know about layers with copy requests, as
1164 // they are aborted if not serviced during draw.
1165 DCHECK(IsActiveTree());
1167 std::vector<LayerImpl*>::iterator it = std::find(
1168 layers_with_copy_output_request_.begin(),
1169 layers_with_copy_output_request_.end(),
1170 layer);
1171 DCHECK(it != layers_with_copy_output_request_.end());
1172 layers_with_copy_output_request_.erase(it);
1174 // TODO(danakj): Remove this once crash is found crbug.com/309777
1175 for (size_t i = 0; i < layers_with_copy_output_request_.size(); ++i) {
1176 CHECK(layers_with_copy_output_request_[i] != layer)
1177 << i << " of " << layers_with_copy_output_request_.size();
1181 const std::vector<LayerImpl*>& LayerTreeImpl::LayersWithCopyOutputRequest()
1182 const {
1183 // Only the active tree needs to know about layers with copy requests, as
1184 // they are aborted if not serviced during draw.
1185 DCHECK(IsActiveTree());
1187 return layers_with_copy_output_request_;
1190 template <typename LayerType>
1191 static inline bool LayerClipsSubtree(LayerType* layer) {
1192 return layer->masks_to_bounds() || layer->mask_layer();
1195 static bool PointHitsRect(
1196 const gfx::PointF& screen_space_point,
1197 const gfx::Transform& local_space_to_screen_space_transform,
1198 const gfx::RectF& local_space_rect,
1199 float* distance_to_camera) {
1200 // If the transform is not invertible, then assume that this point doesn't hit
1201 // this rect.
1202 gfx::Transform inverse_local_space_to_screen_space(
1203 gfx::Transform::kSkipInitialization);
1204 if (!local_space_to_screen_space_transform.GetInverse(
1205 &inverse_local_space_to_screen_space))
1206 return false;
1208 // Transform the hit test point from screen space to the local space of the
1209 // given rect.
1210 bool clipped = false;
1211 gfx::Point3F planar_point = MathUtil::ProjectPoint3D(
1212 inverse_local_space_to_screen_space, screen_space_point, &clipped);
1213 gfx::PointF hit_test_point_in_local_space =
1214 gfx::PointF(planar_point.x(), planar_point.y());
1216 // If ProjectPoint could not project to a valid value, then we assume that
1217 // this point doesn't hit this rect.
1218 if (clipped)
1219 return false;
1221 if (!local_space_rect.Contains(hit_test_point_in_local_space))
1222 return false;
1224 if (distance_to_camera) {
1225 // To compute the distance to the camera, we have to take the planar point
1226 // and pull it back to world space and compute the displacement along the
1227 // z-axis.
1228 gfx::Point3F planar_point_in_screen_space(planar_point);
1229 local_space_to_screen_space_transform.TransformPoint(
1230 &planar_point_in_screen_space);
1231 *distance_to_camera = planar_point_in_screen_space.z();
1234 return true;
1237 static bool PointHitsRegion(const gfx::PointF& screen_space_point,
1238 const gfx::Transform& screen_space_transform,
1239 const Region& layer_space_region,
1240 float layer_content_scale_x,
1241 float layer_content_scale_y) {
1242 // If the transform is not invertible, then assume that this point doesn't hit
1243 // this region.
1244 gfx::Transform inverse_screen_space_transform(
1245 gfx::Transform::kSkipInitialization);
1246 if (!screen_space_transform.GetInverse(&inverse_screen_space_transform))
1247 return false;
1249 // Transform the hit test point from screen space to the local space of the
1250 // given region.
1251 bool clipped = false;
1252 gfx::PointF hit_test_point_in_content_space = MathUtil::ProjectPoint(
1253 inverse_screen_space_transform, screen_space_point, &clipped);
1254 gfx::PointF hit_test_point_in_layer_space =
1255 gfx::ScalePoint(hit_test_point_in_content_space,
1256 1.f / layer_content_scale_x,
1257 1.f / layer_content_scale_y);
1259 // If ProjectPoint could not project to a valid value, then we assume that
1260 // this point doesn't hit this region.
1261 if (clipped)
1262 return false;
1264 return layer_space_region.Contains(
1265 gfx::ToRoundedPoint(hit_test_point_in_layer_space));
1268 static const LayerImpl* GetNextClippingLayer(const LayerImpl* layer) {
1269 if (layer->scroll_parent())
1270 return layer->scroll_parent();
1271 if (layer->clip_parent())
1272 return layer->clip_parent();
1273 return layer->parent();
1276 static bool PointIsClippedBySurfaceOrClipRect(
1277 const gfx::PointF& screen_space_point,
1278 const LayerImpl* layer) {
1279 // Walk up the layer tree and hit-test any render_surfaces and any layer
1280 // clip rects that are active.
1281 for (; layer; layer = GetNextClippingLayer(layer)) {
1282 if (layer->render_surface() &&
1283 !PointHitsRect(screen_space_point,
1284 layer->render_surface()->screen_space_transform(),
1285 layer->render_surface()->content_rect(),
1286 NULL))
1287 return true;
1289 if (LayerClipsSubtree(layer) &&
1290 !PointHitsRect(screen_space_point,
1291 layer->screen_space_transform(),
1292 gfx::Rect(layer->content_bounds()),
1293 NULL))
1294 return true;
1297 // If we have finished walking all ancestors without having already exited,
1298 // then the point is not clipped by any ancestors.
1299 return false;
1302 static bool PointHitsLayer(const LayerImpl* layer,
1303 const gfx::PointF& screen_space_point,
1304 float* distance_to_intersection) {
1305 gfx::RectF content_rect(layer->content_bounds());
1306 if (!PointHitsRect(screen_space_point,
1307 layer->screen_space_transform(),
1308 content_rect,
1309 distance_to_intersection))
1310 return false;
1312 // At this point, we think the point does hit the layer, but we need to walk
1313 // up the parents to ensure that the layer was not clipped in such a way
1314 // that the hit point actually should not hit the layer.
1315 if (PointIsClippedBySurfaceOrClipRect(screen_space_point, layer))
1316 return false;
1318 // Skip the HUD layer.
1319 if (layer == layer->layer_tree_impl()->hud_layer())
1320 return false;
1322 return true;
1325 struct FindClosestMatchingLayerDataForRecursion {
1326 FindClosestMatchingLayerDataForRecursion()
1327 : closest_match(NULL),
1328 closest_distance(-std::numeric_limits<float>::infinity()) {}
1329 LayerImpl* closest_match;
1330 // Note that the positive z-axis points towards the camera, so bigger means
1331 // closer in this case, counterintuitively.
1332 float closest_distance;
1335 template <typename Functor>
1336 static void FindClosestMatchingLayer(
1337 const gfx::PointF& screen_space_point,
1338 LayerImpl* layer,
1339 const Functor& func,
1340 FindClosestMatchingLayerDataForRecursion* data_for_recursion) {
1341 for (int i = layer->children().size() - 1; i >= 0; --i) {
1342 FindClosestMatchingLayer(
1343 screen_space_point, layer->children()[i], func, data_for_recursion);
1346 float distance_to_intersection = 0.f;
1347 if (func(layer) &&
1348 PointHitsLayer(layer, screen_space_point, &distance_to_intersection) &&
1349 ((!data_for_recursion->closest_match ||
1350 distance_to_intersection > data_for_recursion->closest_distance))) {
1351 data_for_recursion->closest_distance = distance_to_intersection;
1352 data_for_recursion->closest_match = layer;
1356 static bool ScrollsAnyDrawnRenderSurfaceLayerListMember(LayerImpl* layer) {
1357 if (!layer->scrollable())
1358 return false;
1359 if (layer->draw_properties().layer_or_descendant_is_drawn)
1360 return true;
1362 if (!layer->scroll_children())
1363 return false;
1364 for (std::set<LayerImpl*>::const_iterator it =
1365 layer->scroll_children()->begin();
1366 it != layer->scroll_children()->end();
1367 ++it) {
1368 if ((*it)->draw_properties().layer_or_descendant_is_drawn)
1369 return true;
1371 return false;
1374 struct FindScrollingLayerFunctor {
1375 bool operator()(LayerImpl* layer) const {
1376 return ScrollsAnyDrawnRenderSurfaceLayerListMember(layer);
1380 LayerImpl* LayerTreeImpl::FindFirstScrollingLayerThatIsHitByPoint(
1381 const gfx::PointF& screen_space_point) {
1382 FindClosestMatchingLayerDataForRecursion data_for_recursion;
1383 FindClosestMatchingLayer(screen_space_point,
1384 root_layer(),
1385 FindScrollingLayerFunctor(),
1386 &data_for_recursion);
1387 return data_for_recursion.closest_match;
1390 struct HitTestVisibleScrollableOrTouchableFunctor {
1391 bool operator()(LayerImpl* layer) const {
1392 return layer->IsDrawnRenderSurfaceLayerListMember() ||
1393 ScrollsAnyDrawnRenderSurfaceLayerListMember(layer) ||
1394 !layer->touch_event_handler_region().IsEmpty() ||
1395 layer->have_wheel_event_handlers();
1399 LayerImpl* LayerTreeImpl::FindLayerThatIsHitByPoint(
1400 const gfx::PointF& screen_space_point) {
1401 if (!root_layer())
1402 return NULL;
1403 bool update_lcd_text = false;
1404 if (!UpdateDrawProperties(update_lcd_text))
1405 return NULL;
1406 FindClosestMatchingLayerDataForRecursion data_for_recursion;
1407 FindClosestMatchingLayer(screen_space_point,
1408 root_layer(),
1409 HitTestVisibleScrollableOrTouchableFunctor(),
1410 &data_for_recursion);
1411 return data_for_recursion.closest_match;
1414 static bool LayerHasTouchEventHandlersAt(const gfx::PointF& screen_space_point,
1415 LayerImpl* layer_impl) {
1416 if (layer_impl->touch_event_handler_region().IsEmpty())
1417 return false;
1419 if (!PointHitsRegion(screen_space_point,
1420 layer_impl->screen_space_transform(),
1421 layer_impl->touch_event_handler_region(),
1422 layer_impl->contents_scale_x(),
1423 layer_impl->contents_scale_y()))
1424 return false;
1426 // At this point, we think the point does hit the touch event handler region
1427 // on the layer, but we need to walk up the parents to ensure that the layer
1428 // was not clipped in such a way that the hit point actually should not hit
1429 // the layer.
1430 if (PointIsClippedBySurfaceOrClipRect(screen_space_point, layer_impl))
1431 return false;
1433 return true;
1436 struct FindWheelEventLayerFunctor {
1437 bool operator()(LayerImpl* layer) const {
1438 return layer->have_wheel_event_handlers();
1442 LayerImpl* LayerTreeImpl::FindLayerWithWheelHandlerThatIsHitByPoint(
1443 const gfx::PointF& screen_space_point) {
1444 if (!root_layer())
1445 return NULL;
1446 bool update_lcd_text = false;
1447 if (!UpdateDrawProperties(update_lcd_text))
1448 return NULL;
1449 FindWheelEventLayerFunctor func;
1450 FindClosestMatchingLayerDataForRecursion data_for_recursion;
1451 FindClosestMatchingLayer(screen_space_point, root_layer(), func,
1452 &data_for_recursion);
1453 return data_for_recursion.closest_match;
1456 struct FindTouchEventLayerFunctor {
1457 bool operator()(LayerImpl* layer) const {
1458 return LayerHasTouchEventHandlersAt(screen_space_point, layer);
1460 const gfx::PointF screen_space_point;
1463 LayerImpl* LayerTreeImpl::FindLayerThatIsHitByPointInTouchHandlerRegion(
1464 const gfx::PointF& screen_space_point) {
1465 if (!root_layer())
1466 return NULL;
1467 bool update_lcd_text = false;
1468 if (!UpdateDrawProperties(update_lcd_text))
1469 return NULL;
1470 FindTouchEventLayerFunctor func = {screen_space_point};
1471 FindClosestMatchingLayerDataForRecursion data_for_recursion;
1472 FindClosestMatchingLayer(
1473 screen_space_point, root_layer(), func, &data_for_recursion);
1474 return data_for_recursion.closest_match;
1477 void LayerTreeImpl::RegisterSelection(const LayerSelectionBound& start,
1478 const LayerSelectionBound& end) {
1479 selection_start_ = start;
1480 selection_end_ = end;
1483 static ViewportSelectionBound ComputeViewportSelection(
1484 const LayerSelectionBound& layer_bound,
1485 LayerImpl* layer,
1486 float device_scale_factor) {
1487 ViewportSelectionBound viewport_bound;
1488 viewport_bound.type = layer_bound.type;
1490 if (!layer || layer_bound.type == SELECTION_BOUND_EMPTY)
1491 return viewport_bound;
1493 gfx::PointF layer_scaled_top = gfx::ScalePoint(layer_bound.edge_top,
1494 layer->contents_scale_x(),
1495 layer->contents_scale_y());
1496 gfx::PointF layer_scaled_bottom = gfx::ScalePoint(layer_bound.edge_bottom,
1497 layer->contents_scale_x(),
1498 layer->contents_scale_y());
1500 bool clipped = false;
1501 gfx::PointF screen_top = MathUtil::MapPoint(
1502 layer->screen_space_transform(), layer_scaled_top, &clipped);
1503 gfx::PointF screen_bottom = MathUtil::MapPoint(
1504 layer->screen_space_transform(), layer_scaled_bottom, &clipped);
1506 const float inv_scale = 1.f / device_scale_factor;
1507 viewport_bound.edge_top = gfx::ScalePoint(screen_top, inv_scale);
1508 viewport_bound.edge_bottom = gfx::ScalePoint(screen_bottom, inv_scale);
1510 // The bottom edge point is used for visibility testing as it is the logical
1511 // focal point for bound selection handles (this may change in the future).
1512 // Shifting the visibility point fractionally inward ensures that neighboring
1513 // or logically coincident layers aligned to integral DPI coordinates will not
1514 // spuriously occlude the bound.
1515 gfx::Vector2dF visibility_offset = layer_scaled_top - layer_scaled_bottom;
1516 visibility_offset.Scale(device_scale_factor / visibility_offset.Length());
1517 gfx::PointF visibility_point = layer_scaled_bottom + visibility_offset;
1518 if (visibility_point.x() <= 0)
1519 visibility_point.set_x(visibility_point.x() + device_scale_factor);
1520 visibility_point = MathUtil::MapPoint(
1521 layer->screen_space_transform(), visibility_point, &clipped);
1523 float intersect_distance = 0.f;
1524 viewport_bound.visible =
1525 PointHitsLayer(layer, visibility_point, &intersect_distance);
1527 return viewport_bound;
1530 void LayerTreeImpl::GetViewportSelection(ViewportSelectionBound* start,
1531 ViewportSelectionBound* end) {
1532 DCHECK(start);
1533 DCHECK(end);
1535 *start = ComputeViewportSelection(
1536 selection_start_,
1537 selection_start_.layer_id ? LayerById(selection_start_.layer_id) : NULL,
1538 device_scale_factor());
1539 if (start->type == SELECTION_BOUND_CENTER ||
1540 start->type == SELECTION_BOUND_EMPTY) {
1541 *end = *start;
1542 } else {
1543 *end = ComputeViewportSelection(
1544 selection_end_,
1545 selection_end_.layer_id ? LayerById(selection_end_.layer_id) : NULL,
1546 device_scale_factor());
1550 void LayerTreeImpl::InputScrollAnimationFinished() {
1551 layer_tree_host_impl_->ScrollEnd();
1554 bool LayerTreeImpl::SmoothnessTakesPriority() const {
1555 return layer_tree_host_impl_->GetTreePriority() == SMOOTHNESS_TAKES_PRIORITY;
1558 BlockingTaskRunner* LayerTreeImpl::BlockingMainThreadTaskRunner() const {
1559 return proxy()->blocking_main_thread_task_runner();
1562 void LayerTreeImpl::SetPendingPageScaleAnimation(
1563 scoped_ptr<PendingPageScaleAnimation> pending_animation) {
1564 pending_page_scale_animation_ = pending_animation.Pass();
1567 scoped_ptr<PendingPageScaleAnimation>
1568 LayerTreeImpl::TakePendingPageScaleAnimation() {
1569 return pending_page_scale_animation_.Pass();
1572 } // namespace cc