summaryrefslogtreecommitdiffstats
path: root/chromium/cc/trees
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2021-10-26 13:57:00 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2021-11-02 11:31:01 +0000
commit1943b3c2a1dcee36c233724fc4ee7613d71b9cf6 (patch)
tree8c1b5f12357025c197da5427ae02cfdc2f3570d6 /chromium/cc/trees
parent21ba0c5d4bf8fba15dddd97cd693bad2358b77fd (diff)
BASELINE: Update Chromium to 94.0.4606.111
Change-Id: I924781584def20fc800bedf6ff41fdb96c438193 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/cc/trees')
-rw-r--r--chromium/cc/trees/animated_paint_worklet_tracker.cc1
-rw-r--r--chromium/cc/trees/clip_expander.cc2
-rw-r--r--chromium/cc/trees/clip_expander.h1
-rw-r--r--chromium/cc/trees/compositor_commit_data.h1
-rw-r--r--chromium/cc/trees/damage_tracker_unittest.cc46
-rw-r--r--chromium/cc/trees/de_jelly_state.h2
-rw-r--r--chromium/cc/trees/draw_properties_unittest.cc13
-rw-r--r--chromium/cc/trees/draw_property_utils.cc87
-rw-r--r--chromium/cc/trees/effect_node.cc7
-rw-r--r--chromium/cc/trees/effect_node.h3
-rw-r--r--chromium/cc/trees/frame_rate_estimator_unittest.cc2
-rw-r--r--chromium/cc/trees/image_animation_controller.h1
-rw-r--r--chromium/cc/trees/layer_tree_host.cc73
-rw-r--r--chromium/cc/trees/layer_tree_host.h33
-rw-r--r--chromium/cc/trees/layer_tree_host_client.h7
-rw-r--r--chromium/cc/trees/layer_tree_host_impl.cc144
-rw-r--r--chromium/cc/trees/layer_tree_host_impl.h55
-rw-r--r--chromium/cc/trees/layer_tree_host_impl_unittest.cc159
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_blending.cc2
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_masks.cc4
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_readback.cc26
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest.cc335
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_animation.cc9
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_capture_content.cc5
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_context.cc2
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc83
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_damage.cc5
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_scroll.cc36
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_video.cc7
-rw-r--r--chromium/cc/trees/layer_tree_impl.cc20
-rw-r--r--chromium/cc/trees/layer_tree_impl.h12
-rw-r--r--chromium/cc/trees/layer_tree_impl_unittest.cc6
-rw-r--r--chromium/cc/trees/layer_tree_settings.cc4
-rw-r--r--chromium/cc/trees/layer_tree_settings.h4
-rw-r--r--chromium/cc/trees/mobile_optimized_viewport_util.cc41
-rw-r--r--chromium/cc/trees/mobile_optimized_viewport_util.h34
-rw-r--r--chromium/cc/trees/occlusion_tracker.cc4
-rw-r--r--chromium/cc/trees/occlusion_unittest.cc2
-rw-r--r--chromium/cc/trees/paint_holding_commit_trigger.cc22
-rw-r--r--chromium/cc/trees/paint_holding_commit_trigger.h12
-rw-r--r--chromium/cc/trees/paint_holding_reason.h21
-rw-r--r--chromium/cc/trees/presentation_time_callback_buffer.cc43
-rw-r--r--chromium/cc/trees/presentation_time_callback_buffer.h33
-rw-r--r--chromium/cc/trees/presentation_time_callback_buffer_unittest.cc113
-rw-r--r--chromium/cc/trees/property_tree.cc20
-rw-r--r--chromium/cc/trees/property_tree.h41
-rw-r--r--chromium/cc/trees/property_tree_builder.cc19
-rw-r--r--chromium/cc/trees/property_tree_builder_unittest.cc37
-rw-r--r--chromium/cc/trees/proxy.h9
-rw-r--r--chromium/cc/trees/proxy_impl.cc15
-rw-r--r--chromium/cc/trees/proxy_impl.h2
-rw-r--r--chromium/cc/trees/proxy_main.cc71
-rw-r--r--chromium/cc/trees/proxy_main.h13
-rw-r--r--chromium/cc/trees/scroll_node.h1
-rw-r--r--chromium/cc/trees/single_thread_proxy.cc47
-rw-r--r--chromium/cc/trees/single_thread_proxy.h10
-rw-r--r--chromium/cc/trees/sticky_position_constraint.cc3
-rw-r--r--chromium/cc/trees/sticky_position_constraint.h1
-rw-r--r--chromium/cc/trees/throttle_decider.cc9
-rw-r--r--chromium/cc/trees/throttle_decider.h4
-rw-r--r--chromium/cc/trees/transform_node.cc2
-rw-r--r--chromium/cc/trees/transform_node.h1
-rw-r--r--chromium/cc/trees/tree_synchronizer_unittest.cc6
-rw-r--r--chromium/cc/trees/ukm_manager_unittest.cc29
64 files changed, 1436 insertions, 426 deletions
diff --git a/chromium/cc/trees/animated_paint_worklet_tracker.cc b/chromium/cc/trees/animated_paint_worklet_tracker.cc
index b312c24180d..58d51b838fa 100644
--- a/chromium/cc/trees/animated_paint_worklet_tracker.cc
+++ b/chromium/cc/trees/animated_paint_worklet_tracker.cc
@@ -8,6 +8,7 @@
#include <utility>
#include <vector>
+#include "base/containers/cxx20_erase.h"
#include "cc/layers/picture_layer_impl.h"
namespace cc {
diff --git a/chromium/cc/trees/clip_expander.cc b/chromium/cc/trees/clip_expander.cc
index 02df3797a41..b4fbe772b47 100644
--- a/chromium/cc/trees/clip_expander.cc
+++ b/chromium/cc/trees/clip_expander.cc
@@ -14,6 +14,8 @@ ClipExpander::ClipExpander(int filter_effect_id)
ClipExpander::ClipExpander(const ClipExpander& other) = default;
+ClipExpander& ClipExpander::operator=(const ClipExpander& other) = default;
+
bool ClipExpander::operator==(const ClipExpander& other) const {
return target_effect_id_ == other.target_effect_id_;
}
diff --git a/chromium/cc/trees/clip_expander.h b/chromium/cc/trees/clip_expander.h
index 209477a2553..fef2ad5ecda 100644
--- a/chromium/cc/trees/clip_expander.h
+++ b/chromium/cc/trees/clip_expander.h
@@ -16,6 +16,7 @@ class CC_EXPORT ClipExpander {
public:
explicit ClipExpander(int filter_effect_id);
ClipExpander(const ClipExpander& other);
+ ClipExpander& operator=(const ClipExpander& other);
bool operator==(const ClipExpander& other) const;
diff --git a/chromium/cc/trees/compositor_commit_data.h b/chromium/cc/trees/compositor_commit_data.h
index 35a7d8e313a..4fb1482bb96 100644
--- a/chromium/cc/trees/compositor_commit_data.h
+++ b/chromium/cc/trees/compositor_commit_data.h
@@ -13,6 +13,7 @@
#include "cc/input/scroll_snap_data.h"
#include "cc/paint/element_id.h"
#include "cc/trees/layer_tree_host_client.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/scroll_offset.h"
#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/transform.h"
diff --git a/chromium/cc/trees/damage_tracker_unittest.cc b/chromium/cc/trees/damage_tracker_unittest.cc
index a97f44689a3..48332d88b20 100644
--- a/chromium/cc/trees/damage_tracker_unittest.cc
+++ b/chromium/cc/trees/damage_tracker_unittest.cc
@@ -1801,13 +1801,13 @@ TEST_F(DamageTrackerTest, DamageRectTooBig) {
SetCopyRequest(root);
// Really far left.
- child1->SetOffsetToTransformParent(
- gfx::Vector2dF(std::numeric_limits<int>::min() + 100, 0));
+ child1->SetOffsetToTransformParent(gfx::Vector2dF(
+ static_cast<float>(std::numeric_limits<int>::min() + 100), 0));
child1->SetBounds(gfx::Size(1, 1));
// Really far right.
- child2->SetOffsetToTransformParent(
- gfx::Vector2dF(std::numeric_limits<int>::max() - 100, 0));
+ child2->SetOffsetToTransformParent(gfx::Vector2dF(
+ static_cast<float>(std::numeric_limits<int>::max() - 100), 0));
child2->SetBounds(gfx::Size(1, 1));
EmulateDrawingOneFrame(root, 1.f);
@@ -1838,13 +1838,13 @@ TEST_F(DamageTrackerTest, DamageRectTooBigWithFilter) {
SetBackdropFilter(root, filters);
// Really far left.
- child1->SetOffsetToTransformParent(
- gfx::Vector2dF(std::numeric_limits<int>::min() + 100, 0));
+ child1->SetOffsetToTransformParent(gfx::Vector2dF(
+ static_cast<float>(std::numeric_limits<int>::min() + 100), 0));
child1->SetBounds(gfx::Size(1, 1));
// Really far right.
- child2->SetOffsetToTransformParent(
- gfx::Vector2dF(std::numeric_limits<int>::max() - 100, 0));
+ child2->SetOffsetToTransformParent(gfx::Vector2dF(
+ static_cast<float>(std::numeric_limits<int>::max() - 100), 0));
child2->SetBounds(gfx::Size(1, 1));
float device_scale_factor = 1.f;
@@ -1869,14 +1869,14 @@ TEST_F(DamageTrackerTest, DamageRectTooBigInRenderSurface) {
SetCopyRequest(root);
// Really far left.
- grand_child1_->SetOffsetToTransformParent(
- gfx::Vector2dF(std::numeric_limits<int>::min() + 500, 0));
+ grand_child1_->SetOffsetToTransformParent(gfx::Vector2dF(
+ static_cast<float>(std::numeric_limits<int>::min() + 500), 0));
grand_child1_->SetBounds(gfx::Size(1, 1));
grand_child1_->SetDrawsContent(true);
// Really far right.
- grand_child2_->SetOffsetToTransformParent(
- gfx::Vector2dF(std::numeric_limits<int>::max() - 500, 0));
+ grand_child2_->SetOffsetToTransformParent(gfx::Vector2dF(
+ static_cast<float>(std::numeric_limits<int>::max() - 500), 0));
grand_child2_->SetBounds(gfx::Size(1, 1));
grand_child2_->SetDrawsContent(true);
@@ -1959,14 +1959,14 @@ TEST_F(DamageTrackerTest, DamageRectTooBigInRenderSurfaceWithFilter) {
SetBackdropFilter(child1_, filters);
// Really far left.
- grand_child1_->SetOffsetToTransformParent(
- gfx::Vector2dF(std::numeric_limits<int>::min() + 500, 0));
+ grand_child1_->SetOffsetToTransformParent(gfx::Vector2dF(
+ static_cast<float>(std::numeric_limits<int>::min() + 500), 0));
grand_child1_->SetBounds(gfx::Size(1, 1));
grand_child1_->SetDrawsContent(true);
// Really far right.
- grand_child2_->SetOffsetToTransformParent(
- gfx::Vector2dF(std::numeric_limits<int>::max() - 500, 0));
+ grand_child2_->SetOffsetToTransformParent(gfx::Vector2dF(
+ static_cast<float>(std::numeric_limits<int>::max() - 500), 0));
grand_child2_->SetBounds(gfx::Size(1, 1));
grand_child2_->SetDrawsContent(true);
@@ -2217,13 +2217,13 @@ TEST_F(DamageTrackerTest, DamageRectOnlyVisibleContentsMoveToOutside) {
origin_damage.Union(child2->visible_drawable_content_rect());
// Really far left.
- child1->SetOffsetToTransformParent(
- gfx::Vector2dF(std::numeric_limits<int>::min() + 100, 0));
+ child1->SetOffsetToTransformParent(gfx::Vector2dF(
+ static_cast<float>(std::numeric_limits<int>::min() + 100), 0));
child1->SetBounds(gfx::Size(1, 1));
// Really far right.
- child2->SetOffsetToTransformParent(
- gfx::Vector2dF(std::numeric_limits<int>::max() - 100, 0));
+ child2->SetOffsetToTransformParent(gfx::Vector2dF(
+ static_cast<float>(std::numeric_limits<int>::max() - 100), 0));
child2->SetBounds(gfx::Size(1, 1));
EmulateDrawingOneFrame(root, 1.f);
@@ -2252,8 +2252,8 @@ TEST_F(DamageTrackerTest, DamageRectOnlyVisibleContentsLargeTwoContents) {
expected_damage.set_width(GetRenderSurface(root)->content_rect().width());
// Really far left.
- child1->SetOffsetToTransformParent(
- gfx::Vector2dF(std::numeric_limits<int>::min() + 100, 100));
+ child1->SetOffsetToTransformParent(gfx::Vector2dF(
+ static_cast<float>(std::numeric_limits<int>::min() + 100), 100));
child1->SetBounds(
gfx::Size(std::numeric_limits<int>::max(), child1->bounds().height()));
@@ -2263,7 +2263,7 @@ TEST_F(DamageTrackerTest, DamageRectOnlyVisibleContentsLargeTwoContents) {
gfx::Size(std::numeric_limits<int>::max(), child2->bounds().height()));
EmulateDrawingOneFrame(root, 1.f);
- // Above damages should be excludebe because they're outside of
+ // Above damages should be excluded because they're outside of
// the root surface.
gfx::Rect damage_rect;
EXPECT_TRUE(GetRenderSurface(root)->damage_tracker()->GetDamageRectIfValid(
diff --git a/chromium/cc/trees/de_jelly_state.h b/chromium/cc/trees/de_jelly_state.h
index 2f8be8f2a37..b62d1b0c6e2 100644
--- a/chromium/cc/trees/de_jelly_state.h
+++ b/chromium/cc/trees/de_jelly_state.h
@@ -7,8 +7,6 @@
#include <map>
-#include "base/containers/flat_map.h"
-#include "base/no_destructor.h"
#include "cc/cc_export.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/transform.h"
diff --git a/chromium/cc/trees/draw_properties_unittest.cc b/chromium/cc/trees/draw_properties_unittest.cc
index 4f1c15cf86c..f982efe46a1 100644
--- a/chromium/cc/trees/draw_properties_unittest.cc
+++ b/chromium/cc/trees/draw_properties_unittest.cc
@@ -3575,21 +3575,22 @@ TEST_F(DrawPropertiesTest, OpacityAnimatingOnPendingTree) {
active_child->effect_tree_index()));
}
-class TransformInteropTest : public DrawPropertiesTestBase,
- public testing::Test {
+class BackfaceVisibilityInteropTest : public DrawPropertiesTestBase,
+ public testing::Test {
public:
- TransformInteropTest() : DrawPropertiesTestBase(TransformInteropSettings()) {}
+ BackfaceVisibilityInteropTest()
+ : DrawPropertiesTestBase(BackfaceVisibilityInteropSettings()) {}
protected:
- LayerTreeSettings TransformInteropSettings() {
+ LayerTreeSettings BackfaceVisibilityInteropSettings() {
LayerListSettings settings;
- settings.enable_transform_interop = true;
+ settings.enable_backface_visibility_interop = true;
return settings;
}
};
-TEST_F(TransformInteropTest, BackfaceInvisibleTransform) {
+TEST_F(BackfaceVisibilityInteropTest, BackfaceInvisibleTransform) {
LayerImpl* root = root_layer();
root->SetDrawsContent(true);
LayerImpl* back_facing = AddLayer<LayerImpl>();
diff --git a/chromium/cc/trees/draw_property_utils.cc b/chromium/cc/trees/draw_property_utils.cc
index b6c84a81c1d..5196b0189dd 100644
--- a/chromium/cc/trees/draw_property_utils.cc
+++ b/chromium/cc/trees/draw_property_utils.cc
@@ -12,11 +12,13 @@
#include "base/containers/adapters.h"
#include "base/containers/stack.h"
#include "base/logging.h"
+#include "build/build_config.h"
#include "cc/base/math_util.h"
#include "cc/layers/draw_properties.h"
#include "cc/layers/layer.h"
#include "cc/layers/layer_impl.h"
#include "cc/layers/picture_layer.h"
+#include "cc/paint/filter_operation.h"
#include "cc/trees/clip_node.h"
#include "cc/trees/effect_node.h"
#include "cc/trees/layer_tree_impl.h"
@@ -1121,20 +1123,86 @@ void RecordRenderSurfaceReasonsForTracing(
void UpdateElasticOverscroll(
PropertyTrees* property_trees,
TransformNode* overscroll_elasticity_transform_node,
- const gfx::Vector2dF& elastic_overscroll) {
+ ElementId overscroll_elasticity_effect_element_id,
+ const gfx::Vector2dF& elastic_overscroll,
+ const ScrollNode* inner_viewport) {
+#if defined(OS_ANDROID)
+ // On android, elastic overscroll is implemented by stretching the content
+ // from the overscrolled edge.
+ if (!overscroll_elasticity_effect_element_id &&
+ !overscroll_elasticity_transform_node) {
+ DCHECK(elastic_overscroll.IsZero());
+ return;
+ }
+ if (overscroll_elasticity_effect_element_id) {
+ if (elastic_overscroll.IsZero() || !inner_viewport) {
+ property_trees->effect_tree.OnFilterAnimated(
+ overscroll_elasticity_effect_element_id, FilterOperations());
+ return;
+ }
+ // The inner viewport container size takes into account the size change as a
+ // result of the top controls, see ScrollTree::container_bounds.
+ gfx::Size scroller_size =
+ property_trees->scroll_tree.container_bounds(inner_viewport->id);
+
+ property_trees->effect_tree.OnFilterAnimated(
+ overscroll_elasticity_effect_element_id,
+ FilterOperations(
+ std::vector<FilterOperation>({FilterOperation::CreateStretchFilter(
+ -elastic_overscroll.x() / scroller_size.width(),
+ -elastic_overscroll.y() / scroller_size.height())})));
+ return;
+ }
+
+ // If there is no overscroll elasticity effect node, we apply a stretch
+ // transform.
+ overscroll_elasticity_transform_node->local.MakeIdentity();
+ overscroll_elasticity_transform_node->origin.SetPoint(0.f, 0.f, 0.f);
+ overscroll_elasticity_transform_node->to_screen_is_potentially_animated =
+ !elastic_overscroll.IsZero();
+
+ if (!elastic_overscroll.IsZero() && inner_viewport) {
+ // The inner viewport container size takes into account the size change as a
+ // result of the top controls, see ScrollTree::container_bounds.
+ gfx::Size scroller_size =
+ property_trees->scroll_tree.container_bounds(inner_viewport->id);
+
+ overscroll_elasticity_transform_node->local.Scale(
+ 1.f + std::abs(elastic_overscroll.x()) / scroller_size.width(),
+ 1.f + std::abs(elastic_overscroll.y()) / scroller_size.height());
+
+ // If overscrolling to the right, stretch from right.
+ if (elastic_overscroll.x() > 0.f) {
+ overscroll_elasticity_transform_node->origin.set_x(scroller_size.width());
+ }
+
+ // If overscrolling off the bottom, stretch from bottom.
+ if (elastic_overscroll.y() > 0.f) {
+ overscroll_elasticity_transform_node->origin.set_y(
+ scroller_size.height());
+ }
+ }
+ overscroll_elasticity_transform_node->needs_local_transform_update = true;
+ property_trees->transform_tree.set_needs_update(true);
+#else // defined(OS_ANDROID)
if (!overscroll_elasticity_transform_node) {
DCHECK(elastic_overscroll.IsZero());
return;
}
+ // On other platforms, we modify the translation offset to match the
+ // overscroll amount.
if (overscroll_elasticity_transform_node->scroll_offset ==
gfx::ScrollOffset(elastic_overscroll))
return;
overscroll_elasticity_transform_node->scroll_offset =
gfx::ScrollOffset(elastic_overscroll);
+
overscroll_elasticity_transform_node->needs_local_transform_update = true;
property_trees->transform_tree.set_needs_update(true);
+
+#endif // defined(OS_ANDROID)
}
void ComputeDrawPropertiesOfVisibleLayers(const LayerImplList* layer_list,
@@ -1215,7 +1283,6 @@ bool NodeMayContainBackdropBlurFilter(const EffectNode& node) {
default:
return false;
}
- return false;
}
#endif
@@ -1245,7 +1312,7 @@ bool CC_EXPORT LayerShouldBeSkippedForDrawPropertiesComputation(
if (!transform_node->node_and_ancestors_are_animated_or_invertible ||
!effect_node->is_drawn)
return true;
- if (layer->layer_tree_impl()->settings().enable_transform_interop) {
+ if (layer->layer_tree_impl()->settings().enable_backface_visibility_interop) {
return layer->should_check_backface_visibility() &&
IsLayerBackFaceVisible(layer, layer->transform_tree_index(),
property_trees);
@@ -1257,7 +1324,7 @@ bool CC_EXPORT LayerShouldBeSkippedForDrawPropertiesComputation(
bool CC_EXPORT IsLayerBackFaceVisible(LayerImpl* layer,
int transform_tree_index,
const PropertyTrees* property_trees) {
- if (layer->layer_tree_impl()->settings().enable_transform_interop) {
+ if (layer->layer_tree_impl()->settings().enable_backface_visibility_interop) {
return IsTransformToRootOf3DRenderingContextBackFaceVisible(
layer, transform_tree_index, property_trees);
} else {
@@ -1269,7 +1336,9 @@ bool CC_EXPORT IsLayerBackFaceVisible(LayerImpl* layer,
bool CC_EXPORT IsLayerBackFaceVisible(Layer* layer,
int transform_tree_index,
const PropertyTrees* property_trees) {
- if (layer->layer_tree_host()->GetSettings().enable_transform_interop) {
+ if (layer->layer_tree_host()
+ ->GetSettings()
+ .enable_backface_visibility_interop) {
return IsTransformToRootOf3DRenderingContextBackFaceVisible(
layer, transform_tree_index, property_trees);
} else {
@@ -1446,9 +1515,11 @@ void CalculateDrawProperties(
UpdatePageScaleFactor(property_trees,
layer_tree_impl->PageScaleTransformNode(),
layer_tree_impl->current_page_scale_factor());
- UpdateElasticOverscroll(property_trees,
- layer_tree_impl->OverscrollElasticityTransformNode(),
- layer_tree_impl->current_elastic_overscroll());
+ UpdateElasticOverscroll(
+ property_trees, layer_tree_impl->OverscrollElasticityTransformNode(),
+ layer_tree_impl->OverscrollElasticityEffectElementId(),
+ layer_tree_impl->current_elastic_overscroll(),
+ layer_tree_impl->InnerViewportScrollNode());
// Similarly, the device viewport and device transform are shared
// by both trees.
property_trees->clip_tree.SetViewportClip(
diff --git a/chromium/cc/trees/effect_node.cc b/chromium/cc/trees/effect_node.cc
index bf2aa003a08..704f3ffa0d3 100644
--- a/chromium/cc/trees/effect_node.cc
+++ b/chromium/cc/trees/effect_node.cc
@@ -56,6 +56,7 @@ bool EffectNode::operator==(const EffectNode& other) const {
screen_space_opacity == other.screen_space_opacity &&
backdrop_filter_quality == other.backdrop_filter_quality &&
subtree_capture_id == other.subtree_capture_id &&
+ subtree_size == other.subtree_size &&
cache_render_surface == other.cache_render_surface &&
has_copy_request == other.has_copy_request &&
filters == other.filters &&
@@ -183,14 +184,16 @@ void EffectNode::AsValueInto(base::trace_event::TracedValue* value) const {
}
value->SetString("blend_mode", SkBlendMode_Name(blend_mode));
value->SetString("subtree_capture_id", subtree_capture_id.ToString());
+ value->SetString("subtree_size", subtree_size.ToString());
value->SetBoolean("cache_render_surface", cache_render_surface);
value->SetBoolean("has_copy_request", has_copy_request);
- value->SetBoolean("double_sided", double_sided);
value->SetBoolean("hidden_by_backface_visibility",
hidden_by_backface_visibility);
+ value->SetBoolean("double_sided", double_sided);
value->SetBoolean("trilinear_filtering", trilinear_filtering);
value->SetBoolean("is_drawn", is_drawn);
value->SetBoolean("only_draws_visible_content", only_draws_visible_content);
+ value->SetBoolean("subtree_hidden", subtree_hidden);
value->SetBoolean("has_potential_filter_animation",
has_potential_filter_animation);
value->SetBoolean("has_potential_backdrop_filter_animation",
@@ -200,6 +203,7 @@ void EffectNode::AsValueInto(base::trace_event::TracedValue* value) const {
value->SetBoolean("has_masking_child", has_masking_child);
value->SetBoolean("effect_changed", effect_changed);
value->SetBoolean("subtree_has_copy_request", subtree_has_copy_request);
+ value->SetBoolean("affected_by_backdrop_filter", affected_by_backdrop_filter);
value->SetString("render_surface_reason",
RenderSurfaceReasonToString(render_surface_reason));
value->SetInteger("transform_id", transform_id);
@@ -211,7 +215,6 @@ void EffectNode::AsValueInto(base::trace_event::TracedValue* value) const {
closest_ancestor_with_copy_request_id);
value->SetInteger("closest_ancestor_being_captured_id",
closest_ancestor_being_captured_id);
- value->SetBoolean("affected_by_backdrop_filter", affected_by_backdrop_filter);
}
} // namespace cc
diff --git a/chromium/cc/trees/effect_node.h b/chromium/cc/trees/effect_node.h
index 682befae955..36c0cfb9ad7 100644
--- a/chromium/cc/trees/effect_node.h
+++ b/chromium/cc/trees/effect_node.h
@@ -10,8 +10,10 @@
#include "cc/paint/element_id.h"
#include "cc/paint/filter_operations.h"
#include "components/viz/common/surfaces/subtree_capture_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkBlendMode.h"
#include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/size_f.h"
#include "ui/gfx/mask_filter_info.h"
#include "ui/gfx/rrect_f.h"
@@ -95,6 +97,7 @@ struct CC_EXPORT EffectNode {
gfx::Vector2dF surface_contents_scale;
viz::SubtreeCaptureId subtree_capture_id;
+ gfx::Size subtree_size;
bool cache_render_surface : 1;
bool has_copy_request : 1;
diff --git a/chromium/cc/trees/frame_rate_estimator_unittest.cc b/chromium/cc/trees/frame_rate_estimator_unittest.cc
index 03df3952a9b..9aa75eb03d1 100644
--- a/chromium/cc/trees/frame_rate_estimator_unittest.cc
+++ b/chromium/cc/trees/frame_rate_estimator_unittest.cc
@@ -4,7 +4,7 @@
#include "cc/trees/frame_rate_estimator.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/test/test_simple_task_runner.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/cc/trees/image_animation_controller.h b/chromium/cc/trees/image_animation_controller.h
index 22776f886f9..361f1fbc512 100644
--- a/chromium/cc/trees/image_animation_controller.h
+++ b/chromium/cc/trees/image_animation_controller.h
@@ -20,7 +20,6 @@
#include "cc/paint/paint_image_generator.h"
#include "cc/tiles/tile_priority.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
namespace cc {
class PaintImage;
diff --git a/chromium/cc/trees/layer_tree_host.cc b/chromium/cc/trees/layer_tree_host.cc
index 9a241b6ae4d..cf54a3665fe 100644
--- a/chromium/cc/trees/layer_tree_host.cc
+++ b/chromium/cc/trees/layer_tree_host.cc
@@ -25,7 +25,6 @@
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_math.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -57,7 +56,9 @@
#include "cc/trees/layer_tree_host_client.h"
#include "cc/trees/layer_tree_host_impl.h"
#include "cc/trees/layer_tree_impl.h"
+#include "cc/trees/mobile_optimized_viewport_util.h"
#include "cc/trees/mutator_host.h"
+#include "cc/trees/paint_holding_reason.h"
#include "cc/trees/property_tree_builder.h"
#include "cc/trees/proxy_main.h"
#include "cc/trees/render_frame_metadata_observer.h"
@@ -67,6 +68,7 @@
#include "cc/trees/transform_node.h"
#include "cc/trees/tree_synchronizer.h"
#include "cc/trees/ukm_manager.h"
+#include "components/viz/common/features.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/tracing/public/cpp/perfetto/flow_event_utils.h"
#include "services/tracing/public/cpp/perfetto/macros.h"
@@ -158,6 +160,35 @@ LayerTreeHost::LayerTreeHost(InitParams params, CompositorMode mode)
debug_state_.RecordRenderingStats());
}
+bool LayerTreeHost::IsMobileOptimized() const {
+ gfx::SizeF scrollable_viewport_size;
+ auto* inner_node =
+ property_trees()->scroll_tree.Node(viewport_property_ids_.inner_scroll);
+ if (!inner_node)
+ scrollable_viewport_size = gfx::SizeF();
+ else
+ scrollable_viewport_size = gfx::ScaleSize(
+ gfx::SizeF(inner_node->container_bounds),
+ 1.0f / (external_page_scale_factor_ * page_scale_factor()));
+
+ gfx::SizeF scrollable_size;
+ auto* scroll_node =
+ property_trees()->scroll_tree.Node(viewport_property_ids_.outer_scroll);
+ if (!scroll_node) {
+ DCHECK(!inner_node);
+ scrollable_size = gfx::SizeF();
+ } else {
+ const auto& scroll_tree = property_trees()->scroll_tree;
+ auto size = scroll_tree.scroll_bounds(scroll_node->id);
+ size.SetToMax(gfx::SizeF(scroll_tree.container_bounds(scroll_node->id)));
+ scrollable_size = size;
+ }
+
+ return util::IsMobileOptimized(
+ min_page_scale_factor(), max_page_scale_factor(), page_scale_factor(),
+ scrollable_viewport_size, scrollable_size, is_viewport_mobile_optimized_);
+}
+
void LayerTreeHost::InitializeThreaded(
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
@@ -604,16 +635,22 @@ void LayerTreeHost::OnDeferMainFrameUpdatesChanged(bool defer_status) {
client_->OnDeferMainFrameUpdatesChanged(defer_status);
}
-void LayerTreeHost::StartDeferringCommits(base::TimeDelta timeout) {
- proxy_->StartDeferringCommits(timeout);
+bool LayerTreeHost::StartDeferringCommits(base::TimeDelta timeout,
+ PaintHoldingReason reason) {
+ return proxy_->StartDeferringCommits(timeout, reason);
}
void LayerTreeHost::StopDeferringCommits(PaintHoldingCommitTrigger trigger) {
proxy_->StopDeferringCommits(trigger);
}
-void LayerTreeHost::OnDeferCommitsChanged(bool defer_status) {
- client_->OnDeferCommitsChanged(defer_status);
+bool LayerTreeHost::IsDeferringCommits() const {
+ return proxy_->IsDeferringCommits();
+}
+
+void LayerTreeHost::OnDeferCommitsChanged(bool defer_status,
+ PaintHoldingReason reason) {
+ client_->OnDeferCommitsChanged(defer_status, reason);
}
DISABLE_CFI_PERF
@@ -641,6 +678,11 @@ void LayerTreeHost::SetNeedsCommit() {
events_metrics_manager_.SaveActiveEventMetrics();
}
+void LayerTreeHost::SetTargetLocalSurfaceId(
+ const viz::LocalSurfaceId& target_local_surface_id) {
+ proxy_->SetTargetLocalSurfaceId(target_local_surface_id);
+}
+
bool LayerTreeHost::RequestedMainFramePendingForTesting() const {
return proxy_->RequestedAnimatePending();
}
@@ -749,7 +791,7 @@ bool LayerTreeHost::UpdateLayers() {
void LayerTreeHost::DidPresentCompositorFrame(
uint32_t frame_token,
- std::vector<LayerTreeHost::PresentationTimeCallback> callbacks,
+ std::vector<PresentationTimeCallbackBuffer::MainCallback> callbacks,
const gfx::PresentationFeedback& feedback) {
for (auto& callback : callbacks)
std::move(callback).Run(feedback);
@@ -974,7 +1016,7 @@ void LayerTreeHost::UpdateScrollOffsetFromImpl(
SetNeedsUpdateLayers();
}
- scroll_tree.NotifyDidScroll(id, new_offset, snap_target_ids);
+ scroll_tree.NotifyDidCompositorScroll(id, new_offset, snap_target_ids);
} else if (Layer* layer = LayerByElementId(id)) {
layer->SetScrollOffsetFromImplSide(layer->scroll_offset() + delta);
SetNeedsUpdateLayers();
@@ -1122,7 +1164,7 @@ bool LayerTreeHost::IsThreaded() const {
}
void LayerTreeHost::RequestPresentationTimeForNextFrame(
- PresentationTimeCallback callback) {
+ PresentationTimeCallbackBuffer::MainCallback callback) {
pending_presentation_time_callbacks_.push_back(std::move(callback));
}
@@ -1269,6 +1311,13 @@ void LayerTreeHost::SetViewportRectAndScale(
}
}
+ // If a new viz::LocalSurfaceId has been provided, and the viewport has
+ // changed, we need not begin new frames until it has activated.
+ if (previous_local_surface_id != local_surface_id_from_parent &&
+ device_viewport_rect_changed && features::IsSurfaceSyncThrottling()) {
+ SetTargetLocalSurfaceId(local_surface_id_from_parent);
+ }
+
if (device_viewport_rect_changed || painted_device_scale_factor_changed ||
device_scale_factor_changed) {
SetPropertyTreesNeedRebuild();
@@ -1381,6 +1430,13 @@ void LayerTreeHost::UpdateViewportIsMobileOptimized(
SetNeedsCommit();
}
+void LayerTreeHost::SetPrefersReducedMotion(bool prefers_reduced_motion) {
+ if (prefers_reduced_motion_ == prefers_reduced_motion)
+ return;
+ prefers_reduced_motion_ = prefers_reduced_motion;
+ SetNeedsCommit();
+}
+
void LayerTreeHost::SetExternalPageScaleFactor(
float page_scale_factor,
bool is_external_pinch_gesture_active) {
@@ -1692,6 +1748,7 @@ void LayerTreeHost::PushLayerTreeHostPropertiesTo(
host_impl->SetDebugState(debug_state_);
host_impl->SetVisualDeviceViewportSize(visual_device_viewport_size_);
host_impl->set_viewport_mobile_optimized(is_viewport_mobile_optimized_);
+ host_impl->SetPrefersReducedMotion(prefers_reduced_motion_);
}
Layer* LayerTreeHost::LayerByElementId(ElementId element_id) const {
diff --git a/chromium/cc/trees/layer_tree_host.h b/chromium/cc/trees/layer_tree_host.h
index cefbb821f75..48b503c5ecf 100644
--- a/chromium/cc/trees/layer_tree_host.h
+++ b/chromium/cc/trees/layer_tree_host.h
@@ -41,12 +41,14 @@
#include "cc/metrics/frame_sequence_tracker.h"
#include "cc/metrics/web_vital_metrics.h"
#include "cc/paint/node_id.h"
+#include "cc/trees//presentation_time_callback_buffer.h"
#include "cc/trees/browser_controls_params.h"
#include "cc/trees/compositor_mode.h"
#include "cc/trees/layer_tree_frame_sink.h"
#include "cc/trees/layer_tree_host_client.h"
#include "cc/trees/layer_tree_settings.h"
#include "cc/trees/mutator_host.h"
+#include "cc/trees/paint_holding_reason.h"
#include "cc/trees/proxy.h"
#include "cc/trees/swap_promise.h"
#include "cc/trees/swap_promise_manager.h"
@@ -243,6 +245,12 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
// synchronization.
virtual void SetNeedsCommit();
+ // Notifies that a new viz::LocalSurfaceId has been set, ahead of it becoming
+ // activated. Requests that the compositor thread does not produce new frames
+ // until it has activated.
+ virtual void SetTargetLocalSurfaceId(
+ const viz::LocalSurfaceId& target_local_surface_id);
+
// Returns true after SetNeedsAnimate(), SetNeedsUpdateLayers() or
// SetNeedsCommit(), until it is satisfied.
bool RequestedMainFramePendingForTesting() const;
@@ -267,13 +275,17 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
// is the interval after which commits will restart if nothing stops
// deferring sooner. If multiple calls are made to StartDeferringCommits
// while deferal is active, the first timeout continues to apply.
- void StartDeferringCommits(base::TimeDelta timeout);
+ bool StartDeferringCommits(base::TimeDelta timeout,
+ PaintHoldingReason reason);
// Stop deferring commits immediately.
void StopDeferringCommits(PaintHoldingCommitTrigger);
+ // Returns true if commits are currently deferred.
+ bool IsDeferringCommits() const;
+
// Notification that the proxy started or stopped deferring commits.
- void OnDeferCommitsChanged(bool);
+ void OnDeferCommitsChanged(bool defer_status, PaintHoldingReason reason);
// Returns whether there are any outstanding ScopedDeferMainFrameUpdate,
// though commits may be deferred also when the local_surface_id_from_parent()
@@ -332,9 +344,8 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
// Registers a callback that is run when the next frame successfully makes it
// to the screen (it's entirely possible some frames may be dropped between
// the time this is called and the callback is run).
- using PresentationTimeCallback =
- base::OnceCallback<void(const gfx::PresentationFeedback&)>;
- void RequestPresentationTimeForNextFrame(PresentationTimeCallback callback);
+ void RequestPresentationTimeForNextFrame(
+ PresentationTimeCallbackBuffer::MainCallback callback);
// Registers a callback that is run when any ongoing scroll-animation ends. If
// there are no ongoing animations, then the callback is run immediately.
@@ -351,6 +362,7 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
struct ViewportPropertyIds {
int overscroll_elasticity_transform = TransformTree::kInvalidNodeId;
+ ElementId overscroll_elasticity_effect;
int page_scale_transform = TransformTree::kInvalidNodeId;
int inner_scroll = ScrollTree::kInvalidNodeId;
int outer_clip = ClipTree::kInvalidNodeId;
@@ -429,6 +441,11 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
void UpdateViewportIsMobileOptimized(bool is_viewport_mobile_optimized);
+ // Returns if the viewport is considered to be mobile optimized.
+ bool IsMobileOptimized() const;
+
+ void SetPrefersReducedMotion(bool prefers_reduced_motion);
+
void SetBrowserControlsParams(const BrowserControlsParams& params);
void SetBrowserControlsShownRatio(float top_ratio, float bottom_ratio);
@@ -621,7 +638,7 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
bool UpdateLayers();
void DidPresentCompositorFrame(
uint32_t frame_token,
- std::vector<LayerTreeHost::PresentationTimeCallback> callbacks,
+ std::vector<PresentationTimeCallbackBuffer::MainCallback> callbacks,
const gfx::PresentationFeedback& feedback);
// Called when the compositor completed page scale animation.
void DidCompletePageScaleAnimation();
@@ -900,6 +917,7 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
// <meta name="viewport" content="initial-scale=1.0">
bool is_viewport_mobile_optimized_ = false;
+ bool prefers_reduced_motion_ = false;
bool have_scroll_event_handlers_ = false;
EventListenerProperties event_listener_properties_
[static_cast<size_t>(EventListenerClass::kLast) + 1];
@@ -951,7 +969,8 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
// Presentation time callbacks requested for the next frame are initially
// added here.
- std::vector<PresentationTimeCallback> pending_presentation_time_callbacks_;
+ std::vector<PresentationTimeCallbackBuffer::MainCallback>
+ pending_presentation_time_callbacks_;
struct ScrollAnimationState {
ScrollAnimationState();
diff --git a/chromium/cc/trees/layer_tree_host_client.h b/chromium/cc/trees/layer_tree_host_client.h
index f411eefcfa5..00f3e63fd42 100644
--- a/chromium/cc/trees/layer_tree_host_client.h
+++ b/chromium/cc/trees/layer_tree_host_client.h
@@ -11,6 +11,7 @@
#include "base/time/time.h"
#include "cc/input/browser_controls_state.h"
#include "cc/metrics/frame_sequence_tracker_collection.h"
+#include "cc/trees/paint_holding_reason.h"
#include "cc/trees/property_tree.h"
#include "ui/gfx/geometry/scroll_offset.h"
#include "ui/gfx/geometry/vector2d_f.h"
@@ -119,8 +120,10 @@ class LayerTreeHostClient {
// Notification that the proxy started or stopped deferring main frame updates
virtual void OnDeferMainFrameUpdatesChanged(bool) = 0;
- // Notification that the proxy started or stopped deferring commits.
- virtual void OnDeferCommitsChanged(bool) = 0;
+ // Notification that the proxy started or stopped deferring commits. |reason|
+ // indicates why commits are/were deferred.
+ virtual void OnDeferCommitsChanged(bool defer_status,
+ PaintHoldingReason reason) = 0;
// Visual frame-based updates to the state of the LayerTreeHost are expected
// to happen only in calls to LayerTreeHostClient::UpdateLayerTreeHost, which
diff --git a/chromium/cc/trees/layer_tree_host_impl.cc b/chromium/cc/trees/layer_tree_host_impl.cc
index 78addb27c8e..63f61838cbf 100644
--- a/chromium/cc/trees/layer_tree_host_impl.cc
+++ b/chromium/cc/trees/layer_tree_host_impl.cc
@@ -93,6 +93,7 @@
#include "cc/trees/latency_info_swap_promise_monitor.h"
#include "cc/trees/layer_tree_frame_sink.h"
#include "cc/trees/layer_tree_impl.h"
+#include "cc/trees/mobile_optimized_viewport_util.h"
#include "cc/trees/mutator_host.h"
#include "cc/trees/presentation_time_callback_buffer.h"
#include "cc/trees/render_frame_metadata.h"
@@ -142,10 +143,11 @@ using ScrollThread = cc::InputHandler::ScrollThread;
namespace cc {
namespace {
-// Used to accommodate finite precision when comparing scaled viewport and
-// content widths. While this value may seem large, width=device-width on an N7
-// V1 saw errors of ~0.065 between computed window and content widths.
-const float kMobileViewportWidthEpsilon = 0.15f;
+// The threshold which determines at what point during a scroll, should the
+// tree priority change from SMOOTHNESS_TAKES_PRIORITY to
+// NEW_CONTENT_TAKES_PRIORITY. The threshold represents visible checkerboarded
+// area.
+const float kVisibleCheckerboardedThresholdForPreferNewContent = 0.3f;
// In BuildHitTestData we iterate all layers to find all layers that overlap
// OOPIFs, but when the number of layers is greater than
@@ -161,25 +163,13 @@ static_assert(kContainsSrgbCacheSize ==
gfx::DisplayColorSpaces::kConfigCount / 2,
"sRGB cache must match the size of DisplayColorSpaces");
-bool HasFixedPageScale(LayerTreeImpl* active_tree) {
- return active_tree->min_page_scale_factor() ==
- active_tree->max_page_scale_factor();
-}
-
-bool HasMobileViewport(LayerTreeImpl* active_tree) {
- float window_width_dip = active_tree->current_page_scale_factor() *
- active_tree->ScrollableViewportSize().width();
- float content_width_css = active_tree->ScrollableSize().width();
- return content_width_css <= window_width_dip + kMobileViewportWidthEpsilon;
-}
-
bool IsMobileOptimized(LayerTreeImpl* active_tree) {
- bool has_mobile_viewport = HasMobileViewport(active_tree);
- bool has_fixed_page_scale = HasFixedPageScale(active_tree);
- return has_fixed_page_scale || has_mobile_viewport ||
- (base::FeatureList::IsEnabled(
- ::features::kRemoveMobileViewportDoubleTap) &&
- active_tree->viewport_mobile_optimized());
+ return util::IsMobileOptimized(active_tree->min_page_scale_factor(),
+ active_tree->max_page_scale_factor(),
+ active_tree->current_page_scale_factor(),
+ active_tree->ScrollableViewportSize(),
+ active_tree->ScrollableSize(),
+ active_tree->viewport_mobile_optimized());
}
viz::ResourceFormat TileRasterBufferFormat(
@@ -244,16 +234,16 @@ void ApplyFirstScrollTracking(const ui::LatencyInfo* latency,
return;
}
- // Construct a callback that, given presentation feedback, will report the
- // time span between the scroll input-event creation and the
+ // Construct a callback that, given a successful presentation timestamp, will
+ // report the time span between the scroll input-event creation and the
// presentation timestamp.
- LayerTreeHost::PresentationTimeCallback presentation_callback =
+ PresentationTimeCallbackBuffer::CompositorCallback presentation_callback =
base::BindOnce(
[](base::TimeTicks event_creation,
LayerTreeHostImpl* layer_tree_host_impl,
- const gfx::PresentationFeedback& feedback) {
+ base::TimeTicks presentation_timestamp) {
layer_tree_host_impl->DidObserveScrollDelay(
- feedback.timestamp - event_creation, event_creation);
+ presentation_timestamp - event_creation, event_creation);
},
creation_timestamp, impl);
@@ -334,6 +324,7 @@ void LayerTreeHostImpl::DidStartScroll() {
void LayerTreeHostImpl::DidEndScroll() {
scroll_affects_scroll_handler_ = false;
+ current_scroll_did_checkerboard_large_area_ = false;
}
void LayerTreeHostImpl::DidMouseLeave() {
@@ -1026,9 +1017,9 @@ void LayerTreeHostImpl::FrameData::AsValueInto(
}
if (quads_enabled) {
value->BeginArray("render_passes");
- for (size_t i = 0; i < render_passes.size(); ++i) {
+ for (const auto& render_pass : render_passes) {
value->BeginDictionary();
- render_passes[i]->AsValueInto(value);
+ render_pass->AsValueInto(value);
value->EndDictionary();
}
value->EndArray();
@@ -1290,6 +1281,9 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
layer->transform_tree_index(),
target_render_pass);
}
+ } else {
+ if (settings_.enable_compositing_based_throttling)
+ throttle_decider_.ProcessLayerNotToDraw(layer);
}
rendering_stats_instrumentation_->AddVisibleContentArea(
@@ -1331,6 +1325,18 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
append_quads_data.use_default_lower_bound_deadline;
}
+ if (total_visible_area > 0 &&
+ GetActivelyScrollingType() != ActivelyScrollingType::kNone) {
+ float visible_area_checkerboarded_ratio =
+ (checkerboarded_no_recording_content_area +
+ checkerboarded_needs_raster_content_area) /
+ total_visible_area;
+ if (visible_area_checkerboarded_ratio >
+ kVisibleCheckerboardedThresholdForPreferNewContent) {
+ SetCurrentScrollDidCheckerboardLargeArea();
+ }
+ }
+
// If CommitToActiveTree() is true, then we wait to draw until
// NotifyReadyToDraw. That means we're in as good shape as is possible now,
// so there's no reason to stop the draw now (and this is not supported by
@@ -1509,13 +1515,13 @@ DrawResult LayerTreeHostImpl::PrepareToDraw(FrameData* frame) {
UMA_HISTOGRAM_CUSTOM_COUNTS(
base::StringPrintf("Compositing.%s.NumActiveLayers", client_name),
- base::saturated_cast<int>(active_tree_->NumLayers()), 1, 400, 20);
+ base::saturated_cast<int>(active_tree_->NumLayers()), 1, 1000, 20);
UMA_HISTOGRAM_CUSTOM_COUNTS(
base::StringPrintf("Compositing.%s.NumActivePictureLayers",
client_name),
base::saturated_cast<int>(active_tree_->picture_layers().size()), 1,
- 400, 20);
+ 1000, 20);
// TODO(pdr): Instead of skipping empty picture layers, maybe we should
// accumulate layer->GetRasterSource()->GetMemoryUsage() above and skip
@@ -1752,6 +1758,11 @@ void LayerTreeHostImpl::DidModifyTilePriorities() {
client_->SetNeedsPrepareTilesOnImplThread();
}
+void LayerTreeHostImpl::SetTargetLocalSurfaceId(
+ const viz::LocalSurfaceId& target_local_surface_id) {
+ target_local_surface_id_ = target_local_surface_id;
+}
+
std::unique_ptr<RasterTilePriorityQueue> LayerTreeHostImpl::BuildRasterQueue(
TreePriority tree_priority,
RasterTilePriorityQueue::Type type) {
@@ -2041,8 +2052,14 @@ void LayerTreeHostImpl::DidReceiveCompositorFrameAck() {
void LayerTreeHostImpl::DidPresentCompositorFrame(
uint32_t frame_token,
const viz::FrameTimingDetails& details) {
+ // Presentation callbacks registered on the compositor thread are expected to
+ // be called on the first successful presentation. So, if the presentation is
+ // failed, we only pop main thread callbacks at this point and leave
+ // compositor thread callbacks alone until a successful presentation.
+ const bool main_callbacks_only = details.presentation_feedback.failed();
PresentationTimeCallbackBuffer::PendingCallbacks activated_callbacks =
- presentation_time_callbacks_.PopPendingCallbacks(frame_token);
+ presentation_time_callbacks_.PopPendingCallbacks(frame_token,
+ main_callbacks_only);
// Send all tasks to the client so that it can decide which tasks
// should run on which thread.
@@ -2426,7 +2443,8 @@ bool LayerTreeHostImpl::DrawLayers(FrameData* frame) {
active_tree_->ResetAllChangeTracking();
active_tree_->set_has_ever_been_drawn(true);
- devtools_instrumentation::DidDrawFrame(id_);
+ devtools_instrumentation::DidDrawFrame(
+ id_, frame->begin_frame_ack.frame_id.sequence_number);
benchmark_instrumentation::IssueImplThreadRenderingStatsEvent(
rendering_stats_instrumentation_->TakeImplThreadRenderingStats());
@@ -2811,20 +2829,20 @@ void LayerTreeHostImpl::UpdateTreeResourcesForGpuRasterizationIfNeeded() {
SetRequiresHighResToDraw();
}
-void LayerTreeHostImpl::RegisterMainThreadPresentationTimeCallback(
+void LayerTreeHostImpl::RegisterMainThreadPresentationTimeCallbackForTesting(
uint32_t frame_token,
- LayerTreeHost::PresentationTimeCallback callback) {
- std::vector<LayerTreeHost::PresentationTimeCallback> as_vector;
- as_vector.emplace_back(std::move(callback));
+ PresentationTimeCallbackBuffer::MainCallback callback) {
+ std::vector<PresentationTimeCallbackBuffer::MainCallback> as_vector;
+ as_vector.push_back(std::move(callback));
presentation_time_callbacks_.RegisterMainThreadPresentationCallbacks(
frame_token, std::move(as_vector));
}
void LayerTreeHostImpl::RegisterCompositorPresentationTimeCallback(
uint32_t frame_token,
- LayerTreeHost::PresentationTimeCallback callback) {
- std::vector<LayerTreeHost::PresentationTimeCallback> as_vector;
- as_vector.emplace_back(std::move(callback));
+ PresentationTimeCallbackBuffer::CompositorCallback callback) {
+ std::vector<PresentationTimeCallbackBuffer::CompositorCallback> as_vector;
+ as_vector.push_back(std::move(callback));
presentation_time_callbacks_.RegisterCompositorPresentationCallbacks(
frame_token, std::move(as_vector));
}
@@ -2834,11 +2852,27 @@ bool LayerTreeHostImpl::WillBeginImplFrame(const viz::BeginFrameArgs& args) {
current_begin_frame_tracker_.Start(args);
frame_trackers_.NotifyBeginImplFrame(args);
total_frame_counter_.OnBeginFrame(args);
- devtools_instrumentation::DidBeginFrame(id_, args.frame_time);
+ devtools_instrumentation::DidBeginFrame(id_, args.frame_time,
+ args.frame_id.sequence_number);
UMA_HISTOGRAM_CUSTOM_COUNTS("GPU.AcceleratedSurfaceRefreshRate",
1 / args.interval.InSecondsF(), 0, 121, 122);
+ // When there is a |target_local_surface_id_|, we do not wish to begin
+ // producing Impl Frames for an older viz::LocalSurfaceId, as it will never
+ // be displayed.
+ //
+ // Once the Main thread has finished adjusting to the new visual properties,
+ // it will push the updated viz::LocalSurfaceId. Begin Impl Frame production
+ // if it has already become activated, or is on the |pending_tree| to be
+ // activated during this frame's production.
+ const viz::LocalSurfaceId& upcoming_lsid =
+ pending_tree() ? pending_tree()->local_surface_id_from_parent()
+ : active_tree()->local_surface_id_from_parent();
+ if (target_local_surface_id_.IsNewerThan(upcoming_lsid)) {
+ return false;
+ }
+
if (is_likely_to_require_a_draw_) {
// Optimistically schedule a draw. This will let us expect the tile manager
// to complete its work so that we can draw new tiles within the impl frame
@@ -3139,8 +3173,9 @@ void LayerTreeHostImpl::CreatePendingTree() {
pending_tree_fully_painted_ = false;
client_->OnCanDrawStateChanged(CanDraw());
- TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("cc", "PendingTree:waiting",
- TRACE_ID_LOCAL(pending_tree_.get()));
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
+ "cc", "PendingTree:waiting", TRACE_ID_LOCAL(pending_tree_.get()),
+ "active_lsid", active_tree()->local_surface_id_from_parent().ToString());
}
void LayerTreeHostImpl::PushScrollbarOpacitiesFromActiveToPending() {
@@ -3174,8 +3209,10 @@ void LayerTreeHostImpl::PushScrollbarOpacitiesFromActiveToPending() {
void LayerTreeHostImpl::ActivateSyncTree() {
TRACE_EVENT0("cc,benchmark", "LayerTreeHostImpl::ActivateSyncTree()");
if (pending_tree_) {
- TRACE_EVENT_NESTABLE_ASYNC_END0("cc", "PendingTree:waiting",
- TRACE_ID_LOCAL(pending_tree_.get()));
+ TRACE_EVENT_NESTABLE_ASYNC_END1(
+ "cc", "PendingTree:waiting", TRACE_ID_LOCAL(pending_tree_.get()),
+ "pending_lsid",
+ pending_tree_->local_surface_id_from_parent().ToString());
active_tree_->lifecycle().AdvanceTo(LayerTreeLifecycle::kBeginningSync);
// In most cases, this will be reset in NotifyReadyToActivate, since we
@@ -3965,6 +4002,7 @@ float LayerTreeHostImpl::PageScaleFactor() const {
void LayerTreeHostImpl::BindToInputHandler(
std::unique_ptr<InputDelegateForCompositor> delegate) {
input_delegate_ = std::move(delegate);
+ input_delegate_->SetPrefersReducedMotion(prefers_reduced_motion_);
}
void LayerTreeHostImpl::SetVisualDeviceViewportSize(
@@ -3976,6 +4014,15 @@ gfx::Size LayerTreeHostImpl::VisualDeviceViewportSize() const {
return visual_device_viewport_size_;
}
+void LayerTreeHostImpl::SetPrefersReducedMotion(bool prefers_reduced_motion) {
+ if (prefers_reduced_motion_ == prefers_reduced_motion)
+ return;
+
+ prefers_reduced_motion_ = prefers_reduced_motion;
+ if (input_delegate_)
+ input_delegate_->SetPrefersReducedMotion(prefers_reduced_motion_);
+}
+
ScrollTree& LayerTreeHostImpl::GetScrollTree() const {
return active_tree_->property_trees()->scroll_tree;
}
@@ -4944,13 +4991,12 @@ void LayerTreeHostImpl::SetUkmSmoothnessDestination(
void LayerTreeHostImpl::NotifyDidPresentCompositorFrameOnImplThread(
uint32_t frame_token,
- std::vector<LayerTreeHost::PresentationTimeCallback> callbacks,
+ std::vector<PresentationTimeCallbackBuffer::CompositorCallback> callbacks,
const viz::FrameTimingDetails& details) {
frame_trackers_.NotifyFramePresented(frame_token,
details.presentation_feedback);
- for (LayerTreeHost::PresentationTimeCallback& callback : callbacks) {
- std::move(callback).Run(details.presentation_feedback);
- }
+ for (auto& callback : callbacks)
+ std::move(callback).Run(details.presentation_feedback.timestamp);
}
void LayerTreeHostImpl::AllocateLocalSurfaceId() {
diff --git a/chromium/cc/trees/layer_tree_host_impl.h b/chromium/cc/trees/layer_tree_host_impl.h
index bf8b7a8a7bd..1d79f4bfaf2 100644
--- a/chromium/cc/trees/layer_tree_host_impl.h
+++ b/chromium/cc/trees/layer_tree_host_impl.h
@@ -403,6 +403,8 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient,
return is_viewport_mobile_optimized_;
}
+ void SetPrefersReducedMotion(bool prefers_reduced_motion);
+
// Updates registered ElementIds present in |changed_list|. Call this after
// changing the property trees for the |changed_list| trees.
void UpdateElements(ElementListType changed_list);
@@ -601,27 +603,37 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient,
uint32_t next_frame_token() const { return *next_frame_token_; }
- // Buffers |callback| until a relevant frame swap ocurrs, at which point the
- // callback will be posted to run on the main thread. A frame swap is
- // considered relevant if the swapped frame's token is greater than or equal
- // to |frame_token|.
- void RegisterMainThreadPresentationTimeCallback(
+ // Buffers `callback` until a relevant presentation feedback arrives, at which
+ // point the callback will be posted to run on the main thread. A presentation
+ // feedback is considered relevant if the frame's token is greater than or
+ // equal to `frame_token`.
+ void RegisterMainThreadPresentationTimeCallbackForTesting(
uint32_t frame_token,
- LayerTreeHost::PresentationTimeCallback callback);
+ PresentationTimeCallbackBuffer::MainCallback callback);
- // Buffers |callback| until a relevant frame swap ocurrs, at which point the
- // callback will be run on the compositor thread. A frame swap is considered
- // relevant if the swapped frame's token is greater than or equal to
- // |frame_token|.
+ // Buffers `callback` until a relevant successful presentation occurs, at
+ // which point the callback will be run on the compositor thread. A successful
+ // presentation is considered relevant if the presented frame's token is
+ // greater than or equal to `frame_token`.
void RegisterCompositorPresentationTimeCallback(
uint32_t frame_token,
- LayerTreeHost::PresentationTimeCallback callback);
+ PresentationTimeCallbackBuffer::CompositorCallback callback);
virtual bool WillBeginImplFrame(const viz::BeginFrameArgs& args);
virtual void DidFinishImplFrame(const viz::BeginFrameArgs& args);
void DidNotProduceFrame(const viz::BeginFrameAck& ack,
FrameSkippedReason reason);
void DidModifyTilePriorities();
+ // Requests that we do not produce frames until the new viz::LocalSurfaceId
+ // has been activated.
+ void SetTargetLocalSurfaceId(
+ const viz::LocalSurfaceId& target_local_surface_id);
+ const viz::LocalSurfaceId& target_local_surface_id() const {
+ return target_local_surface_id_;
+ }
+ const viz::LocalSurfaceId& last_draw_local_surface_id() const {
+ return last_draw_local_surface_id_;
+ }
LayerTreeImpl* active_tree() { return active_tree_.get(); }
const LayerTreeImpl* active_tree() const { return active_tree_.get(); }
@@ -651,6 +663,12 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient,
// See comment in equivalent ThreadedInputHandler method for what this means.
ActivelyScrollingType GetActivelyScrollingType() const;
bool ScrollAffectsScrollHandler() const;
+ bool CurrentScrollDidCheckerboardLargeArea() const {
+ return current_scroll_did_checkerboard_large_area_;
+ }
+ void SetCurrentScrollDidCheckerboardLargeArea() {
+ current_scroll_did_checkerboard_large_area_ = true;
+ }
void SetExternalPinchGestureActive(bool active);
void set_force_smooth_wheel_scrolling_for_testing(bool enabled) {
GetInputHandler().set_force_smooth_wheel_scrolling_for_testing(enabled);
@@ -820,7 +838,7 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient,
// was presented.
void NotifyDidPresentCompositorFrameOnImplThread(
uint32_t frame_token,
- std::vector<LayerTreeHost::PresentationTimeCallback> callbacks,
+ std::vector<PresentationTimeCallbackBuffer::CompositorCallback> callbacks,
const viz::FrameTimingDetails& details);
CompositorFrameReportingController* compositor_frame_reporting_controller()
@@ -855,6 +873,10 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient,
return pending_raster_queries_.get();
}
+ base::flat_set<viz::FrameSinkId> GetFrameSinksToThrottleForTesting() const {
+ return throttle_decider_.ids();
+ }
+
protected:
LayerTreeHostImpl(
const LayerTreeSettings& settings,
@@ -1156,6 +1178,8 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient,
// <meta name="viewport" content="initial-scale=1.0">
bool is_viewport_mobile_optimized_ = false;
+ bool prefers_reduced_motion_ = false;
+
std::unique_ptr<PendingTreeRasterDurationHistogramTimer>
pending_tree_raster_duration_timer_;
@@ -1183,6 +1207,8 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient,
viz::LocalSurfaceId last_draw_local_surface_id_;
base::flat_set<viz::SurfaceRange> last_draw_referenced_surfaces_;
absl::optional<RenderFrameMetadata> last_draw_render_frame_metadata_;
+ // The viz::LocalSurfaceId to unthrottle drawing for.
+ viz::LocalSurfaceId target_local_surface_id_;
viz::ChildLocalSurfaceIdAllocator child_local_surface_id_allocator_;
// Indicates the direction of the last vertical scroll of the root layer.
@@ -1220,6 +1246,11 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient,
// sophisticated since so it's not clear how much value it's still providing.
bool scroll_affects_scroll_handler_ = false;
+ // Whether at least 30% of the viewport at the time of draw was
+ // checkerboarded during a scroll. This bit can get set during a scroll and
+ // is sticky for the duration of the scroll.
+ bool current_scroll_did_checkerboard_large_area_ = false;
+
// Provides support for PaintWorklets which depend on input properties that
// are being animated by the compositor (aka 'animated' PaintWorklets).
// Responsible for storing animated custom property values and for
diff --git a/chromium/cc/trees/layer_tree_host_impl_unittest.cc b/chromium/cc/trees/layer_tree_host_impl_unittest.cc
index e937bb490aa..19a4006dd4a 100644
--- a/chromium/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/chromium/cc/trees/layer_tree_host_impl_unittest.cc
@@ -264,7 +264,9 @@ class LayerTreeHostImplTest : public testing::Test,
uint32_t frame_token,
PresentationTimeCallbackBuffer::PendingCallbacks activated,
const viz::FrameTimingDetails& details) override {
- std::move(activated.main_thread_callbacks);
+ // We don't call main thread callbacks in this test.
+ activated.main_thread_callbacks.clear();
+
host_impl_->NotifyDidPresentCompositorFrameOnImplThread(
frame_token, std::move(activated.compositor_thread_callbacks), details);
}
@@ -891,6 +893,16 @@ class CommitToPendingTreeLayerTreeHostImplTest : public LayerTreeHostImplTest {
}
};
+class OccludedSurfaceThrottlingLayerTreeHostImplTest
+ : public LayerTreeHostImplTest {
+ public:
+ void SetUp() override {
+ LayerTreeSettings settings = DefaultSettings();
+ settings.enable_compositing_based_throttling = true;
+ CreateHostImpl(settings, CreateLayerTreeFrameSink());
+ }
+};
+
// A test fixture for new animation timelines tests.
class LayerTreeHostImplTimelinesTest : public LayerTreeHostImplTest {
public:
@@ -916,6 +928,7 @@ class TestInputHandlerClient : public InputHandlerClient {
void WillShutdown() override {}
void Animate(base::TimeTicks time) override {}
void ReconcileElasticOverscrollAndRootScroll() override {}
+ void SetPrefersReducedMotion(bool prefers_reduced_motion) override {}
void UpdateRootLayerStateForSynchronousInputHandler(
const gfx::ScrollOffset& total_scroll_offset,
const gfx::ScrollOffset& max_scroll_offset,
@@ -1679,10 +1692,8 @@ class LayerTreeHostImplTestInvokeMainThreadCallbacks
auto main_thread_callbacks = std::move(activated.main_thread_callbacks);
host_impl_->NotifyDidPresentCompositorFrameOnImplThread(
frame_token, std::move(activated.compositor_thread_callbacks), details);
- for (LayerTreeHost::PresentationTimeCallback& callback :
- main_thread_callbacks) {
+ for (auto& callback : main_thread_callbacks)
std::move(callback).Run(details.presentation_feedback);
- }
}
};
@@ -1692,25 +1703,27 @@ TEST_F(LayerTreeHostImplTestInvokeMainThreadCallbacks,
PresentationFeedbackCallbacksFire) {
bool compositor_thread_callback_fired = false;
bool main_thread_callback_fired = false;
- gfx::PresentationFeedback feedback_seen_by_compositor_thread_callback;
+ base::TimeTicks presentation_time_seen_by_compositor_thread_callback;
gfx::PresentationFeedback feedback_seen_by_main_thread_callback;
// Register a compositor-thread callback to run when the frame for
// |frame_token_1| gets presented.
constexpr uint32_t frame_token_1 = 1;
host_impl_->RegisterCompositorPresentationTimeCallback(
- frame_token_1, base::BindLambdaForTesting(
- [&](const gfx::PresentationFeedback& feedback) {
- compositor_thread_callback_fired = true;
- feedback_seen_by_compositor_thread_callback =
- feedback;
- }));
+ frame_token_1,
+ base::BindLambdaForTesting([&](base::TimeTicks presentation_timestamp) {
+ DCHECK(presentation_time_seen_by_compositor_thread_callback.is_null());
+ DCHECK(!presentation_timestamp.is_null());
+ compositor_thread_callback_fired = true;
+ presentation_time_seen_by_compositor_thread_callback =
+ presentation_timestamp;
+ }));
// Register a main-thread callback to run when the frame for |frame_token_2|
// gets presented.
constexpr uint32_t frame_token_2 = 2;
ASSERT_GT(frame_token_2, frame_token_1);
- host_impl_->RegisterMainThreadPresentationTimeCallback(
+ host_impl_->RegisterMainThreadPresentationTimeCallbackForTesting(
frame_token_2, base::BindLambdaForTesting(
[&](const gfx::PresentationFeedback& feedback) {
main_thread_callback_fired = true;
@@ -1723,8 +1736,8 @@ TEST_F(LayerTreeHostImplTestInvokeMainThreadCallbacks,
host_impl_->DidPresentCompositorFrame(frame_token_1, mock_details);
EXPECT_TRUE(compositor_thread_callback_fired);
- EXPECT_EQ(feedback_seen_by_compositor_thread_callback,
- mock_details.presentation_feedback);
+ EXPECT_EQ(presentation_time_seen_by_compositor_thread_callback,
+ mock_details.presentation_feedback.timestamp);
// Since |frame_token_2| is strictly greater than |frame_token_1|, the
// main-thread callback must remain queued for now.
@@ -3242,7 +3255,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollNodeWithoutScrollLayer) {
EXPECT_FALSE(status.needs_main_thread_hit_test);
} else {
EXPECT_EQ(ScrollThread::SCROLL_ON_MAIN_THREAD, status.thread);
- EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion,
+ EXPECT_EQ(MainThreadScrollingReason::kNoScrollingLayer,
status.main_thread_scrolling_reasons);
}
}
@@ -3461,22 +3474,88 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest,
class MissingTilesLayer : public LayerImpl {
public:
- MissingTilesLayer(LayerTreeImpl* layer_tree_impl, int id)
- : LayerImpl(layer_tree_impl, id), has_missing_tiles_(true) {}
-
- void set_has_missing_tiles(bool has_missing_tiles) {
- has_missing_tiles_ = has_missing_tiles;
+ static std::unique_ptr<MissingTilesLayer> Create(LayerTreeImpl* tree_impl,
+ int id) {
+ return base::WrapUnique(new MissingTilesLayer(tree_impl, id));
}
+ MissingTilesLayer(LayerTreeImpl* layer_tree_impl, int id)
+ : LayerImpl(layer_tree_impl, id) {}
void AppendQuads(viz::CompositorRenderPass* render_pass,
AppendQuadsData* append_quads_data) override {
- append_quads_data->num_missing_tiles += has_missing_tiles_;
+ append_quads_data->num_missing_tiles += 10;
+ append_quads_data->checkerboarded_no_recording_content_area += 200;
+ append_quads_data->checkerboarded_needs_raster_content_area += 200;
+ append_quads_data->visible_layer_area += 200;
}
-
- private:
- bool has_missing_tiles_;
};
+TEST_P(ScrollUnifiedLayerTreeHostImplTest,
+ CurrentScrollDidCheckerboardLargeArea) {
+ LayerTreeSettings settings = DefaultSettings();
+ CreateHostImpl(settings, CreateLayerTreeFrameSink());
+ host_impl_->active_tree()->PushPageScaleFromMainThread(1, 0.25f, 4);
+
+ const gfx::Size content_size(1000, 1000);
+ const gfx::Size viewport_size(500, 500);
+ SetupViewportLayersOuterScrolls(viewport_size, content_size);
+
+ LayerImpl* outer_scroll_layer = OuterViewportScrollLayer();
+ outer_scroll_layer->SetDrawsContent(true);
+ LayerImpl* inner_scroll_layer = InnerViewportScrollLayer();
+ inner_scroll_layer->SetDrawsContent(true);
+
+ // Add layer that draws content and has checkerboarded areas.
+ auto* scroll_layer = AddLayer<MissingTilesLayer>(host_impl_->active_tree());
+ CopyProperties(inner_scroll_layer, scroll_layer);
+ scroll_layer->SetBounds(gfx::Size(500, 500));
+ scroll_layer->SetDrawsContent(true);
+ scroll_layer->SetHitTestable(false);
+ host_impl_->active_tree()->SetElementIdsForTesting();
+
+ UpdateDrawProperties(host_impl_->active_tree());
+
+ DrawFrame();
+
+ // No scroll has taken place so this should be false.
+ EXPECT_FALSE(host_impl_->CurrentScrollDidCheckerboardLargeArea());
+
+ // Send scroll begin.
+ GetInputHandler().ScrollBegin(
+ BeginState(gfx::Point(250, 250), gfx::Vector2dF(),
+ ui::ScrollInputType::kTouchscreen)
+ .get(),
+ ui::ScrollInputType::kTouchscreen);
+
+ DrawFrame();
+
+ // Even though a ScrollBegin has been processed, we still don't consider the
+ // interaction to be "actively scrolling". Expect this to be false.
+ EXPECT_FALSE(host_impl_->CurrentScrollDidCheckerboardLargeArea());
+
+ gfx::ScrollOffset scroll_delta(0, 10);
+
+ // Send scroll update.
+ GetInputHandler().ScrollUpdate(
+ UpdateState(gfx::Point(10, 10),
+ gfx::ScrollOffsetToVector2dF(scroll_delta),
+ ui::ScrollInputType::kWheel)
+ .get());
+
+ host_impl_->SetFullViewportDamage();
+ DrawFrame();
+
+ // Now that a scroll update has been processed and the latest
+ // CalculateRenderPasses run has computed significant visible checkerboarding,
+ // expect this flag to be true.
+ EXPECT_TRUE(host_impl_->CurrentScrollDidCheckerboardLargeArea());
+
+ GetInputHandler().ScrollEnd();
+
+ // Expect state to be reset after a scroll end.
+ EXPECT_FALSE(host_impl_->CurrentScrollDidCheckerboardLargeArea());
+}
+
TEST_P(ScrollUnifiedLayerTreeHostImplTest, ImplPinchZoom) {
SetupViewportLayersInnerScrolls(gfx::Size(50, 50), gfx::Size(100, 100));
DrawFrame();
@@ -11668,7 +11747,8 @@ TEST_P(LayerTreeHostImplTestWithRenderer, ShutdownReleasesContext) {
GetPropertyTrees(root)->effect_tree.AddCopyRequest(
root->effect_tree_index(),
std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_TEXTURE,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kNativeTextures,
base::BindOnce(&Helper::OnResult, base::Unretained(&helper),
copy_request_run_loop.QuitClosure())));
DrawFrame();
@@ -12017,7 +12097,7 @@ class LayerTreeHostImplWithBrowserControlsTest : public LayerTreeHostImplTest {
settings.commit_to_active_tree = false;
CreateHostImpl(settings, CreateLayerTreeFrameSink());
host_impl_->active_tree()->SetBrowserControlsParams(
- {top_controls_height_, 0, 0, 0, false, false});
+ {static_cast<float>(top_controls_height_), 0, 0, 0, false, false});
host_impl_->active_tree()->SetCurrentBrowserControlsShownRatio(1.f, 1.f);
}
@@ -18083,6 +18163,33 @@ TEST_F(UnifiedScrollingTest, CompositedWithSquashedLayerMutatesTransform) {
ScrollEnd();
}
+// Verifies that when a surface layer is occluded, its frame sink id will be
+// marked as qualified for throttling.
+TEST_F(OccludedSurfaceThrottlingLayerTreeHostImplTest,
+ ThrottleOccludedSurface) {
+ LayerTreeImpl* tree = host_impl_->active_tree();
+ gfx::Rect viewport_rect(0, 0, 800, 600);
+ auto* root = SetupRootLayer<LayerImpl>(tree, viewport_rect.size());
+
+ auto* occluded = AddLayer<SurfaceLayerImpl>(tree);
+ occluded->SetBounds(gfx::Size(400, 300));
+ occluded->SetDrawsContent(true);
+ viz::SurfaceId start = MakeSurfaceId(viz::FrameSinkId(1, 2), 1);
+ viz::SurfaceId end = MakeSurfaceId(viz::FrameSinkId(3, 4), 1);
+ occluded->SetRange(viz::SurfaceRange(start, end), 2u);
+ CopyProperties(root, occluded);
+
+ auto* occluder = AddLayer<SolidColorLayerImpl>(tree);
+ occluder->SetBounds(gfx::Size(400, 400));
+ occluder->SetDrawsContent(true);
+ occluder->SetContentsOpaque(true);
+ CopyProperties(root, occluder);
+
+ DrawFrame();
+ EXPECT_EQ(host_impl_->GetFrameSinksToThrottleForTesting(),
+ base::flat_set<viz::FrameSinkId>{end.frame_sink_id()});
+}
+
TEST_F(LayerTreeHostImplTest, FrameElementIdHitTestSimple) {
SetupDefaultRootLayer(gfx::Size(100, 100));
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc b/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc
index 98bb4f49eb5..5289f95ac8f 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc
@@ -4,7 +4,7 @@
#include <stdint.h>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "build/build_config.h"
#include "cc/layers/solid_color_layer.h"
#include "cc/paint/paint_image.h"
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc
index d858c5bad32..19f076021e8 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc
@@ -4,7 +4,7 @@
#include <stddef.h>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "build/build_config.h"
#include "cc/layers/content_layer_client.h"
#include "cc/layers/picture_layer.h"
@@ -764,7 +764,7 @@ class LayerTreeHostMaskAsBlendingPixelTest
// ARM Windows, macOS, and Fuchsia has some pixels difference
// Affected tests: RotatedClippedCircle, RotatedClippedCircleUnderflow
// crbug.com/1030244, crbug.com/1048249, crbug.com/1128443
- percentage_pixels_error = 6.1f;
+ percentage_pixels_error = 6.2f;
average_error_allowed_in_bad_pixels = 5.f;
large_error_allowed = 20;
#else
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc b/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc
index f52003c1912..b734b02d11f 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc
@@ -66,14 +66,16 @@ class LayerTreeHostReadbackPixelTest
if (readback_type() == TestReadBackType::kBitmap) {
request = std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(
&LayerTreeHostReadbackPixelTest::ReadbackResultAsBitmap,
base::Unretained(this)));
} else {
DCHECK_NE(renderer_type_, viz::RendererType::kSoftware);
request = std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_TEXTURE,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kNativeTextures,
base::BindOnce(
&LayerTreeHostReadbackPixelTest::ReadbackResultAsTexture,
base::Unretained(this)));
@@ -114,17 +116,24 @@ class LayerTreeHostReadbackPixelTest
void ReadbackResultAsTexture(std::unique_ptr<viz::CopyOutputResult> result) {
EXPECT_TRUE(task_runner_provider()->IsMainThread());
- ASSERT_EQ(result->format(), viz::CopyOutputResult::Format::RGBA_TEXTURE);
-
- gpu::Mailbox mailbox = result->GetTextureResult()->mailbox;
- gpu::SyncToken sync_token = result->GetTextureResult()->sync_token;
+ ASSERT_FALSE(result->IsEmpty());
+ ASSERT_EQ(result->format(), viz::CopyOutputResult::Format::RGBA);
+ ASSERT_EQ(result->destination(),
+ viz::CopyOutputResult::Destination::kNativeTextures);
+
+ gpu::Mailbox mailbox = result->GetTextureResult()->planes[0].mailbox;
+ gpu::SyncToken sync_token =
+ result->GetTextureResult()->planes[0].sync_token;
gfx::ColorSpace color_space = result->GetTextureResult()->color_space;
EXPECT_EQ(result->GetTextureResult()->color_space, output_color_space_);
- viz::ReleaseCallback release_callback = result->TakeTextureOwnership();
+
+ viz::CopyOutputResult::ReleaseCallbacks release_callbacks =
+ result->TakeTextureOwnership();
+ EXPECT_EQ(1u, release_callbacks.size());
SkBitmap bitmap =
CopyMailboxToBitmap(result->size(), mailbox, sync_token, color_space);
- std::move(release_callback).Run(gpu::SyncToken(), false);
+ std::move(release_callbacks[0]).Run(gpu::SyncToken(), false);
ReadbackResultAsBitmap(std::make_unique<viz::CopyOutputSkBitmapResult>(
result->rect(), std::move(bitmap)));
@@ -439,6 +448,7 @@ ReadbackTestConfig const kTestConfigs[] = {
#endif // BUILDFLAG(ENABLE_GL_BACKEND_TESTS)
#if BUILDFLAG(ENABLE_VULKAN_BACKEND_TESTS)
ReadbackTestConfig{viz::RendererType::kSkiaVk, TestReadBackType::kBitmap},
+ ReadbackTestConfig{viz::RendererType::kSkiaVk, TestReadBackType::kTexture},
#endif // BUILDFLAG(ENABLE_VULKAN_BACKEND_TESTS)
#if BUILDFLAG(ENABLE_DAWN_BACKEND_TESTS)
ReadbackTestConfig{viz::RendererType::kSkiaDawn, TestReadBackType::kBitmap},
diff --git a/chromium/cc/trees/layer_tree_host_unittest.cc b/chromium/cc/trees/layer_tree_host_unittest.cc
index ff324688b0d..ee9668d3820 100644
--- a/chromium/cc/trees/layer_tree_host_unittest.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest.cc
@@ -18,6 +18,7 @@
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
#include "base/test/bind.h"
+#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
@@ -59,12 +60,14 @@
#include "cc/trees/effect_node.h"
#include "cc/trees/layer_tree_host_impl.h"
#include "cc/trees/layer_tree_impl.h"
+#include "cc/trees/paint_holding_reason.h"
#include "cc/trees/scroll_node.h"
#include "cc/trees/single_thread_proxy.h"
#include "cc/trees/swap_promise.h"
#include "cc/trees/swap_promise_manager.h"
#include "cc/trees/transform_node.h"
#include "components/ukm/test_ukm_recorder.h"
+#include "components/viz/common/features.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/frame_sinks/copy_output_result.h"
@@ -651,7 +654,8 @@ class LayerTreeHostFreeContextResourcesOnDestroy
: public LayerTreeHostContextCacheTest {
public:
void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
if (!first_will_begin_impl_frame_)
return;
@@ -681,7 +685,8 @@ class LayerTreeHostCacheBehaviorOnLayerTreeFrameSinkRecreated
: public LayerTreeHostContextCacheTest {
public:
void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
// This code is run once, to trigger recreation of our LayerTreeFrameSink.
if (test_state_ != TestState::INIT)
return;
@@ -2680,6 +2685,225 @@ class LayerTreeHostTestDeviceScaleFactorChange : public LayerTreeHostTest {
SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestDeviceScaleFactorChange);
+// Tests that when the LayerTreeHost has received an updated Viewport Rect and
+// viz::LocalSurfaceId that the Impl Frame does not begin until the new tree has
+// been either activated or pushed as the new pending tree.
+class LayerTreeHostTestViewportRectChangeBlockedMainThread
+ : public LayerTreeHostTest {
+ public:
+ LayerTreeHostTestViewportRectChangeBlockedMainThread() {
+ scoped_feature_list_.InitAndEnableFeature(features::kSurfaceSyncThrottling);
+ }
+
+ void SetupTree() override {
+ root_layer_ = Layer::Create();
+ root_layer_->SetBounds(initial_size_);
+
+ child_layer_ = FakePictureLayer::Create(&client_);
+ child_layer_->SetBounds(gfx::Size(10, 10));
+ root_layer_->AddChild(child_layer_);
+
+ layer_tree_host()->SetRootLayer(root_layer_);
+ LayerTreeHostTest::SetupTree();
+ client_.set_bounds(root_layer_->bounds());
+ }
+
+ void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+
+ void StopDeferringCommits() { scoped_defer_main_frame_update_.reset(); }
+
+ void ChangeViewportRect() {
+ gfx::Rect rect = layer_tree_host()->device_viewport_rect();
+ rect.set_size(target_size_);
+ GenerateNewLocalSurfaceId();
+ target_local_surface_id_ = GetCurrentLocalSurfaceId();
+ layer_tree_host()->SetViewportRectAndScale(rect, 1.f,
+ GetCurrentLocalSurfaceId());
+ // Block Main to simulate it being busy with a long layout.
+ PostGetDeferMainFrameUpdateToMainThread(&scoped_defer_main_frame_update_);
+ }
+
+ void WillCommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
+ switch (host_impl->sync_tree()->source_frame_number()) {
+ case 0:
+ initial_local_surface_id_ = GetCurrentLocalSurfaceId();
+
+ // After we have committed the initial tree, enqueue the change to the
+ // viewport rect for the next stage of the test.
+ MainThreadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &LayerTreeHostTestViewportRectChangeBlockedMainThread::
+ ChangeViewportRect,
+ base::Unretained(this)));
+ break;
+ }
+ }
+
+ void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
+ switch (host_impl->active_tree()->source_frame_number()) {
+ case -1:
+ EXPECT_FALSE(host_impl->active_tree()
+ ->local_surface_id_from_parent()
+ .is_valid());
+ break;
+ case 0:
+ EXPECT_EQ(initial_local_surface_id_,
+ host_impl->active_tree()->local_surface_id_from_parent());
+ // Main creates a new |target_local_surface_id_| and posts it back to
+ // the Compositor thread in ChangeViewportRect. However if it is
+ // possible for a new Impl frame to start before the queued setting of
+ // |target_local_surface_id_| has been processed. So ignore those.
+ //
+ // The |source_frame_number| will not advance until a new tree has
+ // been committed. Which will not occur until we've passed here and
+ // called StopDeferringCommits. If the test times out there there is a
+ // bug in syncing the id.
+ if (!host_impl->target_local_surface_id().is_valid())
+ return;
+ EXPECT_EQ(target_local_surface_id_,
+ host_impl->target_local_surface_id());
+ // On slower configurations more than one frame at the original
+ // |source_frame_number| can be triggered between when we begin allowing
+ // commits again, and before the commit occurs.
+ //
+ // If so do not attempt to re-unblock. Once we have stopped the blocking
+ // the first time, all subsequent Commit/Activate/BeginMainFramme will
+ // be allowed to continue as normal.
+ //
+ // When this occurs there will be a new pending tree. We also expect
+ // there to be damage now, to unblock impl frame production ahead of the
+ // upcoming activation. CC is already build around Activations that can
+ // arrive mid-frame. It does this by delaying non-immediate mode
+ // painting until either Activation arrives, or an internal deadline is
+ // hit.
+ //
+ // The normal flow is:
+ // Main hasn't committed yet, due to explicitly being blocked.
+ // BeginImplFrame - we don't have damage
+ // Main is unblocked by StopDeferringCommits
+ // Main commits
+ // Main activates
+ // BeginImplFrame has new active_tree and starts
+ //
+ // The slower flow is:
+ // Main hasn't committed yet, due to explicitly being blocked.
+ // BeginImplFrame - we don't want have damage
+ // Main is unblocked by StopDeferringCommits
+ // Main commits
+ // BeginImplFrame has new pending_tree and starts
+ // Main activates
+ // Impl receives activation
+ // Painting.
+ if (host_impl->pending_tree()) {
+ EXPECT_TRUE(has_damage);
+ return;
+ }
+ // When the |active_tree| in the LayerTreeHostImpl is behind the new
+ // |target_local_surface_id| that the LayerTreeHost is processing,
+ // there should be no damage.
+ EXPECT_FALSE(has_damage)
+ << "target " << target_local_surface_id_.ToString();
+ // Unblock the main thread now to allow for activation of the new
+ // surface.
+ MainThreadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &LayerTreeHostTestViewportRectChangeBlockedMainThread::
+ StopDeferringCommits,
+ base::Unretained(this)));
+ break;
+ case 1:
+ // When the main thread has become unblocked and pushed the new tree,
+ // frame production should continue.
+ EXPECT_EQ(target_local_surface_id_,
+ host_impl->active_tree()->local_surface_id_from_parent());
+ EXPECT_EQ(target_local_surface_id_,
+ host_impl->target_local_surface_id());
+ EXPECT_TRUE(has_damage);
+ break;
+ }
+ }
+
+ void WillActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
+ switch (host_impl->active_tree()->source_frame_number()) {
+ case -1:
+ EXPECT_EQ(initial_local_surface_id_,
+ host_impl->pending_tree()->local_surface_id_from_parent());
+ break;
+ case 0:
+ EXPECT_EQ(initial_local_surface_id_,
+ host_impl->active_tree()->local_surface_id_from_parent());
+ // For single threaded compositing we will not have built a
+ // |pending_tree| yet.
+ if (host_impl->pending_tree()) {
+ EXPECT_EQ(target_local_surface_id_,
+ host_impl->pending_tree()->local_surface_id_from_parent());
+ }
+ break;
+ case 1:
+ EXPECT_EQ(target_local_surface_id_,
+ host_impl->active_tree()->local_surface_id_from_parent());
+ break;
+ }
+ }
+
+ DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
+ LayerTreeHostImpl::FrameData* frame_data,
+ DrawResult draw_result) override {
+ // The damage rect will be set before drawing.
+ gfx::Rect root_damage_rect = frame_data->render_passes.back()->damage_rect;
+ switch (host_impl->active_tree()->source_frame_number()) {
+ case 0:
+ EXPECT_EQ(initial_size_, root_damage_rect.size());
+ break;
+ case 1:
+ EXPECT_EQ(target_size_, root_damage_rect.size());
+ PostSetNeedsRedrawToMainThread();
+ break;
+ }
+ return draw_result;
+ }
+
+ void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
+ // The viz::LocalSurfaceId is not associated with a frame until it is drawn.
+ switch (host_impl->active_tree()->source_frame_number()) {
+ case 0:
+ EXPECT_EQ(initial_local_surface_id_,
+ host_impl->last_draw_local_surface_id());
+ break;
+ case 1:
+ EXPECT_EQ(target_local_surface_id_,
+ host_impl->last_draw_local_surface_id());
+ EndTest();
+ break;
+ }
+ }
+
+ private:
+ std::unique_ptr<ScopedDeferMainFrameUpdate> scoped_defer_main_frame_update_;
+
+ viz::LocalSurfaceId initial_local_surface_id_;
+ viz::LocalSurfaceId target_local_surface_id_;
+
+ const gfx::Size initial_size_ = {10, 20};
+ const gfx::Size target_size_ = {20, 30};
+
+ FakeContentLayerClient client_;
+ scoped_refptr<Layer> root_layer_;
+ scoped_refptr<Layer> child_layer_;
+
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+// TODO(crbug.com/1223226): Disabled on Chrome OS due to flakiness.
+#if !defined(OS_CHROMEOS)
+SINGLE_AND_MULTI_THREAD_TEST_F(
+ LayerTreeHostTestViewportRectChangeBlockedMainThread);
+#endif
+
class LayerTreeHostTestRasterColorSpaceChange : public LayerTreeHostTest {
public:
void SetupTree() override {
@@ -3154,7 +3378,8 @@ class LayerTreeHostTestFrameTimeUpdatesAfterActivationFails
}
void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
if (impl->pending_tree())
frame_count_with_pending_tree_++;
@@ -3354,10 +3579,10 @@ class ViewportDeltasAppliedDuringPinch : public LayerTreeHostTest,
void AfterTest() override { EXPECT_TRUE(sent_gesture_); }
// ScrollCallbacks
- void DidScroll(ElementId element_id,
- const gfx::ScrollOffset& scroll_offset,
- const absl::optional<TargetSnapAreaElementIds>&
- snap_target_ids) override {
+ void DidCompositorScroll(ElementId element_id,
+ const gfx::ScrollOffset& scroll_offset,
+ const absl::optional<TargetSnapAreaElementIds>&
+ snap_target_ids) override {
last_scrolled_element_id_ = element_id;
last_scrolled_offset_ = scroll_offset;
}
@@ -3561,7 +3786,8 @@ class LayerTreeHostTestDeferMainFrameUpdate : public LayerTreeHostTest {
}
void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
// Impl frames happen while commits are deferred.
num_will_begin_impl_frame_++;
switch (num_will_begin_impl_frame_) {
@@ -3819,7 +4045,8 @@ class LayerTreeHostTestAnimateOnlyBeginFrames
}
void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
EXPECT_EQ(args.animate_only,
(begin_frame_count_ >= 2 && begin_frame_count_ <= 4));
}
@@ -3932,7 +4159,8 @@ class LayerTreeHostTestCompositeImmediatelyStateTransitions
}
void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
EXPECT_EQ(current_state_, kStartedTest);
current_state_ = kStartedImplFrame;
@@ -5543,34 +5771,57 @@ class LayerTreeHostTestElasticOverscroll : public LayerTreeHostTest {
}
}
+ void VerifyOverscroll(const gfx::Vector2dF& stretch_amount,
+ const gfx::Transform& transform) {
+#if defined(OS_ANDROID)
+ gfx::Vector2dF scale = transform.Scale2d();
+ // On android, overscroll stretches the content. We don't assert the amount
+ // of stretch but there should be some stretch for overscroll and no stretch
+ // without it.
+ if (stretch_amount.x() == 0.f)
+ EXPECT_EQ(1.f, scale.x());
+ else
+ EXPECT_GT(scale.x(), 1.f);
+ if (stretch_amount.y() == 0.f)
+ EXPECT_EQ(1.f, scale.y());
+ else
+ EXPECT_GT(scale.y(), 1.f);
+#else // defined(OS_ANDROID)
+ gfx::Transform expected_draw_transform;
+ expected_draw_transform.Translate(-stretch_amount);
+ EXPECT_EQ(expected_draw_transform, transform);
+#endif // defined(OS_ANDROID)
+ }
+
void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
num_draws_++;
LayerImpl* content_layer_impl =
host_impl->active_tree()->LayerById(content_layer_id_);
- gfx::Transform expected_draw_transform;
switch (num_draws_) {
case 1:
// Initially, there's no overscroll.
- EXPECT_EQ(expected_draw_transform, content_layer_impl->DrawTransform());
+ VerifyOverscroll(gfx::Vector2dF(), content_layer_impl->DrawTransform());
// Begin overscrolling. This should be reflected in the draw transform
// the next time we draw.
scroll_elasticity_helper_->SetStretchAmount(gfx::Vector2dF(5.f, 6.f));
break;
case 2:
- expected_draw_transform.Translate(-5.0, -6.0);
- EXPECT_EQ(expected_draw_transform, content_layer_impl->DrawTransform());
+ // We should have some overscroll.
+ VerifyOverscroll(gfx::Vector2dF(5.f, 6.f),
+ content_layer_impl->DrawTransform());
scroll_elasticity_helper_->SetStretchAmount(gfx::Vector2dF(3.f, 2.f));
break;
case 3:
- expected_draw_transform.Translate(-3.0, -2.0);
- EXPECT_EQ(expected_draw_transform, content_layer_impl->DrawTransform());
+ VerifyOverscroll(gfx::Vector2dF(3.f, 2.f),
+ content_layer_impl->DrawTransform());
scroll_elasticity_helper_->SetStretchAmount(gfx::Vector2dF());
break;
case 4:
- EXPECT_EQ(expected_draw_transform, content_layer_impl->DrawTransform());
+ // In the final frame there is no more overscroll.
+ VerifyOverscroll(gfx::Vector2dF(), content_layer_impl->DrawTransform());
EndTest();
break;
default:
@@ -5746,8 +5997,8 @@ class LayerTreeHostTestBreakSwapPromise : public LayerTreeHostTest {
}
void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
- int frame = host_impl->active_tree()->source_frame_number();
- if (frame == 2) {
+ int frame_num = host_impl->active_tree()->source_frame_number();
+ if (frame_num == 2) {
EndTest();
}
}
@@ -6016,7 +6267,8 @@ class LayerTreeHostTestDeferSwapPromiseForVisibility
}
void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
if (!sent_queue_request_) {
sent_queue_request_ = true;
MainThreadTaskRunner()->PostTask(
@@ -6472,7 +6724,8 @@ class LayerTreeHostTestWillBeginImplFrameHasDidFinishImplFrame
}
void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
EXPECT_EQ(will_begin_impl_frame_count_, did_finish_impl_frame_count_);
EXPECT_FALSE(TestEnded());
will_begin_impl_frame_count_++;
@@ -6545,7 +6798,8 @@ class LayerTreeHostTestBeginMainFrameTimeIsAlsoImplTime
}
void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
impl_frame_args_.push_back(args);
will_begin_impl_frame_count_++;
@@ -7938,7 +8192,8 @@ class LayerTreeHostTestBeginFrameAcks : public LayerTreeHostTest {
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
EXPECT_TRUE(args.IsValid());
current_begin_frame_args_ = args;
}
@@ -7999,8 +8254,8 @@ class LayerTreeHostTestQueueImageDecode : public LayerTreeHostTest {
image_ =
DrawImage(CreateDiscardablePaintImage(gfx::Size(400, 400)), false,
- SkIRect::MakeWH(400, 400), kNone_SkFilterQuality, SkM44(),
- PaintImage::kDefaultFrameIndex, gfx::ColorSpace());
+ SkIRect::MakeWH(400, 400), PaintFlags::FilterQuality::kNone,
+ SkM44(), PaintImage::kDefaultFrameIndex, gfx::ColorSpace());
auto callback = base::BindRepeating(
&LayerTreeHostTestQueueImageDecode::ImageDecodeFinished,
base::Unretained(this));
@@ -8350,8 +8605,9 @@ class LayerTreeHostTestImageAnimationSynchronousSchedulingSoftwareDraw
}
};
-MULTI_THREAD_TEST_F(
- LayerTreeHostTestImageAnimationSynchronousSchedulingSoftwareDraw);
+// TODO(crbug.com/1092110): Flaky on TSan bot.
+// MULTI_THREAD_TEST_F(
+// LayerTreeHostTestImageAnimationSynchronousSchedulingSoftwareDraw);
class LayerTreeHostTestImageDecodingHints : public LayerTreeHostTest {
public:
@@ -9012,7 +9268,8 @@ class LayerTreeHostTestEventsMetrics : public LayerTreeHostTest {
tick_clock.Advance(base::TimeDelta::FromMicroseconds(10));
std::unique_ptr<EventMetrics> metrics = EventMetrics::CreateForTesting(
ui::ET_GESTURE_SCROLL_UPDATE,
- EventMetrics::ScrollUpdateType::kContinued, ui::ScrollInputType::kWheel,
+ EventMetrics::ScrollParams(ui::ScrollInputType::kWheel, false,
+ EventMetrics::ScrollUpdateType::kContinued),
event_time, &tick_clock);
DCHECK_NE(metrics, nullptr);
{
@@ -9051,7 +9308,8 @@ class LayerTreeHostTestKeepEventsMetricsForVisibility
: public LayerTreeHostTestEventsMetrics {
protected:
void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
// Skip if we have already received a begin-impl-frame and acted on it.
if (received_will_begin_impl_frame_)
return;
@@ -9117,7 +9375,8 @@ class LayerTreeHostTestKeepEventsMetricsForDeferredMainFrameUpdate
: public LayerTreeHostTestEventsMetrics {
protected:
void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
// Skip if we have already received a begin-impl-frame and acted on it.
if (received_will_begin_impl_frame_)
return;
@@ -9198,7 +9457,8 @@ class LayerTreeHostTestKeepEventsMetricsForDeferredCommit
: public LayerTreeHostTestEventsMetrics {
protected:
void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
// Skip if we have already received a begin-impl-frame and acted on it.
if (received_will_begin_impl_frame_)
return;
@@ -9240,7 +9500,9 @@ class LayerTreeHostTestKeepEventsMetricsForDeferredCommit
private:
void DeferCommitOnMain() {
- layer_tree_host()->StartDeferringCommits(base::TimeDelta::FromDays(1));
+ layer_tree_host()->StartDeferringCommits(
+ base::TimeDelta::FromDays(1),
+ PaintHoldingReason::kFirstContentfulPaint);
}
void PostDeferCommit() {
@@ -9276,7 +9538,8 @@ class LayerTreeHostTestIgnoreEventsMetricsForNoUpdate
: public LayerTreeHostTestEventsMetrics {
protected:
void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
// Continue only if we are waiting for the second frame's being-impl-frame.
// The first frame will end up in a commit which is not what we want.
if (state_ != State::kWaitingForSecondFrameBeginImpl)
@@ -9376,7 +9639,8 @@ class LayerTreeHostUkmSmoothnessMetric : public LayerTreeTest {
}
void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
host_impl->dropped_frame_counter()->OnFcpReceived();
}
@@ -9421,7 +9685,8 @@ class LayerTreeHostUkmSmoothnessMemoryOwnership : public LayerTreeTest {
}
void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
host_impl->dropped_frame_counter()->OnFcpReceived();
host_impl->SetNeedsCommit();
}
diff --git a/chromium/cc/trees/layer_tree_host_unittest_animation.cc b/chromium/cc/trees/layer_tree_host_unittest_animation.cc
index 1b528540583..356a8789575 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_animation.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_animation.cc
@@ -1033,7 +1033,8 @@ class LayerTreeHostPresentationDuringAnimation
}
void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
if (host_impl->next_frame_token() >= 5)
host_impl->BlockNotifyReadyToActivateForTesting(false);
}
@@ -1125,7 +1126,8 @@ class LayerTreeHostAnimationTestScrollOffsetAnimationRemoval
}
void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
host_impl->BlockNotifyReadyToActivateForTesting(
ShouldBlockActivation(host_impl));
}
@@ -1348,7 +1350,8 @@ class LayerTreeHostAnimationTestAnimationsAddedToNewAndExistingLayers
}
void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
if (!host_impl->pending_tree() ||
host_impl->pending_tree()->source_frame_number() != 2)
return;
diff --git a/chromium/cc/trees/layer_tree_host_unittest_capture_content.cc b/chromium/cc/trees/layer_tree_host_unittest_capture_content.cc
index 2423cef7446..747063b9b35 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_capture_content.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_capture_content.cc
@@ -8,6 +8,7 @@
#include "cc/test/fake_picture_layer.h"
#include "cc/test/layer_tree_test.h"
#include "cc/trees/transform_node.h"
+#include "third_party/skia/include/core/SkTextBlob.h"
namespace cc {
namespace {
@@ -38,7 +39,9 @@ class FakeCaptureContentLayerClient : public FakeContentLayerClient {
display_list->StartPaint();
display_list->push<DrawTextBlobOp>(
SkTextBlob::MakeFromString(holder.text().data(), SkFont()),
- holder.rect().x(), holder.rect().y(), holder.node_id(), PaintFlags());
+ static_cast<float>(holder.rect().x()),
+ static_cast<float>(holder.rect().y()), holder.node_id(),
+ PaintFlags());
display_list->EndPaintOfUnpaired(holder.rect());
}
display_list->Finalize();
diff --git a/chromium/cc/trees/layer_tree_host_unittest_context.cc b/chromium/cc/trees/layer_tree_host_unittest_context.cc
index 6358f0afb4b..cb7610f60f5 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_context.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_context.cc
@@ -6,7 +6,7 @@
#include <stdint.h>
#include "base/bind.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "build/build_config.h"
#include "cc/layers/heads_up_display_layer.h"
#include "cc/layers/layer_impl.h"
diff --git a/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc
index 5640d141a98..02c23624f96 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc
@@ -95,7 +95,8 @@ class LayerTreeHostCopyRequestTestMultipleRequests
switch (frame) {
case 1:
child->RequestCopyOfOutput(std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(&LayerTreeHostCopyRequestTestMultipleRequests::
CopyOutputCallback,
base::Unretained(this), 0)));
@@ -113,18 +114,21 @@ class LayerTreeHostCopyRequestTestMultipleRequests
EXPECT_EQ(gfx::Size(10, 10).ToString(), callbacks_[0].ToString());
child->RequestCopyOfOutput(std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(&LayerTreeHostCopyRequestTestMultipleRequests::
CopyOutputCallback,
base::Unretained(this), 1)));
root->RequestCopyOfOutput(std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(&LayerTreeHostCopyRequestTestMultipleRequests::
CopyOutputCallback,
base::Unretained(this), 2)));
grand_child->RequestCopyOfOutput(
std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(&LayerTreeHostCopyRequestTestMultipleRequests::
CopyOutputCallback,
base::Unretained(this), 3)));
@@ -260,7 +264,8 @@ class LayerTreeHostCopyRequestCompletionCausesCommit
switch (frame) {
case 1:
layer_->RequestCopyOfOutput(std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(&LayerTreeHostCopyRequestCompletionCausesCommit::
CopyOutputCallback)));
break;
@@ -326,13 +331,15 @@ class LayerTreeHostCopyRequestTestLayerDestroyed
case 1:
main_destroyed_->RequestCopyOfOutput(std::make_unique<
viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(
&LayerTreeHostCopyRequestTestLayerDestroyed::CopyOutputCallback,
base::Unretained(this), &main_destroyed_event_)));
impl_destroyed_->RequestCopyOfOutput(std::make_unique<
viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(
&LayerTreeHostCopyRequestTestLayerDestroyed::CopyOutputCallback,
base::Unretained(this), &impl_destroyed_event_)));
@@ -437,7 +444,8 @@ class LayerTreeHostCopyRequestTestInHiddenSubtree
void AddCopyRequest(Layer* layer) {
layer->RequestCopyOfOutput(std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(
&LayerTreeHostCopyRequestTestInHiddenSubtree::CopyOutputCallback,
base::Unretained(this))));
@@ -563,7 +571,8 @@ class LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest
PostSetNeedsCommitToMainThread();
copy_layer_->RequestCopyOfOutput(std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(
&LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest::
CopyOutputCallback,
@@ -670,7 +679,8 @@ class LayerTreeHostCopyRequestTestClippedOut
PostSetNeedsCommitToMainThread();
copy_layer_->RequestCopyOfOutput(std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(
&LayerTreeHostCopyRequestTestClippedOut::CopyOutputCallback,
base::Unretained(this))));
@@ -733,7 +743,8 @@ class LayerTreeHostCopyRequestTestScaledLayer
std::unique_ptr<viz::CopyOutputRequest> request =
std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(
&LayerTreeHostCopyRequestTestScaledLayer::CopyOutputCallback,
base::Unretained(this)));
@@ -786,7 +797,8 @@ class LayerTreeHostTestAsyncTwoReadbacksWithoutDraw
void AddCopyRequest(Layer* layer) {
layer->RequestCopyOfOutput(std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(
&LayerTreeHostTestAsyncTwoReadbacksWithoutDraw::CopyOutputCallback,
base::Unretained(this))));
@@ -913,7 +925,9 @@ class LayerTreeHostCopyRequestTestDeleteSharedImage
std::unique_ptr<viz::CopyOutputResult> result) {
EXPECT_TRUE(layer_tree_host()->GetTaskRunnerProvider()->IsMainThread());
EXPECT_EQ(gfx::Size(10, 10).ToString(), result->size().ToString());
- EXPECT_EQ(result->format(), viz::CopyOutputResult::Format::RGBA_TEXTURE);
+ EXPECT_EQ(result->format(), viz::CopyOutputResult::Format::RGBA);
+ EXPECT_EQ(result->destination(),
+ viz::CopyOutputResult::Destination::kNativeTextures);
EXPECT_NE(result->GetTextureResult(), nullptr);
// Save the result for later.
@@ -926,7 +940,8 @@ class LayerTreeHostCopyRequestTestDeleteSharedImage
void InsertCopyRequest() {
copy_layer_->RequestCopyOfOutput(std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_TEXTURE,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputResult::Destination::kNativeTextures,
base::BindOnce(&LayerTreeHostCopyRequestTestDeleteSharedImage::
ReceiveCopyRequestOutputAndCommit,
base::Unretained(this))));
@@ -1088,6 +1103,22 @@ class LayerTreeHostCopyRequestTestCountSharedImages
}
}
+ std::unique_ptr<TestLayerTreeFrameSink> CreateLayerTreeFrameSink(
+ const viz::RendererSettings& renderer_settings,
+ double refresh_rate,
+ scoped_refptr<viz::ContextProvider> compositor_context_provider,
+ scoped_refptr<viz::RasterContextProvider> worker_context_provider)
+ override {
+ // Since this test counts shared images and SkiaRenderer uses shared images
+ // for render passes, we need render pass allocation to be stable.
+ auto settings = renderer_settings;
+ settings.disable_render_pass_bypassing = true;
+ auto frame_sink = LayerTreeHostCopyRequestTest::CreateLayerTreeFrameSink(
+ settings, refresh_rate, std::move(compositor_context_provider),
+ std::move(worker_context_provider));
+ return frame_sink;
+ }
+
void DisplayDidDrawAndSwapOnThread() override {
auto* sii = display_context_provider_->SharedImageInterface();
switch (num_swaps_++) {
@@ -1135,7 +1166,8 @@ class LayerTreeHostCopyRequestTestCreatesSharedImage
void RequestCopy(Layer* layer) override {
// Request a normal texture copy. This should create a new shared image.
copy_layer_->RequestCopyOfOutput(std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_TEXTURE,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputResult::Destination::kNativeTextures,
base::BindOnce(
&LayerTreeHostCopyRequestTestCreatesSharedImage::CopyOutputCallback,
base::Unretained(this))));
@@ -1143,21 +1175,25 @@ class LayerTreeHostCopyRequestTestCreatesSharedImage
void CopyOutputCallback(std::unique_ptr<viz::CopyOutputResult> result) {
EXPECT_FALSE(result->IsEmpty());
- EXPECT_EQ(result->format(), viz::CopyOutputResult::Format::RGBA_TEXTURE);
+ EXPECT_EQ(result->format(), viz::CopyOutputResult::Format::RGBA);
+ EXPECT_EQ(result->destination(),
+ viz::CopyOutputResult::Destination::kNativeTextures);
ASSERT_NE(nullptr, result->GetTextureResult());
release_ = result->TakeTextureOwnership();
- EXPECT_TRUE(release_);
+ EXPECT_EQ(1u, release_.size());
}
void AfterTest() override {
- std::move(release_).Run(gpu::SyncToken(), false);
+ for (auto& release : release_) {
+ std::move(release).Run(gpu::SyncToken(), false);
+ }
// Except the copy to have made a new shared image.
EXPECT_EQ(num_shared_images_without_readback_ + 1,
num_shared_images_with_readback_);
}
- viz::ReleaseCallback release_;
+ viz::CopyOutputResult::ReleaseCallbacks release_;
};
INSTANTIATE_TEST_SUITE_P(
@@ -1216,7 +1252,8 @@ class LayerTreeHostCopyRequestTestDestroyBeforeCopy
// drawing to take place.
std::unique_ptr<viz::CopyOutputRequest> request =
std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_TEXTURE,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputResult::Destination::kNativeTextures,
base::BindOnce(&LayerTreeHostCopyRequestTestDestroyBeforeCopy::
CopyOutputCallback,
base::Unretained(this)));
@@ -1308,7 +1345,8 @@ class LayerTreeHostCopyRequestTestShutdownBeforeCopy
// drawing to take place.
std::unique_ptr<viz::CopyOutputRequest> request =
std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_TEXTURE,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputResult::Destination::kNativeTextures,
base::BindOnce(&LayerTreeHostCopyRequestTestShutdownBeforeCopy::
CopyOutputCallback,
base::Unretained(this)));
@@ -1381,7 +1419,8 @@ class LayerTreeHostCopyRequestTestMultipleDrawsHiddenCopyRequest
// Send a copy request after the first commit.
if (layer_tree_host()->SourceFrameNumber() == 1) {
child_->RequestCopyOfOutput(std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(
&LayerTreeHostCopyRequestTestMultipleDrawsHiddenCopyRequest::
CopyOutputCallback,
diff --git a/chromium/cc/trees/layer_tree_host_unittest_damage.cc b/chromium/cc/trees/layer_tree_host_unittest_damage.cc
index 2d2993d1413..479801c7cb0 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_damage.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_damage.cc
@@ -337,7 +337,10 @@ class LayerTreeHostScrollbarDamageTest : public LayerTreeHostDamageTest {
content_layer_ = FakePictureLayer::Create(&client_);
content_layer_->SetElementId(
LayerIdToElementIdForTesting(content_layer_->id()));
- content_layer_->SetScrollable(root_layer->bounds());
+
+ // The size of the container in which scrolling contents are visible need
+ // to be smaller than the bounds of the layer itself.
+ content_layer_->SetScrollable(gfx::Size(80, 180));
content_layer_->SetScrollOffset(gfx::ScrollOffset(10, 20));
content_layer_->SetBounds(gfx::Size(100, 200));
content_layer_->SetIsDrawable(true);
diff --git a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc
index 5767d3784b2..3a4ecfab2da 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -87,10 +87,10 @@ class LayerTreeHostScrollTest : public LayerTreeTest, public ScrollCallbacks {
}
// ScrollCallbacks
- void DidScroll(ElementId element_id,
- const gfx::ScrollOffset& scroll_offset,
- const absl::optional<TargetSnapAreaElementIds>&
- snap_target_ids) override {
+ void DidCompositorScroll(ElementId element_id,
+ const gfx::ScrollOffset& scroll_offset,
+ const absl::optional<TargetSnapAreaElementIds>&
+ snap_target_ids) override {
// Simulates cc client (e.g Blink) behavior when handling impl-side scrolls.
SetScrollOffsetFromImplSide(layer_tree_host()->LayerByElementId(element_id),
scroll_offset);
@@ -621,11 +621,12 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest {
}
}
- void DidScroll(ElementId element_id,
- const gfx::ScrollOffset& offset,
- const absl::optional<TargetSnapAreaElementIds>&
- snap_target_ids) override {
- LayerTreeHostScrollTest::DidScroll(element_id, offset, snap_target_ids);
+ void DidCompositorScroll(ElementId element_id,
+ const gfx::ScrollOffset& offset,
+ const absl::optional<TargetSnapAreaElementIds>&
+ snap_target_ids) override {
+ LayerTreeHostScrollTest::DidCompositorScroll(element_id, offset,
+ snap_target_ids);
if (element_id == expected_scroll_layer_->element_id()) {
final_scroll_offset_ = CurrentScrollOffset(expected_scroll_layer_);
EXPECT_EQ(offset, final_scroll_offset_);
@@ -1094,7 +1095,6 @@ class SmoothScrollAnimationEndNotification : public LayerTreeHostScrollTest {
child_layer_ = Layer::Create();
child_layer_->SetElementId(
LayerIdToElementIdForTesting(child_layer_->id()));
- child_layer_->SetBounds(gfx::Size(110, 110));
child_layer_->SetIsDrawable(true);
child_layer_->SetHitTestable(true);
@@ -1111,11 +1111,11 @@ class SmoothScrollAnimationEndNotification : public LayerTreeHostScrollTest {
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
void WillCommit() override {
+ if (TestEnded())
+ return;
// Keep the test committing (otherwise the early out for no update
// will stall the test).
- if (layer_tree_host()->SourceFrameNumber() < 2) {
- layer_tree_host()->SetNeedsCommit();
- }
+ layer_tree_host()->SetNeedsCommit();
}
void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
@@ -1767,6 +1767,8 @@ class ThreadCheckingInputHandlerClient : public InputHandlerClient {
}
}
+ void SetPrefersReducedMotion(bool prefers_reduced_motion) override {}
+
void UpdateRootLayerStateForSynchronousInputHandler(
const gfx::ScrollOffset& total_scroll_offset,
const gfx::ScrollOffset& max_scroll_offset,
@@ -1840,9 +1842,10 @@ class LayerTreeHostScrollTestLayerStructureChange
}
}
- void DidScroll(ElementId element_id,
- const gfx::ScrollOffset&,
- const absl::optional<TargetSnapAreaElementIds>&) override {
+ void DidCompositorScroll(
+ ElementId element_id,
+ const gfx::ScrollOffset&,
+ const absl::optional<TargetSnapAreaElementIds>&) override {
if (scroll_destroy_whole_tree_) {
layer_tree_host()->SetRootLayer(nullptr);
layer_tree_host()->property_trees()->clear();
@@ -2235,6 +2238,7 @@ class MockInputHandlerClient : public InputHandlerClient {
void WillShutdown() override {}
void Animate(base::TimeTicks) override {}
+ void SetPrefersReducedMotion(bool prefers_reduced_motion) override {}
void UpdateRootLayerStateForSynchronousInputHandler(
const gfx::ScrollOffset& total_scroll_offset,
const gfx::ScrollOffset& max_scroll_offset,
diff --git a/chromium/cc/trees/layer_tree_host_unittest_video.cc b/chromium/cc/trees/layer_tree_host_unittest_video.cc
index f69dc76d788..c7b664cb484 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_video.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_video.cc
@@ -16,6 +16,9 @@
namespace cc {
namespace {
+constexpr auto kTestTransform =
+ media::VideoTransformation(media::VIDEO_ROTATION_90, /*mirrored=*/true);
+
// These tests deal with compositing video.
class LayerTreeHostVideoTest : public LayerTreeTest {};
@@ -28,7 +31,7 @@ class LayerTreeHostVideoTestSetNeedsDisplay
root->SetIsDrawable(true);
scoped_refptr<VideoLayer> video =
- VideoLayer::Create(&video_frame_provider_, media::VIDEO_ROTATION_90);
+ VideoLayer::Create(&video_frame_provider_, kTestTransform);
video->SetPosition(gfx::PointF(3.f, 3.f));
video->SetBounds(gfx::Size(4, 5));
video->SetIsDrawable(true);
@@ -74,7 +77,7 @@ class LayerTreeHostVideoTestSetNeedsDisplay
VideoLayerImpl* video = static_cast<VideoLayerImpl*>(
host_impl->active_tree()->LayerById(video_layer_id_));
- EXPECT_EQ(media::VIDEO_ROTATION_90, video->video_rotation());
+ EXPECT_EQ(kTestTransform, video->video_transform_for_testing());
if (num_draws_ == 0)
video->SetNeedsRedraw();
diff --git a/chromium/cc/trees/layer_tree_impl.cc b/chromium/cc/trees/layer_tree_impl.cc
index 8d78780435b..e923a3e0551 100644
--- a/chromium/cc/trees/layer_tree_impl.cc
+++ b/chromium/cc/trees/layer_tree_impl.cc
@@ -17,11 +17,11 @@
#include "base/containers/adapters.h"
#include "base/containers/contains.h"
+#include "base/cxx17_backports.h"
#include "base/debug/crash_logging.h"
#include "base/debug/dump_without_crashing.h"
#include "base/json/json_writer.h"
#include "base/metrics/histogram_macros.h"
-#include "base/numerics/ranges.h"
#include "base/strings/stringprintf.h"
#include "base/timer/elapsed_timer.h"
#include "base/trace_event/trace_event.h"
@@ -108,8 +108,8 @@ std::pair<gfx::PointF, gfx::PointF> GetVisibleSelectionEndPoints(
const gfx::RectF& rect,
const gfx::PointF& top,
const gfx::PointF& bottom) {
- gfx::PointF start(base::ClampToRange(top.x(), rect.x(), rect.right()),
- base::ClampToRange(top.y(), rect.y(), rect.bottom()));
+ gfx::PointF start(base::clamp(top.x(), rect.x(), rect.right()),
+ base::clamp(top.y(), rect.y(), rect.bottom()));
gfx::PointF end =
start + gfx::Vector2dF(bottom.x() - top.x(), bottom.y() - top.y());
return {start, end};
@@ -805,15 +805,15 @@ void LayerTreeImpl::SetBackdropFilterMutated(
}
void LayerTreeImpl::AddPresentationCallbacks(
- std::vector<LayerTreeHost::PresentationTimeCallback> callbacks) {
+ std::vector<PresentationTimeCallbackBuffer::MainCallback> callbacks) {
std::copy(std::make_move_iterator(callbacks.begin()),
std::make_move_iterator(callbacks.end()),
std::back_inserter(presentation_callbacks_));
}
-std::vector<LayerTreeHost::PresentationTimeCallback>
+std::vector<PresentationTimeCallbackBuffer::MainCallback>
LayerTreeImpl::TakePresentationCallbacks() {
- std::vector<LayerTreeHost::PresentationTimeCallback> callbacks;
+ std::vector<PresentationTimeCallbackBuffer::MainCallback> callbacks;
callbacks.swap(presentation_callbacks_);
return callbacks;
}
@@ -1070,7 +1070,7 @@ bool LayerTreeImpl::ClampTopControlsShownRatio() {
host_impl_->browser_controls_manager()->TopControlsShownRatioRange();
}
return top_controls_shown_ratio_->SetCurrent(
- base::ClampToRange(ratio, range.first, range.second));
+ base::clamp(ratio, range.first, range.second));
}
bool LayerTreeImpl::ClampBottomControlsShownRatio() {
@@ -1083,7 +1083,7 @@ bool LayerTreeImpl::ClampBottomControlsShownRatio() {
host_impl_->browser_controls_manager()->BottomControlsShownRatioRange();
}
return bottom_controls_shown_ratio_->SetCurrent(
- base::ClampToRange(ratio, range.first, range.second));
+ base::clamp(ratio, range.first, range.second));
}
bool LayerTreeImpl::SetCurrentBrowserControlsShownRatio(float top_ratio,
@@ -1292,6 +1292,10 @@ const TransformNode* LayerTreeImpl::OverscrollElasticityTransformNode() const {
viewport_property_ids_.overscroll_elasticity_transform);
}
+ElementId LayerTreeImpl::OverscrollElasticityEffectElementId() const {
+ return viewport_property_ids_.overscroll_elasticity_effect;
+}
+
const TransformNode* LayerTreeImpl::PageScaleTransformNode() const {
return property_trees()->transform_tree.Node(
viewport_property_ids_.page_scale_transform);
diff --git a/chromium/cc/trees/layer_tree_impl.h b/chromium/cc/trees/layer_tree_impl.h
index 708b0702807..6971fd0d614 100644
--- a/chromium/cc/trees/layer_tree_impl.h
+++ b/chromium/cc/trees/layer_tree_impl.h
@@ -284,8 +284,8 @@ class CC_EXPORT LayerTreeImpl {
gfx::ScrollOffset TotalMaxScrollOffset() const;
void AddPresentationCallbacks(
- std::vector<LayerTreeHost::PresentationTimeCallback> callbacks);
- std::vector<LayerTreeHost::PresentationTimeCallback>
+ std::vector<PresentationTimeCallbackBuffer::MainCallback> callbacks);
+ std::vector<PresentationTimeCallbackBuffer::MainCallback>
TakePresentationCallbacks();
bool has_presentation_callbacks() const {
return !presentation_callbacks_.empty();
@@ -303,6 +303,7 @@ class CC_EXPORT LayerTreeImpl {
const_cast<const LayerTreeImpl*>(this)
->OverscrollElasticityTransformNode());
}
+ ElementId OverscrollElasticityEffectElementId() const;
const TransformNode* PageScaleTransformNode() const;
TransformNode* PageScaleTransformNode() {
return const_cast<TransformNode*>(
@@ -734,6 +735,10 @@ class CC_EXPORT LayerTreeImpl {
return host_impl_->GetActivelyScrollingType();
}
+ bool CurrentScrollDidCheckerboardLargeArea() {
+ return host_impl_->CurrentScrollDidCheckerboardLargeArea();
+ }
+
// These functions are used for plumbing DelegatedInkMetadata from blink
// through the compositor and into viz via a compositor frame. They should
// only be called after the JS API |updateInkTrailStartPoint| has been
@@ -917,7 +922,8 @@ class CC_EXPORT LayerTreeImpl {
// Display transform hint to tag frames generated from this tree.
gfx::OverlayTransform display_transform_hint_ = gfx::OVERLAY_TRANSFORM_NONE;
- std::vector<LayerTreeHost::PresentationTimeCallback> presentation_callbacks_;
+ std::vector<PresentationTimeCallbackBuffer::MainCallback>
+ presentation_callbacks_;
// Event metrics that are reported back from the main thread.
EventMetrics::List events_metrics_from_main_thread_;
diff --git a/chromium/cc/trees/layer_tree_impl_unittest.cc b/chromium/cc/trees/layer_tree_impl_unittest.cc
index a132530bfaa..ff133afcada 100644
--- a/chromium/cc/trees/layer_tree_impl_unittest.cc
+++ b/chromium/cc/trees/layer_tree_impl_unittest.cc
@@ -4,7 +4,7 @@
#include "cc/trees/layer_tree_impl.h"
-#include "base/numerics/ranges.h"
+#include "base/cxx17_backports.h"
#include "cc/layers/heads_up_display_layer_impl.h"
#include "cc/test/fake_layer_tree_host_impl.h"
#include "cc/test/fake_raster_source.h"
@@ -23,8 +23,8 @@ std::pair<gfx::PointF, gfx::PointF> GetVisibleSelectionEndPoints(
const gfx::RectF& rect,
const gfx::PointF& top,
const gfx::PointF& bottom) {
- gfx::PointF start(base::ClampToRange(top.x(), rect.x(), rect.right()),
- base::ClampToRange(top.y(), rect.y(), rect.bottom()));
+ gfx::PointF start(base::clamp(top.x(), rect.x(), rect.right()),
+ base::clamp(top.y(), rect.y(), rect.bottom()));
gfx::PointF end =
start + gfx::Vector2dF(bottom.x() - top.x(), bottom.y() - top.y());
return {start, end};
diff --git a/chromium/cc/trees/layer_tree_settings.cc b/chromium/cc/trees/layer_tree_settings.cc
index 2a13e654421..b8168bd5b9e 100644
--- a/chromium/cc/trees/layer_tree_settings.cc
+++ b/chromium/cc/trees/layer_tree_settings.cc
@@ -26,10 +26,6 @@ SchedulerSettings LayerTreeSettings::ToSchedulerSettings() const {
main_frame_before_activation_enabled;
scheduler_settings.using_synchronous_renderer_compositor =
using_synchronous_renderer_compositor;
- scheduler_settings.enable_impl_latency_recovery =
- enable_impl_latency_recovery;
- scheduler_settings.enable_main_latency_recovery =
- enable_main_latency_recovery;
scheduler_settings.wait_for_all_pipeline_stages_before_draw =
wait_for_all_pipeline_stages_before_draw;
return scheduler_settings;
diff --git a/chromium/cc/trees/layer_tree_settings.h b/chromium/cc/trees/layer_tree_settings.h
index 7fa2b4da8c8..e38646f8834 100644
--- a/chromium/cc/trees/layer_tree_settings.h
+++ b/chromium/cc/trees/layer_tree_settings.h
@@ -38,8 +38,6 @@ class CC_EXPORT LayerTreeSettings {
// When |enable_early_damage_check| is true, the early damage check is
// performed if one of the last |damaged_frame_limit| frames had no damage.
int damaged_frame_limit = 3;
- bool enable_impl_latency_recovery = false;
- bool enable_main_latency_recovery = false;
bool can_use_lcd_text = true;
bool gpu_rasterization_disabled = false;
int gpu_rasterization_msaa_sample_count = -1;
@@ -193,7 +191,7 @@ class CC_EXPORT LayerTreeSettings {
// When enabled, enforces new interoperable semantics for 3D transforms.
// See crbug.com/1008483.
- bool enable_transform_interop = false;
+ bool enable_backface_visibility_interop = false;
// Enables ThrottleDecider which produces a list of FrameSinkIds that are
// candidates for throttling.
diff --git a/chromium/cc/trees/mobile_optimized_viewport_util.cc b/chromium/cc/trees/mobile_optimized_viewport_util.cc
new file mode 100644
index 00000000000..2f70f27a70d
--- /dev/null
+++ b/chromium/cc/trees/mobile_optimized_viewport_util.cc
@@ -0,0 +1,41 @@
+// Copyright 2021 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/mobile_optimized_viewport_util.h"
+
+#include "base/feature_list.h"
+#include "cc/base/features.h"
+#include "ui/gfx/geometry/size_f.h"
+
+namespace cc {
+namespace util {
+namespace {
+// Used to accommodate finite precision when comparing scaled viewport and
+// content widths. While this value may seem large, width=device-width on an N7
+// V1 saw errors of ~0.065 between computed window and content widths.
+const float kMobileViewportWidthEpsilon = 0.15f;
+} // namespace
+
+bool IsMobileOptimized(float min_page_scale_factor,
+ float max_page_scale_factor,
+ float current_page_scale_factor,
+ gfx::SizeF scrollable_viewport_size,
+ gfx::SizeF scrollable_size,
+ bool viewport_meta_mobile_optimized) {
+ bool has_fixed_page_scale = min_page_scale_factor == max_page_scale_factor;
+
+ float window_width_dip =
+ current_page_scale_factor * scrollable_viewport_size.width();
+ float content_width_css = scrollable_size.width();
+ bool has_mobile_viewport =
+ content_width_css <= window_width_dip + kMobileViewportWidthEpsilon;
+
+ return has_mobile_viewport || has_fixed_page_scale ||
+ (base::FeatureList::IsEnabled(
+ ::features::kRemoveMobileViewportDoubleTap) &&
+ viewport_meta_mobile_optimized);
+}
+
+} // namespace util
+} // namespace cc
diff --git a/chromium/cc/trees/mobile_optimized_viewport_util.h b/chromium/cc/trees/mobile_optimized_viewport_util.h
new file mode 100644
index 00000000000..9bd59891aba
--- /dev/null
+++ b/chromium/cc/trees/mobile_optimized_viewport_util.h
@@ -0,0 +1,34 @@
+// Copyright 2021 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_MOBILE_OPTIMIZED_VIEWPORT_UTIL_H_
+#define CC_TREES_MOBILE_OPTIMIZED_VIEWPORT_UTIL_H_
+
+#include "ui/gfx/geometry/size_f.h"
+
+namespace cc {
+namespace util {
+
+// Returns whether the viewport should be considered mobile optimized,
+// not needing the double tap to zoom gesture.
+// Arguments:
+// min_page_scale_factor - the minimum page scale
+// max_page_scale_factor - the maximum page scale
+// current_page_scale_factor - current page scale
+// scrollable_viewport_size - the size of the user-visible scrolling viewport
+// in CSS layout coordinates
+// scrollable_size - the size of the root scrollable area in CSS layout
+// coordinates
+// viewport_meta_mobile_optimized - if the viewport meta tag is mobile
+// optimized
+bool IsMobileOptimized(float min_page_scale_factor,
+ float max_page_scale_factor,
+ float current_page_scale_factor,
+ gfx::SizeF scrollable_viewport_size,
+ gfx::SizeF scrollable_size,
+ bool viewport_meta_mobile_optimized);
+} // namespace util
+} // namespace cc
+
+#endif // CC_TREES_MOBILE_OPTIMIZED_VIEWPORT_UTIL_H_
diff --git a/chromium/cc/trees/occlusion_tracker.cc b/chromium/cc/trees/occlusion_tracker.cc
index 91f8fefa627..0f9c92265c8 100644
--- a/chromium/cc/trees/occlusion_tracker.cc
+++ b/chromium/cc/trees/occlusion_tracker.cc
@@ -104,7 +104,7 @@ static SimpleEnclosedRegion TransformSurfaceOpaqueRegion(
// to each rect within |region| in order to transform the entire Region.
// TODO(danakj): Find a rect interior to each transformed quad.
- if (!transform.Preserves2dAxisAlignment())
+ if (!transform.NonDegeneratePreserves2dAxisAlignment())
return SimpleEnclosedRegion();
SimpleEnclosedRegion transformed_region;
@@ -371,7 +371,7 @@ void OcclusionTracker::MarkOccludedBehindLayer(const LayerImpl* layer) {
gfx::Transform draw_transform = layer->DrawTransform();
// TODO(danakj): Find a rect interior to each transformed quad.
- if (!draw_transform.Preserves2dAxisAlignment())
+ if (!draw_transform.NonDegeneratePreserves2dAxisAlignment())
return;
gfx::Rect clip_rect_in_target = ScreenSpaceClipRectInTargetSurface(
diff --git a/chromium/cc/trees/occlusion_unittest.cc b/chromium/cc/trees/occlusion_unittest.cc
index e5b31e41193..a0c17bd881c 100644
--- a/chromium/cc/trees/occlusion_unittest.cc
+++ b/chromium/cc/trees/occlusion_unittest.cc
@@ -6,7 +6,7 @@
#include <stddef.h>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cc {
diff --git a/chromium/cc/trees/paint_holding_commit_trigger.cc b/chromium/cc/trees/paint_holding_commit_trigger.cc
new file mode 100644
index 00000000000..daba1843c87
--- /dev/null
+++ b/chromium/cc/trees/paint_holding_commit_trigger.cc
@@ -0,0 +1,22 @@
+// Copyright 2021 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/paint_holding_commit_trigger.h"
+
+#include "base/notreached.h"
+
+namespace cc {
+
+PaintHoldingCommitTrigger ReasonToTimeoutTrigger(PaintHoldingReason reason) {
+ switch (reason) {
+ case PaintHoldingReason::kFirstContentfulPaint:
+ return PaintHoldingCommitTrigger::kTimeoutFCP;
+ case PaintHoldingReason::kDocumentTransition:
+ return PaintHoldingCommitTrigger::kTimeoutDocumentTransition;
+ }
+ NOTREACHED();
+ return PaintHoldingCommitTrigger::kTimeoutFCP;
+}
+
+} // namespace cc
diff --git a/chromium/cc/trees/paint_holding_commit_trigger.h b/chromium/cc/trees/paint_holding_commit_trigger.h
index b8828028019..5c9439d7f78 100644
--- a/chromium/cc/trees/paint_holding_commit_trigger.h
+++ b/chromium/cc/trees/paint_holding_commit_trigger.h
@@ -5,6 +5,8 @@
#ifndef CC_TREES_PAINT_HOLDING_COMMIT_TRIGGER_H_
#define CC_TREES_PAINT_HOLDING_COMMIT_TRIGGER_H_
+#include "cc/trees/paint_holding_reason.h"
+
namespace cc {
enum class PaintHoldingCommitTrigger {
@@ -18,13 +20,19 @@ enum class PaintHoldingCommitTrigger {
// The commit was triggered by first contentful paint (FCP)
kFirstContentfulPaint = 2,
// The commit was triggered by a timeout waiting for FCP
- kTimeout = 3,
+ kTimeoutFCP = 3,
// The timeout was never set, probably due to non-main frame
kNotDeferred = 4,
+ // The commit was triggered by a document transition start
+ kDocumentTransition = 5,
+ // The commit was triggered by a timeout waiting for document transition start
+ kTimeoutDocumentTransition = 6,
// Required for UMA enum
- kMaxValue = kNotDeferred
+ kMaxValue = kTimeoutDocumentTransition
};
+PaintHoldingCommitTrigger ReasonToTimeoutTrigger(PaintHoldingReason reason);
+
} // namespace cc
#endif // CC_TREES_PAINT_HOLDING_COMMIT_TRIGGER_H_
diff --git a/chromium/cc/trees/paint_holding_reason.h b/chromium/cc/trees/paint_holding_reason.h
new file mode 100644
index 00000000000..3e063246b4b
--- /dev/null
+++ b/chromium/cc/trees/paint_holding_reason.h
@@ -0,0 +1,21 @@
+// Copyright 2021 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_PAINT_HOLDING_REASON_H_
+#define CC_TREES_PAINT_HOLDING_REASON_H_
+
+namespace cc {
+
+enum class PaintHoldingReason {
+ // Deferred to allow a frame with contentful paint.
+ kFirstContentfulPaint,
+
+ // Deferred to allow the document to be updated asynchronously for a
+ // transition.
+ kDocumentTransition,
+};
+
+} // namespace cc
+
+#endif // CC_TREES_PAINT_HOLDING_REASON_H_
diff --git a/chromium/cc/trees/presentation_time_callback_buffer.cc b/chromium/cc/trees/presentation_time_callback_buffer.cc
index c6de964c244..7ae602bf330 100644
--- a/chromium/cc/trees/presentation_time_callback_buffer.cc
+++ b/chromium/cc/trees/presentation_time_callback_buffer.cc
@@ -7,6 +7,8 @@
#include <utility>
#include <vector>
+#include "components/viz/common/quads/compositor_frame_metadata.h"
+
namespace cc {
PresentationTimeCallbackBuffer::PresentationTimeCallbackBuffer() = default;
@@ -37,7 +39,7 @@ PresentationTimeCallbackBuffer::FrameTokenInfo::~FrameTokenInfo() = default;
void PresentationTimeCallbackBuffer::RegisterMainThreadPresentationCallbacks(
uint32_t frame_token,
- std::vector<CallbackType> callbacks) {
+ std::vector<MainCallback> callbacks) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
FrameTokenInfo& frame_info = GetOrMakeRegistration(frame_token);
@@ -45,20 +47,16 @@ void PresentationTimeCallbackBuffer::RegisterMainThreadPresentationCallbacks(
auto& sink = frame_info.main_thread_callbacks;
sink.reserve(sink.size() + callbacks.size());
std::move(callbacks.begin(), callbacks.end(), std::back_inserter(sink));
-
- DCHECK_LE(frame_token_infos_.size(), 25u);
}
void PresentationTimeCallbackBuffer::RegisterCompositorPresentationCallbacks(
uint32_t frame_token,
- std::vector<CallbackType> callbacks) {
+ std::vector<CompositorCallback> callbacks) {
// Splice the given |callbacks| onto the vector of existing callbacks.
- std::vector<LayerTreeHost::PresentationTimeCallback>& sink =
+ std::vector<CompositorCallback>& sink =
GetOrMakeRegistration(frame_token).compositor_thread_callbacks;
sink.reserve(sink.size() + callbacks.size());
std::move(callbacks.begin(), callbacks.end(), std::back_inserter(sink));
-
- DCHECK_LE(frame_token_infos_.size(), 25u);
}
PresentationTimeCallbackBuffer::PendingCallbacks::PendingCallbacks() = default;
@@ -70,29 +68,33 @@ PresentationTimeCallbackBuffer::PendingCallbacks::operator=(
PresentationTimeCallbackBuffer::PendingCallbacks::~PendingCallbacks() = default;
PresentationTimeCallbackBuffer::PendingCallbacks
-PresentationTimeCallbackBuffer::PopPendingCallbacks(uint32_t frame_token) {
+PresentationTimeCallbackBuffer::PopPendingCallbacks(uint32_t frame_token,
+ bool main_only) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
PendingCallbacks result;
- while (!frame_token_infos_.empty()) {
- auto info = frame_token_infos_.begin();
+ for (auto info = frame_token_infos_.begin();
+ info != frame_token_infos_.end();) {
if (viz::FrameTokenGT(info->token, frame_token))
break;
- // Collect the main-thread callbacks. It's the caller's job to post them to
- // the main thread.
std::move(info->main_thread_callbacks.begin(),
info->main_thread_callbacks.end(),
std::back_inserter(result.main_thread_callbacks));
-
- // Collect the compositor-thread callbacks. It's the caller's job to run
- // them on the compositor thread.
- std::move(info->compositor_thread_callbacks.begin(),
- info->compositor_thread_callbacks.end(),
- std::back_inserter(result.compositor_thread_callbacks));
-
- frame_token_infos_.erase(info);
+ info->main_thread_callbacks.clear();
+
+ const bool should_keep_callbacks =
+ main_only && !info->compositor_thread_callbacks.empty();
+
+ if (should_keep_callbacks) {
+ ++info;
+ } else {
+ std::move(info->compositor_thread_callbacks.begin(),
+ info->compositor_thread_callbacks.end(),
+ std::back_inserter(result.compositor_thread_callbacks));
+ info = frame_token_infos_.erase(info);
+ }
}
return result;
@@ -105,6 +107,7 @@ PresentationTimeCallbackBuffer::GetOrMakeRegistration(uint32_t frame_token) {
if (frame_token_infos_.empty() ||
viz::FrameTokenGT(frame_token, frame_token_infos_.back().token)) {
frame_token_infos_.emplace_back(frame_token);
+ DCHECK_LE(frame_token_infos_.size(), 25u);
}
// Registrations should use monotonically increasing frame tokens.
diff --git a/chromium/cc/trees/presentation_time_callback_buffer.h b/chromium/cc/trees/presentation_time_callback_buffer.h
index 820b8fc3767..ab36aa5bd22 100644
--- a/chromium/cc/trees/presentation_time_callback_buffer.h
+++ b/chromium/cc/trees/presentation_time_callback_buffer.h
@@ -6,9 +6,11 @@
#include <vector>
+#include "base/callback_forward.h"
#include "base/containers/circular_deque.h"
#include "base/sequence_checker.h"
-#include "cc/trees/layer_tree_host.h"
+#include "cc/cc_export.h"
+#include "ui/gfx/presentation_feedback.h"
namespace cc {
@@ -32,7 +34,15 @@ namespace cc {
// CC_EXPORT is only needed for testing.
class CC_EXPORT PresentationTimeCallbackBuffer {
public:
- using CallbackType = LayerTreeHost::PresentationTimeCallback;
+ // TODO(crbug.com/1199373): Compositor thread callbacks are only run for
+ // successful presentations and only need the presentation timestamp. On the
+ // other hand, main thread callbacks can be run on both successful and failed
+ // presentations and need a full `gfx::PresentationFeedback`. Conceptually,
+ // main thread callbacks should only be run for successful presentations, too,
+ // in which case the two callback signatures can be unified.
+ using MainCallback =
+ base::OnceCallback<void(const gfx::PresentationFeedback&)>;
+ using CompositorCallback = base::OnceCallback<void(base::TimeTicks)>;
PresentationTimeCallbackBuffer();
@@ -51,14 +61,14 @@ class CC_EXPORT PresentationTimeCallbackBuffer {
// main thread once they're popped.
void RegisterMainThreadPresentationCallbacks(
uint32_t frame_token,
- std::vector<CallbackType> callbacks);
+ std::vector<MainCallback> callbacks);
// Buffers the given |callbacks| in preparation for a GPU frame swap at or
// after the given |frame_token|. Calling code invokes these callbacks on the
// compositor thread once they're popped.
void RegisterCompositorPresentationCallbacks(
uint32_t frame_token,
- std::vector<CallbackType> callbacks);
+ std::vector<CompositorCallback> callbacks);
// Structured return value for |PopPendingCallbacks|. CC_EXPORT is only
// needed for testing.
@@ -75,18 +85,19 @@ class CC_EXPORT PresentationTimeCallbackBuffer {
// Holds callbacks registered through
// |RegisterMainThreadPresentationCallbacks|.
- std::vector<CallbackType> main_thread_callbacks;
+ std::vector<MainCallback> main_thread_callbacks;
// Holds callbacks registered through
// |RegisterCompositorPresentationCallbacks|.
- std::vector<CallbackType> compositor_thread_callbacks;
+ std::vector<CompositorCallback> compositor_thread_callbacks;
};
- // Call this once the presentation for the given |frame_token| has completed.
+ // Call this once the presentation for the given `frame_token` has completed.
// Yields any pending callbacks that were registered against a frame token
- // that was less than or equal to the given |frame_token|. It is the caller's
+ // that was less than or equal to the given `frame_token`. If `main_only` is
+ // true, only callbacks for the main thread are returned. It is the caller's
// responsibility to run the callbacks on the right threads/sequences.
- PendingCallbacks PopPendingCallbacks(uint32_t frame_token);
+ PendingCallbacks PopPendingCallbacks(uint32_t frame_token, bool main_only);
private:
// Stores information needed once we get a response for a particular
@@ -104,10 +115,10 @@ class CC_EXPORT PresentationTimeCallbackBuffer {
uint32_t token;
// The callbacks to send back to the main thread.
- std::vector<CallbackType> main_thread_callbacks;
+ std::vector<MainCallback> main_thread_callbacks;
// The callbacks to invoke on the compositor thread.
- std::vector<CallbackType> compositor_thread_callbacks;
+ std::vector<CompositorCallback> compositor_thread_callbacks;
};
// Returns a reference to a |FrameTokenInfo| with the given |frame_token|.
diff --git a/chromium/cc/trees/presentation_time_callback_buffer_unittest.cc b/chromium/cc/trees/presentation_time_callback_buffer_unittest.cc
index 6b8aa1e0186..ee68a898f3c 100644
--- a/chromium/cc/trees/presentation_time_callback_buffer_unittest.cc
+++ b/chromium/cc/trees/presentation_time_callback_buffer_unittest.cc
@@ -4,16 +4,18 @@
#include "cc/trees/presentation_time_callback_buffer.h"
+#include "base/bind.h"
+#include "base/callback.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
-std::vector<cc::PresentationTimeCallbackBuffer::CallbackType> GenerateCallbacks(
- int num_callbacks) {
- std::vector<cc::PresentationTimeCallbackBuffer::CallbackType> result;
+std::vector<cc::PresentationTimeCallbackBuffer::MainCallback>
+GenerateMainCallbacks(int num_callbacks) {
+ std::vector<cc::PresentationTimeCallbackBuffer::MainCallback> result;
while (num_callbacks-- > 0) {
- // PresentationTimeCallbackBuffer isn't supposed to invoke any callbacks.
+ // `PresentationTimeCallbackBuffer` isn't supposed to invoke any callbacks.
// We can check for that by passing callbacks which cause test failure.
result.push_back(base::BindOnce([](const gfx::PresentationFeedback&) {
FAIL() << "Callbacks should not be directly invoked by "
@@ -24,6 +26,22 @@ std::vector<cc::PresentationTimeCallbackBuffer::CallbackType> GenerateCallbacks(
return result;
}
+std::vector<cc::PresentationTimeCallbackBuffer::CompositorCallback>
+GenerateCompositorCallbacks(int num_callbacks) {
+ std::vector<cc::PresentationTimeCallbackBuffer::CompositorCallback> result;
+
+ while (num_callbacks-- > 0) {
+ // `PresentationTimeCallbackBuffer` isn't supposed to invoke any callbacks.
+ // We can check for that by passing callbacks which cause test failure.
+ result.push_back(base::BindOnce([](base::TimeTicks presentation_timestamp) {
+ FAIL() << "Callbacks should not be directly invoked by "
+ "PresentationTimeCallbackBuffer";
+ }));
+ }
+
+ return result;
+}
+
constexpr uint32_t kFrameToken1 = 234;
constexpr uint32_t kFrameToken2 = 345;
constexpr uint32_t kFrameToken3 = 456;
@@ -36,7 +54,7 @@ namespace cc {
TEST(PresentationTimeCallbackBufferTest, TestNoCallbacks) {
PresentationTimeCallbackBuffer buffer;
- auto result = buffer.PopPendingCallbacks(kFrameToken1);
+ auto result = buffer.PopPendingCallbacks(kFrameToken1, false);
EXPECT_TRUE(result.main_thread_callbacks.empty());
EXPECT_TRUE(result.compositor_thread_callbacks.empty());
@@ -46,25 +64,25 @@ TEST(PresentationTimeCallbackBufferTest, TestOneMainThreadCallback) {
PresentationTimeCallbackBuffer buffer;
buffer.RegisterMainThreadPresentationCallbacks(kFrameToken2,
- GenerateCallbacks(1));
+ GenerateMainCallbacks(1));
// Make sure that popping early frame tokens doesn't return irrelevant
// entries.
{
- auto result = buffer.PopPendingCallbacks(kFrameToken1);
+ auto result = buffer.PopPendingCallbacks(kFrameToken1, false);
EXPECT_TRUE(result.main_thread_callbacks.empty());
EXPECT_TRUE(result.compositor_thread_callbacks.empty());
}
{
- auto result = buffer.PopPendingCallbacks(kFrameToken2);
+ auto result = buffer.PopPendingCallbacks(kFrameToken2, false);
EXPECT_EQ(result.main_thread_callbacks.size(), 1ull);
EXPECT_TRUE(result.compositor_thread_callbacks.empty());
}
// Make sure that the buffer has removed the registration since the "pop".
{
- auto result = buffer.PopPendingCallbacks(kFrameToken2);
+ auto result = buffer.PopPendingCallbacks(kFrameToken2, false);
EXPECT_TRUE(result.main_thread_callbacks.empty());
EXPECT_TRUE(result.compositor_thread_callbacks.empty());
}
@@ -73,26 +91,26 @@ TEST(PresentationTimeCallbackBufferTest, TestOneMainThreadCallback) {
TEST(PresentationTimeCallbackBufferTest, TestOneCompositorThreadCallback) {
PresentationTimeCallbackBuffer buffer;
- buffer.RegisterCompositorPresentationCallbacks(kFrameToken2,
- GenerateCallbacks(1));
+ buffer.RegisterCompositorPresentationCallbacks(
+ kFrameToken2, GenerateCompositorCallbacks(1));
// Make sure that popping early frame tokens doesn't return irrelevant
// entries.
{
- auto result = buffer.PopPendingCallbacks(kFrameToken1);
+ auto result = buffer.PopPendingCallbacks(kFrameToken1, false);
EXPECT_TRUE(result.main_thread_callbacks.empty());
EXPECT_TRUE(result.compositor_thread_callbacks.empty());
}
{
- auto result = buffer.PopPendingCallbacks(kFrameToken2);
+ auto result = buffer.PopPendingCallbacks(kFrameToken2, false);
EXPECT_TRUE(result.main_thread_callbacks.empty());
EXPECT_EQ(result.compositor_thread_callbacks.size(), 1ull);
}
// Make sure that the buffer has removed the registration since the "pop".
{
- auto result = buffer.PopPendingCallbacks(kFrameToken2);
+ auto result = buffer.PopPendingCallbacks(kFrameToken2, false);
EXPECT_TRUE(result.main_thread_callbacks.empty());
EXPECT_TRUE(result.compositor_thread_callbacks.empty());
}
@@ -102,27 +120,27 @@ TEST(PresentationTimeCallbackBufferTest, TestMixedCallbacks) {
PresentationTimeCallbackBuffer buffer;
buffer.RegisterMainThreadPresentationCallbacks(kFrameToken2,
- GenerateCallbacks(1));
- buffer.RegisterCompositorPresentationCallbacks(kFrameToken2,
- GenerateCallbacks(1));
+ GenerateMainCallbacks(1));
+ buffer.RegisterCompositorPresentationCallbacks(
+ kFrameToken2, GenerateCompositorCallbacks(1));
// Make sure that popping early frame tokens doesn't return irrelevant
// entries.
{
- auto result = buffer.PopPendingCallbacks(kFrameToken1);
+ auto result = buffer.PopPendingCallbacks(kFrameToken1, false);
EXPECT_TRUE(result.main_thread_callbacks.empty());
EXPECT_TRUE(result.compositor_thread_callbacks.empty());
}
{
- auto result = buffer.PopPendingCallbacks(kFrameToken2);
+ auto result = buffer.PopPendingCallbacks(kFrameToken2, false);
EXPECT_EQ(result.main_thread_callbacks.size(), 1ull);
EXPECT_EQ(result.compositor_thread_callbacks.size(), 1ull);
}
// Make sure that the buffer has removed the registrations since the "pop".
{
- auto result = buffer.PopPendingCallbacks(kFrameToken2);
+ auto result = buffer.PopPendingCallbacks(kFrameToken2, false);
EXPECT_TRUE(result.main_thread_callbacks.empty());
EXPECT_TRUE(result.compositor_thread_callbacks.empty());
}
@@ -133,19 +151,66 @@ TEST(PresentationTimeCallbackBufferTest, TestCallbackBatching) {
// Register one callback for frame1, two for frame2 and two for frame4.
buffer.RegisterMainThreadPresentationCallbacks(kFrameToken1,
- GenerateCallbacks(1));
+ GenerateMainCallbacks(1));
buffer.RegisterMainThreadPresentationCallbacks(kFrameToken2,
- GenerateCallbacks(2));
+ GenerateMainCallbacks(2));
buffer.RegisterMainThreadPresentationCallbacks(kFrameToken4,
- GenerateCallbacks(2));
+ GenerateMainCallbacks(2));
// Pop callbacks up to and including frame3. Should be three in total; one
// from frame1 and two from frame2.
{
- auto result = buffer.PopPendingCallbacks(kFrameToken3);
+ auto result = buffer.PopPendingCallbacks(kFrameToken3, false);
EXPECT_EQ(result.main_thread_callbacks.size(), 3ull);
EXPECT_TRUE(result.compositor_thread_callbacks.empty());
}
}
+// Tests that popping callbacks for main thread only vs. for both main and
+// compositor threads works properly.
+TEST(PresentationTimeCallbackBufferTest, PopMainCallbacksOnly) {
+ PresentationTimeCallbackBuffer buffer;
+
+ // Register callbacks for main and compositor threads of 3 frames.
+ buffer.RegisterMainThreadPresentationCallbacks(kFrameToken1,
+ GenerateMainCallbacks(1));
+ buffer.RegisterCompositorPresentationCallbacks(
+ kFrameToken1, GenerateCompositorCallbacks(1));
+ buffer.RegisterMainThreadPresentationCallbacks(kFrameToken2,
+ GenerateMainCallbacks(1));
+ buffer.RegisterCompositorPresentationCallbacks(
+ kFrameToken2, GenerateCompositorCallbacks(1));
+ buffer.RegisterMainThreadPresentationCallbacks(kFrameToken3,
+ GenerateMainCallbacks(1));
+ buffer.RegisterCompositorPresentationCallbacks(
+ kFrameToken3, GenerateCompositorCallbacks(1));
+
+ // Pop only main thread callbacks up to and including frame1. The result
+ // should only contain 1 main thread callback of frame1 and no compositor
+ // thread callback.
+ {
+ auto result = buffer.PopPendingCallbacks(kFrameToken1, true);
+ EXPECT_EQ(result.main_thread_callbacks.size(), 1ull);
+ EXPECT_TRUE(result.compositor_thread_callbacks.empty());
+ }
+
+ // Pop only main thread callbacks up to and including frame2. The result
+ // should only contain 1 main thread callback of frame2 and no compositor
+ // thread callback.
+ {
+ auto result = buffer.PopPendingCallbacks(kFrameToken2, true);
+ EXPECT_EQ(result.main_thread_callbacks.size(), 1ull);
+ EXPECT_TRUE(result.compositor_thread_callbacks.empty());
+ }
+
+ // Pop both main and compositor thread callbacks up to and including frame3.
+ // The result should contain 1 main thread callback of frame3 and all 3
+ // compositor thread callbacks of the 3 frames.
+ {
+ auto result = buffer.PopPendingCallbacks(kFrameToken3, false);
+ EXPECT_EQ(result.main_thread_callbacks.size(), 1ull);
+ EXPECT_EQ(result.compositor_thread_callbacks.size(), 3ull);
+ }
+}
+
} // namespace cc
diff --git a/chromium/cc/trees/property_tree.cc b/chromium/cc/trees/property_tree.cc
index 211e67ce70d..076797230cf 100644
--- a/chromium/cc/trees/property_tree.cc
+++ b/chromium/cc/trees/property_tree.cc
@@ -1495,7 +1495,8 @@ void ScrollTree::CollectScrollDeltas(
CompositorCommitData* commit_data,
ElementId inner_viewport_scroll_element_id,
bool use_fractional_deltas,
- const base::flat_set<ElementId>& snapped_elements) {
+ const base::flat_map<ElementId, TargetSnapAreaElementIds>&
+ snapped_elements) {
DCHECK(!property_trees()->is_main_thread);
TRACE_EVENT0("cc", "ScrollTree::CollectScrollDeltas");
for (auto map_entry : synced_scroll_offset_map_) {
@@ -1505,13 +1506,8 @@ void ScrollTree::CollectScrollDeltas(
ElementId id = map_entry.first;
absl::optional<TargetSnapAreaElementIds> snap_target_ids;
- if (snapped_elements.find(id) != snapped_elements.end()) {
- ScrollNode* scroll_node = FindNodeFromElementId(id);
- if (scroll_node && scroll_node->snap_container_data) {
- snap_target_ids = scroll_node->snap_container_data.value()
- .GetTargetSnapAreaElementIds();
- }
- }
+ if (snapped_elements.contains(id))
+ snap_target_ids = snapped_elements.at(id);
// Snap targets are set at the end of scroll offset animations (i.e when the
// animation state is updated to FINISHED). The state can be updated after
@@ -1724,13 +1720,15 @@ void ScrollTree::SetScrollCallbacks(base::WeakPtr<ScrollCallbacks> callbacks) {
callbacks_ = std::move(callbacks);
}
-void ScrollTree::NotifyDidScroll(
+void ScrollTree::NotifyDidCompositorScroll(
ElementId scroll_element_id,
const gfx::ScrollOffset& scroll_offset,
const absl::optional<TargetSnapAreaElementIds>& snap_target_ids) {
DCHECK(property_trees()->is_main_thread);
- if (callbacks_)
- callbacks_->DidScroll(scroll_element_id, scroll_offset, snap_target_ids);
+ if (callbacks_) {
+ callbacks_->DidCompositorScroll(scroll_element_id, scroll_offset,
+ snap_target_ids);
+ }
}
void ScrollTree::NotifyDidChangeScrollbarsHidden(ElementId scroll_element_id,
diff --git a/chromium/cc/trees/property_tree.h b/chromium/cc/trees/property_tree.h
index 13a73759d45..3ac68f86ee4 100644
--- a/chromium/cc/trees/property_tree.h
+++ b/chromium/cc/trees/property_tree.h
@@ -23,6 +23,7 @@
#include "cc/paint/filter_operations.h"
#include "cc/trees/mutator_host.h"
#include "cc/trees/sticky_position_constraint.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/scroll_offset.h"
#include "ui/gfx/transform.h"
@@ -57,12 +58,7 @@ class CC_EXPORT PropertyTree {
public:
PropertyTree();
PropertyTree(const PropertyTree& other) = delete;
-
- // These C++ special member functions cannot be implicit inline because
- // 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.
- virtual ~PropertyTree();
+ ~PropertyTree();
PropertyTree<T>& operator=(const PropertyTree<T>&);
// Property tree node starts from index 0. See equivalent constants in
@@ -78,11 +74,11 @@ class CC_EXPORT PropertyTree {
int Insert(const T& tree_node, int parent_id);
T* Node(int i) {
- DCHECK(i < static_cast<int>(nodes_.size()));
+ CHECK_LT(i, static_cast<int>(nodes_.size()));
return i > kInvalidNodeId ? &nodes_[i] : nullptr;
}
const T* Node(int i) const {
- DCHECK(i < static_cast<int>(nodes_.size()));
+ CHECK_LT(i, static_cast<int>(nodes_.size()));
return i > kInvalidNodeId ? &nodes_[i] : nullptr;
}
@@ -95,7 +91,7 @@ class CC_EXPORT PropertyTree {
void clear();
size_t size() const { return nodes_.size(); }
- virtual void set_needs_update(bool needs_update) {
+ void set_needs_update(bool needs_update) {
needs_update_ = needs_update;
}
bool needs_update() const { return needs_update_; }
@@ -129,7 +125,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() final;
+ ~TransformTree();
TransformTree& operator=(const TransformTree&);
#if DCHECK_IS_ON()
@@ -155,7 +151,7 @@ class CC_EXPORT TransformTree final : public PropertyTree<TransformNode> {
void UpdateNodeOrAncestorsWillChangeTransform(TransformNode* node,
TransformNode* parent_node);
- void set_needs_update(bool needs_update) final;
+ void set_needs_update(bool needs_update);
// We store the page scale factor on the transform tree so that it can be
// easily be retrieved and updated in UpdatePageScale.
@@ -288,7 +284,7 @@ class CC_EXPORT ClipTree final : public PropertyTree<ClipNode> {
class CC_EXPORT EffectTree final : public PropertyTree<EffectNode> {
public:
EffectTree();
- ~EffectTree() final;
+ ~EffectTree();
EffectTree& operator=(const EffectTree& from);
@@ -385,9 +381,10 @@ class CC_EXPORT EffectTree final : public PropertyTree<EffectNode> {
class ScrollCallbacks {
public:
// Called after the composited scroll offset changed.
- virtual void DidScroll(ElementId scroll_element_id,
- const gfx::ScrollOffset&,
- const absl::optional<TargetSnapAreaElementIds>&) = 0;
+ virtual void DidCompositorScroll(
+ ElementId scroll_element_id,
+ const gfx::ScrollOffset&,
+ const absl::optional<TargetSnapAreaElementIds>&) = 0;
// Called after the hidden status of composited scrollbars changed. Note that
// |scroll_element_id| is the element id of the scroll not of the scrollbars.
virtual void DidChangeScrollbarsHidden(ElementId scroll_element_id,
@@ -400,7 +397,7 @@ class ScrollCallbacks {
class CC_EXPORT ScrollTree final : public PropertyTree<ScrollNode> {
public:
ScrollTree();
- ~ScrollTree() final;
+ ~ScrollTree();
ScrollTree& operator=(const ScrollTree& from);
@@ -449,10 +446,12 @@ class CC_EXPORT ScrollTree final : public PropertyTree<ScrollNode> {
// Collects deltas for scroll changes on the impl thread that need to be
// reported to the main thread during the main frame. As such, should only be
// called on the impl thread side PropertyTrees.
- void CollectScrollDeltas(CompositorCommitData* commit_data,
- ElementId inner_viewport_scroll_element_id,
- bool use_fractional_deltas,
- const base::flat_set<ElementId>& snapped_elements);
+ void CollectScrollDeltas(
+ CompositorCommitData* commit_data,
+ ElementId inner_viewport_scroll_element_id,
+ bool use_fractional_deltas,
+ const base::flat_map<ElementId, TargetSnapAreaElementIds>&
+ snapped_elements);
// Applies deltas sent in the previous main frame onto the impl thread state.
// Should only be called on the impl thread side PropertyTrees.
@@ -502,7 +501,7 @@ class CC_EXPORT ScrollTree final : public PropertyTree<ScrollNode> {
void SetScrollCallbacks(base::WeakPtr<ScrollCallbacks> callbacks);
- void NotifyDidScroll(
+ void NotifyDidCompositorScroll(
ElementId scroll_element_id,
const gfx::ScrollOffset& scroll_offset,
const absl::optional<TargetSnapAreaElementIds>& snap_target_ids);
diff --git a/chromium/cc/trees/property_tree_builder.cc b/chromium/cc/trees/property_tree_builder.cc
index 5bd4eeeae24..99083b30235 100644
--- a/chromium/cc/trees/property_tree_builder.cc
+++ b/chromium/cc/trees/property_tree_builder.cc
@@ -10,6 +10,7 @@
#include <memory>
#include <set>
#include <utility>
+#include <vector>
#include "base/auto_reset.h"
#include "cc/base/math_util.h"
@@ -26,6 +27,7 @@
#include "cc/trees/transform_node.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/vector2d_conversions.h"
namespace cc {
@@ -455,6 +457,23 @@ bool PropertyTreeBuilderContext::AddEffectNodeIfNeeded(
node->opacity = layer->opacity();
node->blend_mode = layer->blend_mode();
node->subtree_capture_id = layer->subtree_capture_id();
+
+ // Layers marked with a valid |subtree_capture_id| represent a subsection
+ // of the tree that should be rendered and copied as a separate render pass.
+ // Using the layer bounds as the subtree size here allows us to crop out
+ // undesired sections of the render pass, such as the shadow added by the
+ // shadow layer.
+ //
+ // If it becomes desirable to capture a different sub-rectangle of the render
+ // pass, a new custom size (or potentially rect) can be plumbed through the
+ // layer to here.
+ if (node->subtree_capture_id.is_valid()) {
+ // Layer bounds are specified in layer space, which excludes device and
+ // page scale factors. While the page scale can be ignored for subtree
+ // capture purposes, the device scale must be accounted for here.
+ node->subtree_size = gfx::ScaleToFlooredSize(
+ layer->bounds(), layer_tree_host_->device_scale_factor());
+ }
node->cache_render_surface = layer->cache_render_surface();
node->has_copy_request = layer->HasCopyRequest();
node->filters = layer->filters();
diff --git a/chromium/cc/trees/property_tree_builder_unittest.cc b/chromium/cc/trees/property_tree_builder_unittest.cc
index 2576916ed38..0b11f149d9f 100644
--- a/chromium/cc/trees/property_tree_builder_unittest.cc
+++ b/chromium/cc/trees/property_tree_builder_unittest.cc
@@ -356,8 +356,9 @@ TEST_F(PropertyTreeBuilderTest, VisibleRectWithClippingAndFilters) {
gfx::Transform vertical_flip;
vertical_flip.Scale(1, -1);
- sk_sp<PaintFilter> flip_filter = sk_make_sp<MatrixPaintFilter>(
- SkMatrix(vertical_flip.matrix()), kLow_SkFilterQuality, nullptr);
+ sk_sp<PaintFilter> flip_filter =
+ sk_make_sp<MatrixPaintFilter>(SkMatrix(vertical_flip.matrix()),
+ PaintFlags::FilterQuality::kLow, nullptr);
FilterOperations reflection_filter;
reflection_filter.Append(
FilterOperation::CreateReferenceFilter(sk_make_sp<XfermodePaintFilter>(
@@ -416,8 +417,9 @@ TEST_F(PropertyTreeBuilderTest, VisibleRectWithScalingClippingAndFilters) {
gfx::Transform vertical_flip;
vertical_flip.Scale(1, -1);
- sk_sp<PaintFilter> flip_filter = sk_make_sp<MatrixPaintFilter>(
- SkMatrix(vertical_flip.matrix()), kLow_SkFilterQuality, nullptr);
+ sk_sp<PaintFilter> flip_filter =
+ sk_make_sp<MatrixPaintFilter>(SkMatrix(vertical_flip.matrix()),
+ PaintFlags::FilterQuality::kLow, nullptr);
FilterOperations reflection_filter;
reflection_filter.Append(
FilterOperation::CreateReferenceFilter(sk_make_sp<XfermodePaintFilter>(
@@ -1827,5 +1829,32 @@ TEST_F(PropertyTreeBuilderTest,
kRoundedCorner4Radius * kDeviceScale);
}
+TEST_F(PropertyTreeBuilderTest, SubtreeSize) {
+ constexpr viz::SubtreeCaptureId kCaptureId{42};
+
+ auto parent = Layer::Create();
+ host()->SetRootLayer(parent);
+ auto child = Layer::Create();
+ parent->AddChild(child);
+ child->SetSubtreeCaptureId(kCaptureId);
+
+ // Layer has empty bounds.
+ Commit(1.1f);
+ EffectNode* node = GetEffectNode(child.get());
+ EXPECT_EQ((gfx::Size{}), node->subtree_size);
+ EXPECT_EQ(kCaptureId, node->subtree_capture_id);
+
+ // Layer has bounds, scaling is 1.
+ child->SetBounds(gfx::Size{1280, 720});
+ Commit(1.0f);
+ node = GetEffectNode(child.get());
+ EXPECT_EQ((gfx::Size{1280, 720}), node->subtree_size);
+
+ // Layer has bounds, scaling is 2.
+ Commit(2.0f);
+ node = GetEffectNode(child.get());
+ EXPECT_EQ((gfx::Size{2560, 1440}), node->subtree_size);
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/trees/proxy.h b/chromium/cc/trees/proxy.h
index c927579ed7b..316fbd1a25e 100644
--- a/chromium/cc/trees/proxy.h
+++ b/chromium/cc/trees/proxy.h
@@ -14,8 +14,10 @@
#include "cc/cc_export.h"
#include "cc/input/browser_controls_state.h"
#include "cc/trees/paint_holding_commit_trigger.h"
+#include "cc/trees/paint_holding_reason.h"
#include "cc/trees/task_runner_provider.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
+#include "components/viz/common/surfaces/local_surface_id.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "url/gurl.h"
@@ -48,6 +50,8 @@ class CC_EXPORT Proxy {
virtual void SetNeedsCommit() = 0;
virtual void SetNeedsRedraw(const gfx::Rect& damage_rect) = 0;
virtual void SetNextCommitWaitsForActivation() = 0;
+ virtual void SetTargetLocalSurfaceId(
+ const viz::LocalSurfaceId& target_local_surface_id) = 0;
// Returns true if an animate or commit has been requested, and hasn't
// completed yet.
@@ -61,11 +65,14 @@ class CC_EXPORT Proxy {
// but continues to update the document lifecycle in
// LayerTreeHost::BeginMainFrameUpdate. If multiple calls are made when
// deferal is active the first |timeout| continues to apply.
- virtual void StartDeferringCommits(base::TimeDelta timeout) = 0;
+ virtual bool StartDeferringCommits(base::TimeDelta timeout,
+ PaintHoldingReason reason) = 0;
// Immediately stop deferring commits.
virtual void StopDeferringCommits(PaintHoldingCommitTrigger) = 0;
+ virtual bool IsDeferringCommits() const = 0;
+
virtual bool CommitRequested() const = 0;
// Must be called before using the proxy.
diff --git a/chromium/cc/trees/proxy_impl.cc b/chromium/cc/trees/proxy_impl.cc
index 726d6ff1233..2c8babc0eb0 100644
--- a/chromium/cc/trees/proxy_impl.cc
+++ b/chromium/cc/trees/proxy_impl.cc
@@ -187,6 +187,12 @@ void ProxyImpl::SetNeedsCommitOnImpl() {
SetNeedsCommitOnImplThread();
}
+void ProxyImpl::SetTargetLocalSurfaceIdOnImpl(
+ const viz::LocalSurfaceId& target_local_surface_id) {
+ DCHECK(IsImplThread());
+ host_impl_->SetTargetLocalSurfaceId(target_local_surface_id);
+}
+
void ProxyImpl::BeginMainFrameAbortedOnImpl(
CommitEarlyOutReason reason,
base::TimeTicks main_thread_start_time,
@@ -404,6 +410,7 @@ void ProxyImpl::RenewTreePriority() {
DCHECK(IsImplThread());
bool scroll_type_considered_interaction = false;
+ bool prefer_new_content = false;
bool non_scroll_interaction_in_progress =
host_impl_->IsPinchGestureActive() ||
host_impl_->page_scale_animation_active();
@@ -430,8 +437,14 @@ void ProxyImpl::RenewTreePriority() {
user_interaction_in_progress);
}
+ if (host_impl_->CurrentScrollDidCheckerboardLargeArea() &&
+ base::FeatureList::IsEnabled(
+ features::kPreferNewContentForCheckerboardedScrolls)) {
+ prefer_new_content = true;
+ }
+
// Schedule expiration if smoothness currently takes priority.
- if (user_interaction_in_progress)
+ if (user_interaction_in_progress && !prefer_new_content)
smoothness_priority_expiration_notifier_.Schedule();
// We use the same priority for both trees by default.
diff --git a/chromium/cc/trees/proxy_impl.h b/chromium/cc/trees/proxy_impl.h
index 05eb84ed3eb..15f13db26b1 100644
--- a/chromium/cc/trees/proxy_impl.h
+++ b/chromium/cc/trees/proxy_impl.h
@@ -54,6 +54,8 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient,
void SetDeferBeginMainFrameOnImpl(bool defer_begin_main_frame) const;
void SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect);
void SetNeedsCommitOnImpl();
+ void SetTargetLocalSurfaceIdOnImpl(
+ const viz::LocalSurfaceId& target_local_surface_id);
void BeginMainFrameAbortedOnImpl(
CommitEarlyOutReason reason,
base::TimeTicks main_thread_start_time,
diff --git a/chromium/cc/trees/proxy_main.cc b/chromium/cc/trees/proxy_main.cc
index 6f1e341a730..735a814e1f5 100644
--- a/chromium/cc/trees/proxy_main.cc
+++ b/chromium/cc/trees/proxy_main.cc
@@ -22,6 +22,7 @@
#include "cc/trees/layer_tree_frame_sink.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/mutator_host.h"
+#include "cc/trees/paint_holding_reason.h"
#include "cc/trees/proxy_impl.h"
#include "cc/trees/render_frame_metadata_observer.h"
#include "cc/trees/scoped_abort_remaining_swap_promises.h"
@@ -41,8 +42,7 @@ ProxyMain::ProxyMain(LayerTreeHost* layer_tree_host,
deferred_final_pipeline_stage_(NO_PIPELINE_STAGE),
commit_waits_for_activation_(false),
started_(false),
- defer_main_frame_update_(false),
- defer_commits_(false) {
+ defer_main_frame_update_(false) {
TRACE_EVENT0("cc", "ProxyMain::ProxyMain");
DCHECK(task_runner_provider_);
DCHECK(IsMainThread());
@@ -170,24 +170,10 @@ void ProxyMain::BeginMainFrame(
final_pipeline_stage_ = max_requested_pipeline_stage_;
max_requested_pipeline_stage_ = NO_PIPELINE_STAGE;
- // When we don't need to produce a CompositorFrame, there's also no need to
- // commit our updates. We still need to run layout and paint though, as it can
- // have side effects on page loading behavior.
- bool skip_commit = begin_main_frame_state->begin_frame_args.animate_only;
-
// If main frame updates and commits are deferred, skip the entire pipeline.
- bool skip_full_pipeline = defer_main_frame_update_;
-
- // We may have previously skipped paint and commit. If we should still skip it
- // now, and there was no intermediate request for a commit since the last
- // BeginMainFrame, we can skip the full pipeline.
- skip_full_pipeline |=
- skip_commit && final_pipeline_stage_ == NO_PIPELINE_STAGE;
-
- if (skip_full_pipeline) {
+ if (defer_main_frame_update_) {
TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit",
TRACE_EVENT_SCOPE_THREAD);
-
// In this case, since the commit is deferred to a later time, gathered
// events metrics are not discarded so that they can be reported if the
// commit happens in the future.
@@ -215,9 +201,9 @@ void ProxyMain::BeginMainFrame(
// Check now if we should stop deferring commits due to a timeout. We
// may also stop deferring in layer_tree_host_->BeginMainFrame, but update
// the status at this point to keep scroll in sync.
- if (defer_commits_ && base::TimeTicks::Now() > commits_restart_time_)
- StopDeferringCommits(PaintHoldingCommitTrigger::kTimeout);
- skip_commit |= defer_commits_;
+ if (IsDeferringCommits() && base::TimeTicks::Now() > commits_restart_time_)
+ StopDeferringCommits(ReasonToTimeoutTrigger(*paint_holding_reason_));
+ bool skip_commit = IsDeferringCommits();
if (!skip_commit) {
// Synchronizes scroll offsets and page scale deltas (for pinch zoom) from
@@ -264,7 +250,12 @@ void ProxyMain::BeginMainFrame(
// avoid committing right now, or we may be deferring commits but not
// deferring main frame updates. Either may have changed the status
// of the defer... flags, so re-evaluate skip_commit.
- skip_commit |= defer_main_frame_update_ || defer_commits_;
+ skip_commit |= defer_main_frame_update_ || IsDeferringCommits();
+
+ // When we don't need to produce a CompositorFrame, there's also no need to
+ // commit our updates. We still need to run layout and paint though, as it can
+ // have side effects on page loading behavior.
+ skip_commit |= begin_main_frame_state->begin_frame_args.animate_only;
if (skip_commit) {
current_pipeline_stage_ = NO_PIPELINE_STAGE;
@@ -317,7 +308,8 @@ void ProxyMain::BeginMainFrame(
layer_tree_host_->WillCommit();
devtools_instrumentation::ScopedCommitTrace commit_task(
- layer_tree_host_->GetId());
+ layer_tree_host_->GetId(),
+ begin_main_frame_state->begin_frame_args.frame_id.sequence_number);
current_pipeline_stage_ = COMMIT_PIPELINE_STAGE;
if (final_pipeline_stage_ < COMMIT_PIPELINE_STAGE) {
@@ -387,7 +379,7 @@ void ProxyMain::BeginMainFrame(
void ProxyMain::DidPresentCompositorFrame(
uint32_t frame_token,
- std::vector<LayerTreeHost::PresentationTimeCallback> callbacks,
+ std::vector<PresentationTimeCallbackBuffer::MainCallback> callbacks,
const gfx::PresentationFeedback& feedback) {
layer_tree_host_->DidPresentCompositorFrame(frame_token, std::move(callbacks),
feedback);
@@ -477,6 +469,15 @@ void ProxyMain::SetNextCommitWaitsForActivation() {
commit_waits_for_activation_ = true;
}
+void ProxyMain::SetTargetLocalSurfaceId(
+ const viz::LocalSurfaceId& target_local_surface_id) {
+ DCHECK(IsMainThread());
+ ImplThreadTaskRunner()->PostTask(
+ FROM_HERE, base::BindOnce(&ProxyImpl::SetTargetLocalSurfaceIdOnImpl,
+ base::Unretained(proxy_impl_.get()),
+ target_local_surface_id));
+}
+
bool ProxyMain::RequestedAnimatePending() {
return max_requested_pipeline_stage_ >= ANIMATE_PIPELINE_STAGE;
}
@@ -505,35 +506,43 @@ void ProxyMain::SetDeferMainFrameUpdate(bool defer_main_frame_update) {
defer_main_frame_update));
}
-void ProxyMain::StartDeferringCommits(base::TimeDelta timeout) {
+bool ProxyMain::StartDeferringCommits(base::TimeDelta timeout,
+ PaintHoldingReason reason) {
DCHECK(task_runner_provider_->IsMainThread());
// Do nothing if already deferring. The timeout remains as it was from when
// we most recently began deferring.
- if (defer_commits_)
- return;
+ if (IsDeferringCommits())
+ return false;
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("cc", "ProxyMain::SetDeferCommits",
TRACE_ID_LOCAL(this));
- defer_commits_ = true;
+ paint_holding_reason_ = reason;
commits_restart_time_ = base::TimeTicks::Now() + timeout;
// Notify dependent systems that the deferral status has changed.
- layer_tree_host_->OnDeferCommitsChanged(defer_commits_);
+ layer_tree_host_->OnDeferCommitsChanged(true, reason);
+ return true;
}
void ProxyMain::StopDeferringCommits(PaintHoldingCommitTrigger trigger) {
- if (!defer_commits_)
+ if (!IsDeferringCommits())
return;
- defer_commits_ = false;
+ auto reason = *paint_holding_reason_;
+ paint_holding_reason_.reset();
UMA_HISTOGRAM_ENUMERATION("PaintHolding.CommitTrigger2", trigger);
commits_restart_time_ = base::TimeTicks();
TRACE_EVENT_NESTABLE_ASYNC_END0("cc", "ProxyMain::SetDeferCommits",
TRACE_ID_LOCAL(this));
// Notify depended systems that the deferral status has changed.
- layer_tree_host_->OnDeferCommitsChanged(defer_commits_);
+ layer_tree_host_->OnDeferCommitsChanged(false, reason);
+}
+
+bool ProxyMain::IsDeferringCommits() const {
+ DCHECK(IsMainThread());
+ return paint_holding_reason_.has_value();
}
bool ProxyMain::CommitRequested() const {
diff --git a/chromium/cc/trees/proxy_main.h b/chromium/cc/trees/proxy_main.h
index 186de9d07b6..1157b1adcfb 100644
--- a/chromium/cc/trees/proxy_main.h
+++ b/chromium/cc/trees/proxy_main.h
@@ -11,6 +11,7 @@
#include "cc/cc_export.h"
#include "cc/input/browser_controls_state.h"
#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/paint_holding_reason.h"
#include "cc/trees/proxy.h"
#include "cc/trees/proxy_common.h"
@@ -58,7 +59,7 @@ class CC_EXPORT ProxyMain : public Proxy {
std::unique_ptr<BeginMainFrameAndCommitState> begin_main_frame_state);
void DidPresentCompositorFrame(
uint32_t frame_token,
- std::vector<LayerTreeHost::PresentationTimeCallback> callbacks,
+ std::vector<PresentationTimeCallbackBuffer::MainCallback> callbacks,
const gfx::PresentationFeedback& feedback);
void NotifyThroughputTrackerResults(CustomTrackerResults results);
void DidObserveFirstScrollDelay(base::TimeDelta first_scroll_delay,
@@ -85,10 +86,14 @@ class CC_EXPORT ProxyMain : public Proxy {
void SetNeedsCommit() override;
void SetNeedsRedraw(const gfx::Rect& damage_rect) override;
void SetNextCommitWaitsForActivation() override;
+ void SetTargetLocalSurfaceId(
+ const viz::LocalSurfaceId& target_local_surface_id) override;
bool RequestedAnimatePending() override;
void SetDeferMainFrameUpdate(bool defer_main_frame_update) override;
- void StartDeferringCommits(base::TimeDelta timeout) override;
+ bool StartDeferringCommits(base::TimeDelta timeout,
+ PaintHoldingReason reason) override;
void StopDeferringCommits(PaintHoldingCommitTrigger) override;
+ bool IsDeferringCommits() const override;
bool CommitRequested() const override;
void Start() override;
void Stop() override;
@@ -146,9 +151,9 @@ class CC_EXPORT ProxyMain : public Proxy {
bool started_;
// defer_main_frame_update_ will also cause commits to be deferred, regardless
- // of the setting for defer_commits_.
+ // of the setting for paint_holding_reason_.
bool defer_main_frame_update_;
- bool defer_commits_;
+ absl::optional<PaintHoldingReason> paint_holding_reason_;
// Only used when defer_commits_ is active and must be set in such cases.
base::TimeTicks commits_restart_time_;
diff --git a/chromium/cc/trees/scroll_node.h b/chromium/cc/trees/scroll_node.h
index b178e47f83d..33c764c370a 100644
--- a/chromium/cc/trees/scroll_node.h
+++ b/chromium/cc/trees/scroll_node.h
@@ -11,6 +11,7 @@
#include "cc/input/scroll_snap_data.h"
#include "cc/paint/element_id.h"
#include "cc/paint/filter_operations.h"
+#include "third_party/abseil-cpp/absl/types/optional.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 a24ce56473e..3dfb23d7532 100644
--- a/chromium/cc/trees/single_thread_proxy.cc
+++ b/chromium/cc/trees/single_thread_proxy.cc
@@ -27,6 +27,7 @@
#include "cc/trees/layer_tree_host_single_thread_client.h"
#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/mutator_host.h"
+#include "cc/trees/paint_holding_reason.h"
#include "cc/trees/render_frame_metadata_observer.h"
#include "cc/trees/scoped_abort_remaining_swap_promises.h"
#include "components/power_scheduler/power_mode_arbiter.h"
@@ -56,7 +57,6 @@ SingleThreadProxy::SingleThreadProxy(LayerTreeHost* layer_tree_host,
#endif
inside_draw_(false),
defer_main_frame_update_(false),
- defer_commits_(false),
animate_requested_(false),
update_layers_requested_(false),
commit_requested_(false),
@@ -194,7 +194,7 @@ void SingleThreadProxy::DoCommit(const viz::BeginFrameArgs& commit_args) {
layer_tree_host_->WillCommit();
devtools_instrumentation::ScopedCommitTrace commit_task(
- layer_tree_host_->GetId());
+ layer_tree_host_->GetId(), commit_args.frame_id.sequence_number);
// Commit immediately.
{
@@ -271,6 +271,13 @@ void SingleThreadProxy::SetNextCommitWaitsForActivation() {
DCHECK(task_runner_provider_->IsMainThread());
}
+void SingleThreadProxy::SetTargetLocalSurfaceId(
+ const viz::LocalSurfaceId& target_local_surface_id) {
+ if (!scheduler_on_impl_thread_)
+ return;
+ host_impl_->SetTargetLocalSurfaceId(target_local_surface_id);
+}
+
bool SingleThreadProxy::RequestedAnimatePending() {
return animate_requested_ || update_layers_requested_ || commit_requested_ ||
needs_impl_frame_;
@@ -303,36 +310,44 @@ void SingleThreadProxy::SetDeferMainFrameUpdate(bool defer_main_frame_update) {
scheduler_on_impl_thread_->SetDeferBeginMainFrame(defer_main_frame_update_);
}
-void SingleThreadProxy::StartDeferringCommits(base::TimeDelta timeout) {
+bool SingleThreadProxy::StartDeferringCommits(base::TimeDelta timeout,
+ PaintHoldingReason reason) {
DCHECK(task_runner_provider_->IsMainThread());
// Do nothing if already deferring. The timeout remains as it was from when
// we most recently began deferring.
- if (defer_commits_)
- return;
+ if (IsDeferringCommits())
+ return false;
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("cc", "SingleThreadProxy::SetDeferCommits",
TRACE_ID_LOCAL(this));
- defer_commits_ = true;
+ paint_holding_reason_ = reason;
commits_restart_time_ = base::TimeTicks::Now() + timeout;
// Notify dependent systems that the deferral status has changed.
- layer_tree_host_->OnDeferCommitsChanged(defer_commits_);
+ layer_tree_host_->OnDeferCommitsChanged(true, reason);
+ return true;
}
void SingleThreadProxy::StopDeferringCommits(
PaintHoldingCommitTrigger trigger) {
- if (!defer_commits_)
+ if (!IsDeferringCommits())
return;
- defer_commits_ = false;
+ auto reason = *paint_holding_reason_;
+ paint_holding_reason_.reset();
commits_restart_time_ = base::TimeTicks();
UMA_HISTOGRAM_ENUMERATION("PaintHolding.CommitTrigger2", trigger);
TRACE_EVENT_NESTABLE_ASYNC_END0("cc", "SingleThreadProxy::SetDeferCommits",
TRACE_ID_LOCAL(this));
// Notify dependent systems that the deferral status has changed.
- layer_tree_host_->OnDeferCommitsChanged(defer_commits_);
+ layer_tree_host_->OnDeferCommitsChanged(false, reason);
+}
+
+bool SingleThreadProxy::IsDeferringCommits() const {
+ DCHECK(task_runner_provider_->IsMainThread());
+ return paint_holding_reason_.has_value();
}
bool SingleThreadProxy::CommitRequested() const {
@@ -533,15 +548,13 @@ void SingleThreadProxy::DidPresentCompositorFrameOnImplThread(
uint32_t frame_token,
PresentationTimeCallbackBuffer::PendingCallbacks callbacks,
const viz::FrameTimingDetails& details) {
- std::vector<LayerTreeHost::PresentationTimeCallback> main_thread_callbacks =
- std::move(callbacks.main_thread_callbacks);
DebugScopedSetImplThread impl(task_runner_provider_);
host_impl_->NotifyDidPresentCompositorFrameOnImplThread(
frame_token, std::move(callbacks.compositor_thread_callbacks), details);
{
DebugScopedSetMainThread main(task_runner_provider_);
layer_tree_host_->DidPresentCompositorFrame(
- frame_token, std::move(main_thread_callbacks),
+ frame_token, std::move(callbacks.main_thread_callbacks),
details.presentation_feedback);
}
if (scheduler_on_impl_thread_) {
@@ -852,8 +865,8 @@ void SingleThreadProxy::BeginMainFrame(
// Check now if we should stop deferring commits. Do this before
// DoBeginMainFrame because the latter updates scroll offsets, which
// we should avoid if deferring commits.
- if (defer_commits_ && base::TimeTicks::Now() > commits_restart_time_)
- StopDeferringCommits(PaintHoldingCommitTrigger::kTimeout);
+ if (IsDeferringCommits() && base::TimeTicks::Now() > commits_restart_time_)
+ StopDeferringCommits(ReasonToTimeoutTrigger(*paint_holding_reason_));
DoBeginMainFrame(begin_frame_args);
@@ -862,7 +875,7 @@ void SingleThreadProxy::BeginMainFrame(
// At this point the main frame may have deferred commits to avoid committing
// right now.
- if (defer_main_frame_update_ || defer_commits_ ||
+ if (defer_main_frame_update_ || IsDeferringCommits() ||
begin_frame_args.animate_only) {
TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit_InsideBeginMainFrame",
TRACE_EVENT_SCOPE_THREAD);
@@ -879,7 +892,7 @@ void SingleThreadProxy::DoBeginMainFrame(
const viz::BeginFrameArgs& begin_frame_args) {
// Only update scroll deltas if we are going to commit the frame, otherwise
// scroll offsets get confused.
- if (!defer_commits_) {
+ if (!IsDeferringCommits()) {
// The impl-side scroll deltas may be manipulated directly via the
// InputHandler on the UI thread and the scale deltas may change when they
// are clamped on the impl thread.
diff --git a/chromium/cc/trees/single_thread_proxy.h b/chromium/cc/trees/single_thread_proxy.h
index c5d23a90a38..9d3c9f1864b 100644
--- a/chromium/cc/trees/single_thread_proxy.h
+++ b/chromium/cc/trees/single_thread_proxy.h
@@ -14,9 +14,11 @@
#include "base/time/time.h"
#include "cc/scheduler/scheduler.h"
#include "cc/trees/layer_tree_host_impl.h"
+#include "cc/trees/paint_holding_reason.h"
#include "cc/trees/proxy.h"
#include "cc/trees/task_runner_provider.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
+#include "components/viz/common/surfaces/local_surface_id.h"
namespace viz {
class BeginFrameSource;
@@ -53,10 +55,14 @@ class CC_EXPORT SingleThreadProxy : public Proxy,
void SetNeedsCommit() override;
void SetNeedsRedraw(const gfx::Rect& damage_rect) override;
void SetNextCommitWaitsForActivation() override;
+ void SetTargetLocalSurfaceId(
+ const viz::LocalSurfaceId& target_local_surface_id) override;
bool RequestedAnimatePending() override;
void SetDeferMainFrameUpdate(bool defer_main_frame_update) override;
- void StartDeferringCommits(base::TimeDelta timeout) override;
+ bool StartDeferringCommits(base::TimeDelta timeout,
+ PaintHoldingReason reason) override;
void StopDeferringCommits(PaintHoldingCommitTrigger) override;
+ bool IsDeferringCommits() const override;
bool CommitRequested() const override;
void Start() override;
void Stop() override;
@@ -204,7 +210,7 @@ class CC_EXPORT SingleThreadProxy : public Proxy,
#endif
bool inside_draw_;
bool defer_main_frame_update_;
- bool defer_commits_;
+ absl::optional<PaintHoldingReason> paint_holding_reason_;
bool animate_requested_;
bool update_layers_requested_;
bool commit_requested_;
diff --git a/chromium/cc/trees/sticky_position_constraint.cc b/chromium/cc/trees/sticky_position_constraint.cc
index 19f4cabe0fe..bc163937dae 100644
--- a/chromium/cc/trees/sticky_position_constraint.cc
+++ b/chromium/cc/trees/sticky_position_constraint.cc
@@ -19,6 +19,9 @@ StickyPositionConstraint::StickyPositionConstraint()
StickyPositionConstraint::StickyPositionConstraint(
const StickyPositionConstraint& other) = default;
+StickyPositionConstraint& StickyPositionConstraint::operator=(
+ const StickyPositionConstraint& other) = default;
+
bool StickyPositionConstraint::operator==(
const StickyPositionConstraint& other) const {
return is_anchored_left == other.is_anchored_left &&
diff --git a/chromium/cc/trees/sticky_position_constraint.h b/chromium/cc/trees/sticky_position_constraint.h
index 3a6ac2408dc..94b016753b8 100644
--- a/chromium/cc/trees/sticky_position_constraint.h
+++ b/chromium/cc/trees/sticky_position_constraint.h
@@ -17,6 +17,7 @@ namespace cc {
struct CC_EXPORT StickyPositionConstraint {
StickyPositionConstraint();
StickyPositionConstraint(const StickyPositionConstraint& other);
+ StickyPositionConstraint& operator=(const StickyPositionConstraint& other);
bool is_anchored_left : 1;
bool is_anchored_right : 1;
diff --git a/chromium/cc/trees/throttle_decider.cc b/chromium/cc/trees/throttle_decider.cc
index 3ce286bc80b..f2f31cfa327 100644
--- a/chromium/cc/trees/throttle_decider.cc
+++ b/chromium/cc/trees/throttle_decider.cc
@@ -6,6 +6,7 @@
#include <vector>
+#include "cc/layers/surface_layer_impl.h"
#include "components/viz/common/quads/compositor_render_pass_draw_quad.h"
#include "components/viz/common/quads/surface_draw_quad.h"
#include "components/viz/common/surfaces/surface_range.h"
@@ -86,6 +87,14 @@ void ThrottleDecider::ProcessRenderPass(
id_to_pass_map_.emplace(render_pass.id, &render_pass);
}
+void ThrottleDecider::ProcessLayerNotToDraw(const LayerImpl* layer) {
+ if (layer->is_surface_layer()) {
+ const auto* surface_layer = static_cast<const SurfaceLayerImpl*>(layer);
+ if (surface_layer->range().IsValid())
+ ids_.insert(surface_layer->range().end().frame_sink_id());
+ }
+}
+
bool ThrottleDecider::HasThrottlingChanged() const {
return ids_ != last_ids_;
}
diff --git a/chromium/cc/trees/throttle_decider.h b/chromium/cc/trees/throttle_decider.h
index d41479a423c..eb1c3418f26 100644
--- a/chromium/cc/trees/throttle_decider.h
+++ b/chromium/cc/trees/throttle_decider.h
@@ -12,6 +12,7 @@
#include "components/viz/common/surfaces/frame_sink_id.h"
namespace cc {
+class LayerImpl;
// This class is used to decide if any frame sinks in a render pass list
// satisfies the compositing-based criteria to be throttled.
@@ -30,6 +31,9 @@ class CC_EXPORT ThrottleDecider {
// intersection calculation of surface/quad rects are confined to the render
// pass's constituent quads.
void ProcessRenderPass(const viz::CompositorRenderPass& render_pass);
+ // Process a layer that will not draw. This is only relevant for surface
+ // layers and checks if the embedded frame sink is qualified for throttling.
+ void ProcessLayerNotToDraw(const LayerImpl* layer);
bool HasThrottlingChanged() const;
const base::flat_set<viz::FrameSinkId>& ids() const { return ids_; }
diff --git a/chromium/cc/trees/transform_node.cc b/chromium/cc/trees/transform_node.cc
index 1c91fcae2fc..765b6fbf836 100644
--- a/chromium/cc/trees/transform_node.cc
+++ b/chromium/cc/trees/transform_node.cc
@@ -39,6 +39,8 @@ TransformNode::TransformNode()
TransformNode::TransformNode(const TransformNode&) = default;
+TransformNode& TransformNode::operator=(const TransformNode&) = default;
+
#if DCHECK_IS_ON()
bool TransformNode::operator==(const TransformNode& other) const {
return id == other.id && parent_id == other.parent_id &&
diff --git a/chromium/cc/trees/transform_node.h b/chromium/cc/trees/transform_node.h
index 71d8e98f459..2e62467e4e5 100644
--- a/chromium/cc/trees/transform_node.h
+++ b/chromium/cc/trees/transform_node.h
@@ -23,6 +23,7 @@ namespace cc {
struct CC_EXPORT TransformNode {
TransformNode();
TransformNode(const TransformNode&);
+ TransformNode& operator=(const TransformNode&);
// The node index of this node in the transform tree node vector.
int id;
diff --git a/chromium/cc/trees/tree_synchronizer_unittest.cc b/chromium/cc/trees/tree_synchronizer_unittest.cc
index 7a1d5b0def0..6b89b13c49f 100644
--- a/chromium/cc/trees/tree_synchronizer_unittest.cc
+++ b/chromium/cc/trees/tree_synchronizer_unittest.cc
@@ -662,9 +662,9 @@ TEST_F(TreeSynchronizerTest, SynchronizeScrollTreeScrollOffsetMap) {
// Pull ScrollOffset delta for main thread, and change offset on main thread
std::unique_ptr<CompositorCommitData> commit_data(new CompositorCommitData());
- scroll_tree.CollectScrollDeltas(commit_data.get(), ElementId(),
- settings.commit_fractional_scroll_deltas,
- base::flat_set<ElementId>());
+ scroll_tree.CollectScrollDeltas(
+ commit_data.get(), ElementId(), settings.commit_fractional_scroll_deltas,
+ base::flat_map<ElementId, TargetSnapAreaElementIds>());
host_->proxy()->SetNeedsCommit();
host_->ApplyCompositorChanges(commit_data.get());
EXPECT_EQ(gfx::ScrollOffset(20, 30), scroll_layer->scroll_offset());
diff --git a/chromium/cc/trees/ukm_manager_unittest.cc b/chromium/cc/trees/ukm_manager_unittest.cc
index 4e36a6e2fd3..738de678558 100644
--- a/chromium/cc/trees/ukm_manager_unittest.cc
+++ b/chromium/cc/trees/ukm_manager_unittest.cc
@@ -142,13 +142,11 @@ class UkmManagerTest : public testing::Test {
std::unique_ptr<EventMetrics> CreateEventMetrics(
ui::EventType type,
- absl::optional<EventMetrics::ScrollUpdateType> scroll_update_type,
- absl::optional<ui::ScrollInputType> scroll_input_type) {
+ absl::optional<EventMetrics::ScrollParams> scroll_params) {
base::TimeTicks event_time = AdvanceNowByMs(10);
AdvanceNowByMs(10);
std::unique_ptr<EventMetrics> metrics = EventMetrics::CreateForTesting(
- type, scroll_update_type, scroll_input_type, event_time,
- &test_tick_clock_);
+ type, scroll_params, event_time, &test_tick_clock_);
if (metrics) {
AdvanceNowByMs(10);
metrics->SetDispatchStageTimestamp(
@@ -523,15 +521,24 @@ TEST_P(UkmManagerCompositorLatencyTest, CompositorLatency) {
}
TEST_F(UkmManagerTest, EventLatency) {
+ const bool kIsInertial = true;
+ const bool kIsNotInertial = false;
std::unique_ptr<EventMetrics> event_metrics_ptrs[] = {
- CreateEventMetrics(ui::ET_GESTURE_SCROLL_BEGIN, absl::nullopt,
- ui::ScrollInputType::kWheel),
+ CreateEventMetrics(ui::ET_GESTURE_SCROLL_BEGIN,
+ EventMetrics::ScrollParams(ui::ScrollInputType::kWheel,
+ kIsNotInertial)),
CreateEventMetrics(ui::ET_GESTURE_SCROLL_UPDATE,
- EventMetrics::ScrollUpdateType::kStarted,
- ui::ScrollInputType::kWheel),
+ EventMetrics::ScrollParams(
+ ui::ScrollInputType::kWheel, kIsNotInertial,
+ EventMetrics::ScrollUpdateType::kStarted)),
CreateEventMetrics(ui::ET_GESTURE_SCROLL_UPDATE,
- EventMetrics::ScrollUpdateType::kContinued,
- ui::ScrollInputType::kWheel),
+ EventMetrics::ScrollParams(
+ ui::ScrollInputType::kWheel, kIsNotInertial,
+ EventMetrics::ScrollUpdateType::kContinued)),
+ CreateEventMetrics(ui::ET_GESTURE_SCROLL_UPDATE,
+ EventMetrics::ScrollParams(
+ ui::ScrollInputType::kWheel, kIsInertial,
+ EventMetrics::ScrollUpdateType::kContinued)),
};
EXPECT_THAT(event_metrics_ptrs, ::testing::Each(::testing::NotNull()));
EventMetrics::List events_metrics(
@@ -609,7 +616,7 @@ TEST_F(UkmManagerTest, EventLatency) {
processed_viz_breakdown);
const auto& entries = test_ukm_recorder_->GetEntriesByName(kEventLatency);
- EXPECT_EQ(3u, entries.size());
+ EXPECT_EQ(4u, entries.size());
for (size_t i = 0; i < entries.size(); i++) {
const auto* entry = entries[i];
const auto* event_metrics = events_metrics[i].get();