diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-07-12 14:07:37 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-07-17 10:29:26 +0000 |
commit | ec02ee4181c49b61fce1c8fb99292dbb8139cc90 (patch) | |
tree | 25cde714b2b71eb639d1cd53f5a22e9ba76e14ef /chromium/cc/trees | |
parent | bb09965444b5bb20b096a291445170876225268d (diff) |
BASELINE: Update Chromium to 59.0.3071.134
Change-Id: Id02ef6fb2204c5fd21668a1c3e6911c83b17585a
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/cc/trees')
70 files changed, 4378 insertions, 3155 deletions
diff --git a/chromium/cc/trees/blocking_task_runner.h b/chromium/cc/trees/blocking_task_runner.h index 515cb258945..d34e2f20cd4 100644 --- a/chromium/cc/trees/blocking_task_runner.h +++ b/chromium/cc/trees/blocking_task_runner.h @@ -13,7 +13,7 @@ #include "base/single_thread_task_runner.h" #include "base/synchronization/lock.h" #include "base/threading/platform_thread.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace cc { diff --git a/chromium/cc/trees/clip_expander.h b/chromium/cc/trees/clip_expander.h index 781d489ba04..209477a2553 100644 --- a/chromium/cc/trees/clip_expander.h +++ b/chromium/cc/trees/clip_expander.h @@ -5,7 +5,7 @@ #ifndef CC_TREES_CLIP_EXPANDER_H_ #define CC_TREES_CLIP_EXPANDER_H_ -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "ui/gfx/geometry/rect.h" namespace cc { diff --git a/chromium/cc/trees/clip_node.cc b/chromium/cc/trees/clip_node.cc index d3c1863d448..c8d2eff7f65 100644 --- a/chromium/cc/trees/clip_node.cc +++ b/chromium/cc/trees/clip_node.cc @@ -15,14 +15,10 @@ ClipNode::ClipNode() : id(ClipTree::kInvalidNodeId), parent_id(ClipTree::kInvalidNodeId), owning_layer_id(Layer::INVALID_ID), - clip_type(ClipType::NONE), - transform_id(TransformTree::kInvalidNodeId), - target_transform_id(TransformTree::kInvalidNodeId), - target_effect_id(EffectTree::kInvalidNodeId), - layer_clipping_uses_only_local_clip(false), - layers_are_clipped(false), - layers_are_clipped_when_surfaces_disabled(false), - resets_clip(false) {} + clip_type(ClipType::APPLIES_LOCAL_CLIP), + transform_id(TransformTree::kInvalidNodeId) { + cached_clip_rects = std::vector<ClipRectData>(defaultCachedClipsSize); +} ClipNode::ClipNode(const ClipNode& other) : id(other.id), @@ -30,21 +26,14 @@ ClipNode::ClipNode(const ClipNode& other) owning_layer_id(other.owning_layer_id), clip_type(other.clip_type), clip(other.clip), - combined_clip_in_target_space(other.combined_clip_in_target_space), - clip_in_target_space(other.clip_in_target_space), - transform_id(other.transform_id), - target_transform_id(other.target_transform_id), - target_effect_id(other.target_effect_id), - layer_clipping_uses_only_local_clip( - other.layer_clipping_uses_only_local_clip), - layers_are_clipped(other.layers_are_clipped), - layers_are_clipped_when_surfaces_disabled( - other.layers_are_clipped_when_surfaces_disabled), - resets_clip(other.resets_clip) { + transform_id(other.transform_id) { if (other.clip_expander) { DCHECK_EQ(clip_type, ClipType::EXPANDS_CLIP); clip_expander = base::MakeUnique<ClipExpander>(*other.clip_expander); } + cached_clip_rects = other.cached_clip_rects; + cached_accumulated_rect_in_screen_space = + other.cached_accumulated_rect_in_screen_space; } ClipNode& ClipNode::operator=(const ClipNode& other) { @@ -53,17 +42,7 @@ ClipNode& ClipNode::operator=(const ClipNode& other) { owning_layer_id = other.owning_layer_id; clip_type = other.clip_type; clip = other.clip; - combined_clip_in_target_space = other.combined_clip_in_target_space; - clip_in_target_space = other.clip_in_target_space; transform_id = other.transform_id; - target_transform_id = other.target_transform_id; - target_effect_id = other.target_effect_id; - layer_clipping_uses_only_local_clip = - other.layer_clipping_uses_only_local_clip; - layers_are_clipped = other.layers_are_clipped; - layers_are_clipped_when_surfaces_disabled = - other.layers_are_clipped_when_surfaces_disabled; - resets_clip = other.resets_clip; if (other.clip_expander) { DCHECK_EQ(clip_type, ClipType::EXPANDS_CLIP); @@ -71,7 +50,9 @@ ClipNode& ClipNode::operator=(const ClipNode& other) { } else { clip_expander.reset(); } - + cached_clip_rects = other.cached_clip_rects; + cached_accumulated_rect_in_screen_space = + other.cached_accumulated_rect_in_screen_space; return *this; } @@ -87,17 +68,7 @@ bool ClipNode::operator==(const ClipNode& other) const { return id == other.id && parent_id == other.parent_id && owning_layer_id == other.owning_layer_id && clip_type == other.clip_type && clip == other.clip && - combined_clip_in_target_space == other.combined_clip_in_target_space && - clip_in_target_space == other.clip_in_target_space && - transform_id == other.transform_id && - target_transform_id == other.target_transform_id && - target_effect_id == other.target_effect_id && - layer_clipping_uses_only_local_clip == - other.layer_clipping_uses_only_local_clip && - layers_are_clipped == other.layers_are_clipped && - layers_are_clipped_when_surfaces_disabled == - other.layers_are_clipped_when_surfaces_disabled && - resets_clip == other.resets_clip; + transform_id == other.transform_id; } void ClipNode::AsValueInto(base::trace_event::TracedValue* value) const { @@ -107,14 +78,6 @@ void ClipNode::AsValueInto(base::trace_event::TracedValue* value) const { value->SetInteger("clip_type", static_cast<int>(clip_type)); MathUtil::AddToTracedValue("clip", clip, value); value->SetInteger("transform_id", transform_id); - value->SetInteger("target_transform_id", target_transform_id); - value->SetInteger("target_effect_id", target_effect_id); - value->SetBoolean("layer_clipping_uses_only_local_clip", - layer_clipping_uses_only_local_clip); - value->SetBoolean("layers_are_clipped", layers_are_clipped); - value->SetBoolean("layers_are_clipped_when_surfaces_disabled", - layers_are_clipped_when_surfaces_disabled); - value->SetBoolean("resets_clip", resets_clip); } } // namespace cc diff --git a/chromium/cc/trees/clip_node.h b/chromium/cc/trees/clip_node.h index b81c72c235e..5c204549d1c 100644 --- a/chromium/cc/trees/clip_node.h +++ b/chromium/cc/trees/clip_node.h @@ -7,7 +7,7 @@ #include <memory> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/trees/clip_expander.h" #include "ui/gfx/geometry/rect_f.h" @@ -27,6 +27,8 @@ struct CC_EXPORT ClipNode { ~ClipNode(); + static const int defaultCachedClipsSize = 1; + // The node index of this node in the clip tree node vector. int id; // The node index of the parent node in the clip tree node vector. @@ -35,10 +37,6 @@ struct CC_EXPORT ClipNode { int owning_layer_id; enum class ClipType { - // The node doesn't contribute a new clip. It exists only for caching clips - // or for resetting clipping state. - NONE, - // The node contributes a new clip (that is, |clip| needs to be applied). APPLIES_LOCAL_CLIP, @@ -57,46 +55,20 @@ struct CC_EXPORT ClipNode { // transform node. gfx::RectF clip; + // Each element of this cache stores the accumulated clip from this clip + // node to a particular target. + mutable std::vector<ClipRectData> cached_clip_rects; + + // This rect accumulates all clips from this node to the root in screen space. + // It is used in the computation of layer's visible rect. + gfx::RectF cached_accumulated_rect_in_screen_space; + // For nodes that expand, this represents the amount of expansion. std::unique_ptr<ClipExpander> clip_expander; - // Clip nodes are used for two reasons. First, they are used for determining - // which parts of each layer are visible. Second, they are used for - // determining whether a clip needs to be applied when drawing a layer, and if - // so, the rect that needs to be used. These can be different since not all - // clips need to be applied directly to each layer. For example, a layer is - // implicitly clipped by the bounds of its target render surface and by clips - // applied to this surface. |combined_clip_in_target_space| is used for - // computing visible rects, and |clip_in_target_space| is used for computing - // clips applied at draw time. Both rects are expressed in the space of the - // target transform node, and may include clips contributed by ancestors. - gfx::RectF combined_clip_in_target_space; - gfx::RectF clip_in_target_space; - // The id of the transform node that defines the clip node's local space. int transform_id; - // The id of the transform node that defines the clip node's target space. - int target_transform_id; - - // The id of the effect node that defines the clip node's target space. - // TODO(crbug.com/642581 crbug.com/642584): As we progress toward SPv2 and - // layer list mode, there may be layers having the same clip but draw onto - // different target. Target information shall be removed from here. - int target_effect_id; - - // When true, |clip_in_target_space| does not include clips from ancestor - // nodes. - bool layer_clipping_uses_only_local_clip : 1; - - // True if layers with this clip tree node need to be drawn with a clip - // applied. - bool layers_are_clipped : 1; - bool layers_are_clipped_when_surfaces_disabled : 1; - - // Nodes that correspond to unclipped surfaces disregard ancestor clips. - bool resets_clip : 1; - bool operator==(const ClipNode& other) const; void AsValueInto(base::trace_event::TracedValue* value) const; diff --git a/chromium/cc/trees/damage_tracker.cc b/chromium/cc/trees/damage_tracker.cc index ae311dd2cfd..aa4a6236801 100644 --- a/chromium/cc/trees/damage_tracker.cc +++ b/chromium/cc/trees/damage_tracker.cc @@ -9,11 +9,11 @@ #include <algorithm> #include "base/memory/ptr_util.h" +#include "cc/base/filter_operations.h" #include "cc/base/math_util.h" #include "cc/layers/heads_up_display_layer_impl.h" #include "cc/layers/layer_impl.h" #include "cc/layers/render_surface_impl.h" -#include "cc/output/filter_operations.h" #include "cc/trees/layer_tree_host_common.h" #include "cc/trees/layer_tree_impl.h" #include "ui/gfx/geometry/rect_conversions.h" @@ -128,8 +128,8 @@ void DamageTracker::UpdateDamageTrackingState( gfx::Rect damage_rect; bool is_rect_valid = damage_for_this_update.GetAsRect(&damage_rect); if (is_rect_valid) { - damage_rect = filters.MapRect( - damage_rect, target_surface->FiltersTransform().matrix()); + damage_rect = + filters.MapRect(damage_rect, target_surface->SurfaceScale().matrix()); damage_for_this_update = DamageAccumulator(); damage_for_this_update.Union(damage_rect); } diff --git a/chromium/cc/trees/damage_tracker.h b/chromium/cc/trees/damage_tracker.h index e41a1cf8573..6ddc504dafa 100644 --- a/chromium/cc/trees/damage_tracker.h +++ b/chromium/cc/trees/damage_tracker.h @@ -9,7 +9,7 @@ #include <vector> #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/layer_collections.h" #include "ui/gfx/geometry/rect.h" diff --git a/chromium/cc/trees/damage_tracker_unittest.cc b/chromium/cc/trees/damage_tracker_unittest.cc index 13f8742476f..91cec6dc030 100644 --- a/chromium/cc/trees/damage_tracker_unittest.cc +++ b/chromium/cc/trees/damage_tracker_unittest.cc @@ -6,10 +6,10 @@ #include <stddef.h> +#include "cc/base/filter_operation.h" +#include "cc/base/filter_operations.h" #include "cc/base/math_util.h" #include "cc/layers/layer_impl.h" -#include "cc/output/filter_operation.h" -#include "cc/output/filter_operations.h" #include "cc/test/fake_impl_task_runner_provider.h" #include "cc/test/fake_layer_tree_host_impl.h" #include "cc/test/geometry_test_utils.h" @@ -27,18 +27,14 @@ namespace { void ExecuteCalculateDrawProperties(LayerImpl* root, float device_scale_factor, - bool skip_verify_visible_rect_calculations, LayerImplList* render_surface_layer_list) { // Sanity check: The test itself should create the root layer's render // surface, so that the surface (and its damage tracker) can // persist across multiple calls to this function. ASSERT_FALSE(render_surface_layer_list->size()); - FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(root); LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( root, root->bounds(), device_scale_factor, render_surface_layer_list); - if (skip_verify_visible_rect_calculations) - inputs.verify_visible_rect_calculations = false; LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); ASSERT_TRUE(root->GetRenderSurface()); } @@ -50,10 +46,7 @@ void ClearDamageForAllSurfaces(LayerImpl* root) { } } -void EmulateDrawingOneFrame( - LayerImpl* root, - float device_scale_factor = 1.f, - bool skip_verify_visible_rect_calculations = false) { +void EmulateDrawingOneFrame(LayerImpl* root, float device_scale_factor = 1.f) { // This emulates only steps that are relevant to testing the damage tracker: // 1. computing the render passes and layerlists // 2. updating all damage trackers in the correct order @@ -62,7 +55,6 @@ void EmulateDrawingOneFrame( LayerImplList render_surface_layer_list; ExecuteCalculateDrawProperties(root, device_scale_factor, - skip_verify_visible_rect_calculations, &render_surface_layer_list); // Iterate back-to-front, so that damage correctly propagates from descendant @@ -106,6 +98,7 @@ class DamageTrackerTest : public testing::Test { root->test_properties()->AddChild(std::move(child)); } host_impl_.active_tree()->SetRootLayerForTesting(std::move(root)); + host_impl_.active_tree()->SetElementIdsForTesting(); return host_impl_.active_tree()->root_layer_for_testing(); } @@ -157,6 +150,7 @@ class DamageTrackerTest : public testing::Test { root->test_properties()->AddChild(std::move(child1)); root->test_properties()->AddChild(std::move(child2)); host_impl_.active_tree()->SetRootLayerForTesting(std::move(root)); + host_impl_.active_tree()->SetElementIdsForTesting(); return host_impl_.active_tree()->root_layer_for_testing(); } @@ -393,8 +387,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForPropertyChanges) { EmulateDrawingOneFrame(root); ClearDamageForAllSurfaces(root); child->SetUpdateRect(gfx::Rect(10, 11, 12, 13)); - root->layer_tree_impl()->property_trees()->effect_tree.OnOpacityAnimated( - 0.5f, child->effect_tree_index(), root->layer_tree_impl()); + root->layer_tree_impl()->SetOpacityMutated(child->element_id(), 0.5f); EmulateDrawingOneFrame(root); ASSERT_EQ(2u, root->GetRenderSurface()->layer_list().size()); @@ -423,8 +416,8 @@ TEST_F(DamageTrackerTest, VerifyDamageForPropertyChanges) { ClearDamageForAllSurfaces(root); gfx::Transform translation; translation.Translate(100.f, 130.f); - root->layer_tree_impl()->property_trees()->transform_tree.OnTransformAnimated( - translation, child->transform_tree_index(), root->layer_tree_impl()); + root->layer_tree_impl()->SetTransformMutated(child->element_id(), + translation); EmulateDrawingOneFrame(root); // Expect damage to be the combination of the previous one and the new one. @@ -482,8 +475,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForTransformedLayer) { // With the anchor on the layer's center, now we can test the rotation more // intuitively, since it applies about the layer's anchor. ClearDamageForAllSurfaces(root); - root->layer_tree_impl()->property_trees()->transform_tree.OnTransformAnimated( - rotation, child->transform_tree_index(), root->layer_tree_impl()); + root->layer_tree_impl()->SetTransformMutated(child->element_id(), rotation); EmulateDrawingOneFrame(root); // Since the child layer is square, rotation by 45 degrees about the center @@ -530,9 +522,9 @@ TEST_F(DamageTrackerTest, VerifyDamageForPerspectiveClippedLayer) { // Sanity check that the child layer's bounds would actually get clipped by // w < 0, otherwise this test is not actually testing the intended scenario. - gfx::QuadF test_quad(gfx::RectF(gfx::PointF(), gfx::SizeF(100.f, 100.f))); + gfx::RectF test_rect(child->position(), gfx::SizeF(child->bounds())); bool clipped = false; - MathUtil::MapQuad(transform, test_quad, &clipped); + MathUtil::MapQuad(transform, gfx::QuadF(test_rect), &clipped); EXPECT_TRUE(clipped); // Damage the child without moving it. @@ -540,8 +532,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForPerspectiveClippedLayer) { root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root); ClearDamageForAllSurfaces(root); - root->layer_tree_impl()->property_trees()->effect_tree.OnOpacityAnimated( - 0.5f, child->effect_tree_index(), root->layer_tree_impl()); + root->layer_tree_impl()->SetOpacityMutated(child->element_id(), 0.5f); EmulateDrawingOneFrame(root); // The expected damage should cover the entire root surface (500x500), but we @@ -601,8 +592,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForImageFilter) { child->test_properties()->force_render_surface = true; root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root); - child->layer_tree_impl()->property_trees()->effect_tree.OnFilterAnimated( - filters, child->effect_tree_index(), child->layer_tree_impl()); + child->layer_tree_impl()->SetFilterMutated(child->element_id(), filters); EmulateDrawingOneFrame(root); EXPECT_TRUE(root->GetRenderSurface()->damage_tracker()->GetDamageRectIfValid( &root_damage_rect)); @@ -652,8 +642,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForTransformedImageFilter) { child->test_properties()->transform = transform; root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root); - child->layer_tree_impl()->property_trees()->effect_tree.OnFilterAnimated( - filters, child->effect_tree_index(), child->layer_tree_impl()); + child->layer_tree_impl()->SetFilterMutated(child->element_id(), filters); EmulateDrawingOneFrame(root); EXPECT_TRUE(root->GetRenderSurface()->damage_tracker()->GetDamageRectIfValid( &root_damage_rect)); @@ -708,8 +697,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForHighDPIImageFilter) { root->layer_tree_impl()->property_trees()->needs_rebuild = true; int device_scale_factor = 2; EmulateDrawingOneFrame(root, device_scale_factor); - child->layer_tree_impl()->property_trees()->effect_tree.OnFilterAnimated( - filters, child->effect_tree_index(), child->layer_tree_impl()); + child->layer_tree_impl()->SetFilterMutated(child->element_id(), filters); EmulateDrawingOneFrame(root, device_scale_factor); EXPECT_TRUE(root->GetRenderSurface()->damage_tracker()->GetDamageRectIfValid( &root_damage_rect)); @@ -1009,8 +997,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForNestedSurfaces) { // CASE 1: Damage to a descendant surface should propagate properly to // ancestor surface. ClearDamageForAllSurfaces(root); - root->layer_tree_impl()->property_trees()->effect_tree.OnOpacityAnimated( - 0.5f, grand_child1->effect_tree_index(), root->layer_tree_impl()); + root->layer_tree_impl()->SetOpacityMutated(grand_child1->element_id(), 0.5f); EmulateDrawingOneFrame(root); EXPECT_TRUE( child1->GetRenderSurface()->damage_tracker()->GetDamageRectIfValid( @@ -1027,10 +1014,8 @@ TEST_F(DamageTrackerTest, VerifyDamageForNestedSurfaces) { // - child2 damage in root surface space: // gfx::Rect(11, 11, 18, 18); ClearDamageForAllSurfaces(root); - root->layer_tree_impl()->property_trees()->effect_tree.OnOpacityAnimated( - 0.7f, grand_child1->effect_tree_index(), root->layer_tree_impl()); - root->layer_tree_impl()->property_trees()->effect_tree.OnOpacityAnimated( - 0.7f, child2->effect_tree_index(), root->layer_tree_impl()); + root->layer_tree_impl()->SetOpacityMutated(grand_child1->element_id(), 0.7f); + root->layer_tree_impl()->SetOpacityMutated(child2->element_id(), 0.7f); EmulateDrawingOneFrame(root); EXPECT_TRUE( child1->GetRenderSurface()->damage_tracker()->GetDamageRectIfValid( @@ -1099,8 +1084,8 @@ TEST_F(DamageTrackerTest, VerifyDamageForSurfaceChangeFromAncestorLayer) { ClearDamageForAllSurfaces(root); gfx::Transform translation; translation.Translate(-50.f, -50.f); - root->layer_tree_impl()->property_trees()->transform_tree.OnTransformAnimated( - translation, child1->transform_tree_index(), root->layer_tree_impl()); + root->layer_tree_impl()->SetTransformMutated(child1->element_id(), + translation); EmulateDrawingOneFrame(root); EXPECT_TRUE( child1->GetRenderSurface()->damage_tracker()->GetDamageRectIfValid( @@ -1451,9 +1436,7 @@ TEST_F(DamageTrackerTest, HugeDamageRect) { // Visible rects computed from combining clips in target space and root // space don't match because of the loss in floating point accuracy. So, we // skip verify_clip_tree_calculations. - bool skip_verify_visible_rect_calculations = true; - EmulateDrawingOneFrame(root, device_scale_factor, - skip_verify_visible_rect_calculations); + EmulateDrawingOneFrame(root, device_scale_factor); // The expected damage should cover the visible part of the child layer, // which is (0, 0, i, i) in the viewport. @@ -1482,9 +1465,7 @@ TEST_F(DamageTrackerTest, DamageRectTooBig) { root->layer_tree_impl()->property_trees()->needs_rebuild = true; float device_scale_factor = 1.f; - bool skip_verify_visible_rect_calculations = true; - EmulateDrawingOneFrame(root, device_scale_factor, - skip_verify_visible_rect_calculations); + EmulateDrawingOneFrame(root, device_scale_factor); // The expected damage would be too large to store in a gfx::Rect, so we // should damage everything (ie, we don't have a valid rect). @@ -1515,9 +1496,7 @@ TEST_F(DamageTrackerTest, DamageRectTooBigWithFilter) { root->layer_tree_impl()->property_trees()->needs_rebuild = true; float device_scale_factor = 1.f; - bool skip_verify_visible_rect_calculations = true; - EmulateDrawingOneFrame(root, device_scale_factor, - skip_verify_visible_rect_calculations); + EmulateDrawingOneFrame(root, device_scale_factor); // The expected damage would be too large to store in a gfx::Rect, so we // should damage everything (ie, we don't have a valid rect). @@ -1548,10 +1527,8 @@ TEST_F(DamageTrackerTest, DamageRectTooBigInRenderSurface) { root->layer_tree_impl()->property_trees()->needs_rebuild = true; float device_scale_factor = 1.f; - bool skip_verify_visible_rect_calculations = true; LayerImplList render_surface_layer_list; ExecuteCalculateDrawProperties(root, device_scale_factor, - skip_verify_visible_rect_calculations, &render_surface_layer_list); auto* surface = child1->GetRenderSurface(); @@ -1590,7 +1567,6 @@ TEST_F(DamageTrackerTest, DamageRectTooBigInRenderSurface) { // Recompute all damage / properties. render_surface_layer_list.clear(); ExecuteCalculateDrawProperties(root, device_scale_factor, - skip_verify_visible_rect_calculations, &render_surface_layer_list); surface = child1->GetRenderSurface(); surface->damage_tracker()->UpdateDamageTrackingState( @@ -1645,10 +1621,8 @@ TEST_F(DamageTrackerTest, DamageRectTooBigInRenderSurfaceWithFilter) { root->layer_tree_impl()->property_trees()->needs_rebuild = true; float device_scale_factor = 1.f; - bool skip_verify_visible_rect_calculations = true; LayerImplList render_surface_layer_list; ExecuteCalculateDrawProperties(root, device_scale_factor, - skip_verify_visible_rect_calculations, &render_surface_layer_list); auto* surface = child1->GetRenderSurface(); @@ -1687,7 +1661,6 @@ TEST_F(DamageTrackerTest, DamageRectTooBigInRenderSurfaceWithFilter) { // Recompute all damage / properties. render_surface_layer_list.clear(); ExecuteCalculateDrawProperties(root, device_scale_factor, - skip_verify_visible_rect_calculations, &render_surface_layer_list); surface = child1->GetRenderSurface(); surface->damage_tracker()->UpdateDamageTrackingState( diff --git a/chromium/cc/trees/debug_rect_history.cc b/chromium/cc/trees/debug_rect_history.cc new file mode 100644 index 00000000000..243c610214c --- /dev/null +++ b/chromium/cc/trees/debug_rect_history.cc @@ -0,0 +1,238 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/trees/debug_rect_history.h" + +#include <stddef.h> + +#include "base/memory/ptr_util.h" +#include "cc/base/math_util.h" +#include "cc/layers/layer_impl.h" +#include "cc/layers/layer_list_iterator.h" +#include "cc/layers/layer_utils.h" +#include "cc/layers/render_surface_impl.h" +#include "cc/trees/damage_tracker.h" +#include "cc/trees/layer_tree_host.h" +#include "cc/trees/layer_tree_host_common.h" +#include "cc/trees/layer_tree_impl.h" +#include "ui/gfx/geometry/rect_conversions.h" + +namespace cc { + +// static +std::unique_ptr<DebugRectHistory> DebugRectHistory::Create() { + return base::WrapUnique(new DebugRectHistory()); +} + +DebugRectHistory::DebugRectHistory() {} + +DebugRectHistory::~DebugRectHistory() {} + +void DebugRectHistory::SaveDebugRectsForCurrentFrame( + LayerTreeImpl* tree_impl, + LayerImpl* hud_layer, + const LayerImplList& render_surface_layer_list, + const LayerTreeDebugState& debug_state) { + // For now, clear all rects from previous frames. In the future we may want to + // store all debug rects for a history of many frames. + debug_rects_.clear(); + + if (debug_state.show_touch_event_handler_rects) + SaveTouchEventHandlerRects(tree_impl); + + if (debug_state.show_wheel_event_handler_rects) + SaveWheelEventHandlerRects(tree_impl); + + if (debug_state.show_scroll_event_handler_rects) + SaveScrollEventHandlerRects(tree_impl); + + if (debug_state.show_non_fast_scrollable_rects) + SaveNonFastScrollableRects(tree_impl); + + if (debug_state.show_paint_rects) + SavePaintRects(tree_impl); + + if (debug_state.show_property_changed_rects) + SavePropertyChangedRects(render_surface_layer_list, hud_layer); + + if (debug_state.show_surface_damage_rects) + SaveSurfaceDamageRects(render_surface_layer_list); + + if (debug_state.show_screen_space_rects) + SaveScreenSpaceRects(render_surface_layer_list); + + if (debug_state.show_layer_animation_bounds_rects) + SaveLayerAnimationBoundsRects(tree_impl); +} + +void DebugRectHistory::SavePaintRects(LayerTreeImpl* tree_impl) { + // We would like to visualize where any layer's paint rect (update rect) has + // changed, regardless of whether this layer is skipped for actual drawing or + // not. Therefore we traverse over all layers, not just the render surface + // list. + for (auto* layer : *tree_impl) { + Region invalidation_region = layer->GetInvalidationRegionForDebugging(); + if (invalidation_region.IsEmpty() || !layer->DrawsContent()) + continue; + + for (Region::Iterator it(invalidation_region); it.has_rect(); it.next()) { + debug_rects_.push_back(DebugRect( + PAINT_RECT_TYPE, MathUtil::MapEnclosingClippedRect( + layer->ScreenSpaceTransform(), it.rect()))); + } + } +} + +void DebugRectHistory::SavePropertyChangedRects( + const LayerImplList& render_surface_layer_list, + LayerImpl* hud_layer) { + for (size_t i = 0; i < render_surface_layer_list.size(); ++i) { + size_t surface_index = render_surface_layer_list.size() - 1 - i; + LayerImpl* render_surface_layer = render_surface_layer_list[surface_index]; + RenderSurfaceImpl* render_surface = + render_surface_layer->GetRenderSurface(); + DCHECK(render_surface); + + const LayerImplList& layer_list = render_surface->layer_list(); + for (unsigned layer_index = 0; layer_index < layer_list.size(); + ++layer_index) { + LayerImpl* layer = layer_list[layer_index]; + + if (layer->GetRenderSurface() && + layer->GetRenderSurface() != render_surface) + continue; + + if (layer == hud_layer) + continue; + + if (!layer->LayerPropertyChanged()) + continue; + + debug_rects_.push_back(DebugRect( + PROPERTY_CHANGED_RECT_TYPE, + MathUtil::MapEnclosingClippedRect(layer->ScreenSpaceTransform(), + gfx::Rect(layer->bounds())))); + } + } +} + +void DebugRectHistory::SaveSurfaceDamageRects( + const LayerImplList& render_surface_layer_list) { + for (size_t i = 0; i < render_surface_layer_list.size(); ++i) { + size_t surface_index = render_surface_layer_list.size() - 1 - i; + LayerImpl* render_surface_layer = render_surface_layer_list[surface_index]; + RenderSurfaceImpl* render_surface = + render_surface_layer->GetRenderSurface(); + DCHECK(render_surface); + + debug_rects_.push_back(DebugRect( + SURFACE_DAMAGE_RECT_TYPE, MathUtil::MapEnclosingClippedRect( + render_surface->screen_space_transform(), + render_surface->GetDamageRect()))); + } +} + +void DebugRectHistory::SaveScreenSpaceRects( + const LayerImplList& render_surface_layer_list) { + for (size_t i = 0; i < render_surface_layer_list.size(); ++i) { + size_t surface_index = render_surface_layer_list.size() - 1 - i; + LayerImpl* render_surface_layer = render_surface_layer_list[surface_index]; + RenderSurfaceImpl* render_surface = + render_surface_layer->GetRenderSurface(); + DCHECK(render_surface); + + debug_rects_.push_back(DebugRect( + SCREEN_SPACE_RECT_TYPE, MathUtil::MapEnclosingClippedRect( + render_surface->screen_space_transform(), + render_surface->content_rect()))); + } +} + +void DebugRectHistory::SaveTouchEventHandlerRects(LayerTreeImpl* tree_impl) { + LayerTreeHostCommon::CallFunctionForEveryLayer( + tree_impl, + [this](LayerImpl* layer) { SaveTouchEventHandlerRectsCallback(layer); }); +} + +void DebugRectHistory::SaveTouchEventHandlerRectsCallback(LayerImpl* layer) { + for (Region::Iterator iter(layer->touch_event_handler_region()); + iter.has_rect(); iter.next()) { + debug_rects_.push_back( + DebugRect(TOUCH_EVENT_HANDLER_RECT_TYPE, + MathUtil::MapEnclosingClippedRect( + layer->ScreenSpaceTransform(), iter.rect()))); + } +} + +void DebugRectHistory::SaveWheelEventHandlerRects(LayerTreeImpl* tree_impl) { + EventListenerProperties event_properties = + tree_impl->event_listener_properties(EventListenerClass::kMouseWheel); + if (event_properties == EventListenerProperties::kNone || + event_properties == EventListenerProperties::kPassive) { + return; + } + + // Since the wheel event handlers property is on the entire layer tree just + // mark inner viewport if have listeners. + LayerImpl* inner_viewport = tree_impl->InnerViewportScrollLayer(); + if (!inner_viewport) + return; + debug_rects_.push_back(DebugRect( + WHEEL_EVENT_HANDLER_RECT_TYPE, + MathUtil::MapEnclosingClippedRect(inner_viewport->ScreenSpaceTransform(), + gfx::Rect(inner_viewport->bounds())))); +} + +void DebugRectHistory::SaveScrollEventHandlerRects(LayerTreeImpl* tree_impl) { + LayerTreeHostCommon::CallFunctionForEveryLayer( + tree_impl, + [this](LayerImpl* layer) { SaveScrollEventHandlerRectsCallback(layer); }); +} + +void DebugRectHistory::SaveScrollEventHandlerRectsCallback(LayerImpl* layer) { + if (!layer->layer_tree_impl()->have_scroll_event_handlers()) + return; + + debug_rects_.push_back( + DebugRect(SCROLL_EVENT_HANDLER_RECT_TYPE, + MathUtil::MapEnclosingClippedRect(layer->ScreenSpaceTransform(), + gfx::Rect(layer->bounds())))); +} + +void DebugRectHistory::SaveNonFastScrollableRects(LayerTreeImpl* tree_impl) { + LayerTreeHostCommon::CallFunctionForEveryLayer( + tree_impl, + [this](LayerImpl* layer) { SaveNonFastScrollableRectsCallback(layer); }); +} + +void DebugRectHistory::SaveNonFastScrollableRectsCallback(LayerImpl* layer) { + for (Region::Iterator iter(layer->non_fast_scrollable_region()); + iter.has_rect(); iter.next()) { + debug_rects_.push_back( + DebugRect(NON_FAST_SCROLLABLE_RECT_TYPE, + MathUtil::MapEnclosingClippedRect( + layer->ScreenSpaceTransform(), iter.rect()))); + } +} + +void DebugRectHistory::SaveLayerAnimationBoundsRects(LayerTreeImpl* tree_impl) { + for (auto it = tree_impl->rbegin(); it != tree_impl->rend(); ++it) { + if (!(*it)->is_drawn_render_surface_layer_list_member()) + continue; + + // TODO(avallee): Figure out if we should show something for a layer who's + // animating bounds but that we can't compute them. + gfx::BoxF inflated_bounds; + if (!LayerUtils::GetAnimationBounds(**it, &inflated_bounds)) + continue; + + debug_rects_.push_back( + DebugRect(ANIMATION_BOUNDS_RECT_TYPE, + gfx::ToEnclosingRect(gfx::RectF( + inflated_bounds.x(), inflated_bounds.y(), + inflated_bounds.width(), inflated_bounds.height())))); + } +} + +} // namespace cc diff --git a/chromium/cc/trees/debug_rect_history.h b/chromium/cc/trees/debug_rect_history.h new file mode 100644 index 00000000000..183cddeb775 --- /dev/null +++ b/chromium/cc/trees/debug_rect_history.h @@ -0,0 +1,99 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_TREES_DEBUG_RECT_HISTORY_H_ +#define CC_TREES_DEBUG_RECT_HISTORY_H_ + +#include <memory> +#include <vector> + +#include "base/macros.h" +#include "cc/layers/layer_collections.h" +#include "ui/gfx/geometry/rect.h" + +namespace cc { + +class LayerImpl; +class LayerTreeDebugState; +class LayerTreeImpl; + +// There are currently six types of debug rects: +// +// - Paint rects (update rects): regions of a layer that needed to be +// re-uploaded to the texture resource; in most cases implying that they had to +// be repainted, too. +// +// - Property-changed rects: enclosing bounds of layers that cause changes to +// the screen even if the layer did not change internally. (For example, if the +// layer's opacity or position changes.) +// +// - Surface damage rects: the aggregate damage on a target surface that is +// caused by all layers and surfaces that contribute to it. This includes (1) +// paint rects, (2) property- changed rects, and (3) newly exposed areas. +// +// - Screen space rects: this is the region the contents occupy in screen space. +enum DebugRectType { + PAINT_RECT_TYPE, + PROPERTY_CHANGED_RECT_TYPE, + SURFACE_DAMAGE_RECT_TYPE, + SCREEN_SPACE_RECT_TYPE, + TOUCH_EVENT_HANDLER_RECT_TYPE, + WHEEL_EVENT_HANDLER_RECT_TYPE, + SCROLL_EVENT_HANDLER_RECT_TYPE, + NON_FAST_SCROLLABLE_RECT_TYPE, + ANIMATION_BOUNDS_RECT_TYPE, +}; + +struct DebugRect { + DebugRect(DebugRectType new_type, const gfx::Rect& new_rect) + : type(new_type), rect(new_rect) {} + + DebugRectType type; + gfx::Rect rect; +}; + +// This class maintains a history of rects of various types that can be used +// for debugging purposes. The overhead of collecting rects is performed only if +// the appropriate LayerTreeSettings are enabled. +class DebugRectHistory { + public: + static std::unique_ptr<DebugRectHistory> Create(); + + ~DebugRectHistory(); + + // Note: Saving debug rects must happen before layers' change tracking is + // reset. + void SaveDebugRectsForCurrentFrame( + LayerTreeImpl* tree_impl, + LayerImpl* hud_layer, + const LayerImplList& render_surface_layer_list, + const LayerTreeDebugState& debug_state); + + const std::vector<DebugRect>& debug_rects() { return debug_rects_; } + + private: + DebugRectHistory(); + + void SavePaintRects(LayerTreeImpl* tree_impl); + void SavePropertyChangedRects(const LayerImplList& render_surface_layer_list, + LayerImpl* hud_layer); + void SaveSurfaceDamageRects(const LayerImplList& render_surface_layer_list); + void SaveScreenSpaceRects(const LayerImplList& render_surface_layer_list); + void SaveTouchEventHandlerRects(LayerTreeImpl* layer); + void SaveTouchEventHandlerRectsCallback(LayerImpl* layer); + void SaveWheelEventHandlerRects(LayerTreeImpl* tree_impl); + void SaveScrollEventHandlerRects(LayerTreeImpl* layer); + void SaveScrollEventHandlerRectsCallback(LayerImpl* layer); + void SaveNonFastScrollableRects(LayerTreeImpl* layer); + void SaveNonFastScrollableRectsCallback(LayerImpl* layer); + void SaveLayerAnimationBoundsRects(LayerTreeImpl* tree_impl); + + std::vector<DebugRect> debug_rects_; + + DISALLOW_COPY_AND_ASSIGN(DebugRectHistory); +}; + +} // namespace cc + +#endif // CC_TREES_DEBUG_RECT_HISTORY_H_ diff --git a/chromium/cc/trees/draw_property_utils.cc b/chromium/cc/trees/draw_property_utils.cc index c5128934db9..5af6686aa61 100644 --- a/chromium/cc/trees/draw_property_utils.cc +++ b/chromium/cc/trees/draw_property_utils.cc @@ -17,6 +17,7 @@ #include "cc/trees/layer_tree_impl.h" #include "cc/trees/property_tree.h" #include "cc/trees/property_tree_builder.h" +#include "cc/trees/scroll_node.h" #include "cc/trees/transform_node.h" #include "ui/gfx/geometry/rect_conversions.h" @@ -34,54 +35,45 @@ static bool IsRootLayer(const LayerImpl* layer) { return layer->layer_tree_impl()->IsRootLayer(layer); } -static const EffectNode* ContentsTargetEffectNode( - const int effect_tree_index, - const EffectTree& effect_tree) { - const EffectNode* effect_node = effect_tree.Node(effect_tree_index); - return effect_tree.GetRenderSurface(effect_tree_index) - ? effect_node - : effect_tree.Node(effect_node->target_id); +static void PostConcatSurfaceContentsScale(const EffectNode* effect_node, + gfx::Transform* transform) { + if (!effect_node) { + // This can happen when PaintArtifactCompositor builds property trees as it + // doesn't set effect ids on clip nodes. + return; + } + DCHECK(effect_node->has_render_surface); + transform->matrix().postScale(effect_node->surface_contents_scale.x(), + effect_node->surface_contents_scale.y(), 1.f); } -bool ComputeClipRectInTargetSpace(const LayerImpl* layer, - const ClipNode* clip_node, - const PropertyTrees* property_trees, - int target_node_id, - bool for_visible_rect_calculation, - gfx::RectF* clip_rect_in_target_space) { - DCHECK(layer->clip_tree_index() == clip_node->id); - DCHECK(clip_node->target_transform_id != target_node_id); - - const EffectTree& effect_tree = property_trees->effect_tree; - const EffectNode* target_effect_node = - ContentsTargetEffectNode(layer->effect_tree_index(), effect_tree); - gfx::Transform clip_to_target; - // We use the local clip for clip rect calculation and combined clip for - // visible rect calculation. - gfx::RectF clip_from_clip_node = - for_visible_rect_calculation ? clip_node->combined_clip_in_target_space - : clip_node->clip_in_target_space; - - if (clip_node->target_transform_id > target_node_id) { - // In this case, layer has a scroll parent. We need to keep the scale - // at the layer's target but remove the scale at the scroll parent's - // target. - if (property_trees->GetToTarget(clip_node->target_transform_id, - target_effect_node->id, &clip_to_target)) { - const EffectNode* source_node = - effect_tree.Node(clip_node->target_effect_id); - ConcatInverseSurfaceContentsScale(source_node, &clip_to_target); - *clip_rect_in_target_space = - MathUtil::MapClippedRect(clip_to_target, clip_from_clip_node); +static bool ConvertRectBetweenSurfaceSpaces(const PropertyTrees* property_trees, + int source_effect_id, + int dest_effect_id, + gfx::RectF clip_in_source_space, + gfx::RectF* clip_in_dest_space) { + const EffectNode* source_effect_node = + property_trees->effect_tree.Node(source_effect_id); + int source_transform_id = source_effect_node->transform_id; + const EffectNode* dest_effect_node = + property_trees->effect_tree.Node(dest_effect_id); + int dest_transform_id = dest_effect_node->transform_id; + gfx::Transform source_to_dest; + if (source_transform_id > dest_transform_id) { + if (property_trees->GetToTarget(source_transform_id, dest_effect_id, + &source_to_dest)) { + ConcatInverseSurfaceContentsScale(source_effect_node, &source_to_dest); + *clip_in_dest_space = + MathUtil::MapClippedRect(source_to_dest, clip_in_source_space); } else { return false; } } else { - if (property_trees->GetFromTarget( - target_node_id, clip_node->target_effect_id, &clip_to_target)) { - PostConcatSurfaceContentsScale(target_effect_node, &clip_to_target); - *clip_rect_in_target_space = - MathUtil::ProjectClippedRect(clip_to_target, clip_from_clip_node); + if (property_trees->GetFromTarget(dest_transform_id, source_effect_id, + &source_to_dest)) { + PostConcatSurfaceContentsScale(dest_effect_node, &source_to_dest); + *clip_in_dest_space = + MathUtil::ProjectClippedRect(source_to_dest, clip_in_source_space); } else { return false; } @@ -89,11 +81,6 @@ bool ComputeClipRectInTargetSpace(const LayerImpl* layer, return true; } -struct ConditionalClip { - bool is_clipped; - gfx::RectF clip_rect; -}; - static ConditionalClip ComputeTargetRectInLocalSpace( gfx::RectF rect, const PropertyTrees* property_trees, @@ -103,8 +90,8 @@ static ConditionalClip ComputeTargetRectInLocalSpace( gfx::Transform target_to_local; bool success = property_trees->GetFromTarget( local_transform_id, target_effect_id, &target_to_local); + // If transform is not invertible, cannot apply clip. if (!success) - // If transform is not invertible, cannot apply clip. return ConditionalClip{false, gfx::RectF()}; if (target_transform_id > local_transform_id) @@ -115,29 +102,6 @@ static ConditionalClip ComputeTargetRectInLocalSpace( MathUtil::ProjectClippedRect(target_to_local, rect)}; } -static ConditionalClip ConvertRectBetweenSurfaceSpaces( - gfx::RectF rect, - const PropertyTrees* property_trees, - int source_transform_id, - int source_effect_id, - int dest_transform_id, - int dest_effect_id) { - gfx::Transform source_to_dest; - bool success = property_trees->GetToTarget(source_transform_id, - dest_effect_id, &source_to_dest); - if (!success) - return ConditionalClip{false, gfx::RectF()}; - const EffectTree& effect_tree = property_trees->effect_tree; - const EffectNode* source_effect_node = effect_tree.Node(source_effect_id); - ConcatInverseSurfaceContentsScale(source_effect_node, &source_to_dest); - if (source_transform_id > dest_transform_id) { - return ConditionalClip{true, // is_clipped - MathUtil::MapClippedRect(source_to_dest, rect)}; - } - return ConditionalClip{true, // is_clipped - MathUtil::ProjectClippedRect(source_to_dest, rect)}; -} - static ConditionalClip ComputeLocalRectInTargetSpace( gfx::RectF rect, const PropertyTrees* property_trees, @@ -206,362 +170,149 @@ static bool ApplyClipNodeToAccumulatedClip(const PropertyTrees* property_trees, const EffectNode* expanding_effect_node = property_trees->effect_tree.Node( clip_node->clip_expander->target_effect_id()); - ConditionalClip accumulated_clip_in_expanding_space = - ConvertRectBetweenSurfaceSpaces( - *accumulated_clip, property_trees, target_transform_id, target_id, - expanding_effect_node->transform_id, expanding_effect_node->id); + gfx::RectF accumulated_clip_rect_in_expanding_space; + bool success = ConvertRectBetweenSurfaceSpaces( + property_trees, target_id, expanding_effect_node->id, + *accumulated_clip, &accumulated_clip_rect_in_expanding_space); // If transform is not invertible, no clip will be applied. - if (!accumulated_clip_in_expanding_space.is_clipped) + if (!success) return false; // Do the expansion. gfx::RectF expanded_clip_in_expanding_space = gfx::RectF(clip_node->clip_expander->MapRectReverse( - gfx::ToEnclosingRect( - accumulated_clip_in_expanding_space.clip_rect), + gfx::ToEnclosingRect(accumulated_clip_rect_in_expanding_space), property_trees)); // Put the expanded clip back into the original target space. - ConditionalClip expanded_clip_in_target_space = - ConvertRectBetweenSurfaceSpaces( - expanded_clip_in_expanding_space, property_trees, - expanding_effect_node->transform_id, expanding_effect_node->id, - target_transform_id, target_id); + success = ConvertRectBetweenSurfaceSpaces( + property_trees, expanding_effect_node->id, target_id, + expanded_clip_in_expanding_space, accumulated_clip); // If transform is not invertible, no clip will be applied. - if (!expanded_clip_in_target_space.is_clipped) + if (!success) return false; - *accumulated_clip = expanded_clip_in_target_space.clip_rect; return true; } - case ClipNode::ClipType::NONE: - return true; } NOTREACHED(); return true; } -static ConditionalClip ComputeAccumulatedClip( - const PropertyTrees* property_trees, - bool include_viewport_clip, - bool include_expanding_clips, - int local_clip_id, - int target_id) { - DCHECK(!include_viewport_clip || - target_id == EffectTree::kContentsRootNodeId); - const ClipTree& clip_tree = property_trees->clip_tree; - const EffectTree& effect_tree = property_trees->effect_tree; +static ConditionalClip ComputeAccumulatedClip(PropertyTrees* property_trees, + bool include_expanding_clips, + int local_clip_id, + int target_id) { + ClipRectData* cached_data = + property_trees->FetchClipRectFromCache(local_clip_id, target_id); + if (cached_data->target_id != EffectTree::kInvalidNodeId) { + // Cache hit + return cached_data->clip; + } + cached_data->target_id = target_id; + const ClipTree& clip_tree = property_trees->clip_tree; const ClipNode* clip_node = clip_tree.Node(local_clip_id); + const EffectTree& effect_tree = property_trees->effect_tree; const EffectNode* target_node = effect_tree.Node(target_id); int target_transform_id = target_node->transform_id; + bool cache_hit = false; + ConditionalClip cached_clip = ConditionalClip{false, gfx::RectF()}; + ConditionalClip unclipped = ConditionalClip{false, gfx::RectF()}; + // Collect all the clips that need to be accumulated. - std::stack<const ClipNode*> parent_chain; + std::stack<const ClipNode*, std::vector<const ClipNode*>> parent_chain; // If target is not direct ancestor of clip, this will find least common - // ancestor between the target and the clip. + // ancestor between the target and the clip. Or, if the target has a + // contributing layer that escapes clip, this will find the nearest ancestor + // that doesn't. while (target_node->clip_id > clip_node->id || - target_node->has_unclipped_descendants) { + effect_tree.GetRenderSurface(target_node->id) + ->has_contributing_layer_that_escapes_clip()) { target_node = effect_tree.Node(target_node->target_id); } - // Collect clip nodes up to the least common ancestor. + // Collect clip nodes up to the least common ancestor or till we get a cache + // hit. while (target_node->clip_id < clip_node->id) { + if (parent_chain.size() > 0) { + // Search the cache. + for (auto& data : clip_node->cached_clip_rects) { + if (data.target_id == target_id) { + cache_hit = true; + cached_clip = data.clip; + } + } + } parent_chain.push(clip_node); clip_node = clip_tree.parent(clip_node); } - DCHECK_EQ(target_node->clip_id, clip_node->id); - if (!include_viewport_clip && parent_chain.size() == 0) { - // There aren't any clips to apply. - return ConditionalClip{false, gfx::RectF()}; + if (parent_chain.size() == 0) { + // No accumulated clip nodes. + cached_data->clip = unclipped; + return unclipped; } - if (!include_viewport_clip) { - clip_node = parent_chain.top(); - parent_chain.pop(); - } - - // Find the first clip in the chain that we need to apply. - while (clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP && - parent_chain.size() > 0) { - clip_node = parent_chain.top(); - parent_chain.pop(); - } + clip_node = parent_chain.top(); + parent_chain.pop(); - if (clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP) { - // No clip node applying clip in between. - return ConditionalClip{false, gfx::RectF()}; - } - - ConditionalClip current_clip = ComputeCurrentClip( - clip_node, property_trees, target_transform_id, target_id); - - // If transform is not invertible, no clip will be applied. - if (!current_clip.is_clipped) - return ConditionalClip{false, gfx::RectF()}; - gfx::RectF accumulated_clip = current_clip.clip_rect; - - while (parent_chain.size() > 0) { - clip_node = parent_chain.top(); - parent_chain.pop(); + gfx::RectF accumulated_clip; + if (cache_hit && cached_clip.is_clipped) { + // Apply the first clip in parent_chain to the cached clip. + accumulated_clip = cached_clip.clip_rect; bool success = ApplyClipNodeToAccumulatedClip( property_trees, include_expanding_clips, target_id, target_transform_id, clip_node, &accumulated_clip); - - // Failure to apply the clip means we encountered an uninvertible transform, - // so no clip will be applied. - if (!success) - return ConditionalClip{false /* is_clipped */, gfx::RectF()}; - } - - return ConditionalClip{true /* is_clipped */, accumulated_clip.IsEmpty() - ? gfx::RectF() - : accumulated_clip}; -} - -static gfx::RectF ComputeAccumulatedClipInRootSpaceForVisibleRect( - const PropertyTrees* property_trees, - int local_clip_id) { - const int root_effect_id = EffectTree::kContentsRootNodeId; - bool include_viewport_clip = true; - bool include_expanding_clips = true; - ConditionalClip accumulated_clip = ComputeAccumulatedClip( - property_trees, include_viewport_clip, include_expanding_clips, - local_clip_id, root_effect_id); - DCHECK(accumulated_clip.is_clipped); - return accumulated_clip.clip_rect; -} - -void CalculateClipRects(const std::vector<LayerImpl*>& visible_layer_list, - const PropertyTrees* property_trees, - bool non_root_surfaces_enabled) { - const ClipTree& clip_tree = property_trees->clip_tree; - for (auto* layer : visible_layer_list) { - const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index()); - bool layer_needs_clip_rect = - non_root_surfaces_enabled - ? clip_node->layers_are_clipped - : clip_node->layers_are_clipped_when_surfaces_disabled; - if (!layer_needs_clip_rect) { - layer->set_clip_rect(gfx::Rect()); - continue; + if (!success) { + // Singular transform + cached_data->clip = unclipped; + return unclipped; } - if (!non_root_surfaces_enabled) { - layer->set_clip_rect( - gfx::ToEnclosingRect(clip_node->clip_in_target_space)); - continue; + } else { + // No cache hit or the cached clip has no clip to apply. We need to find + // the first clip that applies clip as there is no clip to expand. + while (clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP && + parent_chain.size() > 0) { + clip_node = parent_chain.top(); + parent_chain.pop(); } - const TransformTree& transform_tree = property_trees->transform_tree; - const TransformNode* transform_node = - transform_tree.Node(layer->transform_tree_index()); - int target_node_id = transform_tree.ContentTargetId(transform_node->id); - - // The clip node stores clip rect in its target space. - gfx::RectF clip_rect_in_target_space = clip_node->clip_in_target_space; - - // If required, this clip rect should be mapped to the current layer's - // target space. - if (clip_node->target_transform_id != target_node_id) { - // In this case, layer has a clip parent or scroll parent (or shares the - // target with an ancestor layer that has clip parent) and the clip - // parent's target is different from the layer's target. As the layer's - // target has unclippped descendants, it is unclippped. - if (!clip_node->layers_are_clipped) - continue; - - // Compute the clip rect in target space and store it. - bool for_visible_rect_calculation = false; - if (!ComputeClipRectInTargetSpace( - layer, clip_node, property_trees, target_node_id, - for_visible_rect_calculation, &clip_rect_in_target_space)) - continue; + if (clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP) { + // No clip to apply. + cached_data->clip = unclipped; + return unclipped; } - - if (!clip_rect_in_target_space.IsEmpty()) { - layer->set_clip_rect(gfx::ToEnclosingRect(clip_rect_in_target_space)); - } else { - layer->set_clip_rect(gfx::Rect()); + ConditionalClip current_clip = ComputeCurrentClip( + clip_node, property_trees, target_transform_id, target_id); + if (!current_clip.is_clipped) { + // Singular transform + cached_data->clip = unclipped; + return unclipped; } + accumulated_clip = current_clip.clip_rect; } -} - -void CalculateVisibleRects(const LayerImplList& visible_layer_list, - const PropertyTrees* property_trees, - bool non_root_surfaces_enabled) { - const EffectTree& effect_tree = property_trees->effect_tree; - const TransformTree& transform_tree = property_trees->transform_tree; - const ClipTree& clip_tree = property_trees->clip_tree; - for (auto* layer : visible_layer_list) { - gfx::Size layer_bounds = layer->bounds(); - - int effect_ancestor_with_copy_request = - effect_tree.ClosestAncestorWithCopyRequest(layer->effect_tree_index()); - if (effect_ancestor_with_copy_request > EffectTree::kContentsRootNodeId) { - // Non root copy request. - bool include_viewport_clip = false; - bool include_expanding_clips = true; - ConditionalClip accumulated_clip_rect = ComputeAccumulatedClip( - property_trees, include_viewport_clip, include_expanding_clips, - layer->clip_tree_index(), effect_ancestor_with_copy_request); - if (!accumulated_clip_rect.is_clipped) { - layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); - continue; - } - - gfx::RectF accumulated_clip_in_copy_request_space = - accumulated_clip_rect.clip_rect; - - const EffectNode* copy_request_effect_node = - effect_tree.Node(effect_ancestor_with_copy_request); - ConditionalClip clip_in_layer_space = ComputeTargetRectInLocalSpace( - accumulated_clip_in_copy_request_space, property_trees, - copy_request_effect_node->transform_id, layer->transform_tree_index(), - copy_request_effect_node->id); - - if (clip_in_layer_space.is_clipped) { - gfx::RectF clip_rect = clip_in_layer_space.clip_rect; - clip_rect.Offset(-layer->offset_to_transform_parent()); - gfx::Rect visible_rect = gfx::ToEnclosingRect(clip_rect); - visible_rect.Intersect(gfx::Rect(layer_bounds)); - layer->set_visible_layer_rect(visible_rect); - } else { - layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); - } - continue; - } - - const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index()); - const TransformNode* transform_node = - transform_tree.Node(layer->transform_tree_index()); - if (!non_root_surfaces_enabled) { - // When we only have a root surface, the clip node and the layer must - // necessarily have the same target (the root). - if (transform_node->ancestors_are_invertible) { - gfx::RectF combined_clip_rect_in_target_space = - clip_node->combined_clip_in_target_space; - gfx::Transform target_to_content; - target_to_content.Translate(-layer->offset_to_transform_parent().x(), - -layer->offset_to_transform_parent().y()); - target_to_content.PreconcatTransform( - transform_tree.FromScreen(transform_node->id)); - - gfx::Rect visible_rect = - gfx::ToEnclosingRect(MathUtil::ProjectClippedRect( - target_to_content, combined_clip_rect_in_target_space)); - visible_rect.Intersect(gfx::Rect(layer_bounds)); - layer->set_visible_layer_rect(visible_rect); - } else { - layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); - } - continue; - } - - // When both the layer and the target are unclipped, we only have to apply - // the viewport clip. - const bool fully_visible = - !clip_node->layers_are_clipped && - !effect_tree.Node(clip_node->target_effect_id)->surface_is_clipped; - - if (fully_visible) { - if (!transform_node->ancestors_are_invertible) { - // An animated singular transform may become non-singular during the - // animation, so we still need to compute a visible rect. In this - // situation, we treat the entire layer as visible. - layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); - } else { - gfx::Transform from_screen; - from_screen.Translate(-layer->offset_to_transform_parent().x(), - -layer->offset_to_transform_parent().y()); - from_screen.PreconcatTransform( - property_trees->transform_tree.FromScreen(transform_node->id)); - gfx::Rect visible_rect = - gfx::ToEnclosingRect(MathUtil::ProjectClippedRect( - from_screen, property_trees->clip_tree.ViewportClip())); - visible_rect.Intersect(gfx::Rect(layer_bounds)); - layer->set_visible_layer_rect(visible_rect); - } - continue; - } - - int target_node_id = transform_tree.ContentTargetId(transform_node->id); - - // The clip node stores clip rect in its target space. If required, - // this clip rect should be mapped to the current layer's target space. - gfx::RectF combined_clip_rect_in_target_space; - if (clip_node->target_transform_id != target_node_id) { - // In this case, layer has a clip parent or scroll parent (or shares the - // target with an ancestor layer that has clip parent) and the clip - // parent's target is different from the layer's target. As the layer's - // target has unclippped descendants, it is unclippped. - if (!clip_node->layers_are_clipped) { - layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); - continue; - } - - bool for_visible_rect_calculation = true; - if (!ComputeClipRectInTargetSpace(layer, clip_node, property_trees, - target_node_id, - for_visible_rect_calculation, - &combined_clip_rect_in_target_space)) { - layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); - continue; - } - } else { - combined_clip_rect_in_target_space = - clip_node->combined_clip_in_target_space; - } - - // The clip rect should be intersected with layer rect in target space. - gfx::Transform content_to_target; - property_trees->GetToTarget(transform_node->id, - layer->render_target_effect_tree_index(), - &content_to_target); - content_to_target.Translate(layer->offset_to_transform_parent().x(), - layer->offset_to_transform_parent().y()); - gfx::Rect layer_content_rect = gfx::Rect(layer_bounds); - gfx::RectF layer_content_bounds_in_target_space = MathUtil::MapClippedRect( - content_to_target, gfx::RectF(layer_content_rect)); - // If the layer is fully contained within the clip, treat it as fully - // visible. - if (!layer_content_bounds_in_target_space.IsEmpty() && - combined_clip_rect_in_target_space.Contains( - layer_content_bounds_in_target_space)) { - layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); - continue; - } - - combined_clip_rect_in_target_space.Intersect( - layer_content_bounds_in_target_space); - if (combined_clip_rect_in_target_space.IsEmpty()) { - layer->set_visible_layer_rect(gfx::Rect()); - continue; - } - - gfx::Transform target_to_layer; - const EffectNode* target_effect_node = - ContentsTargetEffectNode(layer->effect_tree_index(), effect_tree); - bool success = property_trees->GetFromTarget( - transform_node->id, target_effect_node->id, &target_to_layer); + // Apply remaining clips + while (parent_chain.size() > 0) { + clip_node = parent_chain.top(); + parent_chain.pop(); + bool success = ApplyClipNodeToAccumulatedClip( + property_trees, include_expanding_clips, target_id, target_transform_id, + clip_node, &accumulated_clip); if (!success) { - // An animated singular transform may become non-singular during the - // animation, so we still need to compute a visible rect. In this - // situation, we treat the entire layer as visible. - layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); - continue; + // Singular transform + cached_data->clip = unclipped; + return unclipped; } - gfx::Transform target_to_content; - target_to_content.Translate(-layer->offset_to_transform_parent().x(), - -layer->offset_to_transform_parent().y()); - target_to_content.PreconcatTransform(target_to_layer); - - gfx::Rect visible_rect = gfx::ToEnclosingRect(MathUtil::ProjectClippedRect( - target_to_content, combined_clip_rect_in_target_space)); - visible_rect.Intersect(gfx::Rect(layer_bounds)); - layer->set_visible_layer_rect(visible_rect); } + + ConditionalClip clip = ConditionalClip{ + true /* is_clipped */, + accumulated_clip.IsEmpty() ? gfx::RectF() : accumulated_clip}; + cached_data->clip = clip; + return clip; } static bool HasSingularTransform(int transform_tree_index, @@ -570,6 +321,36 @@ static bool HasSingularTransform(int transform_tree_index, return !node->is_invertible || !node->ancestors_are_invertible; } +static int LowestCommonAncestor(int clip_id_1, + int clip_id_2, + const ClipTree* clip_tree) { + const ClipNode* clip_node_1 = clip_tree->Node(clip_id_1); + const ClipNode* clip_node_2 = clip_tree->Node(clip_id_2); + while (clip_node_1->id != clip_node_2->id) { + if (clip_node_1->id < clip_node_2->id) + clip_node_2 = clip_tree->parent(clip_node_2); + else + clip_node_1 = clip_tree->parent(clip_node_1); + } + return clip_node_1->id; +} + +static void SetHasContributingLayerThatEscapesClip(int lca_clip_id, + int target_effect_id, + EffectTree* effect_tree) { + const EffectNode* effect_node = effect_tree->Node(target_effect_id); + // Find all ancestor targets starting from effect_node who are clipped by + // a descendant of lowest ancestor clip and set their + // has_contributing_layer_that_escapes_clip to true. + while (effect_node->clip_id > lca_clip_id) { + RenderSurfaceImpl* render_surface = + effect_tree->GetRenderSurface(effect_node->id); + DCHECK(render_surface); + render_surface->set_has_contributing_layer_that_escapes_clip(true); + effect_node = effect_tree->Node(effect_node->target_id); + } +} + template <typename LayerType> static int TransformTreeIndexForBackfaceVisibility(LayerType* layer, const TransformTree& tree) { @@ -668,27 +449,6 @@ static bool LayerNeedsUpdateInternal(LayerType* layer, return true; } -void FindLayersThatNeedUpdates(LayerTreeImpl* layer_tree_impl, - const PropertyTrees* property_trees, - std::vector<LayerImpl*>* visible_layer_list) { - const TransformTree& transform_tree = property_trees->transform_tree; - const EffectTree& effect_tree = property_trees->effect_tree; - - for (auto* layer_impl : *layer_tree_impl) { - if (!IsRootLayer(layer_impl) && - LayerShouldBeSkipped(layer_impl, transform_tree, effect_tree)) - continue; - - bool layer_is_drawn = - effect_tree.Node(layer_impl->effect_tree_index())->is_drawn; - - if (LayerNeedsUpdate(layer_impl, layer_is_drawn, property_trees)) - visible_layer_list->push_back(layer_impl); - } -} - -} // namespace - template <typename LayerType> static inline bool LayerShouldBeSkippedInternal( LayerType* layer, @@ -701,6 +461,7 @@ static inline bool LayerShouldBeSkippedInternal( if (effect_node->has_render_surface && effect_node->num_copy_requests_in_subtree > 0) return false; + // If the layer transform is not invertible, it should be skipped. // TODO(ajuma): Correctly process subtrees with singular transform for the // case where we may animate to a non-singular transform and wish to @@ -709,6 +470,345 @@ static inline bool LayerShouldBeSkippedInternal( effect_node->hidden_by_backface_visibility || !effect_node->is_drawn; } +template <typename LayerType> +static void UpdateElasticOverscrollInternal( + PropertyTrees* property_trees, + const LayerType* overscroll_elasticity_layer, + const gfx::Vector2dF& elastic_overscroll) { + if (!overscroll_elasticity_layer) { + DCHECK(elastic_overscroll.IsZero()); + return; + } + + TransformNode* node = property_trees->transform_tree.Node( + overscroll_elasticity_layer->transform_tree_index()); + DCHECK(node); + + // TODO(pdr): This is a workaround for https://crbug.com/721772 to avoid + // crashing when there's no transform node. This workaround should be removed. + if (!node) + return; + + if (node->scroll_offset == gfx::ScrollOffset(elastic_overscroll)) + return; + + node->scroll_offset = gfx::ScrollOffset(elastic_overscroll); + node->needs_local_transform_update = true; + property_trees->transform_tree.set_needs_update(true); +} + +#if DCHECK_IS_ON() +static void ValidatePageScaleLayer(const Layer* page_scale_layer) { + DCHECK_EQ(page_scale_layer->position().ToString(), gfx::PointF().ToString()); + DCHECK_EQ(page_scale_layer->transform_origin().ToString(), + gfx::Point3F().ToString()); +} + +static void ValidatePageScaleLayer(const LayerImpl* page_scale_layer) {} +#endif + +template <typename LayerType> +static void UpdatePageScaleFactorInternal(PropertyTrees* property_trees, + const LayerType* page_scale_layer, + float page_scale_factor, + float device_scale_factor, + gfx::Transform device_transform) { + if (property_trees->transform_tree.page_scale_factor() == page_scale_factor) + return; + + property_trees->transform_tree.set_page_scale_factor(page_scale_factor); + DCHECK(page_scale_layer); + DCHECK_GE(page_scale_layer->transform_tree_index(), + TransformTree::kRootNodeId); + TransformNode* node = property_trees->transform_tree.Node( + page_scale_layer->transform_tree_index()); +// TODO(enne): property trees can't ask the layer these things, but +// the page scale layer should *just* be the page scale. +#if DCHECK_IS_ON() + ValidatePageScaleLayer(page_scale_layer); +#endif + + if (IsRootLayer(page_scale_layer)) { + // When the page scale layer is also the root layer, the node should also + // store the combined scale factor and not just the page scale factor. + float post_local_scale_factor = page_scale_factor * device_scale_factor; + node->post_local_scale_factor = post_local_scale_factor; + node->post_local = device_transform; + node->post_local.Scale(post_local_scale_factor, post_local_scale_factor); + } else { + node->post_local_scale_factor = page_scale_factor; + node->update_post_local_transform(gfx::PointF(), gfx::Point3F()); + } + node->needs_local_transform_update = true; + property_trees->transform_tree.set_needs_update(true); +} + +static gfx::Rect LayerDrawableContentRect( + const LayerImpl* layer, + const gfx::Rect& layer_bounds_in_target_space, + const gfx::Rect& clip_rect) { + if (layer->is_clipped()) + return IntersectRects(layer_bounds_in_target_space, clip_rect); + + return layer_bounds_in_target_space; +} + +static void SetSurfaceIsClipped(const ClipTree& clip_tree, + RenderSurfaceImpl* render_surface) { + bool is_clipped; + if (render_surface->EffectTreeIndex() == EffectTree::kContentsRootNodeId) { + // Root render surface is always clipped. + is_clipped = true; + } else if (render_surface->has_contributing_layer_that_escapes_clip()) { + // We cannot clip a surface that has a contribuitng layer which escapes the + // clip. + is_clipped = false; + } else if (render_surface->ClipTreeIndex() == + render_surface->render_target()->ClipTreeIndex()) { + // There is no clip between between the render surface and its target, so + // the surface need not be clipped. + is_clipped = false; + } else { + // If the clips between the render surface and its target only expand the + // clips and do not apply any new clip, we need not clip the render surface. + const ClipNode* clip_node = clip_tree.Node(render_surface->ClipTreeIndex()); + is_clipped = clip_node->clip_type != ClipNode::ClipType::EXPANDS_CLIP; + } + render_surface->SetIsClipped(is_clipped); +} + +static void SetSurfaceDrawOpacity(const EffectTree& tree, + RenderSurfaceImpl* render_surface) { + // Draw opacity of a surface is the product of opacities between the surface + // (included) and its target surface (excluded). + const EffectNode* node = tree.Node(render_surface->EffectTreeIndex()); + float draw_opacity = tree.EffectiveOpacity(node); + for (node = tree.parent(node); node && !node->has_render_surface; + node = tree.parent(node)) { + draw_opacity *= tree.EffectiveOpacity(node); + } + render_surface->SetDrawOpacity(draw_opacity); +} + +static float LayerDrawOpacity(const LayerImpl* layer, const EffectTree& tree) { + if (!layer->render_target()) + return 0.f; + + const EffectNode* target_node = + tree.Node(layer->render_target()->EffectTreeIndex()); + const EffectNode* node = tree.Node(layer->effect_tree_index()); + if (node == target_node) + return 1.f; + + float draw_opacity = 1.f; + while (node != target_node) { + draw_opacity *= tree.EffectiveOpacity(node); + node = tree.parent(node); + } + return draw_opacity; +} + +template <typename LayerType> +static gfx::Transform ScreenSpaceTransformInternal(LayerType* layer, + const TransformTree& tree) { + gfx::Transform xform(1, 0, 0, 1, layer->offset_to_transform_parent().x(), + layer->offset_to_transform_parent().y()); + gfx::Transform ssxform = tree.ToScreen(layer->transform_tree_index()); + xform.ConcatTransform(ssxform); + if (layer->should_flatten_transform_from_property_tree()) + xform.FlattenTo2d(); + return xform; +} + +static void SetSurfaceClipRect(const ClipNode* parent_clip_node, + PropertyTrees* property_trees, + RenderSurfaceImpl* render_surface) { + if (!render_surface->is_clipped()) { + render_surface->SetClipRect(gfx::Rect()); + return; + } + + const EffectTree& effect_tree = property_trees->effect_tree; + const ClipTree& clip_tree = property_trees->clip_tree; + const EffectNode* effect_node = + effect_tree.Node(render_surface->EffectTreeIndex()); + const EffectNode* target_node = effect_tree.Node(effect_node->target_id); + bool include_expanding_clips = false; + if (render_surface->EffectTreeIndex() == EffectTree::kContentsRootNodeId) { + render_surface->SetClipRect( + gfx::ToEnclosingRect(clip_tree.Node(effect_node->clip_id)->clip)); + } else { + ConditionalClip accumulated_clip_rect = + ComputeAccumulatedClip(property_trees, include_expanding_clips, + effect_node->clip_id, target_node->id); + render_surface->SetClipRect( + gfx::ToEnclosingRect(accumulated_clip_rect.clip_rect)); + } +} + +static void SetSurfaceDrawTransform(const PropertyTrees* property_trees, + RenderSurfaceImpl* render_surface) { + const TransformTree& transform_tree = property_trees->transform_tree; + const EffectTree& effect_tree = property_trees->effect_tree; + const TransformNode* transform_node = + transform_tree.Node(render_surface->TransformTreeIndex()); + const EffectNode* effect_node = + effect_tree.Node(render_surface->EffectTreeIndex()); + // The draw transform of root render surface is identity tranform. + if (transform_node->id == TransformTree::kRootNodeId) { + render_surface->SetDrawTransform(gfx::Transform()); + return; + } + + gfx::Transform render_surface_transform; + const EffectNode* target_effect_node = + effect_tree.Node(effect_node->target_id); + property_trees->GetToTarget(transform_node->id, target_effect_node->id, + &render_surface_transform); + + ConcatInverseSurfaceContentsScale(effect_node, &render_surface_transform); + render_surface->SetDrawTransform(render_surface_transform); +} + +static gfx::Rect LayerVisibleRect(PropertyTrees* property_trees, + LayerImpl* layer) { + int effect_ancestor_with_copy_request = + property_trees->effect_tree.ClosestAncestorWithCopyRequest( + layer->effect_tree_index()); + bool non_root_copy_request = + effect_ancestor_with_copy_request > EffectTree::kContentsRootNodeId; + gfx::Rect layer_content_rect = gfx::Rect(layer->bounds()); + gfx::RectF accumulated_clip_in_root_space; + if (non_root_copy_request) { + bool include_expanding_clips = true; + ConditionalClip accumulated_clip = ComputeAccumulatedClip( + property_trees, include_expanding_clips, layer->clip_tree_index(), + effect_ancestor_with_copy_request); + if (!accumulated_clip.is_clipped) + return layer_content_rect; + accumulated_clip_in_root_space = accumulated_clip.clip_rect; + } else { + const ClipNode* clip_node = + property_trees->clip_tree.Node(layer->clip_tree_index()); + accumulated_clip_in_root_space = + clip_node->cached_accumulated_rect_in_screen_space; + } + + const EffectNode* root_effect_node = + non_root_copy_request + ? property_trees->effect_tree.Node(effect_ancestor_with_copy_request) + : property_trees->effect_tree.Node(EffectTree::kContentsRootNodeId); + ConditionalClip accumulated_clip_in_layer_space = + ComputeTargetRectInLocalSpace( + accumulated_clip_in_root_space, property_trees, + root_effect_node->transform_id, layer->transform_tree_index(), + root_effect_node->id); + if (!accumulated_clip_in_layer_space.is_clipped) { + return layer_content_rect; + } + gfx::RectF clip_in_layer_space = accumulated_clip_in_layer_space.clip_rect; + clip_in_layer_space.Offset(-layer->offset_to_transform_parent()); + + gfx::Rect visible_rect = gfx::ToEnclosingRect(clip_in_layer_space); + visible_rect.Intersect(layer_content_rect); + return visible_rect; +} + +static ConditionalClip LayerClipRect(PropertyTrees* property_trees, + LayerImpl* layer) { + const EffectTree* effect_tree = &property_trees->effect_tree; + const EffectNode* effect_node = effect_tree->Node(layer->effect_tree_index()); + const EffectNode* target_node = + effect_node->has_render_surface + ? effect_node + : effect_tree->Node(effect_node->target_id); + // TODO(weiliangc): When effect node has up to date render surface info on + // compositor thread, no need to check for resourceless draw mode + if (!property_trees->non_root_surfaces_enabled) { + target_node = effect_tree->Node(1); + } + + bool include_expanding_clips = false; + return ComputeAccumulatedClip(property_trees, include_expanding_clips, + layer->clip_tree_index(), target_node->id); +} + +static void UpdateRenderTarget(EffectTree* effect_tree, + bool can_render_to_separate_surface) { + for (int i = EffectTree::kContentsRootNodeId; + i < static_cast<int>(effect_tree->size()); ++i) { + EffectNode* node = effect_tree->Node(i); + if (i == EffectTree::kContentsRootNodeId) { + // Render target of the node corresponding to root is itself. + node->target_id = EffectTree::kContentsRootNodeId; + } else if (!can_render_to_separate_surface) { + node->target_id = EffectTree::kContentsRootNodeId; + } else if (effect_tree->parent(node)->has_render_surface) { + node->target_id = node->parent_id; + } else { + node->target_id = effect_tree->parent(node)->target_id; + } + } +} + +static void UpdateScrollTree(ScrollTree* scroll_tree, + const LayerTreeHost* layer_tree_host) { + if (!scroll_tree->needs_update()) + return; + + for (int i = ScrollTree::kRootNodeId; + i < static_cast<int>(scroll_tree->size()); ++i) { + ScrollNode* scroll_node = scroll_tree->Node(i); + if (Layer* scroll_layer = + layer_tree_host->LayerById(scroll_node->owning_layer_id)) { + if (Layer* scroll_clip_layer = scroll_layer->scroll_clip_layer()) { + scroll_node->scroll_clip_layer_bounds = scroll_clip_layer->bounds(); + } + } + } +} + +static void ComputeClips(PropertyTrees* property_trees) { + DCHECK(!property_trees->transform_tree.needs_update()); + ClipTree* clip_tree = &property_trees->clip_tree; + if (!clip_tree->needs_update()) + return; + const int target_effect_id = EffectTree::kContentsRootNodeId; + const int target_transform_id = TransformTree::kRootNodeId; + const bool include_expanding_clips = true; + for (int i = ClipTree::kViewportNodeId; + i < static_cast<int>(clip_tree->size()); ++i) { + ClipNode* clip_node = clip_tree->Node(i); + // Clear the clip rect cache + clip_node->cached_clip_rects = std::vector<ClipRectData>(1); + if (clip_node->id == ClipTree::kViewportNodeId) { + clip_node->cached_accumulated_rect_in_screen_space = clip_node->clip; + continue; + } + ClipNode* parent_clip_node = clip_tree->parent(clip_node); + DCHECK(parent_clip_node); + gfx::RectF accumulated_clip = + parent_clip_node->cached_accumulated_rect_in_screen_space; + bool success = ApplyClipNodeToAccumulatedClip( + property_trees, include_expanding_clips, target_effect_id, + target_transform_id, clip_node, &accumulated_clip); + DCHECK(success); + clip_node->cached_accumulated_rect_in_screen_space = accumulated_clip; + } + clip_tree->set_needs_update(false); +} + +} // namespace + +void ConcatInverseSurfaceContentsScale(const EffectNode* effect_node, + gfx::Transform* transform) { + DCHECK(effect_node->has_render_surface); + if (effect_node->surface_contents_scale.x() != 0.0 && + effect_node->surface_contents_scale.y() != 0.0) + transform->Scale(1.0 / effect_node->surface_contents_scale.x(), + 1.0 / effect_node->surface_contents_scale.y()); +} + bool LayerShouldBeSkipped(LayerImpl* layer, const TransformTree& transform_tree, const EffectTree& effect_tree) { @@ -745,184 +845,31 @@ void FindLayersThatNeedUpdates(LayerTreeHost* layer_tree_host, } } -static void ResetIfHasNanCoordinate(gfx::RectF* rect) { - if (std::isnan(rect->x()) || std::isnan(rect->y()) || - std::isnan(rect->right()) || std::isnan(rect->bottom())) - *rect = gfx::RectF(); -} - -void PostConcatSurfaceContentsScale(const EffectNode* effect_node, - gfx::Transform* transform) { - if (!effect_node) { - // This can happen when PaintArtifactCompositor builds property trees as it - // doesn't set effect ids on clip nodes. - return; - } - DCHECK(effect_node->has_render_surface); - transform->matrix().postScale(effect_node->surface_contents_scale.x(), - effect_node->surface_contents_scale.y(), 1.f); -} - -void ConcatInverseSurfaceContentsScale(const EffectNode* effect_node, - gfx::Transform* transform) { - DCHECK(effect_node->has_render_surface); - if (effect_node->surface_contents_scale.x() != 0.0 && - effect_node->surface_contents_scale.y() != 0.0) - transform->Scale(1.0 / effect_node->surface_contents_scale.x(), - 1.0 / effect_node->surface_contents_scale.y()); -} - -void ComputeClips(PropertyTrees* property_trees, - bool non_root_surfaces_enabled) { - ClipTree* clip_tree = &property_trees->clip_tree; - if (!clip_tree->needs_update()) - return; - for (int i = ClipTree::kViewportNodeId; - i < static_cast<int>(clip_tree->size()); ++i) { - ClipNode* clip_node = clip_tree->Node(i); +void FindLayersThatNeedUpdates(LayerTreeImpl* layer_tree_impl, + const PropertyTrees* property_trees, + std::vector<LayerImpl*>* visible_layer_list) { + const TransformTree& transform_tree = property_trees->transform_tree; + const EffectTree& effect_tree = property_trees->effect_tree; - if (clip_node->id == ClipTree::kViewportNodeId) { - ResetIfHasNanCoordinate(&clip_node->clip); - clip_node->clip_in_target_space = clip_node->clip; - clip_node->combined_clip_in_target_space = clip_node->clip; + for (auto* layer_impl : *layer_tree_impl) { + DCHECK(layer_impl); + DCHECK(layer_impl->layer_tree_impl()); + // TODO(crbug.com/726423) : This is a workaround for crbug.com/725851 to + // avoid crashing when layer_impl is nullptr. This workaround should be + // removed as layer_impl should not be nullptr here. + if (!layer_impl || !layer_impl->HasValidPropertyTreeIndices()) continue; - } - const TransformTree& transform_tree = property_trees->transform_tree; - const EffectTree& effect_tree = property_trees->effect_tree; - const TransformNode* transform_node = - transform_tree.Node(clip_node->transform_id); - ClipNode* parent_clip_node = clip_tree->parent(clip_node); - bool target_is_clipped = - effect_tree.Node(clip_node->target_effect_id)->surface_is_clipped; - - gfx::Transform parent_to_current; - const TransformNode* parent_target_transform_node = - transform_tree.Node(parent_clip_node->target_transform_id); - bool success = true; - - // Clips must be combined in target space. We cannot, for example, combine - // clips in the space of the child clip. The reason is non-affine - // transforms. Say we have the following tree T->A->B->C, and B clips C, but - // draw into target T. It may be the case that A applies a perspective - // transform, and B and C are at different z positions. When projected into - // target space, the relative sizes and positions of B and C can shift. - // Since it's the relationship in target space that matters, that's where we - // must combine clips. For each clip node, we save the clip rects in its - // target space. So, we need to get the ancestor clip rect in the current - // clip node's target space. - gfx::RectF parent_combined_clip_in_target_space = - parent_clip_node->combined_clip_in_target_space; - gfx::RectF parent_clip_in_target_space = - parent_clip_node->clip_in_target_space; - if (parent_target_transform_node && - parent_target_transform_node->id != clip_node->target_transform_id && - non_root_surfaces_enabled) { - success &= property_trees->GetFromTarget( - clip_node->target_transform_id, parent_clip_node->target_effect_id, - &parent_to_current); - const EffectNode* target_effect_node = - effect_tree.Node(clip_node->target_effect_id); - PostConcatSurfaceContentsScale(target_effect_node, &parent_to_current); - // If we can't compute a transform, it's because we had to use the inverse - // of a singular transform. We won't draw in this case, so there's no need - // to compute clips. - if (!success) - continue; - parent_combined_clip_in_target_space = MathUtil::ProjectClippedRect( - parent_to_current, parent_clip_node->combined_clip_in_target_space); - if (clip_node->clip_type == ClipNode::ClipType::EXPANDS_CLIP) { - parent_combined_clip_in_target_space = - gfx::RectF(clip_node->clip_expander->MapRectReverse( - gfx::ToEnclosingRect(parent_combined_clip_in_target_space), - property_trees)); - } - parent_clip_in_target_space = MathUtil::ProjectClippedRect( - parent_to_current, parent_clip_node->clip_in_target_space); - } - // Only nodes affected by ancestor clips will have their clip adjusted due - // to intersecting with an ancestor clip. But, we still need to propagate - // the combined clip to our children because if they are clipped, they may - // need to clip using our parent clip and if we don't propagate it here, - // it will be lost. - if (clip_node->resets_clip && non_root_surfaces_enabled) { - if (clip_node->clip_type == ClipNode::ClipType::APPLIES_LOCAL_CLIP) { - gfx::Transform to_target; - property_trees->GetToTarget(clip_node->transform_id, - clip_node->target_effect_id, &to_target); - clip_node->clip_in_target_space = - MathUtil::MapClippedRect(to_target, clip_node->clip); - ResetIfHasNanCoordinate(&clip_node->clip_in_target_space); - clip_node->combined_clip_in_target_space = - gfx::IntersectRects(clip_node->clip_in_target_space, - parent_combined_clip_in_target_space); - } else { - DCHECK(!target_is_clipped); - DCHECK(!clip_node->layers_are_clipped); - clip_node->combined_clip_in_target_space = - parent_combined_clip_in_target_space; - } - ResetIfHasNanCoordinate(&clip_node->combined_clip_in_target_space); + if (!IsRootLayer(layer_impl) && + LayerShouldBeSkipped(layer_impl, transform_tree, effect_tree)) continue; - } - bool use_only_parent_clip = - clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP; - if (use_only_parent_clip) { - clip_node->combined_clip_in_target_space = - parent_combined_clip_in_target_space; - if (!non_root_surfaces_enabled) { - clip_node->clip_in_target_space = - parent_clip_node->clip_in_target_space; - } else if (!target_is_clipped) { - clip_node->clip_in_target_space = parent_clip_in_target_space; - } else { - // Render Surface applies clip and the owning layer itself applies - // no clip. So, clip_in_target_space is not used and hence we can set - // it to an empty rect. - clip_node->clip_in_target_space = gfx::RectF(); - } - } else { - gfx::Transform source_to_target; - - if (!non_root_surfaces_enabled) { - source_to_target = transform_tree.ToScreen(clip_node->transform_id); - } else if (transform_tree.ContentTargetId(transform_node->id) == - clip_node->target_transform_id) { - property_trees->GetToTarget(clip_node->transform_id, - clip_node->target_effect_id, - &source_to_target); - } else { - success = property_trees->GetToTarget( - transform_node->id, clip_node->target_effect_id, &source_to_target); - // source_to_target computation should be successful as target is an - // ancestor of the transform node. - DCHECK(success); - } - gfx::RectF source_clip_in_target_space = - MathUtil::MapClippedRect(source_to_target, clip_node->clip); - - // With surfaces disabled, the only case where we use only the local clip - // for layer clipping is the case where no non-viewport ancestor node - // applies a local clip. - bool layer_clipping_uses_only_local_clip = - non_root_surfaces_enabled - ? clip_node->layer_clipping_uses_only_local_clip - : !parent_clip_node->layers_are_clipped_when_surfaces_disabled; - if (!layer_clipping_uses_only_local_clip) { - clip_node->clip_in_target_space = gfx::IntersectRects( - parent_clip_in_target_space, source_clip_in_target_space); - } else { - clip_node->clip_in_target_space = source_clip_in_target_space; - } + bool layer_is_drawn = + effect_tree.Node(layer_impl->effect_tree_index())->is_drawn; - clip_node->combined_clip_in_target_space = gfx::IntersectRects( - parent_combined_clip_in_target_space, source_clip_in_target_space); - } - ResetIfHasNanCoordinate(&clip_node->clip_in_target_space); - ResetIfHasNanCoordinate(&clip_node->combined_clip_in_target_space); + if (LayerNeedsUpdate(layer_impl, layer_is_drawn, property_trees)) + visible_layer_list->push_back(layer_impl); } - clip_tree->set_needs_update(false); } void ComputeTransforms(TransformTree* transform_tree) { @@ -934,24 +881,6 @@ void ComputeTransforms(TransformTree* transform_tree) { transform_tree->set_needs_update(false); } -void UpdateRenderTarget(EffectTree* effect_tree, - bool can_render_to_separate_surface) { - for (int i = EffectTree::kContentsRootNodeId; - i < static_cast<int>(effect_tree->size()); ++i) { - EffectNode* node = effect_tree->Node(i); - if (i == EffectTree::kContentsRootNodeId) { - // Render target of the node corresponding to root is itself. - node->target_id = EffectTree::kContentsRootNodeId; - } else if (!can_render_to_separate_surface) { - node->target_id = EffectTree::kContentsRootNodeId; - } else if (effect_tree->parent(node)->has_render_surface) { - node->target_id = node->parent_id; - } else { - node->target_id = effect_tree->parent(node)->target_id; - } - } -} - void ComputeEffects(EffectTree* effect_tree) { if (!effect_tree->needs_update()) return; @@ -961,220 +890,62 @@ void ComputeEffects(EffectTree* effect_tree) { effect_tree->set_needs_update(false); } -static void ComputeClipsWithEffectTree(PropertyTrees* property_trees) { - EffectTree* effect_tree = &property_trees->effect_tree; - const ClipTree* clip_tree = &property_trees->clip_tree; - EffectNode* root_effect_node = - effect_tree->Node(EffectTree::kContentsRootNodeId); - const RenderSurfaceImpl* root_render_surface = - effect_tree->GetRenderSurface(EffectTree::kContentsRootNodeId); - gfx::Rect root_clip = - gfx::ToEnclosingRect(clip_tree->Node(root_effect_node->clip_id)->clip); - if (root_render_surface->is_clipped()) - DCHECK(root_clip == root_render_surface->clip_rect()) - << "clip on root render surface: " - << root_render_surface->clip_rect().ToString() - << " v.s. root effect node's clip: " << root_clip.ToString(); - for (int i = 2; i < static_cast<int>(effect_tree->size()); ++i) { - EffectNode* effect_node = effect_tree->Node(i); - const EffectNode* target_node = effect_tree->Node(effect_node->target_id); - bool include_viewport_clip = false; - bool include_expanding_clips = false; - ConditionalClip accumulated_clip_rect = ComputeAccumulatedClip( - property_trees, include_viewport_clip, include_expanding_clips, - effect_node->clip_id, target_node->id); - gfx::RectF accumulated_clip = accumulated_clip_rect.clip_rect; - const RenderSurfaceImpl* render_surface = effect_tree->GetRenderSurface(i); - if (render_surface && render_surface->is_clipped()) { - DCHECK(gfx::ToEnclosingRect(accumulated_clip) == - render_surface->clip_rect()) - << " render surface's clip rect: " - << render_surface->clip_rect().ToString() - << " v.s. accumulated clip: " - << gfx::ToEnclosingRect(accumulated_clip).ToString(); - } - } -} - -static void ComputeLayerClipRect(const PropertyTrees* property_trees, - const LayerImpl* layer) { - const EffectTree* effect_tree = &property_trees->effect_tree; - const ClipTree* clip_tree = &property_trees->clip_tree; - const ClipNode* clip_node = clip_tree->Node(layer->clip_tree_index()); - const EffectNode* effect_node = effect_tree->Node(layer->effect_tree_index()); - const EffectNode* target_node = - effect_node->has_render_surface - ? effect_node - : effect_tree->Node(effect_node->target_id); - // TODO(weiliangc): When effect node has up to date render surface info on - // compositor thread, no need to check for resourceless draw mode - if (!property_trees->non_root_surfaces_enabled) { - target_node = effect_tree->Node(1); - } - - bool include_viewport_clip = false; - bool include_expanding_clips = false; - ConditionalClip accumulated_clip_rect = ComputeAccumulatedClip( - property_trees, include_viewport_clip, include_expanding_clips, - layer->clip_tree_index(), target_node->id); - - bool is_clipped_from_clip_tree = - property_trees->non_root_surfaces_enabled - ? clip_node->layers_are_clipped - : clip_node->layers_are_clipped_when_surfaces_disabled; - DCHECK_EQ(is_clipped_from_clip_tree, accumulated_clip_rect.is_clipped); - - gfx::RectF accumulated_clip = accumulated_clip_rect.clip_rect; - - DCHECK(layer->clip_rect() == gfx::ToEnclosingRect(accumulated_clip)) - << " layer: " << layer->id() << " clip id: " << layer->clip_tree_index() - << " layer clip: " << layer->clip_rect().ToString() << " v.s. " - << gfx::ToEnclosingRect(accumulated_clip).ToString() - << " and clip node clip: " - << gfx::ToEnclosingRect(clip_node->clip_in_target_space).ToString(); -} - -void ComputeVisibleRects(LayerImpl* root_layer, +void UpdatePropertyTrees(LayerTreeHost* layer_tree_host, PropertyTrees* property_trees, - bool can_render_to_separate_surface, - LayerImplList* visible_layer_list) { - bool render_surfaces_need_update = false; + bool can_render_to_separate_surface) { + DCHECK(layer_tree_host); + DCHECK(property_trees); + DCHECK_EQ(layer_tree_host->property_trees(), property_trees); if (property_trees->non_root_surfaces_enabled != can_render_to_separate_surface) { property_trees->non_root_surfaces_enabled = can_render_to_separate_surface; property_trees->transform_tree.set_needs_update(true); - render_surfaces_need_update = true; } if (property_trees->transform_tree.needs_update()) { property_trees->clip_tree.set_needs_update(true); property_trees->effect_tree.set_needs_update(true); } - - if (render_surfaces_need_update) { - property_trees->effect_tree.UpdateRenderSurfaces( - root_layer->layer_tree_impl(), - property_trees->non_root_surfaces_enabled); - } - UpdateRenderTarget(&property_trees->effect_tree, - property_trees->non_root_surfaces_enabled); + UpdateScrollTree(&property_trees->scroll_tree, layer_tree_host); ComputeTransforms(&property_trees->transform_tree); - // Computation of clips uses surface contents scale which is updated while - // computing effects. So, ComputeEffects should be before ComputeClips. ComputeEffects(&property_trees->effect_tree); - ComputeClips(property_trees, can_render_to_separate_surface); - - FindLayersThatNeedUpdates(root_layer->layer_tree_impl(), property_trees, - visible_layer_list); - CalculateClipRects(*visible_layer_list, property_trees, - can_render_to_separate_surface); - CalculateVisibleRects(*visible_layer_list, property_trees, - can_render_to_separate_surface); + // Computation of clips uses ToScreen which is updated while computing + // transforms. So, ComputeTransforms should be before ComputeClips. + ComputeClips(property_trees); } -void UpdatePropertyTrees(PropertyTrees* property_trees, - bool can_render_to_separate_surface) { +void UpdatePropertyTreesAndRenderSurfaces(LayerImpl* root_layer, + PropertyTrees* property_trees, + bool can_render_to_separate_surface, + bool can_adjust_raster_scales) { + bool render_surfaces_need_update = false; if (property_trees->non_root_surfaces_enabled != can_render_to_separate_surface) { property_trees->non_root_surfaces_enabled = can_render_to_separate_surface; property_trees->transform_tree.set_needs_update(true); + render_surfaces_need_update = true; + } + if (property_trees->can_adjust_raster_scales != can_adjust_raster_scales) { + property_trees->can_adjust_raster_scales = can_adjust_raster_scales; + property_trees->transform_tree.set_needs_update(true); + render_surfaces_need_update = true; } if (property_trees->transform_tree.needs_update()) { property_trees->clip_tree.set_needs_update(true); property_trees->effect_tree.set_needs_update(true); } - ComputeTransforms(&property_trees->transform_tree); - // Computation of clips uses surface contents scale which is updated while - // computing effects. So, ComputeEffects should be before ComputeClips. - ComputeEffects(&property_trees->effect_tree); - ComputeClips(property_trees, can_render_to_separate_surface); -} - -void BuildPropertyTreesAndComputeVisibleRects( - LayerImpl* root_layer, - const LayerImpl* page_scale_layer, - const LayerImpl* inner_viewport_scroll_layer, - const LayerImpl* outer_viewport_scroll_layer, - const LayerImpl* overscroll_elasticity_layer, - const gfx::Vector2dF& elastic_overscroll, - float page_scale_factor, - float device_scale_factor, - const gfx::Rect& viewport, - const gfx::Transform& device_transform, - bool can_render_to_separate_surface, - PropertyTrees* property_trees, - LayerImplList* visible_layer_list) { - PropertyTreeBuilder::BuildPropertyTrees( - root_layer, page_scale_layer, inner_viewport_scroll_layer, - outer_viewport_scroll_layer, overscroll_elasticity_layer, - elastic_overscroll, page_scale_factor, device_scale_factor, viewport, - device_transform, property_trees); - ComputeVisibleRects(root_layer, property_trees, - can_render_to_separate_surface, visible_layer_list); -} - -void VerifyClipTreeCalculations(const LayerImplList& layer_list, - PropertyTrees* property_trees) { - if (property_trees->non_root_surfaces_enabled) { - ComputeClipsWithEffectTree(property_trees); - } - for (auto* layer : layer_list) - ComputeLayerClipRect(property_trees, layer); -} - -gfx::Rect ComputeLayerVisibleRectDynamic(const PropertyTrees* property_trees, - const LayerImpl* layer) { - int effect_ancestor_with_copy_request = - property_trees->effect_tree.ClosestAncestorWithCopyRequest( - layer->effect_tree_index()); - bool non_root_copy_request = - effect_ancestor_with_copy_request > EffectTree::kContentsRootNodeId; - gfx::Rect layer_content_rect = gfx::Rect(layer->bounds()); - gfx::RectF accumulated_clip_in_root_space; - if (non_root_copy_request) { - bool include_viewport_clip = false; - bool include_expanding_clips = true; - ConditionalClip accumulated_clip = ComputeAccumulatedClip( - property_trees, include_viewport_clip, include_expanding_clips, - layer->clip_tree_index(), effect_ancestor_with_copy_request); - if (!accumulated_clip.is_clipped) - return layer_content_rect; - accumulated_clip_in_root_space = accumulated_clip.clip_rect; - } else { - accumulated_clip_in_root_space = - ComputeAccumulatedClipInRootSpaceForVisibleRect( - property_trees, layer->clip_tree_index()); + if (render_surfaces_need_update) { + property_trees->effect_tree.UpdateRenderSurfaces( + root_layer->layer_tree_impl(), + property_trees->non_root_surfaces_enabled); } + UpdateRenderTarget(&property_trees->effect_tree, + property_trees->non_root_surfaces_enabled); - const EffectNode* root_effect_node = - non_root_copy_request - ? property_trees->effect_tree.Node(effect_ancestor_with_copy_request) - : property_trees->effect_tree.Node(EffectTree::kContentsRootNodeId); - ConditionalClip accumulated_clip_in_layer_space = - ComputeTargetRectInLocalSpace( - accumulated_clip_in_root_space, property_trees, - root_effect_node->transform_id, layer->transform_tree_index(), - root_effect_node->id); - if (!accumulated_clip_in_layer_space.is_clipped) - return layer_content_rect; - gfx::RectF clip_in_layer_space = accumulated_clip_in_layer_space.clip_rect; - clip_in_layer_space.Offset(-layer->offset_to_transform_parent()); - - gfx::Rect visible_rect = gfx::ToEnclosingRect(clip_in_layer_space); - visible_rect.Intersect(layer_content_rect); - return visible_rect; -} - -void VerifyVisibleRectsCalculations(const LayerImplList& layer_list, - const PropertyTrees* property_trees) { - for (auto* layer : layer_list) { - gfx::Rect visible_rect_dynamic = - ComputeLayerVisibleRectDynamic(property_trees, layer); - DCHECK(layer->visible_layer_rect() == visible_rect_dynamic) - << " layer: " << layer->id() << " clip id: " << layer->clip_tree_index() - << " visible rect cached: " << layer->visible_layer_rect().ToString() - << " v.s. " - << " visible rect dynamic: " << visible_rect_dynamic.ToString(); - } + ComputeTransforms(&property_trees->transform_tree); + ComputeEffects(&property_trees->effect_tree); + // Computation of clips uses ToScreen which is updated while computing + // transforms. So, ComputeTransforms should be before ComputeClips. + ComputeClips(property_trees); } bool LayerNeedsUpdate(Layer* layer, @@ -1209,88 +980,6 @@ gfx::Transform DrawTransform(const LayerImpl* layer, return xform; } -static void SetSurfaceDrawTransform(const PropertyTrees* property_trees, - RenderSurfaceImpl* render_surface) { - const TransformTree& transform_tree = property_trees->transform_tree; - const EffectTree& effect_tree = property_trees->effect_tree; - const TransformNode* transform_node = - transform_tree.Node(render_surface->TransformTreeIndex()); - const EffectNode* effect_node = - effect_tree.Node(render_surface->EffectTreeIndex()); - // The draw transform of root render surface is identity tranform. - if (transform_node->id == TransformTree::kRootNodeId) { - render_surface->SetDrawTransform(gfx::Transform()); - return; - } - - gfx::Transform render_surface_transform; - const EffectNode* target_effect_node = - effect_tree.Node(effect_node->target_id); - property_trees->GetToTarget(transform_node->id, target_effect_node->id, - &render_surface_transform); - - ConcatInverseSurfaceContentsScale(effect_node, &render_surface_transform); - render_surface->SetDrawTransform(render_surface_transform); -} - -static void SetSurfaceClipRect(const ClipNode* parent_clip_node, - const PropertyTrees* property_trees, - RenderSurfaceImpl* render_surface) { - if (!render_surface->is_clipped()) { - render_surface->SetClipRect(gfx::Rect()); - return; - } - - const EffectTree& effect_tree = property_trees->effect_tree; - const TransformTree& transform_tree = property_trees->transform_tree; - const TransformNode* transform_node = - transform_tree.Node(render_surface->TransformTreeIndex()); - if (transform_tree.TargetId(transform_node->id) == - parent_clip_node->target_transform_id) { - render_surface->SetClipRect( - gfx::ToEnclosingRect(parent_clip_node->clip_in_target_space)); - return; - } - - // In this case, the clip child has reset the clip node for subtree and hence - // the parent clip node's clip rect is in clip parent's target space and not - // our target space. We need to transform it to our target space. - gfx::Transform clip_parent_target_to_target; - const EffectNode* effect_node = - effect_tree.Node(render_surface->EffectTreeIndex()); - int target_effect_id = effect_node->target_id; - const bool success = property_trees->GetToTarget( - parent_clip_node->target_transform_id, target_effect_id, - &clip_parent_target_to_target); - - if (!success) { - render_surface->SetClipRect(gfx::Rect()); - return; - } - - if (parent_clip_node->target_transform_id < - transform_tree.TargetId(transform_node->id)) { - render_surface->SetClipRect(gfx::ToEnclosingRect( - MathUtil::ProjectClippedRect(clip_parent_target_to_target, - parent_clip_node->clip_in_target_space))); - } else { - render_surface->SetClipRect(gfx::ToEnclosingRect(MathUtil::MapClippedRect( - clip_parent_target_to_target, parent_clip_node->clip_in_target_space))); - } -} - -template <typename LayerType> -static gfx::Transform ScreenSpaceTransformInternal(LayerType* layer, - const TransformTree& tree) { - gfx::Transform xform(1, 0, 0, 1, layer->offset_to_transform_parent().x(), - layer->offset_to_transform_parent().y()); - gfx::Transform ssxform = tree.ToScreen(layer->transform_tree_index()); - xform.ConcatTransform(ssxform); - if (layer->should_flatten_transform_from_property_tree()) - xform.FlattenTo2d(); - return xform; -} - gfx::Transform ScreenSpaceTransform(const Layer* layer, const TransformTree& tree) { return ScreenSpaceTransformInternal(layer, tree); @@ -1301,81 +990,68 @@ gfx::Transform ScreenSpaceTransform(const LayerImpl* layer, return ScreenSpaceTransformInternal(layer, tree); } -static float LayerDrawOpacity(const LayerImpl* layer, const EffectTree& tree) { - if (!layer->render_target()) - return 0.f; - - const EffectNode* target_node = - tree.Node(layer->render_target()->EffectTreeIndex()); - const EffectNode* node = tree.Node(layer->effect_tree_index()); - if (node == target_node) - return 1.f; - - float draw_opacity = 1.f; - while (node != target_node) { - draw_opacity *= tree.EffectiveOpacity(node); - node = tree.parent(node); +void ComputeDrawPropertiesOfVisibleLayers(const LayerImplList* layer_list, + PropertyTrees* property_trees) { + // Compute transforms + for (LayerImpl* layer : *layer_list) { + const TransformNode* transform_node = + property_trees->transform_tree.Node(layer->transform_tree_index()); + + layer->draw_properties().screen_space_transform = + ScreenSpaceTransformInternal(layer, property_trees->transform_tree); + layer->draw_properties().target_space_transform = DrawTransform( + layer, property_trees->transform_tree, property_trees->effect_tree); + layer->draw_properties().screen_space_transform_is_animating = + transform_node->to_screen_is_potentially_animated; } - return draw_opacity; -} -static void SetSurfaceDrawOpacity(const EffectTree& tree, - RenderSurfaceImpl* render_surface) { - // Draw opacity of a surface is the product of opacities between the surface - // (included) and its target surface (excluded). - const EffectNode* node = tree.Node(render_surface->EffectTreeIndex()); - float draw_opacity = tree.EffectiveOpacity(node); - for (node = tree.parent(node); node && !node->has_render_surface; - node = tree.parent(node)) { - draw_opacity *= tree.EffectiveOpacity(node); + // Compute effects and determine if render surfaces have contributing layers + // that escape clip. + for (LayerImpl* layer : *layer_list) { + layer->draw_properties().opacity = + LayerDrawOpacity(layer, property_trees->effect_tree); + RenderSurfaceImpl* render_target = layer->render_target(); + int lca_clip_id = LowestCommonAncestor(layer->clip_tree_index(), + render_target->ClipTreeIndex(), + &property_trees->clip_tree); + if (lca_clip_id != render_target->ClipTreeIndex()) { + SetHasContributingLayerThatEscapesClip(lca_clip_id, + render_target->EffectTreeIndex(), + &property_trees->effect_tree); + } } - render_surface->SetDrawOpacity(draw_opacity); -} -static gfx::Rect LayerDrawableContentRect( - const LayerImpl* layer, - const gfx::Rect& layer_bounds_in_target_space, - const gfx::Rect& clip_rect) { - if (layer->is_clipped()) - return IntersectRects(layer_bounds_in_target_space, clip_rect); - - return layer_bounds_in_target_space; -} - -void ComputeLayerDrawProperties(LayerImpl* layer, - const PropertyTrees* property_trees) { - const TransformNode* transform_node = - property_trees->transform_tree.Node(layer->transform_tree_index()); - const ClipNode* clip_node = - property_trees->clip_tree.Node(layer->clip_tree_index()); - - layer->draw_properties().screen_space_transform = - ScreenSpaceTransformInternal(layer, property_trees->transform_tree); - layer->draw_properties().target_space_transform = DrawTransform( - layer, property_trees->transform_tree, property_trees->effect_tree); - layer->draw_properties().screen_space_transform_is_animating = - transform_node->to_screen_is_potentially_animated; - - layer->draw_properties().opacity = - LayerDrawOpacity(layer, property_trees->effect_tree); - if (property_trees->non_root_surfaces_enabled) { - layer->draw_properties().is_clipped = clip_node->layers_are_clipped; - } else { - layer->draw_properties().is_clipped = - clip_node->layers_are_clipped_when_surfaces_disabled; + // Compute clips and visible rects + for (LayerImpl* layer : *layer_list) { + ConditionalClip clip = LayerClipRect(property_trees, layer); + // is_clipped should be set before visible rect computation as it is used + // there. + layer->draw_properties().is_clipped = clip.is_clipped; + layer->draw_properties().clip_rect = gfx::ToEnclosingRect(clip.clip_rect); + layer->draw_properties().visible_layer_rect = + LayerVisibleRect(property_trees, layer); } - gfx::Rect bounds_in_target_space = MathUtil::MapEnclosingClippedRect( - layer->draw_properties().target_space_transform, - gfx::Rect(layer->bounds())); - layer->draw_properties().drawable_content_rect = LayerDrawableContentRect( - layer, bounds_in_target_space, layer->draw_properties().clip_rect); + // Compute drawable content rects + for (LayerImpl* layer : *layer_list) { + gfx::Rect bounds_in_target_space = MathUtil::MapEnclosingClippedRect( + layer->draw_properties().target_space_transform, + gfx::Rect(layer->bounds())); + layer->draw_properties().drawable_content_rect = LayerDrawableContentRect( + layer, bounds_in_target_space, layer->draw_properties().clip_rect); + } } void ComputeMaskDrawProperties(LayerImpl* mask_layer, const PropertyTrees* property_trees) { // Mask draw properties are used only for rastering, so most of the draw // properties computed for other layers are not needed. + // Draw transform of a mask layer has to be a 2d scale. + // TODO(sunxd): the draw transform of a mask layer misses the "scale to fit" + // factor from mask layer to its parent. So does the screen space transform. + // It does not cause a problem because currently we only have 1:1 mask layer. + mask_layer->draw_properties().target_space_transform = DrawTransform( + mask_layer, property_trees->transform_tree, property_trees->effect_tree); mask_layer->draw_properties().screen_space_transform = ScreenSpaceTransformInternal(mask_layer, property_trees->transform_tree); @@ -1383,11 +1059,10 @@ void ComputeMaskDrawProperties(LayerImpl* mask_layer, gfx::Rect(mask_layer->bounds()); } -void ComputeSurfaceDrawProperties(const PropertyTrees* property_trees, - RenderSurfaceImpl* render_surface) { - const EffectNode* effect_node = - property_trees->effect_tree.Node(render_surface->EffectTreeIndex()); - render_surface->SetIsClipped(effect_node->surface_is_clipped); +void ComputeSurfaceDrawProperties(PropertyTrees* property_trees, + RenderSurfaceImpl* render_surface, + const bool use_layer_lists) { + SetSurfaceIsClipped(property_trees->clip_tree, render_surface); SetSurfaceDrawOpacity(property_trees->effect_tree, render_surface); SetSurfaceDrawTransform(property_trees, render_surface); render_surface->SetScreenSpaceTransform( @@ -1400,52 +1075,6 @@ void ComputeSurfaceDrawProperties(const PropertyTrees* property_trees, SetSurfaceClipRect(clip_node, property_trees, render_surface); } -#if DCHECK_IS_ON() -static void ValidatePageScaleLayer(const Layer* page_scale_layer) { - DCHECK_EQ(page_scale_layer->position().ToString(), gfx::PointF().ToString()); - DCHECK_EQ(page_scale_layer->transform_origin().ToString(), - gfx::Point3F().ToString()); -} - -static void ValidatePageScaleLayer(const LayerImpl* page_scale_layer) {} -#endif - -template <typename LayerType> -static void UpdatePageScaleFactorInternal(PropertyTrees* property_trees, - const LayerType* page_scale_layer, - float page_scale_factor, - float device_scale_factor, - gfx::Transform device_transform) { - if (property_trees->transform_tree.page_scale_factor() == page_scale_factor) - return; - - property_trees->transform_tree.set_page_scale_factor(page_scale_factor); - DCHECK(page_scale_layer); - DCHECK_GE(page_scale_layer->transform_tree_index(), - TransformTree::kRootNodeId); - TransformNode* node = property_trees->transform_tree.Node( - page_scale_layer->transform_tree_index()); - // TODO(enne): property trees can't ask the layer these things, but - // the page scale layer should *just* be the page scale. -#if DCHECK_IS_ON() - ValidatePageScaleLayer(page_scale_layer); -#endif - - if (IsRootLayer(page_scale_layer)) { - // When the page scale layer is also the root layer, the node should also - // store the combined scale factor and not just the page scale factor. - float post_local_scale_factor = page_scale_factor * device_scale_factor; - node->post_local_scale_factor = post_local_scale_factor; - node->post_local = device_transform; - node->post_local.Scale(post_local_scale_factor, post_local_scale_factor); - } else { - node->post_local_scale_factor = page_scale_factor; - node->update_post_local_transform(gfx::PointF(), gfx::Point3F()); - } - node->needs_local_transform_update = true; - property_trees->transform_tree.set_needs_update(true); -} - void UpdatePageScaleFactor(PropertyTrees* property_trees, const LayerImpl* page_scale_layer, float page_scale_factor, @@ -1466,26 +1095,6 @@ void UpdatePageScaleFactor(PropertyTrees* property_trees, device_transform); } -template <typename LayerType> -static void UpdateElasticOverscrollInternal( - PropertyTrees* property_trees, - const LayerType* overscroll_elasticity_layer, - const gfx::Vector2dF& elastic_overscroll) { - if (!overscroll_elasticity_layer) { - DCHECK(elastic_overscroll.IsZero()); - return; - } - - TransformNode* node = property_trees->transform_tree.Node( - overscroll_elasticity_layer->transform_tree_index()); - if (node->scroll_offset == gfx::ScrollOffset(elastic_overscroll)) - return; - - node->scroll_offset = gfx::ScrollOffset(elastic_overscroll); - node->needs_local_transform_update = true; - property_trees->transform_tree.set_needs_update(true); -} - void UpdateElasticOverscroll(PropertyTrees* property_trees, const LayerImpl* overscroll_elasticity_layer, const gfx::Vector2dF& elastic_overscroll) { diff --git a/chromium/cc/trees/draw_property_utils.h b/chromium/cc/trees/draw_property_utils.h index 4f19d144f88..b5ff981c579 100644 --- a/chromium/cc/trees/draw_property_utils.h +++ b/chromium/cc/trees/draw_property_utils.h @@ -5,11 +5,10 @@ #ifndef CC_TREES_DRAW_PROPERTY_UTILS_H_ #define CC_TREES_DRAW_PROPERTY_UTILS_H_ -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/layer_collections.h" namespace gfx { -class Rect; class Transform; class Vector2dF; } // namespace gfx @@ -19,6 +18,7 @@ namespace cc { class Layer; class LayerImpl; class LayerTreeHost; +class LayerTreeImpl; class RenderSurfaceImpl; class EffectTree; class TransformTree; @@ -27,15 +27,8 @@ struct EffectNode; namespace draw_property_utils { -void CC_EXPORT PostConcatSurfaceContentsScale(const EffectNode* effect_node, - gfx::Transform* transform); - void CC_EXPORT ConcatInverseSurfaceContentsScale(const EffectNode* effect_node, gfx::Transform* transform); -// Computes combined clips for every node in |clip_tree|. This function requires -// that |transform_tree| has been updated via |ComputeTransforms|. -void CC_EXPORT ComputeClips(PropertyTrees* property_trees, - bool non_root_surfaces_enabled); // Computes combined (screen space) transforms for every node in the transform // tree. This must be done prior to calling |ComputeClips|. @@ -44,48 +37,36 @@ void CC_EXPORT ComputeTransforms(TransformTree* transform_tree); // Computes screen space opacity for every node in the opacity tree. void CC_EXPORT ComputeEffects(EffectTree* effect_tree); -void CC_EXPORT BuildPropertyTreesAndComputeVisibleRects( - LayerImpl* root_layer, - const LayerImpl* page_scale_layer, - const LayerImpl* inner_viewport_scroll_layer, - const LayerImpl* outer_viewport_scroll_layer, - const LayerImpl* overscroll_elasticity_layer, - const gfx::Vector2dF& elastic_overscroll, - float page_scale_factor, - float device_scale_factor, - const gfx::Rect& viewport, - const gfx::Transform& device_transform, - bool can_render_to_separate_surface, - PropertyTrees* property_trees, - LayerImplList* visible_layer_list); - -void CC_EXPORT UpdatePropertyTrees(PropertyTrees* property_trees, + +void CC_EXPORT UpdatePropertyTrees(LayerTreeHost* layer_tree_host, + PropertyTrees* property_trees, bool can_render_to_separate_surface); +void CC_EXPORT +UpdatePropertyTreesAndRenderSurfaces(LayerImpl* root_layer, + PropertyTrees* property_trees, + bool can_render_to_separate_surface, + bool can_adjust_raster_scales); + void CC_EXPORT FindLayersThatNeedUpdates(LayerTreeHost* layer_tree_host, const PropertyTrees* property_trees, LayerList* update_layer_list); -void CC_EXPORT ComputeVisibleRects(LayerImpl* root_layer, - PropertyTrees* property_trees, - bool can_render_to_separate_surface, - LayerImplList* visible_layer_list); - -gfx::Rect CC_EXPORT -ComputeLayerVisibleRectDynamic(const PropertyTrees* property_trees, - const LayerImpl* layer); void CC_EXPORT -VerifyVisibleRectsCalculations(const LayerImplList& layer_list, - const PropertyTrees* property_trees); +FindLayersThatNeedUpdates(LayerTreeImpl* layer_tree_impl, + const PropertyTrees* property_trees, + std::vector<LayerImpl*>* visible_layer_list); -void CC_EXPORT ComputeLayerDrawProperties(LayerImpl* layer, - const PropertyTrees* property_trees); +void CC_EXPORT +ComputeDrawPropertiesOfVisibleLayers(const LayerImplList* layer_list, + PropertyTrees* property_trees); void CC_EXPORT ComputeMaskDrawProperties(LayerImpl* mask_layer, const PropertyTrees* property_trees); -void CC_EXPORT ComputeSurfaceDrawProperties(const PropertyTrees* property_trees, - RenderSurfaceImpl* render_surface); +void CC_EXPORT ComputeSurfaceDrawProperties(PropertyTrees* property_trees, + RenderSurfaceImpl* render_surface, + const bool use_layer_lists); bool CC_EXPORT LayerShouldBeSkipped(LayerImpl* layer, const TransformTree& transform_tree, @@ -99,9 +80,6 @@ bool CC_EXPORT LayerNeedsUpdate(LayerImpl* layer, bool layer_is_drawn, const PropertyTrees* property_trees); -void CC_EXPORT VerifyClipTreeCalculations(const LayerImplList& layer_list, - PropertyTrees* property_trees); - gfx::Transform CC_EXPORT DrawTransform(const LayerImpl* layer, const TransformTree& transform_tree, const EffectTree& effect_tree); diff --git a/chromium/cc/trees/effect_node.cc b/chromium/cc/trees/effect_node.cc index 5385b35286c..142cb08db41 100644 --- a/chromium/cc/trees/effect_node.cc +++ b/chromium/cc/trees/effect_node.cc @@ -17,7 +17,6 @@ EffectNode::EffectNode() screen_space_opacity(1.f), blend_mode(SkBlendMode::kSrcOver), has_render_surface(false), - surface_is_clipped(false), has_copy_request(false), hidden_by_backface_visibility(false), double_sided(false), @@ -29,7 +28,6 @@ EffectNode::EffectNode() is_currently_animating_opacity(false), effect_changed(false), num_copy_requests_in_subtree(0), - has_unclipped_descendants(false), transform_id(0), clip_id(0), target_id(1), @@ -42,7 +40,6 @@ bool EffectNode::operator==(const EffectNode& other) const { owning_layer_id == other.owning_layer_id && opacity == other.opacity && screen_space_opacity == other.screen_space_opacity && has_render_surface == other.has_render_surface && - surface_is_clipped == other.surface_is_clipped && has_copy_request == other.has_copy_request && filters == other.filters && background_filters == other.background_filters && @@ -72,7 +69,6 @@ void EffectNode::AsValueInto(base::trace_event::TracedValue* value) const { value->SetInteger("owning_layer_id", owning_layer_id); value->SetDouble("opacity", opacity); value->SetBoolean("has_render_surface", has_render_surface); - value->SetBoolean("surface_is_clipped", surface_is_clipped); value->SetBoolean("has_copy_request", has_copy_request); value->SetBoolean("double_sided", double_sided); value->SetBoolean("is_drawn", is_drawn); diff --git a/chromium/cc/trees/effect_node.h b/chromium/cc/trees/effect_node.h index a5a1385de5b..48997c03823 100644 --- a/chromium/cc/trees/effect_node.h +++ b/chromium/cc/trees/effect_node.h @@ -5,8 +5,8 @@ #ifndef CC_TREES_EFFECT_NODE_H_ #define CC_TREES_EFFECT_NODE_H_ -#include "cc/base/cc_export.h" -#include "cc/output/filter_operations.h" +#include "cc/base/filter_operations.h" +#include "cc/cc_export.h" #include "third_party/skia/include/core/SkBlendMode.h" #include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/size_f.h" @@ -44,13 +44,6 @@ struct CC_EXPORT EffectNode { gfx::Size unscaled_mask_target_size; bool has_render_surface; - // Only applicable if has render surface. A true value means a clip needs to - // be applied to the output of the surface when it is drawn onto its parent - // surface. - // TODO(crbug.com/504464): There is ongoing work to delay render surface - // decision to later phase of the pipeline. This flag shall be removed and - // computed during render surface decision. - bool surface_is_clipped; bool has_copy_request; bool hidden_by_backface_visibility; bool double_sided; @@ -66,7 +59,6 @@ struct CC_EXPORT EffectNode { // rect. bool effect_changed; int num_copy_requests_in_subtree; - bool has_unclipped_descendants; int transform_id; int clip_id; // Effect node id of which this effect contributes to. diff --git a/chromium/cc/trees/element_id.h b/chromium/cc/trees/element_id.h index 4c0b652cc88..74de4c9995f 100644 --- a/chromium/cc/trees/element_id.h +++ b/chromium/cc/trees/element_id.h @@ -13,7 +13,7 @@ #include <memory> #include "base/hash.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace base { class Value; diff --git a/chromium/cc/trees/frame_rate_counter.cc b/chromium/cc/trees/frame_rate_counter.cc new file mode 100644 index 00000000000..f801dbf640d --- /dev/null +++ b/chromium/cc/trees/frame_rate_counter.cc @@ -0,0 +1,145 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/trees/frame_rate_counter.h" + +#include <stddef.h> + +#include <algorithm> +#include <limits> + +#include "base/memory/ptr_util.h" +#include "base/metrics/histogram_macros.h" + +namespace cc { + +// The following constants are measured in seconds. + +// Two thresholds (measured in seconds) that describe what is considered to be a +// "no-op frame" that should not be counted. +// - if the frame is too fast, then given our compositor implementation, the +// frame probably was a no-op and did not draw. +// - if the frame is too slow, then there is probably not animating content, so +// we should not pollute the average. +static const double kFrameTooFast = 1.0 / 70.0; +static const double kFrameTooSlow = 1.5; + +// If a frame takes longer than this threshold (measured in seconds) then we +// (naively) assume that it missed a screen refresh; that is, we dropped a +// frame. +// TODO(brianderson): Determine this threshold based on monitor refresh rate, +// crbug.com/138642. +static const double kDroppedFrameTime = 1.0 / 50.0; + +// static +std::unique_ptr<FrameRateCounter> FrameRateCounter::Create( + bool has_impl_thread) { + return base::WrapUnique(new FrameRateCounter(has_impl_thread)); +} + +base::TimeDelta FrameRateCounter::RecentFrameInterval(size_t n) const { + DCHECK_GT(n, 0u); + DCHECK_LT(n, ring_buffer_.BufferSize()); + return ring_buffer_.ReadBuffer(n) - ring_buffer_.ReadBuffer(n - 1); +} + +FrameRateCounter::FrameRateCounter(bool has_impl_thread) + : has_impl_thread_(has_impl_thread), dropped_frame_count_(0) {} + +void FrameRateCounter::SaveTimeStamp(base::TimeTicks timestamp, bool software) { + ring_buffer_.SaveToBuffer(timestamp); + + // Check if frame interval can be computed. + if (ring_buffer_.CurrentIndex() < 2) + return; + + base::TimeDelta frame_interval_seconds = + RecentFrameInterval(ring_buffer_.BufferSize() - 1); + + if (has_impl_thread_ && ring_buffer_.CurrentIndex() > 0) { + if (software) { + UMA_HISTOGRAM_CUSTOM_COUNTS( + "Renderer4.SoftwareCompositorThreadImplDrawDelay", + frame_interval_seconds.InMilliseconds(), 1, 120, 60); + } else { + UMA_HISTOGRAM_CUSTOM_COUNTS("Renderer4.CompositorThreadImplDrawDelay", + frame_interval_seconds.InMilliseconds(), 1, + 120, 60); + } + } + + if (!IsBadFrameInterval(frame_interval_seconds) && + frame_interval_seconds.InSecondsF() > kDroppedFrameTime) + dropped_frame_count_ += + frame_interval_seconds.InSecondsF() / kDroppedFrameTime; +} + +bool FrameRateCounter::IsBadFrameInterval( + base::TimeDelta interval_between_consecutive_frames) const { + double delta = interval_between_consecutive_frames.InSecondsF(); + bool scheduler_allows_double_frames = !has_impl_thread_; + bool interval_too_fast = + scheduler_allows_double_frames ? delta < kFrameTooFast : delta <= 0.0; + bool interval_too_slow = delta > kFrameTooSlow; + return interval_too_fast || interval_too_slow; +} + +void FrameRateCounter::GetMinAndMaxFPS(double* min_fps, double* max_fps) const { + *min_fps = std::numeric_limits<double>::max(); + *max_fps = 0.0; + + for (RingBufferType::Iterator it = --ring_buffer_.End(); it; --it) { + base::TimeDelta delta = RecentFrameInterval(it.index() + 1); + + if (IsBadFrameInterval(delta)) + continue; + + DCHECK_GT(delta.InSecondsF(), 0.f); + double fps = 1.0 / delta.InSecondsF(); + + *min_fps = std::min(fps, *min_fps); + *max_fps = std::max(fps, *max_fps); + } + + if (*min_fps > *max_fps) + *min_fps = *max_fps; +} + +double FrameRateCounter::GetAverageFPS() const { + int frame_count = 0; + double frame_times_total = 0.0; + double average_fps = 0.0; + + // Walk backwards through the samples looking for a run of good frame + // timings from which to compute the mean. + // + // Slow frames occur just because the user is inactive, and should be + // ignored. Fast frames are ignored if the scheduler is in single-thread + // mode in order to represent the true frame rate in spite of the fact that + // the first few swapbuffers happen instantly which skews the statistics + // too much for short lived animations. + // + // IsBadFrameInterval encapsulates the frame too slow/frame too fast logic. + + for (RingBufferType::Iterator it = --ring_buffer_.End(); + it && frame_times_total < 1.0; --it) { + base::TimeDelta delta = RecentFrameInterval(it.index() + 1); + + if (!IsBadFrameInterval(delta)) { + frame_count++; + frame_times_total += delta.InSecondsF(); + } else if (frame_count) { + break; + } + } + + if (frame_count) { + DCHECK_GT(frame_times_total, 0.0); + average_fps = frame_count / frame_times_total; + } + + return average_fps; +} + +} // namespace cc diff --git a/chromium/cc/trees/frame_rate_counter.h b/chromium/cc/trees/frame_rate_counter.h new file mode 100644 index 00000000000..83e8cf7151f --- /dev/null +++ b/chromium/cc/trees/frame_rate_counter.h @@ -0,0 +1,60 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_TREES_FRAME_RATE_COUNTER_H_ +#define CC_TREES_FRAME_RATE_COUNTER_H_ + +#include <stddef.h> + +#include <memory> + +#include "base/macros.h" +#include "base/time/time.h" +#include "cc/base/ring_buffer.h" + +namespace cc { + +// This class maintains a history of timestamps, and provides functionality to +// intelligently compute average frames per second. +class FrameRateCounter { + public: + static std::unique_ptr<FrameRateCounter> Create(bool has_impl_thread); + + size_t current_frame_number() const { return ring_buffer_.CurrentIndex(); } + int dropped_frame_count() const { return dropped_frame_count_; } + size_t time_stamp_history_size() const { return ring_buffer_.BufferSize(); } + + void SaveTimeStamp(base::TimeTicks timestamp, bool software); + + // n = 0 returns the oldest frame interval retained in the history, while n = + // time_stamp_history_size() - 1 returns the most recent frame interval. + base::TimeDelta RecentFrameInterval(size_t n) const; + + // This is a heuristic that can be used to ignore frames in a reasonable way. + // Returns true if the given frame interval is too fast or too slow, based on + // constant thresholds. + bool IsBadFrameInterval( + base::TimeDelta interval_between_consecutive_frames) const; + + void GetMinAndMaxFPS(double* min_fps, double* max_fps) const; + double GetAverageFPS() const; + + typedef RingBuffer<base::TimeTicks, 136> RingBufferType; + RingBufferType::Iterator begin() const { return ring_buffer_.Begin(); } + RingBufferType::Iterator end() const { return ring_buffer_.End(); } + + private: + explicit FrameRateCounter(bool has_impl_thread); + + RingBufferType ring_buffer_; + + bool has_impl_thread_; + int dropped_frame_count_; + + DISALLOW_COPY_AND_ASSIGN(FrameRateCounter); +}; + +} // namespace cc + +#endif // CC_TREES_FRAME_RATE_COUNTER_H_ diff --git a/chromium/cc/trees/layer_tree_host.cc b/chromium/cc/trees/layer_tree_host.cc index 942d5938681..e8a6f4b0c07 100644 --- a/chromium/cc/trees/layer_tree_host.cc +++ b/chromium/cc/trees/layer_tree_host.cc @@ -29,19 +29,18 @@ #include "base/timer/elapsed_timer.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" +#include "cc/base/devtools_instrumentation.h" #include "cc/base/histograms.h" #include "cc/base/math_util.h" -#include "cc/debug/devtools_instrumentation.h" -#include "cc/debug/frame_viewer_instrumentation.h" #include "cc/debug/rendering_stats_instrumentation.h" #include "cc/input/layer_selection_bound.h" #include "cc/input/page_scale_animation.h" #include "cc/layers/heads_up_display_layer.h" #include "cc/layers/heads_up_display_layer_impl.h" #include "cc/layers/layer.h" -#include "cc/layers/layer_iterator.h" #include "cc/layers/painted_scrollbar_layer.h" #include "cc/resources/ui_resource_manager.h" +#include "cc/tiles/frame_viewer_instrumentation.h" #include "cc/trees/draw_property_utils.h" #include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_host_client.h" @@ -161,6 +160,8 @@ void LayerTreeHost::InitializeProxy(std::unique_ptr<Proxy> proxy) { proxy_ = std::move(proxy); proxy_->Start(); + UpdateDeferCommitsInternal(); + mutator_host_->SetSupportsScrollAnimations(proxy_->SupportsImplScrolling()); } @@ -315,6 +316,11 @@ void LayerTreeHost::FinishCommitOnImplThread( sync_tree->SetDeviceScaleFactor(device_scale_factor_); host_impl->SetDebugState(debug_state_); + if (did_navigate_) { + did_navigate_ = false; + host_impl->ClearImageCacheOnNavigation(); + } + sync_tree->set_ui_resource_request_queue( ui_resource_manager_->TakeUIResourcesRequests()); @@ -340,6 +346,11 @@ void LayerTreeHost::FinishCommitOnImplThread( mutator_host_->PushPropertiesTo(host_impl->mutator_host()); } + // Transfer image decode requests to the impl thread. + for (auto& request : queued_image_decodes_) + host_impl->QueueImageDecode(std::move(request.first), request.second); + queued_image_decodes_.clear(); + micro_benchmark_controller_.ScheduleImplBenchmarks(host_impl); property_trees_.ResetAllChangeTracking(); } @@ -349,7 +360,12 @@ void LayerTreeHost::WillCommit() { client_->WillCommit(); } -void LayerTreeHost::UpdateHudLayer() {} + +void LayerTreeHost::UpdateDeferCommitsInternal() { + proxy_->SetDeferCommits(defer_commits_ || + (settings_.enable_surface_synchronization && + !local_surface_id_.is_valid())); +} void LayerTreeHost::CommitComplete() { source_frame_number_++; @@ -427,7 +443,10 @@ void LayerTreeHost::DidLoseCompositorFrameSink() { } void LayerTreeHost::SetDeferCommits(bool defer_commits) { - proxy_->SetDeferCommits(defer_commits); + if (defer_commits_ == defer_commits) + return; + defer_commits_ = defer_commits; + UpdateDeferCommitsInternal(); } DISABLE_CFI_PERF @@ -464,9 +483,9 @@ void LayerTreeHost::SetNextCommitWaitsForActivation() { proxy_->SetNextCommitWaitsForActivation(); } -void LayerTreeHost::SetNextCommitForcesRedraw() { +void LayerTreeHost::SetNeedsCommitWithForcedRedraw() { next_commit_forces_redraw_ = true; - proxy_->SetNeedsUpdateLayers(); + proxy_->SetNeedsCommit(); } void LayerTreeHost::SetAnimationEvents( @@ -581,7 +600,7 @@ bool LayerTreeHost::UpdateLayers() { ->Add(timer.Elapsed().InMicroseconds()); } - return result || next_commit_forces_redraw_; + return result; } void LayerTreeHost::DidCompletePageScaleAnimation() { @@ -630,7 +649,6 @@ bool LayerTreeHost::DoUpdateLayers(Layer* root_layer) { "source_frame_number", SourceFrameNumber()); UpdateHudLayer(debug_state_.ShowHudInfo()); - UpdateHudLayer(); Layer* root_scroll = PropertyTreeBuilder::FindFirstScrollableLayer(root_layer); @@ -641,6 +659,16 @@ bool LayerTreeHost::DoUpdateLayers(Layer* root_layer) { if (hud_layer_) { hud_layer_->PrepareForCalculateDrawProperties(device_viewport_size_, device_scale_factor_); + // The HUD layer is managed outside the layer list sent to LayerTreeHost + // and needs to have its property tree state set. + if (settings_.use_layer_lists && root_layer_.get()) { + hud_layer_->SetTransformTreeIndex(root_layer_->transform_tree_index()); + hud_layer_->SetEffectTreeIndex(root_layer_->effect_tree_index()); + hud_layer_->SetClipTreeIndex(root_layer_->clip_tree_index()); + hud_layer_->SetScrollTreeIndex(root_layer_->scroll_tree_index()); + hud_layer_->set_property_tree_sequence_number( + root_layer_->property_tree_sequence_number()); + } } gfx::Transform identity_transform; @@ -654,7 +682,6 @@ bool LayerTreeHost::DoUpdateLayers(Layer* root_layer) { TRACE_EVENT0( TRACE_DISABLED_BY_DEFAULT("cc.debug.cdp-perf"), "LayerTreeHostInProcessCommon::ComputeVisibleRectsWithPropertyTrees"); - PropertyTreeBuilder::PreCalculateMetaInformation(root_layer); bool can_render_to_separate_surface = true; PropertyTrees* property_trees = &property_trees_; if (!settings_.use_layer_lists) { @@ -675,7 +702,7 @@ bool LayerTreeHost::DoUpdateLayers(Layer* root_layer) { TRACE_EVENT_SCOPE_THREAD, "property_trees", property_trees->AsTracedValue()); } - draw_property_utils::UpdatePropertyTrees(property_trees, + draw_property_utils::UpdatePropertyTrees(this, property_trees, can_render_to_separate_surface); draw_property_utils::FindLayersThatNeedUpdates(this, property_trees, &update_layer_list); @@ -732,6 +759,16 @@ void LayerTreeHost::ApplyViewportDeltas(ScrollAndScaleSet* info) { SetNeedsUpdateLayers(); } +void LayerTreeHost::RecordWheelAndTouchScrollingCount(ScrollAndScaleSet* info) { + bool has_scrolled_by_wheel = info->has_scrolled_by_wheel; + bool has_scrolled_by_touch = info->has_scrolled_by_touch; + + if (has_scrolled_by_wheel || has_scrolled_by_touch) { + client_->RecordWheelAndTouchScrollingCount(has_scrolled_by_wheel, + has_scrolled_by_touch); + } +} + void LayerTreeHost::ApplyScrollAndScale(ScrollAndScaleSet* info) { for (auto& swap_promise : info->swap_promises) { TRACE_EVENT_WITH_FLOW1("input,benchmark", "LatencyInfo.Flow", @@ -762,6 +799,8 @@ void LayerTreeHost::ApplyScrollAndScale(ScrollAndScaleSet* info) { // controls from clamping the layout viewport both on the compositor and // on the main thread. ApplyViewportDeltas(info); + + RecordWheelAndTouchScrollingCount(info); } const base::WeakPtr<InputHandler>& LayerTreeHost::GetInputHandler() @@ -839,6 +878,7 @@ void LayerTreeHost::SetRootLayer(scoped_refptr<Layer> root_layer) { ResetGpuRasterizationTracking(); SetNeedsFullTreeSync(); + did_navigate_ = true; } void LayerTreeHost::RegisterViewportLayers( @@ -964,11 +1004,11 @@ void LayerTreeHost::SetPaintedDeviceScaleFactor( SetNeedsCommit(); } -void LayerTreeHost::SetDeviceColorSpace( - const gfx::ColorSpace& device_color_space) { - if (device_color_space_ == device_color_space) +void LayerTreeHost::SetRasterColorSpace( + const gfx::ColorSpace& raster_color_space) { + if (raster_color_space_ == raster_color_space) return; - device_color_space_ = device_color_space; + raster_color_space_ = raster_color_space; LayerTreeHostCommon::CallFunctionForEveryLayer( this, [](Layer* layer) { layer->SetNeedsDisplay(); }); } @@ -980,6 +1020,14 @@ void LayerTreeHost::SetContentSourceId(uint32_t id) { SetNeedsCommit(); } +void LayerTreeHost::SetLocalSurfaceId(const LocalSurfaceId& local_surface_id) { + if (local_surface_id_ == local_surface_id) + return; + local_surface_id_ = local_surface_id; + UpdateDeferCommitsInternal(); + SetNeedsCommit(); +} + void LayerTreeHost::RegisterLayer(Layer* layer) { DCHECK(!LayerById(layer->id())); DCHECK(!in_paint_layer_contents_); @@ -1038,10 +1086,6 @@ bool LayerTreeHost::LayerNeedsPushPropertiesForTesting(Layer* layer) const { layers_that_should_push_properties_.end(); } -void LayerTreeHost::SetNeedsMetaInfoRecomputation(bool needs_recomputation) { - needs_meta_info_recomputation_ = needs_recomputation; -} - void LayerTreeHost::SetPageScaleFromImplSide(float page_scale) { DCHECK(CommitRequested()); page_scale_factor_ = page_scale; @@ -1070,8 +1114,6 @@ void LayerTreeHost::UpdateHudLayer(bool show_hud_info) { void LayerTreeHost::SetNeedsFullTreeSync() { needs_full_tree_sync_ = true; - needs_meta_info_recomputation_ = true; - property_trees_.needs_rebuild = true; SetNeedsCommit(); } @@ -1148,10 +1190,12 @@ void LayerTreeHost::PushPropertiesTo(LayerTreeImpl* tree_impl) { tree_impl->set_painted_device_scale_factor(painted_device_scale_factor_); - tree_impl->SetDeviceColorSpace(device_color_space_); + tree_impl->SetRasterColorSpace(raster_color_space_); tree_impl->set_content_source_id(content_source_id_); + tree_impl->set_local_surface_id(local_surface_id_); + if (pending_page_scale_animation_) { tree_impl->SetPendingPageScaleAnimation( std::move(pending_page_scale_animation_)); @@ -1196,7 +1240,6 @@ void LayerTreeHost::SetElementIdsForTesting() { } void LayerTreeHost::BuildPropertyTreesForTesting() { - PropertyTreeBuilder::PreCalculateMetaInformation(root_layer()); gfx::Transform identity_transform; PropertyTreeBuilder::BuildPropertyTrees( root_layer(), page_scale_layer(), inner_viewport_scroll_layer(), @@ -1235,12 +1278,10 @@ void LayerTreeHost::SetElementOpacityMutated(ElementId element_id, DCHECK_LE(opacity, 1.f); layer->OnOpacityAnimated(opacity); - if (property_trees_.IsInIdToIndexMap(PropertyTrees::TreeType::EFFECT, - layer->id())) { - DCHECK_EQ(layer->effect_tree_index(), - property_trees_.layer_id_to_effect_node_index[layer->id()]); - EffectNode* node = - property_trees_.effect_tree.Node(layer->effect_tree_index()); + if (EffectNode* node = + property_trees_.effect_tree.UpdateNodeFromOwningLayerId( + layer->id())) { + DCHECK_EQ(layer->effect_tree_index(), node->id); if (node->opacity == opacity) return; @@ -1259,12 +1300,10 @@ void LayerTreeHost::SetElementTransformMutated( DCHECK(layer); layer->OnTransformAnimated(transform); - if (property_trees_.IsInIdToIndexMap(PropertyTrees::TreeType::TRANSFORM, - layer->id())) { - DCHECK_EQ(layer->transform_tree_index(), - property_trees_.layer_id_to_transform_node_index[layer->id()]); - TransformNode* node = - property_trees_.transform_tree.Node(layer->transform_tree_index()); + if (TransformNode* node = + property_trees_.transform_tree.UpdateNodeFromOwningLayerId( + layer->id())) { + DCHECK_EQ(layer->transform_tree_index(), node->id); if (node->local == transform) return; @@ -1291,9 +1330,79 @@ void LayerTreeHost::ElementIsAnimatingChanged( ElementListType list_type, const PropertyAnimationState& mask, const PropertyAnimationState& state) { - Layer* layer = LayerByElementId(element_id); - if (layer) - layer->OnIsAnimatingChanged(mask, state); + // TODO(weiliangc): Most of the code is duplicated with LayerTeeHostImpl + // version of function. Should try to share code. + DCHECK_EQ(ElementListType::ACTIVE, list_type); + + for (int property = TargetProperty::FIRST_TARGET_PROPERTY; + property <= TargetProperty::LAST_TARGET_PROPERTY; ++property) { + if (!mask.currently_running[property] && + !mask.potentially_animating[property]) + continue; + + switch (property) { + case TargetProperty::TRANSFORM: + if (TransformNode* transform_node = + property_trees()->transform_tree.FindNodeFromElementId( + element_id)) { + if (mask.currently_running[property]) + transform_node->is_currently_animating = + state.currently_running[property]; + if (mask.potentially_animating[property]) { + transform_node->has_potential_animation = + state.potentially_animating[property]; + transform_node->has_only_translation_animations = + mutator_host()->HasOnlyTranslationTransforms(element_id, + list_type); + property_trees()->transform_tree.set_needs_update(true); + } + } else { + if (state.currently_running[property] || + state.potentially_animating[property]) + DCHECK(property_trees()->needs_rebuild) + << "Attempting to animate non existent transform node"; + } + break; + case TargetProperty::OPACITY: + if (EffectNode* effect_node = + property_trees()->effect_tree.FindNodeFromElementId( + element_id)) { + if (mask.currently_running[property]) + effect_node->is_currently_animating_opacity = + state.currently_running[property]; + if (mask.potentially_animating[property]) { + effect_node->has_potential_opacity_animation = + state.potentially_animating[property]; + property_trees()->effect_tree.set_needs_update(true); + } + } else { + if (state.currently_running[property] || + state.potentially_animating[property]) + DCHECK(property_trees()->needs_rebuild) + << "Attempting to animate opacity on non existent effect node"; + } + break; + case TargetProperty::FILTER: + if (EffectNode* effect_node = + property_trees()->effect_tree.FindNodeFromElementId( + element_id)) { + if (mask.currently_running[property]) + effect_node->is_currently_animating_filter = + state.currently_running[property]; + if (mask.potentially_animating[property]) + effect_node->has_potential_filter_animation = + state.potentially_animating[property]; + } else { + if (state.currently_running[property] || + state.potentially_animating[property]) + DCHECK(property_trees()->needs_rebuild) + << "Attempting to animate filter on non existent effect node"; + } + break; + default: + break; + } + } } gfx::ScrollOffset LayerTreeHost::GetScrollOffsetForAnimation( @@ -1303,6 +1412,14 @@ gfx::ScrollOffset LayerTreeHost::GetScrollOffsetForAnimation( return layer->ScrollOffsetForAnimation(); } +void LayerTreeHost::QueueImageDecode( + sk_sp<const SkImage> image, + const base::Callback<void(bool)>& callback) { + TRACE_EVENT0("cc", "LayerTreeHost::QueueImageDecode"); + queued_image_decodes_.emplace_back(std::move(image), callback); + SetNeedsCommit(); +} + LayerListIterator<Layer> LayerTreeHost::begin() const { return LayerListIterator<Layer>(root_layer_.get()); } diff --git a/chromium/cc/trees/layer_tree_host.h b/chromium/cc/trees/layer_tree_host.h index 9a5deabf7aa..bf5520e2a39 100644 --- a/chromium/cc/trees/layer_tree_host.h +++ b/chromium/cc/trees/layer_tree_host.h @@ -20,9 +20,9 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" -#include "cc/base/cc_export.h" -#include "cc/debug/micro_benchmark.h" -#include "cc/debug/micro_benchmark_controller.h" +#include "cc/benchmarks/micro_benchmark.h" +#include "cc/benchmarks/micro_benchmark_controller.h" +#include "cc/cc_export.h" #include "cc/input/browser_controls_state.h" #include "cc/input/event_listener_properties.h" #include "cc/input/input_handler.h" @@ -45,6 +45,8 @@ #include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/geometry/rect.h" +class SkImage; + namespace cc { class HeadsUpDisplayLayer; class Layer; @@ -191,7 +193,7 @@ class CC_EXPORT LayerTreeHost : public NON_EXPORTED_BASE(SurfaceReferenceOwner), // Requests a main frame (including layer updates) and ensures that this main // frame results in a redraw for the complete viewport when producing the // CompositorFrame. - void SetNextCommitForcesRedraw(); + void SetNeedsCommitWithForcedRedraw(); // Input Handling --------------------------------------------- @@ -312,9 +314,14 @@ class CC_EXPORT LayerTreeHost : public NON_EXPORTED_BASE(SurfaceReferenceOwner), void SetContentSourceId(uint32_t); uint32_t content_source_id() const { return content_source_id_; } - void SetDeviceColorSpace(const gfx::ColorSpace& device_color_space); - const gfx::ColorSpace& device_color_space() const { - return device_color_space_; + // If this LayerTreeHost needs a valid LocalSurfaceId then commits will be + // deferred until a valid LocalSurfaceId is provided. + void SetLocalSurfaceId(const LocalSurfaceId& local_surface_id); + const LocalSurfaceId& local_surface_id() const { return local_surface_id_; } + + void SetRasterColorSpace(const gfx::ColorSpace& raster_color_space); + const gfx::ColorSpace& raster_color_space() const { + return raster_color_space_; } // Used externally by blink for setting the PropertyTrees when @@ -339,12 +346,6 @@ class CC_EXPORT LayerTreeHost : public NON_EXPORTED_BASE(SurfaceReferenceOwner), std::unordered_set<Layer*>& LayersThatShouldPushProperties(); bool LayerNeedsPushPropertiesForTesting(Layer* layer) const; - virtual void SetNeedsMetaInfoRecomputation( - bool needs_meta_info_recomputation); - bool needs_meta_info_recomputation() const { - return needs_meta_info_recomputation_; - } - void SetPageScaleFromImplSide(float page_scale); void SetElasticOverscrollFromImplSide(gfx::Vector2dF elastic_overscroll); gfx::Vector2dF elastic_overscroll() const { return elastic_overscroll_; } @@ -457,6 +458,9 @@ class CC_EXPORT LayerTreeHost : public NON_EXPORTED_BASE(SurfaceReferenceOwner), gfx::ScrollOffset GetScrollOffsetForAnimation( ElementId element_id) const override; + void QueueImageDecode(sk_sp<const SkImage> image, + const base::Callback<void(bool)>& callback); + protected: LayerTreeHost(InitParams* params, CompositorMode mode); @@ -496,15 +500,13 @@ class CC_EXPORT LayerTreeHost : public NON_EXPORTED_BASE(SurfaceReferenceOwner), enum { kNumFramesToConsiderBeforeGpuRasterization = 60 }; void ApplyViewportDeltas(ScrollAndScaleSet* info); + void RecordWheelAndTouchScrollingCount(ScrollAndScaleSet* info); void ApplyPageScaleDeltaFromImplSide(float page_scale_delta); void InitializeProxy(std::unique_ptr<Proxy> proxy); bool DoUpdateLayers(Layer* root_layer); - void UpdateHudLayer(); - - bool AnimateLayersRecursive(Layer* current, base::TimeTicks time); - void CalculateLCDTextMetricsCallback(Layer* layer); + void UpdateDeferCommitsInternal(); const CompositorMode compositor_mode_; @@ -571,9 +573,11 @@ class CC_EXPORT LayerTreeHost : public NON_EXPORTED_BASE(SurfaceReferenceOwner), float page_scale_factor_ = 1.f; float min_page_scale_factor_ = 1.f; float max_page_scale_factor_ = 1.f; - gfx::ColorSpace device_color_space_; + gfx::ColorSpace raster_color_space_; uint32_t content_source_id_; + LocalSurfaceId local_surface_id_; + bool defer_commits_ = false; SkColor background_color_ = SK_ColorWHITE; bool has_transparent_background_ = false; @@ -591,7 +595,6 @@ class CC_EXPORT LayerTreeHost : public NON_EXPORTED_BASE(SurfaceReferenceOwner), PropertyTrees property_trees_; bool needs_full_tree_sync_ = true; - bool needs_meta_info_recomputation_ = true; gfx::Vector2dF elastic_overscroll_; @@ -610,6 +613,11 @@ class CC_EXPORT LayerTreeHost : public NON_EXPORTED_BASE(SurfaceReferenceOwner), MutatorHost* mutator_host_; + std::vector<std::pair<sk_sp<const SkImage>, base::Callback<void(bool)>>> + queued_image_decodes_; + + bool did_navigate_ = false; + DISALLOW_COPY_AND_ASSIGN(LayerTreeHost); }; diff --git a/chromium/cc/trees/layer_tree_host_client.h b/chromium/cc/trees/layer_tree_host_client.h index c0fcb4bef14..84416d60ef0 100644 --- a/chromium/cc/trees/layer_tree_host_client.h +++ b/chromium/cc/trees/layer_tree_host_client.h @@ -43,6 +43,9 @@ class LayerTreeHostClient { const gfx::Vector2dF& elastic_overscroll_delta, float page_scale, float top_controls_delta) = 0; + virtual void RecordWheelAndTouchScrollingCount( + bool has_scrolled_by_wheel, + bool has_scrolled_by_touch) = 0; // Request an CompositorFrameSink from the client. When the client has one it // should call LayerTreeHost::SetCompositorFrameSink. This will result in // either DidFailToInitializeCompositorFrameSink or @@ -55,6 +58,10 @@ class LayerTreeHostClient { virtual void DidCommitAndDrawFrame() = 0; virtual void DidReceiveCompositorFrameAck() = 0; virtual void DidCompletePageScaleAnimation() = 0; + // The only time a subframe ever gets its own LayerTree is when the subframe + // renders in a different process its ancestors; this returns true in + // that case. + virtual bool IsForSubframe() = 0; protected: virtual ~LayerTreeHostClient() {} diff --git a/chromium/cc/trees/layer_tree_host_common.cc b/chromium/cc/trees/layer_tree_host_common.cc index 2e4ded747af..8d09c07ec1d 100644 --- a/chromium/cc/trees/layer_tree_host_common.cc +++ b/chromium/cc/trees/layer_tree_host_common.cc @@ -14,7 +14,6 @@ #include "cc/layers/heads_up_display_layer_impl.h" #include "cc/layers/layer.h" #include "cc/layers/layer_impl.h" -#include "cc/layers/layer_iterator.h" #include "cc/trees/draw_property_utils.h" #include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_host.h" @@ -80,8 +79,7 @@ LayerTreeHostCommon::CalcDrawPropsImplInputs::CalcDrawPropsImplInputs( int max_texture_size, bool can_render_to_separate_surface, bool can_adjust_raster_scales, - bool verify_clip_tree_calculations, - bool verify_visible_rect_calculations, + bool use_layer_lists, LayerImplList* render_surface_layer_list, PropertyTrees* property_trees) : root_layer(root_layer), @@ -98,8 +96,7 @@ LayerTreeHostCommon::CalcDrawPropsImplInputs::CalcDrawPropsImplInputs( max_texture_size(max_texture_size), can_render_to_separate_surface(can_render_to_separate_surface), can_adjust_raster_scales(can_adjust_raster_scales), - verify_clip_tree_calculations(verify_clip_tree_calculations), - verify_visible_rect_calculations(verify_visible_rect_calculations), + use_layer_lists(use_layer_lists), render_surface_layer_list(render_surface_layer_list), property_trees(property_trees) {} @@ -122,8 +119,7 @@ LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting:: std::numeric_limits<int>::max() / 2, true, false, - true, - true, + false, render_surface_layer_list, GetPropertyTrees(root_layer)) { DCHECK(root_layer); @@ -183,8 +179,10 @@ bool LayerTreeHostCommon::ScrollbarsUpdateInfo::operator==( } ScrollAndScaleSet::ScrollAndScaleSet() - : page_scale_delta(1.f), top_controls_delta(0.f) { -} + : page_scale_delta(1.f), + top_controls_delta(0.f), + has_scrolled_by_wheel(false), + has_scrolled_by_touch(false) {} ScrollAndScaleSet::~ScrollAndScaleSet() {} @@ -286,11 +284,23 @@ static void ComputeInitialRenderSurfaceLayerList( LayerTreeImpl* layer_tree_impl, PropertyTrees* property_trees, LayerImplList* render_surface_layer_list, - bool can_render_to_separate_surface) { + bool can_render_to_separate_surface, + bool use_layer_lists) { // Add all non-skipped surfaces to the initial render surface layer list. Add // all non-skipped layers to the layer list of their target surface, and // add their content rect to their target surface's accumulated content rect. for (LayerImpl* layer : *layer_tree_impl) { + DCHECK(layer); + + // TODO(crbug.com/726423): LayerImpls should never have invalid PropertyTree + // indices. + if (!layer) + continue; + + layer->set_is_drawn_render_surface_layer_list_member(false); + if (!layer->HasValidPropertyTreeIndices()) + continue; + RenderSurfaceImpl* render_surface = layer->GetRenderSurface(); if (render_surface) { render_surface->ClearLayerLists(); @@ -326,8 +336,8 @@ static void ComputeInitialRenderSurfaceLayerList( contributes_to_drawn_surface); } - draw_property_utils::ComputeSurfaceDrawProperties(property_trees, - render_surface); + draw_property_utils::ComputeSurfaceDrawProperties( + property_trees, render_surface, use_layer_lists); // Ignore occlusion from outside the surface when surface contents need to // be fully drawn. Layers with copy-request need to be complete. We could @@ -437,6 +447,7 @@ static void CalculateRenderSurfaceLayerList( PropertyTrees* property_trees, LayerImplList* render_surface_layer_list, const bool can_render_to_separate_surface, + const bool use_layer_lists, const int max_texture_size) { // This calculates top level Render Surface Layer List, and Layer List for all // Render Surfaces. @@ -447,9 +458,9 @@ static void CalculateRenderSurfaceLayerList( // First compute an RSLL that might include surfaces that later turn out to // have an empty content rect. After surface content rects are computed, // produce a final RSLL that omits empty surfaces. - ComputeInitialRenderSurfaceLayerList(layer_tree_impl, property_trees, - &initial_render_surface_list, - can_render_to_separate_surface); + ComputeInitialRenderSurfaceLayerList( + layer_tree_impl, property_trees, &initial_render_surface_list, + can_render_to_separate_surface, use_layer_lists); ComputeSurfaceContentRects(layer_tree_impl, property_trees, &initial_render_surface_list, max_texture_size); ComputeListOfNonEmptySurfaces(layer_tree_impl, property_trees, @@ -477,15 +488,18 @@ void CalculateDrawPropertiesInternal( "LayerTreeHostCommon::ComputeVisibleRectsWithPropertyTrees"); } - draw_property_utils::BuildPropertyTreesAndComputeVisibleRects( + PropertyTreeBuilder::BuildPropertyTrees( inputs->root_layer, inputs->page_scale_layer, inputs->inner_viewport_scroll_layer, inputs->outer_viewport_scroll_layer, inputs->elastic_overscroll_application_layer, inputs->elastic_overscroll, inputs->page_scale_factor, inputs->device_scale_factor, gfx::Rect(inputs->device_viewport_size), - inputs->device_transform, inputs->can_render_to_separate_surface, - inputs->property_trees, &visible_layer_list); + inputs->device_transform, inputs->property_trees); + draw_property_utils::UpdatePropertyTreesAndRenderSurfaces( + inputs->root_layer, inputs->property_trees, + inputs->can_render_to_separate_surface, + inputs->can_adjust_raster_scales); // Property trees are normally constructed on the main thread and // passed to compositor thread. Source to parent updates on them are not @@ -529,9 +543,10 @@ void CalculateDrawPropertiesInternal( property_trees->transform_tree.SetRootTransformsAndScales( inputs->device_scale_factor, page_scale_factor_for_root, inputs->device_transform, inputs->root_layer->position()); - draw_property_utils::ComputeVisibleRects( + draw_property_utils::UpdatePropertyTreesAndRenderSurfaces( inputs->root_layer, inputs->property_trees, - inputs->can_render_to_separate_surface, &visible_layer_list); + inputs->can_render_to_separate_surface, + inputs->can_adjust_raster_scales); break; } } @@ -541,24 +556,18 @@ void CalculateDrawPropertiesInternal( "LayerTreeHostCommon::CalculateDrawProperties"); } + draw_property_utils::FindLayersThatNeedUpdates( + inputs->root_layer->layer_tree_impl(), inputs->property_trees, + &visible_layer_list); DCHECK(inputs->can_render_to_separate_surface == inputs->property_trees->non_root_surfaces_enabled); - for (LayerImpl* layer : visible_layer_list) { - draw_property_utils::ComputeLayerDrawProperties(layer, - inputs->property_trees); - } + draw_property_utils::ComputeDrawPropertiesOfVisibleLayers( + &visible_layer_list, inputs->property_trees); CalculateRenderSurfaceLayerList( inputs->root_layer->layer_tree_impl(), inputs->property_trees, inputs->render_surface_layer_list, inputs->can_render_to_separate_surface, - inputs->max_texture_size); - - if (inputs->verify_clip_tree_calculations) - draw_property_utils::VerifyClipTreeCalculations(visible_layer_list, - inputs->property_trees); - if (inputs->verify_visible_rect_calculations) - draw_property_utils::VerifyVisibleRectsCalculations(visible_layer_list, - inputs->property_trees); + inputs->use_layer_lists, inputs->max_texture_size); if (should_measure_property_tree_performance) { TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cc.debug.cdp-perf"), @@ -585,8 +594,9 @@ void LayerTreeHostCommon::CalculateDrawPropertiesForTesting( inputs->page_scale_factor, inputs->device_scale_factor, gfx::Rect(inputs->device_viewport_size), inputs->device_transform, property_trees); - draw_property_utils::UpdatePropertyTrees(property_trees, - can_render_to_separate_surface); + draw_property_utils::UpdatePropertyTrees( + inputs->root_layer->layer_tree_host(), property_trees, + can_render_to_separate_surface); draw_property_utils::FindLayersThatNeedUpdates( inputs->root_layer->layer_tree_host(), property_trees, &update_layer_list); @@ -641,8 +651,6 @@ void LayerTreeHostCommon::CalculateDrawProperties( void LayerTreeHostCommon::CalculateDrawPropertiesForTesting( CalcDrawPropsImplInputsForTesting* inputs) { - PropertyTreeBuilder::PreCalculateMetaInformationForTesting( - inputs->root_layer); CalculateDrawPropertiesInternal(inputs, BUILD_PROPERTY_TREES_IF_NEEDED); } diff --git a/chromium/cc/trees/layer_tree_host_common.h b/chromium/cc/trees/layer_tree_host_common.h index de96d955c5a..dd668caa88e 100644 --- a/chromium/cc/trees/layer_tree_host_common.h +++ b/chromium/cc/trees/layer_tree_host_common.h @@ -13,7 +13,7 @@ #include "base/bind.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/layers/layer.h" #include "cc/layers/layer_collections.h" #include "cc/layers/layer_impl.h" @@ -74,8 +74,7 @@ class CC_EXPORT LayerTreeHostCommon { int max_texture_size, bool can_render_to_separate_surface, bool can_adjust_raster_scales, - bool verify_clip_tree_calculations, - bool verify_visible_rect_calculations, + bool use_layer_lists, LayerImplList* render_surface_layer_list, PropertyTrees* property_trees); @@ -92,8 +91,7 @@ class CC_EXPORT LayerTreeHostCommon { int max_texture_size; bool can_render_to_separate_surface; bool can_adjust_raster_scales; - bool verify_clip_tree_calculations; - bool verify_visible_rect_calculations; + bool use_layer_lists; LayerImplList* render_surface_layer_list; PropertyTrees* property_trees; }; @@ -177,6 +175,8 @@ struct CC_EXPORT ScrollAndScaleSet { float top_controls_delta; std::vector<LayerTreeHostCommon::ScrollbarsUpdateInfo> scrollbars; std::vector<std::unique_ptr<SwapPromise>> swap_promises; + bool has_scrolled_by_wheel; + bool has_scrolled_by_touch; private: DISALLOW_COPY_AND_ASSIGN(ScrollAndScaleSet); diff --git a/chromium/cc/trees/layer_tree_host_common_perftest.cc b/chromium/cc/trees/layer_tree_host_common_perftest.cc index 132872c5a67..89946eea48a 100644 --- a/chromium/cc/trees/layer_tree_host_common_perftest.cc +++ b/chromium/cc/trees/layer_tree_host_common_perftest.cc @@ -14,7 +14,7 @@ #include "base/strings/string_piece.h" #include "base/threading/thread.h" #include "base/time/time.h" -#include "cc/debug/lap_timer.h" +#include "cc/base/lap_timer.h" #include "cc/layers/layer.h" #include "cc/test/fake_content_layer_client.h" #include "cc/test/fake_layer_tree_host_client.h" @@ -114,9 +114,8 @@ class CalcDrawPropsTest : public LayerTreeHostCommonPerfTest { active_tree->elastic_overscroll()->Current(active_tree->IsActiveTree()), active_tree->OverscrollElasticityLayer(), max_texture_size, can_render_to_separate_surface, + false, // don't use layer lists for perf tests host_impl->settings().layer_transforms_should_scale_layer_contents, - false, // do not verify_clip_tree_calculation for perf tests - false, // do not verify_visible_rect_calculation for perf tests &update_list, active_tree->property_trees()); LayerTreeHostCommon::CalculateDrawProperties(&inputs); } diff --git a/chromium/cc/trees/layer_tree_host_common_unittest.cc b/chromium/cc/trees/layer_tree_host_common_unittest.cc index 45782b01bf6..e6f69f6dd99 100644 --- a/chromium/cc/trees/layer_tree_host_common_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_common_unittest.cc @@ -20,10 +20,10 @@ #include "cc/base/math_util.h" #include "cc/input/main_thread_scrolling_reason.h" #include "cc/layers/content_layer_client.h" +#include "cc/layers/effect_tree_layer_list_iterator.h" #include "cc/layers/layer.h" #include "cc/layers/layer_client.h" #include "cc/layers/layer_impl.h" -#include "cc/layers/layer_iterator.h" #include "cc/layers/render_surface_impl.h" #include "cc/layers/texture_layer_impl.h" #include "cc/output/copy_output_request.h" @@ -62,7 +62,6 @@ namespace { class VerifyTreeCalcsLayerTreeSettings : public LayerTreeSettings { public: VerifyTreeCalcsLayerTreeSettings() { - verify_clip_tree_calculations = true; } }; @@ -104,8 +103,6 @@ class LayerTreeHostCommonTestBase : public LayerTestCommon::LayerImplTest { Layer* page_scale_layer, Layer* inner_viewport_scroll_layer, Layer* outer_viewport_scroll_layer) { - PropertyTreeBuilder::PreCalculateMetaInformation(root_layer); - EXPECT_TRUE(page_scale_layer || (page_scale_factor == 1.f)); gfx::Size device_viewport_size = gfx::Size(root_layer->bounds().width() * device_scale_factor, @@ -124,14 +121,12 @@ class LayerTreeHostCommonTestBase : public LayerTestCommon::LayerImplTest { LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); } - void ExecuteCalculateDrawProperties( - LayerImpl* root_layer, - float device_scale_factor, - float page_scale_factor, - LayerImpl* page_scale_layer, - LayerImpl* inner_viewport_scroll_layer, - LayerImpl* outer_viewport_scroll_layer, - bool skip_verify_visible_rect_calculations = false) { + void ExecuteCalculateDrawProperties(LayerImpl* root_layer, + float device_scale_factor, + float page_scale_factor, + LayerImpl* page_scale_layer, + LayerImpl* inner_viewport_scroll_layer, + LayerImpl* outer_viewport_scroll_layer) { if (device_scale_factor != root_layer->layer_tree_impl()->device_scale_factor()) root_layer->layer_tree_impl()->property_trees()->needs_rebuild = true; @@ -158,8 +153,6 @@ class LayerTreeHostCommonTestBase : public LayerTestCommon::LayerImplTest { inputs.inner_viewport_scroll_layer = inner_viewport_scroll_layer; inputs.outer_viewport_scroll_layer = outer_viewport_scroll_layer; inputs.can_adjust_raster_scales = true; - if (skip_verify_visible_rect_calculations) - inputs.verify_visible_rect_calculations = false; LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); } @@ -189,8 +182,6 @@ class LayerTreeHostCommonTestBase : public LayerTestCommon::LayerImplTest { void ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(Layer* root_layer) { DCHECK(root_layer->layer_tree_host()); - PropertyTreeBuilder::PreCalculateMetaInformation(root_layer); - bool can_render_to_separate_surface = true; const Layer* page_scale_layer = @@ -216,26 +207,25 @@ class LayerTreeHostCommonTestBase : public LayerTestCommon::LayerImplTest { outer_viewport_scroll_layer, overscroll_elasticity_layer, elastic_overscroll, page_scale_factor, device_scale_factor, gfx::Rect(device_viewport_size), gfx::Transform(), property_trees); - draw_property_utils::UpdatePropertyTrees(property_trees, + draw_property_utils::UpdatePropertyTrees(root_layer->layer_tree_host(), + property_trees, can_render_to_separate_surface); draw_property_utils::FindLayersThatNeedUpdates( root_layer->layer_tree_host(), property_trees, &update_layer_list_); } void ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList( - LayerImpl* root_layer, - bool skip_verify_visible_rect_calculations = false) { + LayerImpl* root_layer) { DCHECK(root_layer->layer_tree_impl()); - PropertyTreeBuilder::PreCalculateMetaInformationForTesting(root_layer); - bool can_render_to_separate_surface = true; + bool can_adjust_raster_scales = true; - LayerImpl* page_scale_layer = nullptr; + const LayerImpl* page_scale_layer = nullptr; LayerImpl* inner_viewport_scroll_layer = root_layer->layer_tree_impl()->InnerViewportScrollLayer(); LayerImpl* outer_viewport_scroll_layer = root_layer->layer_tree_impl()->OuterViewportScrollLayer(); - LayerImpl* overscroll_elasticity_layer = + const LayerImpl* overscroll_elasticity_layer = root_layer->layer_tree_impl()->OverscrollElasticityLayer(); gfx::Vector2dF elastic_overscroll = root_layer->layer_tree_impl()->elastic_overscroll()->Current( @@ -249,18 +239,19 @@ class LayerTreeHostCommonTestBase : public LayerTestCommon::LayerImplTest { root_layer->layer_tree_impl()->BuildLayerListForTesting(); PropertyTrees* property_trees = root_layer->layer_tree_impl()->property_trees(); - draw_property_utils::BuildPropertyTreesAndComputeVisibleRects( + PropertyTreeBuilder::BuildPropertyTrees( root_layer, page_scale_layer, inner_viewport_scroll_layer, outer_viewport_scroll_layer, overscroll_elasticity_layer, elastic_overscroll, page_scale_factor, device_scale_factor, - gfx::Rect(device_viewport_size), gfx::Transform(), - can_render_to_separate_surface, property_trees, + gfx::Rect(device_viewport_size), gfx::Transform(), property_trees); + draw_property_utils::UpdatePropertyTreesAndRenderSurfaces( + root_layer, property_trees, can_render_to_separate_surface, + can_adjust_raster_scales); + draw_property_utils::FindLayersThatNeedUpdates( + root_layer->layer_tree_impl(), property_trees, update_layer_list_impl_.get()); - draw_property_utils::VerifyClipTreeCalculations(*update_layer_list_impl_, - property_trees); - if (!skip_verify_visible_rect_calculations) - draw_property_utils::VerifyVisibleRectsCalculations( - *update_layer_list_impl_, property_trees); + draw_property_utils::ComputeDrawPropertiesOfVisibleLayers( + update_layer_list_impl(), property_trees); } void ExecuteCalculateDrawPropertiesWithoutSeparateSurfaces( @@ -279,6 +270,22 @@ class LayerTreeHostCommonTestBase : public LayerTestCommon::LayerImplTest { LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); } + void ExecuteCalculateDrawPropertiesWithoutAdjustingRasterScales( + LayerImpl* root_layer) { + gfx::Size device_viewport_size = + gfx::Size(root_layer->bounds().width(), root_layer->bounds().height()); + render_surface_layer_list_impl_.reset(new LayerImplList); + + DCHECK(!root_layer->bounds().IsEmpty()); + LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( + root_layer, device_viewport_size, + render_surface_layer_list_impl_.get()); + inputs.can_render_to_separate_surface = true; + inputs.can_adjust_raster_scales = false; + + LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); + } + bool UpdateLayerListImplContains(int id) const { for (auto* layer : *update_layer_list_impl_) { if (layer->id() == id) @@ -1125,18 +1132,16 @@ TEST_F(LayerTreeHostCommonTest, LayerFullyContainedWithinClipInTargetSpace) { LayerImpl* page_scale_layer = nullptr; LayerImpl* inner_viewport_scroll_layer = nullptr; LayerImpl* outer_viewport_scroll_layer = nullptr; - // Visible rects computed by combining clips in target space and root space - // don't match because of rotation transforms. So, we skip - // verify_visible_rect_calculations. - bool skip_verify_visible_rect_calculations = true; ExecuteCalculateDrawProperties(root, device_scale_factor, page_scale_factor, page_scale_layer, inner_viewport_scroll_layer, - outer_viewport_scroll_layer, - skip_verify_visible_rect_calculations); + outer_viewport_scroll_layer); - // Mapping grand_child's bounds to target space produces a non-empty rect - // that is fully contained within the target's bounds, so grand_child should - // be considered fully visible. + // Mapping grand_child's bounds to screen space produces an empty rect, but + // only because it is turned sideways. The entire rect is contained inside + // the clip, and is only empty so long as the numerical precision of the + // transform is effectively perfect. Currently we do the calculation the + // other way around, and the Projection of the screen space clip into layer + // space includes the entire bounds. EXPECT_EQ(gfx::Rect(grand_child->bounds()), grand_child->visible_layer_rect()); } @@ -1434,6 +1439,7 @@ TEST_F(LayerTreeHostCommonTest, render_surface1->test_properties()->background_filters = filters; child->SetBounds(gfx::Size(10, 10)); child->SetDrawsContent(true); + root->layer_tree_impl()->SetElementIdsForTesting(); { LayerImplList render_surface_layer_list; @@ -1455,10 +1461,9 @@ TEST_F(LayerTreeHostCommonTest, EXPECT_TRUE(node->is_drawn); // When root is transparent, the layer should not be drawn. - effect_tree.OnOpacityAnimated(0.f, root->effect_tree_index(), - root->layer_tree_impl()); - effect_tree.OnOpacityAnimated(1.f, render_surface1->effect_tree_index(), - root->layer_tree_impl()); + root->layer_tree_impl()->SetOpacityMutated(root->element_id(), 0.f); + root->layer_tree_impl()->SetOpacityMutated(render_surface1->element_id(), + 1.f); render_surface1->set_visible_layer_rect(gfx::Rect()); { LayerImplList render_surface_layer_list; @@ -1575,13 +1580,11 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceForBlendMode) { ExecuteCalculateDrawProperties(root); // Since the child layer has a blend mode other than normal, it should get - // its own render surface. Also, layer's draw_properties should contain the - // default blend mode, since the render surface becomes responsible for - // applying the blend mode. + // its own render surface. ASSERT_TRUE(child->GetRenderSurface()); EXPECT_EQ(1.0f, child->draw_opacity()); EXPECT_EQ(0.5f, child->GetRenderSurface()->draw_opacity()); - EXPECT_EQ(SkBlendMode::kSrcOver, child->draw_blend_mode()); + EXPECT_EQ(SkBlendMode::kMultiply, child->GetRenderSurface()->BlendMode()); } TEST_F(LayerTreeHostCommonTest, RenderSurfaceDrawOpacity) { @@ -2552,7 +2555,6 @@ TEST_F(LayerTreeHostCommonTest, AnimationsForRenderSurfaceHierarchy) { gfx::Point3F(0.25f, 0.f, 0.f); root->layer_tree_impl()->BuildLayerListAndPropertyTreesForTesting(); - SetElementIdsForTesting(); // Put an animated opacity on the render surface. AddOpacityTransitionToElementWithPlayer( @@ -2966,6 +2968,21 @@ TEST_F(LayerTreeHostCommonDrawRectsTest, drawing_layer->drawable_content_rect()); } +static bool ProjectionClips(const gfx::Transform& map_transform, + const gfx::RectF& mapped_rect) { + gfx::Transform inverse(Inverse(map_transform)); + bool clipped = false; + if (!clipped) + MathUtil::ProjectPoint(inverse, mapped_rect.top_right(), &clipped); + if (!clipped) + MathUtil::ProjectPoint(inverse, mapped_rect.origin(), &clipped); + if (!clipped) + MathUtil::ProjectPoint(inverse, mapped_rect.bottom_right(), &clipped); + if (!clipped) + MathUtil::ProjectPoint(inverse, mapped_rect.bottom_left(), &clipped); + return clipped; +} + TEST_F(LayerTreeHostCommonDrawRectsTest, DrawRectsForPerspectiveUnprojection) { // To determine visible rect in layer space, there needs to be an // un-projection from surface space to layer space. When the original @@ -2988,12 +3005,9 @@ TEST_F(LayerTreeHostCommonDrawRectsTest, DrawRectsForPerspectiveUnprojection) { // Sanity check that un-projection does indeed cause w < 0, otherwise this // code is not testing the intended scenario. - bool clipped; gfx::RectF clipped_rect = MathUtil::MapClippedRect( layer_to_surface_transform, gfx::RectF(layer_content_rect)); - MathUtil::ProjectQuad( - Inverse(layer_to_surface_transform), gfx::QuadF(clipped_rect), &clipped); - ASSERT_TRUE(clipped); + ASSERT_TRUE(ProjectionClips(layer_to_surface_transform, clipped_rect)); // Only the corner of the layer is not visible on the surface because of being // clipped. But, the net result of rounding visible region to an axis-aligned @@ -4011,7 +4025,8 @@ TEST_F(LayerTreeHostCommonTest, TEST_F(LayerTreeHostCommonTest, ClipRectOfSurfaceWhoseParentIsAClipChild) { LayerImpl* root = root_layer_for_testing(); LayerImpl* clip_parent = AddChildToRoot<LayerImpl>(); - LayerImpl* render_surface1 = AddChild<LayerImpl>(clip_parent); + LayerImpl* clip_layer = AddChild<LayerImpl>(clip_parent); + LayerImpl* render_surface1 = AddChild<LayerImpl>(clip_layer); LayerImpl* clip_child = AddChild<LayerImpl>(render_surface1); LayerImpl* render_surface2 = AddChild<LayerImpl>(clip_child); @@ -4023,6 +4038,8 @@ TEST_F(LayerTreeHostCommonTest, ClipRectOfSurfaceWhoseParentIsAClipChild) { base::MakeUnique<std::set<LayerImpl*>>(); clip_parent->test_properties()->clip_children->insert(clip_child); + clip_layer->SetBounds(gfx::Size(50, 50)); + render_surface1->SetBounds(gfx::Size(20, 20)); render_surface1->SetDrawsContent(true); render_surface1->test_properties()->force_render_surface = true; @@ -4036,11 +4053,17 @@ TEST_F(LayerTreeHostCommonTest, ClipRectOfSurfaceWhoseParentIsAClipChild) { render_surface2->test_properties()->force_render_surface = true; clip_parent->SetMasksToBounds(true); + clip_layer->SetMasksToBounds(true); render_surface1->SetMasksToBounds(true); - ExecuteCalculateDrawProperties(root); + float device_scale_factor = 1.f; + ExecuteCalculateDrawProperties(root, device_scale_factor); EXPECT_EQ(gfx::Rect(50, 50), render_surface2->GetRenderSurface()->clip_rect()); + device_scale_factor = 2.f; + ExecuteCalculateDrawProperties(root, device_scale_factor); + EXPECT_EQ(gfx::Rect(100, 100), + render_surface2->GetRenderSurface()->clip_rect()); } TEST_F(LayerTreeHostCommonTest, RenderSurfaceContentRectWhenLayerNotDrawn) { @@ -5055,7 +5078,6 @@ TEST_F(LayerTreeHostCommonTest, OpacityAnimatingOnPendingTree) { scoped_refptr<AnimationTimeline> timeline = AnimationTimeline::Create(AnimationIdProvider::NextTimelineId()); host_impl.animation_host()->AddAnimationTimeline(timeline); - host_impl.pending_tree()->SetElementIdsForTesting(); ElementId child_element_id = host_impl.pending_tree()->LayerById(child_id)->element_id(); @@ -5723,7 +5745,7 @@ TEST_F(LayerTreeHostCommonTest, TransformedClipParent) { clip_child->test_properties()->clip_parent = clip_parent; std::unique_ptr<std::set<LayerImpl*>> clip_children(new std::set<LayerImpl*>); clip_children->insert(clip_child); - clip_parent->test_properties()->clip_children.reset(clip_children.release()); + clip_parent->test_properties()->clip_children = std::move(clip_children); intervening->SetMasksToBounds(true); clip_parent->SetMasksToBounds(true); @@ -5812,37 +5834,40 @@ TEST_F(LayerTreeHostCommonTest, ClipParentWithInterveningRenderSurface) { EXPECT_TRUE(render_surface1->GetRenderSurface()); EXPECT_TRUE(render_surface2->GetRenderSurface()); - // Since the render surfaces could have expanded, they should not clip (their - // bounds would no longer be reliable). We should resort to layer clipping - // in this case. - EXPECT_EQ(gfx::Rect(0, 0, 0, 0), + // render_surface1 should apply the clip from clip_parent. Though there is a + // clip child, render_surface1 can apply the clip as there are no clips + // between the clip parent and render_surface1 + EXPECT_EQ(gfx::Rect(1, 1, 40, 40), render_surface1->GetRenderSurface()->clip_rect()); - EXPECT_FALSE(render_surface1->GetRenderSurface()->is_clipped()); + EXPECT_TRUE(render_surface1->GetRenderSurface()->is_clipped()); + EXPECT_EQ(gfx::Rect(), render_surface1->clip_rect()); + EXPECT_FALSE(render_surface1->is_clipped()); + + // render_surface2 could have expanded, as there is a clip between + // clip_child's clip (clip_parent) and render_surface2's clip (intervening). + // So, it should not be clipped (their bounds would no longer be reliable). + // We should resort to layer clipping in this case. EXPECT_EQ(gfx::Rect(0, 0, 0, 0), render_surface2->GetRenderSurface()->clip_rect()); EXPECT_FALSE(render_surface2->GetRenderSurface()->is_clipped()); - // NB: clip rects are in target space. - EXPECT_EQ(gfx::Rect(0, 0, 40, 40), render_surface1->clip_rect()); - EXPECT_TRUE(render_surface1->is_clipped()); - // This value is inherited from the clipping ancestor layer, 'intervening'. EXPECT_EQ(gfx::Rect(0, 0, 5, 5), render_surface2->clip_rect()); EXPECT_TRUE(render_surface2->is_clipped()); - // The content rects of both render surfaces should both have expanded to - // contain the clip child. + // The content rects of render_surface2 should have expanded to contain the + // clip child. EXPECT_EQ(gfx::Rect(0, 0, 40, 40), render_surface1->GetRenderSurface()->content_rect()); - EXPECT_EQ(gfx::Rect(-1, -1, 40, 40), + EXPECT_EQ(gfx::Rect(-10, -10, 60, 60), render_surface2->GetRenderSurface()->content_rect()); // The clip child should have inherited the clip parent's clip (projected to - // the right space, of course), and should have the correctly sized visible - // content rect. - EXPECT_EQ(gfx::Rect(-1, -1, 40, 40), clip_child->clip_rect()); + // the right space, of course), but as render_surface1 already applies that + // clip, clip_child need not apply it again. + EXPECT_EQ(gfx::Rect(), clip_child->clip_rect()); EXPECT_EQ(gfx::Rect(9, 9, 40, 40), clip_child->visible_layer_rect()); - EXPECT_TRUE(clip_child->is_clipped()); + EXPECT_FALSE(clip_child->is_clipped()); } TEST_F(LayerTreeHostCommonTest, ClipParentScrolledInterveningLayer) { @@ -5895,37 +5920,39 @@ TEST_F(LayerTreeHostCommonTest, ClipParentScrolledInterveningLayer) { EXPECT_TRUE(render_surface1->GetRenderSurface()); EXPECT_TRUE(render_surface2->GetRenderSurface()); - // Since the render surfaces could have expanded, they should not clip (their - // bounds would no longer be reliable). We should resort to layer clipping - // in this case. - EXPECT_EQ(gfx::Rect(0, 0, 0, 0), + // render_surface1 should apply the clip from clip_parent. Though there is a + // clip child, render_surface1 can apply the clip as there are no clips + // between the clip parent and render_surface1 + EXPECT_EQ(gfx::Rect(3, 3, 40, 40), render_surface1->GetRenderSurface()->clip_rect()); - EXPECT_FALSE(render_surface1->GetRenderSurface()->is_clipped()); + EXPECT_TRUE(render_surface1->GetRenderSurface()->is_clipped()); + EXPECT_EQ(gfx::Rect(), render_surface1->clip_rect()); + EXPECT_FALSE(render_surface1->is_clipped()); + + // render_surface2 could have expanded, as there is a clip between + // clip_child's clip (clip_parent) and render_surface2's clip (intervening). + // So, it should not be clipped (their bounds would no longer be reliable). + // We should resort to layer clipping in this case. EXPECT_EQ(gfx::Rect(0, 0, 0, 0), render_surface2->GetRenderSurface()->clip_rect()); EXPECT_FALSE(render_surface2->GetRenderSurface()->is_clipped()); - - // NB: clip rects are in target space. - EXPECT_EQ(gfx::Rect(0, 0, 40, 40), render_surface1->clip_rect()); - EXPECT_TRUE(render_surface1->is_clipped()); - // This value is inherited from the clipping ancestor layer, 'intervening'. - EXPECT_EQ(gfx::Rect(2, 2, 3, 3), render_surface2->clip_rect()); + EXPECT_EQ(gfx::Rect(0, 0, 5, 5), render_surface2->clip_rect()); EXPECT_TRUE(render_surface2->is_clipped()); - // The content rects of both render surfaces should both have expanded to - // contain the clip child. + // The content rects of render_surface2 should have expanded to contain the + // clip child. EXPECT_EQ(gfx::Rect(0, 0, 40, 40), render_surface1->GetRenderSurface()->content_rect()); - EXPECT_EQ(gfx::Rect(2, 2, 40, 40), + EXPECT_EQ(gfx::Rect(-10, -10, 60, 60), render_surface2->GetRenderSurface()->content_rect()); // The clip child should have inherited the clip parent's clip (projected to - // the right space, of course), and should have the correctly sized visible - // content rect. - EXPECT_EQ(gfx::Rect(2, 2, 40, 40), clip_child->clip_rect()); + // the right space, of course), but as render_surface1 already applies that + // clip, clip_child need not apply it again. + EXPECT_EQ(gfx::Rect(), clip_child->clip_rect()); EXPECT_EQ(gfx::Rect(12, 12, 40, 40), clip_child->visible_layer_rect()); - EXPECT_TRUE(clip_child->is_clipped()); + EXPECT_FALSE(clip_child->is_clipped()); } TEST_F(LayerTreeHostCommonTest, DescendantsOfClipChildren) { @@ -5977,17 +6004,19 @@ TEST_F(LayerTreeHostCommonTest, // // root (a render surface) // + clip_parent (masks to bounds) - // + render_surface1 - // + clip_child - // + render_surface2 - // + non_clip_child + // + clip_layer (masks to bounds) + // + render_surface1 + // + clip_child + // + render_surface2 + // + non_clip_child // // In this example render_surface2 should be unaffected by clip_child. LayerImpl* root = root_layer_for_testing(); LayerImpl* clip_parent = AddChildToRoot<LayerImpl>(); - LayerImpl* render_surface1 = AddChild<LayerImpl>(clip_parent); + LayerImpl* clip_layer = AddChild<LayerImpl>(clip_parent); + LayerImpl* render_surface1 = AddChild<LayerImpl>(clip_layer); LayerImpl* clip_child = AddChild<LayerImpl>(render_surface1); - LayerImpl* render_surface2 = AddChild<LayerImpl>(clip_parent); + LayerImpl* render_surface2 = AddChild<LayerImpl>(clip_layer); LayerImpl* non_clip_child = AddChild<LayerImpl>(render_surface2); clip_child->test_properties()->clip_parent = clip_parent; @@ -5996,7 +6025,7 @@ TEST_F(LayerTreeHostCommonTest, clip_parent->test_properties()->clip_children->insert(clip_child); clip_parent->SetMasksToBounds(true); - render_surface1->SetMasksToBounds(true); + clip_layer->SetMasksToBounds(true); render_surface1->SetDrawsContent(true); clip_child->SetDrawsContent(true); @@ -6005,6 +6034,7 @@ TEST_F(LayerTreeHostCommonTest, root->SetBounds(gfx::Size(15, 15)); clip_parent->SetBounds(gfx::Size(10, 10)); + clip_layer->SetBounds(gfx::Size(10, 10)); render_surface1->SetPosition(gfx::PointF(5, 5)); render_surface1->SetBounds(gfx::Size(5, 5)); render_surface1->test_properties()->force_render_surface = true; @@ -6020,7 +6050,7 @@ TEST_F(LayerTreeHostCommonTest, EXPECT_TRUE(render_surface1->GetRenderSurface()); EXPECT_TRUE(render_surface2->GetRenderSurface()); - EXPECT_EQ(gfx::Rect(0, 0, 5, 5), render_surface1->clip_rect()); + EXPECT_EQ(gfx::Rect(-5, -5, 10, 10), render_surface1->clip_rect()); EXPECT_TRUE(render_surface1->is_clipped()); // The render surface should not clip (it has unclipped descendants), instead @@ -6043,10 +6073,6 @@ TEST_F(LayerTreeHostCommonTest, // It also shouldn't have grown to accomodate the clip child. EXPECT_EQ(gfx::Rect(0, 0, 5, 5), render_surface2->GetRenderSurface()->content_rect()); - - // Sanity check our num_unclipped_descendants values. - EXPECT_EQ(1u, render_surface1->test_properties()->num_unclipped_descendants); - EXPECT_EQ(0u, render_surface2->test_properties()->num_unclipped_descendants); } TEST_F(LayerTreeHostCommonTest, @@ -6121,7 +6147,6 @@ TEST_F(LayerTreeHostCommonTest, CanRenderToSeparateSurface) { { LayerImplList render_surface_layer_list; - FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(root_layer); LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( root_layer, root_layer->bounds(), &render_surface_layer_list); inputs.can_render_to_separate_surface = true; @@ -6132,15 +6157,16 @@ TEST_F(LayerTreeHostCommonTest, CanRenderToSeparateSurface) { int count_represents_target_render_surface = 0; int count_represents_contributing_render_surface = 0; int count_represents_itself = 0; - LayerIterator end = LayerIterator::End(&render_surface_layer_list); - for (LayerIterator it = LayerIterator::Begin(&render_surface_layer_list); - it != end; ++it) { - if (it.represents_target_render_surface()) + for (EffectTreeLayerListIterator it(host_impl.active_tree()); + it.state() != EffectTreeLayerListIterator::State::END; ++it) { + if (it.state() == EffectTreeLayerListIterator::State::TARGET_SURFACE) { count_represents_target_render_surface++; - if (it.represents_contributing_render_surface()) + } else if (it.state() == + EffectTreeLayerListIterator::State::CONTRIBUTING_SURFACE) { count_represents_contributing_render_surface++; - if (it.represents_itself()) + } else { count_represents_itself++; + } } // Two render surfaces. @@ -6163,15 +6189,16 @@ TEST_F(LayerTreeHostCommonTest, CanRenderToSeparateSurface) { int count_represents_target_render_surface = 0; int count_represents_contributing_render_surface = 0; int count_represents_itself = 0; - LayerIterator end = LayerIterator::End(&render_surface_layer_list); - for (LayerIterator it = LayerIterator::Begin(&render_surface_layer_list); - it != end; ++it) { - if (it.represents_target_render_surface()) + for (EffectTreeLayerListIterator it(host_impl.active_tree()); + it.state() != EffectTreeLayerListIterator::State::END; ++it) { + if (it.state() == EffectTreeLayerListIterator::State::TARGET_SURFACE) { count_represents_target_render_surface++; - if (it.represents_contributing_render_surface()) + } else if (it.state() == + EffectTreeLayerListIterator::State::CONTRIBUTING_SURFACE) { count_represents_contributing_render_surface++; - if (it.represents_itself()) + } else { count_represents_itself++; + } } // Only root layer has a render surface. @@ -6368,6 +6395,7 @@ TEST_F(LayerTreeHostCommonTest, TransformAnimationUpdatesBackfaceVisibility) { render_surface2->test_properties()->double_sided = false; render_surface2->test_properties()->force_render_surface = true; render_surface2->test_properties()->sorting_context_id = 1; + SetElementIdsForTesting(); ExecuteCalculateDrawProperties(root); const EffectTree& tree = @@ -6377,21 +6405,18 @@ TEST_F(LayerTreeHostCommonTest, TransformAnimationUpdatesBackfaceVisibility) { EXPECT_TRUE(tree.Node(render_surface2->effect_tree_index()) ->hidden_by_backface_visibility); - root->layer_tree_impl()->property_trees()->transform_tree.OnTransformAnimated( - gfx::Transform(), back_facing->transform_tree_index(), - root->layer_tree_impl()); - root->layer_tree_impl()->property_trees()->transform_tree.OnTransformAnimated( - rotate_about_y, render_surface2->transform_tree_index(), - root->layer_tree_impl()); + root->layer_tree_impl()->SetTransformMutated(back_facing->element_id(), + gfx::Transform()); + root->layer_tree_impl()->SetTransformMutated(render_surface2->element_id(), + rotate_about_y); ExecuteCalculateDrawProperties(root); EXPECT_FALSE(tree.Node(render_surface1->effect_tree_index()) ->hidden_by_backface_visibility); EXPECT_TRUE(tree.Node(render_surface2->effect_tree_index()) ->hidden_by_backface_visibility); - root->layer_tree_impl()->property_trees()->transform_tree.OnTransformAnimated( - rotate_about_y, render_surface1->transform_tree_index(), - root->layer_tree_impl()); + root->layer_tree_impl()->SetTransformMutated(render_surface1->element_id(), + rotate_about_y); ExecuteCalculateDrawProperties(root); EXPECT_TRUE(tree.Node(render_surface1->effect_tree_index()) ->hidden_by_backface_visibility); @@ -6484,50 +6509,6 @@ TEST_F(LayerTreeHostCommonTest, ScrollChildAndScrollParentDifferentTargets) { EXPECT_TRANSFORMATION_MATRIX_EQ(scroll_child->DrawTransform(), scale); } -TEST_F(LayerTreeHostCommonTest, TargetBetweenScrollChildandScrollParentTarget) { - LayerImpl* root = root_layer_for_testing(); - LayerImpl* scroll_child_target = AddChildToRoot<LayerImpl>(); - LayerImpl* scroll_child = AddChild<LayerImpl>(scroll_child_target); - LayerImpl* child_of_scroll_child = AddChild<LayerImpl>(scroll_child); - LayerImpl* intervening_target = AddChild<LayerImpl>(scroll_child_target); - LayerImpl* clip = AddChild<LayerImpl>(intervening_target); - LayerImpl* scroll_parent_target = AddChild<LayerImpl>(clip); - LayerImpl* scroll_parent = AddChild<LayerImpl>(scroll_parent_target); - - scroll_parent->SetDrawsContent(true); - child_of_scroll_child->SetDrawsContent(true); - - scroll_child->test_properties()->scroll_parent = scroll_parent; - scroll_parent->test_properties()->scroll_children = - base::MakeUnique<std::set<LayerImpl*>>(); - scroll_parent->test_properties()->scroll_children->insert(scroll_child); - - root->SetBounds(gfx::Size(50, 50)); - scroll_child_target->SetBounds(gfx::Size(50, 50)); - scroll_child_target->SetMasksToBounds(true); - scroll_child_target->test_properties()->force_render_surface = true; - scroll_child->SetBounds(gfx::Size(50, 50)); - child_of_scroll_child->SetBounds(gfx::Size(50, 50)); - child_of_scroll_child->test_properties()->force_render_surface = true; - intervening_target->SetBounds(gfx::Size(50, 50)); - intervening_target->test_properties()->force_render_surface = true; - clip->SetBounds(gfx::Size(50, 50)); - clip->SetMasksToBounds(true); - scroll_parent_target->SetBounds(gfx::Size(50, 50)); - scroll_parent_target->SetMasksToBounds(true); - scroll_parent_target->test_properties()->force_render_surface = true; - scroll_parent->SetBounds(gfx::Size(50, 50)); - - ExecuteCalculateDrawProperties(root); - PropertyTrees* property_trees = root->layer_tree_impl()->property_trees(); - ClipNode* clip_node = - property_trees->clip_tree.Node(child_of_scroll_child->clip_tree_index()); - ClipNode* parent_clip_node = property_trees->clip_tree.parent(clip_node); - DCHECK_GT(parent_clip_node->target_transform_id, - property_trees->transform_tree.TargetId( - child_of_scroll_child->transform_tree_index())); -} - TEST_F(LayerTreeHostCommonTest, SingularTransformSubtreesDoNotDraw) { LayerImpl* root = root_layer_for_testing(); LayerImpl* parent = AddChildToRoot<LayerImpl>(); @@ -7138,6 +7119,9 @@ TEST_F(LayerTreeHostCommonTest, StickyPositionTopScrollParent) { host()->SetRootLayer(root); scroller->SetScrollClipLayerId(container->id()); + // The sticky layer has already been scrolled on the main thread side, and has + // stuck. This test then checks that further changes from cc-only scrolling + // are handled correctly. LayerStickyPositionConstraint sticky_position; sticky_position.is_sticky = true; sticky_position.is_anchored_top = true; @@ -7915,6 +7899,106 @@ TEST_F(LayerTreeHostCommonTest, StickyPositionScaledContainer) { sticky_pos_impl->ScreenSpaceTransform().To2dTranslation()); } +TEST_F(LayerTreeHostCommonTest, StickyPositionNested) { + scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> container = Layer::Create(); + scoped_refptr<Layer> scroller = Layer::Create(); + scoped_refptr<Layer> outer_sticky = Layer::Create(); + scoped_refptr<Layer> inner_sticky = Layer::Create(); + + root->AddChild(container); + container->AddChild(scroller); + scroller->AddChild(outer_sticky); + outer_sticky->AddChild(inner_sticky); + host()->SetRootLayer(root); + scroller->SetScrollClipLayerId(container->id()); + + root->SetBounds(gfx::Size(100, 100)); + container->SetBounds(gfx::Size(100, 100)); + scroller->SetBounds(gfx::Size(100, 1000)); + outer_sticky->SetBounds(gfx::Size(10, 50)); + outer_sticky->SetPosition(gfx::PointF(0, 50)); + inner_sticky->SetBounds(gfx::Size(10, 10)); + inner_sticky->SetPosition(gfx::PointF(0, 0)); + + LayerStickyPositionConstraint outer_sticky_pos; + outer_sticky_pos.is_sticky = true; + outer_sticky_pos.is_anchored_top = true; + outer_sticky_pos.top_offset = 10.0f; + outer_sticky_pos.parent_relative_sticky_box_offset = gfx::Point(0, 50); + outer_sticky_pos.scroll_container_relative_sticky_box_rect = + gfx::Rect(0, 50, 10, 50); + outer_sticky_pos.scroll_container_relative_containing_block_rect = + gfx::Rect(0, 0, 50, 400); + outer_sticky->SetStickyPositionConstraint(outer_sticky_pos); + + LayerStickyPositionConstraint inner_sticky_pos; + inner_sticky_pos.is_sticky = true; + inner_sticky_pos.is_anchored_top = true; + inner_sticky_pos.top_offset = 25.0f; + inner_sticky_pos.parent_relative_sticky_box_offset = gfx::Point(0, 0); + inner_sticky_pos.scroll_container_relative_sticky_box_rect = + gfx::Rect(0, 50, 10, 10); + inner_sticky_pos.scroll_container_relative_containing_block_rect = + gfx::Rect(0, 50, 10, 50); + inner_sticky_pos.nearest_layer_shifting_containing_block = outer_sticky->id(); + inner_sticky->SetStickyPositionConstraint(inner_sticky_pos); + + ExecuteCalculateDrawProperties(root.get()); + host()->host_impl()->CreatePendingTree(); + host()->CommitAndCreatePendingTree(); + host()->host_impl()->ActivateSyncTree(); + LayerTreeImpl* layer_tree_impl = host()->host_impl()->active_tree(); + + LayerImpl* root_impl = layer_tree_impl->LayerById(root->id()); + LayerImpl* scroller_impl = layer_tree_impl->LayerById(scroller->id()); + LayerImpl* outer_sticky_impl = layer_tree_impl->LayerById(outer_sticky->id()); + LayerImpl* inner_sticky_impl = layer_tree_impl->LayerById(inner_sticky->id()); + + ExecuteCalculateDrawProperties(root_impl); + + // Before any scrolling is done, the sticky elements should still be at their + // original positions. + EXPECT_VECTOR2DF_EQ( + gfx::Vector2dF(0.f, 50.f), + outer_sticky_impl->ScreenSpaceTransform().To2dTranslation()); + EXPECT_VECTOR2DF_EQ( + gfx::Vector2dF(0.f, 50.f), + inner_sticky_impl->ScreenSpaceTransform().To2dTranslation()); + + // Scroll less than the sticking point. Both sticky elements should move with + // scroll as we haven't gotten to the sticky item locations yet. + SetScrollOffsetDelta(scroller_impl, gfx::Vector2dF(0.f, 5.f)); + ExecuteCalculateDrawProperties(root_impl); + EXPECT_VECTOR2DF_EQ( + gfx::Vector2dF(0.f, 45.f), + outer_sticky_impl->ScreenSpaceTransform().To2dTranslation()); + EXPECT_VECTOR2DF_EQ( + gfx::Vector2dF(0.f, 45.f), + inner_sticky_impl->ScreenSpaceTransform().To2dTranslation()); + + // Scroll such that the inner sticky should stick, but the outer one should + // keep going as it hasn't reached its position yet. + SetScrollOffsetDelta(scroller_impl, gfx::Vector2dF(0.f, 30.f)); + ExecuteCalculateDrawProperties(root_impl); + EXPECT_VECTOR2DF_EQ( + gfx::Vector2dF(0.f, 20.f), + outer_sticky_impl->ScreenSpaceTransform().To2dTranslation()); + EXPECT_VECTOR2DF_EQ( + gfx::Vector2dF(0.f, 25.f), + inner_sticky_impl->ScreenSpaceTransform().To2dTranslation()); + + // Keep going, both should stick. + SetScrollOffsetDelta(scroller_impl, gfx::Vector2dF(0.f, 100.f)); + ExecuteCalculateDrawProperties(root_impl); + EXPECT_VECTOR2DF_EQ( + gfx::Vector2dF(0.f, 10.f), + outer_sticky_impl->ScreenSpaceTransform().To2dTranslation()); + EXPECT_VECTOR2DF_EQ( + gfx::Vector2dF(0.f, 25.f), + inner_sticky_impl->ScreenSpaceTransform().To2dTranslation()); +} + TEST_F(LayerTreeHostCommonTest, NonFlatContainerForFixedPosLayer) { scoped_refptr<Layer> root = Layer::Create(); scoped_refptr<Layer> container = Layer::Create(); @@ -8266,20 +8350,18 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) { EXPECT_EQ(0.f, GetStartingAnimationScale(grand_child_raw)); } -static void GatherDrawnLayers(const LayerImplList* rsll, +static void GatherDrawnLayers(LayerTreeImpl* tree_impl, std::set<LayerImpl*>* drawn_layers) { - for (LayerIterator it = LayerIterator::Begin(rsll), - end = LayerIterator::End(rsll); - it != end; ++it) { - LayerImpl* layer = *it; - if (it.represents_itself()) - drawn_layers->insert(layer); - - if (!it.represents_contributing_render_surface()) + for (EffectTreeLayerListIterator it(tree_impl); + it.state() != EffectTreeLayerListIterator::State::END; ++it) { + if (it.state() == EffectTreeLayerListIterator::State::LAYER) + drawn_layers->insert(it.current_layer()); + + if (it.state() != EffectTreeLayerListIterator::State::CONTRIBUTING_SURFACE) continue; - if (layer->GetRenderSurface()->MaskLayer()) - drawn_layers->insert(layer->GetRenderSurface()->MaskLayer()); + if (it.current_render_surface()->MaskLayer()) + drawn_layers->insert(it.current_render_surface()->MaskLayer()); } } @@ -8328,7 +8410,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceLayerListMembership) { std::set<LayerImpl*> expected; std::set<LayerImpl*> actual; - GatherDrawnLayers(render_surface_layer_list_impl(), &actual); + GatherDrawnLayers(host_impl.active_tree(), &actual); EXPECT_EQ(expected, actual); // If we force render surface, but none of the layers are in the layer list, @@ -8346,7 +8428,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceLayerListMembership) { expected.clear(); actual.clear(); - GatherDrawnLayers(render_surface_layer_list_impl(), &actual); + GatherDrawnLayers(host_impl.active_tree(), &actual); EXPECT_EQ(expected, actual); // However, if we say that this layer also draws content, it will appear in @@ -8365,7 +8447,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceLayerListMembership) { expected.insert(grand_child1_raw); actual.clear(); - GatherDrawnLayers(render_surface_layer_list_impl(), &actual); + GatherDrawnLayers(host_impl.active_tree(), &actual); EXPECT_EQ(expected, actual); // Now child is forced to have a render surface, and one if its children draws @@ -8388,7 +8470,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceLayerListMembership) { expected.insert(grand_child2_raw); actual.clear(); - GatherDrawnLayers(render_surface_layer_list_impl(), &actual); + GatherDrawnLayers(host_impl.active_tree(), &actual); EXPECT_EQ(expected, actual); // Add a mask layer to child. @@ -8415,7 +8497,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceLayerListMembership) { expected.insert(child_raw->test_properties()->mask_layer); actual.clear(); - GatherDrawnLayers(render_surface_layer_list_impl(), &actual); + GatherDrawnLayers(host_impl.active_tree(), &actual); EXPECT_EQ(expected, actual); ExecuteCalculateDrawProperties(grand_parent_raw); @@ -8433,7 +8515,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceLayerListMembership) { expected.insert(child_raw->test_properties()->mask_layer); actual.clear(); - GatherDrawnLayers(render_surface_layer_list_impl(), &actual); + GatherDrawnLayers(host_impl.active_tree(), &actual); EXPECT_EQ(expected, actual); child_raw->layer_tree_impl()->property_trees()->needs_rebuild = true; @@ -8453,7 +8535,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceLayerListMembership) { expected.clear(); actual.clear(); - GatherDrawnLayers(render_surface_layer_list_impl(), &actual); + GatherDrawnLayers(host_impl.active_tree(), &actual); EXPECT_EQ(expected, actual); // Child itself draws means that we should have the child and the mask in the @@ -8474,7 +8556,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceLayerListMembership) { expected.insert(child_raw); expected.insert(child_raw->test_properties()->mask_layer); actual.clear(); - GatherDrawnLayers(render_surface_layer_list_impl(), &actual); + GatherDrawnLayers(host_impl.active_tree(), &actual); EXPECT_EQ(expected, actual); child_raw->test_properties()->SetMaskLayer(nullptr); @@ -8503,7 +8585,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceLayerListMembership) { expected.insert(grand_child2_raw); actual.clear(); - GatherDrawnLayers(render_surface_layer_list_impl(), &actual); + GatherDrawnLayers(host_impl.active_tree(), &actual); EXPECT_EQ(expected, actual); } @@ -8679,11 +8761,8 @@ TEST_F(LayerTreeHostCommonTest, AnimationScales) { // Correctly updates animation scale when layer property changes. child1_layer->test_properties()->transform = gfx::Transform(); - root_layer->layer_tree_impl() - ->property_trees() - ->transform_tree.OnTransformAnimated(gfx::Transform(), - child1_layer->transform_tree_index(), - root_layer->layer_tree_impl()); + root_layer->layer_tree_impl()->SetTransformMutated(child1_layer->element_id(), + gfx::Transform()); root_layer->layer_tree_impl()->property_trees()->needs_rebuild = false; ExecuteCalculateDrawProperties(root_layer); EXPECT_FLOAT_EQ(8.f, GetMaximumAnimationScale(child2_layer)); @@ -8959,32 +9038,19 @@ TEST_F(LayerTreeHostCommonTest, gfx::Transform zero_matrix; zero_matrix.Scale3d(0.f, 0.f, 0.f); - root->layer_tree_impl()->property_trees()->transform_tree.OnTransformAnimated( - zero_matrix, animated->transform_tree_index(), root->layer_tree_impl()); - // While computing visible rects by combining clips in screen space, we set - // the entire layer as visible if the screen space transform is singular. This - // is not always true when we combine clips in target space because if the - // intersection of combined_clip in taret space with layer_rect projected to - // target space is empty, we set it to an empty rect. - bool skip_verify_visible_rect_calculations = true; - ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList( - root, skip_verify_visible_rect_calculations); - - // The animated layer maps to the empty rect in clipped target space, so is - // treated as having an empty visible rect. - EXPECT_EQ(gfx::Rect(), animated->visible_layer_rect()); + root->layer_tree_impl()->SetTransformMutated(animated->element_id(), + zero_matrix); + ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root); // The animated layer will be treated as fully visible when we combine clips // in screen space. - gfx::Rect visible_rect = draw_property_utils::ComputeLayerVisibleRectDynamic( - root->layer_tree_impl()->property_trees(), animated); - EXPECT_EQ(gfx::Rect(120, 120), visible_rect); + EXPECT_EQ(gfx::Rect(120, 120), animated->visible_layer_rect()); // This time, flattening does not make |animated|'s transform invertible. This // means the clip cannot be projected into |surface|'s space, so we treat // |surface| and layers that draw into it as having empty visible rect. - EXPECT_EQ(gfx::Rect(), surface->visible_layer_rect()); - EXPECT_EQ(gfx::Rect(), descendant_of_animation->visible_layer_rect()); + EXPECT_EQ(gfx::Rect(100, 100), surface->visible_layer_rect()); + EXPECT_EQ(gfx::Rect(200, 200), descendant_of_animation->visible_layer_rect()); } // Verify that having animated opacity but current opacity 1 still creates @@ -9473,8 +9539,8 @@ TEST_F(LayerTreeHostCommonTest, SkippingLayerImpl) { EXPECT_EQ(gfx::Rect(0, 0), grandchild_ptr->visible_layer_rect()); child_ptr->test_properties()->hide_layer_and_subtree = false; - child_ptr->layer_tree_impl()->property_trees()->effect_tree.OnOpacityAnimated( - 0.f, child_ptr->effect_tree_index(), child_ptr->layer_tree_impl()); + child_ptr->test_properties()->opacity = 0.f; + host_impl.active_tree()->property_trees()->needs_rebuild = true; ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root_ptr); EXPECT_EQ(gfx::Rect(0, 0), grandchild_ptr->visible_layer_rect()); child_ptr->test_properties()->opacity = 1.f; @@ -9715,9 +9781,8 @@ TEST_F(LayerTreeHostCommonTest, LayerTreeRebuildTest) { CopyOutputRequest::CreateRequest(base::Bind(&EmptyCopyOutputCallback))); ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get()); - EXPECT_EQ(parent->num_unclipped_descendants(), 1u); - EXPECT_GT(root->num_copy_requests_in_target_subtree(), 0); + ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get()); EXPECT_GT(root->num_copy_requests_in_target_subtree(), 0); } @@ -9781,14 +9846,9 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceClipsSubtree) { LayerImpl* page_scale_layer = nullptr; LayerImpl* inner_viewport_scroll_layer = nullptr; LayerImpl* outer_viewport_scroll_layer = nullptr; - // Visible rects computed by combining clips in target space and root space - // don't match because of rotation transforms. So, we skip - // verify_visible_rect_calculations. - bool skip_verify_visible_rect_calculations = true; ExecuteCalculateDrawProperties(root, device_scale_factor, page_scale_factor, page_scale_layer, inner_viewport_scroll_layer, - outer_viewport_scroll_layer, - skip_verify_visible_rect_calculations); + outer_viewport_scroll_layer); TransformTree& transform_tree = root->layer_tree_impl()->property_trees()->transform_tree; @@ -9802,15 +9862,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceClipsSubtree) { EXPECT_TRUE(render_surface->GetRenderSurface()); EXPECT_FALSE(test_layer->GetRenderSurface()); - ClipTree& clip_tree = root->layer_tree_impl()->property_trees()->clip_tree; - ClipNode* clip_node = clip_tree.Node(render_surface->clip_tree_index()); - EXPECT_EQ(clip_node->clip_type, ClipNode::ClipType::NONE); - EXPECT_EQ(gfx::Rect(20, 20), test_layer->visible_layer_rect()); - - // Also test the visible rects computed by combining clips in root space. - gfx::Rect visible_rect = draw_property_utils::ComputeLayerVisibleRectDynamic( - root->layer_tree_impl()->property_trees(), test_layer); - EXPECT_EQ(gfx::Rect(30, 20), visible_rect); + EXPECT_EQ(gfx::Rect(30, 20), test_layer->visible_layer_rect()); } TEST_F(LayerTreeHostCommonTest, TransformOfParentClipNodeAncestorOfTarget) { @@ -9860,6 +9912,7 @@ TEST_F(LayerTreeHostCommonTest, clip_parent->SetMasksToBounds(true); between_clip_parent_and_child->test_properties()->transform = translate; between_clip_parent_and_child->SetBounds(gfx::Size(30, 30)); + between_clip_parent_and_child->SetMasksToBounds(true); render_surface->SetBounds(gfx::Size(30, 30)); render_surface->test_properties()->force_render_surface = true; test_layer->SetBounds(gfx::Size(30, 30)); @@ -9979,7 +10032,8 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceContentRectWithMultipleSurfaces) { LayerImpl* root = root_layer_for_testing(); LayerImpl* unclipped_surface = AddChildToRoot<LayerImpl>(); LayerImpl* clip_parent = AddChild<LayerImpl>(unclipped_surface); - LayerImpl* unclipped_desc_surface = AddChild<LayerImpl>(clip_parent); + LayerImpl* clip_layer = AddChild<LayerImpl>(clip_parent); + LayerImpl* unclipped_desc_surface = AddChild<LayerImpl>(clip_layer); LayerImpl* unclipped_desc_surface2 = AddChild<LayerImpl>(unclipped_desc_surface); LayerImpl* clip_child = AddChild<LayerImpl>(unclipped_desc_surface2); @@ -9992,8 +10046,9 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceContentRectWithMultipleSurfaces) { unclipped_surface->test_properties()->force_render_surface = true; clip_parent->SetBounds(gfx::Size(50, 50)); clip_parent->SetMasksToBounds(true); + clip_layer->SetMasksToBounds(true); + clip_layer->SetBounds(gfx::Size(100, 100)); unclipped_desc_surface->SetBounds(gfx::Size(100, 100)); - unclipped_desc_surface->SetMasksToBounds(true); unclipped_desc_surface->SetDrawsContent(true); unclipped_desc_surface->test_properties()->force_render_surface = true; unclipped_desc_surface2->SetBounds(gfx::Size(60, 60)); @@ -10014,7 +10069,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceContentRectWithMultipleSurfaces) { unclipped_surface->GetRenderSurface()->content_rect()); EXPECT_EQ(gfx::Rect(50, 50), unclipped_desc_surface->GetRenderSurface()->content_rect()); - EXPECT_EQ(gfx::Rect(50, 50), + EXPECT_EQ(gfx::Rect(60, 60), unclipped_desc_surface2->GetRenderSurface()->content_rect()); EXPECT_EQ(gfx::Rect(50, 50), clipped_surface->GetRenderSurface()->content_rect()); @@ -10125,13 +10180,16 @@ TEST_F(LayerTreeHostCommonTest, ClipParentDrawsIntoScaledRootSurface) { LayerImpl* root = root_layer_for_testing(); LayerImpl* clip_layer = AddChild<LayerImpl>(root); LayerImpl* clip_parent = AddChild<LayerImpl>(clip_layer); - LayerImpl* unclipped_desc_surface = AddChild<LayerImpl>(clip_parent); + LayerImpl* clip_parent_child = AddChild<LayerImpl>(clip_parent); + LayerImpl* unclipped_desc_surface = AddChild<LayerImpl>(clip_parent_child); LayerImpl* clip_child = AddChild<LayerImpl>(unclipped_desc_surface); root->SetBounds(gfx::Size(100, 100)); clip_layer->SetBounds(gfx::Size(20, 20)); clip_layer->SetMasksToBounds(true); clip_parent->SetBounds(gfx::Size(50, 50)); + clip_parent_child->SetBounds(gfx::Size(20, 20)); + clip_parent_child->SetMasksToBounds(true); unclipped_desc_surface->SetBounds(gfx::Size(100, 100)); unclipped_desc_surface->SetDrawsContent(true); unclipped_desc_surface->test_properties()->force_render_surface = true; @@ -10219,22 +10277,27 @@ TEST_F(LayerTreeHostCommonTest, SubtreeIsHiddenTest) { test->test_properties()->force_render_surface = true; ExecuteCalculateDrawProperties(root); - EXPECT_TRUE(test->IsHidden()); + EXPECT_EQ(0.f, + test->GetRenderSurface()->OwningEffectNode()->screen_space_opacity); hidden->test_properties()->hide_layer_and_subtree = false; root->layer_tree_impl()->property_trees()->needs_rebuild = true; ExecuteCalculateDrawProperties(root); - EXPECT_FALSE(test->IsHidden()); + EXPECT_EQ(1.f, + test->GetRenderSurface()->OwningEffectNode()->screen_space_opacity); } TEST_F(LayerTreeHostCommonTest, TwoUnclippedRenderSurfaces) { LayerImpl* root = root_layer_for_testing(); - LayerImpl* render_surface1 = AddChild<LayerImpl>(root); + LayerImpl* clip_layer = AddChild<LayerImpl>(root); + LayerImpl* render_surface1 = AddChild<LayerImpl>(clip_layer); LayerImpl* render_surface2 = AddChild<LayerImpl>(render_surface1); LayerImpl* clip_child = AddChild<LayerImpl>(render_surface2); root->SetBounds(gfx::Size(30, 30)); root->SetMasksToBounds(true); + clip_layer->SetBounds(gfx::Size(30, 30)); + clip_layer->SetMasksToBounds(true); render_surface1->SetPosition(gfx::PointF(10, 10)); render_surface1->SetBounds(gfx::Size(30, 30)); render_surface1->SetDrawsContent(true); @@ -10243,6 +10306,7 @@ TEST_F(LayerTreeHostCommonTest, TwoUnclippedRenderSurfaces) { render_surface2->SetDrawsContent(true); render_surface2->test_properties()->force_render_surface = true; clip_child->SetBounds(gfx::Size(30, 30)); + clip_child->SetDrawsContent(true); clip_child->test_properties()->clip_parent = root; root->test_properties()->clip_children = @@ -10252,9 +10316,6 @@ TEST_F(LayerTreeHostCommonTest, TwoUnclippedRenderSurfaces) { ExecuteCalculateDrawProperties(root); EXPECT_EQ(gfx::Rect(-10, -10, 30, 30), render_surface2->clip_rect()); - // A clip node is created for every render surface and for layers that have - // local clip. So, here it should be craeted for every layer. - EXPECT_EQ(root->layer_tree_impl()->property_trees()->clip_tree.size(), 5u); } TEST_F(LayerTreeHostCommonTest, MaskLayerDrawProperties) { @@ -10443,8 +10504,8 @@ TEST_F(LayerTreeHostCommonTest, PropertyTreesRebuildWithOpacityChanges) { EXPECT_TRUE(property_trees->needs_rebuild); ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get()); - EXPECT_NE(property_trees->layer_id_to_effect_node_index.find(child->id()), - property_trees->layer_id_to_effect_node_index.end()); + EXPECT_NE(property_trees->effect_tree.FindNodeFromOwningLayerId(child->id()), + nullptr); // child already has an effect node. Changing its opacity shouldn't trigger // a property trees rebuild. @@ -10453,8 +10514,8 @@ TEST_F(LayerTreeHostCommonTest, PropertyTreesRebuildWithOpacityChanges) { EXPECT_FALSE(property_trees->needs_rebuild); ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get()); - EXPECT_NE(property_trees->layer_id_to_effect_node_index.find(child->id()), - property_trees->layer_id_to_effect_node_index.end()); + EXPECT_NE(property_trees->effect_tree.FindNodeFromOwningLayerId(child->id()), + nullptr); // Changing the opacity from non-1 value to 1 should trigger a rebuild of // property trees as the effect node may no longer be needed. @@ -10463,8 +10524,8 @@ TEST_F(LayerTreeHostCommonTest, PropertyTreesRebuildWithOpacityChanges) { EXPECT_TRUE(property_trees->needs_rebuild); ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get()); - EXPECT_EQ(property_trees->layer_id_to_effect_node_index.find(child->id()), - property_trees->layer_id_to_effect_node_index.end()); + EXPECT_EQ(property_trees->effect_tree.FindNodeFromOwningLayerId(child->id()), + nullptr); } TEST_F(LayerTreeHostCommonTest, OpacityAnimationsTrackingTest) { @@ -10685,6 +10746,8 @@ TEST_F(LayerTreeHostCommonTest, ScrollTreeBuilderTest) { scroll_root1.user_scrollable_vertical = true; scroll_root1.transform_id = root1->transform_tree_index(); expected_scroll_tree.Insert(scroll_root1, 0); + expected_scroll_tree.SetOwningLayerIdForNode(expected_scroll_tree.back(), + root1->id()); // The node owned by parent2 ScrollNode scroll_parent2; @@ -10701,6 +10764,8 @@ TEST_F(LayerTreeHostCommonTest, ScrollTreeBuilderTest) { scroll_parent2.user_scrollable_vertical = true; scroll_parent2.transform_id = parent2->transform_tree_index(); expected_scroll_tree.Insert(scroll_parent2, 1); + expected_scroll_tree.SetOwningLayerIdForNode(expected_scroll_tree.back(), + parent2->id()); // The node owned by child6 ScrollNode scroll_child6; @@ -10713,6 +10778,8 @@ TEST_F(LayerTreeHostCommonTest, ScrollTreeBuilderTest) { scroll_child6.user_scrollable_vertical = true; scroll_child6.transform_id = child6->transform_tree_index(); expected_scroll_tree.Insert(scroll_child6, 2); + expected_scroll_tree.SetOwningLayerIdForNode(expected_scroll_tree.back(), + child6->id()); // The node owned by child7, child7 also owns a transform node ScrollNode scroll_child7; @@ -10725,6 +10792,8 @@ TEST_F(LayerTreeHostCommonTest, ScrollTreeBuilderTest) { scroll_child7.user_scrollable_vertical = true; scroll_child7.transform_id = child7->transform_tree_index(); expected_scroll_tree.Insert(scroll_child7, 1); + expected_scroll_tree.SetOwningLayerIdForNode(expected_scroll_tree.back(), + child7->id()); // The node owned by grand_child11, grand_child11 also owns a transform node ScrollNode scroll_grand_child11; @@ -10735,6 +10804,8 @@ TEST_F(LayerTreeHostCommonTest, ScrollTreeBuilderTest) { scroll_grand_child11.user_scrollable_vertical = true; scroll_grand_child11.transform_id = grand_child11->transform_tree_index(); expected_scroll_tree.Insert(scroll_grand_child11, 4); + expected_scroll_tree.SetOwningLayerIdForNode(expected_scroll_tree.back(), + grand_child11->id()); // The node owned by parent5 ScrollNode scroll_parent5; @@ -10747,6 +10818,8 @@ TEST_F(LayerTreeHostCommonTest, ScrollTreeBuilderTest) { scroll_parent5.user_scrollable_vertical = true; scroll_parent5.transform_id = parent5->transform_tree_index(); expected_scroll_tree.Insert(scroll_parent5, 1); + expected_scroll_tree.SetOwningLayerIdForNode(expected_scroll_tree.back(), + parent5->id()); expected_scroll_tree.SetScrollOffset(parent2->id(), gfx::ScrollOffset(0, 0)); expected_scroll_tree.SetScrollOffset(child7->id(), gfx::ScrollOffset(0, 0)); @@ -10766,5 +10839,38 @@ TEST_F(LayerTreeHostCommonTest, ScrollTreeBuilderTest) { EXPECT_EQ(scroll_root1.id, grand_child12->scroll_tree_index()); } +TEST_F(LayerTreeHostCommonTest, CanAdjustRasterScaleTest) { + LayerImpl* root = root_layer_for_testing(); + LayerImpl* render_surface = AddChild<LayerImpl>(root); + LayerImpl* child = AddChild<LayerImpl>(render_surface); + + root->SetBounds(gfx::Size(50, 50)); + + render_surface->SetBounds(gfx::Size(10, 10)); + render_surface->test_properties()->force_render_surface = true; + gfx::Transform transform; + transform.Scale(5.f, 5.f); + render_surface->test_properties()->transform = transform; + + child->SetDrawsContent(true); + child->SetMasksToBounds(true); + child->SetBounds(gfx::Size(10, 10)); + + ExecuteCalculateDrawPropertiesWithoutAdjustingRasterScales(root); + + // Check surface draw properties. + EXPECT_EQ(gfx::Rect(10, 10), + render_surface->GetRenderSurface()->content_rect()); + EXPECT_EQ(transform, render_surface->GetRenderSurface()->draw_transform()); + EXPECT_EQ(gfx::RectF(50.0f, 50.0f), + render_surface->GetRenderSurface()->DrawableContentRect()); + + // Check child layer draw properties. + EXPECT_EQ(gfx::Rect(10, 10), child->visible_layer_rect()); + EXPECT_EQ(gfx::Transform(), child->DrawTransform()); + EXPECT_EQ(gfx::Rect(10, 10), child->clip_rect()); + EXPECT_EQ(gfx::Rect(10, 10), child->drawable_content_rect()); +} + } // namespace } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_impl.cc b/chromium/cc/trees/layer_tree_host_impl.cc index ecfd4d84487..05e4e3add0a 100644 --- a/chromium/cc/trees/layer_tree_host_impl.cc +++ b/chromium/cc/trees/layer_tree_host_impl.cc @@ -24,13 +24,10 @@ #include "base/stl_util.h" #include "base/strings/stringprintf.h" #include "base/trace_event/trace_event_argument.h" +#include "cc/base/devtools_instrumentation.h" #include "cc/base/histograms.h" #include "cc/base/math_util.h" -#include "cc/debug/benchmark_instrumentation.h" -#include "cc/debug/debug_rect_history.h" -#include "cc/debug/devtools_instrumentation.h" -#include "cc/debug/frame_rate_counter.h" -#include "cc/debug/frame_viewer_instrumentation.h" +#include "cc/benchmarks/benchmark_instrumentation.h" #include "cc/debug/rendering_stats_instrumentation.h" #include "cc/debug/traced_value.h" #include "cc/input/browser_controls_offset_manager.h" @@ -40,9 +37,9 @@ #include "cc/input/scroll_state.h" #include "cc/input/scrollbar_animation_controller.h" #include "cc/layers/append_quads_data.h" +#include "cc/layers/effect_tree_layer_list_iterator.h" #include "cc/layers/heads_up_display_layer_impl.h" #include "cc/layers/layer_impl.h" -#include "cc/layers/layer_iterator.h" #include "cc/layers/painted_scrollbar_layer_impl.h" #include "cc/layers/render_surface_impl.h" #include "cc/layers/scrollbar_layer_impl_base.h" @@ -67,18 +64,23 @@ #include "cc/resources/ui_resource_bitmap.h" #include "cc/scheduler/delay_based_time_source.h" #include "cc/tiles/eviction_tile_priority_queue.h" +#include "cc/tiles/frame_viewer_instrumentation.h" #include "cc/tiles/gpu_image_decode_cache.h" #include "cc/tiles/picture_layer_tiling.h" #include "cc/tiles/raster_tile_priority_queue.h" #include "cc/tiles/software_image_decode_cache.h" #include "cc/trees/damage_tracker.h" +#include "cc/trees/debug_rect_history.h" #include "cc/trees/draw_property_utils.h" +#include "cc/trees/effect_node.h" +#include "cc/trees/frame_rate_counter.h" #include "cc/trees/latency_info_swap_promise_monitor.h" #include "cc/trees/layer_tree_host_common.h" #include "cc/trees/layer_tree_impl.h" #include "cc/trees/mutator_host.h" #include "cc/trees/scroll_node.h" #include "cc/trees/single_thread_proxy.h" +#include "cc/trees/transform_node.h" #include "cc/trees/tree_synchronizer.h" #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/context_support.h" @@ -237,7 +239,11 @@ LayerTreeHostImpl::LayerTreeHostImpl( requires_high_res_to_draw_(false), is_likely_to_require_a_draw_(false), has_valid_compositor_frame_sink_(false), - mutator_(nullptr) { + mutator_(nullptr), + scroll_animating_latched_node_id_(ScrollTree::kInvalidNodeId), + has_scrolled_by_wheel_(false), + has_scrolled_by_touch_(false), + touchpad_and_wheel_scroll_latching_enabled_(false) { DCHECK(mutator_host_); mutator_host_->SetMutatorHostClient(this); @@ -598,13 +604,12 @@ EventListenerProperties LayerTreeHostImpl::GetEventListenerProperties( // Return true if scrollable node for 'ancestor' is the same as 'child' or an // ancestor along the scroll tree. -bool IsScrolledBy(LayerImpl* child, ScrollNode* ancestor) { +bool LayerTreeHostImpl::IsScrolledBy(LayerImpl* child, ScrollNode* ancestor) { DCHECK(ancestor && ancestor->scrollable); if (!child) return false; - - auto* property_trees = child->layer_tree_impl()->property_trees(); - ScrollTree& scroll_tree = property_trees->scroll_tree; + DCHECK_EQ(child->layer_tree_impl(), active_tree_.get()); + ScrollTree& scroll_tree = active_tree_->property_trees()->scroll_tree; for (ScrollNode* scroll_node = scroll_tree.Node(child->scroll_tree_index()); scroll_node; scroll_node = scroll_tree.parent(scroll_node)) { if (scroll_node->id == ancestor->id) @@ -621,15 +626,22 @@ LayerTreeHostImpl::EventListenerTypeForTouchStartAt( // Now determine if there are actually any handlers at that point. // TODO(rbyers): Consider also honoring touch-action (crbug.com/347272). - LayerImpl* layer_impl = + LayerImpl* layer_impl_with_touch_handler = active_tree_->FindLayerThatIsHitByPointInTouchHandlerRegion( device_viewport_point); - if (layer_impl == NULL) + if (layer_impl_with_touch_handler == NULL) return InputHandler::TouchStartEventListenerType::NO_HANDLER; if (!CurrentlyScrollingNode()) return InputHandler::TouchStartEventListenerType::HANDLER; + // Check if the touch start hits on the current scrolling layer or its + // descendant. layer_impl_with_touch_handler is the layer hit by the pointer + // and has an event handler, otherwise it is null. + // We want to compare the most inner layer we are hitting on which may not + // have an event listener with the actual scrolling layer. + LayerImpl* layer_impl = + active_tree_->FindLayerThatIsHitByPoint(device_viewport_point); bool is_ancestor = IsScrolledBy(layer_impl, CurrentlyScrollingNode()); return is_ancestor ? InputHandler::TouchStartEventListenerType:: HANDLER_ON_SCROLLING_LAYER @@ -673,6 +685,22 @@ bool LayerTreeHostImpl::ScrollLayerTo(int layer_id, return true; } +bool LayerTreeHostImpl::ScrollingShouldSwitchtoMainThread() { + ScrollTree& scroll_tree = active_tree_->property_trees()->scroll_tree; + ScrollNode* scroll_node = scroll_tree.CurrentlyScrollingNode(); + + if (!scroll_node) + return true; + + for (; scroll_tree.parent(scroll_node); + scroll_node = scroll_tree.parent(scroll_node)) { + if (!!scroll_node->main_thread_scrolling_reasons) + return true; + } + + return false; +} + void LayerTreeHostImpl::QueueSwapPromiseForMainThreadScrollUpdate( std::unique_ptr<SwapPromise> swap_promise) { swap_promises_for_main_thread_scroll_update_.push_back( @@ -720,11 +748,6 @@ void LayerTreeHostImpl::FrameData::AsValueInto( } } -void LayerTreeHostImpl::FrameData::AppendRenderPass( - std::unique_ptr<RenderPass> render_pass) { - render_passes.push_back(std::move(render_pass)); -} - DrawMode LayerTreeHostImpl::GetDrawMode() const { if (resourceless_software_draw_) { return DRAW_MODE_RESOURCELESS_SOFTWARE; @@ -837,7 +860,7 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) { render_surface->contributes_to_drawn_surface() || render_surface->HasCopyRequest(); if (should_draw_into_render_pass) - render_surface->AppendRenderPasses(frame); + frame->render_passes.push_back(render_surface->CreateRenderPass()); } // Damage rects for non-root passes aren't meaningful, so set them to be @@ -885,19 +908,16 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) { active_tree()->property_trees()->effect_tree.HasCopyRequests(); bool have_missing_animated_tiles = false; - LayerIterator end = LayerIterator::End(frame->render_surface_layer_list); - for (LayerIterator it = - LayerIterator::Begin(frame->render_surface_layer_list); - it != end; ++it) { - auto target_render_pass_id = - it.target_render_surface_layer()->GetRenderSurface()->GetRenderPassId(); + for (EffectTreeLayerListIterator it(active_tree()); + it.state() != EffectTreeLayerListIterator::State::END; ++it) { + auto target_render_pass_id = it.target_render_surface()->GetRenderPassId(); RenderPass* target_render_pass = FindRenderPassById(frame->render_passes, target_render_pass_id); AppendQuadsData append_quads_data; - RenderSurfaceImpl* render_surface = it->GetRenderSurface(); - if (it.represents_target_render_surface()) { + if (it.state() == EffectTreeLayerListIterator::State::TARGET_SURFACE) { + RenderSurfaceImpl* render_surface = it.target_render_surface(); if (render_surface->HasCopyRequest()) { active_tree() ->property_trees() @@ -905,50 +925,57 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) { render_surface->EffectTreeIndex(), &target_render_pass->copy_requests); } - } else if (it.represents_contributing_render_surface() && - render_surface->contributes_to_drawn_surface()) { - render_surface->AppendQuads(target_render_pass, &append_quads_data); - } else if (it.represents_itself() && !it->visible_layer_rect().IsEmpty()) { + } else if (it.state() == + EffectTreeLayerListIterator::State::CONTRIBUTING_SURFACE) { + RenderSurfaceImpl* render_surface = it.current_render_surface(); + if (render_surface->contributes_to_drawn_surface()) + render_surface->AppendQuads(target_render_pass, &append_quads_data); + } else if (it.state() == EffectTreeLayerListIterator::State::LAYER && + !it.current_layer()->visible_layer_rect().IsEmpty()) { + LayerImpl* layer = it.current_layer(); bool occluded = - it->draw_properties().occlusion_in_content_space.IsOccluded( - it->visible_layer_rect()); - if (!occluded && it->WillDraw(draw_mode, resource_provider_.get())) { - DCHECK_EQ(active_tree_.get(), it->layer_tree_impl()); + layer->draw_properties().occlusion_in_content_space.IsOccluded( + layer->visible_layer_rect()); + if (!occluded && layer->WillDraw(draw_mode, resource_provider_.get())) { + DCHECK_EQ(active_tree_.get(), layer->layer_tree_impl()); - frame->will_draw_layers.push_back(*it); - if (it->may_contain_video()) + frame->will_draw_layers.push_back(layer); + if (layer->may_contain_video()) frame->may_contain_video = true; - it->AppendQuads(target_render_pass, &append_quads_data); + layer->AppendQuads(target_render_pass, &append_quads_data); } ++layers_drawn; - } - rendering_stats_instrumentation_->AddVisibleContentArea( - append_quads_data.visible_layer_area); - rendering_stats_instrumentation_->AddApproximatedVisibleContentArea( - append_quads_data.approximated_visible_content_area); - rendering_stats_instrumentation_->AddCheckerboardedVisibleContentArea( - append_quads_data.checkerboarded_visible_content_area); - rendering_stats_instrumentation_->AddCheckerboardedNoRecordingContentArea( - append_quads_data.checkerboarded_no_recording_content_area); - rendering_stats_instrumentation_->AddCheckerboardedNeedsRasterContentArea( - append_quads_data.checkerboarded_needs_raster_content_area); - - num_missing_tiles += append_quads_data.num_missing_tiles; - num_incomplete_tiles += append_quads_data.num_incomplete_tiles; - checkerboarded_no_recording_content_area += - append_quads_data.checkerboarded_no_recording_content_area; - checkerboarded_needs_raster_content_area += - append_quads_data.checkerboarded_needs_raster_content_area; - if (append_quads_data.num_missing_tiles > 0) { - have_missing_animated_tiles |= - !it->was_ever_ready_since_last_transform_animation() || - it->screen_space_transform_is_animating(); - } else { - it->set_was_ever_ready_since_last_transform_animation(true); + rendering_stats_instrumentation_->AddVisibleContentArea( + append_quads_data.visible_layer_area); + rendering_stats_instrumentation_->AddApproximatedVisibleContentArea( + append_quads_data.approximated_visible_content_area); + rendering_stats_instrumentation_->AddCheckerboardedVisibleContentArea( + append_quads_data.checkerboarded_visible_content_area); + rendering_stats_instrumentation_->AddCheckerboardedNoRecordingContentArea( + append_quads_data.checkerboarded_no_recording_content_area); + rendering_stats_instrumentation_->AddCheckerboardedNeedsRasterContentArea( + append_quads_data.checkerboarded_needs_raster_content_area); + + num_missing_tiles += append_quads_data.num_missing_tiles; + num_incomplete_tiles += append_quads_data.num_incomplete_tiles; + checkerboarded_no_recording_content_area += + append_quads_data.checkerboarded_no_recording_content_area; + checkerboarded_needs_raster_content_area += + append_quads_data.checkerboarded_needs_raster_content_area; + if (append_quads_data.num_missing_tiles > 0) { + have_missing_animated_tiles |= + !layer->was_ever_ready_since_last_transform_animation() || + layer->screen_space_transform_is_animating(); + } else { + layer->set_was_ever_ready_since_last_transform_animation(true); + } } + frame->embedded_surfaces.insert(frame->embedded_surfaces.end(), + append_quads_data.embedded_surfaces.begin(), + append_quads_data.embedded_surfaces.end()); } // If CommitToActiveTree() is true, then we wait to draw until @@ -1020,11 +1047,6 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) { checkerboarded_needs_raster_content_area); } - // Should only have one render pass in resourceless software mode. - DCHECK(draw_mode != DRAW_MODE_RESOURCELESS_SOFTWARE || - frame->render_passes.size() == 1u) - << frame->render_passes.size(); - TRACE_EVENT_END2("cc", "LayerTreeHostImpl::CalculateRenderPasses", "draw_result", draw_result, "missing tiles", num_missing_tiles); @@ -1169,7 +1191,8 @@ void LayerTreeHostImpl::RemoveRenderPasses(FrameData* frame) { break; } - if (pass->quad_list.empty() && pass->copy_requests.empty()) { + if (pass->quad_list.empty() && pass->copy_requests.empty() && + pass->filters.IsEmpty() && pass->background_filters.IsEmpty()) { // Remove the pass and decrement |i| to counter the for loop's increment, // so we don't skip the next pass in the loop. frame->render_passes.erase(frame->render_passes.begin() + i); @@ -1328,10 +1351,12 @@ void LayerTreeHostImpl::SetIsLikelyToRequireADraw( is_likely_to_require_a_draw_ = is_likely_to_require_a_draw; } -gfx::ColorSpace LayerTreeHostImpl::GetTileColorSpace() const { - if (!sync_tree()) +gfx::ColorSpace LayerTreeHostImpl::GetRasterColorSpace() const { + if (!settings_.enable_color_correct_rasterization) return gfx::ColorSpace(); - return sync_tree()->device_color_space(); + if (!sync_tree()) + return gfx::ColorSpace::CreateSRGB(); + return sync_tree()->raster_color_space(); } void LayerTreeHostImpl::RequestImplSideInvalidation() { @@ -1600,13 +1625,14 @@ CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() const { for (LayerImpl* surface_layer : active_tree_->SurfaceLayers()) { SurfaceLayerImpl* surface_layer_impl = static_cast<SurfaceLayerImpl*>(surface_layer); - metadata.referenced_surfaces.push_back( - surface_layer_impl->primary_surface_info().id()); - // We need to retain a reference to the fallback surface too so that it's - // guaranteed to be available when needed. - if (surface_layer_impl->fallback_surface_info().is_valid()) { + if (settings_.enable_surface_synchronization) { + if (surface_layer_impl->fallback_surface_info().is_valid()) { + metadata.referenced_surfaces.push_back( + surface_layer_impl->fallback_surface_info().id()); + } + } else { metadata.referenced_surfaces.push_back( - surface_layer_impl->fallback_surface_info().id()); + surface_layer_impl->primary_surface_info().id()); } } if (!InnerViewportScrollLayer()) @@ -1683,6 +1709,7 @@ bool LayerTreeHostImpl::DrawLayers(FrameData* frame) { CompositorFrameMetadata metadata = MakeCompositorFrameMetadata(); metadata.may_contain_video = frame->may_contain_video; + metadata.embedded_surfaces = std::move(frame->embedded_surfaces); active_tree()->FinishSwapPromises(&metadata); for (auto& latency : metadata.latency_info) { TRACE_EVENT_WITH_FLOW1("input,benchmark", "LatencyInfo.Flow", @@ -1707,11 +1734,21 @@ bool LayerTreeHostImpl::DrawLayers(FrameData* frame) { } } + DCHECK_LE(BeginFrameArgs::kStartingFrameNumber, + frame->begin_frame_ack.sequence_number); + metadata.begin_frame_ack = frame->begin_frame_ack; + CompositorFrame compositor_frame; compositor_frame.metadata = std::move(metadata); resource_provider_->PrepareSendToParent(resources, &compositor_frame.resource_list); compositor_frame.render_pass_list = std::move(frame->render_passes); + // TODO(fsamuel): Once all clients get their LocalSurfaceId from their parent, + // the LocalSurfaceId should hang off CompositorFrameMetadata. + if (active_tree()->local_surface_id().is_valid()) { + compositor_frame_sink_->SetLocalSurfaceId( + active_tree()->local_surface_id()); + } compositor_frame_sink_->SubmitCompositorFrame(std::move(compositor_frame)); // Clears the list of swap promises after calling DidSwap on each of them to @@ -2041,10 +2078,10 @@ void LayerTreeHostImpl::ActivateSyncTree() { else active_tree_->MoveChangeTrackingToLayers(); } + TreeSynchronizer::PushLayerProperties(pending_tree(), active_tree()); active_tree_->property_trees()->PushOpacityIfNeeded( pending_tree_->property_trees()); - TreeSynchronizer::PushLayerProperties(pending_tree(), active_tree()); pending_tree_->PushPropertiesTo(active_tree_.get()); if (!pending_tree_->LayerListIsEmpty()) pending_tree_->property_trees()->ResetAllChangeTracking(); @@ -2108,6 +2145,17 @@ void LayerTreeHostImpl::SetVisible(bool visible) { if (visible_) { // TODO(crbug.com/469175): Replace with RequiresHighResToDraw. SetRequiresHighResToDraw(); + // Prior CompositorFrame may have been discarded and thus we need to ensure + // that we submit a new one, even if there are no tiles. Therefore, force a + // full viewport redraw. However, this is unnecessary when we become visible + // for the first time (before the first commit) as there is no prior + // CompositorFrame to replace. We can safely use |!active_tree_-> + // LayerListIsEmpty()| as a proxy for this, because we wouldn't be able to + // draw anything even if this is not the first time we become visible. + if (!active_tree_->LayerListIsEmpty()) { + SetFullViewportDamage(); + SetNeedsRedraw(); + } } else { EvictAllUIResources(); // Call PrepareTiles to evict tiles when we become invisible. @@ -2174,11 +2222,12 @@ void LayerTreeHostImpl::CreateTileManagerResources() { image_decode_cache_ = base::MakeUnique<GpuImageDecodeCache>( compositor_frame_sink_->worker_context_provider(), settings_.renderer_settings.preferred_tile_format, - settings_.gpu_decoded_image_budget_bytes); + settings_.decoded_image_working_set_budget_bytes, + settings_.decoded_image_cache_budget_bytes); } else { image_decode_cache_ = base::MakeUnique<SoftwareImageDecodeCache>( settings_.renderer_settings.preferred_tile_format, - settings_.software_decoded_image_budget_bytes); + settings_.decoded_image_working_set_budget_bytes); } // Pass the single-threaded synchronous task graph runner to the worker pool @@ -2237,7 +2286,8 @@ void LayerTreeHostImpl::CreateResourceAndRasterBufferProvider( *raster_buffer_provider = base::MakeUnique<GpuRasterBufferProvider>( compositor_context_provider, worker_context_provider, resource_provider_.get(), settings_.use_distance_field_text, - msaa_sample_count, settings_.async_worker_context_enabled); + msaa_sample_count, settings_.renderer_settings.preferred_tile_format, + settings_.async_worker_context_enabled); return; } @@ -2293,7 +2343,38 @@ LayerImpl* LayerTreeHostImpl::ViewportMainScrollLayer() { return viewport()->MainScrollLayer(); } +void LayerTreeHostImpl::QueueImageDecode( + sk_sp<const SkImage> image, + const base::Callback<void(bool)>& embedder_callback) { + decoded_image_tracker_.QueueImageDecode( + std::move(image), base::Bind(&LayerTreeHostImpl::ImageDecodeFinished, + base::Unretained(this), embedder_callback)); +} + +void LayerTreeHostImpl::ImageDecodeFinished( + const base::Callback<void(bool)>& embedder_callback, + bool decode_succeeded) { + completed_image_decode_callbacks_.emplace_back( + base::Bind(embedder_callback, decode_succeeded)); + client_->SetNeedsCommitOnImplThread(); +} + +std::vector<base::Closure> +LayerTreeHostImpl::TakeCompletedImageDecodeCallbacks() { + auto result = std::move(completed_image_decode_callbacks_); + completed_image_decode_callbacks_.clear(); + return result; +} + +void LayerTreeHostImpl::ClearImageCacheOnNavigation() { + if (image_decode_cache_) + image_decode_cache_->ClearCache(); +} + void LayerTreeHostImpl::DidChangeScrollbarVisibility() { + // Need a commit since input handling for scrollbars is handled in Blink so + // we need to communicate to Blink when the compositor shows/hides the + // scrollbars. client_->SetNeedsCommitOnImplThread(); } @@ -2380,7 +2461,7 @@ bool LayerTreeHostImpl::InitializeRenderer( settings_.renderer_settings.texture_id_allocation_chunk_size, compositor_frame_sink_->capabilities().delegated_sync_points_required, settings_.renderer_settings.use_gpu_memory_buffer_resources, - settings_.enable_color_correct_rendering, + settings_.enable_color_correct_rasterization, settings_.renderer_settings.buffer_to_texture_target_map); // Since the new context may be capable of MSAA, update status here. We don't @@ -2480,9 +2561,11 @@ float LayerTreeHostImpl::CurrentBrowserControlsShownRatio() const { return active_tree_->CurrentBrowserControlsShownRatio(); } -void LayerTreeHostImpl::BindToClient(InputHandlerClient* client) { +void LayerTreeHostImpl::BindToClient(InputHandlerClient* client, + bool wheel_scroll_latching_enabled) { DCHECK(input_handler_client_ == NULL); input_handler_client_ = client; + touchpad_and_wheel_scroll_latching_enabled_ = wheel_scroll_latching_enabled; } InputHandler::ScrollStatus LayerTreeHostImpl::TryScroll( @@ -2668,6 +2751,8 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBeginImpl( client_->RenewTreePriority(); RecordCompositorSlowScrollMetric(type, CC_THREAD); + UpdateScrollSourceInfo(wheel_scrolling_); + return scroll_status; } @@ -2805,8 +2890,8 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimatedBegin( // this does not currently go through the scroll customization machinery // that ScrollBy uses for non-animated wheel scrolls. scroll_status = ScrollBegin(&scroll_state, WHEEL); - scroll_node = scroll_tree.CurrentlyScrollingNode(); if (scroll_status.thread == SCROLL_ON_IMPL_THREAD) { + scroll_animating_latched_node_id_ = ScrollTree::kInvalidNodeId; ScrollStateData scroll_state_end_data; scroll_state_end_data.is_ending = true; ScrollState scroll_state_end(scroll_state_end_data); @@ -2878,7 +2963,15 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimated( MainThreadScrollingReason::kNotScrollingOnMain; ScrollTree& scroll_tree = active_tree_->property_trees()->scroll_tree; ScrollNode* scroll_node = scroll_tree.CurrentlyScrollingNode(); + if (scroll_node) { + // Flash the overlay scrollbar even if the scroll dalta is 0. + ScrollbarAnimationController* animation_controller = + ScrollbarAnimationControllerForId(scroll_node->owning_layer_id); + + if (animation_controller) + animation_controller->WillUpdateScroll(); + gfx::Vector2dF delta = scroll_delta; if (!scroll_node->user_scrollable_horizontal) delta.set_x(0); @@ -2913,29 +3006,54 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimated( if (!scroll_node->scrollable) continue; + if (touchpad_and_wheel_scroll_latching_enabled_ && + scroll_animating_latched_node_id_ != ScrollTree::kInvalidNodeId && + scroll_node->id != scroll_animating_latched_node_id_) { + continue; + } + bool scrolls_main_viewport_scroll_layer = viewport()->MainScrollLayer() && viewport()->MainScrollLayer()->scroll_tree_index() == scroll_node->id; if (scrolls_main_viewport_scroll_layer) { + // Flash the overlay scrollbar even if the scroll dalta is 0. + ScrollbarAnimationController* animation_controller = + ScrollbarAnimationControllerForId(scroll_node->owning_layer_id); + + if (animation_controller) + animation_controller->WillUpdateScroll(); + gfx::Vector2dF scrolled = viewport()->ScrollAnimated(pending_delta, delayed_by); // Viewport::ScrollAnimated returns pending_delta as long as it starts // an animation. - if (scrolled == pending_delta) + if (scrolled == pending_delta) { + scroll_animating_latched_node_id_ = scroll_node->id; return scroll_status; + } break; } gfx::Vector2dF scroll_delta = ComputeScrollDelta(scroll_node, pending_delta); - if (ScrollAnimationCreate(scroll_node, scroll_delta, delayed_by)) + if (ScrollAnimationCreate(scroll_node, scroll_delta, delayed_by)) { + scroll_animating_latched_node_id_ = scroll_node->id; return scroll_status; + } pending_delta -= scroll_delta; } } scroll_state.set_is_ending(true); ScrollEnd(&scroll_state); + if (settings_.is_layer_tree_for_subframe && + scroll_status.thread == SCROLL_ON_IMPL_THREAD) { + // If we get to here, we shouldn't return SCROLL_ON_IMPL_THREAD as otherwise + // we'll mark the scroll as handled and the scroll won't bubble. + scroll_status.thread = SCROLL_IGNORED; + scroll_status.main_thread_scrolling_reasons = + MainThreadScrollingReason::kNotScrollable; + } return scroll_status; } @@ -3161,9 +3279,18 @@ InputHandlerScrollResult LayerTreeHostImpl::ScrollBy( DCHECK(scroll_state); TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollBy"); - if (!CurrentlyScrollingNode()) + ScrollTree& scroll_tree = active_tree_->property_trees()->scroll_tree; + ScrollNode* scroll_node = scroll_tree.CurrentlyScrollingNode(); + + if (!scroll_node) return InputHandlerScrollResult(); + ScrollbarAnimationController* animation_controller = + ScrollbarAnimationControllerForId(scroll_node->owning_layer_id); + + if (animation_controller) + animation_controller->WillUpdateScroll(); + float initial_top_controls_offset = browser_controls_offset_manager_->ControlsTopOffset(); @@ -3464,6 +3591,11 @@ std::unique_ptr<ScrollAndScaleSet> LayerTreeHostImpl::ProcessScrollDeltas() { active_tree_->elastic_overscroll()->PullDeltaForMainThread(); scroll_info->swap_promises.swap(swap_promises_for_main_thread_scroll_update_); + // Record and reset scroll source flags. + scroll_info->has_scrolled_by_wheel = has_scrolled_by_wheel_; + scroll_info->has_scrolled_by_touch = has_scrolled_by_touch_; + has_scrolled_by_wheel_ = has_scrolled_by_touch_ = false; + return scroll_info; } @@ -3785,7 +3917,7 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid, id = resource_provider_->CreateResource( upload_size, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format, - gfx::ColorSpace()); + gfx::ColorSpace::CreateSRGB()); if (!scaled) { AutoLockUIResourceBitmap bitmap_lock(bitmap); @@ -3965,55 +4097,6 @@ void LayerTreeHostImpl::SetMutatorsNeedCommit() {} void LayerTreeHostImpl::SetMutatorsNeedRebuildPropertyTrees() {} -void LayerTreeHostImpl::SetTreeLayerFilterMutated( - ElementId element_id, - LayerTreeImpl* tree, - const FilterOperations& filters) { - if (!tree) - return; - - PropertyTrees* property_trees = tree->property_trees(); - DCHECK_EQ(1u, - property_trees->element_id_to_effect_node_index.count(element_id)); - const int effect_node_index = - property_trees->element_id_to_effect_node_index[element_id]; - property_trees->effect_tree.OnFilterAnimated(filters, effect_node_index, - tree); -} - -void LayerTreeHostImpl::SetTreeLayerOpacityMutated(ElementId element_id, - LayerTreeImpl* tree, - float opacity) { - if (!tree) - return; - - PropertyTrees* property_trees = tree->property_trees(); - DCHECK_EQ(1u, - property_trees->element_id_to_effect_node_index.count(element_id)); - const int effect_node_index = - property_trees->element_id_to_effect_node_index[element_id]; - property_trees->effect_tree.OnOpacityAnimated(opacity, effect_node_index, - tree); -} - -void LayerTreeHostImpl::SetTreeLayerTransformMutated( - ElementId element_id, - LayerTreeImpl* tree, - const gfx::Transform& transform) { - if (!tree) - return; - - PropertyTrees* property_trees = tree->property_trees(); - DCHECK_EQ( - 1u, property_trees->element_id_to_transform_node_index.count(element_id)); - const int transform_node_index = - property_trees->element_id_to_transform_node_index[element_id]; - property_trees->transform_tree.OnTransformAnimated( - transform, transform_node_index, tree); - if (LayerImpl* layer = tree->LayerByElementId(element_id)) - layer->set_was_ever_ready_since_last_transform_animation(false); -} - void LayerTreeHostImpl::SetTreeLayerScrollOffsetMutated( ElementId element_id, LayerTreeImpl* tree, @@ -4047,10 +4130,12 @@ void LayerTreeHostImpl::SetElementFilterMutated( ElementListType list_type, const FilterOperations& filters) { if (list_type == ElementListType::ACTIVE) { - SetTreeLayerFilterMutated(element_id, active_tree(), filters); + active_tree()->SetFilterMutated(element_id, filters); } else { - SetTreeLayerFilterMutated(element_id, pending_tree(), filters); - SetTreeLayerFilterMutated(element_id, recycle_tree(), filters); + if (pending_tree()) + pending_tree()->SetFilterMutated(element_id, filters); + if (recycle_tree()) + recycle_tree()->SetFilterMutated(element_id, filters); } } @@ -4058,10 +4143,12 @@ void LayerTreeHostImpl::SetElementOpacityMutated(ElementId element_id, ElementListType list_type, float opacity) { if (list_type == ElementListType::ACTIVE) { - SetTreeLayerOpacityMutated(element_id, active_tree(), opacity); + active_tree()->SetOpacityMutated(element_id, opacity); } else { - SetTreeLayerOpacityMutated(element_id, pending_tree(), opacity); - SetTreeLayerOpacityMutated(element_id, recycle_tree(), opacity); + if (pending_tree()) + pending_tree()->SetOpacityMutated(element_id, opacity); + if (recycle_tree()) + recycle_tree()->SetOpacityMutated(element_id, opacity); } } @@ -4070,10 +4157,12 @@ void LayerTreeHostImpl::SetElementTransformMutated( ElementListType list_type, const gfx::Transform& transform) { if (list_type == ElementListType::ACTIVE) { - SetTreeLayerTransformMutated(element_id, active_tree(), transform); + active_tree()->SetTransformMutated(element_id, transform); } else { - SetTreeLayerTransformMutated(element_id, pending_tree(), transform); - SetTreeLayerTransformMutated(element_id, recycle_tree(), transform); + if (pending_tree()) + pending_tree()->SetTransformMutated(element_id, transform); + if (recycle_tree()) + recycle_tree()->SetTransformMutated(element_id, transform); } } @@ -4094,13 +4183,75 @@ void LayerTreeHostImpl::ElementIsAnimatingChanged( ElementListType list_type, const PropertyAnimationState& mask, const PropertyAnimationState& state) { + // TODO(weiliangc): Most of the code is duplicated with LayerTeeHost version + // of function. Should try to share code. LayerTreeImpl* tree = list_type == ElementListType::ACTIVE ? active_tree() : pending_tree(); if (!tree) return; - LayerImpl* layer = tree->LayerByElementId(element_id); - if (layer) - layer->OnIsAnimatingChanged(mask, state); + PropertyTrees* property_trees = tree->property_trees(); + + for (int property = TargetProperty::FIRST_TARGET_PROPERTY; + property <= TargetProperty::LAST_TARGET_PROPERTY; ++property) { + if (!mask.currently_running[property] && + !mask.potentially_animating[property]) + continue; + + switch (property) { + case TargetProperty::TRANSFORM: + if (TransformNode* transform_node = + property_trees->transform_tree.FindNodeFromElementId( + element_id)) { + if (mask.currently_running[property]) + transform_node->is_currently_animating = + state.currently_running[property]; + if (mask.potentially_animating[property]) { + transform_node->has_potential_animation = + state.potentially_animating[property]; + transform_node->has_only_translation_animations = + mutator_host()->HasOnlyTranslationTransforms(element_id, + list_type); + property_trees->transform_tree.set_needs_update(true); + tree->set_needs_update_draw_properties(); + // TODO(crbug.com/702777): + // was_ever_ready_since_last_transform_animation should not live on + // layers. + if (LayerImpl* layer = tree->LayerByElementId(element_id)) { + layer->set_was_ever_ready_since_last_transform_animation(false); + } + } + } + break; + case TargetProperty::OPACITY: + if (EffectNode* effect_node = + property_trees->effect_tree.FindNodeFromElementId(element_id)) { + if (mask.currently_running[property]) + effect_node->is_currently_animating_opacity = + state.currently_running[property]; + if (mask.potentially_animating[property]) { + effect_node->has_potential_opacity_animation = + state.potentially_animating[property]; + property_trees->effect_tree.set_needs_update(true); + } + } + break; + case TargetProperty::FILTER: + if (EffectNode* effect_node = + property_trees->effect_tree.FindNodeFromElementId(element_id)) { + if (mask.currently_running[property]) + effect_node->is_currently_animating_filter = + state.currently_running[property]; + if (mask.potentially_animating[property]) + effect_node->has_potential_filter_animation = + state.potentially_animating[property]; + // Filter animation changes only the node, and the subtree does not + // care. There is no need to request update on property trees here. + } + break; + default: + break; + } + } } void LayerTreeHostImpl::ScrollOffsetAnimationFinished() { @@ -4166,4 +4317,11 @@ void LayerTreeHostImpl::SetContextVisibility(bool is_visible) { } } +void LayerTreeHostImpl::UpdateScrollSourceInfo(bool is_wheel_scroll) { + if (is_wheel_scroll) + has_scrolled_by_wheel_ = true; + else + has_scrolled_by_touch_ = true; +} + } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_impl.h b/chromium/cc/trees/layer_tree_host_impl.h index 704eb1ab922..0b72dc47333 100644 --- a/chromium/cc/trees/layer_tree_host_impl.h +++ b/chromium/cc/trees/layer_tree_host_impl.h @@ -17,14 +17,13 @@ #include "base/callback.h" #include "base/macros.h" #include "base/time/time.h" -#include "cc/base/cc_export.h" #include "cc/base/synced_property.h" -#include "cc/debug/micro_benchmark_controller_impl.h" +#include "cc/benchmarks/micro_benchmark_controller_impl.h" +#include "cc/cc_export.h" #include "cc/input/browser_controls_offset_manager_client.h" #include "cc/input/input_handler.h" #include "cc/input/scrollbar_animation_controller.h" #include "cc/layers/layer_collections.h" -#include "cc/layers/render_pass_sink.h" #include "cc/output/begin_frame_args.h" #include "cc/output/compositor_frame_sink_client.h" #include "cc/output/context_cache_controller.h" @@ -36,6 +35,8 @@ #include "cc/scheduler/commit_earlyout_reason.h" #include "cc/scheduler/draw_result.h" #include "cc/scheduler/video_frame_controller.h" +#include "cc/surfaces/local_surface_id.h" +#include "cc/surfaces/surface_id.h" #include "cc/tiles/decoded_image_tracker.h" #include "cc/tiles/image_decode_cache.h" #include "cc/tiles/tile_manager.h" @@ -152,7 +153,8 @@ class CC_EXPORT LayerTreeHostImpl ~LayerTreeHostImpl() override; // InputHandler implementation - void BindToClient(InputHandlerClient* client) override; + void BindToClient(InputHandlerClient* client, + bool wheel_scroll_latching_enabled) override; InputHandler::ScrollStatus ScrollBegin( ScrollState* scroll_state, InputHandler::ScrollInputType type) override; @@ -200,6 +202,7 @@ class CC_EXPORT LayerTreeHostImpl bool GetScrollOffsetForLayer(int layer_id, gfx::ScrollOffset* offset) override; bool ScrollLayerTo(int layer_id, const gfx::ScrollOffset& offset) override; + bool ScrollingShouldSwitchtoMainThread() override; // BrowserControlsOffsetManagerClient implementation. float TopControlsHeight() const override; @@ -215,11 +218,12 @@ class CC_EXPORT LayerTreeHostImpl resourceless_software_draw_ = true; } - struct CC_EXPORT FrameData : public RenderPassSink { + struct CC_EXPORT FrameData { FrameData(); - ~FrameData() override; + ~FrameData(); void AsValueInto(base::trace_event::TracedValue* value) const; + std::vector<SurfaceId> embedded_surfaces; std::vector<gfx::Rect> occluding_screen_space_rects; std::vector<gfx::Rect> non_occluding_screen_space_rects; RenderPassList render_passes; @@ -227,9 +231,7 @@ class CC_EXPORT LayerTreeHostImpl LayerImplList will_draw_layers; bool has_no_damage; bool may_contain_video; - - // RenderPassSink implementation. - void AppendRenderPass(std::unique_ptr<RenderPass> render_pass) override; + BeginFrameAck begin_frame_ack; private: DISALLOW_COPY_AND_ASSIGN(FrameData); @@ -257,15 +259,6 @@ class CC_EXPORT LayerTreeHostImpl // virtual for testing. virtual void InvalidateContentOnImplSide(); - void SetTreeLayerFilterMutated(ElementId element_id, - LayerTreeImpl* tree, - const FilterOperations& filters); - void SetTreeLayerOpacityMutated(ElementId element_id, - LayerTreeImpl* tree, - float opacity); - void SetTreeLayerTransformMutated(ElementId element_id, - LayerTreeImpl* tree, - const gfx::Transform& transform); void SetTreeLayerScrollOffsetMutated(ElementId element_id, LayerTreeImpl* tree, const gfx::ScrollOffset& scroll_offset); @@ -354,7 +347,7 @@ class CC_EXPORT LayerTreeHostImpl std::unique_ptr<EvictionTilePriorityQueue> BuildEvictionQueue( TreePriority tree_priority) override; void SetIsLikelyToRequireADraw(bool is_likely_to_require_a_draw) override; - gfx::ColorSpace GetTileColorSpace() const override; + gfx::ColorSpace GetRasterColorSpace() const override; void RequestImplSideInvalidation() override; // ScrollbarAnimationControllerClient implementation. @@ -603,6 +596,12 @@ class CC_EXPORT LayerTreeHostImpl LayerImpl* ViewportMainScrollLayer(); + void QueueImageDecode(sk_sp<const SkImage> image, + const base::Callback<void(bool)>& embedder_callback); + std::vector<base::Closure> TakeCompletedImageDecodeCallbacks(); + + void ClearImageCacheOnNavigation(); + protected: LayerTreeHostImpl( const LayerTreeSettings& settings, @@ -702,6 +701,18 @@ class CC_EXPORT LayerTreeHostImpl base::TimeDelta delayed_by); void SetContextVisibility(bool is_visible); + void ImageDecodeFinished(const base::Callback<void(bool)>& embedder_callback, + bool decode_succeeded); + + // This function keeps track of sources of scrolls that are handled in the + // compositor side. The information gets shared by the main thread as part of + // the begin_main_frame_state. Finally Use counters are updated in the main + // thread side to keep track of the frequency of scrolling with different + // sources per page load. TODO(crbug.com/691886): Use GRC API to plumb the + // scroll source info for Use Counters. + void UpdateScrollSourceInfo(bool is_wheel_scroll); + + bool IsScrolledBy(LayerImpl* child, ScrollNode* ancestor); using UIResourceMap = std::unordered_map<UIResourceId, UIResourceData>; UIResourceMap ui_resource_map_; @@ -713,6 +724,8 @@ class CC_EXPORT LayerTreeHostImpl CompositorFrameSink* compositor_frame_sink_; + LocalSurfaceId local_surface_id_; + // The following scoped variables must not outlive the // |compositor_frame_sink_|. // These should be transfered to ContextCacheController's @@ -843,6 +856,22 @@ class CC_EXPORT LayerTreeHostImpl std::unique_ptr<PendingTreeDurationHistogramTimer> pending_tree_duration_timer_; + // The id of the scroll node to which scroll animations must latch. + // This gets reset at ScrollAnimatedBegin, and updated the first time that a + // scroll animation is created in ScrollAnimated. + int scroll_animating_latched_node_id_; + + // These callbacks are stored here to be transfered to the main thread when we + // begin main frame. These callbacks must only be called on the main thread. + std::vector<base::Closure> completed_image_decode_callbacks_; + + // These are used to transfer usage of touch and wheel scrolls to the main + // thread. + bool has_scrolled_by_wheel_; + bool has_scrolled_by_touch_; + + bool touchpad_and_wheel_scroll_latching_enabled_; + DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImpl); }; diff --git a/chromium/cc/trees/layer_tree_host_impl_unittest.cc b/chromium/cc/trees/layer_tree_host_impl_unittest.cc index 5c12dbc07db..a52bdf7996c 100644 --- a/chromium/cc/trees/layer_tree_host_impl_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_impl_unittest.cc @@ -30,6 +30,7 @@ #include "cc/layers/render_surface_impl.h" #include "cc/layers/solid_color_layer_impl.h" #include "cc/layers/solid_color_scrollbar_layer_impl.h" +#include "cc/layers/surface_layer_impl.h" #include "cc/layers/texture_layer_impl.h" #include "cc/layers/video_layer_impl.h" #include "cc/layers/viewport.h" @@ -93,6 +94,19 @@ using media::VideoFrame; namespace cc { namespace { +SurfaceId MakeSurfaceId(const FrameSinkId& frame_sink_id, uint32_t local_id) { + return SurfaceId( + frame_sink_id, + LocalSurfaceId(local_id, base::UnguessableToken::Deserialize(0, 1u))); +} + +struct TestFrameData : public LayerTreeHostImpl::FrameData { + TestFrameData() { + // Set ack to something valid, so DCHECKs don't complain. + begin_frame_ack = BeginFrameAck(0, 1, 1, true); + } +}; + class LayerTreeHostImplTest : public testing::Test, public LayerTreeHostImplClient { public: @@ -115,7 +129,6 @@ class LayerTreeHostImplTest : public testing::Test, LayerTreeSettings settings; settings.minimum_occlusion_tracking_size = gfx::Size(); settings.renderer_settings.texture_id_allocation_chunk_size = 1; - settings.verify_clip_tree_calculations = true; settings.renderer_settings.buffer_to_texture_target_map = DefaultBufferToTextureTargetMapForTesting(); return settings; @@ -166,8 +179,7 @@ class LayerTreeHostImplTest : public testing::Test, did_complete_page_scale_animation_ = true; } void OnDrawForCompositorFrameSink(bool resourceless_software_draw) override { - std::unique_ptr<LayerTreeHostImpl::FrameData> frame( - new LayerTreeHostImpl::FrameData); + std::unique_ptr<TestFrameData> frame(new TestFrameData); EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(frame.get())); last_on_draw_render_passes_.clear(); RenderPass::CopyAll(frame->render_passes, &last_on_draw_render_passes_); @@ -326,6 +338,8 @@ class LayerTreeHostImplTest : public testing::Test, LayerImpl::Create(layer_tree_impl, kPageScaleLayerId); inner_scroll->SetScrollClipLayer(inner_clip->id()); + inner_scroll->SetElementId( + LayerIdToElementIdForTesting(inner_scroll->id())); inner_scroll->SetBounds(content_size); inner_scroll->SetPosition(gfx::PointF()); @@ -338,6 +352,8 @@ class LayerTreeHostImplTest : public testing::Test, std::unique_ptr<LayerImpl> outer_scroll = LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId); outer_scroll->SetScrollClipLayer(outer_clip->id()); + outer_scroll->SetElementId( + LayerIdToElementIdForTesting(outer_scroll->id())); outer_scroll->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting(outer_scroll->id(), @@ -401,9 +417,6 @@ class LayerTreeHostImplTest : public testing::Test, inner_clip_layer->SetBounds(viewport_size); host_impl_->InnerViewportScrollLayer()->SetBounds(viewport_size); - // Needs to happen before building property trees as the latter propagates - // these element ids to property tree nodes. - host_impl_->active_tree()->SetElementIdsForTesting(); host_impl_->active_tree()->BuildPropertyTreesForTesting(); host_impl_->SetViewportSize(viewport_size); @@ -420,6 +433,7 @@ class LayerTreeHostImplTest : public testing::Test, std::unique_ptr<LayerImpl> layer = LayerImpl::Create(host_impl_->active_tree(), id); layer->SetScrollClipLayer(clip_layer->id()); + layer->SetElementId(LayerIdToElementIdForTesting(layer->id())); layer->SetDrawsContent(true); layer->SetBounds(size); clip_layer->SetBounds(gfx::Size(size.width() / 2, size.height() / 2)); @@ -457,7 +471,7 @@ class LayerTreeHostImplTest : public testing::Test, } void DrawFrame() { - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -481,7 +495,7 @@ class LayerTreeHostImplTest : public testing::Test, } void DrawOneFrame() { - LayerTreeHostImpl::FrameData frame_data; + TestFrameData frame_data; host_impl_->PrepareToDraw(&frame_data); host_impl_->DidDrawAllLayers(frame_data); } @@ -531,7 +545,7 @@ class LayerTreeHostImplTest : public testing::Test, bool did_request_impl_side_invalidation_; base::Closure animation_task_; base::TimeDelta requested_animation_delay_; - std::unique_ptr<LayerTreeHostImpl::FrameData> last_on_draw_frame_; + std::unique_ptr<TestFrameData> last_on_draw_frame_; RenderPassList last_on_draw_render_passes_; scoped_refptr<AnimationTimeline> timeline_; std::unique_ptr<base::Thread> image_worker_; @@ -545,6 +559,58 @@ class LayerTreeHostImplTimelinesTest : public LayerTreeHostImplTest { } }; +class TestInputHandlerClient : public InputHandlerClient { + public: + TestInputHandlerClient() + : page_scale_factor_(0.f), + min_page_scale_factor_(-1.f), + max_page_scale_factor_(-1.f) {} + ~TestInputHandlerClient() override {} + + // InputHandlerClient implementation. + void WillShutdown() override {} + void Animate(base::TimeTicks time) override {} + void MainThreadHasStoppedFlinging() override {} + void ReconcileElasticOverscrollAndRootScroll() override {} + void UpdateRootLayerStateForSynchronousInputHandler( + const gfx::ScrollOffset& total_scroll_offset, + const gfx::ScrollOffset& max_scroll_offset, + const gfx::SizeF& scrollable_size, + float page_scale_factor, + float min_page_scale_factor, + float max_page_scale_factor) override { + DCHECK(total_scroll_offset.x() <= max_scroll_offset.x()); + DCHECK(total_scroll_offset.y() <= max_scroll_offset.y()); + last_set_scroll_offset_ = total_scroll_offset; + max_scroll_offset_ = max_scroll_offset; + scrollable_size_ = scrollable_size; + page_scale_factor_ = page_scale_factor; + min_page_scale_factor_ = min_page_scale_factor; + max_page_scale_factor_ = max_page_scale_factor; + } + void DeliverInputForBeginFrame() override {} + + gfx::ScrollOffset last_set_scroll_offset() { return last_set_scroll_offset_; } + + gfx::ScrollOffset max_scroll_offset() const { return max_scroll_offset_; } + + gfx::SizeF scrollable_size() const { return scrollable_size_; } + + float page_scale_factor() const { return page_scale_factor_; } + + float min_page_scale_factor() const { return min_page_scale_factor_; } + + float max_page_scale_factor() const { return max_page_scale_factor_; } + + private: + gfx::ScrollOffset last_set_scroll_offset_; + gfx::ScrollOffset max_scroll_offset_; + gfx::SizeF scrollable_size_; + float page_scale_factor_; + float min_page_scale_factor_; + float max_page_scale_factor_; +}; + TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) { // Note: It is not possible to disable the renderer once it has been set, // so we do not need to test that disabling the renderer notifies us @@ -661,6 +727,7 @@ TEST_F(LayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) { root_clip->test_properties()->AddChild(std::move(root_owned)); root->SetBounds(gfx::Size(110, 110)); root->SetScrollClipLayer(root_clip->id()); + root->SetElementId(LayerIdToElementIdForTesting(root->id())); root->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting(root->id(), scroll_offset); @@ -966,6 +1033,7 @@ TEST_F(LayerTreeHostImplTest, ScrollWithOverlappingNonScrollableLayer) { std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 3); scroll->SetBounds(scroll_content_size); scroll->SetScrollClipLayer(clip->id()); + scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); std::unique_ptr<SolidColorScrollbarLayerImpl> scrollbar = @@ -1037,6 +1105,7 @@ TEST_F(LayerTreeHostImplTest, ScrolledOverlappingDrawnScrollbarLayer) { std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 3); scroll->SetBounds(scroll_content_size); scroll->SetScrollClipLayer(clip->id()); + scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); std::unique_ptr<SolidColorScrollbarLayerImpl> drawn_scrollbar = @@ -1281,6 +1350,7 @@ TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) { overflow->SetBounds(overflow_size); overflow->SetScrollClipLayer( scroll_layer->test_properties()->parent->test_properties()->parent->id()); + overflow->SetElementId(LayerIdToElementIdForTesting(overflow->id())); overflow->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting(overflow->id(), @@ -1628,7 +1698,7 @@ TEST_F(LayerTreeHostImplTest, AnimationMarksLayerNotReady) { host_impl_->ResetRequiresHighResToDraw(); // Child layer has an animating transform but missing tiles. - FakeLayerTreeHostImpl::FrameData frame; + TestFrameData frame; DrawResult result = host_impl_->PrepareToDraw(&frame); EXPECT_EQ(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS, result); host_impl_->DidDrawAllLayers(frame); @@ -2105,7 +2175,7 @@ TEST_F(LayerTreeHostImplTest, ScrollDoesntBubble) { std::unique_ptr<std::set<LayerImpl*>> scroll_children( new std::set<LayerImpl*>); scroll_children->insert(child_clip); - parent->test_properties()->scroll_children.reset(scroll_children.release()); + parent->test_properties()->scroll_children = std::move(scroll_children); host_impl_->active_tree()->BuildPropertyTreesForTesting(); DrawFrame(); @@ -2791,15 +2861,19 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { host_impl_->active_tree()->BuildPropertyTreesForTesting(); host_impl_->active_tree()->DidBecomeActive(); DrawFrame(); + + // SetScrollLayerId will initialize the scrollbar which will cause it to + // show and request a redraw. + did_request_redraw_ = false; } void RunTest(LayerTreeSettings::ScrollbarAnimator animator) { LayerTreeSettings settings = DefaultSettings(); settings.scrollbar_animator = animator; - settings.scrollbar_show_delay = base::TimeDelta::FromMilliseconds(20); - settings.scrollbar_fade_out_delay = base::TimeDelta::FromMilliseconds(20); - settings.scrollbar_fade_out_duration = + settings.scrollbar_fade_delay = base::TimeDelta::FromMilliseconds(20); + settings.scrollbar_fade_out_resize_delay = base::TimeDelta::FromMilliseconds(20); + settings.scrollbar_fade_duration = base::TimeDelta::FromMilliseconds(20); // If no animator is set, scrollbar won't show and no animation is expected. bool expecting_animations = animator != LayerTreeSettings::NO_ANIMATOR; @@ -2831,6 +2905,25 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); EXPECT_TRUE(animation_task_.Equals(base::Closure())); + // For Aura Overlay Scrollbar, if no scroll happened during a scroll + // gesture, shows scrollbars and schedules a delay fade out. + host_impl_->ScrollBegin(BeginState(gfx::Point()).get(), + InputHandler::WHEEL); + host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2dF(0, 0)).get()); + host_impl_->ScrollEnd(EndState().get()); + EXPECT_FALSE(did_request_next_frame_); + EXPECT_FALSE(did_request_redraw_); + if (animator == LayerTreeSettings::AURA_OVERLAY) { + EXPECT_EQ(base::TimeDelta::FromMilliseconds(20), + requested_animation_delay_); + EXPECT_FALSE(animation_task_.Equals(base::Closure())); + requested_animation_delay_ = base::TimeDelta(); + animation_task_ = base::Closure(); + } else { + EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); + EXPECT_TRUE(animation_task_.Equals(base::Closure())); + } + // Before the scrollbar animation exists, we should not get redraws. BeginFrameArgs begin_frame_args = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2, fake_now); @@ -2938,7 +3031,9 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { host_impl_->DidFinishImplFrame(); } - // Scrollbar animation is not triggered unnecessarily. + // For Andrdoid, scrollbar animation is not triggered unnecessarily. + // For Aura Overlay Scrollbar, scrollbar appears even if scroll offset did + // not change. host_impl_->ScrollBegin(BeginState(gfx::Point()).get(), InputHandler::WHEEL); host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2dF(5, 0)).get()); @@ -2951,8 +3046,16 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { host_impl_->ScrollEnd(EndState().get()); EXPECT_FALSE(did_request_next_frame_); EXPECT_FALSE(did_request_redraw_); - EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); - EXPECT_TRUE(animation_task_.Equals(base::Closure())); + if (animator == LayerTreeSettings::AURA_OVERLAY) { + EXPECT_EQ(base::TimeDelta::FromMilliseconds(20), + requested_animation_delay_); + EXPECT_FALSE(animation_task_.Equals(base::Closure())); + requested_animation_delay_ = base::TimeDelta(); + animation_task_ = base::Closure(); + } else { + EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); + EXPECT_TRUE(animation_task_.Equals(base::Closure())); + } // Changing page scale triggers scrollbar animation. host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 4.f); @@ -2989,10 +3092,8 @@ class LayerTreeHostImplTestScrollbarOpacity : public LayerTreeHostImplTest { void RunTest(LayerTreeSettings::ScrollbarAnimator animator) { LayerTreeSettings settings = DefaultSettings(); settings.scrollbar_animator = animator; - settings.scrollbar_show_delay = base::TimeDelta::FromMilliseconds(20); - settings.scrollbar_fade_out_delay = base::TimeDelta::FromMilliseconds(20); - settings.scrollbar_fade_out_duration = - base::TimeDelta::FromMilliseconds(20); + settings.scrollbar_fade_delay = base::TimeDelta::FromMilliseconds(20); + settings.scrollbar_fade_duration = base::TimeDelta::FromMilliseconds(20); gfx::Size content_size(100, 100); // If no animator is set, scrollbar won't show and no animation is expected. @@ -3085,6 +3186,75 @@ TEST_F(LayerTreeHostImplTestScrollbarOpacity, NoAnimator) { RunTest(LayerTreeSettings::NO_ANIMATOR); } +TEST_F(LayerTreeHostImplTest, ScrollbarVisibilityChangeCausesRedrawAndCommit) { + LayerTreeSettings settings = DefaultSettings(); + settings.scrollbar_animator = LayerTreeSettings::AURA_OVERLAY; + settings.scrollbar_fade_delay = base::TimeDelta::FromMilliseconds(20); + settings.scrollbar_fade_duration = base::TimeDelta::FromMilliseconds(20); + gfx::Size content_size(100, 100); + + CreateHostImpl(settings, CreateCompositorFrameSink()); + host_impl_->CreatePendingTree(); + CreateScrollAndContentsLayers(host_impl_->pending_tree(), content_size); + std::unique_ptr<SolidColorScrollbarLayerImpl> scrollbar = + SolidColorScrollbarLayerImpl::Create(host_impl_->pending_tree(), 400, + VERTICAL, 10, 0, false, true); + scrollbar->test_properties()->opacity = 0.f; + LayerImpl* scroll = host_impl_->pending_tree()->OuterViewportScrollLayer(); + LayerImpl* container = + host_impl_->pending_tree()->InnerViewportContainerLayer(); + scrollbar->SetScrollLayerId(scroll->id()); + container->test_properties()->AddChild(std::move(scrollbar)); + host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f); + host_impl_->pending_tree()->BuildPropertyTreesForTesting(); + host_impl_->ActivateSyncTree(); + + ScrollbarAnimationController* scrollbar_controller = + host_impl_->ScrollbarAnimationControllerForId(scroll->id()); + + // Scrollbars will flash shown but we should have a fade out animation + // queued. Run it and fade out the scrollbars. + { + ASSERT_FALSE(animation_task_.Equals(base::Closure())); + ASSERT_FALSE(animation_task_.IsCancelled()); + animation_task_.Run(); + + base::TimeTicks fake_now = base::TimeTicks::Now(); + scrollbar_controller->Animate(fake_now); + fake_now += settings.scrollbar_fade_delay; + scrollbar_controller->Animate(fake_now); + + ASSERT_TRUE(scrollbar_controller->ScrollbarsHidden()); + } + + // Move the mouse over the scrollbar region. This should post a delayed fade + // in task. Execute it to show the scrollbars. + { + animation_task_ = base::Closure(); + scrollbar_controller->DidMouseMoveNear(VERTICAL, 0); + ASSERT_FALSE(animation_task_.Equals(base::Closure())); + ASSERT_FALSE(animation_task_.IsCancelled()); + } + + // The fade in task should cause the scrollbars to show. Ensure that we + // requested a redraw and a commit. + { + did_request_redraw_ = false; + did_request_commit_ = false; + ASSERT_TRUE(scrollbar_controller->ScrollbarsHidden()); + animation_task_.Run(); + + base::TimeTicks fake_now = base::TimeTicks::Now(); + scrollbar_controller->Animate(fake_now); + fake_now += settings.scrollbar_fade_duration; + scrollbar_controller->Animate(fake_now); + + ASSERT_FALSE(scrollbar_controller->ScrollbarsHidden()); + EXPECT_TRUE(did_request_redraw_); + EXPECT_TRUE(did_request_commit_); + } +} + TEST_F(LayerTreeHostImplTest, ScrollbarInnerLargerThanOuter) { LayerTreeSettings settings = DefaultSettings(); CreateHostImpl(settings, CreateCompositorFrameSink()); @@ -3122,9 +3292,8 @@ TEST_F(LayerTreeHostImplTest, ScrollbarInnerLargerThanOuter) { TEST_F(LayerTreeHostImplTest, ScrollbarRegistration) { LayerTreeSettings settings = DefaultSettings(); settings.scrollbar_animator = LayerTreeSettings::ANDROID_OVERLAY; - settings.scrollbar_show_delay = base::TimeDelta::FromMilliseconds(20); - settings.scrollbar_fade_out_delay = base::TimeDelta::FromMilliseconds(20); - settings.scrollbar_fade_out_duration = base::TimeDelta::FromMilliseconds(20); + settings.scrollbar_fade_delay = base::TimeDelta::FromMilliseconds(20); + settings.scrollbar_fade_duration = base::TimeDelta::FromMilliseconds(20); CreateHostImpl(settings, CreateCompositorFrameSink()); gfx::Size viewport_size(300, 200); @@ -3192,6 +3361,7 @@ TEST_F(LayerTreeHostImplTest, ScrollbarRegistration) { // Check scrollbar registration on a sublayer. child->SetScrollClipLayer(child_clip->id()); + child->SetElementId(LayerIdToElementIdForTesting(child->id())); child_clip->test_properties()->AddChild(std::move(child)); root_scroll->test_properties()->AddChild(std::move(child_clip)); EXPECT_EQ(0ul, host_impl_->ScrollbarsFor(child_scroll_id).size()); @@ -3243,9 +3413,8 @@ TEST_F(LayerTreeHostImplTest, ScrollbarRegistration) { void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale( float device_scale_factor) { LayerTreeSettings settings = DefaultSettings(); - settings.scrollbar_show_delay = base::TimeDelta::FromMilliseconds(500); - settings.scrollbar_fade_out_delay = base::TimeDelta::FromMilliseconds(500); - settings.scrollbar_fade_out_duration = base::TimeDelta::FromMilliseconds(300); + settings.scrollbar_fade_delay = base::TimeDelta::FromMilliseconds(500); + settings.scrollbar_fade_duration = base::TimeDelta::FromMilliseconds(300); settings.scrollbar_animator = LayerTreeSettings::AURA_OVERLAY; gfx::Size viewport_size(300, 200); @@ -3290,31 +3459,24 @@ void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale( host_impl_->MouseMoveAt( gfx::Point(15 + kMouseDistanceToTriggerAnimation * 2, 1)); - EXPECT_FALSE( - scrollbar_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + EXPECT_FALSE(scrollbar_animation_controller->MouseIsNearScrollbar(VERTICAL)); host_impl_->MouseMoveAt( gfx::Point(15 + kMouseDistanceToTriggerAnimation - 1, 50)); - EXPECT_TRUE( - scrollbar_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_animation_controller->MouseIsNearScrollbar(VERTICAL)); host_impl_->MouseMoveAt( gfx::Point(15 + kMouseDistanceToTriggerAnimation, 100)); - EXPECT_FALSE( - scrollbar_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + EXPECT_FALSE(scrollbar_animation_controller->MouseIsNearScrollbar(VERTICAL)); did_request_redraw_ = false; - EXPECT_FALSE( - scrollbar_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + EXPECT_FALSE(scrollbar_animation_controller->MouseIsOverScrollbar(VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(10, 100)); - EXPECT_TRUE( - scrollbar_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_animation_controller->MouseIsOverScrollbar(VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(10, 120)); - EXPECT_TRUE( - scrollbar_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_animation_controller->MouseIsOverScrollbar(VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(150, 120)); - EXPECT_FALSE( - scrollbar_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + EXPECT_FALSE(scrollbar_animation_controller->MouseIsOverScrollbar(VERTICAL)); } TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) { @@ -3325,6 +3487,43 @@ TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf2) { SetupMouseMoveAtWithDeviceScale(2.f); } +// This test verifies that only SurfaceLayers in the viewport are included +// in CompositorFrameMetadata's |embedded_surfaces|. +TEST_F(LayerTreeHostImplTest, EmbeddedSurfacesInMetadata) { + SetupScrollAndContentsLayers(gfx::Size(100, 100)); + host_impl_->SetViewportSize(gfx::Size(50, 50)); + LayerImpl* root = host_impl_->active_tree()->root_layer_for_testing(); + + std::vector<SurfaceId> children = {MakeSurfaceId(FrameSinkId(1, 1), 1), + MakeSurfaceId(FrameSinkId(2, 2), 2), + MakeSurfaceId(FrameSinkId(3, 3), 3)}; + for (size_t i = 0; i < children.size(); ++i) { + std::unique_ptr<SurfaceLayerImpl> child = + SurfaceLayerImpl::Create(host_impl_->active_tree(), i + 6); + child->SetPosition(gfx::PointF(25.f * i, 0.f)); + child->SetBounds(gfx::Size(1, 1)); + child->SetDrawsContent(true); + child->SetPrimarySurfaceInfo( + SurfaceInfo(children[i], 1.f /* device_scale_factor */, + gfx::Size(10, 10) /* size_in_pixels */)); + root->test_properties()->AddChild(std::move(child)); + } + + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + DrawFrame(); + + FakeCompositorFrameSink* fake_compositor_frame_sink = + static_cast<FakeCompositorFrameSink*>( + host_impl_->compositor_frame_sink()); + const CompositorFrameMetadata& metadata = + fake_compositor_frame_sink->last_sent_frame()->metadata; + EXPECT_THAT(metadata.embedded_surfaces, + testing::UnorderedElementsAre(children[0], children[1])); + EXPECT_THAT( + metadata.referenced_surfaces, + testing::UnorderedElementsAre(children[0], children[1], children[2])); +} + TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) { SetupScrollAndContentsLayers(gfx::Size(100, 100)); host_impl_->SetViewportSize(gfx::Size(50, 50)); @@ -3526,7 +3725,7 @@ TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) { host_impl_->active_tree()->BuildPropertyTreesForTesting(); { - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -3539,7 +3738,7 @@ TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) { host_impl_->SetViewportDamage(gfx::Rect(10, 10)); { - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; layer->set_will_draw_returns_false(); layer->ClearDidDrawCheck(); @@ -3572,7 +3771,7 @@ TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) { layer->SetBounds(gfx::Size(10, 10)); host_impl_->active_tree()->BuildPropertyTreesForTesting(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_FALSE(layer->will_draw_called()); EXPECT_FALSE(layer->did_draw_called()); @@ -3629,7 +3828,7 @@ TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) { top_layer->SetContentsOpaque(true); host_impl_->active_tree()->BuildPropertyTreesForTesting(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_FALSE(occluded_layer->will_draw_called()); EXPECT_FALSE(occluded_layer->did_draw_called()); @@ -3671,9 +3870,7 @@ TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) { EXPECT_FALSE(layer1->did_draw_called()); EXPECT_FALSE(layer2->did_draw_called()); - LayerTreeHostImpl::FrameData frame; - FakeLayerTreeHostImpl::RecursiveUpdateNumChildren( - *host_impl_->active_tree()->begin()); + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -3842,7 +4039,7 @@ TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsAndFails) { root->test_properties()->force_render_surface = true; host_impl_->active_tree()->BuildPropertyTreesForTesting(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -3869,7 +4066,7 @@ TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsAndFails) { if (testcase.high_res_required) host_impl_->SetRequiresHighResToDraw(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -4038,6 +4235,7 @@ class LayerTreeHostImplBrowserControlsTest : public LayerTreeHostImplTest { root_clip->SetBounds(inner_viewport_size); root->SetScrollClipLayer(root_clip->id()); + root->SetElementId(LayerIdToElementIdForTesting(root->id())); root->SetBounds(outer_viewport_size); root->SetPosition(gfx::PointF()); root->SetDrawsContent(false); @@ -4045,6 +4243,8 @@ class LayerTreeHostImplBrowserControlsTest : public LayerTreeHostImplTest { root->test_properties()->is_container_for_fixed_position_layers = true; outer_clip->SetBounds(outer_viewport_size); outer_scroll->SetScrollClipLayer(outer_clip->id()); + outer_scroll->SetElementId( + LayerIdToElementIdForTesting(outer_scroll->id())); outer_scroll->SetBounds(scroll_layer_size); outer_scroll->SetPosition(gfx::PointF()); outer_scroll->SetDrawsContent(false); @@ -4398,6 +4598,7 @@ TEST_F(LayerTreeHostImplBrowserControlsTest, child_clip->SetBounds(sub_content_layer_size); child->SetScrollClipLayer(child_clip->id()); + child->SetElementId(LayerIdToElementIdForTesting(child->id())); child->SetBounds(sub_content_size); child->SetPosition(gfx::PointF()); child->SetDrawsContent(true); @@ -4944,6 +5145,7 @@ TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) { std::unique_ptr<LayerImpl> scroll_layer = LayerImpl::Create(host_impl_->active_tree(), 12); scroll_layer->SetScrollClipLayer(scroll_clip_layer->id()); + scroll_layer->SetElementId(LayerIdToElementIdForTesting(scroll_layer->id())); scroll_layer->SetBounds(contents_size); scroll_layer->SetPosition(gfx::PointF()); scroll_layer->test_properties()->AddChild(std::move(content_layer)); @@ -5229,7 +5431,7 @@ TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) { // Make sure all the layers are drawn with the page scale delta applied, i.e., // the page scale delta on the root layer is applied hierarchically. - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -5349,6 +5551,106 @@ TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) { } } +TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimatedLatchToChild) { + // Enable wheel scroll latching flag. + TestInputHandlerClient input_handler_client; + host_impl_->BindToClient(&input_handler_client, true); + + // Scroll a child layer beyond its maximum scroll range and make sure the + // parent layer isn't scrolled. + gfx::Size surface_size(100, 100); + gfx::Size content_size(150, 150); + + LayerImpl* root = + CreateBasicVirtualViewportLayers(surface_size, surface_size); + root->test_properties()->force_render_surface = true; + + root->test_properties()->force_render_surface = true; + std::unique_ptr<LayerImpl> grand_child = + CreateScrollableLayer(13, content_size, root); + + std::unique_ptr<LayerImpl> child = + CreateScrollableLayer(12, content_size, root); + LayerImpl* grand_child_layer = grand_child.get(); + child->test_properties()->AddChild(std::move(grand_child)); + + LayerImpl* child_layer = child.get(); + root->test_properties()->AddChild(std::move(child)); + host_impl_->active_tree()->SetElementIdsForTesting(); + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + host_impl_->active_tree()->DidBecomeActive(); + + grand_child_layer->layer_tree_impl() + ->property_trees() + ->scroll_tree.UpdateScrollOffsetBaseForTesting(grand_child_layer->id(), + gfx::ScrollOffset(0, 30)); + child_layer->layer_tree_impl() + ->property_trees() + ->scroll_tree.UpdateScrollOffsetBaseForTesting(child_layer->id(), + gfx::ScrollOffset(0, 50)); + + host_impl_->SetViewportSize(surface_size); + DrawFrame(); + + base::TimeTicks start_time = + base::TimeTicks() + base::TimeDelta::FromMilliseconds(10); + + BeginFrameArgs begin_frame_args = + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1); + + EXPECT_EQ( + InputHandler::SCROLL_ON_IMPL_THREAD, + host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, -100)).thread); + + begin_frame_args.frame_time = start_time; + begin_frame_args.sequence_number++; + host_impl_->WillBeginImplFrame(begin_frame_args); + host_impl_->Animate(); + host_impl_->UpdateAnimationState(true); + + EXPECT_EQ(gfx::ScrollOffset(0, 30), grand_child_layer->CurrentScrollOffset()); + host_impl_->DidFinishImplFrame(); + + begin_frame_args.frame_time = + start_time + base::TimeDelta::FromMilliseconds(200); + begin_frame_args.sequence_number++; + host_impl_->WillBeginImplFrame(begin_frame_args); + host_impl_->Animate(); + host_impl_->UpdateAnimationState(true); + + EXPECT_EQ(gfx::ScrollOffset(0, 0), grand_child_layer->CurrentScrollOffset()); + EXPECT_EQ(gfx::ScrollOffset(0, 50), child_layer->CurrentScrollOffset()); + host_impl_->DidFinishImplFrame(); + + // Second ScrollAnimated should still latch to the grand_child_layer. + EXPECT_EQ( + InputHandler::SCROLL_ON_IMPL_THREAD, + host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, -100)).thread); + + begin_frame_args.frame_time = + start_time + base::TimeDelta::FromMilliseconds(250); + begin_frame_args.sequence_number++; + host_impl_->WillBeginImplFrame(begin_frame_args); + host_impl_->Animate(); + host_impl_->UpdateAnimationState(true); + host_impl_->DidFinishImplFrame(); + + begin_frame_args.frame_time = + start_time + base::TimeDelta::FromMilliseconds(450); + begin_frame_args.sequence_number++; + host_impl_->WillBeginImplFrame(begin_frame_args); + host_impl_->Animate(); + host_impl_->UpdateAnimationState(true); + + EXPECT_EQ(gfx::ScrollOffset(0, 0), grand_child_layer->CurrentScrollOffset()); + EXPECT_EQ(gfx::ScrollOffset(0, 50), child_layer->CurrentScrollOffset()); + host_impl_->DidFinishImplFrame(); + + // Tear down the LayerTreeHostImpl before the InputHandlerClient. + host_impl_->ReleaseCompositorFrameSink(); + host_impl_ = nullptr; +} + TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) { // Scroll a child layer beyond its maximum scroll range and make sure the // the scroll doesn't bubble up to the parent layer. @@ -5894,58 +6196,6 @@ TEST_F(LayerTreeHostImplTest, ScrollViewportRounding) { inner_viewport_scroll_layer->MaxScrollOffset()); } -class TestInputHandlerClient : public InputHandlerClient { - public: - TestInputHandlerClient() - : page_scale_factor_(0.f), - min_page_scale_factor_(-1.f), - max_page_scale_factor_(-1.f) {} - ~TestInputHandlerClient() override {} - - // InputHandlerClient implementation. - void WillShutdown() override {} - void Animate(base::TimeTicks time) override {} - void MainThreadHasStoppedFlinging() override {} - void ReconcileElasticOverscrollAndRootScroll() override {} - void UpdateRootLayerStateForSynchronousInputHandler( - const gfx::ScrollOffset& total_scroll_offset, - const gfx::ScrollOffset& max_scroll_offset, - const gfx::SizeF& scrollable_size, - float page_scale_factor, - float min_page_scale_factor, - float max_page_scale_factor) override { - DCHECK(total_scroll_offset.x() <= max_scroll_offset.x()); - DCHECK(total_scroll_offset.y() <= max_scroll_offset.y()); - last_set_scroll_offset_ = total_scroll_offset; - max_scroll_offset_ = max_scroll_offset; - scrollable_size_ = scrollable_size; - page_scale_factor_ = page_scale_factor; - min_page_scale_factor_ = min_page_scale_factor; - max_page_scale_factor_ = max_page_scale_factor; - } - void DeliverInputForBeginFrame() override {} - - gfx::ScrollOffset last_set_scroll_offset() { return last_set_scroll_offset_; } - - gfx::ScrollOffset max_scroll_offset() const { return max_scroll_offset_; } - - gfx::SizeF scrollable_size() const { return scrollable_size_; } - - float page_scale_factor() const { return page_scale_factor_; } - - float min_page_scale_factor() const { return min_page_scale_factor_; } - - float max_page_scale_factor() const { return max_page_scale_factor_; } - - private: - gfx::ScrollOffset last_set_scroll_offset_; - gfx::ScrollOffset max_scroll_offset_; - gfx::SizeF scrollable_size_; - float page_scale_factor_; - float min_page_scale_factor_; - float max_page_scale_factor_; -}; - TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) { TestInputHandlerClient scroll_watcher; host_impl_->SetViewportSize(gfx::Size(10, 20)); @@ -5955,7 +6205,7 @@ TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) { clip_layer->SetBounds(gfx::Size(10, 20)); host_impl_->active_tree()->BuildPropertyTreesForTesting(); - host_impl_->BindToClient(&scroll_watcher); + host_impl_->BindToClient(&scroll_watcher, false); gfx::Vector2dF initial_scroll_delta(10.f, 10.f); scroll_layer->layer_tree_impl() @@ -6078,7 +6328,7 @@ TEST_F(LayerTreeHostImplTest, host_impl_->active_tree()->BuildPropertyTreesForTesting(); // Check scroll delta reflected in layer. - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -6527,6 +6777,7 @@ TEST_F(LayerTreeHostImplTest, ScrollFromOuterViewportSibling) { std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 11); scroll->SetBounds(gfx::Size(400, 400)); scroll->SetScrollClipLayer(clip->id()); + scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); scroll_layer = scroll.get(); @@ -6617,6 +6868,7 @@ TEST_F(LayerTreeHostImplTest, ScrollChainingWithReplacedOuterViewport) { std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 11); scroll->SetBounds(gfx::Size(400, 400)); scroll->SetScrollClipLayer(clip->id()); + scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); std::unique_ptr<LayerImpl> clip2 = LayerImpl::Create(layer_tree_impl, 12); @@ -6627,6 +6879,7 @@ TEST_F(LayerTreeHostImplTest, ScrollChainingWithReplacedOuterViewport) { std::unique_ptr<LayerImpl> scroll2 = LayerImpl::Create(layer_tree_impl, 13); scroll2->SetBounds(gfx::Size(500, 500)); scroll2->SetScrollClipLayer(clip2->id()); + scroll2->SetElementId(LayerIdToElementIdForTesting(scroll2->id())); scroll2->SetDrawsContent(true); scroll_layer = scroll.get(); @@ -6748,6 +7001,7 @@ TEST_F(LayerTreeHostImplTest, RootScrollerScrollNonDescendant) { std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 11); scroll->SetBounds(gfx::Size(1200, 1200)); scroll->SetScrollClipLayer(clip->id()); + scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); outer_scroll_layer = scroll.get(); @@ -6763,6 +7017,7 @@ TEST_F(LayerTreeHostImplTest, RootScrollerScrollNonDescendant) { std::unique_ptr<LayerImpl> scroll2 = LayerImpl::Create(layer_tree_impl, 15); scroll2->SetBounds(gfx::Size(1200, 1200)); scroll2->SetScrollClipLayer(clip2->id()); + scroll2->SetElementId(LayerIdToElementIdForTesting(scroll2->id())); scroll2->SetDrawsContent(true); sibling_scroll_layer = scroll2.get(); @@ -7027,7 +7282,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { static_cast<BlendStateCheckLayer*>(root->test_properties()->children[0]); layer1->SetPosition(gfx::PointF(2.f, 2.f)); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; // Opaque layer, drawn without blending. layer1->SetContentsOpaque(true); @@ -7142,8 +7397,6 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { layer1->SetUpdateRect(gfx::Rect(layer1->bounds())); layer2->SetExpectation(false, false); layer2->SetUpdateRect(gfx::Rect(layer1->bounds())); - FakeLayerTreeHostImpl::RecursiveUpdateNumChildren( - host_impl_->active_tree()->root_layer_for_testing()); host_impl_->active_tree()->BuildPropertyTreesForTesting(); EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); @@ -7269,7 +7522,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { static bool MayContainVideoBitSetOnFrameData(LayerTreeHostImpl* host_impl) { host_impl->active_tree()->BuildPropertyTreesForTesting(); host_impl->active_tree()->set_needs_update_draw_properties(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl->PrepareToDraw(&frame)); host_impl->DrawLayers(&frame); host_impl->DidDrawAllLayers(frame); @@ -7359,7 +7612,7 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest { child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size())); host_impl_->active_tree()->BuildPropertyTreesForTesting(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); ASSERT_EQ(1u, frame.render_passes.size()); @@ -7393,7 +7646,7 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest { void TestEmptyLayer() { SetUpEmptylayer(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); VerifyEmptyLayerRenderPasses(frame.render_passes); host_impl_->DidDrawAllLayers(frame); @@ -7430,7 +7683,7 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest { void TestLayerInMiddleOfViewport() { SetUpLayerInMiddleOfViewport(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); VerifyLayerInMiddleOfViewport(frame.render_passes); host_impl_->DidDrawAllLayers(frame); @@ -7466,7 +7719,7 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest { void TestLayerIsLargerThanViewport() { SetUpLayerIsLargerThanViewport(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); VerifyLayerIsLargerThanViewport(frame.render_passes); host_impl_->DidDrawAllLayers(frame); @@ -7664,7 +7917,7 @@ TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) { layer_tree_host_impl->active_tree()->SetRootLayerForTesting(std::move(root)); layer_tree_host_impl->active_tree()->BuildPropertyTreesForTesting(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; // First frame, the entire screen should get swapped. EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame)); @@ -7726,7 +7979,7 @@ TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) { host_impl_->active_tree()->SetRootLayerForTesting(std::move(root)); host_impl_->active_tree()->BuildPropertyTreesForTesting(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); EXPECT_EQ(1u, frame.render_surface_layer_list->size()); @@ -7845,7 +8098,7 @@ TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) { DefaultSettings(), true, this, &task_runner_provider_, &task_graph_runner, &stats_instrumentation_, compositor_frame_sink.get()); { - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame)); // Verify all quads have been computed @@ -7874,7 +8127,7 @@ TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) { DefaultSettings(), false, this, &task_runner_provider_, &task_graph_runner, &stats_instrumentation_, compositor_frame_sink.get()); { - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame)); // Verify all quads have been computed @@ -7920,7 +8173,7 @@ TEST_F(LayerTreeHostImplTest, LayersFreeTextures) { EXPECT_EQ(0u, context3d->NumTextures()); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -7948,7 +8201,7 @@ TEST_F(LayerTreeHostImplTest, HasTransparentBackground) { // Verify one quad is drawn when transparent background set is not set. host_impl_->active_tree()->set_has_transparent_background(false); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); { const auto& root_pass = frame.render_passes.back(); @@ -7982,7 +8235,7 @@ class LayerTreeHostImplTestDrawAndTestDamage : public LayerTreeHostImplTest { void DrawFrameAndTestDamage(const gfx::Rect& expected_damage) { bool expect_to_draw = !expected_damage.IsEmpty(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); if (!expect_to_draw) { @@ -8024,6 +8277,7 @@ TEST_F(LayerTreeHostImplTestDrawAndTestDamage, FrameIncludesDamageRect) { root->SetPosition(gfx::PointF()); root->SetBounds(gfx::Size(10, 10)); root->SetDrawsContent(true); + root->SetBackgroundColor(SK_ColorRED); root->test_properties()->force_render_surface = true; // Child layer is in the bottom right corner. @@ -8032,6 +8286,7 @@ TEST_F(LayerTreeHostImplTestDrawAndTestDamage, FrameIncludesDamageRect) { child->SetPosition(gfx::PointF(9.f, 9.f)); child->SetBounds(gfx::Size(1, 1)); child->SetDrawsContent(true); + child->SetBackgroundColor(SK_ColorRED); root->test_properties()->AddChild(std::move(child)); host_impl_->active_tree()->SetRootLayerForTesting(std::move(root)); @@ -8100,6 +8355,8 @@ TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) { gfx::ScrollOffset scroll_offset(100000, 0); scrolling_layer->SetScrollClipLayer(root->id()); + scrolling_layer->SetElementId( + LayerIdToElementIdForTesting(scrolling_layer->id())); host_impl_->pending_tree()->BuildPropertyTreesForTesting(); scrolling_layer->layer_tree_impl() @@ -8112,7 +8369,7 @@ TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) { host_impl_->active_tree()->UpdateDrawProperties(update_lcd_text); ASSERT_EQ(1u, host_impl_->active_tree()->RenderSurfaceLayerList().size()); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); ASSERT_EQ(1u, frame.render_passes.size()); @@ -8147,7 +8404,7 @@ TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) { SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1)); host_impl_->active_tree()->BuildPropertyTreesForTesting(); { - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -8301,12 +8558,36 @@ TEST_F(LayerTreeHostImplTest, MemoryLimits) { } } -TEST_F(LayerTreeHostImplTest, RequireHighResWhenVisible) { +namespace { +void ExpectFullDamageAndDraw(LayerTreeHostImpl* host_impl) { + gfx::Rect full_frame_damage(host_impl->DeviceViewport().size()); + TestFrameData frame; + EXPECT_EQ(DRAW_SUCCESS, host_impl->PrepareToDraw(&frame)); + ASSERT_EQ(1u, frame.render_passes.size()); + const RenderPass* root_render_pass = frame.render_passes.back().get(); + EXPECT_EQ(full_frame_damage, root_render_pass->damage_rect); + EXPECT_TRUE(host_impl->DrawLayers(&frame)); + host_impl->DidDrawAllLayers(frame); +} +} // namespace + +TEST_F(LayerTreeHostImplTestDrawAndTestDamage, + RequireHighResAndRedrawWhenVisible) { ASSERT_TRUE(host_impl_->active_tree()); + std::unique_ptr<SolidColorLayerImpl> root = + SolidColorLayerImpl::Create(host_impl_->active_tree(), 1); + root->SetBackgroundColor(SK_ColorRED); + SetupRootLayerImpl(std::move(root)); + + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + // RequiresHighResToDraw is set when new output surface is used. EXPECT_TRUE(host_impl_->RequiresHighResToDraw()); + // Expect full frame damage for first frame. + EXPECT_SCOPED(ExpectFullDamageAndDraw(host_impl_.get())); + host_impl_->ResetRequiresHighResToDraw(); host_impl_->SetVisible(false); @@ -8319,8 +8600,12 @@ TEST_F(LayerTreeHostImplTest, RequireHighResWhenVisible) { host_impl_->ResetRequiresHighResToDraw(); EXPECT_FALSE(host_impl_->RequiresHighResToDraw()); + did_request_redraw_ = false; host_impl_->SetVisible(true); EXPECT_TRUE(host_impl_->RequiresHighResToDraw()); + // Expect redraw and full frame damage when becoming visible. + EXPECT_TRUE(did_request_redraw_); + EXPECT_SCOPED(ExpectFullDamageAndDraw(host_impl_.get())); } TEST_F(LayerTreeHostImplTest, RequireHighResAfterGpuRasterizationToggles) { @@ -8432,7 +8717,7 @@ TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) { // correct width/height are passed directly to UIResourceBitmap. SkImageInfo info = SkImageInfo::Make(4, 2, kAlpha_8_SkColorType, kPremul_SkAlphaType); - sk_sp<SkPixelRef> pixel_ref(SkMallocPixelRef::NewAllocate(info, 0, 0)); + sk_sp<SkPixelRef> pixel_ref(SkMallocPixelRef::MakeAllocate(info, 0, 0)); pixel_ref->setImmutable(); UIResourceBitmap bitmap(std::move(pixel_ref), size); UIResourceId ui_resource_id = 1; @@ -8456,6 +8741,8 @@ class FrameSinkClient : public TestCompositorFrameSinkClient { return FakeOutputSurface::Create3d(std::move(display_context_provider_)); } + void DisplayReceivedLocalSurfaceId( + const LocalSurfaceId& local_surface_id) override {} void DisplayReceivedCompositorFrame(const CompositorFrame& frame) override {} void DisplayWillDrawAndSwap(bool will_draw_and_swap, const RenderPassList& render_passes) override {} @@ -8487,7 +8774,7 @@ TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) { base::Bind(&ShutdownReleasesContext_Callback))); host_impl_->active_tree()->BuildPropertyTreesForTesting(); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); @@ -8836,7 +9123,7 @@ TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) { host_impl_->active_tree()->QueuePinnedSwapPromise(std::move(swap_promise)); gfx::Rect full_frame_damage(host_impl_->DrawViewportSize()); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); EXPECT_TRUE(host_impl_->DrawLayers(&frame)); host_impl_->DidDrawAllLayers(frame); @@ -8880,7 +9167,7 @@ TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToCompositorFrameMetadata) { host_impl_->SetNeedsRedraw(); gfx::Rect full_frame_damage(host_impl_->DrawViewportSize()); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); EXPECT_TRUE(host_impl_->DrawLayers(&frame)); host_impl_->DidDrawAllLayers(frame); @@ -9550,6 +9837,7 @@ TEST_F(LayerTreeHostImplBrowserControlsTest, std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 11); scroll->SetBounds(scroll_content_size); scroll->SetScrollClipLayer(clip->id()); + scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); scroll_layer = scroll.get(); @@ -9611,6 +9899,8 @@ class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest { LayerImpl::Create(layer_tree_impl, kPageScaleLayerId); inner_scroll->SetScrollClipLayer(inner_clip->id()); + inner_scroll->SetElementId( + LayerIdToElementIdForTesting(inner_scroll->id())); inner_scroll->SetBounds(outer_viewport); inner_scroll->SetPosition(gfx::PointF()); @@ -9623,6 +9913,8 @@ class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest { std::unique_ptr<LayerImpl> outer_scroll = LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId); outer_scroll->SetScrollClipLayer(outer_clip->id()); + outer_scroll->SetElementId( + LayerIdToElementIdForTesting(outer_scroll->id())); outer_scroll->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting(outer_scroll->id(), @@ -10065,26 +10357,31 @@ TEST_F(LayerTreeHostImplTest, OnDrawConstraintSetNeedsRedraw) { EXPECT_FALSE(last_on_draw_frame_->has_no_damage); } -// We will force the touch event handler to be passive if we touch on a -// layer which is the current scrolling layer or its descendant. -TEST_F(LayerTreeHostImplTest, TouchInsideOrOutsideFlingLayer) { +// We will force the touch event handler to be passive if we touch on a layer +// which is the current scrolling layer. +TEST_F(LayerTreeHostImplTest, TouchInsideFlingLayer) { gfx::Size surface_size(100, 100); - gfx::Size inner_size(50, 50); + gfx::Size content_size(200, 200); LayerImpl* root = CreateBasicVirtualViewportLayers(surface_size, surface_size); root->test_properties()->force_render_surface = true; + // A div layer which has an event handler. std::unique_ptr<LayerImpl> child = CreateScrollableLayer(26, surface_size, root); LayerImpl* child_layer = child.get(); + // The layer tree should create a layer for the div layer, which is the + // actual scrolling layer. std::unique_ptr<LayerImpl> grand_child = - CreateScrollableLayer(27, inner_size, root); + CreateScrollableLayer(27, content_size, root); LayerImpl* grand_child_layer = grand_child.get(); + child->test_properties()->AddChild(std::move(grand_child)); root->test_properties()->AddChild(std::move(child)); + host_impl_->SetViewportSize(surface_size); host_impl_->active_tree()->BuildPropertyTreesForTesting(); host_impl_->active_tree()->DidBecomeActive(); DrawFrame(); @@ -10094,10 +10391,9 @@ TEST_F(LayerTreeHostImplTest, TouchInsideOrOutsideFlingLayer) { EXPECT_EQ(InputHandler::TouchStartEventListenerType::NO_HANDLER, host_impl_->EventListenerTypeForTouchStartAt(gfx::Point(10, 10))); child_layer->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100)); - grand_child_layer->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100)); EXPECT_EQ(InputHandler::TouchStartEventListenerType::HANDLER, host_impl_->EventListenerTypeForTouchStartAt(gfx::Point(10, 10))); - // Flinging the child layer. + // Flinging the grand_child layer. EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, host_impl_ ->ScrollBegin(BeginState(gfx::Point(60, 60)).get(), @@ -10105,20 +10401,78 @@ TEST_F(LayerTreeHostImplTest, TouchInsideOrOutsideFlingLayer) { .thread); EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, host_impl_->FlingScrollBegin().thread); - EXPECT_EQ(child_layer->scroll_tree_index(), + EXPECT_EQ(grand_child_layer->scroll_tree_index(), host_impl_->CurrentlyScrollingNode()->id); - // Touch on the child layer, which is an active fling layer, the touch + // Touch on the grand_child layer, which is an active fling layer, the touch // event handler will force to be passive. EXPECT_EQ( InputHandler::TouchStartEventListenerType::HANDLER_ON_SCROLLING_LAYER, host_impl_->EventListenerTypeForTouchStartAt(gfx::Point(70, 80))); - // Touch on the grand child layer, which is a descendant of an active fling - // layer, the touch event handler will force to be passive. + } +} + +// We will force the touch event handler to be passive if we touch on a layer +// which is a descendant of the current scrolling layer. If we touch on its +// ancestor, then the touch event handler will still be blocked. +TEST_F(LayerTreeHostImplTest, TouchInsideOrOutsideFlingLayer) { + gfx::Size surface_size(100, 100); + gfx::Size content_size(200, 200); + gfx::Size inner_size(50, 50); + + LayerImpl* root = + CreateBasicVirtualViewportLayers(surface_size, surface_size); + root->test_properties()->force_render_surface = true; + + // A div layer which has an event handler. + std::unique_ptr<LayerImpl> child = + CreateScrollableLayer(26, surface_size, root); + LayerImpl* child_layer = child.get(); + + // The layer tree should create a layer for the div layer, which is the + // actual scrolling layer. + std::unique_ptr<LayerImpl> grand_child = + CreateScrollableLayer(27, content_size, root); + LayerImpl* grand_child_layer = grand_child.get(); + + // A child scrollable layer inside grand_child_layer. + std::unique_ptr<LayerImpl> great_grand_child = + CreateScrollableLayer(28, inner_size, root); + LayerImpl* great_grand_child_layer = great_grand_child.get(); + + grand_child->test_properties()->AddChild(std::move(great_grand_child)); + child->test_properties()->AddChild(std::move(grand_child)); + root->test_properties()->AddChild(std::move(child)); + + host_impl_->SetViewportSize(surface_size); + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + host_impl_->active_tree()->DidBecomeActive(); + DrawFrame(); + + { + child_layer->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100)); + grand_child_layer->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 50, 50)); + // Flinging the grand_child layer. + EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, + host_impl_ + ->ScrollBegin(BeginState(gfx::Point(60, 60)).get(), + InputHandler::TOUCHSCREEN) + .thread); + EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, + host_impl_->FlingScrollBegin().thread); + EXPECT_EQ(grand_child_layer->scroll_tree_index(), + host_impl_->CurrentlyScrollingNode()->id); + // Touch on the grand_child layer, which is an active fling layer, the touch + // event handler will force to be passive. + EXPECT_EQ( + InputHandler::TouchStartEventListenerType::HANDLER_ON_SCROLLING_LAYER, + host_impl_->EventListenerTypeForTouchStartAt(gfx::Point(70, 80))); + // Touch on the great_grand_child_layer layer, which is the child of the + // active fling layer, the touch event handler will force to be passive. EXPECT_EQ( InputHandler::TouchStartEventListenerType::HANDLER_ON_SCROLLING_LAYER, host_impl_->EventListenerTypeForTouchStartAt(gfx::Point(20, 30))); - // Now flinging on the grand child layer. + // Now flinging on the great_grand_child_layer. EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, host_impl_ ->ScrollBegin(BeginState(gfx::Point(10, 10)).get(), @@ -10126,9 +10480,9 @@ TEST_F(LayerTreeHostImplTest, TouchInsideOrOutsideFlingLayer) { .thread); EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, host_impl_->FlingScrollBegin().thread); - EXPECT_EQ(grand_child_layer->scroll_tree_index(), + EXPECT_EQ(great_grand_child_layer->scroll_tree_index(), host_impl_->CurrentlyScrollingNode()->id); - // Touch on the child layer, the touch event handler will still be blocking. + // Touch on the child layer, the touch event handler will be blocked. EXPECT_EQ(InputHandler::TouchStartEventListenerType::HANDLER, host_impl_->EventListenerTypeForTouchStartAt(gfx::Point(60, 60))); } @@ -11007,7 +11361,7 @@ TEST_F(LayerTreeHostImplTest, InvalidLayerNotAddedToRasterQueue) { layer->SetBounds(gfx::Size(10, 10)); layer->set_gpu_raster_max_texture_size(host_impl_->device_viewport_size()); layer->SetDrawsContent(true); - layer->tilings()->AddTiling(1.0f, raster_source_with_tiles); + layer->tilings()->AddTiling(gfx::AxisTransform2d(), raster_source_with_tiles); layer->UpdateRasterSource(raster_source_with_tiles, &empty_invalidation, nullptr); layer->tilings()->tiling_at(0)->set_resolution( @@ -11141,7 +11495,7 @@ size_t CountRenderPassesWithId(const RenderPassList& list, int id) { } TEST_F(LayerTreeHostImplTest, RemoveUnreferencedRenderPass) { - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; frame.render_passes.push_back(RenderPass::Create()); RenderPass* pass3 = frame.render_passes.back().get(); frame.render_passes.push_back(RenderPass::Create()); @@ -11178,7 +11532,7 @@ TEST_F(LayerTreeHostImplTest, RemoveUnreferencedRenderPass) { } TEST_F(LayerTreeHostImplTest, RemoveEmptyRenderPass) { - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; frame.render_passes.push_back(RenderPass::Create()); RenderPass* pass3 = frame.render_passes.back().get(); frame.render_passes.push_back(RenderPass::Create()); @@ -11220,7 +11574,7 @@ TEST_F(LayerTreeHostImplTest, RemoveEmptyRenderPass) { } TEST_F(LayerTreeHostImplTest, DoNotRemoveEmptyRootRenderPass) { - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; frame.render_passes.push_back(RenderPass::Create()); RenderPass* pass3 = frame.render_passes.back().get(); frame.render_passes.push_back(RenderPass::Create()); @@ -11286,7 +11640,7 @@ TEST_F(LayerTreeHostImplTest, AddVideoFrameControllerInsideFrame) { host_impl_->DidFinishImplFrame(); EXPECT_FALSE(controller.did_draw_frame()); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; host_impl_->DidDrawAllLayers(frame); EXPECT_TRUE(controller.did_draw_frame()); @@ -11315,7 +11669,7 @@ TEST_F(LayerTreeHostImplTest, AddVideoFrameControllerOutsideFrame) { EXPECT_TRUE(controller.begin_frame_args().IsValid()); EXPECT_FALSE(controller.did_draw_frame()); - LayerTreeHostImpl::FrameData frame; + TestFrameData frame; host_impl_->DidDrawAllLayers(frame); EXPECT_TRUE(controller.did_draw_frame()); @@ -11707,9 +12061,8 @@ TEST_F(LayerTreeHostImplTest, RecomputeGpuRasterOnCompositorFrameSinkChange) { void LayerTreeHostImplTest::SetupMouseMoveAtTestScrollbarStates( bool main_thread_scrolling) { LayerTreeSettings settings = DefaultSettings(); - settings.scrollbar_show_delay = base::TimeDelta::FromMilliseconds(500); - settings.scrollbar_fade_out_delay = base::TimeDelta::FromMilliseconds(500); - settings.scrollbar_fade_out_duration = base::TimeDelta::FromMilliseconds(300); + settings.scrollbar_fade_delay = base::TimeDelta::FromMilliseconds(500); + settings.scrollbar_fade_duration = base::TimeDelta::FromMilliseconds(300); settings.scrollbar_animator = LayerTreeSettings::AURA_OVERLAY; gfx::Size viewport_size(300, 200); @@ -11770,32 +12123,28 @@ void LayerTreeHostImplTest::SetupMouseMoveAtTestScrollbarStates( host_impl_->MouseMoveAt( gfx::Point(15 + kMouseDistanceToTriggerAnimation, 150)); EXPECT_FALSE( - scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); EXPECT_FALSE( - scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + scrollbar_1_animation_controller->MouseIsOverScrollbar(VERTICAL)); host_impl_->MouseMoveAt( gfx::Point(14 + kMouseDistanceToTriggerAnimation, 150)); - EXPECT_TRUE( - scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); EXPECT_FALSE( - scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + scrollbar_1_animation_controller->MouseIsOverScrollbar(VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(10, 150)); - EXPECT_TRUE( - scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); - EXPECT_TRUE( - scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsOverScrollbar(VERTICAL)); host_impl_->MouseMoveAt( gfx::Point(14 + kMouseDistanceToTriggerAnimation, 150)); - EXPECT_TRUE( - scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); EXPECT_FALSE( - scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + scrollbar_1_animation_controller->MouseIsOverScrollbar(VERTICAL)); host_impl_->MouseMoveAt( gfx::Point(15 + kMouseDistanceToTriggerAnimation, 150)); EXPECT_FALSE( - scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); EXPECT_FALSE( - scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + scrollbar_1_animation_controller->MouseIsOverScrollbar(VERTICAL)); // scrollbar_2 on child. std::unique_ptr<SolidColorScrollbarLayerImpl> scrollbar_2 = @@ -11810,6 +12159,7 @@ void LayerTreeHostImplTest::SetupMouseMoveAtTestScrollbarStates( child->SetBounds(child_layer_size); child->SetDrawsContent(true); child->SetScrollClipLayer(child_clip_id); + child->SetElementId(LayerIdToElementIdForTesting(child->id())); if (main_thread_scrolling) { child->set_main_thread_scrolling_reasons( @@ -11835,42 +12185,36 @@ void LayerTreeHostImplTest::SetupMouseMoveAtTestScrollbarStates( // scrollbar_1, goes over scrollbar_1. host_impl_->MouseMoveAt(gfx::Point(60, 150)); EXPECT_FALSE( - scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); EXPECT_FALSE( - scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); - EXPECT_TRUE( - scrollbar_2_animation_controller->mouse_is_near_scrollbar(VERTICAL)); - EXPECT_TRUE( - scrollbar_2_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + scrollbar_1_animation_controller->MouseIsOverScrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_2_animation_controller->MouseIsNearScrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_2_animation_controller->MouseIsOverScrollbar(VERTICAL)); host_impl_->MouseMoveAt( gfx::Point(64 + kMouseDistanceToTriggerAnimation, 150)); EXPECT_FALSE( - scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); EXPECT_FALSE( - scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); - EXPECT_TRUE( - scrollbar_2_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + scrollbar_1_animation_controller->MouseIsOverScrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_2_animation_controller->MouseIsNearScrollbar(VERTICAL)); EXPECT_FALSE( - scrollbar_2_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + scrollbar_2_animation_controller->MouseIsOverScrollbar(VERTICAL)); host_impl_->MouseMoveAt( gfx::Point(14 + kMouseDistanceToTriggerAnimation, 150)); - EXPECT_TRUE( - scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); EXPECT_FALSE( - scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + scrollbar_1_animation_controller->MouseIsOverScrollbar(VERTICAL)); EXPECT_FALSE( - scrollbar_2_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + scrollbar_2_animation_controller->MouseIsNearScrollbar(VERTICAL)); EXPECT_FALSE( - scrollbar_2_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + scrollbar_2_animation_controller->MouseIsOverScrollbar(VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(10, 150)); - EXPECT_TRUE( - scrollbar_1_animation_controller->mouse_is_near_scrollbar(VERTICAL)); - EXPECT_TRUE( - scrollbar_1_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsOverScrollbar(VERTICAL)); EXPECT_FALSE( - scrollbar_2_animation_controller->mouse_is_near_scrollbar(VERTICAL)); + scrollbar_2_animation_controller->MouseIsNearScrollbar(VERTICAL)); EXPECT_FALSE( - scrollbar_2_animation_controller->mouse_is_over_scrollbar(VERTICAL)); + scrollbar_2_animation_controller->MouseIsOverScrollbar(VERTICAL)); // Capture scrollbar_1, then move mouse to scrollbar_2's layer, should post an // event to fade out scrollbar_1. diff --git a/chromium/cc/trees/layer_tree_host_perftest.cc b/chromium/cc/trees/layer_tree_host_perftest.cc index 1a25a13cb11..ff17af70317 100644 --- a/chromium/cc/trees/layer_tree_host_perftest.cc +++ b/chromium/cc/trees/layer_tree_host_perftest.cc @@ -13,7 +13,7 @@ #include "base/path_service.h" #include "base/strings/string_piece.h" #include "base/time/time.h" -#include "cc/debug/lap_timer.h" +#include "cc/base/lap_timer.h" #include "cc/layers/nine_patch_layer.h" #include "cc/layers/solid_color_layer.h" #include "cc/layers/texture_layer.h" @@ -59,10 +59,8 @@ class LayerTreeHostPerfTest : public LayerTreeTest { } void BeginMainFrame(const BeginFrameArgs& args) override { - if (begin_frame_driven_drawing_ && !TestEnded()) { - layer_tree_host()->SetNeedsAnimate(); - layer_tree_host()->SetNextCommitForcesRedraw(); - } + if (begin_frame_driven_drawing_ && !TestEnded()) + layer_tree_host()->SetNeedsCommitWithForcedRedraw(); } void BeginCommitOnThread(LayerTreeHostImpl* host_impl) override { @@ -309,9 +307,9 @@ class BrowserCompositorInvalidateLayerTreePerfTest clean_up_started_ = true; MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&BrowserCompositorInvalidateLayerTreePerfTest:: - CleanUpAndEndTestOnMainThread, - base::Unretained(this))); + base::BindOnce(&BrowserCompositorInvalidateLayerTreePerfTest:: + CleanUpAndEndTestOnMainThread, + base::Unretained(this))); } void CleanUpAndEndTestOnMainThread() { diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc index bd43e52f94f..eed99f6a625 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc @@ -9,10 +9,9 @@ #include "cc/layers/picture_image_layer.h" #include "cc/layers/picture_layer.h" #include "cc/layers/solid_color_layer.h" +#include "cc/paint/drawing_display_item.h" #include "cc/paint/paint_flags.h" #include "cc/paint/paint_recorder.h" -#include "cc/paint/paint_surface.h" -#include "cc/playback/drawing_display_item.h" #include "cc/test/layer_tree_pixel_resource_test.h" #include "cc/test/pixel_comparator.h" #include "cc/test/solid_color_content_layer_client.h" diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc b/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc index b74968e44c3..d6145d577c8 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc @@ -7,11 +7,11 @@ #include "cc/layers/content_layer_client.h" #include "cc/layers/picture_layer.h" #include "cc/output/copy_output_request.h" +#include "cc/paint/display_item_list.h" +#include "cc/paint/drawing_display_item.h" #include "cc/paint/paint_canvas.h" #include "cc/paint/paint_flags.h" #include "cc/paint/paint_recorder.h" -#include "cc/playback/display_item_list.h" -#include "cc/playback/drawing_display_item.h" #include "cc/test/layer_tree_pixel_test.h" #include "cc/test/test_compositor_frame_sink.h" #include "gpu/command_buffer/client/gles2_interface.h" @@ -203,15 +203,30 @@ TEST_F(LayerTreeHostTilesTestPartialInvalidation, base::FilePath(FILE_PATH_LITERAL("blue_yellow_flipped.png"))); } +// crbug.com/707711 +#if defined(OS_LINUX) +#define MAYBE_PartialRaster_MultiThread_OneCopy \ + DISABLED_PartialRaster_MultiThread_OneCopy +#else +#define MAYBE_PartialRaster_MultiThread_OneCopy \ + PartialRaster_MultiThread_OneCopy +#endif TEST_F(LayerTreeHostTilesTestPartialInvalidation, - PartialRaster_MultiThread_OneCopy) { + MAYBE_PartialRaster_MultiThread_OneCopy) { RunRasterPixelTest( true, PARTIAL_ONE_COPY, picture_layer_, base::FilePath(FILE_PATH_LITERAL("blue_yellow_partial_flipped.png"))); } +// crbug.com/707711 +#if defined(OS_LINUX) +#define MAYBE_FullRaster_MultiThread_OneCopy \ + DISABLED_FullRaster_MultiThread_OneCopy +#else +#define MAYBE_FullRaster_MultiThread_OneCopy FullRaster_MultiThread_OneCopy +#endif TEST_F(LayerTreeHostTilesTestPartialInvalidation, - FullRaster_MultiThread_OneCopy) { + MAYBE_FullRaster_MultiThread_OneCopy) { RunRasterPixelTest( true, FULL_ONE_COPY, picture_layer_, base::FilePath(FILE_PATH_LITERAL("blue_yellow_flipped.png"))); diff --git a/chromium/cc/trees/layer_tree_host_unittest.cc b/chromium/cc/trees/layer_tree_host_unittest.cc index 1f2059cb0c3..2e7457a49aa 100644 --- a/chromium/cc/trees/layer_tree_host_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_unittest.cc @@ -17,9 +17,9 @@ #include "base/synchronization/lock.h" #include "base/threading/thread_task_runner_handle.h" #include "cc/animation/timing_function.h" -#include "cc/debug/frame_rate_counter.h" #include "cc/input/scroll_elasticity_helper.h" #include "cc/layers/content_layer_client.h" +#include "cc/layers/heads_up_display_layer.h" #include "cc/layers/layer_impl.h" #include "cc/layers/painted_scrollbar_layer.h" #include "cc/layers/picture_layer.h" @@ -34,6 +34,7 @@ #include "cc/quads/render_pass_draw_quad.h" #include "cc/quads/tile_draw_quad.h" #include "cc/resources/ui_resource_manager.h" +#include "cc/test/begin_frame_args_test.h" #include "cc/test/fake_content_layer_client.h" #include "cc/test/fake_layer_tree_host_client.h" #include "cc/test/fake_output_surface.h" @@ -52,7 +53,9 @@ #include "cc/test/skia_common.h" #include "cc/test/test_compositor_frame_sink.h" #include "cc/test/test_web_graphics_context_3d.h" +#include "cc/trees/clip_node.h" #include "cc/trees/effect_node.h" +#include "cc/trees/frame_rate_counter.h" #include "cc/trees/layer_tree_host_common.h" #include "cc/trees/layer_tree_host_impl.h" #include "cc/trees/layer_tree_impl.h" @@ -802,7 +805,7 @@ class LayerTreeHostTestPushNodeOwnerToNodeIdMap : public LayerTreeHostTest { void DidCommit() override { switch (layer_tree_host()->SourceFrameNumber()) { case 1: - // child_ should create transform, effect, clip node. + // child_ should create transform, effect node. child_->SetForceRenderSurfaceForTesting(true); break; case 2: @@ -810,7 +813,12 @@ class LayerTreeHostTestPushNodeOwnerToNodeIdMap : public LayerTreeHostTest { child_->SetScrollClipLayerId(root_->id()); break; case 3: + // child_ should create a clip node. + child_->SetMasksToBounds(true); + break; + case 4: // child_ should not create any property tree node. + child_->SetMasksToBounds(false); child_->SetForceRenderSurfaceForTesting(false); child_->SetScrollClipLayerId(Layer::INVALID_ID); } @@ -818,92 +826,64 @@ class LayerTreeHostTestPushNodeOwnerToNodeIdMap : public LayerTreeHostTest { void CommitCompleteOnThread(LayerTreeHostImpl* impl) override { PropertyTrees* property_trees = impl->sync_tree()->property_trees(); - auto root_transform_id_to_index = - property_trees->layer_id_to_transform_node_index.find(root_->id()); - auto child_transform_id_to_index = - property_trees->layer_id_to_transform_node_index.find(child_->id()); - auto root_effect_id_to_index = - property_trees->layer_id_to_effect_node_index.find(root_->id()); - auto child_effect_id_to_index = - property_trees->layer_id_to_effect_node_index.find(child_->id()); - auto root_clip_id_to_index = - property_trees->layer_id_to_clip_node_index.find(root_->id()); - auto child_clip_id_to_index = - property_trees->layer_id_to_clip_node_index.find(child_->id()); - auto root_scroll_id_to_index = - property_trees->layer_id_to_scroll_node_index.find(root_->id()); - auto child_scroll_id_to_index = - property_trees->layer_id_to_scroll_node_index.find(child_->id()); + const TransformNode* root_transform_node = + property_trees->transform_tree.FindNodeFromOwningLayerId(root_->id()); + const TransformNode* child_transform_node = + property_trees->transform_tree.FindNodeFromOwningLayerId(child_->id()); + const EffectNode* root_effect_node = + property_trees->effect_tree.FindNodeFromOwningLayerId(root_->id()); + const EffectNode* child_effect_node = + property_trees->effect_tree.FindNodeFromOwningLayerId(child_->id()); + const ClipNode* root_clip_node = + property_trees->clip_tree.FindNodeFromOwningLayerId(root_->id()); + const ClipNode* child_clip_node = + property_trees->clip_tree.FindNodeFromOwningLayerId(child_->id()); + const ScrollNode* root_scroll_node = + property_trees->scroll_tree.FindNodeFromOwningLayerId(root_->id()); + const ScrollNode* child_scroll_node = + property_trees->scroll_tree.FindNodeFromOwningLayerId(child_->id()); switch (impl->sync_tree()->source_frame_number()) { case 0: - // root_ should create every property tree node and child_ should not - // create any. - EXPECT_NE(root_transform_id_to_index, - property_trees->layer_id_to_transform_node_index.end()); - EXPECT_EQ(root_transform_id_to_index->second, - root_->transform_tree_index()); - EXPECT_NE(root_effect_id_to_index, - property_trees->layer_id_to_effect_node_index.end()); - EXPECT_EQ(root_effect_id_to_index->second, root_->effect_tree_index()); - EXPECT_NE(root_clip_id_to_index, - property_trees->layer_id_to_clip_node_index.end()); - EXPECT_EQ(root_clip_id_to_index->second, root_->clip_tree_index()); - EXPECT_NE(root_scroll_id_to_index, - property_trees->layer_id_to_scroll_node_index.end()); - EXPECT_EQ(root_scroll_id_to_index->second, root_->scroll_tree_index()); - EXPECT_EQ(child_transform_id_to_index, - property_trees->layer_id_to_transform_node_index.end()); - EXPECT_EQ(child_effect_id_to_index, - property_trees->layer_id_to_effect_node_index.end()); - EXPECT_EQ(child_clip_id_to_index, - property_trees->layer_id_to_clip_node_index.end()); - EXPECT_EQ(child_scroll_id_to_index, - property_trees->layer_id_to_scroll_node_index.end()); + // root_ should create transform, scroll and effect tree nodes but not + // a clip node. + EXPECT_NE(root_transform_node, nullptr); + EXPECT_EQ(root_transform_node->id, root_->transform_tree_index()); + EXPECT_NE(root_effect_node, nullptr); + EXPECT_EQ(root_effect_node->id, root_->effect_tree_index()); + EXPECT_NE(root_scroll_node, nullptr); + EXPECT_EQ(root_scroll_node->id, root_->scroll_tree_index()); + EXPECT_EQ(root_clip_node, nullptr); + EXPECT_EQ(child_transform_node, nullptr); + EXPECT_EQ(child_effect_node, nullptr); + EXPECT_EQ(child_clip_node, nullptr); + EXPECT_EQ(child_scroll_node, nullptr); break; case 1: - // child_ should create a transfrom, clip, effect nodes but not a scroll + // child_ should create a transfrom, effect nodes but not a scroll, clip // node. - EXPECT_NE( - property_trees->layer_id_to_transform_node_index.find(child_->id()), - property_trees->layer_id_to_transform_node_index.end()); - EXPECT_EQ(child_transform_id_to_index->second, - child_->transform_tree_index()); - EXPECT_NE( - property_trees->layer_id_to_effect_node_index.find(child_->id()), - property_trees->layer_id_to_effect_node_index.end()); - EXPECT_EQ(child_effect_id_to_index->second, - child_->effect_tree_index()); - EXPECT_NE( - property_trees->layer_id_to_clip_node_index.find(child_->id()), - property_trees->layer_id_to_clip_node_index.end()); - EXPECT_EQ(child_clip_id_to_index->second, child_->clip_tree_index()); - EXPECT_EQ( - property_trees->layer_id_to_scroll_node_index.find(child_->id()), - property_trees->layer_id_to_scroll_node_index.end()); + EXPECT_NE(child_transform_node, nullptr); + EXPECT_EQ(child_transform_node->id, child_->transform_tree_index()); + EXPECT_NE(child_effect_node, nullptr); + EXPECT_EQ(child_effect_node->id, child_->effect_tree_index()); + EXPECT_EQ(child_clip_node, nullptr); + EXPECT_EQ(child_scroll_node, nullptr); break; case 2: // child_ should create a scroll node. - EXPECT_NE( - property_trees->layer_id_to_scroll_node_index.find(child_->id()), - property_trees->layer_id_to_scroll_node_index.end()); - EXPECT_EQ(child_scroll_id_to_index->second, - child_->scroll_tree_index()); + EXPECT_NE(child_scroll_node, nullptr); + EXPECT_EQ(child_scroll_node->id, child_->scroll_tree_index()); break; case 3: + // child_ should create a clip node. + EXPECT_NE(child_clip_node, nullptr); + EXPECT_EQ(child_clip_node->id, child_->clip_tree_index()); + break; + case 4: // child_ should not create any property tree nodes. - EXPECT_EQ( - property_trees->layer_id_to_transform_node_index.find(child_->id()), - property_trees->layer_id_to_transform_node_index.end()); - EXPECT_EQ( - property_trees->layer_id_to_effect_node_index.find(child_->id()), - property_trees->layer_id_to_effect_node_index.end()); - EXPECT_EQ( - property_trees->layer_id_to_clip_node_index.find(child_->id()), - property_trees->layer_id_to_clip_node_index.end()); - EXPECT_EQ( - property_trees->layer_id_to_scroll_node_index.find(child_->id()), - property_trees->layer_id_to_scroll_node_index.end()); - + EXPECT_EQ(child_transform_node, nullptr); + EXPECT_EQ(child_effect_node, nullptr); + EXPECT_EQ(child_clip_node, nullptr); + EXPECT_EQ(child_scroll_node, nullptr); EndTest(); break; } @@ -923,7 +903,6 @@ class LayerTreeHostTestPushElementIdToNodeIdMap : public LayerTreeHostTest { void SetupTree() override { root_ = Layer::Create(); child_ = Layer::Create(); - child_->SetElementId(kTestElementId); root_->AddChild(child_); layer_tree_host()->SetRootLayer(root_); LayerTreeHostTest::SetupTree(); @@ -961,13 +940,13 @@ class LayerTreeHostTestPushElementIdToNodeIdMap : public LayerTreeHostTest { ->property_trees() ->scroll_tree.size()); EXPECT_TRUE(property_trees->element_id_to_transform_node_index.find( - kTestElementId) == + child_->element_id()) == property_trees->element_id_to_transform_node_index.end()); EXPECT_TRUE(property_trees->element_id_to_effect_node_index.find( - kTestElementId) == + child_->element_id()) == property_trees->element_id_to_effect_node_index.end()); EXPECT_TRUE(property_trees->element_id_to_scroll_node_index.find( - kTestElementId) == + child_->element_id()) == property_trees->element_id_to_scroll_node_index.end()); break; case 1: @@ -981,12 +960,14 @@ class LayerTreeHostTestPushElementIdToNodeIdMap : public LayerTreeHostTest { ->property_trees() ->scroll_tree.size()); EXPECT_EQ( - 2, - property_trees->element_id_to_transform_node_index[kTestElementId]); - EXPECT_EQ( - 2, property_trees->element_id_to_effect_node_index[kTestElementId]); - EXPECT_EQ( - 2, property_trees->element_id_to_scroll_node_index[kTestElementId]); + 2, property_trees + ->element_id_to_transform_node_index[child_->element_id()]); + EXPECT_EQ(2, + property_trees + ->element_id_to_effect_node_index[child_->element_id()]); + EXPECT_EQ(2, + property_trees + ->element_id_to_scroll_node_index[child_->element_id()]); break; case 2: EXPECT_EQ(2U, child_impl_->layer_tree_impl() @@ -996,13 +977,13 @@ class LayerTreeHostTestPushElementIdToNodeIdMap : public LayerTreeHostTest { ->property_trees() ->effect_tree.size()); EXPECT_TRUE(property_trees->element_id_to_transform_node_index.find( - kTestElementId) == + child_->element_id()) == property_trees->element_id_to_transform_node_index.end()); EXPECT_TRUE(property_trees->element_id_to_effect_node_index.find( - kTestElementId) == + child_->element_id()) == property_trees->element_id_to_effect_node_index.end()); EXPECT_TRUE(property_trees->element_id_to_scroll_node_index.find( - kTestElementId) == + child_->element_id()) == property_trees->element_id_to_scroll_node_index.end()); break; } @@ -1012,8 +993,6 @@ class LayerTreeHostTestPushElementIdToNodeIdMap : public LayerTreeHostTest { void AfterTest() override {} private: - const ElementId kTestElementId = ElementId(42, 8118); - scoped_refptr<Layer> root_; scoped_refptr<Layer> child_; }; @@ -1149,8 +1128,7 @@ class LayerTreeHostTestPropertyTreesChangedSync : public LayerTreeHostTest { case OPACITY: index_++; impl->active_tree()->ResetAllChangeTracking(); - impl->active_tree()->property_trees()->effect_tree.OnOpacityAnimated( - 0.5f, root->effect_tree_index(), impl->active_tree()); + impl->active_tree()->SetOpacityMutated(root->element_id(), 0.5f); PostSetNeedsCommitToMainThread(); break; case TRANSFORM: @@ -1166,10 +1144,7 @@ class LayerTreeHostTestPropertyTreesChangedSync : public LayerTreeHostTest { ->LayerById(child_->id()) ->LayerPropertyChanged()); transform.Translate(10, 10); - impl->active_tree() - ->property_trees() - ->transform_tree.OnTransformAnimated( - transform, root->transform_tree_index(), impl->active_tree()); + impl->active_tree()->SetTransformMutated(root->element_id(), transform); PostSetNeedsCommitToMainThread(); break; case FILTER: @@ -1184,8 +1159,7 @@ class LayerTreeHostTestPropertyTreesChangedSync : public LayerTreeHostTest { ->LayerById(child_->id()) ->LayerPropertyChanged()); filters.Append(FilterOperation::CreateOpacityFilter(0.5f)); - impl->active_tree()->property_trees()->effect_tree.OnFilterAnimated( - filters, root->effect_tree_index(), impl->active_tree()); + impl->active_tree()->SetFilterMutated(root->element_id(), filters); PostSetNeedsCommitToMainThread(); break; case END: @@ -1259,8 +1233,7 @@ class LayerTreeHostTestEffectTreeSync : public LayerTreeHostTest { EffectNode* node = effect_tree.Node(root->effect_tree_index()); switch (impl->sync_tree()->source_frame_number()) { case 0: - effect_tree.OnOpacityAnimated(0.75f, root->effect_tree_index(), - impl->sync_tree()); + impl->sync_tree()->SetOpacityMutated(root->element_id(), 0.75f); PostSetNeedsCommitToMainThread(); break; case 1: @@ -1269,8 +1242,7 @@ class LayerTreeHostTestEffectTreeSync : public LayerTreeHostTest { break; case 2: EXPECT_EQ(node->opacity, 0.75f); - effect_tree.OnOpacityAnimated(0.75f, root->effect_tree_index(), - impl->sync_tree()); + impl->sync_tree()->SetOpacityMutated(root->element_id(), 0.75f); PostSetNeedsCommitToMainThread(); break; case 3: @@ -1279,8 +1251,8 @@ class LayerTreeHostTestEffectTreeSync : public LayerTreeHostTest { break; case 4: EXPECT_EQ(node->opacity, 0.25f); - impl->sync_tree()->property_trees()->effect_tree.OnFilterAnimated( - brightness_filter_, root->effect_tree_index(), impl->sync_tree()); + impl->sync_tree()->SetFilterMutated(root->element_id(), + brightness_filter_); PostSetNeedsCommitToMainThread(); break; case 5: @@ -1289,8 +1261,8 @@ class LayerTreeHostTestEffectTreeSync : public LayerTreeHostTest { break; case 6: EXPECT_EQ(node->filters, brightness_filter_); - impl->sync_tree()->property_trees()->effect_tree.OnFilterAnimated( - brightness_filter_, root->effect_tree_index(), impl->sync_tree()); + impl->sync_tree()->SetFilterMutated(root->element_id(), + brightness_filter_); PostSetNeedsCommitToMainThread(); break; case 7: @@ -1352,16 +1324,17 @@ class LayerTreeHostTestTransformTreeSync : public LayerTreeHostTest { void CommitCompleteOnThread(LayerTreeHostImpl* impl) override { TransformTree& transform_tree = impl->sync_tree()->property_trees()->transform_tree; - TransformNode* node = transform_tree.Node( - impl->sync_tree()->root_layer_for_testing()->transform_tree_index()); + const LayerImpl* root_layer = impl->sync_tree()->root_layer_for_testing(); + const TransformNode* node = + transform_tree.Node(root_layer->transform_tree_index()); gfx::Transform rotate10; rotate10.Rotate(10.f); gfx::Transform rotate20; rotate20.Rotate(20.f); switch (impl->sync_tree()->source_frame_number()) { case 0: - impl->sync_tree()->property_trees()->transform_tree.OnTransformAnimated( - rotate20, node->id, impl->sync_tree()); + impl->sync_tree()->SetTransformMutated(root_layer->element_id(), + rotate20); PostSetNeedsCommitToMainThread(); break; case 1: @@ -1370,8 +1343,8 @@ class LayerTreeHostTestTransformTreeSync : public LayerTreeHostTest { break; case 2: EXPECT_EQ(node->local, rotate20); - impl->sync_tree()->property_trees()->transform_tree.OnTransformAnimated( - rotate20, node->id, impl->sync_tree()); + impl->sync_tree()->SetTransformMutated(root_layer->element_id(), + rotate20); PostSetNeedsCommitToMainThread(); break; case 3: @@ -1455,8 +1428,7 @@ class LayerTreeHostTestTransformTreeDamageIsUpdated : public LayerTreeHostTest { if (impl->active_tree()->source_frame_number() == 0) { gfx::Transform scale; scale.Scale(2.0, 2.0); - impl->active_tree()->property_trees()->transform_tree.OnTransformAnimated( - scale, child_->transform_tree_index(), impl->active_tree()); + impl->active_tree()->SetTransformMutated(child_->element_id(), scale); } } @@ -1888,7 +1860,7 @@ class LayerTreeHostTestDeviceScaleFactorChange : public LayerTreeHostTest { SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestDeviceScaleFactorChange); -class LayerTreeHostTestDeviceColorSpaceChange : public LayerTreeHostTest { +class LayerTreeHostTestRasterColorSpaceChange : public LayerTreeHostTest { public: void SetupTree() override { space1_ = gfx::ColorSpace::CreateXYZD50(); @@ -1902,7 +1874,7 @@ class LayerTreeHostTestDeviceColorSpaceChange : public LayerTreeHostTest { root_layer_->AddChild(child_layer_); layer_tree_host()->SetRootLayer(root_layer_); - layer_tree_host()->SetDeviceColorSpace(space1_); + layer_tree_host()->SetRasterColorSpace(space1_); LayerTreeHostTest::SetupTree(); client_.set_bounds(root_layer_->bounds()); } @@ -1920,32 +1892,32 @@ class LayerTreeHostTestDeviceColorSpaceChange : public LayerTreeHostTest { // The first frame will have full damage, and should be in the initial // color space. EXPECT_FALSE(frame_data->has_no_damage); - EXPECT_TRUE(space1_ == host_impl->active_tree()->device_color_space()); + EXPECT_TRUE(space1_ == host_impl->active_tree()->raster_color_space()); break; case 1: // Empty commit. EXPECT_TRUE(frame_data->has_no_damage); - EXPECT_TRUE(space1_ == host_impl->active_tree()->device_color_space()); + EXPECT_TRUE(space1_ == host_impl->active_tree()->raster_color_space()); break; case 2: // The change from space1 to space2 should cause full damage. EXPECT_FALSE(frame_data->has_no_damage); - EXPECT_TRUE(space2_ == host_impl->active_tree()->device_color_space()); + EXPECT_TRUE(space2_ == host_impl->active_tree()->raster_color_space()); break; case 3: // Empty commit with the color space set to space2 redundantly. EXPECT_TRUE(frame_data->has_no_damage); - EXPECT_TRUE(space2_ == host_impl->active_tree()->device_color_space()); + EXPECT_TRUE(space2_ == host_impl->active_tree()->raster_color_space()); break; case 4: // The change from space2 to space1 should cause full damage. EXPECT_FALSE(frame_data->has_no_damage); - EXPECT_TRUE(space1_ == host_impl->active_tree()->device_color_space()); + EXPECT_TRUE(space1_ == host_impl->active_tree()->raster_color_space()); break; case 5: // Empty commit. EXPECT_TRUE(frame_data->has_no_damage); - EXPECT_TRUE(space1_ == host_impl->active_tree()->device_color_space()); + EXPECT_TRUE(space1_ == host_impl->active_tree()->raster_color_space()); EndTest(); break; default: @@ -1972,19 +1944,19 @@ class LayerTreeHostTestDeviceColorSpaceChange : public LayerTreeHostTest { break; case 2: EXPECT_FALSE(child_layer_->NeedsDisplayForTesting()); - layer_tree_host()->SetDeviceColorSpace(space2_); + layer_tree_host()->SetRasterColorSpace(space2_); EXPECT_TRUE(child_layer_->NeedsDisplayForTesting()); break; case 3: - // The redundant SetDeviceColorSpace should cause no commit and no + // The redundant SetRasterColorSpace should cause no commit and no // damage. Force a commit for the test to continue. - layer_tree_host()->SetDeviceColorSpace(space2_); + layer_tree_host()->SetRasterColorSpace(space2_); PostSetNeedsCommitToMainThread(); EXPECT_FALSE(child_layer_->NeedsDisplayForTesting()); break; case 4: EXPECT_FALSE(child_layer_->NeedsDisplayForTesting()); - layer_tree_host()->SetDeviceColorSpace(space1_); + layer_tree_host()->SetRasterColorSpace(space1_); EXPECT_TRUE(child_layer_->NeedsDisplayForTesting()); break; case 5: @@ -2009,11 +1981,12 @@ class LayerTreeHostTestDeviceColorSpaceChange : public LayerTreeHostTest { scoped_refptr<Layer> child_layer_; }; -SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestDeviceColorSpaceChange); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestRasterColorSpaceChange); -class LayerTreeHostTestSetNextCommitForcesRedraw : public LayerTreeHostTest { +class LayerTreeHostTestSetNeedsCommitWithForcedRedraw + : public LayerTreeHostTest { public: - LayerTreeHostTestSetNextCommitForcesRedraw() + LayerTreeHostTestSetNeedsCommitWithForcedRedraw() : num_draws_(0), bounds_(50, 50), invalid_rect_(10, 10, 20, 20) {} void BeginTest() override { @@ -2073,8 +2046,7 @@ class LayerTreeHostTestSetNextCommitForcesRedraw : public LayerTreeHostTest { break; case 2: // Should force full frame damage on the next commit - PostSetNextCommitForcesRedrawToMainThread(); - PostSetNeedsCommitToMainThread(); + PostSetNeedsCommitWithForcedRedrawToMainThread(); host_impl->BlockNotifyReadyToActivateForTesting(true); break; case 3: @@ -2098,7 +2070,8 @@ class LayerTreeHostTestSetNextCommitForcesRedraw : public LayerTreeHostTest { }; // This test blocks activation which is not supported for single thread mode. -MULTI_THREAD_BLOCKNOTIFY_TEST_F(LayerTreeHostTestSetNextCommitForcesRedraw); +MULTI_THREAD_BLOCKNOTIFY_TEST_F( + LayerTreeHostTestSetNeedsCommitWithForcedRedraw); // Tests that if a layer is not drawn because of some reason in the parent then // its damage is preserved until the next time it is drawn. @@ -2715,17 +2688,20 @@ SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestContinuousInvalidate); class LayerTreeHostTestDeferCommits : public LayerTreeHostTest { public: - LayerTreeHostTestDeferCommits() - : num_will_begin_impl_frame_(0), num_send_begin_main_frame_(0) {} + LayerTreeHostTestDeferCommits() = default; - void BeginTest() override { PostSetNeedsCommitToMainThread(); } + void BeginTest() override { + // Start with commits deferred. + PostSetDeferCommitsToMainThread(true); + PostSetNeedsCommitToMainThread(); + } void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl, const BeginFrameArgs& args) override { + // Impl frames happen while commits are deferred. num_will_begin_impl_frame_++; switch (num_will_begin_impl_frame_) { case 1: - break; case 2: case 3: case 4: @@ -2735,7 +2711,12 @@ class LayerTreeHostTestDeferCommits : public LayerTreeHostTest { PostSetNeedsRedrawToMainThread(); break; case 5: - PostSetDeferCommitsToMainThread(false); + MainThreadTaskRunner()->PostTask( + FROM_HERE, + // Unretained because the test should not end before allowing + // commits via this running. + base::BindOnce(&LayerTreeHostTestDeferCommits::AllowCommits, + base::Unretained(this))); break; default: // Sometimes |num_will_begin_impl_frame_| will be greater than 5 if the @@ -2745,32 +2726,128 @@ class LayerTreeHostTestDeferCommits : public LayerTreeHostTest { } void WillBeginMainFrame() override { + EXPECT_TRUE(allow_commits_); num_send_begin_main_frame_++; - switch (num_send_begin_main_frame_) { - case 1: - layer_tree_host()->SetDeferCommits(true); - break; - case 2: - EndTest(); - break; - default: - NOTREACHED(); - break; - } + EndTest(); + } + + void AllowCommits() { + allow_commits_ = true; + layer_tree_host()->SetDeferCommits(false); } void AfterTest() override { EXPECT_GE(num_will_begin_impl_frame_, 5); - EXPECT_EQ(2, num_send_begin_main_frame_); + EXPECT_EQ(1, num_send_begin_main_frame_); } private: - int num_will_begin_impl_frame_; - int num_send_begin_main_frame_; + bool allow_commits_ = false; + int num_will_begin_impl_frame_ = 0; + int num_send_begin_main_frame_ = 0; }; SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestDeferCommits); +// This verifies that we can abort a commit inside the main frame, and +// we don't leave any weird states around if we never allow the commit +// to happen. +class LayerTreeHostTestDeferCommitsInsideBeginMainFrame + : public LayerTreeHostTest { + public: + LayerTreeHostTestDeferCommitsInsideBeginMainFrame() = default; + + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void WillBeginMainFrame() override { + ++begin_main_frame_count_; + if (allow_commits_) + return; + + // This should prevent the commit from happening. + layer_tree_host()->SetDeferCommits(true); + // Wait to see if the commit happens. It's possible the deferred + // commit happens when it shouldn't but takes long enough that + // this passes. But it won't fail when it shouldn't. + MainThreadTaskRunner()->PostDelayedTask( + FROM_HERE, + // Unretained because the test doesn't end before this runs. + base::BindOnce(&LayerTreeTest::EndTest, base::Unretained(this)), + base::TimeDelta::FromMilliseconds(100)); + } + + void DidCommit() override { ++commit_count_; } + + void AfterTest() override { + EXPECT_EQ(0, commit_count_); + EXPECT_EQ(1, begin_main_frame_count_); + } + + private: + bool allow_commits_ = false; + int commit_count_ = 0; + int begin_main_frame_count_ = 0; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostTestDeferCommitsInsideBeginMainFrame); + +// This verifies that we can abort a commit inside the main frame, and +// we will finish the commit once it is allowed. +class LayerTreeHostTestDeferCommitsInsideBeginMainFrameWithCommitAfter + : public LayerTreeHostTest { + public: + LayerTreeHostTestDeferCommitsInsideBeginMainFrameWithCommitAfter() = default; + + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void WillBeginMainFrame() override { + ++begin_main_frame_count_; + if (allow_commits_) + return; + + // This should prevent the commit from happening. + layer_tree_host()->SetDeferCommits(true); + // Wait to see if the commit happens. It's possible the deferred + // commit happens when it shouldn't but takes long enough that + // this passes. But it won't fail when it shouldn't. + MainThreadTaskRunner()->PostDelayedTask( + FROM_HERE, + // Unretained because the test doesn't end before this runs. + base::BindOnce( + &LayerTreeHostTestDeferCommitsInsideBeginMainFrameWithCommitAfter:: + AllowCommits, + base::Unretained(this)), + base::TimeDelta::FromMilliseconds(100)); + } + + void AllowCommits() { + // Once we've waited and seen that commit did not happen, we + // allow commits and should see this one go through. + allow_commits_ = true; + layer_tree_host()->SetDeferCommits(false); + } + + void DidCommit() override { + ++commit_count_; + EXPECT_TRUE(allow_commits_); + EndTest(); + } + + void AfterTest() override { + EXPECT_EQ(1, commit_count_); + EXPECT_EQ(2, begin_main_frame_count_); + } + + private: + bool allow_commits_ = false; + int commit_count_ = 0; + int begin_main_frame_count_ = 0; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostTestDeferCommitsInsideBeginMainFrameWithCommitAfter); + class LayerTreeHostTestCompositeImmediatelyStateTransitions : public LayerTreeHostTest { public: @@ -2944,7 +3021,7 @@ class LayerTreeHostTestBeginFrameNotificationShutdownWhileEnabled // once we return. End test while it's enabled. ImplThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostTest::EndTest, base::Unretained(this))); + base::BindOnce(&LayerTreeHostTest::EndTest, base::Unretained(this))); } void AfterTest() override {} @@ -3065,9 +3142,9 @@ class LayerTreeHostTestAbortedCommitDoesntStallSynchronousCompositor // surface. But it needs to be done on a new stack frame. bool resourceless_software_draw = false; ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&OnDrawCompositorFrameSink::OnDraw, - base::Unretained(compositor_frame_sink_), - resourceless_software_draw)); + FROM_HERE, base::BindOnce(&OnDrawCompositorFrameSink::OnDraw, + base::Unretained(compositor_frame_sink_), + resourceless_software_draw)); } } @@ -4544,8 +4621,7 @@ class TestSwapPromise : public SwapPromise { class PinnedLayerTreeSwapPromise : public LayerTreeHostTest { protected: void BeginTest() override { - PostSetNextCommitForcesRedrawToMainThread(); - PostSetNeedsCommitToMainThread(); + layer_tree_host()->SetNeedsCommitWithForcedRedraw(); } void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override { @@ -4700,8 +4776,9 @@ class LayerTreeHostTestKeepSwapPromise : public LayerTreeHostTest { void DidCommit() override { MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&LayerTreeHostTestKeepSwapPromise::ChangeFrame, - base::Unretained(this))); + FROM_HERE, + base::BindOnce(&LayerTreeHostTestKeepSwapPromise::ChangeFrame, + base::Unretained(this))); } void ChangeFrame() { @@ -4805,8 +4882,8 @@ class LayerTreeHostTestKeepSwapPromiseMFBA : public LayerTreeHostTest { void DidCommit() override { MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostTestKeepSwapPromiseMFBA::ChangeFrame, - base::Unretained(this))); + base::BindOnce(&LayerTreeHostTestKeepSwapPromiseMFBA::ChangeFrame, + base::Unretained(this))); } void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* host_impl, @@ -4905,9 +4982,10 @@ class LayerTreeHostTestBreakSwapPromiseForVisibility void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl, const BeginFrameArgs& args) override { MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&LayerTreeHostTestBreakSwapPromiseForVisibility:: - SetVisibleFalseAndQueueSwapPromise, - base::Unretained(this))); + FROM_HERE, + base::BindOnce(&LayerTreeHostTestBreakSwapPromiseForVisibility:: + SetVisibleFalseAndQueueSwapPromise, + base::Unretained(this))); } void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* host_impl, @@ -5916,8 +5994,9 @@ class LayerTreeHostTestCrispUpAfterPinchEnds : public LayerTreeHostTest { return; posted_ = true; ImplThreadTaskRunner()->PostDelayedTask( - FROM_HERE, base::Bind(&LayerTreeHostTestCrispUpAfterPinchEnds::Next, - base::Unretained(this), host_impl), + FROM_HERE, + base::BindOnce(&LayerTreeHostTestCrispUpAfterPinchEnds::Next, + base::Unretained(this), host_impl), // Use a delay to allow raster/upload to happen in between frames. This // should cause flakiness if we fail to block raster/upload when // desired. @@ -5957,14 +6036,15 @@ class LayerTreeHostTestCrispUpAfterPinchEnds : public LayerTreeHostTest { // On frame 3, we will have a lower res tile complete for the pinch-out // gesture even though it's not displayed. We wait for it here to prevent // flakiness. - EXPECT_EQ(0.75f, tile->contents_scale()); + EXPECT_EQ(gfx::AxisTransform2d(0.75f, gfx::Vector2dF()), + tile->raster_transform()); PostNextAfterDraw(host_impl); } // On frame_ == 4, we are preventing texture uploads from completing, // so this verifies they are not completing before frame_ == 5. // Flaky failures here indicate we're failing to prevent uploads from // completing. - EXPECT_NE(4, frame_) << tile->contents_scale(); + EXPECT_NE(4, frame_) << tile->contents_scale_key(); } void AfterTest() override {} @@ -6387,9 +6467,10 @@ class LayerTreeHostTestNoTasksBetweenWillAndDidCommit void WillCommit() override { MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&LayerTreeHostTestNoTasksBetweenWillAndDidCommit:: - EndTestShouldRunAfterDidCommit, - base::Unretained(this))); + FROM_HERE, + base::BindOnce(&LayerTreeHostTestNoTasksBetweenWillAndDidCommit:: + EndTestShouldRunAfterDidCommit, + base::Unretained(this))); } void EndTestShouldRunAfterDidCommit() { @@ -6465,6 +6546,104 @@ class LayerTreeHostTestUpdateCopyRequests : public LayerTreeHostTest { SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestUpdateCopyRequests); +class LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin + : public LayerTreeTest { + protected: + void SetupTree() override { + // The masked layer has bounds 50x50, but it has a child that causes + // the surface bounds to be larger. It also has a parent that clips the + // masked layer and its surface. + + scoped_refptr<Layer> root = Layer::Create(); + + scoped_refptr<FakePictureLayer> content_layer = + FakePictureLayer::Create(&client_); + + std::unique_ptr<RecordingSource> recording_source = + FakeRecordingSource::CreateFilledRecordingSource(gfx::Size(100, 100)); + PaintFlags paint1, paint2; + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 0, 100, 90), paint1); + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 90, 100, 10), paint2); + client_.set_fill_with_nonsolid_color(true); + static_cast<FakeRecordingSource*>(recording_source.get())->Rerecord(); + + scoped_refptr<FakePictureLayer> mask_layer = + FakePictureLayer::CreateWithRecordingSource( + &client_, std::move(recording_source)); + content_layer->SetMaskLayer(mask_layer.get()); + + gfx::Size root_size(100, 100); + root->SetBounds(root_size); + + gfx::Size layer_size(100, 100); + content_layer->SetBounds(layer_size); + + gfx::Size mask_size(100, 100); + mask_layer->SetBounds(mask_size); + mask_layer->SetLayerMaskType(Layer::LayerMaskType::MULTI_TEXTURE_MASK); + mask_layer_id_ = mask_layer->id(); + + layer_tree_host()->SetRootLayer(root); + LayerTreeTest::SetupTree(); + scoped_refptr<Layer> outer_viewport_scroll_layer = Layer::Create(); + outer_viewport_scroll_layer->SetBounds(layer_size); + CreateVirtualViewportLayers(root.get(), outer_viewport_scroll_layer, + gfx::Size(50, 50), gfx::Size(50, 50), + layer_tree_host()); + outer_viewport_scroll_layer->scroll_clip_layer()->SetMasksToBounds(true); + outer_viewport_scroll_layer->AddChild(content_layer); + + client_.set_bounds(root->bounds()); + outer_viewport_scroll_layer->SetScrollOffset(gfx::ScrollOffset(50, 50)); + } + + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, + LayerTreeHostImpl::FrameData* frame_data, + DrawResult draw_result) override { + EXPECT_EQ(2u, frame_data->render_passes.size()); + RenderPass* root_pass = frame_data->render_passes.back().get(); + EXPECT_EQ(2u, root_pass->quad_list.size()); + + // There's a solid color quad under everything. + EXPECT_EQ(DrawQuad::SOLID_COLOR, root_pass->quad_list.back()->material); + + EXPECT_EQ(DrawQuad::RENDER_PASS, root_pass->quad_list.front()->material); + const RenderPassDrawQuad* render_pass_quad = + RenderPassDrawQuad::MaterialCast(root_pass->quad_list.front()); + EXPECT_EQ(gfx::Rect(50, 50, 50, 50).ToString(), + render_pass_quad->rect.ToString()); + if (host_impl->settings().enable_mask_tiling) { + PictureLayerImpl* mask_layer_impl = static_cast<PictureLayerImpl*>( + host_impl->active_tree()->LayerById(mask_layer_id_)); + gfx::SizeF texture_size( + mask_layer_impl->CalculateTileSize(mask_layer_impl->bounds())); + EXPECT_EQ( + gfx::RectF(50.f / texture_size.width(), 50.f / texture_size.height(), + 50.f / texture_size.width(), 50.f / texture_size.height()) + .ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } else { + EXPECT_EQ(gfx::ScaleRect(gfx::RectF(50.f, 50.f, 50.f, 50.f), 1.f / 100.f) + .ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } + EndTest(); + return draw_result; + } + + void AfterTest() override {} + + int mask_layer_id_; + FakeContentLayerClient client_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin); + class LayerTreeTestMaskLayerForSurfaceWithClippedLayer : public LayerTreeTest { protected: void SetupTree() override { @@ -6485,8 +6664,19 @@ class LayerTreeTestMaskLayerForSurfaceWithClippedLayer : public LayerTreeTest { FakePictureLayer::Create(&client_); content_layer->AddChild(content_child_layer); + std::unique_ptr<RecordingSource> recording_source = + FakeRecordingSource::CreateFilledRecordingSource(gfx::Size(100, 100)); + PaintFlags paint1, paint2; + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 0, 100, 90), paint1); + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 90, 100, 10), paint2); + client_.set_fill_with_nonsolid_color(true); + static_cast<FakeRecordingSource*>(recording_source.get())->Rerecord(); + scoped_refptr<FakePictureLayer> mask_layer = - FakePictureLayer::Create(&client_); + FakePictureLayer::CreateWithRecordingSource( + &client_, std::move(recording_source)); content_layer->SetMaskLayer(mask_layer.get()); gfx::Size root_size(100, 100); @@ -6510,6 +6700,7 @@ class LayerTreeTestMaskLayerForSurfaceWithClippedLayer : public LayerTreeTest { gfx::Size mask_size(100, 100); mask_layer->SetBounds(mask_size); mask_layer->SetLayerMaskType(Layer::LayerMaskType::MULTI_TEXTURE_MASK); + mask_layer_id_ = mask_layer->id(); layer_tree_host()->SetRootLayer(root); LayerTreeTest::SetupTree(); @@ -6538,15 +6729,28 @@ class LayerTreeTestMaskLayerForSurfaceWithClippedLayer : public LayerTreeTest { // coords in the mask are scaled by 10/50 and 20/50. // The surface is clipped to (20,10) so the mask texture coords are offset // by 20/50 and 10/50 - EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f), 1.f / 50.f) - .ToString(), - render_pass_quad->mask_uv_rect.ToString()); + if (host_impl->settings().enable_mask_tiling) { + PictureLayerImpl* mask_layer_impl = static_cast<PictureLayerImpl*>( + host_impl->active_tree()->LayerById(mask_layer_id_)); + gfx::SizeF texture_size( + mask_layer_impl->CalculateTileSize(mask_layer_impl->bounds())); + EXPECT_EQ( + gfx::RectF(20.f / texture_size.width(), 10.f / texture_size.height(), + 10.f / texture_size.width(), 20.f / texture_size.height()) + .ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } else { + EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f), 1.f / 50.f) + .ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } EndTest(); return draw_result; } void AfterTest() override {} + int mask_layer_id_; FakeContentLayerClient client_; }; @@ -6576,8 +6780,19 @@ class LayerTreeTestMaskLayerWithScaling : public LayerTreeTest { FakePictureLayer::Create(&client_); scaling_layer->AddChild(content_layer); + std::unique_ptr<RecordingSource> recording_source = + FakeRecordingSource::CreateFilledRecordingSource(gfx::Size(100, 100)); + PaintFlags paint1, paint2; + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 0, 100, 10), paint1); + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 10, 100, 90), paint2); + client_.set_fill_with_nonsolid_color(true); + static_cast<FakeRecordingSource*>(recording_source.get())->Rerecord(); + scoped_refptr<FakePictureLayer> mask_layer = - FakePictureLayer::Create(&client_); + FakePictureLayer::CreateWithRecordingSource( + &client_, std::move(recording_source)); content_layer->SetMaskLayer(mask_layer.get()); gfx::Size root_size(100, 100); @@ -6620,16 +6835,28 @@ class LayerTreeTestMaskLayerWithScaling : public LayerTreeTest { // mask, that should fully map onto the quad. EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), render_pass_quad->rect.ToString()); - EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), - render_pass_quad->mask_uv_rect.ToString()); + if (host_impl->settings().enable_mask_tiling) { + EXPECT_EQ( + gfx::RectF(0.f, 0.f, 100.f / 128.f, 100.f / 128.f).ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } else { + EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } break; case 1: // Applying a DSF should change the render surface size, but won't // affect which part of the mask is used. EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(), render_pass_quad->rect.ToString()); - EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), - render_pass_quad->mask_uv_rect.ToString()); + if (host_impl->settings().enable_mask_tiling) { + EXPECT_EQ( + gfx::RectF(0.f, 0.f, 100.f / 128.f, 100.f / 128.f).ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } else { + EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } EndTest(); break; } @@ -6665,8 +6892,19 @@ class LayerTreeTestMaskLayerWithDifferentBounds : public LayerTreeTest { FakePictureLayer::Create(&client_); root->AddChild(content_layer); + std::unique_ptr<RecordingSource> recording_source = + FakeRecordingSource::CreateFilledRecordingSource(gfx::Size(100, 100)); + PaintFlags paint1, paint2; + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 0, 100, 90), paint1); + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 90, 100, 10), paint2); + client_.set_fill_with_nonsolid_color(true); + static_cast<FakeRecordingSource*>(recording_source.get())->Rerecord(); + scoped_refptr<FakePictureLayer> mask_layer = - FakePictureLayer::Create(&client_); + FakePictureLayer::CreateWithRecordingSource( + &client_, std::move(recording_source)); content_layer->SetMaskLayer(mask_layer.get()); gfx::Size root_size(100, 100); @@ -6704,16 +6942,26 @@ class LayerTreeTestMaskLayerWithDifferentBounds : public LayerTreeTest { // Check that the mask fills the surface. EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(), render_pass_quad->rect.ToString()); - EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), - render_pass_quad->mask_uv_rect.ToString()); + if (host_impl->settings().enable_mask_tiling) { + EXPECT_EQ(gfx::RectF(0.f, 0.f, 50.f / 128.f, 50.f / 128.f).ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } else { + EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } break; case 1: // Applying a DSF should change the render surface size, but won't // affect which part of the mask is used. EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), render_pass_quad->rect.ToString()); - EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), - render_pass_quad->mask_uv_rect.ToString()); + if (host_impl->settings().enable_mask_tiling) { + EXPECT_EQ(gfx::RectF(0.f, 0.f, 50.f / 128.f, 50.f / 128.f).ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } else { + EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } EndTest(); break; } @@ -6851,9 +7099,39 @@ class LayerTreeHostTestPaintedDeviceScaleFactor : public LayerTreeHostTest { void AfterTest() override {} }; - SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestPaintedDeviceScaleFactor); +// Makes sure that LocalSurfaceId is propagated to the CompositorFrameSink. +class LayerTreeHostTestLocalSurfaceId : public LayerTreeHostTest { + protected: + void BeginTest() override { + expected_local_surface_id_ = allocator_.GenerateId(); + PostSetLocalSurfaceIdToMainThread(expected_local_surface_id_); + } + + DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, + LayerTreeHostImpl::FrameData* frame_data, + DrawResult draw_result) override { + EXPECT_EQ(DRAW_SUCCESS, draw_result); + EXPECT_EQ(expected_local_surface_id_, + host_impl->active_tree()->local_surface_id()); + return draw_result; + } + + void DisplayReceivedLocalSurfaceIdOnThread( + const LocalSurfaceId& local_surface_id) override { + EXPECT_EQ(expected_local_surface_id_, local_surface_id); + EndTest(); + } + + void AfterTest() override {} + + LocalSurfaceId expected_local_surface_id_; + LocalSurfaceIdAllocator allocator_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestLocalSurfaceId); + // The GPU image decode controller hands images off to Skia for rasterization. // When used with large images, the images in question could be deleted before // Skia was done with them, causing a crash. This test performs an end-to-end @@ -6870,8 +7148,9 @@ class GpuRasterizationSucceedsWithLargeImage : public LayerTreeHostTest { void InitializeSettings(LayerTreeSettings* settings) override { settings->gpu_rasterization_forced = true; - /// Set to 0 to force at-raster GPU image decode. - settings->gpu_decoded_image_budget_bytes = 0; + // Set to 0 to force at-raster GPU image decode. + settings->decoded_image_working_set_budget_bytes = 0; + settings->decoded_image_cache_budget_bytes = 0; } void SetupTree() override { @@ -7037,5 +7316,191 @@ class LayerTreeHostTestContentSourceId : public LayerTreeHostTest { SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestContentSourceId); +class LayerTreeHostTestBeginFrameSequenceNumbers : public LayerTreeHostTest { + protected: + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl, + const BeginFrameArgs& args) override { + // First BeginFrame will block activation, second one unblocks. + impl->BlockNotifyReadyToActivateForTesting(false); + + EXPECT_TRUE(args.IsValid()); + current_begin_frame_args_ = args; + } + + void BeginMainFrame(const BeginFrameArgs& args) override { + EXPECT_TRUE(args.IsValid()); + if (!current_begin_main_frame_args_.IsValid()) + current_begin_main_frame_args_ = args; + } + + void BeginCommitOnThread(LayerTreeHostImpl* impl) override { + current_begin_main_frame_args_on_impl_ = current_begin_main_frame_args_; + // Request another subsequent commit. That way, the first commit's + // latest_confirmed_sequence_number should stay at the first BeginFrame's + // sequence number. + PostSetNeedsCommitToMainThread(); + } + + void WillCommitCompleteOnThread(LayerTreeHostImpl* impl) override { + // Defer current commit's activation until second BeginFrame. + impl->BlockNotifyReadyToActivateForTesting(true); + } + + DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* impl, + LayerTreeHostImpl::FrameData* frame_data, + DrawResult draw_result) override { + // We should only draw in second BeginFrame. + EXPECT_TRUE(current_begin_main_frame_args_on_impl_.IsValid()); + EXPECT_LT(current_begin_main_frame_args_on_impl_.sequence_number, + current_begin_frame_args_.sequence_number); + frame_data_ = frame_data; + return draw_result; + } + + void DisplayReceivedCompositorFrameOnThread( + const CompositorFrame& frame) override { + if (compositor_frame_submitted_) + return; + compositor_frame_submitted_ = true; + + EXPECT_EQ(BeginFrameAck( + current_begin_frame_args_.source_id, + current_begin_frame_args_.sequence_number, + current_begin_main_frame_args_on_impl_.sequence_number, true), + frame.metadata.begin_frame_ack); + } + + void DrawLayersOnThread(LayerTreeHostImpl* impl) override { + if (layers_drawn_) + return; + layers_drawn_ = true; + + EXPECT_TRUE(frame_data_); + EXPECT_TRUE(compositor_frame_submitted_); + EXPECT_EQ(BeginFrameAck( + current_begin_frame_args_.source_id, + current_begin_frame_args_.sequence_number, + current_begin_main_frame_args_on_impl_.sequence_number, true), + frame_data_->begin_frame_ack); + EndTest(); + } + + void AfterTest() override { EXPECT_TRUE(layers_drawn_); } + + private: + bool compositor_frame_submitted_ = false; + bool layers_drawn_ = false; + BeginFrameArgs current_begin_frame_args_; + BeginFrameArgs current_begin_main_frame_args_; + BeginFrameArgs current_begin_main_frame_args_on_impl_; + LayerTreeHostImpl::FrameData* frame_data_; +}; + +MULTI_THREAD_BLOCKNOTIFY_TEST_F(LayerTreeHostTestBeginFrameSequenceNumbers); + +class LayerTreeHostTestQueueImageDecode : public LayerTreeHostTest { + protected: + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void WillBeginMainFrame() override { + if (!first_) + return; + first_ = false; + + sk_sp<const SkImage> image = CreateDiscardableImage(gfx::Size(10, 10)); + auto callback = + base::Bind(&LayerTreeHostTestQueueImageDecode::ImageDecodeFinished, + base::Unretained(this)); + // Schedule the decode twice for the same image. + layer_tree_host()->QueueImageDecode(image, callback); + layer_tree_host()->QueueImageDecode(image, callback); + } + + void ImageDecodeFinished(bool decode_succeeded) { + EXPECT_TRUE(decode_succeeded); + ++finished_decode_count_; + EXPECT_LE(finished_decode_count_, 2); + if (finished_decode_count_ == 2) + EndTest(); + } + + void AfterTest() override {} + + private: + bool first_ = true; + int finished_decode_count_ = 0; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestQueueImageDecode); + +class LayerTreeHostTestQueueImageDecodeNonLazy : public LayerTreeHostTest { + protected: + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void WillBeginMainFrame() override { + if (!first_) + return; + first_ = false; + + bitmap_.allocN32Pixels(10, 10); + sk_sp<const SkImage> image = SkImage::MakeFromBitmap(bitmap_); + auto callback = base::Bind( + &LayerTreeHostTestQueueImageDecodeNonLazy::ImageDecodeFinished, + base::Unretained(this)); + layer_tree_host()->QueueImageDecode(image, callback); + } + + void ImageDecodeFinished(bool decode_succeeded) { + EXPECT_TRUE(decode_succeeded); + EndTest(); + } + + void AfterTest() override {} + + private: + bool first_ = true; + SkBitmap bitmap_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestQueueImageDecodeNonLazy); + +class LayerTreeHostTestHudLayerWithLayerLists : public LayerTreeHostTest { + public: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->initial_debug_state.show_paint_rects = true; + settings->use_layer_lists = true; + } + + void SetupTree() override { + LayerTreeHostTest::SetupTree(); + + // Build the property trees for the root layer. + layer_tree_host()->BuildPropertyTreesForTesting(); + + // The HUD layer should not have been setup by the property tree building. + DCHECK_EQ(layer_tree_host()->hud_layer(), nullptr); + } + + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override { EndTest(); } + + void DidCommit() override { + auto* hud = layer_tree_host()->hud_layer(); + DCHECK(hud); + auto* root_layer = layer_tree_host()->root_layer(); + DCHECK_EQ(hud->transform_tree_index(), root_layer->transform_tree_index()); + DCHECK_EQ(hud->clip_tree_index(), root_layer->clip_tree_index()); + DCHECK_EQ(hud->effect_tree_index(), root_layer->effect_tree_index()); + DCHECK_EQ(hud->scroll_tree_index(), root_layer->scroll_tree_index()); + } + + void AfterTest() override {} +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestHudLayerWithLayerLists); + } // namespace } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_unittest_animation.cc b/chromium/cc/trees/layer_tree_host_unittest_animation.cc index f77964271d5..f25dc93e40f 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_animation.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_animation.cc @@ -573,7 +573,7 @@ class LayerTreeHostAnimationTestForceRedraw } void UpdateLayerTreeHost() override { - layer_tree_host()->SetNextCommitForcesRedraw(); + layer_tree_host()->SetNeedsCommitWithForcedRedraw(); } void DrawLayersOnThread(LayerTreeHostImpl* impl) override { @@ -1355,9 +1355,9 @@ class LayerTreeHostAnimationTestAddAnimationAfterAnimating if (!TestEnded()) { ImplThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostAnimationTestAddAnimationAfterAnimating:: - CheckAnimations, - base::Unretained(this), host_impl)); + base::BindOnce(&LayerTreeHostAnimationTestAddAnimationAfterAnimating:: + CheckAnimations, + base::Unretained(this), host_impl)); } } diff --git a/chromium/cc/trees/layer_tree_host_unittest_checkerimaging.cc b/chromium/cc/trees/layer_tree_host_unittest_checkerimaging.cc index 580fa3e8363..37b3e1b006f 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_checkerimaging.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_checkerimaging.cc @@ -51,8 +51,8 @@ class LayerTreeHostCheckerImagingTest : public LayerTreeTest { CompletionEvent completion_event; image_worker_task_runner()->PostTask( FROM_HERE, - base::Bind([](CompletionEvent* event) { event->Signal(); }, - base::Unretained(&completion_event))); + base::BindOnce([](CompletionEvent* event) { event->Signal(); }, + base::Unretained(&completion_event))); completion_event.Wait(); } diff --git a/chromium/cc/trees/layer_tree_host_unittest_context.cc b/chromium/cc/trees/layer_tree_host_unittest_context.cc index f59b200beda..3c7351f3ff4 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_context.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_context.cc @@ -6,6 +6,7 @@ #include <stdint.h> #include "base/memory/ptr_util.h" +#include "cc/base/filter_operations.h" #include "cc/layers/heads_up_display_layer.h" #include "cc/layers/layer_impl.h" #include "cc/layers/painted_scrollbar_layer.h" @@ -14,7 +15,6 @@ #include "cc/layers/texture_layer_impl.h" #include "cc/layers/video_layer.h" #include "cc/layers/video_layer_impl.h" -#include "cc/output/filter_operations.h" #include "cc/paint/paint_flags.h" #include "cc/resources/single_release_callback.h" #include "cc/resources/ui_resource_manager.h" @@ -181,9 +181,10 @@ class LayerTreeHostContextTestLostContextSucceeds void RequestNewCompositorFrameSink() override { if (async_compositor_frame_sink_creation_) { MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&LayerTreeHostContextTestLostContextSucceeds:: - AsyncRequestNewCompositorFrameSink, - base::Unretained(this))); + FROM_HERE, + base::BindOnce(&LayerTreeHostContextTestLostContextSucceeds:: + AsyncRequestNewCompositorFrameSink, + base::Unretained(this))); } else { AsyncRequestNewCompositorFrameSink(); } @@ -408,8 +409,9 @@ class LayerTreeHostClientTakeAwayCompositorFrameSink CHECK(surface); MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostClientTakeAwayCompositorFrameSink::MakeVisible, - base::Unretained(this))); + base::BindOnce( + &LayerTreeHostClientTakeAwayCompositorFrameSink::MakeVisible, + base::Unretained(this))); } void DidInitializeCompositorFrameSink() override { @@ -417,9 +419,9 @@ class LayerTreeHostClientTakeAwayCompositorFrameSink if (setos_counter_ == 1) { MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostClientTakeAwayCompositorFrameSink:: - HideAndReleaseCompositorFrameSink, - base::Unretained(this))); + base::BindOnce(&LayerTreeHostClientTakeAwayCompositorFrameSink:: + HideAndReleaseCompositorFrameSink, + base::Unretained(this))); } else { EndTest(); } @@ -539,7 +541,7 @@ class LayerTreeHostContextTestCommitAfterDelayedCompositorFrameSink void RequestNewCompositorFrameSink() override { MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind( + base::BindOnce( &LayerTreeHostContextTestCommitAfterDelayedCompositorFrameSink:: CreateAndSetCompositorFrameSink, base::Unretained(this))); @@ -708,9 +710,9 @@ class LayerTreeHostContextTestLostContextAndEvictTextures if (HasImplThread()) { ImplThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostContextTestLostContextAndEvictTextures:: - EvictTexturesOnImplThread, - base::Unretained(this))); + base::BindOnce(&LayerTreeHostContextTestLostContextAndEvictTextures:: + EvictTexturesOnImplThread, + base::Unretained(this))); } else { DebugScopedSetImplThread impl(task_runner_provider()); EvictTexturesOnImplThread(); @@ -1149,15 +1151,15 @@ class UIResourceLostTest : public LayerTreeHostContextTest { void PostStepCompleteToMainThread() { task_runner_provider()->MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&UIResourceLostTest::StepCompleteOnMainThreadInternal, - base::Unretained(this), time_step_)); + base::BindOnce(&UIResourceLostTest::StepCompleteOnMainThreadInternal, + base::Unretained(this), time_step_)); } void PostLoseContextToImplThread() { EXPECT_TRUE(layer_tree_host()->GetTaskRunnerProvider()->IsMainThread()); ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&LayerTreeHostContextTest::LoseContext, - base::Unretained(this))); + FROM_HERE, base::BindOnce(&LayerTreeHostContextTest::LoseContext, + base::Unretained(this))); } protected: @@ -1563,9 +1565,9 @@ class LayerTreeHostContextTestLoseAfterSendingBeginMainFrame // Meanwhile, lose the context while we are in defer commits. ImplThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostContextTestLoseAfterSendingBeginMainFrame:: - LoseContextOnImplThread, - base::Unretained(this))); + base::BindOnce(&LayerTreeHostContextTestLoseAfterSendingBeginMainFrame:: + LoseContextOnImplThread, + base::Unretained(this))); // After the first frame, we will lose the context and then not start // allowing commits until that happens. The 2nd frame should not happen diff --git a/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc index 201c30f9fab..7805b3d76cf 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc @@ -8,7 +8,7 @@ #include "base/memory/ptr_util.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" -#include "cc/layers/layer_iterator.h" +#include "cc/layers/effect_tree_layer_list_iterator.h" #include "cc/output/copy_output_request.h" #include "cc/output/copy_output_result.h" #include "cc/output/direct_renderer.h" @@ -55,8 +55,8 @@ class LayerTreeHostCopyRequestTestMultipleRequests void WaitForCallback() { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::NextStep, - base::Unretained(this))); + base::BindOnce(&LayerTreeHostCopyRequestTestMultipleRequests::NextStep, + base::Unretained(this))); } void NextStep() { @@ -597,6 +597,10 @@ SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostCopyRequestTestClippedOut); class LayerTreeHostCopyRequestTestScaledLayer : public LayerTreeHostCopyRequestTest { protected: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->layer_transforms_should_scale_layer_contents = true; + } + void SetupTree() override { root_ = Layer::Create(); root_->SetBounds(gfx::Size(20, 20)); @@ -780,9 +784,9 @@ class LayerTreeHostCopyRequestTestDeleteTexture result_ = nullptr; ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&LayerTreeHostCopyRequestTestDeleteTexture:: - CheckNumTexturesAfterReadbackDestroyed, - base::Unretained(this))); + FROM_HERE, base::BindOnce(&LayerTreeHostCopyRequestTestDeleteTexture:: + CheckNumTexturesAfterReadbackDestroyed, + base::Unretained(this))); } void CheckNumTexturesAfterReadbackDestroyed() { @@ -809,7 +813,7 @@ class LayerTreeHostCopyRequestTestDeleteTexture // Request a copy of the layer. This will use another texture. MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind( + base::BindOnce( &LayerTreeHostCopyRequestTestDeleteTexture::InsertCopyRequest, base::Unretained(this))); break; @@ -828,9 +832,10 @@ class LayerTreeHostCopyRequestTestDeleteTexture // to the compositor. Then check the resulting number of allocated // textures. MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&LayerTreeHostCopyRequestTestDeleteTexture:: - DestroyCopyResultAndCheckNumTextures, - base::Unretained(this))); + FROM_HERE, + base::BindOnce(&LayerTreeHostCopyRequestTestDeleteTexture:: + DestroyCopyResultAndCheckNumTextures, + base::Unretained(this))); break; } } @@ -880,6 +885,11 @@ class LayerTreeHostCopyRequestTestCountTextures copy_layer_ = FakePictureLayer::Create(©_client_); copy_layer_->SetBounds(gfx::Size(10, 10)); copy_client_.set_bounds(copy_layer_->bounds()); + PaintFlags flags; + flags.setColor(SK_ColorRED); + // Ensure the layer isn't completely transparent so the RenderPass isn't + // optimized away. + copy_client_.add_draw_rect(gfx::Rect(0, 0, 10, 10), flags); // Doing a copy makes the layer have a render surface which can cause // texture allocations. So get those allocations out of the way in the // first frame by forcing it to have a render surface. @@ -927,8 +937,9 @@ class LayerTreeHostCopyRequestTestCountTextures // readback. MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostCopyRequestTestCountTextures::DoEndTest, - base::Unretained(this))); + base::BindOnce( + &LayerTreeHostCopyRequestTestCountTextures::DoEndTest, + base::Unretained(this))); break; } } @@ -1065,8 +1076,9 @@ class LayerTreeHostCopyRequestTestDestroyBeforeCopy void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override { MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostCopyRequestTestDestroyBeforeCopy::DidActivate, - base::Unretained(this))); + base::BindOnce( + &LayerTreeHostCopyRequestTestDestroyBeforeCopy::DidActivate, + base::Unretained(this))); } void DidActivate() { @@ -1142,8 +1154,9 @@ class LayerTreeHostCopyRequestTestShutdownBeforeCopy void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override { MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostCopyRequestTestShutdownBeforeCopy::DidActivate, - base::Unretained(this))); + base::BindOnce( + &LayerTreeHostCopyRequestTestShutdownBeforeCopy::DidActivate, + base::Unretained(this))); } void DidActivate() { @@ -1168,8 +1181,9 @@ class LayerTreeHostCopyRequestTestShutdownBeforeCopy // the main thread. MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostCopyRequestTestShutdownBeforeCopy::EndTest, - base::Unretained(this))); + base::BindOnce( + &LayerTreeHostCopyRequestTestShutdownBeforeCopy::EndTest, + base::Unretained(this))); break; } } @@ -1227,14 +1241,12 @@ class LayerTreeHostCopyRequestTestMultipleDrawsHiddenCopyRequest bool saw_root = false; bool saw_child = false; - for (LayerIterator it = - LayerIterator::Begin(frame_data->render_surface_layer_list); - it != LayerIterator::End(frame_data->render_surface_layer_list); - ++it) { - if (it.represents_itself()) { - if (*it == root) + for (EffectTreeLayerListIterator it(host_impl->active_tree()); + it.state() != EffectTreeLayerListIterator::State::END; ++it) { + if (it.state() == EffectTreeLayerListIterator::State::LAYER) { + if (it.current_layer() == root) saw_root = true; - else if (*it == child) + else if (it.current_layer() == child) saw_child = true; else NOTREACHED(); @@ -1268,7 +1280,7 @@ class LayerTreeHostCopyRequestTestMultipleDrawsHiddenCopyRequest // to the main thread. MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind( + base::BindOnce( &LayerTreeHostCopyRequestTestMultipleDrawsHiddenCopyRequest:: TryEndTest, base::Unretained(this), WhatHappened::DRAW)); diff --git a/chromium/cc/trees/layer_tree_host_unittest_damage.cc b/chromium/cc/trees/layer_tree_host_unittest_damage.cc index 5873138ce5f..73d71a2d6dd 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_damage.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_damage.cc @@ -354,7 +354,6 @@ class LayerTreeHostScrollbarDamageTest : public LayerTreeHostDamageTest { FakePaintedScrollbarLayer::Create(false, true, content_layer_->id()); scrollbar_layer->SetPosition(gfx::PointF(300.f, 300.f)); scrollbar_layer->SetBounds(gfx::Size(10, 100)); - scrollbar_layer->ToScrollbarLayer()->SetScrollLayer(content_layer_->id()); root_layer->AddChild(scrollbar_layer); gfx::RectF content_rect(content_layer_->position(), @@ -421,9 +420,10 @@ class LayerTreeHostDamageTestScrollbarDoesDamage // Test that modifying the position of the content layer (not // scrolling) won't damage the scrollbar. MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&LayerTreeHostDamageTestScrollbarDoesDamage:: - ModifyContentLayerPosition, - base::Unretained(this))); + FROM_HERE, + base::BindOnce(&LayerTreeHostDamageTestScrollbarDoesDamage:: + ModifyContentLayerPosition, + base::Unretained(this))); break; case 2: scroll_layer->ScrollBy(gfx::Vector2dF(10.f, 10.f)); @@ -433,7 +433,7 @@ class LayerTreeHostDamageTestScrollbarDoesDamage // We will resize the content layer, on the main thread. MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind( + base::BindOnce( &LayerTreeHostDamageTestScrollbarDoesDamage::ResizeScrollLayer, base::Unretained(this))); break; diff --git a/chromium/cc/trees/layer_tree_host_unittest_picture.cc b/chromium/cc/trees/layer_tree_host_unittest_picture.cc index cbdd64173b9..55eabcb1eb7 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_picture.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_picture.cc @@ -250,11 +250,8 @@ class LayerTreeHostPictureTestChangeLiveTilesRectWithRecycleTree // Make the bottom of the layer visible. gfx::Transform transform; transform.Translate(0.f, -100000.f + 100.f); - impl->active_tree() - ->property_trees() - ->transform_tree.OnTransformAnimated( - transform, picture_impl->transform_tree_index(), - impl->active_tree()); + impl->active_tree()->SetTransformMutated(picture_impl->element_id(), + transform); impl->SetNeedsRedraw(); break; } @@ -265,11 +262,8 @@ class LayerTreeHostPictureTestChangeLiveTilesRectWithRecycleTree EXPECT_FALSE(tiling->TileAt(0, 0)); // Make the top of the layer visible again. - impl->active_tree() - ->property_trees() - ->transform_tree.OnTransformAnimated( - gfx::Transform(), picture_impl->transform_tree_index(), - impl->active_tree()); + impl->active_tree()->SetTransformMutated(picture_impl->element_id(), + gfx::Transform()); impl->SetNeedsRedraw(); break; } @@ -458,19 +452,22 @@ class LayerTreeHostPictureTestRSLLMembershipWithScale case 0: // On 1st commit the pending layer has tilings. ASSERT_EQ(1u, picture->tilings()->num_tilings()); - EXPECT_EQ(1.f, picture->tilings()->tiling_at(0)->contents_scale()); + EXPECT_EQ(gfx::AxisTransform2d(), + picture->tilings()->tiling_at(0)->raster_transform()); break; case 1: // On 2nd commit, the pending layer is transparent, so has a stale // value. ASSERT_EQ(1u, picture->tilings()->num_tilings()); - EXPECT_EQ(1.f, picture->tilings()->tiling_at(0)->contents_scale()); + EXPECT_EQ(gfx::AxisTransform2d(), + picture->tilings()->tiling_at(0)->raster_transform()); break; case 2: // On 3rd commit, the pending layer is visible again, so has tilings and // is updated for the pinch. ASSERT_EQ(1u, picture->tilings()->num_tilings()); - EXPECT_EQ(2.f, picture->tilings()->tiling_at(0)->contents_scale()); + EXPECT_EQ(gfx::AxisTransform2d(2.f, gfx::Vector2dF()), + picture->tilings()->tiling_at(0)->raster_transform()); } } @@ -488,7 +485,8 @@ class LayerTreeHostPictureTestRSLLMembershipWithScale if (draws_in_frame_ == 1) { // On 1st commit the layer has tilings. EXPECT_GT(picture->tilings()->num_tilings(), 0u); - EXPECT_EQ(1.f, picture->HighResTiling()->contents_scale()); + EXPECT_EQ(gfx::AxisTransform2d(), + picture->HighResTiling()->raster_transform()); // Pinch zoom in to change the scale on the active tree. impl->PinchGestureBegin(); @@ -498,7 +496,8 @@ class LayerTreeHostPictureTestRSLLMembershipWithScale // If the pinch gesture caused a commit we could get here with a // pending tree. EXPECT_FALSE(impl->pending_tree()); - EXPECT_EQ(2.f, picture->HighResTiling()->contents_scale()); + EXPECT_EQ(gfx::AxisTransform2d(2.f, gfx::Vector2dF()), + picture->HighResTiling()->raster_transform()); // Need to wait for ready to draw here so that the pinch is // entirely complete, otherwise another draw might come in before @@ -507,7 +506,7 @@ class LayerTreeHostPictureTestRSLLMembershipWithScale ++frame_; MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind( + base::BindOnce( &LayerTreeHostPictureTestRSLLMembershipWithScale::NextStep, base::Unretained(this))); } @@ -524,7 +523,7 @@ class LayerTreeHostPictureTestRSLLMembershipWithScale ++frame_; MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind( + base::BindOnce( &LayerTreeHostPictureTestRSLLMembershipWithScale::NextStep, base::Unretained(this))); break; @@ -616,14 +615,16 @@ class LayerTreeHostPictureTestForceRecalculateScales case 0: // On first commit, both layers are at the default scale. ASSERT_EQ(1u, will_change_layer->tilings()->num_tilings()); - EXPECT_EQ(1.f, - will_change_layer->tilings()->tiling_at(0)->contents_scale()); + EXPECT_EQ( + gfx::AxisTransform2d(), + will_change_layer->tilings()->tiling_at(0)->raster_transform()); ASSERT_EQ(1u, normal_layer->tilings()->num_tilings()); - EXPECT_EQ(1.f, normal_layer->tilings()->tiling_at(0)->contents_scale()); + EXPECT_EQ(gfx::AxisTransform2d(), + normal_layer->tilings()->tiling_at(0)->raster_transform()); MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind( + base::BindOnce( &LayerTreeHostPictureTestForceRecalculateScales::ScaleRootUp, base::Unretained(this))); break; @@ -631,25 +632,29 @@ class LayerTreeHostPictureTestForceRecalculateScales // On 2nd commit after scaling up to 2, the normal layer will adjust its // scale and the will change layer should not (as it is will change. ASSERT_EQ(1u, will_change_layer->tilings()->num_tilings()); - EXPECT_EQ(1.f, - will_change_layer->tilings()->tiling_at(0)->contents_scale()); + EXPECT_EQ( + gfx::AxisTransform2d(), + will_change_layer->tilings()->tiling_at(0)->raster_transform()); ASSERT_EQ(1u, normal_layer->tilings()->num_tilings()); - EXPECT_EQ(2.f, normal_layer->tilings()->tiling_at(0)->contents_scale()); + EXPECT_EQ(gfx::AxisTransform2d(2.f, gfx::Vector2dF()), + normal_layer->tilings()->tiling_at(0)->raster_transform()); MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostPictureTestForceRecalculateScales:: - ScaleRootUpAndRecalculateScales, - base::Unretained(this))); + base::BindOnce(&LayerTreeHostPictureTestForceRecalculateScales:: + ScaleRootUpAndRecalculateScales, + base::Unretained(this))); break; case 2: // On 3rd commit, both layers should adjust scales due to forced // recalculating. ASSERT_EQ(1u, will_change_layer->tilings()->num_tilings()); - EXPECT_EQ(4.f, - will_change_layer->tilings()->tiling_at(0)->contents_scale()); + EXPECT_EQ( + gfx::AxisTransform2d(4.f, gfx::Vector2dF()), + will_change_layer->tilings()->tiling_at(0)->raster_transform()); ASSERT_EQ(1u, normal_layer->tilings()->num_tilings()); - EXPECT_EQ(4.f, normal_layer->tilings()->tiling_at(0)->contents_scale()); + EXPECT_EQ(gfx::AxisTransform2d(4.f, gfx::Vector2dF()), + normal_layer->tilings()->tiling_at(0)->raster_transform()); EndTest(); break; } diff --git a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc index ec968022fe0..b547fefcc45 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc @@ -9,7 +9,6 @@ #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" -#include "build/build_config.h" #include "cc/animation/animation_host.h" #include "cc/base/completion_event.h" #include "cc/input/main_thread_scrolling_reason.h" @@ -570,6 +569,8 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest { root_layer->SetBounds(gfx::Size(10, 10)); root_scroll_layer_ = FakePictureLayer::Create(&fake_content_layer_client_); + root_scroll_layer_->SetElementId( + LayerIdToElementIdForTesting(root_scroll_layer_->id())); root_scroll_layer_->SetBounds(gfx::Size(110, 110)); root_scroll_layer_->SetPosition(gfx::PointF()); root_scroll_layer_->SetIsDrawable(true); @@ -582,6 +583,8 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest { child_layer_->set_did_scroll_callback( base::Bind(&LayerTreeHostScrollTestCaseWithChild::DidScroll, base::Unretained(this))); + child_layer_->SetElementId( + LayerIdToElementIdForTesting(child_layer_->id())); child_layer_->SetBounds(gfx::Size(110, 110)); if (scroll_child_layer_) { @@ -599,6 +602,8 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest { child_layer_->SetIsDrawable(true); child_layer_->SetScrollClipLayerId(outer_container_layer->id()); + child_layer_->SetElementId( + LayerIdToElementIdForTesting(child_layer_->id())); child_layer_->SetBounds(root_scroll_layer_->bounds()); root_scroll_layer_->AddChild(child_layer_); @@ -1314,7 +1319,7 @@ class ThreadCheckingInputHandlerClient : public InputHandlerClient { void BindInputHandlerOnCompositorThread( const base::WeakPtr<InputHandler>& input_handler, ThreadCheckingInputHandlerClient* client) { - input_handler->BindToClient(client); + input_handler->BindToClient(client, false); } TEST(LayerTreeHostFlingTest, DidStopFlingingThread) { @@ -1342,9 +1347,9 @@ TEST(LayerTreeHostFlingTest, DidStopFlingingThread) { ThreadCheckingInputHandlerClient input_handler_client( impl_thread.task_runner().get(), &received_stop_flinging); impl_thread.task_runner()->PostTask( - FROM_HERE, base::Bind(&BindInputHandlerOnCompositorThread, - layer_tree_host->GetInputHandler(), - base::Unretained(&input_handler_client))); + FROM_HERE, base::BindOnce(&BindInputHandlerOnCompositorThread, + layer_tree_host->GetInputHandler(), + base::Unretained(&input_handler_client))); layer_tree_host->DidStopFlinging(); @@ -1435,6 +1440,8 @@ class LayerTreeHostScrollTestLayerStructureChange scroll_layer->SetPosition(gfx::PointF()); scroll_layer->SetIsDrawable(true); scroll_layer->SetScrollClipLayerId(parent->id()); + scroll_layer->SetElementId( + LayerIdToElementIdForTesting(scroll_layer->id())); scroll_layer->SetBounds(gfx::Size(parent->bounds().width() + 100, parent->bounds().height() + 100)); scroll_layer->set_did_scroll_callback(base::Bind( @@ -1861,15 +1868,15 @@ class LayerTreeHostScrollTestElasticOverscroll DCHECK(HasImplThread()); ImplThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostScrollTestElasticOverscroll::BindInputHandler, - base::Unretained(this), - layer_tree_host()->GetInputHandler())); + base::BindOnce( + &LayerTreeHostScrollTestElasticOverscroll::BindInputHandler, + base::Unretained(this), layer_tree_host()->GetInputHandler())); PostSetNeedsCommitToMainThread(); } void BindInputHandler(base::WeakPtr<InputHandler> input_handler) { DCHECK(task_runner_provider()->IsImplThread()); - input_handler->BindToClient(&input_handler_client_); + input_handler->BindToClient(&input_handler_client_, false); scroll_elasticity_helper_ = input_handler->CreateScrollElasticityHelper(); DCHECK(scroll_elasticity_helper_); } @@ -2072,20 +2079,11 @@ class LayerTreeHostScrollTestPropertyTreeUpdate SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostScrollTestPropertyTreeUpdate); -// Disabled due to flakes/crashes on Linux TSan Tests and on -// linux_chromium_asan_rel; see https://crbug.com/697652. -#if defined(OS_LINUX) -#define MAYBE_LayerTreeHostScrollTestImplSideInvalidation \ - DISABLED_LayerTreeHostScrollTestImplSideInvalidation -#else -#define MAYBE_LayerTreeHostScrollTestImplSideInvalidation \ - LayerTreeHostScrollTestImplSideInvalidation -#endif -class MAYBE_LayerTreeHostScrollTestImplSideInvalidation +class LayerTreeHostScrollTestImplSideInvalidation : public LayerTreeHostScrollTest { void BeginTest() override { layer_tree_host()->outer_viewport_scroll_layer()->set_did_scroll_callback( - base::Bind(&MAYBE_LayerTreeHostScrollTestImplSideInvalidation:: + base::Bind(&LayerTreeHostScrollTestImplSideInvalidation:: DidScrollOuterViewport, base::Unretained(this))); PostSetNeedsCommitToMainThread(); @@ -2098,9 +2096,9 @@ class MAYBE_LayerTreeHostScrollTestImplSideInvalidation CompletionEvent completion; task_runner_provider()->ImplThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&MAYBE_LayerTreeHostScrollTestImplSideInvalidation:: - WaitForInvalidationOnImplThread, - base::Unretained(this), &completion)); + base::BindOnce(&LayerTreeHostScrollTestImplSideInvalidation:: + WaitForInvalidationOnImplThread, + base::Unretained(this), &completion)); completion.Wait(); } @@ -2172,18 +2170,11 @@ class MAYBE_LayerTreeHostScrollTestImplSideInvalidation void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* host_impl, CommitEarlyOutReason reason) override { - // The aborted main frame is bound to come after the fourth activation, - // since the activation should occur synchronously after the impl-side - // invalidation, and the main thread is released after this activation. It - // should leave the scroll offset unchanged. - EXPECT_EQ(reason, CommitEarlyOutReason::FINISHED_NO_UPDATES); - EXPECT_EQ(num_of_activations_, 4); - EXPECT_EQ(num_of_main_frames_, 3); - EXPECT_EQ(host_impl->active_tree() - ->OuterViewportScrollLayer() - ->CurrentScrollOffset(), - outer_viewport_offsets_[2]); - EndTest(); + EXPECT_EQ(CommitEarlyOutReason::FINISHED_NO_UPDATES, reason); + EXPECT_EQ(3, num_of_main_frames_); + EXPECT_EQ(outer_viewport_offsets_[2], host_impl->active_tree() + ->OuterViewportScrollLayer() + ->CurrentScrollOffset()); } void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override { @@ -2200,11 +2191,10 @@ class MAYBE_LayerTreeHostScrollTestImplSideInvalidation // The second activation is from an impl-side pending tree so the source // frame number on the active tree remains unchanged, and the scroll // offset on the active tree should also remain unchanged. - EXPECT_EQ(host_impl->active_tree()->source_frame_number(), 0); - EXPECT_EQ(host_impl->active_tree() - ->OuterViewportScrollLayer() - ->CurrentScrollOffset(), - outer_viewport_offsets_[1]); + EXPECT_EQ(0, host_impl->active_tree()->source_frame_number()); + EXPECT_EQ(outer_viewport_offsets_[1], host_impl->active_tree() + ->OuterViewportScrollLayer() + ->CurrentScrollOffset()); break; case 3: // The third activation is from a commit. The scroll offset on the @@ -2218,21 +2208,25 @@ class MAYBE_LayerTreeHostScrollTestImplSideInvalidation case 4: // The fourth activation is from an impl-side pending tree, which should // leave the scroll offset unchanged. - EXPECT_EQ(host_impl->active_tree()->source_frame_number(), 1); - EXPECT_EQ(host_impl->active_tree() - ->OuterViewportScrollLayer() - ->CurrentScrollOffset(), - outer_viewport_offsets_[2]); + EXPECT_EQ(1, host_impl->active_tree()->source_frame_number()); + EXPECT_EQ(outer_viewport_offsets_[2], host_impl->active_tree() + ->OuterViewportScrollLayer() + ->CurrentScrollOffset()); break; default: NOTREACHED(); } } + void DrawLayersOnThread(LayerTreeHostImpl* impl) override { + if (++num_of_draws_ == 4) + EndTest(); + } + void AfterTest() override { - EXPECT_EQ(num_of_activations_, 4); - EXPECT_EQ(num_of_deltas_, 2); - EXPECT_EQ(num_of_main_frames_, 3); + EXPECT_EQ(4, num_of_activations_); + EXPECT_EQ(2, num_of_deltas_); + EXPECT_EQ(3, num_of_main_frames_); } const gfx::ScrollOffset outer_viewport_offsets_[3] = { @@ -2241,6 +2235,7 @@ class MAYBE_LayerTreeHostScrollTestImplSideInvalidation // Impl thread. int num_of_activations_ = 0; + int num_of_draws_ = 0; int num_of_main_frames_ = 0; bool invalidated_on_impl_thread_ = false; CompletionEvent* impl_side_invalidation_event_ = nullptr; @@ -2249,7 +2244,7 @@ class MAYBE_LayerTreeHostScrollTestImplSideInvalidation int num_of_deltas_ = 0; }; -MULTI_THREAD_TEST_F(MAYBE_LayerTreeHostScrollTestImplSideInvalidation); +MULTI_THREAD_TEST_F(LayerTreeHostScrollTestImplSideInvalidation); } // namespace } // namespace cc diff --git a/chromium/cc/trees/layer_tree_impl.cc b/chromium/cc/trees/layer_tree_impl.cc index 08ca53054cb..12ebf3fa413 100644 --- a/chromium/cc/trees/layer_tree_impl.cc +++ b/chromium/cc/trees/layer_tree_impl.cc @@ -17,16 +17,16 @@ #include "base/timer/elapsed_timer.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" +#include "cc/base/devtools_instrumentation.h" #include "cc/base/histograms.h" #include "cc/base/math_util.h" #include "cc/base/synced_property.h" -#include "cc/debug/devtools_instrumentation.h" #include "cc/debug/traced_value.h" #include "cc/input/page_scale_animation.h" #include "cc/input/scrollbar_animation_controller.h" +#include "cc/layers/effect_tree_layer_list_iterator.h" #include "cc/layers/heads_up_display_layer_impl.h" #include "cc/layers/layer.h" -#include "cc/layers/layer_iterator.h" #include "cc/layers/layer_list_iterator.h" #include "cc/layers/render_surface_impl.h" #include "cc/layers/scrollbar_layer_impl_base.h" @@ -243,27 +243,31 @@ void LayerTreeImpl::UpdateScrollbars(int scroll_layer_id, int clip_layer_id) { } bool scrollbar_needs_animation = false; + bool clip_layer_size_did_change = false; bool scroll_layer_size_did_change = false; bool y_offset_did_change = false; for (ScrollbarLayerImplBase* scrollbar : ScrollbarsFor(scroll_layer_id)) { if (scrollbar->orientation() == HORIZONTAL) { scrollbar_needs_animation |= scrollbar->SetCurrentPos(current_offset.x()); - scrollbar_needs_animation |= + clip_layer_size_did_change |= scrollbar->SetClipLayerLength(clip_size.width()); - scrollbar_needs_animation |= scroll_layer_size_did_change |= + scroll_layer_size_did_change |= scrollbar->SetScrollLayerLength(scroll_size.width()); } else { scrollbar_needs_animation |= y_offset_did_change |= scrollbar->SetCurrentPos(current_offset.y()); - scrollbar_needs_animation |= + clip_layer_size_did_change |= scrollbar->SetClipLayerLength(clip_size.height()); - scrollbar_needs_animation |= scroll_layer_size_did_change |= + scroll_layer_size_did_change |= scrollbar->SetScrollLayerLength(scroll_size.height()); } scrollbar_needs_animation |= scrollbar->SetVerticalAdjust(clip_layer->bounds_delta().y()); } + scrollbar_needs_animation |= + (clip_layer_size_did_change || scroll_layer_size_did_change); + if (y_offset_did_change && IsViewportLayerId(scroll_layer_id)) TRACE_COUNTER_ID1("cc", "scroll_offset_y", scroll_layer->id(), current_offset.y()); @@ -272,8 +276,16 @@ void LayerTreeImpl::UpdateScrollbars(int scroll_layer_id, int clip_layer_id) { ScrollbarAnimationController* controller = layer_tree_host_impl_->ScrollbarAnimationControllerForId( scroll_layer_id); - if (controller) - controller->DidScrollUpdate(scroll_layer_size_did_change); + if (!controller) + return; + + // TODO(chaopeng) clip_layer_size_did_change should call DidResize after + // crbug.com/701810 got fixed. + if (scroll_layer_size_did_change) { + controller->DidResize(); + } else { + controller->DidScrollUpdate(); + } } } @@ -485,11 +497,13 @@ void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) { max_page_scale_factor()); target_tree->SetDeviceScaleFactor(device_scale_factor()); target_tree->set_painted_device_scale_factor(painted_device_scale_factor()); - target_tree->SetDeviceColorSpace(device_color_space_); + target_tree->SetRasterColorSpace(raster_color_space_); target_tree->elastic_overscroll()->PushPendingToActive(); target_tree->set_content_source_id(content_source_id()); + target_tree->set_local_surface_id(local_surface_id()); + target_tree->pending_page_scale_animation_ = std::move(pending_page_scale_animation_); @@ -527,6 +541,23 @@ void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) { target_tree->set_hud_layer(NULL); target_tree->has_ever_been_drawn_ = false; + + // Note: this needs to happen after SetPropertyTrees. + target_tree->ShowScrollbars(); +} + +void LayerTreeImpl::ShowScrollbars() { + LayerTreeHostCommon::CallFunctionForEveryLayer(this, [this]( + LayerImpl* layer) { + if (!layer->needs_show_scrollbars()) + return; + ScrollbarAnimationController* controller = + layer_tree_host_impl_->ScrollbarAnimationControllerForId(layer->id()); + if (controller) { + controller->DidRequestShowFromMainThread(); + layer->set_needs_show_scrollbars(false); + } + }); } void LayerTreeImpl::MoveChangeTrackingToLayers() { @@ -624,17 +655,40 @@ void LayerTreeImpl::RemoveFromElementMap(LayerImpl* layer) { } void LayerTreeImpl::AddToOpacityAnimationsMap(int id, float opacity) { - opacity_animations_map_[id] = opacity; + if (LayerImpl* layer = LayerById(id)) + element_id_to_opacity_animations_[layer->element_id()] = opacity; +} + +void LayerTreeImpl::SetTransformMutated(ElementId element_id, + const gfx::Transform& transform) { + DCHECK_EQ(1u, property_trees()->element_id_to_transform_node_index.count( + element_id)); + element_id_to_transform_animations_[element_id] = transform; + if (!property_trees()->transform_tree.OnTransformAnimated(element_id, + transform)) + return; + + if (LayerImpl* layer = LayerByElementId(element_id)) + layer->set_was_ever_ready_since_last_transform_animation(false); + + set_needs_update_draw_properties(); } -void LayerTreeImpl::AddToTransformAnimationsMap(int id, - gfx::Transform transform) { - transform_animations_map_[id] = transform; +void LayerTreeImpl::SetOpacityMutated(ElementId element_id, float opacity) { + DCHECK_EQ( + 1u, property_trees()->element_id_to_effect_node_index.count(element_id)); + element_id_to_opacity_animations_[element_id] = opacity; + if (property_trees()->effect_tree.OnOpacityAnimated(element_id, opacity)) + set_needs_update_draw_properties(); } -void LayerTreeImpl::AddToFilterAnimationsMap(int id, - const FilterOperations& filters) { - filter_animations_map_[id] = filters; +void LayerTreeImpl::SetFilterMutated(ElementId element_id, + const FilterOperations& filters) { + DCHECK_EQ( + 1u, property_trees()->element_id_to_effect_node_index.count(element_id)); + element_id_to_filter_animations_[element_id] = filters; + if (property_trees()->effect_tree.OnFilterAnimated(element_id, filters)) + set_needs_update_draw_properties(); } LayerImpl* LayerTreeImpl::InnerViewportContainerLayer() const { @@ -668,17 +722,28 @@ void LayerTreeImpl::SetCurrentlyScrollingNode(ScrollNode* node) { ScrollTree& scroll_tree = property_trees()->scroll_tree; ScrollNode* old_node = scroll_tree.CurrentlyScrollingNode(); - // TODO(pdr): Refactor these to not use owning_layer_id. + + ElementId old_element_id = old_node ? old_node->element_id : ElementId(); + ElementId new_element_id = node ? node->element_id : ElementId(); + +#if DCHECK_IS_ON() int old_layer_id = old_node ? old_node->owning_layer_id : Layer::INVALID_ID; int new_layer_id = node ? node->owning_layer_id : Layer::INVALID_ID; + DCHECK(old_layer_id == LayerIdByElementId(old_element_id)); + DCHECK(new_layer_id == LayerIdByElementId(new_element_id)); +#endif - if (old_layer_id == new_layer_id) + if (old_element_id == new_element_id) return; + // TODO(pdr): Make the scrollbar animation controller lookup based on + // element ids instead of layer ids. ScrollbarAnimationController* old_animation_controller = - layer_tree_host_impl_->ScrollbarAnimationControllerForId(old_layer_id); + layer_tree_host_impl_->ScrollbarAnimationControllerForId( + LayerIdByElementId(old_element_id)); ScrollbarAnimationController* new_animation_controller = - layer_tree_host_impl_->ScrollbarAnimationControllerForId(new_layer_id); + layer_tree_host_impl_->ScrollbarAnimationControllerForId( + LayerIdByElementId(new_element_id)); if (old_animation_controller) old_animation_controller->DidScrollEnd(); @@ -710,61 +775,54 @@ void LayerTreeImpl::UpdatePropertyTreeScrollingAndAnimationFromMainThread() { // frame to a newly-committed property tree. if (layer_list_.empty()) return; - std::vector<int> layer_ids_to_remove; - for (auto& layer_id_to_opacity : opacity_animations_map_) { - const int id = layer_id_to_opacity.first; - if (property_trees_.IsInIdToIndexMap(PropertyTrees::TreeType::EFFECT, id)) { - EffectNode* node = property_trees_.effect_tree.Node( - property_trees_.layer_id_to_effect_node_index[id]); + auto element_id_to_opacity = element_id_to_opacity_animations_.begin(); + while (element_id_to_opacity != element_id_to_opacity_animations_.end()) { + const ElementId id = element_id_to_opacity->first; + if (EffectNode* node = + property_trees_.effect_tree.FindNodeFromElementId(id)) { if (!node->is_currently_animating_opacity || - node->opacity == layer_id_to_opacity.second) { - layer_ids_to_remove.push_back(id); + node->opacity == element_id_to_opacity->second) { + element_id_to_opacity_animations_.erase(element_id_to_opacity++); continue; } - node->opacity = layer_id_to_opacity.second; + node->opacity = element_id_to_opacity->second; property_trees_.effect_tree.set_needs_update(true); } + ++element_id_to_opacity; } - for (auto id : layer_ids_to_remove) - opacity_animations_map_.erase(id); - layer_ids_to_remove.clear(); - - for (auto& layer_id_to_transform : transform_animations_map_) { - const int id = layer_id_to_transform.first; - if (property_trees_.IsInIdToIndexMap(PropertyTrees::TreeType::TRANSFORM, - id)) { - TransformNode* node = property_trees_.transform_tree.Node( - property_trees_.layer_id_to_transform_node_index[id]); - if (!node->is_currently_animating || - node->local == layer_id_to_transform.second) { - layer_ids_to_remove.push_back(id); + + auto element_id_to_filter = element_id_to_filter_animations_.begin(); + while (element_id_to_filter != element_id_to_filter_animations_.end()) { + const ElementId id = element_id_to_filter->first; + if (EffectNode* node = + property_trees_.effect_tree.FindNodeFromElementId(id)) { + if (!node->is_currently_animating_filter || + node->filters == element_id_to_filter->second) { + element_id_to_filter_animations_.erase(element_id_to_filter++); continue; } - node->local = layer_id_to_transform.second; - node->needs_local_transform_update = true; - property_trees_.transform_tree.set_needs_update(true); + node->filters = element_id_to_filter->second; + property_trees_.effect_tree.set_needs_update(true); } + ++element_id_to_filter; } - for (auto id : layer_ids_to_remove) - transform_animations_map_.erase(id); - layer_ids_to_remove.clear(); - - for (auto& layer_id_to_filters : filter_animations_map_) { - const int id = layer_id_to_filters.first; - if (property_trees_.IsInIdToIndexMap(PropertyTrees::TreeType::EFFECT, id)) { - EffectNode* node = property_trees_.effect_tree.Node( - property_trees_.layer_id_to_effect_node_index[id]); - if (!node->is_currently_animating_filter || - node->filters == layer_id_to_filters.second) { - layer_ids_to_remove.push_back(id); + + auto element_id_to_transform = element_id_to_transform_animations_.begin(); + while (element_id_to_transform != element_id_to_transform_animations_.end()) { + const ElementId id = element_id_to_transform->first; + if (TransformNode* node = + property_trees_.transform_tree.FindNodeFromElementId(id)) { + if (!node->is_currently_animating || + node->local == element_id_to_transform->second) { + element_id_to_transform_animations_.erase(element_id_to_transform++); continue; } - node->filters = layer_id_to_filters.second; - property_trees_.effect_tree.set_needs_update(true); + node->local = element_id_to_transform->second; + node->needs_local_transform_update = true; + property_trees_.transform_tree.set_needs_update(true); } + ++element_id_to_transform; } - for (auto id : layer_ids_to_remove) - filter_animations_map_.erase(id); LayerTreeHostCommon::CallFunctionForEveryLayer(this, [](LayerImpl* layer) { layer->UpdatePropertyTreeForScrollingAndAnimationIfNeeded(); @@ -926,11 +984,11 @@ void LayerTreeImpl::SetDeviceScaleFactor(float device_scale_factor) { layer_tree_host_impl_->SetNeedUpdateGpuRasterizationStatus(); } -void LayerTreeImpl::SetDeviceColorSpace( - const gfx::ColorSpace& device_color_space) { - if (device_color_space == device_color_space_) +void LayerTreeImpl::SetRasterColorSpace( + const gfx::ColorSpace& raster_color_space) { + if (raster_color_space == raster_color_space_) return; - device_color_space_ = device_color_space; + raster_color_space_ = raster_color_space; } SyncedProperty<ScaleGroup>* LayerTreeImpl::page_scale_factor() { @@ -999,13 +1057,12 @@ static void SetElementIdForTesting(LayerImpl* layer) { void LayerTreeImpl::SetElementIdsForTesting() { LayerListIterator<LayerImpl> it(root_layer_for_testing_); for (; it != LayerListIterator<LayerImpl>(nullptr); ++it) { - SetElementIdForTesting(*it); + if (!it->element_id()) + SetElementIdForTesting(*it); } } -bool LayerTreeImpl::UpdateDrawProperties( - bool update_lcd_text, - bool force_skip_verify_visible_rect_calculations) { +bool LayerTreeImpl::UpdateDrawProperties(bool update_lcd_text) { if (!needs_update_draw_properties_) return true; @@ -1037,10 +1094,6 @@ bool LayerTreeImpl::UpdateDrawProperties( // We verify visible rect calculations whenever we verify clip tree // calculations except when this function is explicitly passed a flag asking // us to skip it. - bool verify_visible_rect_calculations = - force_skip_verify_visible_rect_calculations - ? false - : settings().verify_clip_tree_calculations; LayerTreeHostCommon::CalcDrawPropsImplInputs inputs( layer_list_[0], DrawViewportSize(), layer_tree_host_impl_->DrawTransform(), device_scale_factor(), @@ -1050,8 +1103,7 @@ bool LayerTreeImpl::UpdateDrawProperties( OverscrollElasticityLayer(), resource_provider()->max_texture_size(), can_render_to_separate_surface, settings().layer_transforms_should_scale_layer_contents, - settings().verify_clip_tree_calculations, - verify_visible_rect_calculations, &render_surface_layer_list_, + settings().use_layer_lists, &render_surface_layer_list_, &property_trees_); LayerTreeHostCommon::CalculateDrawProperties(&inputs); if (const char* client_name = GetClientNameForMetrics()) { @@ -1075,24 +1127,23 @@ bool LayerTreeImpl::UpdateDrawProperties( occlusion_tracker.set_minimum_tracking_size( settings().minimum_occlusion_tracking_size); - // LayerIterator is used here instead of CallFunctionForEveryLayer to only - // UpdateTilePriorities on layers that will be visible (and thus have valid - // draw properties) and not because any ordering is required. - LayerIterator end = LayerIterator::End(&render_surface_layer_list_); - for (LayerIterator it = LayerIterator::Begin(&render_surface_layer_list_); - it != end; ++it) { + for (EffectTreeLayerListIterator it(this); + it.state() != EffectTreeLayerListIterator::State::END; ++it) { occlusion_tracker.EnterLayer(it); - if (it.represents_itself()) { - it->draw_properties().occlusion_in_content_space = - occlusion_tracker.GetCurrentOcclusionForLayer(it->DrawTransform()); + if (it.state() == EffectTreeLayerListIterator::State::LAYER) { + LayerImpl* layer = it.current_layer(); + layer->draw_properties().occlusion_in_content_space = + occlusion_tracker.GetCurrentOcclusionForLayer( + layer->DrawTransform()); } - if (it.represents_contributing_render_surface()) { + if (it.state() == + EffectTreeLayerListIterator::State::CONTRIBUTING_SURFACE) { const RenderSurfaceImpl* occlusion_surface = occlusion_tracker.OcclusionSurfaceForContributingSurface(); gfx::Transform draw_transform; - RenderSurfaceImpl* render_surface = it->GetRenderSurface(); + RenderSurfaceImpl* render_surface = it.current_render_surface(); if (occlusion_surface) { // We are calculating transform between two render surfaces. So, we // need to apply the surface contents scale at target and remove the @@ -1116,7 +1167,7 @@ bool LayerTreeImpl::UpdateDrawProperties( if (LayerImpl* mask = render_surface->MaskLayer()) { mask->draw_properties().occlusion_in_content_space = occlusion_tracker.GetCurrentOcclusionForContributingSurface( - draw_transform * it->DrawTransform()); + draw_transform * render_surface->SurfaceScale()); } } @@ -1178,7 +1229,7 @@ void LayerTreeImpl::BuildLayerListAndPropertyTreesForTesting() { } void LayerTreeImpl::BuildPropertyTreesForTesting() { - PropertyTreeBuilder::PreCalculateMetaInformationForTesting(layer_list_[0]); + SetElementIdsForTesting(); property_trees_.needs_rebuild = true; property_trees_.transform_tree.set_source_to_parent_updates_allowed(true); PropertyTreeBuilder::BuildPropertyTrees( @@ -1250,14 +1301,16 @@ void LayerTreeImpl::RegisterLayer(LayerImpl* layer) { void LayerTreeImpl::UnregisterLayer(LayerImpl* layer) { DCHECK(LayerById(layer->id())); layers_that_should_push_properties_.erase(layer); - transform_animations_map_.erase(layer->id()); - opacity_animations_map_.erase(layer->id()); + element_id_to_transform_animations_.erase(layer->element_id()); + element_id_to_opacity_animations_.erase(layer->element_id()); + element_id_to_filter_animations_.erase(layer->element_id()); layer_id_map_.erase(layer->id()); } // These manage ownership of the LayerImpl. void LayerTreeImpl::AddLayer(std::unique_ptr<LayerImpl> layer) { DCHECK(std::find(layers_->begin(), layers_->end(), layer) == layers_->end()); + DCHECK(layer); layers_->push_back(std::move(layer)); set_needs_update_draw_properties(); } @@ -1417,29 +1470,26 @@ const gfx::Rect LayerTreeImpl::ViewportRectForTilePriority() const { std::unique_ptr<ScrollbarAnimationController> LayerTreeImpl::CreateScrollbarAnimationController(int scroll_layer_id) { - DCHECK(!settings().scrollbar_fade_out_delay.is_zero()); - DCHECK(!settings().scrollbar_fade_out_duration.is_zero()); - base::TimeDelta fade_out_delay = settings().scrollbar_fade_out_delay; + DCHECK(!settings().scrollbar_fade_delay.is_zero()); + DCHECK(!settings().scrollbar_fade_duration.is_zero()); + base::TimeDelta fade_delay = settings().scrollbar_fade_delay; base::TimeDelta fade_out_resize_delay = settings().scrollbar_fade_out_resize_delay; - base::TimeDelta fade_out_duration = settings().scrollbar_fade_out_duration; + base::TimeDelta fade_duration = settings().scrollbar_fade_duration; switch (settings().scrollbar_animator) { case LayerTreeSettings::ANDROID_OVERLAY: { return ScrollbarAnimationController:: CreateScrollbarAnimationControllerAndroid( - scroll_layer_id, layer_tree_host_impl_, fade_out_delay, - fade_out_resize_delay, fade_out_duration); + scroll_layer_id, layer_tree_host_impl_, fade_delay, + fade_out_resize_delay, fade_duration); } case LayerTreeSettings::AURA_OVERLAY: { - DCHECK(!settings().scrollbar_show_delay.is_zero()); - base::TimeDelta show_delay = settings().scrollbar_show_delay; base::TimeDelta thinning_duration = settings().scrollbar_thinning_duration; return ScrollbarAnimationController:: CreateScrollbarAnimationControllerAuraOverlay( - scroll_layer_id, layer_tree_host_impl_, show_delay, - fade_out_delay, fade_out_resize_delay, fade_out_duration, - thinning_duration); + scroll_layer_id, layer_tree_host_impl_, fade_delay, + fade_out_resize_delay, fade_duration, thinning_duration); } case LayerTreeSettings::NO_ANIMATOR: NOTREACHED(); @@ -1470,12 +1520,10 @@ void LayerTreeImpl::SetNeedsRedraw() { void LayerTreeImpl::GetAllPrioritizedTilesForTracing( std::vector<PrioritizedTile>* prioritized_tiles) const { - LayerIterator end = LayerIterator::End(&render_surface_layer_list_); - for (LayerIterator it = LayerIterator::Begin(&render_surface_layer_list_); - it != end; ++it) { - if (!it.represents_itself()) - continue; + for (auto it = layer_list_.rbegin(); it != layer_list_.rend(); ++it) { LayerImpl* layer_impl = *it; + if (!layer_impl->is_drawn_render_surface_layer_list_member()) + continue; layer_impl->GetAllPrioritizedTilesForTracing(prioritized_tiles); } } @@ -1485,10 +1533,8 @@ void LayerTreeImpl::AsValueInto(base::trace_event::TracedValue* state) const { state->SetInteger("source_frame_number", source_frame_number_); state->BeginArray("render_surface_layer_list"); - LayerIterator end = LayerIterator::End(&render_surface_layer_list_); - for (LayerIterator it = LayerIterator::Begin(&render_surface_layer_list_); - it != end; ++it) { - if (!it.represents_itself()) + for (auto it = layer_list_.rbegin(); it != layer_list_.rend(); ++it) { + if (!(*it)->is_drawn_render_surface_layer_list_member()) continue; TracedValue::AppendIDRef(*it, state); } @@ -1741,11 +1787,6 @@ void LayerTreeImpl::RemoveSurfaceLayer(LayerImpl* layer) { surface_layers_.erase(it); } -template <typename LayerType> -static inline bool LayerClipsSubtree(LayerType* layer) { - return layer->masks_to_bounds() || layer->mask_layer(); -} - static bool PointHitsRect( const gfx::PointF& screen_space_point, const gfx::Transform& local_space_to_screen_space_transform, diff --git a/chromium/cc/trees/layer_tree_impl.h b/chromium/cc/trees/layer_tree_impl.h index 02c6e994d3d..1d785f86e4e 100644 --- a/chromium/cc/trees/layer_tree_impl.h +++ b/chromium/cc/trees/layer_tree_impl.h @@ -145,9 +145,14 @@ class CC_EXPORT LayerTreeImpl { LayerImplList::reverse_iterator rbegin(); LayerImplList::reverse_iterator rend(); + // TODO(crbug.com/702832): This won't be needed if overlay scrollbars have + // element ids. void AddToOpacityAnimationsMap(int id, float opacity); - void AddToTransformAnimationsMap(int id, gfx::Transform transform); - void AddToFilterAnimationsMap(int id, const FilterOperations& filters); + + void SetTransformMutated(ElementId element_id, + const gfx::Transform& transform); + void SetOpacityMutated(ElementId element_id, float opacity); + void SetFilterMutated(ElementId element_id, const FilterOperations& filters); int source_frame_number() const { return source_frame_number_; } void set_source_frame_number(int frame_number) { @@ -232,9 +237,14 @@ class CC_EXPORT LayerTreeImpl { void set_content_source_id(uint32_t id) { content_source_id_ = id; } uint32_t content_source_id() { return content_source_id_; } - void SetDeviceColorSpace(const gfx::ColorSpace& device_color_space); - const gfx::ColorSpace& device_color_space() const { - return device_color_space_; + void set_local_surface_id(const LocalSurfaceId& id) { + local_surface_id_ = id; + } + const LocalSurfaceId& local_surface_id() const { return local_surface_id_; } + + void SetRasterColorSpace(const gfx::ColorSpace& raster_color_space); + const gfx::ColorSpace& raster_color_space() const { + return raster_color_space_; } SyncedElasticOverscroll* elastic_overscroll() { @@ -256,9 +266,7 @@ class CC_EXPORT LayerTreeImpl { // Updates draw properties and render surface layer list, as well as tile // priorities. Returns false if it was unable to update. Updating lcd // text may cause invalidations, so should only be done after a commit. - bool UpdateDrawProperties( - bool update_lcd_text, - bool force_skip_verify_visible_rect_calculations = false); + bool UpdateDrawProperties(bool update_lcd_text); void BuildPropertyTreesForTesting(); void BuildLayerListAndPropertyTreesForTesting(); @@ -469,6 +477,7 @@ class CC_EXPORT LayerTreeImpl { float max_page_scale_factor); bool IsViewportLayerId(int id) const; void UpdateScrollbars(int scroll_layer_id, int clip_layer_id); + void ShowScrollbars(); void DidUpdatePageScale(); void PushBrowserControls(const float* top_controls_shown_ratio); bool ClampBrowserControlsShownRatio(); @@ -496,9 +505,10 @@ class CC_EXPORT LayerTreeImpl { float device_scale_factor_; float painted_device_scale_factor_; - gfx::ColorSpace device_color_space_; + gfx::ColorSpace raster_color_space_; uint32_t content_source_id_; + LocalSurfaceId local_surface_id_; scoped_refptr<SyncedElasticOverscroll> elastic_overscroll_; @@ -510,9 +520,12 @@ class CC_EXPORT LayerTreeImpl { std::unordered_map<ElementId, int, ElementIdHash> element_layers_map_; - std::unordered_map<int, float> opacity_animations_map_; - std::unordered_map<int, gfx::Transform> transform_animations_map_; - std::unordered_map<int, FilterOperations> filter_animations_map_; + std::unordered_map<ElementId, float, ElementIdHash> + element_id_to_opacity_animations_; + std::unordered_map<ElementId, gfx::Transform, ElementIdHash> + element_id_to_transform_animations_; + std::unordered_map<ElementId, FilterOperations, ElementIdHash> + element_id_to_filter_animations_; // Maps from clip layer ids to scroll layer ids. Note that this only includes // the subset of clip layers that act as scrolling containers. (This is diff --git a/chromium/cc/trees/layer_tree_impl_unittest.cc b/chromium/cc/trees/layer_tree_impl_unittest.cc index 81d2800c986..3b0cbeec663 100644 --- a/chromium/cc/trees/layer_tree_impl_unittest.cc +++ b/chromium/cc/trees/layer_tree_impl_unittest.cc @@ -10,7 +10,6 @@ #include "cc/test/fake_layer_tree_host_impl.h" #include "cc/test/geometry_test_utils.h" #include "cc/test/layer_test_common.h" -#include "cc/test/layer_tree_settings_for_testing.h" #include "cc/trees/clip_node.h" #include "cc/trees/draw_property_utils.h" #include "cc/trees/layer_tree_host_common.h" @@ -22,7 +21,7 @@ namespace cc { namespace { -class LayerTreeImplTestSettings : public LayerTreeSettingsForTesting { +class LayerTreeImplTestSettings : public LayerTreeSettings { public: LayerTreeImplTestSettings() { layer_transforms_should_scale_layer_contents = true; @@ -41,9 +40,7 @@ class LayerTreeImplTest : public testing::Test { return host_impl().active_tree()->RenderSurfaceLayerList(); } - void ExecuteCalculateDrawProperties( - LayerImpl* root_layer, - bool skip_verify_visible_rect_calculations = false) { + void ExecuteCalculateDrawProperties(LayerImpl* root_layer) { // We are probably not testing what is intended if the root_layer bounds are // empty. DCHECK(!root_layer->bounds().IsEmpty()); @@ -52,8 +49,6 @@ class LayerTreeImplTest : public testing::Test { LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( root_layer, root_layer->bounds(), &render_surface_layer_list_impl_); inputs.can_adjust_raster_scales = true; - if (skip_verify_visible_rect_calculations) - inputs.verify_visible_rect_calculations = false; LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); } @@ -247,14 +242,7 @@ TEST_F(LayerTreeImplTest, HitTestingForUninvertibleTransform) { root->SetDrawsContent(true); host_impl().SetViewportSize(root->bounds()); - // While computing visible rects by combining clips in screen space, we set - // the entire layer as visible if the screen space transform is singular. This - // is not always true when we combine clips in target space because if the - // intersection of combined_clip in taret space with layer_rect projected to - // target space is empty, we set it to an empty rect. - bool skip_verify_visible_rect_calculations = true; - host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree( - skip_verify_visible_rect_calculations); + host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree(); // Sanity check the scenario we just created. ASSERT_EQ(1u, RenderSurfaceLayerList().size()); ASSERT_EQ(1u, root_layer()->GetRenderSurface()->layer_list().size()); @@ -441,10 +429,6 @@ TEST_F(LayerTreeImplTest, HitTestingClipNodeDifferentTransformAndTargetIds) { host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point); ASSERT_TRUE(result_layer); EXPECT_EQ(5, result_layer->id()); - - ClipTree& clip_tree = host_impl().active_tree()->property_trees()->clip_tree; - ClipNode* clip_node = clip_tree.Node(result_layer->clip_tree_index()); - EXPECT_NE(clip_node->transform_id, clip_node->target_transform_id); } TEST_F(LayerTreeImplTest, HitTestingSiblings) { @@ -637,7 +621,6 @@ TEST_F(LayerTreeImplTest, HitTestingForMultiClippedRotatedLayer) { // Visible rects computed by combinig clips in target space and root space // don't match because of rotation transforms. So, we skip // verify_visible_rect_calculations. - bool skip_verify_visible_rect_calculations = true; { std::unique_ptr<LayerImpl> child = LayerImpl::Create(host_impl().active_tree(), 456); @@ -677,12 +660,11 @@ TEST_F(LayerTreeImplTest, HitTestingForMultiClippedRotatedLayer) { child->test_properties()->AddChild(std::move(grand_child)); root->test_properties()->AddChild(std::move(child)); - ExecuteCalculateDrawProperties(root, skip_verify_visible_rect_calculations); + ExecuteCalculateDrawProperties(root); } host_impl().SetViewportSize(root->bounds()); - host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree( - skip_verify_visible_rect_calculations); + host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree(); // (11, 89) is close to the the bottom left corner within the clip, but it is // not inside the layer. gfx::PointF test_point(11.f, 89.f); @@ -1073,7 +1055,7 @@ TEST_F(LayerTreeImplTest, HitTestingRespectsClipParents) { std::unique_ptr<std::set<LayerImpl*>> clip_children( new std::set<LayerImpl*>); clip_children->insert(grand_child.get()); - root->test_properties()->clip_children.reset(clip_children.release()); + root->test_properties()->clip_children = std::move(clip_children); child->test_properties()->AddChild(std::move(grand_child)); root->test_properties()->AddChild(std::move(child)); @@ -1343,14 +1325,7 @@ TEST_F(LayerTreeImplTest, root->SetTouchEventHandlerRegion(touch_handler_region); host_impl().SetViewportSize(root->bounds()); - // While computing visible rects by combining clips in screen space, we set - // the entire layer as visible if the screen space transform is singular. This - // is not always true when we combine clips in target space because if the - // intersection of combined_clip in taret space with layer_rect projected to - // target space is empty, we set it to an empty rect. - bool skip_verify_visible_rect_calculations = true; - host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree( - skip_verify_visible_rect_calculations); + host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree(); // Sanity check the scenario we just created. ASSERT_EQ(1u, RenderSurfaceLayerList().size()); @@ -2242,13 +2217,13 @@ TEST_F(LayerTreeImplTest, DeviceScaleFactorNeedsDrawPropertiesUpdate) { EXPECT_TRUE(host_impl().active_tree()->needs_update_draw_properties()); } -TEST_F(LayerTreeImplTest, DeviceColorSpaceDoesNotNeedDrawPropertiesUpdate) { +TEST_F(LayerTreeImplTest, RasterColorSpaceDoesNotNeedDrawPropertiesUpdate) { host_impl().active_tree()->BuildPropertyTreesForTesting(); - host_impl().active_tree()->SetDeviceColorSpace( + host_impl().active_tree()->SetRasterColorSpace( gfx::ColorSpace::CreateXYZD50()); host_impl().active_tree()->UpdateDrawProperties(false); EXPECT_FALSE(host_impl().active_tree()->needs_update_draw_properties()); - host_impl().active_tree()->SetDeviceColorSpace(gfx::ColorSpace::CreateSRGB()); + host_impl().active_tree()->SetRasterColorSpace(gfx::ColorSpace::CreateSRGB()); EXPECT_FALSE(host_impl().active_tree()->needs_update_draw_properties()); } diff --git a/chromium/cc/trees/layer_tree_mutator.h b/chromium/cc/trees/layer_tree_mutator.h index 9233ca2eec9..f7a1578bec8 100644 --- a/chromium/cc/trees/layer_tree_mutator.h +++ b/chromium/cc/trees/layer_tree_mutator.h @@ -7,7 +7,7 @@ #include "base/callback_forward.h" #include "base/time/time.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace cc { diff --git a/chromium/cc/trees/layer_tree_settings.cc b/chromium/cc/trees/layer_tree_settings.cc index de32ad805da..2b8531c9e01 100644 --- a/chromium/cc/trees/layer_tree_settings.cc +++ b/chromium/cc/trees/layer_tree_settings.cc @@ -22,68 +22,6 @@ LayerTreeSettings::LayerTreeSettings() LayerTreeSettings::LayerTreeSettings(const LayerTreeSettings& other) = default; LayerTreeSettings::~LayerTreeSettings() = default; -bool LayerTreeSettings::operator==(const LayerTreeSettings& other) const { - return renderer_settings == other.renderer_settings && - single_thread_proxy_scheduler == other.single_thread_proxy_scheduler && - main_frame_before_activation_enabled == - other.main_frame_before_activation_enabled && - using_synchronous_renderer_compositor == - other.using_synchronous_renderer_compositor && - enable_latency_recovery == other.enable_latency_recovery && - can_use_lcd_text == other.can_use_lcd_text && - use_distance_field_text == other.use_distance_field_text && - gpu_rasterization_forced == other.gpu_rasterization_forced && - async_worker_context_enabled == other.async_worker_context_enabled && - gpu_rasterization_msaa_sample_count == - other.gpu_rasterization_msaa_sample_count && - create_low_res_tiling == other.create_low_res_tiling && - scrollbar_animator == other.scrollbar_animator && - scrollbar_show_delay == other.scrollbar_show_delay && - scrollbar_fade_out_delay == other.scrollbar_fade_out_delay && - scrollbar_fade_out_resize_delay == - other.scrollbar_fade_out_resize_delay && - scrollbar_fade_out_duration == other.scrollbar_fade_out_duration && - solid_color_scrollbar_color == other.solid_color_scrollbar_color && - timeout_and_draw_when_animation_checkerboards == - other.timeout_and_draw_when_animation_checkerboards && - layer_transforms_should_scale_layer_contents == - other.layer_transforms_should_scale_layer_contents && - layers_always_allowed_lcd_text == - other.layers_always_allowed_lcd_text && - minimum_contents_scale == other.minimum_contents_scale && - low_res_contents_scale_factor == other.low_res_contents_scale_factor && - top_controls_show_threshold == other.top_controls_show_threshold && - top_controls_hide_threshold == other.top_controls_hide_threshold && - background_animation_rate == other.background_animation_rate && - default_tile_size == other.default_tile_size && - max_untiled_layer_size == other.max_untiled_layer_size && - minimum_occlusion_tracking_size == - other.minimum_occlusion_tracking_size && - tiling_interest_area_padding == other.tiling_interest_area_padding && - skewport_target_time_in_seconds == - other.skewport_target_time_in_seconds && - skewport_extrapolation_limit_in_screen_pixels == - other.skewport_extrapolation_limit_in_screen_pixels && - max_memory_for_prepaint_percentage == - other.max_memory_for_prepaint_percentage && - use_zero_copy == other.use_zero_copy && - use_partial_raster == other.use_partial_raster && - enable_elastic_overscroll == other.enable_elastic_overscroll && - ignore_root_layer_flings == other.ignore_root_layer_flings && - scheduled_raster_task_limit == other.scheduled_raster_task_limit && - use_occlusion_for_tile_prioritization == - other.use_occlusion_for_tile_prioritization && - verify_clip_tree_calculations == other.verify_clip_tree_calculations && - image_decode_tasks_enabled == other.image_decode_tasks_enabled && - max_staging_buffer_usage_in_bytes == - other.max_staging_buffer_usage_in_bytes && - gpu_memory_policy == other.gpu_memory_policy && - software_memory_policy == other.software_memory_policy && - enable_mask_tiling == other.enable_mask_tiling && - LayerTreeDebugState::Equal(initial_debug_state, - other.initial_debug_state); -} - SchedulerSettings LayerTreeSettings::ToSchedulerSettings() const { SchedulerSettings scheduler_settings; scheduler_settings.main_frame_before_activation_enabled = diff --git a/chromium/cc/trees/layer_tree_settings.h b/chromium/cc/trees/layer_tree_settings.h index 92b759ba864..90348788b5e 100644 --- a/chromium/cc/trees/layer_tree_settings.h +++ b/chromium/cc/trees/layer_tree_settings.h @@ -10,7 +10,7 @@ #include <vector> #include "base/time/time.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/debug/layer_tree_debug_state.h" #include "cc/output/managed_memory_policy.h" #include "cc/output/renderer_settings.h" @@ -27,8 +27,6 @@ class CC_EXPORT LayerTreeSettings { LayerTreeSettings(const LayerTreeSettings& other); virtual ~LayerTreeSettings(); - bool operator==(const LayerTreeSettings& other) const; - SchedulerSettings ToSchedulerSettings() const; TileManagerSettings ToTileManagerSettings() const; @@ -51,10 +49,9 @@ class CC_EXPORT LayerTreeSettings { AURA_OVERLAY, }; ScrollbarAnimator scrollbar_animator = NO_ANIMATOR; - base::TimeDelta scrollbar_show_delay; - base::TimeDelta scrollbar_fade_out_delay; + base::TimeDelta scrollbar_fade_delay; base::TimeDelta scrollbar_fade_out_resize_delay; - base::TimeDelta scrollbar_fade_out_duration; + base::TimeDelta scrollbar_fade_duration; base::TimeDelta scrollbar_thinning_duration; SkColor solid_color_scrollbar_color = SK_ColorWHITE; bool timeout_and_draw_when_animation_checkerboards = true; @@ -82,7 +79,6 @@ class CC_EXPORT LayerTreeSettings { bool ignore_root_layer_flings = false; size_t scheduled_raster_task_limit = 32; bool use_occlusion_for_tile_prioritization = false; - bool verify_clip_tree_calculations = false; // TODO(khushalsagar): Enable for all client and remove this flag if possible. // See crbug/com/696864. @@ -92,11 +88,11 @@ class CC_EXPORT LayerTreeSettings { int max_staging_buffer_usage_in_bytes = 32 * 1024 * 1024; ManagedMemoryPolicy gpu_memory_policy; ManagedMemoryPolicy software_memory_policy; - size_t gpu_decoded_image_budget_bytes = 96 * 1024 * 1024; - size_t software_decoded_image_budget_bytes = 128 * 1024 * 1024; + size_t decoded_image_cache_budget_bytes = 128 * 1024 * 1024; + size_t decoded_image_working_set_budget_bytes = 128 * 1024 * 1024; int max_preraster_distance_in_screen_pixels = 1000; - bool enable_color_correct_rendering = false; + bool enable_color_correct_rasterization = false; // TODO(sunxd): remove this flag when filter demoting and aa of mask layers // are implemented. @@ -108,6 +104,14 @@ class CC_EXPORT LayerTreeSettings { bool enable_checker_imaging = false; LayerTreeDebugState initial_debug_state; + + // Indicates that the LayerTreeHost should defer commits unless it has a valid + // LocalSurfaceId set. + bool enable_surface_synchronization = false; + + // Indicates the case when a sub-frame gets its own LayerTree because it's + // rendered in a different process from its ancestor frames. + bool is_layer_tree_for_subframe = false; }; } // namespace cc diff --git a/chromium/cc/trees/occlusion.h b/chromium/cc/trees/occlusion.h index 7e856aa66d2..ea38304907f 100644 --- a/chromium/cc/trees/occlusion.h +++ b/chromium/cc/trees/occlusion.h @@ -7,8 +7,8 @@ #include <string> -#include "cc/base/cc_export.h" #include "cc/base/simple_enclosed_region.h" +#include "cc/cc_export.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/transform.h" diff --git a/chromium/cc/trees/occlusion_tracker.cc b/chromium/cc/trees/occlusion_tracker.cc index 78f5cc66675..523b01f830f 100644 --- a/chromium/cc/trees/occlusion_tracker.cc +++ b/chromium/cc/trees/occlusion_tracker.cc @@ -56,23 +56,26 @@ OcclusionTracker::OcclusionSurfaceForContributingSurface() const { return (stack_.size() < 2) ? nullptr : stack_[stack_.size() - 2].target; } -void OcclusionTracker::EnterLayer(const LayerIteratorPosition& layer_iterator) { - LayerImpl* render_target = layer_iterator.target_render_surface_layer; +void OcclusionTracker::EnterLayer( + const EffectTreeLayerListIterator::Position& iterator) { + RenderSurfaceImpl* render_target = iterator.target_render_surface; - if (layer_iterator.represents_itself) + if (iterator.state == EffectTreeLayerListIterator::State::LAYER) EnterRenderTarget(render_target); - else if (layer_iterator.represents_target_render_surface) + else if (iterator.state == EffectTreeLayerListIterator::State::TARGET_SURFACE) FinishedRenderTarget(render_target); } -void OcclusionTracker::LeaveLayer(const LayerIteratorPosition& layer_iterator) { - LayerImpl* render_target = layer_iterator.target_render_surface_layer; +void OcclusionTracker::LeaveLayer( + const EffectTreeLayerListIterator::Position& iterator) { + RenderSurfaceImpl* render_target = iterator.target_render_surface; - if (layer_iterator.represents_itself) - MarkOccludedBehindLayer(layer_iterator.current_layer); + if (iterator.state == EffectTreeLayerListIterator::State::LAYER) + MarkOccludedBehindLayer(iterator.current_layer); // TODO(danakj): This should be done when entering the contributing surface, // but in a way that the surface's own occlusion won't occlude itself. - else if (layer_iterator.represents_contributing_render_surface) + else if (iterator.state == + EffectTreeLayerListIterator::State::CONTRIBUTING_SURFACE) LeaveToRenderTarget(render_target); } @@ -117,9 +120,9 @@ static SimpleEnclosedRegion TransformSurfaceOpaqueRegion( return transformed_region; } -void OcclusionTracker::EnterRenderTarget(const LayerImpl* new_target) { - DCHECK(new_target->GetRenderSurface()); - RenderSurfaceImpl* new_target_surface = new_target->GetRenderSurface(); +void OcclusionTracker::EnterRenderTarget( + const RenderSurfaceImpl* new_target_surface) { + DCHECK(new_target_surface); if (!stack_.empty() && stack_.back().target == new_target_surface) return; @@ -153,7 +156,7 @@ void OcclusionTracker::EnterRenderTarget(const LayerImpl* new_target) { &inverse_new_target_screen_space_transform); bool entering_root_target = - new_target->layer_tree_impl()->IsRootLayer(new_target); + new_target_surface->render_target() == new_target_surface; bool copy_outside_occlusion_forward = stack_.size() > 1 && @@ -177,22 +180,26 @@ void OcclusionTracker::EnterRenderTarget(const LayerImpl* new_target) { gfx::Rect(), old_target_to_new_target_transform)); } -void OcclusionTracker::FinishedRenderTarget(const LayerImpl* finished_target) { +void OcclusionTracker::FinishedRenderTarget( + const RenderSurfaceImpl* finished_target_surface) { // Make sure we know about the target surface. - EnterRenderTarget(finished_target); + EnterRenderTarget(finished_target_surface); - RenderSurfaceImpl* surface = finished_target->GetRenderSurface(); + bool is_hidden = + finished_target_surface->OwningEffectNode()->screen_space_opacity == 0.f; // Readbacks always happen on render targets so we only need to check // for readbacks here. bool target_is_only_for_copy_request = - surface->HasCopyRequest() && finished_target->IsHidden(); + finished_target_surface->HasCopyRequest() && is_hidden; // If the occlusion within the surface can not be applied to things outside of // the surface's subtree, then clear the occlusion here so it won't be used. - if (surface->MaskLayer() || surface->draw_opacity() < 1 || - !surface->UsesDefaultBlendMode() || target_is_only_for_copy_request || - surface->Filters().HasFilterThatAffectsOpacity()) { + if (finished_target_surface->HasMask() || + finished_target_surface->draw_opacity() < 1 || + !finished_target_surface->UsesDefaultBlendMode() || + target_is_only_for_copy_request || + finished_target_surface->Filters().HasFilterThatAffectsOpacity()) { stack_.back().occlusion_from_outside_target.Clear(); stack_.back().occlusion_from_inside_target.Clear(); } @@ -252,13 +259,13 @@ static void ReduceOcclusionBelowSurface( } } -void OcclusionTracker::LeaveToRenderTarget(const LayerImpl* new_target) { +void OcclusionTracker::LeaveToRenderTarget( + const RenderSurfaceImpl* new_target_surface) { DCHECK(!stack_.empty()); size_t last_index = stack_.size() - 1; - DCHECK(new_target->GetRenderSurface()); - RenderSurfaceImpl* new_surface = new_target->GetRenderSurface(); + DCHECK(new_target_surface); bool surface_will_be_at_top_after_pop = - stack_.size() > 1 && stack_[last_index - 1].target == new_surface; + stack_.size() > 1 && stack_[last_index - 1].target == new_target_surface; // We merge the screen occlusion from the current RenderSurfaceImpl subtree // out to its parent target RenderSurfaceImpl. The target occlusion can be @@ -285,23 +292,24 @@ void OcclusionTracker::LeaveToRenderTarget(const LayerImpl* new_target) { surface_occlusion.GetUnoccludedContentRect(old_surface->content_rect()); } + bool is_root = new_target_surface->render_target() == new_target_surface; if (surface_will_be_at_top_after_pop) { // Merge the top of the stack down. stack_[last_index - 1].occlusion_from_inside_target.Union( old_occlusion_from_inside_target_in_new_target); // TODO(danakj): Strictly this should subtract the inside target occlusion // before union. - if (!new_target->layer_tree_impl()->IsRootLayer(new_target)) { + if (!is_root) { stack_[last_index - 1].occlusion_from_outside_target.Union( old_occlusion_from_outside_target_in_new_target); } stack_.pop_back(); } else { // Replace the top of the stack with the new pushed surface. - stack_.back().target = new_surface; + stack_.back().target = new_target_surface; stack_.back().occlusion_from_inside_target = old_occlusion_from_inside_target_in_new_target; - if (!new_target->layer_tree_impl()->IsRootLayer(new_target)) { + if (!is_root) { stack_.back().occlusion_from_outside_target = old_occlusion_from_outside_target_in_new_target; } else { @@ -327,10 +335,6 @@ void OcclusionTracker::MarkOccludedBehindLayer(const LayerImpl* layer) { if (layer->draw_opacity() < 1) return; - // The only currently supported draw_blend_mode is SrcOver mode, so - // draw_blend_mode does not affect occlusion. - DCHECK_EQ(layer->draw_blend_mode(), SkBlendMode::kSrcOver); - if (layer->Is3dSorted()) return; diff --git a/chromium/cc/trees/occlusion_tracker.h b/chromium/cc/trees/occlusion_tracker.h index 13ef757917f..0f360f39313 100644 --- a/chromium/cc/trees/occlusion_tracker.h +++ b/chromium/cc/trees/occlusion_tracker.h @@ -8,9 +8,9 @@ #include <vector> #include "base/macros.h" -#include "cc/base/cc_export.h" #include "cc/base/simple_enclosed_region.h" -#include "cc/layers/layer_iterator.h" +#include "cc/cc_export.h" +#include "cc/layers/effect_tree_layer_list_iterator.h" #include "cc/trees/occlusion.h" #include "ui/gfx/geometry/rect.h" @@ -41,12 +41,12 @@ class CC_EXPORT OcclusionTracker { const gfx::Transform& draw_transform) const; const RenderSurfaceImpl* OcclusionSurfaceForContributingSurface() const; - // Called at the beginning of each step in the LayerIterator's front-to-back - // traversal. - void EnterLayer(const LayerIteratorPosition& layer_iterator); - // Called at the end of each step in the LayerIterator's front-to-back - // traversal. - void LeaveLayer(const LayerIteratorPosition& layer_iterator); + // Called at the beginning of each step in EffectTreeLayerListIterator's + // front-to-back traversal. + void EnterLayer(const EffectTreeLayerListIterator::Position& iterator); + // Called at the end of each step in EffectTreeLayerListIterator's + // front-to-back traversal. + void LeaveLayer(const EffectTreeLayerListIterator::Position& iterator); // Gives the region of the screen that is not occluded by something opaque. Region ComputeVisibleRegionInScreen(const LayerTreeImpl* layer_tree) const; @@ -82,20 +82,20 @@ class CC_EXPORT OcclusionTracker { std::vector<StackObject> stack_; private: - // Called when visiting a layer representing itself. If the target was not - // already current, then this indicates we have entered a new surface subtree. - void EnterRenderTarget(const LayerImpl* new_target); - - // Called when visiting a layer representing a target surface. This indicates - // we have visited all the layers within the surface, and we may perform any - // surface-wide operations. - void FinishedRenderTarget(const LayerImpl* finished_target); - - // Called when visiting a layer representing a contributing surface. This - // indicates that we are leaving our current surface, and entering the new - // one. We then perform any operations required for merging results from the - // child subtree into its parent. - void LeaveToRenderTarget(const LayerImpl* new_target); + // Called when visiting a layer. If the target was not already current, then + // this indicates we have entered a new surface subtree. + void EnterRenderTarget(const RenderSurfaceImpl* new_target_surface); + + // Called when visiting a target surface. This indicates we have visited all + // the layers within the surface, and we may perform any surface-wide + // operations. + void FinishedRenderTarget(const RenderSurfaceImpl* finished_target_surface); + + // Called when visiting a contributing surface. This indicates that we are + // leaving our current surface, and entering the new one. We then perform any + // operations required for merging results from the child subtree into its + // parent. + void LeaveToRenderTarget(const RenderSurfaceImpl* new_target_surface); // Add the layer's occlusion to the tracked state. void MarkOccludedBehindLayer(const LayerImpl* layer); diff --git a/chromium/cc/trees/occlusion_tracker_unittest.cc b/chromium/cc/trees/occlusion_tracker_unittest.cc index 2e0d1b6d92a..8f635a30ccd 100644 --- a/chromium/cc/trees/occlusion_tracker_unittest.cc +++ b/chromium/cc/trees/occlusion_tracker_unittest.cc @@ -7,13 +7,13 @@ #include <stddef.h> #include "cc/animation/animation_host.h" +#include "cc/base/filter_operation.h" +#include "cc/base/filter_operations.h" #include "cc/base/math_util.h" #include "cc/layers/layer.h" #include "cc/layers/layer_impl.h" #include "cc/output/copy_output_request.h" #include "cc/output/copy_output_result.h" -#include "cc/output/filter_operation.h" -#include "cc/output/filter_operations.h" #include "cc/test/animation_test_common.h" #include "cc/test/fake_impl_task_runner_provider.h" #include "cc/test/fake_layer_tree_host.h" @@ -190,7 +190,7 @@ class OcclusionTrackerTest : public testing::Test { host_->host_impl()->active_tree()->SetRootLayerForTesting(nullptr); render_surface_layer_list_impl_.clear(); mask_layers_.clear(); - ResetLayerIterator(); + layer_iterator_.reset(); } void CopyOutputCallback(std::unique_ptr<CopyOutputResult> result) {} @@ -216,28 +216,28 @@ class OcclusionTrackerTest : public testing::Test { // iterations, so rebuild property trees every time. root->layer_tree_impl()->property_trees()->needs_rebuild = true; - FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(root); - LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( root, root->bounds(), &render_surface_layer_list_impl_); inputs.can_adjust_raster_scales = true; LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); - layer_iterator_ = layer_iterator_begin_ = - LayerIterator::Begin(&render_surface_layer_list_impl_); + layer_iterator_ = base::MakeUnique<EffectTreeLayerListIterator>( + host_->host_impl()->active_tree()); } void EnterLayer(LayerImpl* layer, OcclusionTracker* occlusion) { - ASSERT_EQ(*layer_iterator_, layer); - ASSERT_TRUE(layer_iterator_.represents_itself()); - occlusion->EnterLayer(layer_iterator_); + ASSERT_EQ(layer_iterator_->current_layer(), layer); + ASSERT_TRUE(layer_iterator_->state() == + EffectTreeLayerListIterator::State::LAYER); + occlusion->EnterLayer(*layer_iterator_); } void LeaveLayer(LayerImpl* layer, OcclusionTracker* occlusion) { - ASSERT_EQ(*layer_iterator_, layer); - ASSERT_TRUE(layer_iterator_.represents_itself()); - occlusion->LeaveLayer(layer_iterator_); - ++layer_iterator_; + ASSERT_EQ(layer_iterator_->current_layer(), layer); + ASSERT_TRUE(layer_iterator_->state() == + EffectTreeLayerListIterator::State::LAYER); + occlusion->LeaveLayer(*layer_iterator_); + ++(*layer_iterator_); } void VisitLayer(LayerImpl* layer, OcclusionTracker* occlusion) { @@ -246,20 +246,25 @@ class OcclusionTrackerTest : public testing::Test { } void EnterContributingSurface(LayerImpl* layer, OcclusionTracker* occlusion) { - ASSERT_EQ(*layer_iterator_, layer); - ASSERT_TRUE(layer_iterator_.represents_target_render_surface()); - occlusion->EnterLayer(layer_iterator_); - occlusion->LeaveLayer(layer_iterator_); - ++layer_iterator_; - ASSERT_TRUE(layer_iterator_.represents_contributing_render_surface()); - occlusion->EnterLayer(layer_iterator_); + ASSERT_EQ(layer_iterator_->target_render_surface(), + layer->GetRenderSurface()); + ASSERT_TRUE(layer_iterator_->state() == + EffectTreeLayerListIterator::State::TARGET_SURFACE); + occlusion->EnterLayer(*layer_iterator_); + occlusion->LeaveLayer(*layer_iterator_); + ++(*layer_iterator_); + ASSERT_TRUE(layer_iterator_->state() == + EffectTreeLayerListIterator::State::CONTRIBUTING_SURFACE); + occlusion->EnterLayer(*layer_iterator_); } void LeaveContributingSurface(LayerImpl* layer, OcclusionTracker* occlusion) { - ASSERT_EQ(*layer_iterator_, layer); - ASSERT_TRUE(layer_iterator_.represents_contributing_render_surface()); - occlusion->LeaveLayer(layer_iterator_); - ++layer_iterator_; + ASSERT_EQ(layer_iterator_->current_render_surface(), + layer->GetRenderSurface()); + ASSERT_TRUE(layer_iterator_->state() == + EffectTreeLayerListIterator::State::CONTRIBUTING_SURFACE); + occlusion->LeaveLayer(*layer_iterator_); + ++(*layer_iterator_); } void VisitContributingSurface(LayerImpl* layer, OcclusionTracker* occlusion) { @@ -267,7 +272,10 @@ class OcclusionTrackerTest : public testing::Test { LeaveContributingSurface(layer, occlusion); } - void ResetLayerIterator() { layer_iterator_ = layer_iterator_begin_; } + void ResetLayerIterator() { + *layer_iterator_ = + EffectTreeLayerListIterator(host_->host_impl()->active_tree()); + } const gfx::Transform identity_matrix; @@ -298,8 +306,7 @@ class OcclusionTrackerTest : public testing::Test { std::unique_ptr<FakeLayerTreeHost> host_; // These hold ownership of the layers for the duration of the test. LayerImplList render_surface_layer_list_impl_; - LayerIterator layer_iterator_begin_; - LayerIterator layer_iterator_; + std::unique_ptr<EffectTreeLayerListIterator> layer_iterator_; LayerList mask_layers_; int next_layer_impl_id_; }; diff --git a/chromium/cc/trees/property_animation_state.h b/chromium/cc/trees/property_animation_state.h index a171a91c0ed..1b7c07a7ed7 100644 --- a/chromium/cc/trees/property_animation_state.h +++ b/chromium/cc/trees/property_animation_state.h @@ -5,7 +5,7 @@ #ifndef CC_TREES_PROPERTY_ANIMATION_STATE_H_ #define CC_TREES_PROPERTY_ANIMATION_STATE_H_ -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/trees/target_property.h" namespace cc { diff --git a/chromium/cc/trees/property_tree.cc b/chromium/cc/trees/property_tree.cc index af6e451a922..4d1ca75e387 100644 --- a/chromium/cc/trees/property_tree.cc +++ b/chromium/cc/trees/property_tree.cc @@ -48,7 +48,6 @@ TransformTree::TransformTree() device_scale_factor_(1.f), device_transform_scale_factor_(1.f) { cached_data_.push_back(TransformCachedNodeData()); - cached_data_[kRootNodeId].target_id = kRootNodeId; } TransformTree::~TransformTree() = default; @@ -71,6 +70,7 @@ void PropertyTree<T>::clear() { nodes_.push_back(T()); back()->id = kRootNodeId; back()->parent_id = kInvalidNodeId; + owning_layer_id_to_node_index_.clear(); #if DCHECK_IS_ON() PropertyTree<T> tree; @@ -80,7 +80,8 @@ void PropertyTree<T>::clear() { template <typename T> bool PropertyTree<T>::operator==(const PropertyTree<T>& other) const { - return nodes_ == other.nodes() && needs_update_ == other.needs_update(); + return nodes_ == other.nodes() && needs_update_ == other.needs_update() && + owning_layer_id_to_node_index_ == other.owning_layer_id_to_node_index_; } template <typename T> @@ -117,7 +118,6 @@ void TransformTree::clear() { nodes_affected_by_outer_viewport_bounds_delta_.clear(); cached_data_.clear(); cached_data_.push_back(TransformCachedNodeData()); - cached_data_[kRootNodeId].target_id = kRootNodeId; sticky_position_data_.clear(); #if DCHECK_IS_ON() @@ -130,9 +130,9 @@ void TransformTree::clear() { } void TransformTree::set_needs_update(bool needs_update) { - if (needs_update && !needs_update_) + if (needs_update && !PropertyTree<TransformNode>::needs_update()) property_trees()->UpdateTransformTreeUpdateNumber(); - needs_update_ = needs_update; + PropertyTree<TransformNode>::set_needs_update(needs_update); } bool TransformTree::ComputeTranslation(int source_id, @@ -176,21 +176,26 @@ bool TransformTree::ComputeTranslation(int source_id, return true; } -void TransformTree::OnTransformAnimated(const gfx::Transform& transform, - int id, - LayerTreeImpl* layer_tree_impl) { - TransformNode* node = Node(id); - layer_tree_impl->AddToTransformAnimationsMap(node->owning_layer_id, - transform); - if (node->local == transform) { - return; - } +TransformNode* TransformTree::FindNodeFromElementId(ElementId id) { + auto iterator = property_trees()->element_id_to_transform_node_index.find(id); + if (iterator == property_trees()->element_id_to_transform_node_index.end()) + return nullptr; + + return Node(iterator->second); +} + +bool TransformTree::OnTransformAnimated(ElementId element_id, + const gfx::Transform& transform) { + TransformNode* node = FindNodeFromElementId(element_id); + DCHECK(node); + if (node->local == transform) + return false; node->local = transform; node->needs_local_transform_update = true; node->transform_changed = true; property_trees()->changed = true; set_needs_update(true); - layer_tree_impl->set_needs_update_draw_properties(); + return true; } bool TransformTree::NeedsSourceToParentUpdate(TransformNode* node) { @@ -210,7 +215,6 @@ void TransformTree::UpdateTransforms(int id) { TransformNode* node = Node(id); TransformNode* parent_node = parent(node); DCHECK(parent_node); - TransformNode* target_node = Node(TargetId(id)); TransformNode* source_node = Node(node->source_node_id); // TODO(flackr): Only dirty when scroll offset changes. if (node->sticky_position_constraint_id >= 0 || @@ -219,7 +223,7 @@ void TransformTree::UpdateTransforms(int id) { } else { UndoSnapping(node); } - UpdateScreenSpaceTransform(node, parent_node, target_node); + UpdateScreenSpaceTransform(node, parent_node); UpdateAnimationProperties(node, parent_node); UpdateSnapping(node); UpdateNodeAndAncestorsHaveIntegerTranslations(node, parent_node); @@ -346,8 +350,7 @@ bool TransformTree::CombineInversesBetween(int source_id, gfx::Vector2dF StickyPositionOffset(TransformTree* tree, TransformNode* node) { if (node->sticky_position_constraint_id == -1) return gfx::Vector2dF(); - const StickyPositionNodeData* sticky_data = - tree->StickyPositionData(node->id); + StickyPositionNodeData* sticky_data = tree->StickyPositionData(node->id); const LayerStickyPositionConstraint& constraint = sticky_data->constraints; ScrollNode* scroll_node = tree->property_trees()->scroll_tree.Node(sticky_data->scroll_ancestor); @@ -368,10 +371,36 @@ gfx::Vector2dF StickyPositionOffset(TransformTree* tree, TransformNode* node) { scroll_position, gfx::SizeF(tree->property_trees()->scroll_tree.scroll_clip_layer_bounds( scroll_node->id))); - gfx::Vector2dF sticky_offset( - constraint.scroll_container_relative_sticky_box_rect.OffsetFromOrigin()); gfx::Vector2dF layer_offset(sticky_data->main_thread_offset); + gfx::Vector2dF ancestor_sticky_box_offset; + if (sticky_data->nearest_node_shifting_sticky_box != + TransformTree::kInvalidNodeId) { + ancestor_sticky_box_offset = + tree->StickyPositionData(sticky_data->nearest_node_shifting_sticky_box) + ->total_sticky_box_sticky_offset; + } + + gfx::Vector2dF ancestor_containing_block_offset; + if (sticky_data->nearest_node_shifting_containing_block != + TransformTree::kInvalidNodeId) { + ancestor_containing_block_offset = + tree->StickyPositionData( + sticky_data->nearest_node_shifting_containing_block) + ->total_containing_block_sticky_offset; + } + + // Compute the current position of the constraint rects based on the original + // positions and the offsets from ancestor sticky elements. + gfx::RectF sticky_box_rect = + gfx::RectF(constraint.scroll_container_relative_sticky_box_rect) + + ancestor_sticky_box_offset + ancestor_containing_block_offset; + gfx::RectF containing_block_rect = + gfx::RectF(constraint.scroll_container_relative_containing_block_rect) + + ancestor_containing_block_offset; + + gfx::Vector2dF sticky_offset(sticky_box_rect.OffsetFromOrigin()); + // In each of the following cases, we measure the limit which is the point // that the element should stick to, clamping on one side to 0 (because sticky // only pushes elements in one direction). Then we clamp to how far we can @@ -383,55 +412,52 @@ gfx::Vector2dF StickyPositionOffset(TransformTree* tree, TransformNode* node) { // over bottom offset. if (constraint.is_anchored_right) { float right_limit = clip.right() - constraint.right_offset; - float right_delta = std::min<float>( - 0, right_limit - - constraint.scroll_container_relative_sticky_box_rect.right()); - float available_space = std::min<float>( - 0, constraint.scroll_container_relative_containing_block_rect.x() - - constraint.scroll_container_relative_sticky_box_rect.x()); + float right_delta = + std::min<float>(0, right_limit - sticky_box_rect.right()); + float available_space = + std::min<float>(0, containing_block_rect.x() - sticky_box_rect.x()); if (right_delta < available_space) right_delta = available_space; sticky_offset.set_x(sticky_offset.x() + right_delta); } if (constraint.is_anchored_left) { float left_limit = clip.x() + constraint.left_offset; - float left_delta = std::max<float>( - 0, - left_limit - constraint.scroll_container_relative_sticky_box_rect.x()); + float left_delta = std::max<float>(0, left_limit - sticky_box_rect.x()); float available_space = std::max<float>( - 0, constraint.scroll_container_relative_containing_block_rect.right() - - constraint.scroll_container_relative_sticky_box_rect.right()); + 0, containing_block_rect.right() - sticky_box_rect.right()); if (left_delta > available_space) left_delta = available_space; sticky_offset.set_x(sticky_offset.x() + left_delta); } if (constraint.is_anchored_bottom) { float bottom_limit = clip.bottom() - constraint.bottom_offset; - float bottom_delta = std::min<float>( - 0, bottom_limit - - constraint.scroll_container_relative_sticky_box_rect.bottom()); - float available_space = std::min<float>( - 0, constraint.scroll_container_relative_containing_block_rect.y() - - constraint.scroll_container_relative_sticky_box_rect.y()); + float bottom_delta = + std::min<float>(0, bottom_limit - sticky_box_rect.bottom()); + float available_space = + std::min<float>(0, containing_block_rect.y() - sticky_box_rect.y()); if (bottom_delta < available_space) bottom_delta = available_space; sticky_offset.set_y(sticky_offset.y() + bottom_delta); } if (constraint.is_anchored_top) { float top_limit = clip.y() + constraint.top_offset; - float top_delta = std::max<float>( - 0, - top_limit - constraint.scroll_container_relative_sticky_box_rect.y()); + float top_delta = std::max<float>(0, top_limit - sticky_box_rect.y()); float available_space = std::max<float>( - 0, constraint.scroll_container_relative_containing_block_rect.bottom() - - constraint.scroll_container_relative_sticky_box_rect.bottom()); + 0, containing_block_rect.bottom() - sticky_box_rect.bottom()); if (top_delta > available_space) top_delta = available_space; sticky_offset.set_y(sticky_offset.y() + top_delta); } + + sticky_data->total_sticky_box_sticky_offset = + ancestor_sticky_box_offset + sticky_offset - + sticky_box_rect.OffsetFromOrigin(); + sticky_data->total_containing_block_sticky_offset = + ancestor_sticky_box_offset + ancestor_containing_block_offset + + sticky_offset - sticky_box_rect.OffsetFromOrigin(); + return sticky_offset - layer_offset - node->source_to_parent - - constraint.scroll_container_relative_sticky_box_rect - .OffsetFromOrigin(); + sticky_box_rect.OffsetFromOrigin(); } void TransformTree::UpdateLocalTransform(TransformNode* node) { @@ -498,8 +524,7 @@ void TransformTree::UpdateLocalTransform(TransformNode* node) { } void TransformTree::UpdateScreenSpaceTransform(TransformNode* node, - TransformNode* parent_node, - TransformNode* target_node) { + TransformNode* parent_node) { DCHECK(parent_node); gfx::Transform to_screen_space_transform = ToScreen(parent_node->id); if (node->flattens_inherited_transform) @@ -705,26 +730,6 @@ void TransformTree::SetToScreen(int node_id, const gfx::Transform& transform) { cached_data_[node_id].is_showing_backface = transform.IsBackFaceVisible(); } -int TransformTree::TargetId(int node_id) const { - DCHECK(static_cast<int>(cached_data_.size()) > node_id); - return cached_data_[node_id].target_id; -} - -void TransformTree::SetTargetId(int node_id, int target_id) { - DCHECK(static_cast<int>(cached_data_.size()) > node_id); - cached_data_[node_id].target_id = target_id; -} - -int TransformTree::ContentTargetId(int node_id) const { - DCHECK(static_cast<int>(cached_data_.size()) > node_id); - return cached_data_[node_id].content_target_id; -} - -void TransformTree::SetContentTargetId(int node_id, int content_target_id) { - DCHECK(static_cast<int>(cached_data_.size()) > node_id); - cached_data_[node_id].content_target_id = content_target_id; -} - bool TransformTree::operator==(const TransformTree& other) const { return PropertyTree::operator==(other) && source_to_parent_updates_allowed_ == @@ -842,37 +847,59 @@ void EffectTree::UpdateSurfaceContentsScale(EffectNode* effect_node) { transform_tree.Node(effect_node->transform_id); if (transform_node->in_subtree_of_page_scale_layer) layer_scale_factor *= transform_tree.page_scale_factor(); + + // Note: Copy requests currently expect transform to effect output size. + bool use_transform_for_contents_scale = + property_trees()->can_adjust_raster_scales || + effect_node->has_copy_request; effect_node->surface_contents_scale = - MathUtil::ComputeTransform2dScaleComponents( - transform_tree.ToScreen(transform_node->id), layer_scale_factor); + use_transform_for_contents_scale + ? MathUtil::ComputeTransform2dScaleComponents( + transform_tree.ToScreen(transform_node->id), layer_scale_factor) + : gfx::Vector2dF(layer_scale_factor, layer_scale_factor); } -void EffectTree::OnOpacityAnimated(float opacity, - int id, - LayerTreeImpl* layer_tree_impl) { - EffectNode* node = Node(id); - layer_tree_impl->AddToOpacityAnimationsMap(node->owning_layer_id, opacity); +EffectNode* EffectTree::FindNodeFromElementId(ElementId id) { + auto iterator = property_trees()->element_id_to_effect_node_index.find(id); + if (iterator == property_trees()->element_id_to_effect_node_index.end()) + return nullptr; + + return Node(iterator->second); +} + +bool EffectTree::OnOpacityAnimated(ElementId id, float opacity) { + EffectNode* node = FindNodeFromElementId(id); + DCHECK(node); + // TODO(crbug.com/706766): Avoid crash. Need more investigation for what is + // calling this without setting element id. + if (!node) + return false; + if (node->opacity == opacity) - return; + return false; node->opacity = opacity; node->effect_changed = true; property_trees()->changed = true; property_trees()->effect_tree.set_needs_update(true); - layer_tree_impl->set_needs_update_draw_properties(); + return true; } -void EffectTree::OnFilterAnimated(const FilterOperations& filters, - int id, - LayerTreeImpl* layer_tree_impl) { - EffectNode* node = Node(id); - layer_tree_impl->AddToFilterAnimationsMap(node->owning_layer_id, filters); +bool EffectTree::OnFilterAnimated(ElementId id, + const FilterOperations& filters) { + EffectNode* node = FindNodeFromElementId(id); + DCHECK(node); + // TODO(crbug.com/706766): Avoid crash. Need more investigation for what is + // calling this without setting element id. + if (!node) + return false; + if (node->filters == filters) - return; + return false; node->filters = filters; node->effect_changed = true; property_trees()->changed = true; property_trees()->effect_tree.set_needs_update(true); - layer_tree_impl->set_needs_update_draw_properties(); + return true; } void EffectTree::UpdateEffects(int id) { @@ -1580,6 +1607,7 @@ PropertyTreesCachedData::~PropertyTreesCachedData() {} PropertyTrees::PropertyTrees() : needs_rebuild(true), non_root_surfaces_enabled(true), + can_adjust_raster_scales(true), changed(false), full_tree_damaged(false), sequence_number(0), @@ -1597,11 +1625,6 @@ bool PropertyTrees::operator==(const PropertyTrees& other) const { return transform_tree == other.transform_tree && effect_tree == other.effect_tree && clip_tree == other.clip_tree && scroll_tree == other.scroll_tree && - layer_id_to_transform_node_index == - other.layer_id_to_transform_node_index && - layer_id_to_effect_node_index == other.layer_id_to_effect_node_index && - layer_id_to_clip_node_index == other.layer_id_to_clip_node_index && - layer_id_to_scroll_node_index == other.layer_id_to_scroll_node_index && element_id_to_effect_node_index == other.element_id_to_effect_node_index && element_id_to_scroll_node_index == @@ -1615,6 +1638,7 @@ bool PropertyTrees::operator==(const PropertyTrees& other) const { is_main_thread == other.is_main_thread && is_active == other.is_active && non_root_surfaces_enabled == other.non_root_surfaces_enabled && + can_adjust_raster_scales == other.can_adjust_raster_scales && sequence_number == other.sequence_number; } @@ -1623,12 +1647,8 @@ PropertyTrees& PropertyTrees::operator=(const PropertyTrees& from) { effect_tree = from.effect_tree; clip_tree = from.clip_tree; scroll_tree = from.scroll_tree; - layer_id_to_transform_node_index = from.layer_id_to_transform_node_index; - layer_id_to_effect_node_index = from.layer_id_to_effect_node_index; always_use_active_tree_opacity_effect_ids = from.always_use_active_tree_opacity_effect_ids; - layer_id_to_clip_node_index = from.layer_id_to_clip_node_index; - layer_id_to_scroll_node_index = from.layer_id_to_scroll_node_index; element_id_to_effect_node_index = from.element_id_to_effect_node_index; element_id_to_scroll_node_index = from.element_id_to_scroll_node_index; element_id_to_transform_node_index = from.element_id_to_transform_node_index; @@ -1636,6 +1656,7 @@ PropertyTrees& PropertyTrees::operator=(const PropertyTrees& from) { changed = from.changed; full_tree_damaged = from.full_tree_damaged; non_root_surfaces_enabled = from.non_root_surfaces_enabled; + can_adjust_raster_scales = from.can_adjust_raster_scales; sequence_number = from.sequence_number; is_main_thread = from.is_main_thread; is_active = from.is_active; @@ -1658,10 +1679,6 @@ void PropertyTrees::clear() { clip_tree.clear(); effect_tree.clear(); scroll_tree.clear(); - layer_id_to_transform_node_index.clear(); - layer_id_to_effect_node_index.clear(); - layer_id_to_clip_node_index.clear(); - layer_id_to_scroll_node_index.clear(); element_id_to_effect_node_index.clear(); element_id_to_scroll_node_index.clear(); element_id_to_transform_node_index.clear(); @@ -1671,6 +1688,7 @@ void PropertyTrees::clear() { full_tree_damaged = false; changed = false; non_root_surfaces_enabled = true; + can_adjust_raster_scales = true; sequence_number++; #if DCHECK_IS_ON() @@ -1713,46 +1731,25 @@ void PropertyTrees::SetInnerViewportScrollBoundsDelta( void PropertyTrees::PushOpacityIfNeeded(PropertyTrees* target_tree) { for (int id : target_tree->always_use_active_tree_opacity_effect_ids) { - if (layer_id_to_effect_node_index.find(id) == - layer_id_to_effect_node_index.end()) - continue; - EffectNode* source_effect_node = - effect_tree.Node(layer_id_to_effect_node_index[id]); - EffectNode* target_effect_node = target_tree->effect_tree.Node( - target_tree->layer_id_to_effect_node_index[id]); - float source_opacity = source_effect_node->opacity; - float target_opacity = target_effect_node->opacity; - if (source_opacity == target_opacity) - continue; - target_effect_node->opacity = source_opacity; - target_tree->effect_tree.set_needs_update(true); + if (const EffectNode* source_effect_node = + effect_tree.FindNodeFromOwningLayerId(id)) { + EffectNode* target_effect_node = + target_tree->effect_tree.UpdateNodeFromOwningLayerId(id); + float source_opacity = source_effect_node->opacity; + float target_opacity = target_effect_node->opacity; + if (source_opacity == target_opacity) + continue; + target_effect_node->opacity = source_opacity; + target_tree->effect_tree.set_needs_update(true); + } } } void PropertyTrees::RemoveIdFromIdToIndexMaps(int id) { - layer_id_to_transform_node_index.erase(id); - layer_id_to_effect_node_index.erase(id); - layer_id_to_clip_node_index.erase(id); - layer_id_to_scroll_node_index.erase(id); -} - -bool PropertyTrees::IsInIdToIndexMap(TreeType tree_type, int id) { - std::unordered_map<int, int>* id_to_index_map = nullptr; - switch (tree_type) { - case TRANSFORM: - id_to_index_map = &layer_id_to_transform_node_index; - break; - case EFFECT: - id_to_index_map = &layer_id_to_effect_node_index; - break; - case CLIP: - id_to_index_map = &layer_id_to_clip_node_index; - break; - case SCROLL: - id_to_index_map = &layer_id_to_scroll_node_index; - break; - } - return id_to_index_map->find(id) != id_to_index_map->end(); + transform_tree.SetOwningLayerIdForNode(nullptr, id); + clip_tree.SetOwningLayerIdForNode(nullptr, id); + scroll_tree.SetOwningLayerIdForNode(nullptr, id); + effect_tree.SetOwningLayerIdForNode(nullptr, id); } void PropertyTrees::UpdateChangeTracking() { @@ -1983,6 +1980,10 @@ void PropertyTrees::SetAnimationScalesForTesting( bool PropertyTrees::GetToTarget(int transform_id, int effect_id, gfx::Transform* to_target) const { + if (effect_id == EffectTree::kContentsRootNodeId) { + *to_target = transform_tree.ToScreen(transform_id); + return true; + } DrawTransforms& transforms = GetDrawTransforms(transform_id, effect_id); if (transforms.to_valid) { *to_target = transforms.to_target; @@ -2001,6 +2002,12 @@ bool PropertyTrees::GetToTarget(int transform_id, bool PropertyTrees::GetFromTarget(int transform_id, int effect_id, gfx::Transform* from_target) const { + const TransformNode* node = transform_tree.Node(transform_id); + if (node->ancestors_are_invertible && + effect_id == EffectTree::kContentsRootNodeId) { + *from_target = transform_tree.FromScreen(transform_id); + return true; + } DrawTransforms& transforms = GetDrawTransforms(transform_id, effect_id); if (transforms.from_valid) { *from_target = transforms.from_target; @@ -2036,6 +2043,17 @@ DrawTransformData& PropertyTrees::FetchDrawTransformsDataFromCache( return data; } +ClipRectData* PropertyTrees::FetchClipRectFromCache(int clip_id, + int target_id) { + ClipNode* clip_node = clip_tree.Node(clip_id); + for (auto& data : clip_node->cached_clip_rects) { + if (data.target_id == target_id || data.target_id == -1) + return &data; + } + clip_node->cached_clip_rects.push_back(ClipRectData()); + return &clip_node->cached_clip_rects.back(); +} + DrawTransforms& PropertyTrees::GetDrawTransforms(int transform_id, int effect_id) const { const EffectNode* effect_node = effect_tree.Node(effect_id); diff --git a/chromium/cc/trees/property_tree.h b/chromium/cc/trees/property_tree.h index 8c9d158a7bc..de5cc2823de 100644 --- a/chromium/cc/trees/property_tree.h +++ b/chromium/cc/trees/property_tree.h @@ -11,10 +11,11 @@ #include <unordered_map> #include <vector> -#include "cc/base/cc_export.h" +#include "base/containers/flat_map.h" +#include "cc/base/filter_operations.h" #include "cc/base/synced_property.h" +#include "cc/cc_export.h" #include "cc/layers/layer_sticky_position_constraint.h" -#include "cc/output/filter_operations.h" #include "cc/trees/element_id.h" #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/geometry/scroll_offset.h" @@ -53,7 +54,7 @@ class CC_EXPORT PropertyTree { // they are exported by CC_EXPORT. They will be instantiated in every // compilation units that included this header, and compilation can fail // because T may be incomplete. - ~PropertyTree(); + virtual ~PropertyTree(); PropertyTree<T>& operator=(const PropertyTree<T>&); // Property tree node starts from index 0. @@ -82,7 +83,9 @@ class CC_EXPORT PropertyTree { void clear(); size_t size() const { return nodes_.size(); } - void set_needs_update(bool needs_update) { needs_update_ = needs_update; } + virtual void set_needs_update(bool needs_update) { + needs_update_ = needs_update; + } bool needs_update() const { return needs_update_; } std::vector<T>& nodes() { return nodes_; } @@ -97,25 +100,50 @@ class CC_EXPORT PropertyTree { void AsValueInto(base::trace_event::TracedValue* value) const; + const T* FindNodeFromOwningLayerId(int id) const { + return Node(FindNodeIndexFromOwningLayerId(id)); + } + T* UpdateNodeFromOwningLayerId(int id) { + int index = FindNodeIndexFromOwningLayerId(id); + if (index == kInvalidNodeId) { + DCHECK(property_trees()->is_main_thread); + property_trees()->needs_rebuild = true; + } + + return Node(index); + } + + int FindNodeIndexFromOwningLayerId(int id) const { + auto iter = owning_layer_id_to_node_index_.find(id); + if (iter == owning_layer_id_to_node_index_.end()) + return kInvalidNodeId; + else + return iter->second; + } + + void SetOwningLayerIdForNode(const T* node, int id) { + if (!node) { + owning_layer_id_to_node_index_[id] = kInvalidNodeId; + return; + } + + DCHECK(node == Node(node->id)); + owning_layer_id_to_node_index_[id] = node->id; + } + private: std::vector<T> nodes_; - friend class TransformTree; + // Maps from layer id to the property tree node index. This container is + // typically very small and the memory overhead of unordered_map will + // dominate so use a flat_map. See http://crbug.com/709243 + base::flat_map<int, int> owning_layer_id_to_node_index_; + bool needs_update_; PropertyTrees* property_trees_; }; -struct StickyPositionNodeData { - int scroll_ancestor; - LayerStickyPositionConstraint constraints; - - // This is the offset that blink has already applied to counteract the main - // thread scroll offset of the scroll ancestor. We need to account for this - // by computing the additional offset necessary to keep the element stuck. - gfx::Vector2dF main_thread_offset; - - StickyPositionNodeData() : scroll_ancestor(-1) {} -}; +struct StickyPositionNodeData; class CC_EXPORT TransformTree final : public PropertyTree<TransformNode> { public: @@ -126,7 +154,7 @@ class CC_EXPORT TransformTree final : public PropertyTree<TransformNode> { // compilation units that included this header, and compilation can fail // because TransformCachedNodeData may be incomplete. TransformTree(const TransformTree&) = delete; - ~TransformTree(); + ~TransformTree() final; TransformTree& operator=(const TransformTree&); bool operator==(const TransformTree& other) const; @@ -137,9 +165,9 @@ class CC_EXPORT TransformTree final : public PropertyTree<TransformNode> { void clear(); - void OnTransformAnimated(const gfx::Transform& transform, - int id, - LayerTreeImpl* layer_tree_impl); + TransformNode* FindNodeFromElementId(ElementId id); + bool OnTransformAnimated(ElementId element_id, + const gfx::Transform& transform); // Computes the change of basis transform from node |source_id| to |dest_id|. // This is used by scroll children to compute transform from their scroll // parent space (source) to their parent space (destination) and it can atmost @@ -160,7 +188,7 @@ class CC_EXPORT TransformTree final : public PropertyTree<TransformNode> { TransformNode* node, TransformNode* parent_node); - void set_needs_update(bool needs_update); + void set_needs_update(bool needs_update) final; // A TransformNode's source_to_parent value is used to account for the fact // that fixed-position layers are positioned by Blink wrt to their layer tree @@ -254,8 +282,7 @@ class CC_EXPORT TransformTree final : public PropertyTree<TransformNode> { void UpdateLocalTransform(TransformNode* node); void UpdateScreenSpaceTransform(TransformNode* node, - TransformNode* parent_node, - TransformNode* target_node); + TransformNode* parent_node); void UpdateAnimationProperties(TransformNode* node, TransformNode* parent_node); void UndoSnapping(TransformNode* node); @@ -278,6 +305,35 @@ class CC_EXPORT TransformTree final : public PropertyTree<TransformNode> { std::vector<StickyPositionNodeData> sticky_position_data_; }; +struct StickyPositionNodeData { + int scroll_ancestor; + LayerStickyPositionConstraint constraints; + + // This is the offset that blink has already applied to counteract the main + // thread scroll offset of the scroll ancestor. We need to account for this + // by computing the additional offset necessary to keep the element stuck. + gfx::Vector2dF main_thread_offset; + + // In order to properly compute the sticky offset, we need to know if we have + // any sticky ancestors both between ourselves and our containing block and + // between our containing block and the viewport. These ancestors are then + // used to correct the constraining rect locations. + int nearest_node_shifting_sticky_box; + int nearest_node_shifting_containing_block; + + // For performance we cache our accumulated sticky offset to allow descendant + // sticky elements to offset their constraint rects. Because we can either + // affect the sticky box constraint rect or the containing block constraint + // rect, we need to accumulate both. + gfx::Vector2dF total_sticky_box_sticky_offset; + gfx::Vector2dF total_containing_block_sticky_offset; + + StickyPositionNodeData() + : scroll_ancestor(TransformTree::kInvalidNodeId), + nearest_node_shifting_sticky_box(TransformTree::kInvalidNodeId), + nearest_node_shifting_containing_block(TransformTree::kInvalidNodeId) {} +}; + class CC_EXPORT ClipTree final : public PropertyTree<ClipNode> { public: bool operator==(const ClipTree& other) const; @@ -291,7 +347,7 @@ class CC_EXPORT ClipTree final : public PropertyTree<ClipNode> { class CC_EXPORT EffectTree final : public PropertyTree<EffectNode> { public: EffectTree(); - ~EffectTree(); + ~EffectTree() final; EffectTree& operator=(const EffectTree& from); bool operator==(const EffectTree& other) const; @@ -306,10 +362,9 @@ class CC_EXPORT EffectTree final : public PropertyTree<EffectNode> { void UpdateSurfaceContentsScale(EffectNode* node); - void OnOpacityAnimated(float opacity, int id, LayerTreeImpl* layer_tree_impl); - void OnFilterAnimated(const FilterOperations& filters, - int id, - LayerTreeImpl* layer_tree_impl); + EffectNode* FindNodeFromElementId(ElementId id); + bool OnOpacityAnimated(ElementId id, float opacity); + bool OnFilterAnimated(ElementId id, const FilterOperations& filters); void UpdateEffects(int id); @@ -371,7 +426,7 @@ class CC_EXPORT EffectTree final : public PropertyTree<EffectNode> { class CC_EXPORT ScrollTree final : public PropertyTree<ScrollNode> { public: ScrollTree(); - ~ScrollTree(); + ~ScrollTree() final; ScrollTree& operator=(const ScrollTree& from); bool operator==(const ScrollTree& other) const; @@ -548,6 +603,18 @@ struct DrawTransformData { transforms(gfx::Transform(), gfx::Transform()) {} }; +struct ConditionalClip { + bool is_clipped; + gfx::RectF clip_rect; +}; + +struct ClipRectData { + int target_id; + ConditionalClip clip; + + ClipRectData() : target_id(-1) {} +}; + struct PropertyTreesCachedData { int transform_tree_update_number; std::vector<AnimationScaleData> animation_scales; @@ -566,14 +633,6 @@ class CC_EXPORT PropertyTrees final { bool operator==(const PropertyTrees& other) const; PropertyTrees& operator=(const PropertyTrees& from); - // These maps map from layer id to the index for each of the respective - // property node types. - std::unordered_map<int, int> layer_id_to_transform_node_index; - std::unordered_map<int, int> layer_id_to_effect_node_index; - std::unordered_map<int, int> layer_id_to_clip_node_index; - std::unordered_map<int, int> layer_id_to_scroll_node_index; - enum TreeType { TRANSFORM, EFFECT, CLIP, SCROLL }; - // These maps allow mapping directly from a compositor element id to the // respective property node. This will eventually allow simplifying logic in // various places that today has to map from element id to layer id, and then @@ -594,6 +653,7 @@ class CC_EXPORT PropertyTrees final { ScrollTree scroll_tree; bool needs_rebuild; bool non_root_surfaces_enabled; + bool can_adjust_raster_scales; // Change tracking done on property trees needs to be preserved across commits // (when they are not rebuild). We cache a global bool which stores whether // we did any change tracking so that we can skip copying the change status @@ -616,7 +676,6 @@ class CC_EXPORT PropertyTrees final { void SetInnerViewportScrollBoundsDelta(gfx::Vector2dF bounds_delta); void PushOpacityIfNeeded(PropertyTrees* target_tree); void RemoveIdFromIdToIndexMaps(int id); - bool IsInIdToIndexMap(TreeType tree_type, int id); void UpdateChangeTracking(); void PushChangeTrackingTo(PropertyTrees* tree); void ResetAllChangeTracking(); @@ -654,6 +713,8 @@ class CC_EXPORT PropertyTrees final { int transform_id, int effect_id) const; + ClipRectData* FetchClipRectFromCache(int clip_id, int target_id); + private: gfx::Vector2dF inner_viewport_container_bounds_delta_; gfx::Vector2dF outer_viewport_container_bounds_delta_; diff --git a/chromium/cc/trees/property_tree_builder.cc b/chromium/cc/trees/property_tree_builder.cc index ef843d5d989..02fb9bd306c 100644 --- a/chromium/cc/trees/property_tree_builder.cc +++ b/chromium/cc/trees/property_tree_builder.cc @@ -50,7 +50,6 @@ struct DataForRecursion { bool affected_by_outer_viewport_bounds_delta; bool should_flatten; bool is_hidden; - bool apply_ancestor_clip; uint32_t main_thread_scrolling_reasons; bool scroll_tree_parent_created_by_uninheritable_criteria; const gfx::Transform* device_transform; @@ -87,93 +86,6 @@ static LayerStickyPositionConstraint StickyPositionConstraint( return layer->test_properties()->sticky_position_constraint; } -struct PreCalculateMetaInformationRecursiveData { - size_t num_unclipped_descendants; - int num_descendants_that_draw_content; - - PreCalculateMetaInformationRecursiveData() - : num_unclipped_descendants(0), - num_descendants_that_draw_content(0) {} - - void Merge(const PreCalculateMetaInformationRecursiveData& data) { - num_unclipped_descendants += data.num_unclipped_descendants; - num_descendants_that_draw_content += data.num_descendants_that_draw_content; - } -}; - -static inline bool IsRootLayer(const Layer* layer) { - return !layer->parent(); -} - -static bool IsMetaInformationRecomputationNeeded(Layer* layer) { - return layer->layer_tree_host()->needs_meta_info_recomputation(); -} - -// Recursively walks the layer tree(if needed) to compute any information -// that is needed before doing the main recursion. -static void PreCalculateMetaInformationInternal( - Layer* layer, - PreCalculateMetaInformationRecursiveData* recursive_data) { - if (!IsMetaInformationRecomputationNeeded(layer)) { - DCHECK(IsRootLayer(layer)); - return; - } - - if (layer->clip_parent()) - recursive_data->num_unclipped_descendants++; - - for (size_t i = 0; i < layer->children().size(); ++i) { - Layer* child_layer = layer->child_at(i); - - PreCalculateMetaInformationRecursiveData data_for_child; - PreCalculateMetaInformationInternal(child_layer, &data_for_child); - recursive_data->Merge(data_for_child); - } - - if (layer->clip_children()) { - size_t num_clip_children = layer->clip_children()->size(); - DCHECK_GE(recursive_data->num_unclipped_descendants, num_clip_children); - recursive_data->num_unclipped_descendants -= num_clip_children; - } - - layer->set_num_unclipped_descendants( - recursive_data->num_unclipped_descendants); - - if (IsRootLayer(layer)) - layer->layer_tree_host()->SetNeedsMetaInfoRecomputation(false); -} - -static void PreCalculateMetaInformationInternalForTesting( - LayerImpl* layer, - PreCalculateMetaInformationRecursiveData* recursive_data) { - if (layer->test_properties()->clip_parent) - recursive_data->num_unclipped_descendants++; - - for (size_t i = 0; i < layer->test_properties()->children.size(); ++i) { - LayerImpl* child_layer = layer->test_properties()->children[i]; - - PreCalculateMetaInformationRecursiveData data_for_child; - PreCalculateMetaInformationInternalForTesting(child_layer, &data_for_child); - recursive_data->Merge(data_for_child); - } - - if (layer->test_properties()->clip_children) { - size_t num_clip_children = layer->test_properties()->clip_children->size(); - DCHECK_GE(recursive_data->num_unclipped_descendants, num_clip_children); - recursive_data->num_unclipped_descendants -= num_clip_children; - } - - layer->test_properties()->num_unclipped_descendants = - recursive_data->num_unclipped_descendants; - // TODO(enne): this should be synced from the main thread, so is only - // for tests constructing layers on the compositor thread. - layer->test_properties()->num_descendants_that_draw_content = - recursive_data->num_descendants_that_draw_content; - - if (layer->DrawsContent()) - recursive_data->num_descendants_that_draw_content++; -} - static LayerImplList& Children(LayerImpl* layer) { return layer->test_properties()->children; } @@ -214,14 +126,6 @@ static LayerImpl* ClipParent(LayerImpl* layer) { return layer->test_properties()->clip_parent; } -static size_t NumUnclippedDescendants(Layer* layer) { - return layer->num_unclipped_descendants(); -} - -static size_t NumUnclippedDescendants(LayerImpl* layer) { - return layer->test_properties()->num_unclipped_descendants; -} - static inline const FilterOperations& Filters(Layer* layer) { return layer->filters(); } @@ -246,6 +150,12 @@ static const gfx::Transform& Transform(LayerImpl* layer) { return layer->test_properties()->transform; } +static void SetIsScrollClipLayer(Layer* layer) { + layer->set_is_scroll_clip_layer(); +} + +static void SetIsScrollClipLayer(LayerImpl* layer) {} + // Methods to query state from the AnimationHost ---------------------- template <typename LayerType> bool OpacityIsAnimating(LayerType* layer) { @@ -334,86 +244,36 @@ static LayerImpl* Parent(LayerImpl* layer) { return layer->test_properties()->parent; } -template <typename LayerType> -static void SetSurfaceIsClipped(DataForRecursion<LayerType>* data_for_children, - bool apply_ancestor_clip, - LayerType* layer) { - // A surface with unclipped descendants cannot be clipped by its ancestor - // clip at draw time since the unclipped descendants aren't affected by the - // ancestor clip. - EffectNode* effect_node = data_for_children->property_trees->effect_tree.Node( - data_for_children->render_target); - DCHECK_EQ(effect_node->owning_layer_id, layer->id()); - effect_node->surface_is_clipped = - apply_ancestor_clip && !NumUnclippedDescendants(layer); - // The ancestor clip should propagate to children only if the surface doesn't - // apply the clip. - data_for_children->apply_ancestor_clip = - apply_ancestor_clip && !effect_node->surface_is_clipped; +static inline int SortingContextId(Layer* layer) { + return layer->sorting_context_id(); +} + +static inline int SortingContextId(LayerImpl* layer) { + return layer->test_properties()->sorting_context_id; +} + +static inline bool Is3dSorted(Layer* layer) { + return layer->Is3dSorted(); +} + +static inline bool Is3dSorted(LayerImpl* layer) { + return layer->test_properties()->sorting_context_id != 0; } template <typename LayerType> void AddClipNodeIfNeeded(const DataForRecursion<LayerType>& data_from_ancestor, LayerType* layer, - bool created_render_surface, bool created_transform_node, DataForRecursion<LayerType>* data_for_children) { const bool inherits_clip = !ClipParent(layer); const int parent_id = inherits_clip ? data_from_ancestor.clip_tree_parent : ClipParent(layer)->clip_tree_index(); - ClipNode* parent = - data_from_ancestor.property_trees->clip_tree.Node(parent_id); - - bool apply_ancestor_clip = inherits_clip - ? data_from_ancestor.apply_ancestor_clip - : parent->layers_are_clipped; - - bool layers_are_clipped = false; - bool has_unclipped_surface = false; - - if (created_render_surface) { - SetSurfaceIsClipped(data_for_children, apply_ancestor_clip, layer); - // Clips can usually be applied to a surface's descendants simply by - // clipping the surface (or applied implicitly by the surface's bounds). - // However, if the surface has unclipped descendants (layers that aren't - // affected by the ancestor clip), we cannot clip the surface itself, and - // must instead apply clips to the clipped descendants. - if (apply_ancestor_clip && NumUnclippedDescendants(layer) > 0) { - layers_are_clipped = true; - } else if (!apply_ancestor_clip) { - // When there are no ancestor clips that need to be applied to a render - // surface, we reset clipping state. The surface might contribute a clip - // of its own, but clips from ancestor nodes don't need to be considered - // when computing clip rects or visibility. - has_unclipped_surface = true; - DCHECK_NE(parent->clip_type, ClipNode::ClipType::APPLIES_LOCAL_CLIP); - } - } else { - // Without a new render surface, layer clipping state from ancestors needs - // to continue to propagate. - layers_are_clipped = apply_ancestor_clip; - } bool layer_clips_subtree = LayerClipsSubtree(layer); - if (layer_clips_subtree) { - layers_are_clipped = true; - data_for_children->apply_ancestor_clip = true; - } - - // Without surfaces, all non-viewport clips have to be applied using layer - // clipping. - bool layers_are_clipped_when_surfaces_disabled = - layer_clips_subtree || parent->layers_are_clipped_when_surfaces_disabled; - - // Render surface's clip is needed during hit testing. So, we need to create - // a clip node for every render surface. - bool requires_node = layer_clips_subtree || created_render_surface; - + bool requires_node = + layer_clips_subtree || Filters(layer).HasFilterThatMovesPixels(); if (!requires_node) { data_for_children->clip_tree_parent = parent_id; - DCHECK_EQ(layers_are_clipped, parent->layers_are_clipped); - DCHECK_EQ(layers_are_clipped_when_surfaces_disabled, - parent->layers_are_clipped_when_surfaces_disabled); } else { LayerType* transform_parent = data_for_children->transform_tree_parent; if (PositionConstraint(layer).is_fixed_position() && @@ -424,64 +284,24 @@ void AddClipNodeIfNeeded(const DataForRecursion<LayerType>& data_from_ancestor, node.clip = gfx::RectF(gfx::PointF() + layer->offset_to_transform_parent(), gfx::SizeF(layer->bounds())); node.transform_id = transform_parent->transform_tree_index(); - node.target_effect_id = data_for_children->render_target; - node.target_transform_id = data_for_children->property_trees->effect_tree - .Node(data_for_children->render_target) - ->transform_id; node.owning_layer_id = layer->id(); - - if (apply_ancestor_clip || layer_clips_subtree) { - // Surfaces reset the rect used for layer clipping. At other nodes, layer - // clipping state from ancestors must continue to get propagated. - node.layer_clipping_uses_only_local_clip = - (created_render_surface && NumUnclippedDescendants(layer) == 0) || - !apply_ancestor_clip; - } else { - // Otherwise, we're either unclipped, or exist only in order to apply our - // parent's clips in our space. - node.layer_clipping_uses_only_local_clip = false; - } - if (layer_clips_subtree) { node.clip_type = ClipNode::ClipType::APPLIES_LOCAL_CLIP; - } else if (Filters(layer).HasFilterThatMovesPixels()) { + } else { + DCHECK(Filters(layer).HasFilterThatMovesPixels()); node.clip_type = ClipNode::ClipType::EXPANDS_CLIP; node.clip_expander = base::MakeUnique<ClipExpander>(layer->effect_tree_index()); - } else { - node.clip_type = ClipNode::ClipType::NONE; } - node.resets_clip = has_unclipped_surface; - node.layers_are_clipped = layers_are_clipped; - node.layers_are_clipped_when_surfaces_disabled = - layers_are_clipped_when_surfaces_disabled; - data_for_children->clip_tree_parent = data_for_children->property_trees->clip_tree.Insert(node, parent_id); - data_for_children->property_trees - ->layer_id_to_clip_node_index[layer->id()] = - data_for_children->clip_tree_parent; + data_for_children->property_trees->clip_tree.SetOwningLayerIdForNode( + data_for_children->property_trees->clip_tree.back(), layer->id()); } layer->SetClipTreeIndex(data_for_children->clip_tree_parent); } -static inline int SortingContextId(Layer* layer) { - return layer->sorting_context_id(); -} - -static inline int SortingContextId(LayerImpl* layer) { - return layer->test_properties()->sorting_context_id; -} - -static inline bool Is3dSorted(Layer* layer) { - return layer->Is3dSorted(); -} - -static inline bool Is3dSorted(LayerImpl* layer) { - return layer->test_properties()->sorting_context_id != 0; -} - template <typename LayerType> static inline bool IsAtBoundaryOf3dRenderingContext(LayerType* layer) { return Parent(layer) @@ -565,29 +385,21 @@ bool AddTransformNodeIfNeeded( scroll_child_has_different_target || is_sticky || is_at_boundary_of_3d_rendering_context; - LayerType* transform_parent = GetTransformParent(data_from_ancestor, layer); - DCHECK(is_root || transform_parent); - int parent_index = TransformTree::kRootNodeId; - if (transform_parent) - parent_index = transform_parent->transform_tree_index(); + int source_index = TransformTree::kRootNodeId; + gfx::Vector2dF source_offset; - int source_index = parent_index; + LayerType* transform_parent = GetTransformParent(data_from_ancestor, layer); + DCHECK_EQ(is_root, !transform_parent); - gfx::Vector2dF source_offset; if (transform_parent) { - if (ScrollParent(layer)) { - LayerType* source = Parent(layer); - source_offset += source->offset_to_transform_parent(); - source_index = source->transform_tree_index(); - } else if (!is_fixed) { - source_offset = transform_parent->offset_to_transform_parent(); - } else { - source_offset = data_from_ancestor.transform_tree_parent - ->offset_to_transform_parent(); - source_index = - data_from_ancestor.transform_tree_parent->transform_tree_index(); - } + parent_index = transform_parent->transform_tree_index(); + // Because Blink still provides positions with respect to the parent layer, + // we track both a parent TransformNode (which is the parent in the + // TransformTree) and a 'source' TransformNode (which is the TransformNode + // for the parent in the Layer tree). + source_index = Parent(layer)->transform_tree_index(); + source_offset = Parent(layer)->offset_to_transform_parent(); } if (IsContainerForFixedPositionLayers(layer) || is_root) { @@ -630,8 +442,8 @@ bool AddTransformNodeIfNeeded( TransformNode* node = data_for_children->property_trees->transform_tree.back(); layer->SetTransformTreeIndex(node->id); - data_for_children->property_trees - ->layer_id_to_transform_node_index[layer->id()] = node->id; + data_for_children->property_trees->transform_tree.SetOwningLayerIdForNode( + node, layer->id()); // For animation subsystem purposes, if this layer has a compositor element // id, we build a map from that id to this transform node. @@ -656,18 +468,6 @@ bool AddTransformNodeIfNeeded( ShouldFlattenTransform(layer) || has_surface; DCHECK_GT(data_from_ancestor.property_trees->effect_tree.size(), 0u); - data_for_children->property_trees->transform_tree.SetTargetId( - node->id, data_for_children->property_trees->effect_tree - .Node(data_from_ancestor.render_target) - ->transform_id); - data_for_children->property_trees->transform_tree.SetContentTargetId( - node->id, data_for_children->property_trees->effect_tree - .Node(data_for_children->render_target) - ->transform_id); - DCHECK_NE( - data_for_children->property_trees->transform_tree.TargetId(node->id), - TransformTree::kInvalidNodeId); - node->has_potential_animation = has_potentially_animated_transform; node->is_currently_animating = TransformIsAnimating(layer); if (has_potentially_animated_transform) { @@ -759,10 +559,36 @@ bool AddTransformNodeIfNeeded( .AddNodeAffectedByOuterViewportBoundsDelta(node->id); } } + // TODO(smcgruer): Pass main thread sticky-shifting offsets of + // non-promoted ancestors, or promote all ancestor sticky elements. + // See http://crbug.com/702229 sticky_data->main_thread_offset = layer->position().OffsetFromOrigin() - sticky_data->constraints.parent_relative_sticky_box_offset .OffsetFromOrigin(); + + // Copy the ancestor nodes for later use. These layers are guaranteed to + // have transform nodes at this point because they are our ancestors (so + // have already been processed) and are sticky (so have transform nodes). + int shifting_sticky_box_layer_id = + sticky_data->constraints.nearest_layer_shifting_sticky_box; + if (shifting_sticky_box_layer_id != Layer::INVALID_ID) { + sticky_data->nearest_node_shifting_sticky_box = + data_for_children->property_trees->transform_tree + .FindNodeIndexFromOwningLayerId(shifting_sticky_box_layer_id); + DCHECK(sticky_data->nearest_node_shifting_sticky_box != + TransformTree::kInvalidNodeId); + } + int shifting_containing_block_layer_id = + sticky_data->constraints.nearest_layer_shifting_containing_block; + if (shifting_containing_block_layer_id != Layer::INVALID_ID) { + sticky_data->nearest_node_shifting_containing_block = + data_for_children->property_trees->transform_tree + .FindNodeIndexFromOwningLayerId( + shifting_containing_block_layer_id); + DCHECK(sticky_data->nearest_node_shifting_containing_block != + TransformTree::kInvalidNodeId); + } } node->needs_local_transform_update = true; @@ -822,8 +648,24 @@ static inline int NumDescendantsThatDrawContent(Layer* layer) { return layer->NumDescendantsThatDrawContent(); } +static inline int NumLayerOrDescendantsThatDrawContentRecursive( + LayerImpl* layer) { + int num = layer->DrawsContent() ? 1 : 0; + for (size_t i = 0; i < layer->test_properties()->children.size(); ++i) { + LayerImpl* child_layer = layer->test_properties()->children[i]; + num += NumLayerOrDescendantsThatDrawContentRecursive(child_layer); + } + return num; +} + static inline int NumDescendantsThatDrawContent(LayerImpl* layer) { - return layer->test_properties()->num_descendants_that_draw_content; + int num_descendants_that_draw_content = 0; + for (size_t i = 0; i < layer->test_properties()->children.size(); ++i) { + LayerImpl* child_layer = layer->test_properties()->children[i]; + num_descendants_that_draw_content += + NumLayerOrDescendantsThatDrawContentRecursive(child_layer); + } + return num_descendants_that_draw_content; } static inline float EffectiveOpacity(Layer* layer) { @@ -1088,7 +930,6 @@ bool AddEffectNodeIfNeeded( // transform id. node.transform_id = data_from_ancestor.property_trees->transform_tree.next_available_id(); - node.has_unclipped_descendants = (NumUnclippedDescendants(layer) != 0); } node.clip_id = data_from_ancestor.clip_tree_parent; } else { @@ -1102,8 +943,8 @@ bool AddEffectNodeIfNeeded( int node_id = effect_tree.Insert(node, parent_id); data_for_children->effect_tree_parent = node_id; layer->SetEffectTreeIndex(node_id); - data_for_children->property_trees - ->layer_id_to_effect_node_index[layer->id()] = node_id; + data_for_children->property_trees->effect_tree.SetOwningLayerIdForNode( + effect_tree.back(), layer->id()); // For animation subsystem purposes, if this layer has a compositor element // id, we build a map from that id to this effect node. @@ -1165,13 +1006,14 @@ void AddScrollNodeIfNeeded( node.main_thread_scrolling_reasons = main_thread_scrolling_reasons; node.non_fast_scrollable_region = layer->non_fast_scrollable_region(); gfx::Size clip_bounds; - if (layer->scroll_clip_layer()) { - clip_bounds = layer->scroll_clip_layer()->bounds(); - DCHECK(layer->scroll_clip_layer()->transform_tree_index() != + if (LayerType* scroll_clip_layer = layer->scroll_clip_layer()) { + SetIsScrollClipLayer(scroll_clip_layer); + clip_bounds = scroll_clip_layer->bounds(); + DCHECK(scroll_clip_layer->transform_tree_index() != TransformTree::kInvalidNodeId); node.max_scroll_offset_affected_by_page_scale = !data_from_ancestor.property_trees->transform_tree - .Node(layer->scroll_clip_layer()->transform_tree_index()) + .Node(scroll_clip_layer->transform_tree_index()) ->in_subtree_of_page_scale_layer && data_from_ancestor.in_subtree_of_page_scale_layer; } @@ -1198,8 +1040,8 @@ void AddScrollNodeIfNeeded( node.main_thread_scrolling_reasons; data_for_children->scroll_tree_parent_created_by_uninheritable_criteria = scroll_node_uninheritable_criteria; - data_for_children->property_trees - ->layer_id_to_scroll_node_index[layer->id()] = node_id; + data_for_children->property_trees->scroll_tree.SetOwningLayerIdForNode( + data_for_children->property_trees->scroll_tree.back(), layer->id()); // For animation subsystem purposes, if this layer has a compositor element // id, we build a map from that id to this scroll node. if (layer->element_id()) { @@ -1288,17 +1130,13 @@ void BuildPropertyTreesInternal( bool created_render_surface = AddEffectNodeIfNeeded(data_from_parent, layer, &data_for_children); - if (created_render_surface) { + if (created_render_surface) data_for_children.render_target = data_for_children.effect_tree_parent; - layer->set_draw_blend_mode(SkBlendMode::kSrcOver); - } else { - layer->set_draw_blend_mode(BlendMode(layer)); - } bool created_transform_node = AddTransformNodeIfNeeded( data_from_parent, layer, created_render_surface, &data_for_children); - AddClipNodeIfNeeded(data_from_parent, layer, created_render_surface, - created_transform_node, &data_for_children); + AddClipNodeIfNeeded(data_from_parent, layer, created_transform_node, + &data_for_children); AddScrollNodeIfNeeded(data_from_parent, layer, &data_for_children); @@ -1359,18 +1197,6 @@ void BuildPropertyTreesInternal( } // namespace -void CC_EXPORT -PropertyTreeBuilder::PreCalculateMetaInformation(Layer* root_layer) { - PreCalculateMetaInformationRecursiveData recursive_data; - PreCalculateMetaInformationInternal(root_layer, &recursive_data); -} - -void CC_EXPORT PropertyTreeBuilder::PreCalculateMetaInformationForTesting( - LayerImpl* root_layer) { - PreCalculateMetaInformationRecursiveData recursive_data; - PreCalculateMetaInformationInternalForTesting(root_layer, &recursive_data); -} - Layer* PropertyTreeBuilder::FindFirstScrollableLayer(Layer* layer) { if (!layer) return nullptr; @@ -1435,8 +1261,6 @@ void BuildPropertyTreesTopLevelInternal( data_for_recursion.affected_by_outer_viewport_bounds_delta = false; data_for_recursion.should_flatten = false; data_for_recursion.is_hidden = false; - // The root clip is always applied. - data_for_recursion.apply_ancestor_clip = true; data_for_recursion.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollingOnMain; data_for_recursion.scroll_tree_parent_created_by_uninheritable_criteria = @@ -1451,11 +1275,9 @@ void BuildPropertyTreesTopLevelInternal( data_for_recursion.safe_opaque_background_color = color; ClipNode root_clip; - root_clip.resets_clip = true; root_clip.clip_type = ClipNode::ClipType::APPLIES_LOCAL_CLIP; root_clip.clip = gfx::RectF(viewport); root_clip.transform_id = TransformTree::kRootNodeId; - root_clip.target_transform_id = TransformTree::kRootNodeId; data_for_recursion.clip_tree_parent = data_for_recursion.property_trees->clip_tree.Insert( root_clip, ClipTree::kRootNodeId); diff --git a/chromium/cc/trees/property_tree_builder.h b/chromium/cc/trees/property_tree_builder.h index d4b4eefab94..4418f94ee57 100644 --- a/chromium/cc/trees/property_tree_builder.h +++ b/chromium/cc/trees/property_tree_builder.h @@ -16,10 +16,6 @@ class PropertyTreeBuilder { public: static Layer* FindFirstScrollableLayer(Layer* root_layer); - static void CC_EXPORT PreCalculateMetaInformation(Layer* root_layer); - static void CC_EXPORT - PreCalculateMetaInformationForTesting(LayerImpl* root_layer); - static void CC_EXPORT BuildPropertyTrees(Layer* root_layer, const Layer* page_scale_layer, @@ -32,17 +28,18 @@ class PropertyTreeBuilder { const gfx::Rect& viewport, const gfx::Transform& device_transform, PropertyTrees* property_trees); - static void BuildPropertyTrees(LayerImpl* root_layer, - const LayerImpl* page_scale_layer, - const LayerImpl* inner_viewport_scroll_layer, - const LayerImpl* outer_viewport_scroll_layer, - const LayerImpl* overscroll_elasticity_layer, - const gfx::Vector2dF& elastic_overscroll, - float page_scale_factor, - float device_scale_factor, - const gfx::Rect& viewport, - const gfx::Transform& device_transform, - PropertyTrees* property_trees); + static void CC_EXPORT + BuildPropertyTrees(LayerImpl* root_layer, + const LayerImpl* page_scale_layer, + const LayerImpl* inner_viewport_scroll_layer, + const LayerImpl* outer_viewport_scroll_layer, + const LayerImpl* overscroll_elasticity_layer, + const gfx::Vector2dF& elastic_overscroll, + float page_scale_factor, + float device_scale_factor, + const gfx::Rect& viewport, + const gfx::Transform& device_transform, + PropertyTrees* property_trees); }; } // namespace cc diff --git a/chromium/cc/trees/property_tree_unittest.cc b/chromium/cc/trees/property_tree_unittest.cc index 40113d30f79..1c0c37692fc 100644 --- a/chromium/cc/trees/property_tree_unittest.cc +++ b/chromium/cc/trees/property_tree_unittest.cc @@ -23,7 +23,6 @@ TEST(PropertyTreeTest, ComputeTransformRoot) { contents_root.local.Translate(2, 2); contents_root.source_node_id = 0; contents_root.id = tree.Insert(contents_root, 0); - tree.SetTargetId(contents_root.id, 0); tree.UpdateTransforms(1); gfx::Transform expected; @@ -46,7 +45,6 @@ TEST(PropertyTreeTest, SetNeedsUpdate) { TransformNode contents_root; contents_root.source_node_id = 0; contents_root.id = tree.Insert(contents_root, 0); - tree.SetTargetId(contents_root.id, 0); EXPECT_FALSE(tree.needs_update()); tree.SetRootTransformsAndScales(0.6f, 1.f, gfx::Transform(), gfx::PointF()); @@ -63,14 +61,12 @@ TEST(PropertyTreeTest, ComputeTransformChild) { contents_root.local.Translate(2, 2); contents_root.source_node_id = 0; contents_root.id = tree.Insert(contents_root, 0); - tree.SetTargetId(contents_root.id, 0); tree.UpdateTransforms(contents_root.id); TransformNode child; child.local.Translate(3, 3); child.source_node_id = 1; child.id = tree.Insert(child, contents_root.id); - tree.SetTargetId(child.id, 0); tree.UpdateTransforms(child.id); @@ -109,20 +105,17 @@ TEST(PropertyTreeTest, ComputeTransformSibling) { contents_root.source_node_id = 0; contents_root.local.Translate(2, 2); contents_root.id = tree.Insert(contents_root, 0); - tree.SetTargetId(contents_root.id, 0); tree.UpdateTransforms(1); TransformNode child; child.local.Translate(3, 3); child.source_node_id = 1; child.id = tree.Insert(child, 1); - tree.SetTargetId(child.id, 0); TransformNode sibling; sibling.local.Translate(7, 7); sibling.source_node_id = 1; sibling.id = tree.Insert(sibling, 1); - tree.SetTargetId(sibling.id, 0); tree.UpdateTransforms(2); tree.UpdateTransforms(3); @@ -158,26 +151,22 @@ TEST(PropertyTreeTest, ComputeTransformSiblingSingularAncestor) { contents_root.local.Translate(2, 2); contents_root.source_node_id = 0; contents_root.id = tree.Insert(contents_root, 0); - tree.SetTargetId(contents_root.id, 0); tree.UpdateTransforms(1); TransformNode singular; singular.local.matrix().set(2, 2, 0.0); singular.source_node_id = 1; singular.id = tree.Insert(singular, 1); - tree.SetTargetId(singular.id, 0); TransformNode child; child.local.Translate(3, 3); child.source_node_id = 2; child.id = tree.Insert(child, 2); - tree.SetTargetId(child.id, 0); TransformNode sibling; sibling.local.Translate(7, 7); sibling.source_node_id = 2; sibling.id = tree.Insert(sibling, 2); - tree.SetTargetId(sibling.id, 0); tree.UpdateTransforms(2); tree.UpdateTransforms(3); @@ -209,8 +198,6 @@ TEST(PropertyTreeTest, TransformsWithFlattening) { effect_tree.Node(effect_grand_parent)->transform_id = grand_parent; effect_tree.Node(effect_grand_parent)->surface_contents_scale = gfx::Vector2dF(1.f, 1.f); - tree.SetContentTargetId(grand_parent, grand_parent); - tree.SetTargetId(grand_parent, grand_parent); tree.Node(grand_parent)->source_node_id = 0; gfx::Transform rotation_about_x; @@ -222,21 +209,15 @@ TEST(PropertyTreeTest, TransformsWithFlattening) { effect_tree.Node(effect_parent)->has_render_surface = true; effect_tree.Node(effect_parent)->surface_contents_scale = gfx::Vector2dF(1.f, 1.f); - tree.SetTargetId(parent, grand_parent); - tree.SetContentTargetId(parent, parent); tree.Node(parent)->source_node_id = grand_parent; tree.Node(parent)->local = rotation_about_x; int child = tree.Insert(TransformNode(), parent); - tree.SetTargetId(child, parent); - tree.SetContentTargetId(child, parent); tree.Node(child)->source_node_id = parent; tree.Node(child)->flattens_inherited_transform = true; tree.Node(child)->local = rotation_about_x; int grand_child = tree.Insert(TransformNode(), child); - tree.SetTargetId(grand_child, parent); - tree.SetContentTargetId(grand_child, parent); tree.Node(grand_child)->source_node_id = child; tree.Node(grand_child)->flattens_inherited_transform = true; tree.Node(grand_child)->local = rotation_about_x; @@ -293,14 +274,12 @@ TEST(PropertyTreeTest, MultiplicationOrder) { contents_root.local.Translate(2, 2); contents_root.source_node_id = 0; contents_root.id = tree.Insert(contents_root, 0); - tree.SetTargetId(contents_root.id, 0); tree.UpdateTransforms(1); TransformNode child; child.local.Scale(2, 2); child.source_node_id = 1; child.id = tree.Insert(child, 1); - tree.SetTargetId(child.id, 0); tree.UpdateTransforms(2); @@ -328,14 +307,12 @@ TEST(PropertyTreeTest, ComputeTransformWithUninvertibleTransform) { TransformNode contents_root; contents_root.source_node_id = 0; contents_root.id = tree.Insert(contents_root, 0); - tree.SetTargetId(contents_root.id, 0); tree.UpdateTransforms(1); TransformNode child; child.local.Scale(0, 0); child.source_node_id = 1; child.id = tree.Insert(child, 1); - tree.SetTargetId(child.id, 0); tree.UpdateTransforms(2); @@ -360,31 +337,24 @@ TEST(PropertyTreeTest, ComputeTransformToTargetWithZeroSurfaceContentsScale) { TransformNode contents_root; contents_root.source_node_id = 0; contents_root.id = tree.Insert(contents_root, 0); - tree.SetTargetId(contents_root.id, 0); tree.UpdateTransforms(1); TransformNode grand_parent; grand_parent.local.Scale(2.f, 0.f); grand_parent.source_node_id = 1; int grand_parent_id = tree.Insert(grand_parent, 1); - tree.SetTargetId(grand_parent_id, 0); - tree.SetContentTargetId(grand_parent_id, grand_parent_id); tree.UpdateTransforms(grand_parent_id); TransformNode parent; parent.local.Translate(1.f, 1.f); parent.source_node_id = grand_parent_id; int parent_id = tree.Insert(parent, grand_parent_id); - tree.SetTargetId(parent_id, grand_parent_id); - tree.SetContentTargetId(parent_id, grand_parent_id); tree.UpdateTransforms(parent_id); TransformNode child; child.local.Translate(3.f, 4.f); child.source_node_id = parent_id; int child_id = tree.Insert(child, parent_id); - tree.SetTargetId(child_id, grand_parent_id); - tree.SetContentTargetId(child_id, grand_parent_id); tree.UpdateTransforms(child_id); gfx::Transform expected_transform; @@ -425,8 +395,6 @@ TEST(PropertyTreeTest, FlatteningWhenDestinationHasOnlyFlatAncestors) { TransformTree& tree = property_trees.transform_tree; int parent = tree.Insert(TransformNode(), 0); - tree.SetContentTargetId(parent, parent); - tree.SetTargetId(parent, parent); tree.Node(parent)->source_node_id = 0; tree.Node(parent)->local.Translate(2, 2); @@ -434,14 +402,10 @@ TEST(PropertyTreeTest, FlatteningWhenDestinationHasOnlyFlatAncestors) { rotation_about_x.RotateAboutXAxis(15); int child = tree.Insert(TransformNode(), parent); - tree.SetContentTargetId(child, child); - tree.SetTargetId(child, child); tree.Node(child)->source_node_id = parent; tree.Node(child)->local = rotation_about_x; int grand_child = tree.Insert(TransformNode(), child); - tree.SetContentTargetId(grand_child, grand_child); - tree.SetTargetId(grand_child, grand_child); tree.Node(grand_child)->source_node_id = child; tree.Node(grand_child)->flattens_inherited_transform = true; @@ -485,12 +449,10 @@ TEST(PropertyTreeTest, NonIntegerTranslationTest) { TransformTree& tree = property_trees.transform_tree; int parent = tree.Insert(TransformNode(), 0); - tree.SetTargetId(parent, parent); tree.Node(parent)->source_node_id = 0; tree.Node(parent)->local.Translate(1.5f, 1.5f); int child = tree.Insert(TransformNode(), parent); - tree.SetTargetId(child, parent); tree.Node(child)->local.Translate(1, 1); tree.Node(child)->source_node_id = parent; tree.set_needs_update(true); @@ -513,7 +475,6 @@ TEST(PropertyTreeTest, NonIntegerTranslationTest) { tree.Node(child)->local.Translate(0.5f, 0.5f); tree.Node(child)->needs_local_transform_update = true; - tree.SetTargetId(child, child); tree.set_needs_update(true); draw_property_utils::ComputeTransforms(&tree); EXPECT_TRUE( @@ -534,13 +495,11 @@ TEST(PropertyTreeTest, SingularTransformSnapTest) { effect_tree.Node(effect_parent)->has_render_surface = true; effect_tree.Node(effect_parent)->surface_contents_scale = gfx::Vector2dF(1.f, 1.f); - tree.SetTargetId(parent, parent); tree.Node(parent)->scrolls = true; tree.Node(parent)->source_node_id = 0; int child = tree.Insert(TransformNode(), parent); TransformNode* child_node = tree.Node(child); - tree.SetTargetId(child, parent); child_node->scrolls = true; child_node->local.Scale3d(6.0f, 6.0f, 0.0f); child_node->local.Translate(1.3f, 1.3f); diff --git a/chromium/cc/trees/proxy.h b/chromium/cc/trees/proxy.h index 9e6c4c09596..7bb9145a894 100644 --- a/chromium/cc/trees/proxy.h +++ b/chromium/cc/trees/proxy.h @@ -13,7 +13,7 @@ #include "base/threading/platform_thread.h" #include "base/time/time.h" #include "base/values.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/input/browser_controls_state.h" #include "cc/scheduler/begin_frame_source.h" #include "cc/trees/task_runner_provider.h" diff --git a/chromium/cc/trees/proxy_common.h b/chromium/cc/trees/proxy_common.h index 69ffcfda262..45e16a9bd40 100644 --- a/chromium/cc/trees/proxy_common.h +++ b/chromium/cc/trees/proxy_common.h @@ -8,7 +8,7 @@ #include <stddef.h> #include "base/callback_forward.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/output/begin_frame_args.h" #include "cc/trees/layer_tree_host_common.h" @@ -26,6 +26,7 @@ struct CC_EXPORT BeginMainFrameAndCommitState { std::unique_ptr<ScrollAndScaleSet> scroll_info; size_t memory_allocation_limit_bytes = 0; bool evicted_ui_resources = false; + std::vector<base::Closure> completed_image_decode_callbacks; }; } // namespace cc diff --git a/chromium/cc/trees/proxy_impl.cc b/chromium/cc/trees/proxy_impl.cc index 56919567b05..afced7e5c42 100644 --- a/chromium/cc/trees/proxy_impl.cc +++ b/chromium/cc/trees/proxy_impl.cc @@ -4,16 +4,20 @@ #include "cc/trees/proxy_impl.h" +#include <string.h> + #include <algorithm> #include <string> #include "base/auto_reset.h" +#include "base/debug/alias.h" +#include "base/debug/dump_without_crashing.h" #include "base/memory/ptr_util.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" #include "base/trace_event/trace_event_synthetic_delay.h" -#include "cc/debug/benchmark_instrumentation.h" -#include "cc/debug/devtools_instrumentation.h" +#include "cc/base/devtools_instrumentation.h" +#include "cc/benchmarks/benchmark_instrumentation.h" #include "cc/input/browser_controls_offset_manager.h" #include "cc/output/compositor_frame_sink.h" #include "cc/output/context_provider.h" @@ -129,8 +133,8 @@ void ProxyImpl::InitializeCompositorFrameSinkOnImpl( LayerTreeHostImpl* host_impl = layer_tree_host_impl_.get(); bool success = host_impl->InitializeRenderer(compositor_frame_sink); MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyMain::DidInitializeCompositorFrameSink, - proxy_main_weak_ptr_, success)); + FROM_HERE, base::BindOnce(&ProxyMain::DidInitializeCompositorFrameSink, + proxy_main_weak_ptr_, success)); if (success) scheduler_->DidCreateAndInitializeCompositorFrameSink(); } @@ -223,6 +227,28 @@ void ProxyImpl::MainFrameWillHappenOnImplForTesting( completion->Signal(); } +// TODO(sunnyps): Remove this code once crbug.com/668892 is fixed. +NOINLINE void ProxyImpl::DumpForBeginMainFrameHang() { + DCHECK(IsImplThread()); + DCHECK(scheduler_); + + char stack_string[20000] = ""; + base::debug::Alias(&stack_string); + + std::unique_ptr<base::trace_event::ConvertableToTraceFormat> scheduler_state = + scheduler_->AsValue(); + strncat(stack_string, scheduler_state->ToString().c_str(), + arraysize(stack_string) - strlen(stack_string) - 1); + + std::unique_ptr<base::trace_event::ConvertableToTraceFormat> + tile_manager_state = + layer_tree_host_impl_->tile_manager()->ActivationStateAsValue(); + strncat(stack_string, tile_manager_state->ToString().c_str(), + arraysize(stack_string) - strlen(stack_string) - 1); + + base::debug::DumpWithoutCrashing(); +} + void ProxyImpl::NotifyReadyToCommitOnImpl( CompletionEvent* completion, LayerTreeHost* layer_tree_host, @@ -259,8 +285,8 @@ void ProxyImpl::DidLoseCompositorFrameSinkOnImplThread() { TRACE_EVENT0("cc", "ProxyImpl::DidLoseCompositorFrameSinkOnImplThread"); DCHECK(IsImplThread()); MainThreadTaskRunner()->PostTask( - FROM_HERE, - base::Bind(&ProxyMain::DidLoseCompositorFrameSink, proxy_main_weak_ptr_)); + FROM_HERE, base::BindOnce(&ProxyMain::DidLoseCompositorFrameSink, + proxy_main_weak_ptr_)); scheduler_->DidLoseCompositorFrameSink(); } @@ -280,8 +306,8 @@ void ProxyImpl::DidReceiveCompositorFrameAckOnImplThread() { DCHECK(IsImplThread()); scheduler_->DidReceiveCompositorFrameAck(); MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyMain::DidReceiveCompositorFrameAck, - proxy_main_weak_ptr_)); + FROM_HERE, base::BindOnce(&ProxyMain::DidReceiveCompositorFrameAck, + proxy_main_weak_ptr_)); } void ProxyImpl::OnCanDrawStateChanged(bool can_draw) { @@ -339,8 +365,8 @@ void ProxyImpl::PostAnimationEventsToMainThreadOnImplThread( TRACE_EVENT0("cc", "ProxyImpl::PostAnimationEventsToMainThreadOnImplThread"); DCHECK(IsImplThread()); MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyMain::SetAnimationEvents, - proxy_main_weak_ptr_, base::Passed(&events))); + FROM_HERE, base::BindOnce(&ProxyMain::SetAnimationEvents, + proxy_main_weak_ptr_, base::Passed(&events))); } bool ProxyImpl::IsInsideDraw() { @@ -423,8 +449,8 @@ void ProxyImpl::DidPrepareTiles() { void ProxyImpl::DidCompletePageScaleAnimationOnImplThread() { DCHECK(IsImplThread()); MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyMain::DidCompletePageScaleAnimation, - proxy_main_weak_ptr_)); + FROM_HERE, base::BindOnce(&ProxyMain::DidCompletePageScaleAnimation, + proxy_main_weak_ptr_)); } void ProxyImpl::OnDrawForCompositorFrameSink(bool resourceless_software_draw) { @@ -462,9 +488,12 @@ void ProxyImpl::ScheduledActionSendBeginMainFrame(const BeginFrameArgs& args) { layer_tree_host_impl_->ProcessScrollDeltas(); begin_main_frame_state->evicted_ui_resources = layer_tree_host_impl_->EvictedUIResourcesExist(); + begin_main_frame_state->completed_image_decode_callbacks = + layer_tree_host_impl_->TakeCompletedImageDecodeCallbacks(); MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyMain::BeginMainFrame, proxy_main_weak_ptr_, - base::Passed(&begin_main_frame_state))); + FROM_HERE, + base::BindOnce(&ProxyMain::BeginMainFrame, proxy_main_weak_ptr_, + base::Passed(&begin_main_frame_state))); layer_tree_host_impl_->DidSendBeginMainFrame(); devtools_instrumentation::DidRequestMainThreadFrame(layer_tree_host_id_); } @@ -493,6 +522,12 @@ void ProxyImpl::ScheduledActionCommit() { DCHECK(IsMainThreadBlocked()); DCHECK(commit_completion_event_); + // Relax the cross-thread access restriction to non-thread-safe RefCount. + // It's safe since the main thread is blocked while a main-thread-bound + // compositor stuff are accessed from the impl thread. + base::ScopedAllowCrossThreadRefCountAccess + allow_cross_thread_ref_count_access; + layer_tree_host_impl_->BeginCommit(); blocked_main_commit().layer_tree_host->FinishCommitOnImplThread( layer_tree_host_impl_.get()); @@ -537,8 +572,8 @@ void ProxyImpl::ScheduledActionBeginCompositorFrameSinkCreation() { "ProxyImpl::ScheduledActionBeginCompositorFrameSinkCreation"); DCHECK(IsImplThread()); MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyMain::RequestNewCompositorFrameSink, - proxy_main_weak_ptr_)); + FROM_HERE, base::BindOnce(&ProxyMain::RequestNewCompositorFrameSink, + proxy_main_weak_ptr_)); } void ProxyImpl::ScheduledActionPrepareTiles() { @@ -563,8 +598,8 @@ void ProxyImpl::ScheduledActionPerformImplSideInvalidation() { void ProxyImpl::SendBeginMainFrameNotExpectedSoon() { DCHECK(IsImplThread()); MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyMain::BeginMainFrameNotExpectedSoon, - proxy_main_weak_ptr_)); + FROM_HERE, base::BindOnce(&ProxyMain::BeginMainFrameNotExpectedSoon, + proxy_main_weak_ptr_)); } DrawResult ProxyImpl::DrawInternal(bool forced_draw) { @@ -593,6 +628,7 @@ DrawResult ProxyImpl::DrawInternal(bool forced_draw) { // CanDraw() as well. LayerTreeHostImpl::FrameData frame; + frame.begin_frame_ack = scheduler_->CurrentBeginFrameAckForActiveTree(); bool draw_frame = false; DrawResult result; @@ -621,8 +657,8 @@ DrawResult ProxyImpl::DrawInternal(bool forced_draw) { if (next_frame_is_newly_committed_frame_) { next_frame_is_newly_committed_frame_ = false; MainThreadTaskRunner()->PostTask( - FROM_HERE, - base::Bind(&ProxyMain::DidCommitAndDrawFrame, proxy_main_weak_ptr_)); + FROM_HERE, base::BindOnce(&ProxyMain::DidCommitAndDrawFrame, + proxy_main_weak_ptr_)); } DCHECK_NE(INVALID_RESULT, result); diff --git a/chromium/cc/trees/proxy_impl.h b/chromium/cc/trees/proxy_impl.h index a0482ea2ff8..68edc334515 100644 --- a/chromium/cc/trees/proxy_impl.h +++ b/chromium/cc/trees/proxy_impl.h @@ -56,6 +56,8 @@ class CC_EXPORT ProxyImpl : public NON_EXPORTED_BASE(LayerTreeHostImplClient), void MainFrameWillHappenOnImplForTesting(CompletionEvent* completion, bool* main_frame_will_happen); + NOINLINE void DumpForBeginMainFrameHang(); + private: // The members of this struct should be accessed on the impl thread only when // the main thread is blocked for a commit. diff --git a/chromium/cc/trees/proxy_main.cc b/chromium/cc/trees/proxy_main.cc index bab54a09e88..6b06f0ee80f 100644 --- a/chromium/cc/trees/proxy_main.cc +++ b/chromium/cc/trees/proxy_main.cc @@ -12,8 +12,8 @@ #include "base/trace_event/trace_event_argument.h" #include "base/trace_event/trace_event_synthetic_delay.h" #include "cc/base/completion_event.h" -#include "cc/debug/benchmark_instrumentation.h" -#include "cc/debug/devtools_instrumentation.h" +#include "cc/base/devtools_instrumentation.h" +#include "cc/benchmarks/benchmark_instrumentation.h" #include "cc/output/compositor_frame_sink.h" #include "cc/output/swap_promise.h" #include "cc/resources/ui_resource_manager.h" @@ -124,16 +124,23 @@ void ProxyMain::BeginMainFrame( DCHECK(IsMainThread()); DCHECK_EQ(NO_PIPELINE_STAGE, current_pipeline_stage_); + // We need to issue image decode callbacks whether or not we will abort this + // commit, since the callbacks are only stored in |begin_main_frame_state|. + for (auto& callback : + begin_main_frame_state->completed_image_decode_callbacks) { + callback.Run(); + } + if (defer_commits_) { TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit", TRACE_EVENT_SCOPE_THREAD); std::vector<std::unique_ptr<SwapPromise>> empty_swap_promises; ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyImpl::BeginMainFrameAbortedOnImpl, - base::Unretained(proxy_impl_.get()), - CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT, - begin_main_frame_start_time, - base::Passed(&empty_swap_promises))); + FROM_HERE, base::BindOnce(&ProxyImpl::BeginMainFrameAbortedOnImpl, + base::Unretained(proxy_impl_.get()), + CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT, + begin_main_frame_start_time, + base::Passed(&empty_swap_promises))); return; } @@ -150,11 +157,11 @@ void ProxyMain::BeginMainFrame( TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD); std::vector<std::unique_ptr<SwapPromise>> empty_swap_promises; ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyImpl::BeginMainFrameAbortedOnImpl, - base::Unretained(proxy_impl_.get()), - CommitEarlyOutReason::ABORTED_NOT_VISIBLE, - begin_main_frame_start_time, - base::Passed(&empty_swap_promises))); + FROM_HERE, base::BindOnce(&ProxyImpl::BeginMainFrameAbortedOnImpl, + base::Unretained(proxy_impl_.get()), + CommitEarlyOutReason::ABORTED_NOT_VISIBLE, + begin_main_frame_start_time, + base::Passed(&empty_swap_promises))); return; } @@ -180,6 +187,26 @@ void ProxyMain::BeginMainFrame( layer_tree_host_->GetUIResourceManager()->RecreateUIResources(); layer_tree_host_->RequestMainFrameUpdate(); + + // At this point the main frame may have deferred commits to avoid committing + // right now. + if (defer_commits_) { + TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit_InsideBeginMainFrame", + TRACE_EVENT_SCOPE_THREAD); + std::vector<std::unique_ptr<SwapPromise>> empty_swap_promises; + ImplThreadTaskRunner()->PostTask( + FROM_HERE, base::BindOnce(&ProxyImpl::BeginMainFrameAbortedOnImpl, + base::Unretained(proxy_impl_.get()), + CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT, + begin_main_frame_start_time, + base::Passed(&empty_swap_promises))); + current_pipeline_stage_ = NO_PIPELINE_STAGE; + // We intentionally don't report CommitComplete() here since it was aborted + // prematurely and we're waiting to do another commit in the future. + layer_tree_host_->DidBeginMainFrame(); + return; + } + TRACE_EVENT_SYNTHETIC_DELAY_END("cc.BeginMainFrame"); bool can_cancel_this_commit = final_pipeline_stage_ < COMMIT_PIPELINE_STAGE && @@ -200,11 +227,11 @@ void ProxyMain::BeginMainFrame( std::vector<std::unique_ptr<SwapPromise>> swap_promises = layer_tree_host_->GetSwapPromiseManager()->TakeSwapPromises(); ImplThreadTaskRunner()->PostTask( - FROM_HERE, - base::Bind(&ProxyImpl::BeginMainFrameAbortedOnImpl, - base::Unretained(proxy_impl_.get()), - CommitEarlyOutReason::FINISHED_NO_UPDATES, - begin_main_frame_start_time, base::Passed(&swap_promises))); + FROM_HERE, base::BindOnce(&ProxyImpl::BeginMainFrameAbortedOnImpl, + base::Unretained(proxy_impl_.get()), + CommitEarlyOutReason::FINISHED_NO_UPDATES, + begin_main_frame_start_time, + base::Passed(&swap_promises))); // Although the commit is internally aborted, this is because it has been // detected to be a no-op. From the perspective of an embedder, this commit @@ -234,10 +261,11 @@ void ProxyMain::BeginMainFrame( commit_waits_for_activation_ = false; CompletionEvent completion; ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyImpl::NotifyReadyToCommitOnImpl, - base::Unretained(proxy_impl_.get()), &completion, - layer_tree_host_, begin_main_frame_start_time, - hold_commit_for_activation)); + FROM_HERE, + base::BindOnce(&ProxyImpl::NotifyReadyToCommitOnImpl, + base::Unretained(proxy_impl_.get()), &completion, + layer_tree_host_, begin_main_frame_start_time, + hold_commit_for_activation)); completion.Wait(); } @@ -260,16 +288,16 @@ bool ProxyMain::CommitToActiveTree() const { void ProxyMain::SetCompositorFrameSink( CompositorFrameSink* compositor_frame_sink) { ImplThreadTaskRunner()->PostTask( - FROM_HERE, - base::Bind(&ProxyImpl::InitializeCompositorFrameSinkOnImpl, - base::Unretained(proxy_impl_.get()), compositor_frame_sink)); + FROM_HERE, base::BindOnce(&ProxyImpl::InitializeCompositorFrameSinkOnImpl, + base::Unretained(proxy_impl_.get()), + compositor_frame_sink)); } void ProxyMain::SetVisible(bool visible) { TRACE_EVENT1("cc", "ProxyMain::SetVisible", "visible", visible); ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyImpl::SetVisibleOnImpl, - base::Unretained(proxy_impl_.get()), visible)); + FROM_HERE, base::BindOnce(&ProxyImpl::SetVisibleOnImpl, + base::Unretained(proxy_impl_.get()), visible)); } void ProxyMain::SetNeedsAnimate() { @@ -314,8 +342,9 @@ void ProxyMain::SetNeedsRedraw(const gfx::Rect& damage_rect) { TRACE_EVENT0("cc", "ProxyMain::SetNeedsRedraw"); DCHECK(IsMainThread()); ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyImpl::SetNeedsRedrawOnImpl, - base::Unretained(proxy_impl_.get()), damage_rect)); + FROM_HERE, + base::BindOnce(&ProxyImpl::SetNeedsRedrawOnImpl, + base::Unretained(proxy_impl_.get()), damage_rect)); } void ProxyMain::SetNextCommitWaitsForActivation() { @@ -326,8 +355,8 @@ void ProxyMain::SetNextCommitWaitsForActivation() { void ProxyMain::NotifyInputThrottledUntilCommit() { DCHECK(IsMainThread()); ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyImpl::SetInputThrottledUntilCommitOnImpl, - base::Unretained(proxy_impl_.get()), true)); + FROM_HERE, base::BindOnce(&ProxyImpl::SetInputThrottledUntilCommitOnImpl, + base::Unretained(proxy_impl_.get()), true)); } void ProxyMain::SetDeferCommits(bool defer_commits) { @@ -343,8 +372,8 @@ void ProxyMain::SetDeferCommits(bool defer_commits) { ImplThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&ProxyImpl::SetDeferCommitsOnImpl, - base::Unretained(proxy_impl_.get()), defer_commits)); + base::BindOnce(&ProxyImpl::SetDeferCommitsOnImpl, + base::Unretained(proxy_impl_.get()), defer_commits)); } bool ProxyMain::CommitRequested() const { @@ -358,8 +387,8 @@ bool ProxyMain::CommitRequested() const { void ProxyMain::MainThreadHasStoppedFlinging() { DCHECK(IsMainThread()); ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyImpl::MainThreadHasStoppedFlingingOnImpl, - base::Unretained(proxy_impl_.get()))); + FROM_HERE, base::BindOnce(&ProxyImpl::MainThreadHasStoppedFlingingOnImpl, + base::Unretained(proxy_impl_.get()))); } void ProxyMain::Start() { @@ -370,8 +399,8 @@ void ProxyMain::Start() { DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_); CompletionEvent completion; ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyMain::InitializeOnImplThread, - base::Unretained(this), &completion)); + FROM_HERE, base::BindOnce(&ProxyMain::InitializeOnImplThread, + base::Unretained(this), &completion)); completion.Wait(); } @@ -392,16 +421,16 @@ void ProxyMain::Stop() { CompletionEvent completion; ImplThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&ProxyImpl::FinishGLOnImpl, - base::Unretained(proxy_impl_.get()), &completion)); + base::BindOnce(&ProxyImpl::FinishGLOnImpl, + base::Unretained(proxy_impl_.get()), &completion)); completion.Wait(); } { DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_); CompletionEvent completion; ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyMain::DestroyProxyImplOnImplThread, - base::Unretained(this), &completion)); + FROM_HERE, base::BindOnce(&ProxyMain::DestroyProxyImplOnImplThread, + base::Unretained(this), &completion)); completion.Wait(); } @@ -413,9 +442,9 @@ void ProxyMain::Stop() { void ProxyMain::SetMutator(std::unique_ptr<LayerTreeMutator> mutator) { TRACE_EVENT0("compositor-worker", "ThreadProxy::SetMutator"); ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyImpl::InitializeMutatorOnImpl, - base::Unretained(proxy_impl_.get()), - base::Passed(std::move(mutator)))); + FROM_HERE, base::BindOnce(&ProxyImpl::InitializeMutatorOnImpl, + base::Unretained(proxy_impl_.get()), + base::Passed(std::move(mutator)))); } bool ProxyMain::SupportsImplScrolling() const { @@ -429,9 +458,10 @@ bool ProxyMain::MainFrameWillHappenForTesting() { DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_); CompletionEvent completion; ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyImpl::MainFrameWillHappenOnImplForTesting, - base::Unretained(proxy_impl_.get()), &completion, - &main_frame_will_happen)); + FROM_HERE, + base::BindOnce(&ProxyImpl::MainFrameWillHappenOnImplForTesting, + base::Unretained(proxy_impl_.get()), &completion, + &main_frame_will_happen)); completion.Wait(); } return main_frame_will_happen; @@ -442,8 +472,9 @@ void ProxyMain::ReleaseCompositorFrameSink() { DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_); CompletionEvent completion; ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyImpl::ReleaseCompositorFrameSinkOnImpl, - base::Unretained(proxy_impl_.get()), &completion)); + FROM_HERE, + base::BindOnce(&ProxyImpl::ReleaseCompositorFrameSinkOnImpl, + base::Unretained(proxy_impl_.get()), &completion)); completion.Wait(); } @@ -452,9 +483,9 @@ void ProxyMain::UpdateBrowserControlsState(BrowserControlsState constraints, bool animate) { DCHECK(IsMainThread()); ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyImpl::UpdateBrowserControlsStateOnImpl, - base::Unretained(proxy_impl_.get()), constraints, - current, animate)); + FROM_HERE, base::BindOnce(&ProxyImpl::UpdateBrowserControlsStateOnImpl, + base::Unretained(proxy_impl_.get()), + constraints, current, animate)); } bool ProxyMain::SendCommitRequestToImplThreadIfNeeded( @@ -467,8 +498,8 @@ bool ProxyMain::SendCommitRequestToImplThreadIfNeeded( if (already_posted) return false; ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyImpl::SetNeedsCommitOnImpl, - base::Unretained(proxy_impl_.get()))); + FROM_HERE, base::BindOnce(&ProxyImpl::SetNeedsCommitOnImpl, + base::Unretained(proxy_impl_.get()))); return true; } diff --git a/chromium/cc/trees/proxy_main.h b/chromium/cc/trees/proxy_main.h index 29f4880a8b6..3d97276193a 100644 --- a/chromium/cc/trees/proxy_main.h +++ b/chromium/cc/trees/proxy_main.h @@ -6,7 +6,7 @@ #define CC_TREES_PROXY_MAIN_H_ #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/input/browser_controls_state.h" #include "cc/trees/proxy.h" #include "cc/trees/proxy_common.h" diff --git a/chromium/cc/trees/scroll_node.h b/chromium/cc/trees/scroll_node.h index 09d7be86ecf..4eefe42aff1 100644 --- a/chromium/cc/trees/scroll_node.h +++ b/chromium/cc/trees/scroll_node.h @@ -5,9 +5,9 @@ #ifndef CC_TREES_SCROLL_NODE_H_ #define CC_TREES_SCROLL_NODE_H_ -#include "cc/base/cc_export.h" +#include "cc/base/filter_operations.h" #include "cc/base/region.h" -#include "cc/output/filter_operations.h" +#include "cc/cc_export.h" #include "ui/gfx/geometry/size.h" namespace base { diff --git a/chromium/cc/trees/single_thread_proxy.cc b/chromium/cc/trees/single_thread_proxy.cc index 33ed54ae3a9..07b5afa607a 100644 --- a/chromium/cc/trees/single_thread_proxy.cc +++ b/chromium/cc/trees/single_thread_proxy.cc @@ -8,8 +8,8 @@ #include "base/memory/ptr_util.h" #include "base/profiler/scoped_tracker.h" #include "base/trace_event/trace_event.h" -#include "cc/debug/benchmark_instrumentation.h" -#include "cc/debug/devtools_instrumentation.h" +#include "cc/base/devtools_instrumentation.h" +#include "cc/benchmarks/benchmark_instrumentation.h" #include "cc/output/compositor_frame_sink.h" #include "cc/output/context_provider.h" #include "cc/quads/draw_quad.h" @@ -204,6 +204,12 @@ void SingleThreadProxy::DoCommit() { if (scheduler_on_impl_thread_) scheduler_on_impl_thread_->DidCommit(); + // Issue decode callbacks. + auto completed_decode_callbacks = + layer_tree_host_impl_->TakeCompletedImageDecodeCallbacks(); + for (auto& callback : completed_decode_callbacks) + callback.Run(); + layer_tree_host_impl_->CommitComplete(); // Commit goes directly to the active tree, but we need to synchronously @@ -449,8 +455,9 @@ void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) { } BeginFrameArgs begin_frame_args(BeginFrameArgs::Create( - BEGINFRAME_FROM_HERE, 0, 1, frame_begin_time, base::TimeTicks(), - BeginFrameArgs::DefaultInterval(), BeginFrameArgs::NORMAL)); + BEGINFRAME_FROM_HERE, BeginFrameArgs::kManualSourceId, 1, + frame_begin_time, base::TimeTicks(), BeginFrameArgs::DefaultInterval(), + BeginFrameArgs::NORMAL)); // Start the impl frame. { @@ -464,6 +471,7 @@ void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) { DCHECK(inside_impl_frame_); #endif DoBeginMainFrame(begin_frame_args); + DoPainting(); DoCommit(); DCHECK_EQ( @@ -485,6 +493,9 @@ void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) { layer_tree_host_impl_->Animate(); LayerTreeHostImpl::FrameData frame; + frame.begin_frame_ack = BeginFrameAck( + begin_frame_args.source_id, begin_frame_args.sequence_number, + begin_frame_args.sequence_number, true); DoComposite(&frame); // DoComposite could abort, but because this is a synchronous composite @@ -604,8 +615,8 @@ void SingleThreadProxy::ScheduledActionSendBeginMainFrame( #endif task_runner_provider_->MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&SingleThreadProxy::BeginMainFrame, - weak_factory_.GetWeakPtr(), begin_frame_args)); + FROM_HERE, base::BindOnce(&SingleThreadProxy::BeginMainFrame, + weak_factory_.GetWeakPtr(), begin_frame_args)); layer_tree_host_impl_->DidSendBeginMainFrame(); } @@ -648,6 +659,22 @@ void SingleThreadProxy::BeginMainFrame(const BeginFrameArgs& begin_frame_args) { commit_requested_ = true; DoBeginMainFrame(begin_frame_args); + + // New commits requested inside UpdateLayers should be respected. + commit_requested_ = false; + + // At this point the main frame may have deferred commits to avoid committing + // right now. + if (defer_commits_) { + TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit_InsideBeginMainFrame", + TRACE_EVENT_SCOPE_THREAD); + BeginMainFrameAbortedOnImplThread( + CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT); + layer_tree_host_->DidBeginMainFrame(); + return; + } + + DoPainting(); } void SingleThreadProxy::DoBeginMainFrame( @@ -664,10 +691,9 @@ void SingleThreadProxy::DoBeginMainFrame( layer_tree_host_->BeginMainFrame(begin_frame_args); layer_tree_host_->AnimateLayers(begin_frame_args.frame_time); layer_tree_host_->RequestMainFrameUpdate(); +} - // New commits requested inside UpdateLayers should be respected. - commit_requested_ = false; - +void SingleThreadProxy::DoPainting() { layer_tree_host_->UpdateLayers(); // TODO(enne): SingleThreadProxy does not support cancelling commits yet, @@ -692,6 +718,8 @@ void SingleThreadProxy::BeginMainFrameAbortedOnImplThread( DrawResult SingleThreadProxy::ScheduledActionDrawIfPossible() { DebugScopedSetImplThread impl(task_runner_provider_); LayerTreeHostImpl::FrameData frame; + frame.begin_frame_ack = + scheduler_on_impl_thread_->CurrentBeginFrameAckForActiveTree(); return DoComposite(&frame); } diff --git a/chromium/cc/trees/single_thread_proxy.h b/chromium/cc/trees/single_thread_proxy.h index 3e9487ea358..4a091950a27 100644 --- a/chromium/cc/trees/single_thread_proxy.h +++ b/chromium/cc/trees/single_thread_proxy.h @@ -112,6 +112,7 @@ class CC_EXPORT SingleThreadProxy : public Proxy, void BeginMainFrame(const BeginFrameArgs& begin_frame_args); void BeginMainFrameAbortedOnImplThread(CommitEarlyOutReason reason); void DoBeginMainFrame(const BeginFrameArgs& begin_frame_args); + void DoPainting(); void DoCommit(); DrawResult DoComposite(LayerTreeHostImpl::FrameData* frame); void DoSwap(); diff --git a/chromium/cc/trees/swap_promise_manager.h b/chromium/cc/trees/swap_promise_manager.h index 8b5d9a23e56..795493dd3bb 100644 --- a/chromium/cc/trees/swap_promise_manager.h +++ b/chromium/cc/trees/swap_promise_manager.h @@ -9,7 +9,7 @@ #include <vector> #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "cc/output/swap_promise.h" namespace cc { diff --git a/chromium/cc/trees/swap_promise_monitor.h b/chromium/cc/trees/swap_promise_monitor.h index 550176438e9..cde077e6345 100644 --- a/chromium/cc/trees/swap_promise_monitor.h +++ b/chromium/cc/trees/swap_promise_monitor.h @@ -5,7 +5,7 @@ #ifndef CC_TREES_SWAP_PROMISE_MONITOR_H_ #define CC_TREES_SWAP_PROMISE_MONITOR_H_ -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace cc { diff --git a/chromium/cc/trees/target_property.h b/chromium/cc/trees/target_property.h index e118c8db6a7..177ef965afa 100644 --- a/chromium/cc/trees/target_property.h +++ b/chromium/cc/trees/target_property.h @@ -7,7 +7,7 @@ #include <bitset> -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace cc { diff --git a/chromium/cc/trees/task_runner_provider.h b/chromium/cc/trees/task_runner_provider.h index e4c7b195cc4..1a7ebf5adca 100644 --- a/chromium/cc/trees/task_runner_provider.h +++ b/chromium/cc/trees/task_runner_provider.h @@ -16,7 +16,7 @@ #include "base/threading/platform_thread.h" #include "base/time/time.h" #include "base/values.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace base { class SingleThreadTaskRunner; diff --git a/chromium/cc/trees/transform_node.cc b/chromium/cc/trees/transform_node.cc index 8b9360f9091..6f89261dd29 100644 --- a/chromium/cc/trees/transform_node.cc +++ b/chromium/cc/trees/transform_node.cc @@ -108,9 +108,6 @@ void TransformNode::AsValueInto(base::trace_event::TracedValue* value) const { MathUtil::AddToTracedValue("pre_local", pre_local, value); MathUtil::AddToTracedValue("local", local, value); MathUtil::AddToTracedValue("post_local", post_local, value); - // TODO(sunxd): make frameviewer work without target_id - value->SetInteger("target_id", 0); - value->SetInteger("content_target_id", 0); value->SetInteger("source_node_id", source_node_id); value->SetInteger("sorting_context_id", sorting_context_id); MathUtil::AddToTracedValue("scroll_offset", scroll_offset, value); @@ -118,7 +115,7 @@ void TransformNode::AsValueInto(base::trace_event::TracedValue* value) const { } TransformCachedNodeData::TransformCachedNodeData() - : target_id(-1), content_target_id(-1), is_showing_backface(false) {} + : is_showing_backface(false) {} TransformCachedNodeData::TransformCachedNodeData( const TransformCachedNodeData& other) = default; @@ -128,8 +125,6 @@ TransformCachedNodeData::~TransformCachedNodeData() {} bool TransformCachedNodeData::operator==( const TransformCachedNodeData& other) const { return from_screen == other.from_screen && to_screen == other.to_screen && - target_id == other.target_id && - content_target_id == other.content_target_id && is_showing_backface == other.is_showing_backface; } diff --git a/chromium/cc/trees/transform_node.h b/chromium/cc/trees/transform_node.h index b98e83cdae9..76f2a7c2ffc 100644 --- a/chromium/cc/trees/transform_node.h +++ b/chromium/cc/trees/transform_node.h @@ -5,7 +5,7 @@ #ifndef CC_TREES_TRANSFORM_NODE_H_ #define CC_TREES_TRANSFORM_NODE_H_ -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" #include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/scroll_offset.h" #include "ui/gfx/transform.h" @@ -148,10 +148,6 @@ struct CC_EXPORT TransformCachedNodeData { gfx::Transform from_screen; gfx::Transform to_screen; - int target_id; - // This id is used for all content that draws into a render surface associated - // with this transform node. - int content_target_id; bool is_showing_backface : 1; diff --git a/chromium/cc/trees/tree_synchronizer.cc b/chromium/cc/trees/tree_synchronizer.cc index b593a9d66e9..52f1bb384c7 100644 --- a/chromium/cc/trees/tree_synchronizer.cc +++ b/chromium/cc/trees/tree_synchronizer.cc @@ -28,8 +28,10 @@ void SynchronizeTreesInternal(LayerTreeType* source_tree, std::unique_ptr<OwnedLayerImplList> old_layers(tree_impl->DetachLayers()); OwnedLayerImplMap old_layer_map; - for (auto& it : *old_layers) + for (auto& it : *old_layers) { + DCHECK(it); old_layer_map[it->id()] = std::move(it); + } PushLayerList(&old_layer_map, source_tree, tree_impl); diff --git a/chromium/cc/trees/tree_synchronizer.h b/chromium/cc/trees/tree_synchronizer.h index e5a0b62a0f6..1f0a1a1c8cf 100644 --- a/chromium/cc/trees/tree_synchronizer.h +++ b/chromium/cc/trees/tree_synchronizer.h @@ -8,7 +8,7 @@ #include <memory> #include "base/macros.h" -#include "cc/base/cc_export.h" +#include "cc/cc_export.h" namespace cc { |