summaryrefslogtreecommitdiffstats
path: root/chromium/cc/trees
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-01-31 16:33:43 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-02-06 16:33:22 +0000
commitda51f56cc21233c2d30f0fe0d171727c3102b2e0 (patch)
tree4e579ab70ce4b19bee7984237f3ce05a96d59d83 /chromium/cc/trees
parentc8c2d1901aec01e934adf561a9fdf0cc776cdef8 (diff)
BASELINE: Update Chromium to 65.0.3525.40
Also imports missing submodules Change-Id: I36901b7c6a325cda3d2c10cedb2186c25af3b79b Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/cc/trees')
-rw-r--r--chromium/cc/trees/clip_node.cc2
-rw-r--r--chromium/cc/trees/damage_tracker.cc2
-rw-r--r--chromium/cc/trees/debug_rect_history.cc26
-rw-r--r--chromium/cc/trees/image_animation_controller_unittest.cc9
-rw-r--r--chromium/cc/trees/latency_info_swap_promise.cc6
-rw-r--r--chromium/cc/trees/latency_info_swap_promise.h3
-rw-r--r--chromium/cc/trees/latency_info_swap_promise_monitor.cc3
-rw-r--r--chromium/cc/trees/layer_tree_frame_sink.cc97
-rw-r--r--chromium/cc/trees/layer_tree_frame_sink.h31
-rw-r--r--chromium/cc/trees/layer_tree_frame_sink_client.h3
-rw-r--r--chromium/cc/trees/layer_tree_frame_sink_unittest.cc62
-rw-r--r--chromium/cc/trees/layer_tree_host.cc53
-rw-r--r--chromium/cc/trees/layer_tree_host.h25
-rw-r--r--chromium/cc/trees/layer_tree_host_client.h6
-rw-r--r--chromium/cc/trees/layer_tree_host_common.cc2
-rw-r--r--chromium/cc/trees/layer_tree_host_common_unittest.cc9
-rw-r--r--chromium/cc/trees/layer_tree_host_impl.cc227
-rw-r--r--chromium/cc/trees/layer_tree_host_impl.h36
-rw-r--r--chromium/cc/trees/layer_tree_host_impl_unittest.cc454
-rw-r--r--chromium/cc/trees/layer_tree_host_perftest.cc8
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_blending.cc3
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_masks.cc13
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_readback.cc3
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc8
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest.cc217
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_animation.cc13
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_checkerimaging.cc32
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_context.cc46
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc7
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_proxy.cc21
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_scroll.cc38
-rw-r--r--chromium/cc/trees/layer_tree_impl.cc57
-rw-r--r--chromium/cc/trees/layer_tree_impl.h16
-rw-r--r--chromium/cc/trees/layer_tree_impl_unittest.cc11
-rw-r--r--chromium/cc/trees/layer_tree_settings.h7
-rw-r--r--chromium/cc/trees/occlusion.cc3
-rw-r--r--chromium/cc/trees/occlusion_tracker.cc3
-rw-r--r--chromium/cc/trees/property_animation_state.cc8
-rw-r--r--chromium/cc/trees/property_tree.cc37
-rw-r--r--chromium/cc/trees/property_tree_builder.cc60
-rw-r--r--chromium/cc/trees/proxy.h2
-rw-r--r--chromium/cc/trees/proxy_common.cc4
-rw-r--r--chromium/cc/trees/proxy_impl.cc35
-rw-r--r--chromium/cc/trees/proxy_impl.h6
-rw-r--r--chromium/cc/trees/proxy_main.cc87
-rw-r--r--chromium/cc/trees/proxy_main.h8
-rw-r--r--chromium/cc/trees/render_frame_metadata.cc24
-rw-r--r--chromium/cc/trees/render_frame_metadata.h30
-rw-r--r--chromium/cc/trees/scroll_node.cc5
-rw-r--r--chromium/cc/trees/scroll_node.h4
-rw-r--r--chromium/cc/trees/single_thread_proxy.cc42
-rw-r--r--chromium/cc/trees/single_thread_proxy.h6
-rw-r--r--chromium/cc/trees/swap_promise.h4
-rw-r--r--chromium/cc/trees/swap_promise_manager.cc2
-rw-r--r--chromium/cc/trees/swap_promise_manager_unittest.cc9
-rw-r--r--chromium/cc/trees/transform_node.cc2
-rw-r--r--chromium/cc/trees/tree_synchronizer.cc12
-rw-r--r--chromium/cc/trees/tree_synchronizer_unittest.cc2
-rw-r--r--chromium/cc/trees/ukm_manager.cc27
-rw-r--r--chromium/cc/trees/ukm_manager.h8
-rw-r--r--chromium/cc/trees/ukm_manager_unittest.cc15
61 files changed, 1594 insertions, 407 deletions
diff --git a/chromium/cc/trees/clip_node.cc b/chromium/cc/trees/clip_node.cc
index a949dcb9728..3c9c58fcece 100644
--- a/chromium/cc/trees/clip_node.cc
+++ b/chromium/cc/trees/clip_node.cc
@@ -22,7 +22,7 @@ ClipNode::ClipNode(const ClipNode& other) = default;
ClipNode& ClipNode::operator=(const ClipNode& other) = default;
-ClipNode::~ClipNode() {}
+ClipNode::~ClipNode() = default;
bool ClipNode::operator==(const ClipNode& other) const {
return id == other.id && parent_id == other.parent_id &&
diff --git a/chromium/cc/trees/damage_tracker.cc b/chromium/cc/trees/damage_tracker.cc
index 7c127ebb75a..56f03bfa2d6 100644
--- a/chromium/cc/trees/damage_tracker.cc
+++ b/chromium/cc/trees/damage_tracker.cc
@@ -27,7 +27,7 @@ std::unique_ptr<DamageTracker> DamageTracker::Create() {
DamageTracker::DamageTracker() : mailboxId_(0) {}
-DamageTracker::~DamageTracker() {}
+DamageTracker::~DamageTracker() = default;
void DamageTracker::UpdateDamageTracking(
LayerTreeImpl* layer_tree_impl,
diff --git a/chromium/cc/trees/debug_rect_history.cc b/chromium/cc/trees/debug_rect_history.cc
index aa99eb55db3..1fb0255a0cc 100644
--- a/chromium/cc/trees/debug_rect_history.cc
+++ b/chromium/cc/trees/debug_rect_history.cc
@@ -24,9 +24,9 @@ std::unique_ptr<DebugRectHistory> DebugRectHistory::Create() {
return base::WrapUnique(new DebugRectHistory());
}
-DebugRectHistory::DebugRectHistory() {}
+DebugRectHistory::DebugRectHistory() = default;
-DebugRectHistory::~DebugRectHistory() {}
+DebugRectHistory::~DebugRectHistory() = default;
void DebugRectHistory::SaveDebugRectsForCurrentFrame(
LayerTreeImpl* tree_impl,
@@ -72,10 +72,10 @@ void DebugRectHistory::SavePaintRects(LayerTreeImpl* tree_impl) {
if (invalidation_region.IsEmpty() || !layer->DrawsContent())
continue;
- for (Region::Iterator it(invalidation_region); it.has_rect(); it.next()) {
- debug_rects_.push_back(DebugRect(
- PAINT_RECT_TYPE, MathUtil::MapEnclosingClippedRect(
- layer->ScreenSpaceTransform(), it.rect())));
+ for (gfx::Rect rect : invalidation_region) {
+ debug_rects_.push_back(
+ DebugRect(PAINT_RECT_TYPE, MathUtil::MapEnclosingClippedRect(
+ layer->ScreenSpaceTransform(), rect)));
}
}
}
@@ -136,10 +136,10 @@ void DebugRectHistory::SaveTouchEventHandlerRectsCallback(LayerImpl* layer) {
touch_action_index != kTouchActionMax; ++touch_action_index) {
auto touch_action = static_cast<TouchAction>(touch_action_index);
Region region = touch_action_region.GetRegionForTouchAction(touch_action);
- for (Region::Iterator iter(region); iter.has_rect(); iter.next()) {
+ for (gfx::Rect rect : region) {
debug_rects_.emplace_back(TOUCH_EVENT_HANDLER_RECT_TYPE,
MathUtil::MapEnclosingClippedRect(
- layer->ScreenSpaceTransform(), iter.rect()),
+ layer->ScreenSpaceTransform(), rect),
touch_action);
}
}
@@ -187,12 +187,10 @@ void DebugRectHistory::SaveNonFastScrollableRects(LayerTreeImpl* tree_impl) {
}
void DebugRectHistory::SaveNonFastScrollableRectsCallback(LayerImpl* layer) {
- for (Region::Iterator iter(layer->non_fast_scrollable_region());
- iter.has_rect(); iter.next()) {
- debug_rects_.push_back(
- DebugRect(NON_FAST_SCROLLABLE_RECT_TYPE,
- MathUtil::MapEnclosingClippedRect(
- layer->ScreenSpaceTransform(), iter.rect())));
+ for (gfx::Rect rect : layer->non_fast_scrollable_region()) {
+ debug_rects_.push_back(DebugRect(NON_FAST_SCROLLABLE_RECT_TYPE,
+ MathUtil::MapEnclosingClippedRect(
+ layer->ScreenSpaceTransform(), rect)));
}
}
diff --git a/chromium/cc/trees/image_animation_controller_unittest.cc b/chromium/cc/trees/image_animation_controller_unittest.cc
index c4db878ba19..1a4c486dc14 100644
--- a/chromium/cc/trees/image_animation_controller_unittest.cc
+++ b/chromium/cc/trees/image_animation_controller_unittest.cc
@@ -4,7 +4,8 @@
#include "cc/trees/image_animation_controller.h"
-#include "base/memory/ptr_util.h"
+#include <memory>
+
#include "base/run_loop.h"
#include "base/test/gtest_util.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -14,8 +15,8 @@ namespace cc {
class FakeAnimationDriver : public ImageAnimationController::AnimationDriver {
public:
- FakeAnimationDriver() {}
- ~FakeAnimationDriver() override {}
+ FakeAnimationDriver() = default;
+ ~FakeAnimationDriver() override = default;
void set_should_animate(bool should_animate) {
should_animate_ = should_animate;
@@ -76,7 +77,7 @@ class ImageAnimationControllerTest : public testing::Test {
base::Closure invalidation_callback =
base::Bind(&ImageAnimationControllerTest::RequestInvalidation,
base::Unretained(this));
- controller_ = base::MakeUnique<ImageAnimationController>(
+ controller_ = std::make_unique<ImageAnimationController>(
task_runner_.get(), invalidation_callback);
now_ += base::TimeDelta::FromSeconds(10);
}
diff --git a/chromium/cc/trees/latency_info_swap_promise.cc b/chromium/cc/trees/latency_info_swap_promise.cc
index 3dcaf1ecf4b..2caa84022b6 100644
--- a/chromium/cc/trees/latency_info_swap_promise.cc
+++ b/chromium/cc/trees/latency_info_swap_promise.cc
@@ -33,9 +33,11 @@ LatencyInfoSwapPromise::LatencyInfoSwapPromise(const ui::LatencyInfo& latency)
LatencyInfoSwapPromise::~LatencyInfoSwapPromise() = default;
-void LatencyInfoSwapPromise::WillSwap(viz::CompositorFrameMetadata* metadata) {
+void LatencyInfoSwapPromise::WillSwap(
+ viz::CompositorFrameMetadata* compositor_frame_metadata,
+ RenderFrameMetadata* render_frame_metadata) {
DCHECK(!latency_.terminated());
- metadata->latency_info.push_back(latency_);
+ compositor_frame_metadata->latency_info.push_back(latency_);
}
void LatencyInfoSwapPromise::DidSwap() {}
diff --git a/chromium/cc/trees/latency_info_swap_promise.h b/chromium/cc/trees/latency_info_swap_promise.h
index 2b23d67dc80..62a80777b08 100644
--- a/chromium/cc/trees/latency_info_swap_promise.h
+++ b/chromium/cc/trees/latency_info_swap_promise.h
@@ -19,7 +19,8 @@ class CC_EXPORT LatencyInfoSwapPromise : public SwapPromise {
~LatencyInfoSwapPromise() override;
void DidActivate() override {}
- void WillSwap(viz::CompositorFrameMetadata* metadata) override;
+ void WillSwap(viz::CompositorFrameMetadata* compositor_frame_metadata,
+ RenderFrameMetadata* render_frame_metadata) override;
void DidSwap() override;
DidNotSwapAction DidNotSwap(DidNotSwapReason reason) override;
void OnCommit() override;
diff --git a/chromium/cc/trees/latency_info_swap_promise_monitor.cc b/chromium/cc/trees/latency_info_swap_promise_monitor.cc
index dc25793046a..7bca0d6ebf0 100644
--- a/chromium/cc/trees/latency_info_swap_promise_monitor.cc
+++ b/chromium/cc/trees/latency_info_swap_promise_monitor.cc
@@ -46,8 +46,7 @@ LatencyInfoSwapPromiseMonitor::LatencyInfoSwapPromiseMonitor(
LayerTreeHostImpl* host_impl)
: SwapPromiseMonitor(swap_promise_manager, host_impl), latency_(latency) {}
-LatencyInfoSwapPromiseMonitor::~LatencyInfoSwapPromiseMonitor() {
-}
+LatencyInfoSwapPromiseMonitor::~LatencyInfoSwapPromiseMonitor() = default;
void LatencyInfoSwapPromiseMonitor::OnSetNeedsCommitOnMain() {
if (AddRenderingScheduledComponent(latency_, true /* on_main */)) {
diff --git a/chromium/cc/trees/layer_tree_frame_sink.cc b/chromium/cc/trees/layer_tree_frame_sink.cc
index 25a1e3b370a..5c0511403e2 100644
--- a/chromium/cc/trees/layer_tree_frame_sink.cc
+++ b/chromium/cc/trees/layer_tree_frame_sink.cc
@@ -12,27 +12,56 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "cc/trees/layer_tree_frame_sink_client.h"
+#include "components/viz/common/gpu/context_lost_observer.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/context_support.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/client/raster_interface.h"
namespace cc {
+class LayerTreeFrameSink::ContextLostForwarder
+ : public viz::ContextLostObserver {
+ public:
+ ContextLostForwarder(base::WeakPtr<LayerTreeFrameSink> frame_sink,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : frame_sink_(frame_sink), task_runner_(std::move(task_runner)) {}
+ ~ContextLostForwarder() override = default;
+
+ void OnContextLost() override {
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&LayerTreeFrameSink::OnContextLost, frame_sink_));
+ }
+
+ private:
+ base::WeakPtr<LayerTreeFrameSink> frame_sink_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ DISALLOW_COPY_AND_ASSIGN(ContextLostForwarder);
+};
+
LayerTreeFrameSink::LayerTreeFrameSink(
scoped_refptr<viz::ContextProvider> context_provider,
- scoped_refptr<viz::ContextProvider> worker_context_provider,
+ scoped_refptr<viz::RasterContextProvider> worker_context_provider,
+ scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
viz::SharedBitmapManager* shared_bitmap_manager)
: context_provider_(std::move(context_provider)),
worker_context_provider_(std::move(worker_context_provider)),
+ compositor_task_runner_(std::move(compositor_task_runner)),
gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
- shared_bitmap_manager_(shared_bitmap_manager) {}
+ shared_bitmap_manager_(shared_bitmap_manager),
+ weak_ptr_factory_(this) {
+ DETACH_FROM_THREAD(thread_checker_);
+}
LayerTreeFrameSink::LayerTreeFrameSink(
scoped_refptr<viz::VulkanContextProvider> vulkan_context_provider)
: vulkan_context_provider_(vulkan_context_provider),
gpu_memory_buffer_manager_(nullptr),
- shared_bitmap_manager_(nullptr) {}
+ shared_bitmap_manager_(nullptr),
+ weak_ptr_factory_(this) {
+ DETACH_FROM_THREAD(thread_checker_);
+}
LayerTreeFrameSink::~LayerTreeFrameSink() {
if (client_)
@@ -42,38 +71,68 @@ LayerTreeFrameSink::~LayerTreeFrameSink() {
bool LayerTreeFrameSink::BindToClient(LayerTreeFrameSinkClient* client) {
DCHECK(client);
DCHECK(!client_);
- client_ = client;
- bool success = true;
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (context_provider_.get()) {
+ if (context_provider_) {
+ context_provider_->AddObserver(this);
auto result = context_provider_->BindToCurrentThread();
- success = result == gpu::ContextResult::kSuccess;
- if (success) {
- context_provider_->AddObserver(this);
+ if (result != gpu::ContextResult::kSuccess) {
+ context_provider_->RemoveObserver(this);
+ context_provider_ = nullptr;
+ return false;
}
}
- if (!success) {
- // Destroy the viz::ContextProvider on the thread attempted to be bound.
- context_provider_ = nullptr;
- client_ = nullptr;
+ if (worker_context_provider_) {
+ DCHECK(context_provider_);
+ DCHECK(compositor_task_runner_);
+ DCHECK(compositor_task_runner_->BelongsToCurrentThread());
+ viz::RasterContextProvider::ScopedRasterContextLock lock(
+ worker_context_provider_.get());
+ if (lock.RasterInterface()->GetGraphicsResetStatusKHR() != GL_NO_ERROR) {
+ context_provider_->RemoveObserver(this);
+ context_provider_ = nullptr;
+ return false;
+ }
+ // Worker context lost callback is called on the main thread so it has to be
+ // forwarded to compositor thread.
+ worker_context_lost_forwarder_ = std::make_unique<ContextLostForwarder>(
+ weak_ptr_factory_.GetWeakPtr(), compositor_task_runner_);
+ worker_context_provider_->AddObserver(worker_context_lost_forwarder_.get());
}
- return success;
+ client_ = client;
+
+ return true;
}
void LayerTreeFrameSink::DetachFromClient() {
DCHECK(client_);
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ client_ = nullptr;
+ weak_ptr_factory_.InvalidateWeakPtrs();
- if (context_provider_.get())
+ // Do not release worker context provider here as this is called on the
+ // compositor thread and it must be released on the main thread. However,
+ // compositor context provider must be released here.
+ if (context_provider_) {
context_provider_->RemoveObserver(this);
+ context_provider_ = nullptr;
+ }
- // Destroy the viz::ContextProvider on the bound thread.
- context_provider_ = nullptr;
- client_ = nullptr;
+ if (worker_context_provider_) {
+ viz::RasterContextProvider::ScopedRasterContextLock lock(
+ worker_context_provider_.get());
+ worker_context_provider_->RemoveObserver(
+ worker_context_lost_forwarder_.get());
+ worker_context_lost_forwarder_ = nullptr;
+ }
}
void LayerTreeFrameSink::OnContextLost() {
+ DCHECK(client_);
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
TRACE_EVENT0("cc", "LayerTreeFrameSink::OnContextLost");
client_->DidLoseLayerTreeFrameSink();
}
diff --git a/chromium/cc/trees/layer_tree_frame_sink.h b/chromium/cc/trees/layer_tree_frame_sink.h
index a08c1fc97c9..ac9fe419d8e 100644
--- a/chromium/cc/trees/layer_tree_frame_sink.h
+++ b/chromium/cc/trees/layer_tree_frame_sink.h
@@ -10,10 +10,12 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
#include "cc/cc_export.h"
#include "components/viz/common/gpu/context_lost_observer.h"
#include "components/viz/common/gpu/context_provider.h"
+#include "components/viz/common/gpu/raster_context_provider.h"
#include "components/viz/common/gpu/vulkan_context_provider.h"
#include "components/viz/common/resources/returned_resource.h"
#include "gpu/command_buffer/common/texture_in_use_response.h"
@@ -57,15 +59,19 @@ class CC_EXPORT LayerTreeFrameSink : public viz::ContextLostObserver {
};
// Constructor for GL-based and/or software resources.
- // gpu_memory_buffer_manager and shared_bitmap_manager must outlive the
- // LayerTreeFrameSink.
- // shared_bitmap_manager is optional (won't be used) if context_provider is
- // present.
- // gpu_memory_buffer_manager is optional (won't be used) if context_provider
- // is not present.
+ //
+ // |compositor_task_runner| is used to post worker context lost callback and
+ // must belong to the same thread where all calls to or from client are made.
+ // Optional and won't be used unless |worker_context_provider| is present.
+ //
+ // |gpu_memory_buffer_manager| and |shared_bitmap_manager| must outlive the
+ // LayerTreeFrameSink. |shared_bitmap_manager| is optional (won't be used) if
+ // |context_provider| is present. |gpu_memory_buffer_manager| is optional
+ // (won't be used) unless |context_provider| is present.
LayerTreeFrameSink(
scoped_refptr<viz::ContextProvider> context_provider,
- scoped_refptr<viz::ContextProvider> worker_context_provider,
+ scoped_refptr<viz::RasterContextProvider> worker_context_provider,
+ scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
viz::SharedBitmapManager* shared_bitmap_manager);
@@ -99,7 +105,7 @@ class CC_EXPORT LayerTreeFrameSink : public viz::ContextLostObserver {
viz::ContextProvider* context_provider() const {
return context_provider_.get();
}
- viz::ContextProvider* worker_context_provider() const {
+ viz::RasterContextProvider* worker_context_provider() const {
return worker_context_provider_.get();
}
viz::VulkanContextProvider* vulkan_context_provider() const {
@@ -131,6 +137,8 @@ class CC_EXPORT LayerTreeFrameSink : public viz::ContextLostObserver {
virtual void DidNotProduceFrame(const viz::BeginFrameAck& ack) = 0;
protected:
+ class ContextLostForwarder;
+
// viz::ContextLostObserver:
void OnContextLost() override;
@@ -138,12 +146,17 @@ class CC_EXPORT LayerTreeFrameSink : public viz::ContextLostObserver {
struct LayerTreeFrameSink::Capabilities capabilities_;
scoped_refptr<viz::ContextProvider> context_provider_;
- scoped_refptr<viz::ContextProvider> worker_context_provider_;
+ scoped_refptr<viz::RasterContextProvider> worker_context_provider_;
scoped_refptr<viz::VulkanContextProvider> vulkan_context_provider_;
+ scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_;
viz::SharedBitmapManager* shared_bitmap_manager_;
+ std::unique_ptr<ContextLostForwarder> worker_context_lost_forwarder_;
+
private:
+ THREAD_CHECKER(thread_checker_);
+ base::WeakPtrFactory<LayerTreeFrameSink> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(LayerTreeFrameSink);
};
diff --git a/chromium/cc/trees/layer_tree_frame_sink_client.h b/chromium/cc/trees/layer_tree_frame_sink_client.h
index 154d5365497..a463b770007 100644
--- a/chromium/cc/trees/layer_tree_frame_sink_client.h
+++ b/chromium/cc/trees/layer_tree_frame_sink_client.h
@@ -9,7 +9,6 @@
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
#include "cc/cc_export.h"
-#include "components/viz/common/gpu/context_provider.h"
#include "components/viz/common/resources/returned_resource.h"
#include "gpu/command_buffer/common/texture_in_use_response.h"
#include "ui/gfx/geometry/rect.h"
@@ -49,6 +48,8 @@ class CC_EXPORT LayerTreeFrameSinkClient {
// so that frames are submitted only at the rate it can handle them.
virtual void DidReceiveCompositorFrameAck() = 0;
+ // See ui/gfx/presentation_feedback.h for details on args. |time| is always
+ // non-zero.
virtual void DidPresentCompositorFrame(uint32_t presentation_token,
base::TimeTicks time,
base::TimeDelta refresh,
diff --git a/chromium/cc/trees/layer_tree_frame_sink_unittest.cc b/chromium/cc/trees/layer_tree_frame_sink_unittest.cc
index 9895cfad81f..cf41eb3f2ef 100644
--- a/chromium/cc/trees/layer_tree_frame_sink_unittest.cc
+++ b/chromium/cc/trees/layer_tree_frame_sink_unittest.cc
@@ -5,11 +5,13 @@
#include "cc/trees/layer_tree_frame_sink.h"
#include "base/memory/ptr_util.h"
+#include "base/test/test_simple_task_runner.h"
#include "cc/test/fake_layer_tree_frame_sink_client.h"
#include "cc/test/test_context_provider.h"
#include "cc/test/test_web_graphics_context_3d.h"
#include "components/viz/common/quads/compositor_frame.h"
#include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/raster_interface.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cc {
@@ -18,10 +20,12 @@ namespace {
class TestLayerTreeFrameSink : public LayerTreeFrameSink {
public:
explicit TestLayerTreeFrameSink(
- scoped_refptr<TestContextProvider> context_provider,
- scoped_refptr<TestContextProvider> worker_context_provider)
+ scoped_refptr<viz::ContextProvider> context_provider,
+ scoped_refptr<viz::RasterContextProvider> worker_context_provider,
+ scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner)
: LayerTreeFrameSink(std::move(context_provider),
std::move(worker_context_provider),
+ std::move(compositor_task_runner),
nullptr,
nullptr) {}
@@ -35,7 +39,9 @@ TEST(LayerTreeFrameSinkTest, ContextLossInformsClient) {
scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
scoped_refptr<TestContextProvider> worker_provider =
TestContextProvider::CreateWorker();
- TestLayerTreeFrameSink layer_tree_frame_sink(provider, worker_provider);
+ auto task_runner = base::MakeRefCounted<base::TestSimpleTaskRunner>();
+ TestLayerTreeFrameSink layer_tree_frame_sink(provider, worker_provider,
+ task_runner);
EXPECT_FALSE(layer_tree_frame_sink.HasClient());
FakeLayerTreeFrameSinkClient client;
@@ -50,8 +56,6 @@ TEST(LayerTreeFrameSinkTest, ContextLossInformsClient) {
EXPECT_TRUE(client.did_lose_layer_tree_frame_sink_called());
}
-// TODO(danakj): Add a test for worker context failure as well when
-// LayerTreeFrameSink creates/binds it.
TEST(LayerTreeFrameSinkTest, ContextLossFailsBind) {
scoped_refptr<TestContextProvider> context_provider =
TestContextProvider::Create();
@@ -61,8 +65,54 @@ TEST(LayerTreeFrameSinkTest, ContextLossFailsBind) {
// Lose the context so BindToClient fails.
context_provider->UnboundTestContext3d()->set_context_lost(true);
+ auto task_runner = base::MakeRefCounted<base::TestSimpleTaskRunner>();
TestLayerTreeFrameSink layer_tree_frame_sink(context_provider,
- worker_provider);
+ worker_provider, task_runner);
+ EXPECT_FALSE(layer_tree_frame_sink.HasClient());
+
+ FakeLayerTreeFrameSinkClient client;
+ EXPECT_FALSE(layer_tree_frame_sink.BindToClient(&client));
+ EXPECT_FALSE(layer_tree_frame_sink.HasClient());
+}
+
+TEST(LayerTreeFrameSinkTest, WorkerContextLossInformsClient) {
+ scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
+ scoped_refptr<TestContextProvider> worker_provider =
+ TestContextProvider::CreateWorker();
+ auto task_runner = base::MakeRefCounted<base::TestSimpleTaskRunner>();
+ TestLayerTreeFrameSink layer_tree_frame_sink(provider, worker_provider,
+ task_runner);
+ EXPECT_FALSE(layer_tree_frame_sink.HasClient());
+
+ FakeLayerTreeFrameSinkClient client;
+ EXPECT_TRUE(layer_tree_frame_sink.BindToClient(&client));
+ EXPECT_TRUE(layer_tree_frame_sink.HasClient());
+
+ // Verify DidLoseLayerTreeFrameSink callback is hooked up correctly.
+ EXPECT_FALSE(client.did_lose_layer_tree_frame_sink_called());
+ {
+ viz::RasterContextProvider::ScopedRasterContextLock context_lock(
+ layer_tree_frame_sink.worker_context_provider());
+ context_lock.RasterInterface()->LoseContextCHROMIUM(
+ GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB);
+ context_lock.RasterInterface()->Flush();
+ }
+ task_runner->RunPendingTasks();
+ EXPECT_TRUE(client.did_lose_layer_tree_frame_sink_called());
+}
+
+TEST(LayerTreeFrameSinkTest, WorkerContextLossFailsBind) {
+ scoped_refptr<TestContextProvider> context_provider =
+ TestContextProvider::Create();
+ scoped_refptr<TestContextProvider> worker_provider =
+ TestContextProvider::CreateWorker();
+
+ // Lose the context so BindToClient fails.
+ worker_provider->UnboundTestContext3d()->set_context_lost(true);
+
+ auto task_runner = base::MakeRefCounted<base::TestSimpleTaskRunner>();
+ TestLayerTreeFrameSink layer_tree_frame_sink(context_provider,
+ worker_provider, task_runner);
EXPECT_FALSE(layer_tree_frame_sink.HasClient());
FakeLayerTreeFrameSinkClient client;
diff --git a/chromium/cc/trees/layer_tree_host.cc b/chromium/cc/trees/layer_tree_host.cc
index 4ee829d10cf..85872e6203d 100644
--- a/chromium/cc/trees/layer_tree_host.cc
+++ b/chromium/cc/trees/layer_tree_host.cc
@@ -67,9 +67,9 @@ static base::AtomicSequenceNumber s_image_decode_sequence_number;
namespace cc {
-LayerTreeHost::InitParams::InitParams() {}
+LayerTreeHost::InitParams::InitParams() = default;
-LayerTreeHost::InitParams::~InitParams() {}
+LayerTreeHost::InitParams::~InitParams() = default;
std::unique_ptr<LayerTreeHost> LayerTreeHost::CreateThreaded(
scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner,
@@ -77,7 +77,6 @@ std::unique_ptr<LayerTreeHost> LayerTreeHost::CreateThreaded(
DCHECK(params->main_task_runner.get());
DCHECK(impl_task_runner.get());
DCHECK(params->settings);
- DCHECK(params->ukm_recorder_factory);
std::unique_ptr<LayerTreeHost> layer_tree_host(
new LayerTreeHost(params, CompositorMode::THREADED));
layer_tree_host->InitializeThreaded(params->main_task_runner,
@@ -280,8 +279,8 @@ const LayerTreeDebugState& LayerTreeHost::GetDebugState() const {
return debug_state_;
}
-void LayerTreeHost::RequestMainFrameUpdate() {
- client_->UpdateLayerTreeHost();
+void LayerTreeHost::RequestMainFrameUpdate(VisualStateUpdate requested_update) {
+ client_->UpdateLayerTreeHost(requested_update);
}
// This function commits the LayerTreeHost to an impl tree. When modifying
@@ -320,14 +319,31 @@ void LayerTreeHost::FinishCommitOnImplThread(
sync_tree->set_source_frame_number(SourceFrameNumber());
+ // Set presentation token if any pending .
+ bool request_presentation_time = false;
+ if (!pending_presentation_time_callbacks_.empty()) {
+ request_presentation_time = true;
+ frame_to_presentation_time_callbacks_[SourceFrameNumber()] =
+ std::move(pending_presentation_time_callbacks_);
+ pending_presentation_time_callbacks_.clear();
+ } else if (!frame_to_presentation_time_callbacks_.empty()) {
+ // There are pending callbacks. Keep requesting the presentation callback
+ // in case a previous frame was dropped (the callbacks run when the frame
+ // makes it to screen).
+ request_presentation_time = true;
+ }
+ sync_tree->set_request_presentation_time(request_presentation_time);
+
if (needs_full_tree_sync_)
TreeSynchronizer::SynchronizeTrees(root_layer(), sync_tree);
// Track the navigation state before pushing properties since it overwrites
// the |content_source_id_| on the sync tree.
bool did_navigate = content_source_id_ != sync_tree->content_source_id();
- if (did_navigate)
+ if (did_navigate) {
+ proxy_->ClearHistoryOnNavigation();
host_impl->ClearImageCacheOnNavigation();
+ }
{
TRACE_EVENT0("cc", "LayerTreeHostInProcess::PushProperties");
@@ -670,6 +686,22 @@ bool LayerTreeHost::UpdateLayers() {
return result;
}
+void LayerTreeHost::DidPresentCompositorFrame(
+ const std::vector<int>& source_frames,
+ base::TimeTicks time,
+ base::TimeDelta refresh,
+ uint32_t flags) {
+ for (int frame : source_frames) {
+ if (!frame_to_presentation_time_callbacks_.count(frame))
+ continue;
+
+ for (auto& callback : frame_to_presentation_time_callbacks_[frame])
+ std::move(callback).Run(time, refresh, flags);
+
+ frame_to_presentation_time_callbacks_.erase(frame);
+ }
+}
+
void LayerTreeHost::DidCompletePageScaleAnimation() {
did_complete_scale_animation_ = true;
}
@@ -932,6 +964,11 @@ bool LayerTreeHost::IsThreaded() const {
return compositor_mode_ == CompositorMode::THREADED;
}
+void LayerTreeHost::RequestPresentationTimeForNextFrame(
+ PresentationTimeCallback callback) {
+ pending_presentation_time_callbacks_.push_back(std::move(callback));
+}
+
void LayerTreeHost::SetRootLayer(scoped_refptr<Layer> root_layer) {
if (root_layer_.get() == root_layer.get())
return;
@@ -954,9 +991,9 @@ void LayerTreeHost::SetRootLayer(scoped_refptr<Layer> root_layer) {
SetNeedsFullTreeSync();
}
-LayerTreeHost::ViewportLayers::ViewportLayers() {}
+LayerTreeHost::ViewportLayers::ViewportLayers() = default;
-LayerTreeHost::ViewportLayers::~ViewportLayers() {}
+LayerTreeHost::ViewportLayers::~ViewportLayers() = default;
void LayerTreeHost::RegisterViewportLayers(const ViewportLayers& layers) {
DCHECK(!layers.inner_viewport_scroll ||
diff --git a/chromium/cc/trees/layer_tree_host.h b/chromium/cc/trees/layer_tree_host.h
index 138ec2b753f..600ac2b5dc9 100644
--- a/chromium/cc/trees/layer_tree_host.h
+++ b/chromium/cc/trees/layer_tree_host.h
@@ -15,6 +15,7 @@
#include <unordered_map>
#include <vector>
+#include "base/callback_forward.h"
#include "base/cancelable_callback.h"
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
@@ -243,6 +244,13 @@ class CC_EXPORT LayerTreeHost : public viz::SurfaceReferenceOwner,
// Calling this will reset it back to not suitable state.
void ResetGpuRasterizationTracking();
+ // 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(base::TimeTicks, base::TimeDelta, uint32_t)>;
+ void RequestPresentationTimeForNextFrame(PresentationTimeCallback callback);
+
void SetRootLayer(scoped_refptr<Layer> root_layer);
Layer* root_layer() { return root_layer_.get(); }
const Layer* root_layer() const { return root_layer_.get(); }
@@ -420,7 +428,9 @@ class CC_EXPORT LayerTreeHost : public viz::SurfaceReferenceOwner,
void BeginMainFrameNotExpectedSoon();
void BeginMainFrameNotExpectedUntil(base::TimeTicks time);
void AnimateLayers(base::TimeTicks monotonic_frame_begin_time);
- void RequestMainFrameUpdate();
+ using VisualStateUpdate = LayerTreeHostClient::VisualStateUpdate;
+ void RequestMainFrameUpdate(
+ VisualStateUpdate requested_update = VisualStateUpdate::kAll);
void FinishCommitOnImplThread(LayerTreeHostImpl* host_impl);
void WillCommit();
void CommitComplete();
@@ -435,6 +445,10 @@ class CC_EXPORT LayerTreeHost : public viz::SurfaceReferenceOwner,
client_->DidReceiveCompositorFrameAck();
}
bool UpdateLayers();
+ void DidPresentCompositorFrame(const std::vector<int>& source_frames,
+ base::TimeTicks time,
+ base::TimeDelta refresh,
+ uint32_t flags);
// Called when the compositor completed page scale animation.
void DidCompletePageScaleAnimation();
void ApplyScrollAndScale(ScrollAndScaleSet* info);
@@ -675,6 +689,15 @@ class CC_EXPORT LayerTreeHost : public viz::SurfaceReferenceOwner,
std::unordered_map<int, base::OnceCallback<void(bool)>>
pending_image_decodes_;
+ // Presentation time callbacks requested for the next frame are initially
+ // added here.
+ std::vector<PresentationTimeCallback> pending_presentation_time_callbacks_;
+
+ // Maps from the source frame presentation callbacks are requested for to
+ // the callbacks.
+ std::map<int, std::vector<PresentationTimeCallback>>
+ frame_to_presentation_time_callbacks_;
+
DISALLOW_COPY_AND_ASSIGN(LayerTreeHost);
};
diff --git a/chromium/cc/trees/layer_tree_host_client.h b/chromium/cc/trees/layer_tree_host_client.h
index 3c55d39e95e..9cfdfcd7ff2 100644
--- a/chromium/cc/trees/layer_tree_host_client.h
+++ b/chromium/cc/trees/layer_tree_host_client.h
@@ -62,7 +62,11 @@ class LayerTreeHostClient {
// state. (The "compositing state" will result in a mutated layer tree on the
// LayerTreeHost via additional interface indirections which lead back to
// mutations on the LayerTreeHost.)
- virtual void UpdateLayerTreeHost() = 0;
+ //
+ // If |requested_update| is kPrePaint, the client should apply layout and
+ // animation updates and their side effects, but can skip painting stages.
+ enum class VisualStateUpdate { kPrePaint, kAll };
+ virtual void UpdateLayerTreeHost(VisualStateUpdate requested_update) = 0;
virtual void ApplyViewportDeltas(
const gfx::Vector2dF& inner_delta,
diff --git a/chromium/cc/trees/layer_tree_host_common.cc b/chromium/cc/trees/layer_tree_host_common.cc
index 867895e56f9..215b52f341d 100644
--- a/chromium/cc/trees/layer_tree_host_common.cc
+++ b/chromium/cc/trees/layer_tree_host_common.cc
@@ -176,7 +176,7 @@ ScrollAndScaleSet::ScrollAndScaleSet()
has_scrolled_by_wheel(false),
has_scrolled_by_touch(false) {}
-ScrollAndScaleSet::~ScrollAndScaleSet() {}
+ScrollAndScaleSet::~ScrollAndScaleSet() = default;
static inline void SetMaskLayersContributeToDrawnRenderSurface(
RenderSurfaceImpl* surface,
diff --git a/chromium/cc/trees/layer_tree_host_common_unittest.cc b/chromium/cc/trees/layer_tree_host_common_unittest.cc
index ccedbe95a76..774fe2d06cf 100644
--- a/chromium/cc/trees/layer_tree_host_common_unittest.cc
+++ b/chromium/cc/trees/layer_tree_host_common_unittest.cc
@@ -57,8 +57,7 @@ namespace {
class VerifyTreeCalcsLayerTreeSettings : public LayerTreeSettings {
public:
- VerifyTreeCalcsLayerTreeSettings() {
- }
+ VerifyTreeCalcsLayerTreeSettings() = default;
};
class LayerTreeHostCommonTestBase : public LayerTestCommon::LayerImplTest {
@@ -300,12 +299,12 @@ class LayerTreeHostCommonTest : public LayerTreeHostCommonTestBase,
class LayerWithForcedDrawsContent : public Layer {
public:
- LayerWithForcedDrawsContent() {}
+ LayerWithForcedDrawsContent() = default;
bool DrawsContent() const override { return true; }
private:
- ~LayerWithForcedDrawsContent() override {}
+ ~LayerWithForcedDrawsContent() override = default;
};
class LayerTreeSettingsScaleContent : public VerifyTreeCalcsLayerTreeSettings {
@@ -7266,7 +7265,7 @@ class AnimationScaleFactorTrackingLayerImpl : public LayerImpl {
new AnimationScaleFactorTrackingLayerImpl(tree_impl, id));
}
- ~AnimationScaleFactorTrackingLayerImpl() override {}
+ ~AnimationScaleFactorTrackingLayerImpl() override = default;
private:
explicit AnimationScaleFactorTrackingLayerImpl(LayerTreeImpl* tree_impl,
diff --git a/chromium/cc/trees/layer_tree_host_impl.cc b/chromium/cc/trees/layer_tree_host_impl.cc
index f2e123f94f2..5482b96da89 100644
--- a/chromium/cc/trees/layer_tree_host_impl.cc
+++ b/chromium/cc/trees/layer_tree_host_impl.cc
@@ -71,6 +71,7 @@
#include "cc/trees/layer_tree_host_common.h"
#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/mutator_host.h"
+#include "cc/trees/render_frame_metadata.h"
#include "cc/trees/scroll_node.h"
#include "cc/trees/single_thread_proxy.h"
#include "cc/trees/transform_node.h"
@@ -87,6 +88,7 @@
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/client/raster_interface.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "third_party/skia/include/gpu/GrContext.h"
#include "ui/gfx/geometry/point_conversions.h"
@@ -175,7 +177,7 @@ LayerTreeHostImpl::FrameData::FrameData()
has_no_damage(false),
may_contain_video(false) {}
-LayerTreeHostImpl::FrameData::~FrameData() {}
+LayerTreeHostImpl::FrameData::~FrameData() = default;
std::unique_ptr<LayerTreeHostImpl> LayerTreeHostImpl::Create(
const LayerTreeSettings& settings,
@@ -407,6 +409,9 @@ void LayerTreeHostImpl::UpdateSyncTreeAfterCommitOrImplSideInvalidation() {
ImageInvalidationUpdateDurationHistogramTimer image_invalidation_timer;
PaintImageIdFlatSet images_to_invalidate =
tile_manager_.TakeImagesToInvalidateOnSyncTree();
+ if (ukm_manager_)
+ ukm_manager_->AddCheckerboardedImages(images_to_invalidate.size());
+
if (image_animation_controller_.has_value()) {
const auto& animated_images =
image_animation_controller_.value().AnimateForSyncTree(
@@ -817,9 +822,7 @@ static void AppendQuadsToFillScreen(
are_contents_opaque, opacity, SkBlendMode::kSrcOver,
sorting_context_id);
- for (Region::Iterator fill_rects(fill_region); fill_rects.has_rect();
- fill_rects.next()) {
- gfx::Rect screen_space_rect = fill_rects.rect();
+ for (gfx::Rect screen_space_rect : fill_region) {
gfx::Rect visible_screen_space_rect = screen_space_rect;
// Skip the quad culler and just append the quads directly to avoid
// occlusion checks.
@@ -1030,6 +1033,13 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
frame->activation_dependencies.end(),
append_quads_data.activation_dependencies.begin(),
append_quads_data.activation_dependencies.end());
+ if (append_quads_data.deadline_in_frames) {
+ if (!frame->deadline_in_frames)
+ frame->deadline_in_frames = 0u;
+
+ frame->deadline_in_frames = std::max(
+ *frame->deadline_in_frames, *append_quads_data.deadline_in_frames);
+ }
}
// If CommitToActiveTree() is true, then we wait to draw until
@@ -1063,7 +1073,7 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
DCHECK(frame->render_passes.back()->output_rect.origin().IsOrigin());
#endif
bool has_transparent_background =
- active_tree_->background_color() == SK_ColorTRANSPARENT;
+ SkColorGetA(active_tree_->background_color()) != SK_AlphaOPAQUE;
if (!has_transparent_background) {
frame->render_passes.back()->has_transparent_background = false;
AppendQuadsToFillScreen(
@@ -1634,7 +1644,25 @@ void LayerTreeHostImpl::DidReceiveCompositorFrameAck() {
void LayerTreeHostImpl::DidPresentCompositorFrame(uint32_t presentation_token,
base::TimeTicks time,
base::TimeDelta refresh,
- uint32_t flags) {}
+ uint32_t flags) {
+ std::vector<int> source_frames;
+ auto iter = presentation_token_to_frame_.begin();
+ for (; iter != presentation_token_to_frame_.end() &&
+ iter->first <= presentation_token;
+ ++iter) {
+ source_frames.push_back(iter->second);
+ }
+ presentation_token_to_frame_.erase(presentation_token_to_frame_.begin(),
+ iter);
+ if (presentation_token_to_frame_.empty()) {
+ DCHECK_EQ(last_presentation_token_, presentation_token);
+ last_presentation_token_ = 0u;
+ }
+
+ client_->DidPresentCompositorFrameOnImplThread(source_frames, time, refresh,
+ flags);
+}
+
void LayerTreeHostImpl::DidDiscardCompositorFrame(uint32_t presentation_token) {
}
@@ -1716,9 +1744,18 @@ void LayerTreeHostImpl::OnCanDrawStateChangedForTree() {
client_->OnCanDrawStateChanged(CanDraw());
}
-viz::CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata()
- const {
+viz::CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() {
viz::CompositorFrameMetadata metadata;
+
+ if (active_tree_->request_presentation_time()) {
+ metadata.presentation_token = ++last_presentation_token_;
+ // Assume there is never a constant stream of requests that triggers
+ // overflow.
+ CHECK_NE(0u, last_presentation_token_);
+ presentation_token_to_frame_[last_presentation_token_] =
+ active_tree_->source_frame_number();
+ }
+
metadata.device_scale_factor = active_tree_->painted_device_scale_factor() *
active_tree_->device_scale_factor();
@@ -1772,6 +1809,13 @@ viz::CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata()
return metadata;
}
+RenderFrameMetadata LayerTreeHostImpl::MakeRenderFrameMetadata() {
+ RenderFrameMetadata metadata;
+ metadata.root_scroll_offset =
+ gfx::ScrollOffsetToVector2dF(active_tree_->TotalScrollOffset());
+ return metadata;
+}
+
bool LayerTreeHostImpl::DrawLayers(FrameData* frame) {
DCHECK(CanDraw());
DCHECK_EQ(frame->has_no_damage, frame->render_passes.empty());
@@ -1788,7 +1832,8 @@ bool LayerTreeHostImpl::DrawLayers(FrameData* frame) {
return false;
}
- fps_counter_->SaveTimeStamp(CurrentBeginFrameArgs().frame_time,
+ base::TimeTicks frame_time = CurrentBeginFrameArgs().frame_time;
+ fps_counter_->SaveTimeStamp(frame_time,
!layer_tree_frame_sink_->context_provider());
rendering_stats_instrumentation_->IncrementFrameCount(1);
@@ -1834,21 +1879,31 @@ bool LayerTreeHostImpl::DrawLayers(FrameData* frame) {
viz::CompositorFrameMetadata metadata = MakeCompositorFrameMetadata();
metadata.may_contain_video = frame->may_contain_video;
+ metadata.deadline_in_frames = frame->deadline_in_frames;
metadata.activation_dependencies = std::move(frame->activation_dependencies);
- active_tree()->FinishSwapPromises(&metadata);
- for (auto& latency : metadata.latency_info) {
- TRACE_EVENT_WITH_FLOW1("input,benchmark", "LatencyInfo.Flow",
- TRACE_ID_DONT_MANGLE(latency.trace_id()),
- TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
- "step", "SwapBuffers");
- // Only add the latency component once for renderer swap, not the browser
- // swap.
- if (!latency.FindLatency(ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 0,
- nullptr)) {
- latency.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT,
- 0, 0);
+
+ RenderFrameMetadata render_frame_metadata = MakeRenderFrameMetadata();
+
+ active_tree()->FinishSwapPromises(&metadata, &render_frame_metadata);
+
+ metadata.latency_info.emplace_back(ui::SourceEventType::FRAME);
+ ui::LatencyInfo& new_latency_info = metadata.latency_info.back();
+ if (CommitToActiveTree()) {
+ new_latency_info.AddLatencyNumberWithTimestamp(
+ ui::LATENCY_BEGIN_FRAME_UI_COMPOSITOR_COMPONENT, 0, 0, frame_time, 1);
+ } else {
+ new_latency_info.AddLatencyNumberWithTimestamp(
+ ui::LATENCY_BEGIN_FRAME_RENDERER_COMPOSITOR_COMPONENT, 0, 0, frame_time,
+ 1);
+
+ base::TimeTicks draw_time = base::TimeTicks::Now();
+ for (auto& latency : metadata.latency_info) {
+ latency.AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 0, 0, draw_time, 1);
}
}
+ ui::LatencyInfo::TraceIntermediateFlowEvents(metadata.latency_info,
+ "SwapBuffers");
// Collect all resource ids in the render passes into a single array.
ResourceProvider::ResourceIdArray resources;
@@ -1875,6 +1930,14 @@ bool LayerTreeHostImpl::DrawLayers(FrameData* frame) {
layer_tree_frame_sink_->SetLocalSurfaceId(
active_tree()->local_surface_id());
}
+ if (const char* client_name = GetClientNameForMetrics()) {
+ size_t total_quad_count = 0;
+ for (const auto& pass : compositor_frame.render_pass_list)
+ total_quad_count += pass->quad_list.size();
+ UMA_HISTOGRAM_COUNTS_1000(
+ base::StringPrintf("Compositing.%s.CompositorFrame.Quads", client_name),
+ total_quad_count);
+ }
layer_tree_frame_sink_->SubmitCompositorFrame(std::move(compositor_frame));
// Clears the list of swap promises after calling DidSwap on each of them to
@@ -1953,9 +2016,10 @@ void LayerTreeHostImpl::GetGpuRasterizationCapabilities(
layer_tree_frame_sink_->worker_context_provider()))
return;
- viz::ContextProvider* context_provider =
+ viz::RasterContextProvider* context_provider =
layer_tree_frame_sink_->worker_context_provider();
- viz::ContextProvider::ScopedContextLock scoped_context(context_provider);
+ viz::RasterContextProvider::ScopedRasterContextLock scoped_context(
+ context_provider);
const auto& caps = context_provider->ContextCapabilities();
*gpu_rasterization_enabled = caps.gpu_rasterization;
@@ -2150,9 +2214,15 @@ void LayerTreeHostImpl::SynchronouslyInitializeAllTiles() {
}
void LayerTreeHostImpl::DidLoseLayerTreeFrameSink() {
+ // Check that we haven't already detected context loss because we get it via
+ // two paths: compositor context loss on the compositor thread and worker
+ // context loss posted from main thread to compositor thread. We do not want
+ // to reset the context recovery state in the scheduler.
+ if (!has_valid_layer_tree_frame_sink_)
+ return;
+ has_valid_layer_tree_frame_sink_ = false;
if (resource_provider_)
resource_provider_->DidLoseContextProvider();
- has_valid_layer_tree_frame_sink_ = false;
client_->DidLoseLayerTreeFrameSinkOnImplThread();
}
@@ -2442,6 +2512,7 @@ void LayerTreeHostImpl::CreateTileManagerResources() {
if (use_gpu_rasterization_) {
image_decode_cache_ = std::make_unique<GpuImageDecodeCache>(
layer_tree_frame_sink_->worker_context_provider(),
+ settings_.enable_oop_rasterization,
viz::ResourceFormatToClosestSkColorType(
settings_.preferred_tile_format),
settings_.decoded_image_working_set_budget_bytes);
@@ -2485,34 +2556,37 @@ void LayerTreeHostImpl::CreateResourceAndRasterBufferProvider(
viz::ContextProvider* compositor_context_provider =
layer_tree_frame_sink_->context_provider();
if (!compositor_context_provider) {
- *resource_pool =
- ResourcePool::Create(resource_provider_.get(), GetTaskRunner(),
- viz::ResourceTextureHint::kDefault,
- ResourcePool::kDefaultExpirationDelay,
- settings_.disallow_non_exact_resource_reuse);
+ // This ResourcePool will vend software resources.
+ *resource_pool = std::make_unique<ResourcePool>(
+ resource_provider_.get(), GetTaskRunner(),
+ ResourcePool::kDefaultExpirationDelay,
+ settings_.disallow_non_exact_resource_reuse);
*raster_buffer_provider =
BitmapRasterBufferProvider::Create(resource_provider_.get());
return;
}
- viz::ContextProvider* worker_context_provider =
+ viz::RasterContextProvider* worker_context_provider =
layer_tree_frame_sink_->worker_context_provider();
if (use_gpu_rasterization_) {
DCHECK(worker_context_provider);
- *resource_pool =
- ResourcePool::Create(resource_provider_.get(), GetTaskRunner(),
- viz::ResourceTextureHint::kFramebuffer,
- ResourcePool::kDefaultExpirationDelay,
- settings_.disallow_non_exact_resource_reuse);
+ // This ResourcePool will vend gpu resources optimized for binding as a
+ // framebuffer for gpu raster.
+ *resource_pool = std::make_unique<ResourcePool>(
+ resource_provider_.get(), GetTaskRunner(),
+ viz::ResourceTextureHint::kFramebuffer,
+ ResourcePool::kDefaultExpirationDelay,
+ settings_.disallow_non_exact_resource_reuse);
int msaa_sample_count = use_msaa_ ? RequestedMSAASampleCount() : 0;
// The worker context must support oop raster to enable oop rasterization.
bool oop_raster_enabled = settings_.enable_oop_rasterization;
if (oop_raster_enabled) {
- viz::ContextProvider::ScopedContextLock hold(worker_context_provider);
+ viz::RasterContextProvider::ScopedRasterContextLock hold(
+ worker_context_provider);
oop_raster_enabled &=
worker_context_provider->ContextCapabilities().supports_oop_raster;
}
@@ -2520,8 +2594,7 @@ void LayerTreeHostImpl::CreateResourceAndRasterBufferProvider(
*raster_buffer_provider = std::make_unique<GpuRasterBufferProvider>(
compositor_context_provider, worker_context_provider,
resource_provider_.get(), settings_.use_distance_field_text,
- msaa_sample_count, settings_.preferred_tile_format,
- settings_.async_worker_context_enabled, oop_raster_enabled);
+ msaa_sample_count, settings_.preferred_tile_format, oop_raster_enabled);
return;
}
@@ -2535,7 +2608,8 @@ void LayerTreeHostImpl::CreateResourceAndRasterBufferProvider(
}
if (use_zero_copy) {
- *resource_pool = ResourcePool::CreateForGpuMemoryBufferResources(
+ // This ResourcePool will vend gpu resources backed by gpu memory buffers.
+ *resource_pool = std::make_unique<ResourcePool>(
resource_provider_.get(), GetTaskRunner(),
gfx::BufferUsage::GPU_READ_CPU_READ_WRITE,
ResourcePool::kDefaultExpirationDelay,
@@ -2546,7 +2620,8 @@ void LayerTreeHostImpl::CreateResourceAndRasterBufferProvider(
return;
}
- *resource_pool = ResourcePool::Create(
+ // This ResourcePool will vend gpu texture resources.
+ *resource_pool = std::make_unique<ResourcePool>(
resource_provider_.get(), GetTaskRunner(),
viz::ResourceTextureHint::kDefault, ResourcePool::kDefaultExpirationDelay,
settings_.disallow_non_exact_resource_reuse);
@@ -2559,7 +2634,7 @@ void LayerTreeHostImpl::CreateResourceAndRasterBufferProvider(
GetTaskRunner(), compositor_context_provider, worker_context_provider,
resource_provider_.get(), max_copy_texture_chromium_size,
settings_.use_partial_raster, settings_.max_staging_buffer_usage_in_bytes,
- settings_.preferred_tile_format, settings_.async_worker_context_enabled);
+ settings_.preferred_tile_format);
}
void LayerTreeHostImpl::SetLayerTreeMutator(
@@ -2630,8 +2705,8 @@ void LayerTreeHostImpl::CleanUpTileManagerResources() {
compositor_context->ContextGL()->ShallowFlushCHROMIUM();
if (auto* worker_context =
layer_tree_frame_sink_->worker_context_provider()) {
- viz::ContextProvider::ScopedContextLock hold(worker_context);
- worker_context->ContextGL()->ShallowFlushCHROMIUM();
+ viz::RasterContextProvider::ScopedRasterContextLock hold(worker_context);
+ hold.RasterInterface()->ShallowFlushCHROMIUM();
}
}
}
@@ -3138,7 +3213,7 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimatedBegin(
ScrollStateData scroll_state_end_data;
scroll_state_end_data.is_ending = true;
ScrollState scroll_state_end(scroll_state_end_data);
- ScrollEnd(&scroll_state_end);
+ ScrollEndImpl(&scroll_state_end);
}
return scroll_status;
}
@@ -3311,7 +3386,7 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimated(
}
}
scroll_state.set_is_ending(true);
- ScrollEnd(&scroll_state);
+ ScrollEndImpl(&scroll_state);
if (settings_.is_layer_tree_for_subframe &&
scroll_status.thread == SCROLL_ON_IMPL_THREAD) {
// If we get to here, we shouldn't return SCROLL_ON_IMPL_THREAD as otherwise
@@ -3571,6 +3646,12 @@ void LayerTreeHostImpl::DistributeScrollDelta(ScrollState* scroll_state) {
: scroll_state->delta_y();
if (!CanPropagate(scroll_node, delta_x, delta_y)) {
+ // We should add the first node with non-auto overscroll-behavior to
+ // the scroll chain regardlessly, as it's the only node we can latch to.
+ if (current_scroll_chain.empty() ||
+ current_scroll_chain.front() != scroll_node) {
+ current_scroll_chain.push_front(scroll_node);
+ }
scroll_state->set_is_scroll_chain_cut(true);
break;
}
@@ -3662,6 +3743,8 @@ InputHandlerScrollResult LayerTreeHostImpl::ScrollBy(
bool did_scroll_x = scroll_state->caused_scroll_x();
bool did_scroll_y = scroll_state->caused_scroll_y();
+ did_scroll_x_for_scroll_gesture_ |= did_scroll_x;
+ did_scroll_y_for_scroll_gesture_ |= did_scroll_y;
bool did_scroll_content = did_scroll_x || did_scroll_y;
if (did_scroll_content) {
ShowScrollbarsForImplScroll(current_scrolling_node->element_id);
@@ -3742,14 +3825,38 @@ void LayerTreeHostImpl::SetSynchronousInputHandlerRootScrollOffset(
SetNeedsRedraw();
}
+bool LayerTreeHostImpl::SnapAtScrollEnd() {
+ ScrollNode* scroll_node = CurrentlyScrollingNode();
+ if (!scroll_node || !scroll_node->snap_container_data.has_value())
+ return false;
+
+ const SnapContainerData& data = scroll_node->snap_container_data.value();
+ ScrollTree& scroll_tree = active_tree()->property_trees()->scroll_tree;
+ gfx::ScrollOffset current_position =
+ scroll_tree.current_scroll_offset(scroll_node->element_id);
+
+ gfx::ScrollOffset snap_position =
+ data.FindSnapPosition(current_position, did_scroll_x_for_scroll_gesture_,
+ did_scroll_y_for_scroll_gesture_);
+ if (snap_position == current_position)
+ return false;
+
+ ScrollAnimationCreate(
+ scroll_node, ScrollOffsetToVector2dF(snap_position - current_position),
+ base::TimeDelta());
+ return true;
+}
+
void LayerTreeHostImpl::ClearCurrentlyScrollingNode() {
active_tree_->ClearCurrentlyScrollingNode();
did_lock_scrolling_layer_ = false;
scroll_affects_scroll_handler_ = false;
accumulated_root_overscroll_ = gfx::Vector2dF();
+ did_scroll_x_for_scroll_gesture_ = false;
+ did_scroll_y_for_scroll_gesture_ = false;
}
-void LayerTreeHostImpl::ScrollEnd(ScrollState* scroll_state) {
+void LayerTreeHostImpl::ScrollEndImpl(ScrollState* scroll_state) {
DCHECK(scroll_state);
DCHECK(scroll_state->delta_x() == 0 && scroll_state->delta_y() == 0);
@@ -3758,6 +3865,13 @@ void LayerTreeHostImpl::ScrollEnd(ScrollState* scroll_state) {
ClearCurrentlyScrollingNode();
}
+void LayerTreeHostImpl::ScrollEnd(ScrollState* scroll_state, bool should_snap) {
+ if (should_snap && SnapAtScrollEnd())
+ return;
+
+ ScrollEndImpl(scroll_state);
+}
+
InputHandler::ScrollStatus LayerTreeHostImpl::FlingScrollBegin() {
InputHandler::ScrollStatus scroll_status;
scroll_status.main_thread_scrolling_reasons =
@@ -3797,6 +3911,11 @@ void LayerTreeHostImpl::MouseUp() {
}
void LayerTreeHostImpl::MouseMoveAt(const gfx::Point& viewport_point) {
+ // Early out if there are no animation controllers and avoid the hit test.
+ // This happens on platforms without animated scrollbars.
+ if (scrollbar_animation_controllers_.empty())
+ return;
+
gfx::PointF device_viewport_point = gfx::ScalePoint(
gfx::PointF(viewport_point), active_tree_->device_scale_factor());
LayerImpl* layer_impl =
@@ -4282,9 +4401,15 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid,
upload_size = gfx::ScaleToCeiledSize(source_size, scale, scale);
}
- id = resource_provider_->CreateResource(
- upload_size, viz::ResourceTextureHint::kDefault, format,
- gfx::ColorSpace::CreateSRGB());
+ if (layer_tree_frame_sink_->context_provider()) {
+ id = resource_provider_->CreateGpuTextureResource(
+ upload_size, viz::ResourceTextureHint::kDefault, format,
+ gfx::ColorSpace::CreateSRGB());
+ } else {
+ DCHECK_EQ(format, viz::RGBA_8888);
+ id = resource_provider_->CreateBitmapResource(
+ upload_size, gfx::ColorSpace::CreateSRGB());
+ }
if (!scaled) {
resource_provider_->CopyToResource(id, bitmap.GetPixels(), source_size);
@@ -4553,7 +4678,7 @@ void LayerTreeHostImpl::ScrollOffsetAnimationFinished() {
// TODO(majidvp): We should pass in the original starting scroll position here
ScrollStateData scroll_state_data;
ScrollState scroll_state(scroll_state_data);
- ScrollEnd(&scroll_state);
+ ScrollEndImpl(&scroll_state);
}
gfx::ScrollOffset LayerTreeHostImpl::GetScrollOffsetForAnimation(
@@ -4598,7 +4723,7 @@ void LayerTreeHostImpl::SetContextVisibility(bool is_visible) {
// before we get a chance to go invisible in NotifyAllTileTasksComplete.
auto* worker_context = layer_tree_frame_sink_->worker_context_provider();
if (worker_context && is_visible != !!worker_context_visibility_) {
- viz::ContextProvider::ScopedContextLock hold(worker_context);
+ viz::RasterContextProvider::ScopedRasterContextLock hold(worker_context);
if (is_visible) {
worker_context_visibility_ =
worker_context->CacheController()->ClientBecameVisible();
diff --git a/chromium/cc/trees/layer_tree_host_impl.h b/chromium/cc/trees/layer_tree_host_impl.h
index 2dbe0d5832d..abae9212c9b 100644
--- a/chromium/cc/trees/layer_tree_host_impl.h
+++ b/chromium/cc/trees/layer_tree_host_impl.h
@@ -15,6 +15,7 @@
#include <vector>
#include "base/callback.h"
+#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/sequenced_task_runner.h"
#include "base/time/time.h"
@@ -73,6 +74,7 @@ class PendingTreeDurationHistogramTimer;
class PendingTreeRasterDurationHistogramTimer;
class RasterTilePriorityQueue;
class RasterBufferProvider;
+class RenderFrameMetadata;
class RenderingStatsInstrumentation;
class ResourcePool;
class ScrollElasticityHelper;
@@ -138,6 +140,14 @@ class LayerTreeHostImplClient {
virtual void RequestBeginMainFrameNotExpected(bool new_state) = 0;
+ // Called when a presentation time is requested. |source_frames| identifies
+ // the frames that correspond to the request.
+ virtual void DidPresentCompositorFrameOnImplThread(
+ const std::vector<int>& source_frames,
+ base::TimeTicks time,
+ base::TimeDelta refresh,
+ uint32_t flags) = 0;
+
protected:
virtual ~LayerTreeHostImplClient() {}
};
@@ -184,7 +194,7 @@ class CC_EXPORT LayerTreeHostImpl
void RequestUpdateForSynchronousInputHandler() override;
void SetSynchronousInputHandlerRootScrollOffset(
const gfx::ScrollOffset& root_offset) override;
- void ScrollEnd(ScrollState* scroll_state) override;
+ void ScrollEnd(ScrollState* scroll_state, bool should_snap = false) override;
InputHandler::ScrollStatus FlingScrollBegin() override;
void MouseDown() override;
@@ -239,6 +249,7 @@ class CC_EXPORT LayerTreeHostImpl
void AsValueInto(base::trace_event::TracedValue* value) const;
std::vector<viz::SurfaceId> activation_dependencies;
+ base::Optional<uint32_t> deadline_in_frames;
std::vector<gfx::Rect> occluding_screen_space_rects;
std::vector<gfx::Rect> non_occluding_screen_space_rects;
viz::RenderPassList render_passes;
@@ -563,7 +574,8 @@ class CC_EXPORT LayerTreeHostImpl
void ScheduleMicroBenchmark(std::unique_ptr<MicroBenchmarkImpl> benchmark);
- viz::CompositorFrameMetadata MakeCompositorFrameMetadata() const;
+ viz::CompositorFrameMetadata MakeCompositorFrameMetadata();
+ RenderFrameMetadata MakeRenderFrameMetadata();
// Viewport rectangle and clip in device space. These rects are used to
// prioritize raster and determine what is submitted in a CompositorFrame.
@@ -752,6 +764,12 @@ class CC_EXPORT LayerTreeHostImpl
const gfx::Vector2dF& scroll_delta,
base::TimeDelta delayed_by);
+ void ScrollEndImpl(ScrollState* scroll_state);
+
+ // Creates an animation curve and returns true if we need to update the
+ // scroll position to a snap point. Otherwise returns false.
+ bool SnapAtScrollEnd();
+
void SetContextVisibility(bool is_visible);
void ImageDecodeFinished(int request_id, bool decode_succeeded);
@@ -846,6 +864,11 @@ class CC_EXPORT LayerTreeHostImpl
gfx::Vector2dF accumulated_root_overscroll_;
+ // True iff some of the delta has been consumed for the current scroll
+ // sequence on the specific axis.
+ bool did_scroll_x_for_scroll_gesture_;
+ bool did_scroll_y_for_scroll_gesture_;
+
bool pinch_gesture_active_;
bool pinch_gesture_end_should_clear_scrolling_node_;
@@ -943,6 +966,15 @@ class CC_EXPORT LayerTreeHostImpl
std::unique_ptr<UkmManager> ukm_manager_;
+ // Maps from presentation_token set on CF to the source frame that requested
+ // it. Presentation tokens are requested if the active tree has
+ // request_presentation_time() set.
+ base::flat_map<uint32_t, int> presentation_token_to_frame_;
+
+ // If non-zero identifies the presentation-token added to the last CF. Reset
+ // to zero when no more presentation tokens are in flight.
+ uint32_t last_presentation_token_ = 0u;
+
DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImpl);
};
diff --git a/chromium/cc/trees/layer_tree_host_impl_unittest.cc b/chromium/cc/trees/layer_tree_host_impl_unittest.cc
index aa669b284ba..29bb61addcf 100644
--- a/chromium/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/chromium/cc/trees/layer_tree_host_impl_unittest.cc
@@ -52,6 +52,7 @@
#include "cc/test/skia_common.h"
#include "cc/test/test_task_graph_runner.h"
#include "cc/test/test_web_graphics_context_3d.h"
+#include "cc/trees/draw_property_utils.h"
#include "cc/trees/effect_node.h"
#include "cc/trees/latency_info_swap_promise.h"
#include "cc/trees/layer_tree_host_common.h"
@@ -134,8 +135,6 @@ class LayerTreeHostImplTest : public testing::Test,
settings.enable_surface_synchronization = true;
settings.minimum_occlusion_tracking_size = gfx::Size();
settings.resource_settings.texture_id_allocation_chunk_size = 1;
- settings.resource_settings.buffer_to_texture_target_map =
- viz::DefaultBufferToTextureTargetMapForTesting();
return settings;
}
@@ -198,6 +197,11 @@ class LayerTreeHostImplTest : public testing::Test,
}
void NotifyImageDecodeRequestFinished() override {}
void RequestBeginMainFrameNotExpected(bool new_state) override {}
+ void DidPresentCompositorFrameOnImplThread(
+ const std::vector<int>& source_frames,
+ base::TimeTicks time,
+ base::TimeDelta refresh,
+ uint32_t flags) override {}
void set_reduce_memory_result(bool reduce_memory_result) {
reduce_memory_result_ = reduce_memory_result;
@@ -658,6 +662,34 @@ class LayerTreeHostImplTest : public testing::Test,
EXPECT_EQ(kTouchActionPanX, touch_action);
}
+ LayerImpl* CreateLayerForSnapping() {
+ LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
+ host_impl_->SetViewportSize(gfx::Size(100, 100));
+
+ gfx::Size overflow_size(400, 400);
+ EXPECT_EQ(1u, scroll_layer->test_properties()->children.size());
+ LayerImpl* overflow = scroll_layer->test_properties()->children[0];
+ overflow->SetBounds(overflow_size);
+ overflow->SetScrollable(gfx::Size(100, 100));
+ overflow->SetElementId(LayerIdToElementIdForTesting(overflow->id()));
+ overflow->layer_tree_impl()
+ ->property_trees()
+ ->scroll_tree.UpdateScrollOffsetBaseForTesting(overflow->element_id(),
+ gfx::ScrollOffset());
+ overflow->SetPosition(gfx::PointF(0, 0));
+
+ SnapContainerData container_data(
+ ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory),
+ gfx::ScrollOffset(300, 300));
+ SnapAreaData area_data(SnapAxis::kBoth, gfx::ScrollOffset(50, 50), false);
+ container_data.AddSnapAreaData(area_data);
+ overflow->test_properties()->snap_container_data.emplace(container_data);
+ host_impl_->active_tree()->BuildPropertyTreesForTesting();
+ DrawFrame();
+
+ return overflow;
+ }
+
void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor);
void pinch_zoom_pan_viewport_test(float device_scale_factor);
void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor);
@@ -756,7 +788,7 @@ class TestInputHandlerClient : public InputHandlerClient {
: page_scale_factor_(0.f),
min_page_scale_factor_(-1.f),
max_page_scale_factor_(-1.f) {}
- ~TestInputHandlerClient() override {}
+ ~TestInputHandlerClient() override = default;
// InputHandlerClient implementation.
void WillShutdown() override {}
@@ -1499,6 +1531,90 @@ TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) {
.did_scroll);
}
+TEST_F(LayerTreeHostImplTest, ScrollSnapOnX) {
+ LayerImpl* overflow = CreateLayerForSnapping();
+
+ gfx::Point scroll_position(10, 10);
+ EXPECT_EQ(
+ InputHandler::SCROLL_ON_IMPL_THREAD,
+ host_impl_
+ ->ScrollBegin(BeginState(scroll_position).get(), InputHandler::WHEEL)
+ .thread);
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
+
+ gfx::Vector2dF x_delta(20, 0);
+ host_impl_->ScrollBy(UpdateState(scroll_position, x_delta).get());
+
+ viz::BeginFrameArgs begin_frame_args =
+ viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
+ host_impl_->ScrollEnd(EndState().get(), true);
+ base::TimeTicks start_time =
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
+ BeginImplFrameAndAnimate(begin_frame_args, start_time);
+ BeginImplFrameAndAnimate(begin_frame_args,
+ start_time + base::TimeDelta::FromMilliseconds(50));
+ BeginImplFrameAndAnimate(
+ begin_frame_args, start_time + base::TimeDelta::FromMilliseconds(1000));
+
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 0), overflow->CurrentScrollOffset());
+}
+
+TEST_F(LayerTreeHostImplTest, ScrollSnapOnY) {
+ LayerImpl* overflow = CreateLayerForSnapping();
+
+ gfx::Point scroll_position(10, 10);
+ EXPECT_EQ(
+ InputHandler::SCROLL_ON_IMPL_THREAD,
+ host_impl_
+ ->ScrollBegin(BeginState(scroll_position).get(), InputHandler::WHEEL)
+ .thread);
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
+
+ gfx::Vector2dF y_delta(0, 20);
+ host_impl_->ScrollBy(UpdateState(scroll_position, y_delta).get());
+
+ viz::BeginFrameArgs begin_frame_args =
+ viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
+ host_impl_->ScrollEnd(EndState().get(), true);
+ base::TimeTicks start_time =
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
+ BeginImplFrameAndAnimate(begin_frame_args, start_time);
+ BeginImplFrameAndAnimate(begin_frame_args,
+ start_time + base::TimeDelta::FromMilliseconds(50));
+ BeginImplFrameAndAnimate(
+ begin_frame_args, start_time + base::TimeDelta::FromMilliseconds(1000));
+
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 50), overflow->CurrentScrollOffset());
+}
+
+TEST_F(LayerTreeHostImplTest, ScrollSnapOnBoth) {
+ LayerImpl* overflow = CreateLayerForSnapping();
+
+ gfx::Point scroll_position(10, 10);
+ EXPECT_EQ(
+ InputHandler::SCROLL_ON_IMPL_THREAD,
+ host_impl_
+ ->ScrollBegin(BeginState(scroll_position).get(), InputHandler::WHEEL)
+ .thread);
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
+
+ gfx::Vector2dF delta(20, 20);
+ host_impl_->ScrollBy(UpdateState(scroll_position, delta).get());
+
+ viz::BeginFrameArgs begin_frame_args =
+ viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
+ host_impl_->ScrollEnd(EndState().get(), true);
+ base::TimeTicks start_time =
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
+ BeginImplFrameAndAnimate(begin_frame_args, start_time);
+ BeginImplFrameAndAnimate(begin_frame_args,
+ start_time + base::TimeDelta::FromMilliseconds(50));
+ BeginImplFrameAndAnimate(
+ begin_frame_args, start_time + base::TimeDelta::FromMilliseconds(1000));
+
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 50), overflow->CurrentScrollOffset());
+}
+
TEST_F(LayerTreeHostImplTest, OverscrollBehaviorPreventsPropagation) {
LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
host_impl_->SetViewportSize(gfx::Size(100, 100));
@@ -1641,6 +1757,31 @@ TEST_F(LayerTreeHostImplTest, OverscrollBehaviorPreventsPropagation) {
host_impl_->ScrollEnd(EndState().get());
EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), scroll_layer->CurrentScrollOffset());
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
+
+ // Gesture scroll should latch to the first scroller that has non-auto
+ // overscroll-behavior.
+ overflow->test_properties()->overscroll_behavior =
+ OverscrollBehavior(OverscrollBehavior::kOverscrollBehaviorTypeContain,
+ OverscrollBehavior::kOverscrollBehaviorTypeContain);
+ host_impl_->active_tree()->BuildPropertyTreesForTesting();
+
+ DrawFrame();
+
+ EXPECT_EQ(
+ InputHandler::SCROLL_ON_IMPL_THREAD,
+ host_impl_
+ ->ScrollBegin(BeginState(scroll_position).get(), InputHandler::WHEEL)
+ .thread);
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), scroll_layer->CurrentScrollOffset());
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
+
+ host_impl_->ScrollBy(UpdateState(scroll_position, x_delta).get());
+ host_impl_->ScrollBy(UpdateState(scroll_position, -x_delta).get());
+ host_impl_->ScrollBy(UpdateState(scroll_position, y_delta).get());
+ host_impl_->ScrollBy(UpdateState(scroll_position, -y_delta).get());
+ host_impl_->ScrollEnd(EndState().get());
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), scroll_layer->CurrentScrollOffset());
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->CurrentScrollOffset());
}
TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) {
@@ -2616,6 +2757,89 @@ TEST_F(LayerTreeHostImplTest, PinchGesture) {
}
}
+TEST_F(LayerTreeHostImplTest, SyncSubpixelScrollDelta) {
+ SetupScrollAndContentsLayers(gfx::Size(100, 100));
+ host_impl_->SetViewportSize(gfx::Size(50, 50));
+ DrawFrame();
+
+ LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
+ DCHECK(scroll_layer);
+
+ float min_page_scale = 1.f;
+ float max_page_scale = 4.f;
+
+ host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
+ max_page_scale);
+ SetScrollOffsetDelta(scroll_layer, gfx::Vector2d());
+ scroll_layer->layer_tree_impl()
+ ->property_trees()
+ ->scroll_tree.CollectScrollDeltasForTesting();
+ scroll_layer->layer_tree_impl()
+ ->property_trees()
+ ->scroll_tree.UpdateScrollOffsetBaseForTesting(scroll_layer->element_id(),
+ gfx::ScrollOffset(0, 20));
+
+ float page_scale_delta = 1.f;
+ host_impl_->ScrollBegin(BeginState(gfx::Point(10, 10)).get(),
+ InputHandler::TOUCHSCREEN);
+ host_impl_->PinchGestureBegin();
+ host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
+ host_impl_->ScrollBy(
+ UpdateState(gfx::Point(10, 10), gfx::Vector2dF(0, -1.001f)).get());
+ host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 9));
+ host_impl_->PinchGestureEnd(gfx::Point(10, 9), true);
+ host_impl_->ScrollEnd(EndState().get());
+
+ std::unique_ptr<ScrollAndScaleSet> scroll_info =
+ host_impl_->ProcessScrollDeltas();
+ EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
+ EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->element_id(),
+ gfx::Vector2d(0, -1)));
+
+ // Verify this scroll delta is consistent with the snapped position of the
+ // scroll layer.
+ draw_property_utils::ComputeTransforms(
+ &scroll_layer->layer_tree_impl()->property_trees()->transform_tree);
+ EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, -19.f),
+ scroll_layer->ScreenSpaceTransform().To2dTranslation());
+}
+
+TEST_F(LayerTreeHostImplTest, SyncSubpixelScrollFromFractionalActiveBase) {
+ SetupScrollAndContentsLayers(gfx::Size(100, 100));
+ host_impl_->SetViewportSize(gfx::Size(50, 50));
+ DrawFrame();
+
+ LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
+ DCHECK(scroll_layer);
+
+ SetScrollOffsetDelta(scroll_layer, gfx::Vector2d());
+ scroll_layer->layer_tree_impl()
+ ->property_trees()
+ ->scroll_tree.CollectScrollDeltasForTesting();
+ scroll_layer->layer_tree_impl()
+ ->property_trees()
+ ->scroll_tree.UpdateScrollOffsetBaseForTesting(
+ scroll_layer->element_id(), gfx::ScrollOffset(0, 20.5f));
+
+ host_impl_->ScrollBegin(BeginState(gfx::Point(10, 10)).get(),
+ InputHandler::WHEEL);
+ host_impl_->ScrollBy(
+ UpdateState(gfx::Point(10, 10), gfx::Vector2dF(0, -1)).get());
+ host_impl_->ScrollEnd(EndState().get());
+
+ gfx::ScrollOffset active_base =
+ host_impl_->active_tree()
+ ->property_trees()
+ ->scroll_tree.GetScrollOffsetBaseForTesting(
+ scroll_layer->element_id());
+ EXPECT_VECTOR_EQ(active_base, gfx::Vector2dF(0, 20.5));
+ // Fractional active base should not affect the scroll delta.
+ std::unique_ptr<ScrollAndScaleSet> scroll_info =
+ host_impl_->ProcessScrollDeltas();
+ EXPECT_VECTOR_EQ(scroll_info->inner_viewport_scroll.scroll_delta,
+ gfx::Vector2dF(0, -1));
+}
+
TEST_F(LayerTreeHostImplTest, PinchZoomTriggersPageScaleAnimation) {
SetupScrollAndContentsLayers(gfx::Size(100, 100));
host_impl_->SetViewportSize(gfx::Size(50, 50));
@@ -4049,7 +4273,7 @@ TEST_F(LayerTreeHostImplTest, ActivationDependenciesInMetadata) {
child->SetPosition(gfx::PointF(25.f * i, 0.f));
child->SetBounds(gfx::Size(1, 1));
child->SetDrawsContent(true);
- child->SetPrimarySurfaceId(primary_surfaces[i]);
+ child->SetPrimarySurfaceId(primary_surfaces[i], base::nullopt);
child->SetFallbackSurfaceId(fallback_surfaces[i]);
root->test_properties()->AddChild(std::move(child));
}
@@ -6770,12 +6994,12 @@ TEST_F(LayerTreeHostImplTest, ScrollPerspectiveTransformedLayer) {
gfx::Vector2d expected_scroll_deltas[4];
// Perspective affects the vertical delta by a different
// amount depending on the vertical position of the |viewport_point|.
- expected_scroll_deltas[0] = gfx::Vector2d(2, 8);
+ expected_scroll_deltas[0] = gfx::Vector2d(2, 9);
expected_scroll_deltas[1] = gfx::Vector2d(1, 4);
// Deltas which start with the same vertical position of the
// |viewport_point| are subject to identical perspective effects.
- expected_scroll_deltas[2] = gfx::Vector2d(4, 0);
- expected_scroll_deltas[3] = gfx::Vector2d(4, 0);
+ expected_scroll_deltas[2] = gfx::Vector2d(5, 0);
+ expected_scroll_deltas[3] = gfx::Vector2d(5, 0);
gfx::Point viewport_point(1, 1);
@@ -7853,12 +8077,27 @@ TEST_F(LayerTreeHostImplTest, OverscrollOnImplThread) {
class BlendStateCheckLayer : public LayerImpl {
public:
- static std::unique_ptr<LayerImpl> Create(
- LayerTreeImpl* tree_impl,
- int id,
- ResourceProvider* resource_provider) {
- return base::WrapUnique(
- new BlendStateCheckLayer(tree_impl, id, resource_provider));
+ BlendStateCheckLayer(LayerTreeImpl* tree_impl,
+ int id,
+ LayerTreeResourceProvider* resource_provider)
+ : LayerImpl(tree_impl, id),
+ blend_(false),
+ has_render_surface_(false),
+ comparison_layer_(nullptr),
+ quads_appended_(false),
+ quad_rect_(5, 5, 5, 5),
+ quad_visible_rect_(5, 5, 5, 5) {
+ if (tree_impl->context_provider()) {
+ resource_id_ = resource_provider->CreateGpuTextureResource(
+ gfx::Size(1, 1), viz::ResourceTextureHint::kDefault, viz::RGBA_8888,
+ gfx::ColorSpace());
+ } else {
+ resource_id_ = resource_provider->CreateBitmapResource(gfx::Size(1, 1),
+ gfx::ColorSpace());
+ }
+ resource_provider->AllocateForTesting(resource_id_);
+ SetBounds(gfx::Size(10, 10));
+ SetDrawsContent(true);
}
void AppendQuads(viz::RenderPass* render_pass,
@@ -7907,26 +8146,6 @@ class BlendStateCheckLayer : public LayerImpl {
}
private:
- BlendStateCheckLayer(LayerTreeImpl* tree_impl,
- int id,
- ResourceProvider* resource_provider)
- : LayerImpl(tree_impl, id),
- blend_(false),
- has_render_surface_(false),
- comparison_layer_(nullptr),
- quads_appended_(false),
- quad_rect_(5, 5, 5, 5),
- quad_visible_rect_(5, 5, 5, 5),
- resource_id_(resource_provider->CreateResource(
- gfx::Size(1, 1),
- viz::ResourceTextureHint::kDefault,
- viz::RGBA_8888,
- gfx::ColorSpace())) {
- resource_provider->AllocateForTesting(resource_id_);
- SetBounds(gfx::Size(10, 10));
- SetDrawsContent(true);
- }
-
bool blend_;
bool has_render_surface_;
LayerImpl* comparison_layer_;
@@ -7948,7 +8167,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
}
LayerImpl* root = host_impl_->active_tree()->root_layer_for_testing();
- root->test_properties()->AddChild(BlendStateCheckLayer::Create(
+ root->test_properties()->AddChild(std::make_unique<BlendStateCheckLayer>(
host_impl_->active_tree(), 2, host_impl_->resource_provider()));
auto* layer1 =
static_cast<BlendStateCheckLayer*>(root->test_properties()->children[0]);
@@ -8001,7 +8220,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
EXPECT_TRUE(layer1->quads_appended());
host_impl_->DidDrawAllLayers(frame);
- layer1->test_properties()->AddChild(BlendStateCheckLayer::Create(
+ layer1->test_properties()->AddChild(std::make_unique<BlendStateCheckLayer>(
host_impl_->active_tree(), 3, host_impl_->resource_provider()));
auto* layer2 = static_cast<BlendStateCheckLayer*>(
layer1->test_properties()->children[0]);
@@ -8265,7 +8484,7 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
host_impl_->active_tree()
->root_layer_for_testing()
->test_properties()
- ->AddChild(BlendStateCheckLayer::Create(
+ ->AddChild(std::make_unique<BlendStateCheckLayer>(
host_impl_->active_tree(), 2, host_impl_->resource_provider()));
child_ = static_cast<BlendStateCheckLayer*>(host_impl_->active_tree()
->root_layer_for_testing()
@@ -8767,6 +8986,20 @@ TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
}
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
+
+ // Cause damage so we would draw something if possible.
+ host_impl_->SetFullViewportDamage();
+
+ // Verify no quads are drawn when semi-transparent background is set.
+ host_impl_->active_tree()->set_background_color(SkColorSetARGB(5, 255, 0, 0));
+ host_impl_->SetFullViewportDamage();
+ EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+ {
+ const auto& root_pass = frame.render_passes.back();
+ ASSERT_EQ(0u, root_pass->quad_list.size());
+ }
+ host_impl_->DrawLayers(&frame);
+ host_impl_->DidDrawAllLayers(frame);
}
class LayerTreeHostImplTestDrawAndTestDamage : public LayerTreeHostImplTest {
@@ -9374,8 +9607,8 @@ TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
host_impl_->DrawLayers(&frame);
host_impl_->DidDrawAllLayers(frame);
- // The CopyOutputResult has a ref on the viz::ContextProvider and a texture in
- // a texture mailbox.
+ // The CopyOutputResult has a ref on the viz::ContextProvider and a texture
+ // in a texture mailbox.
ASSERT_TRUE(helper.unprocessed_result);
EXPECT_FALSE(context_provider->HasOneRef());
EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
@@ -9702,22 +9935,52 @@ TEST_F(LayerTreeHostImplTest, ScrollInvisibleScroller) {
host_impl_->CurrentlyScrollingNode()->id);
}
-// Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
-// in viz::CompositorFrameMetadata.
-TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) {
- std::unique_ptr<SolidColorLayerImpl> root =
- SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
- root->SetPosition(gfx::PointF());
- root->SetBounds(gfx::Size(10, 10));
- root->SetDrawsContent(true);
- root->test_properties()->force_render_surface = true;
+template <bool commit_to_active_tree>
+class LayerTreeHostImplLatencyInfoTest : public LayerTreeHostImplTest {
+ public:
+ void SetUp() override {
+ LayerTreeSettings settings = DefaultSettings();
+ settings.commit_to_active_tree = commit_to_active_tree;
+ CreateHostImpl(settings, CreateLayerTreeFrameSink());
- host_impl_->active_tree()->SetRootLayerForTesting(std::move(root));
- host_impl_->active_tree()->BuildPropertyTreesForTesting();
+ std::unique_ptr<SolidColorLayerImpl> root =
+ SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
+ root->SetPosition(gfx::PointF());
+ root->SetBounds(gfx::Size(10, 10));
+ root->SetDrawsContent(true);
+ root->test_properties()->force_render_surface = true;
+ host_impl_->active_tree()->SetRootLayerForTesting(std::move(root));
+ host_impl_->active_tree()->BuildPropertyTreesForTesting();
+ }
+};
+
+// Make sure LatencyInfo are passed in viz::CompositorFrameMetadata properly in
+// the Renderer. This includes components added by LatencyInfoSwapPromise and
+// the default LATENCY_BEGIN_FRAME_RENDERER_COMPOSITOR_COMPONENT.
+using LayerTreeHostImplLatencyInfoRendererTest =
+ LayerTreeHostImplLatencyInfoTest<false>;
+TEST_F(LayerTreeHostImplLatencyInfoRendererTest,
+ LatencyInfoPassedToCompositorFrameMetadataRenderer) {
auto* fake_layer_tree_frame_sink =
static_cast<FakeLayerTreeFrameSink*>(host_impl_->layer_tree_frame_sink());
+ // The first frame should only have the default BeginFrame component.
+ TestFrameData frame1;
+ EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame1));
+ EXPECT_TRUE(host_impl_->DrawLayers(&frame1));
+ host_impl_->DidDrawAllLayers(frame1);
+
+ const std::vector<ui::LatencyInfo>& metadata_latency_after1 =
+ fake_layer_tree_frame_sink->last_sent_frame()->metadata.latency_info;
+ EXPECT_EQ(1u, metadata_latency_after1.size());
+ EXPECT_TRUE(metadata_latency_after1[0].FindLatency(
+ ui::LATENCY_BEGIN_FRAME_RENDERER_COMPOSITOR_COMPONENT, 0, nullptr));
+ EXPECT_TRUE(metadata_latency_after1[0].FindLatency(
+ ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 0, nullptr));
+
+ // The second frame should have the default BeginFrame component and the
+ // component attached via LatencyInfoSwapPromise.
ui::LatencyInfo latency_info;
latency_info.set_trace_id(5);
latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0,
@@ -9726,17 +9989,82 @@ TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) {
new LatencyInfoSwapPromise(latency_info));
host_impl_->active_tree()->QueuePinnedSwapPromise(std::move(swap_promise));
- gfx::Rect full_frame_damage(host_impl_->DeviceViewport().size());
- TestFrameData frame;
- EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
- EXPECT_TRUE(host_impl_->DrawLayers(&frame));
- host_impl_->DidDrawAllLayers(frame);
+ TestFrameData frame2;
+ host_impl_->SetFullViewportDamage();
+ host_impl_->SetNeedsRedraw();
+ EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame2));
+ EXPECT_TRUE(host_impl_->DrawLayers(&frame2));
+ host_impl_->DidDrawAllLayers(frame2);
+
+ const std::vector<ui::LatencyInfo>& metadata_latency_after2 =
+ fake_layer_tree_frame_sink->last_sent_frame()->metadata.latency_info;
+ EXPECT_EQ(2u, metadata_latency_after2.size());
+ EXPECT_TRUE(metadata_latency_after2[0].FindLatency(
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, nullptr));
+ EXPECT_TRUE(metadata_latency_after2[1].FindLatency(
+ ui::LATENCY_BEGIN_FRAME_RENDERER_COMPOSITOR_COMPONENT, 0, nullptr));
+
+ // Renderer should also record INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT.
+ EXPECT_TRUE(metadata_latency_after2[0].FindLatency(
+ ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 0, nullptr));
+ EXPECT_TRUE(metadata_latency_after2[1].FindLatency(
+ ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 0, nullptr));
+}
+
+// Make sure LatencyInfo are passed in viz::CompositorFrameMetadata properly in
+// the UI. This includes components added by LatencyInfoSwapPromise and
+// the default LATENCY_BEGIN_FRAME_UI_COMPOSITOR_COMPONENT.
+using LayerTreeHostImplLatencyInfoUITest =
+ LayerTreeHostImplLatencyInfoTest<true>;
+TEST_F(LayerTreeHostImplLatencyInfoUITest,
+ LatencyInfoPassedToCompositorFrameMetadataUI) {
+ auto* fake_layer_tree_frame_sink =
+ static_cast<FakeLayerTreeFrameSink*>(host_impl_->layer_tree_frame_sink());
+
+ // The first frame should only have the default BeginFrame component.
+ TestFrameData frame1;
+ EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame1));
+ EXPECT_TRUE(host_impl_->DrawLayers(&frame1));
+ host_impl_->DidDrawAllLayers(frame1);
- const std::vector<ui::LatencyInfo>& metadata_latency_after =
+ const std::vector<ui::LatencyInfo>& metadata_latency_after1 =
fake_layer_tree_frame_sink->last_sent_frame()->metadata.latency_info;
- EXPECT_EQ(1u, metadata_latency_after.size());
- EXPECT_TRUE(metadata_latency_after[0].FindLatency(
+ EXPECT_EQ(1u, metadata_latency_after1.size());
+ EXPECT_TRUE(metadata_latency_after1[0].FindLatency(
+ ui::LATENCY_BEGIN_FRAME_UI_COMPOSITOR_COMPONENT, 0, nullptr));
+ EXPECT_FALSE(metadata_latency_after1[0].FindLatency(
+ ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 0, nullptr));
+
+ // The second frame should have the default BeginFrame component and the
+ // component attached via LatencyInfoSwapPromise.
+ ui::LatencyInfo latency_info;
+ latency_info.set_trace_id(5);
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0,
+ 0);
+ std::unique_ptr<SwapPromise> swap_promise(
+ new LatencyInfoSwapPromise(latency_info));
+ host_impl_->active_tree()->QueuePinnedSwapPromise(std::move(swap_promise));
+
+ TestFrameData frame2;
+ host_impl_->SetFullViewportDamage();
+ host_impl_->SetNeedsRedraw();
+ EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame2));
+ EXPECT_TRUE(host_impl_->DrawLayers(&frame2));
+ host_impl_->DidDrawAllLayers(frame2);
+
+ const std::vector<ui::LatencyInfo>& metadata_latency_after2 =
+ fake_layer_tree_frame_sink->last_sent_frame()->metadata.latency_info;
+ EXPECT_EQ(2u, metadata_latency_after2.size());
+ EXPECT_TRUE(metadata_latency_after2[0].FindLatency(
ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, nullptr));
+ EXPECT_TRUE(metadata_latency_after2[1].FindLatency(
+ ui::LATENCY_BEGIN_FRAME_UI_COMPOSITOR_COMPONENT, 0, nullptr));
+
+ // UI should not record INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT.
+ EXPECT_FALSE(metadata_latency_after2[0].FindLatency(
+ ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 0, nullptr));
+ EXPECT_FALSE(metadata_latency_after2[1].FindLatency(
+ ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 0, nullptr));
}
TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToCompositorFrameMetadata) {
@@ -9852,7 +10180,7 @@ class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
set_needs_redraw_count_(set_needs_redraw_count),
forward_to_main_count_(forward_to_main_count) {}
- ~SimpleSwapPromiseMonitor() override {}
+ ~SimpleSwapPromiseMonitor() override = default;
void OnSetNeedsCommitOnMain() override { (*set_needs_commit_count_)++; }
@@ -12220,24 +12548,22 @@ TEST_F(LayerTreeHostImplTest, WheelScrollWithPageScaleFactorOnInnerLayer) {
class LayerTreeHostImplCountingLostSurfaces : public LayerTreeHostImplTest {
public:
- LayerTreeHostImplCountingLostSurfaces() : num_lost_surfaces_(0) {}
void DidLoseLayerTreeFrameSinkOnImplThread() override {
num_lost_surfaces_++;
}
protected:
- int num_lost_surfaces_;
+ int num_lost_surfaces_ = 0;
};
+// We do not want to reset context recovery state when we get repeated context
+// loss notifications via different paths.
TEST_F(LayerTreeHostImplCountingLostSurfaces, TwiceLostSurface) {
- // Really we just need at least one client notification each time
- // we go from having a valid output surface to not having a valid output
- // surface.
EXPECT_EQ(0, num_lost_surfaces_);
host_impl_->DidLoseLayerTreeFrameSink();
EXPECT_EQ(1, num_lost_surfaces_);
host_impl_->DidLoseLayerTreeFrameSink();
- EXPECT_LE(1, num_lost_surfaces_);
+ EXPECT_EQ(1, num_lost_surfaces_);
}
size_t CountRenderPassesWithId(const viz::RenderPassList& list,
diff --git a/chromium/cc/trees/layer_tree_host_perftest.cc b/chromium/cc/trees/layer_tree_host_perftest.cc
index 50fb41df3c1..00a4779e28e 100644
--- a/chromium/cc/trees/layer_tree_host_perftest.cc
+++ b/chromium/cc/trees/layer_tree_host_perftest.cc
@@ -51,7 +51,8 @@ class LayerTreeHostPerfTest : public LayerTreeTest {
const viz::RendererSettings& renderer_settings,
double refresh_rate,
scoped_refptr<viz::ContextProvider> compositor_context_provider,
- scoped_refptr<viz::ContextProvider> worker_context_provider) override {
+ scoped_refptr<viz::RasterContextProvider> worker_context_provider)
+ override {
constexpr bool disable_display_vsync = true;
bool synchronous_composite =
!HasImplThread() &&
@@ -253,7 +254,8 @@ class ScrollingLayerTreePerfTest : public LayerTreeHostPerfTestJsonReader {
ASSERT_TRUE(scrollable_.get());
}
- void UpdateLayerTreeHost() override {
+ void UpdateLayerTreeHost(
+ LayerTreeHostClient::VisualStateUpdate requested_update) override {
if (TestEnded())
return;
static const gfx::Vector2d delta = gfx::Vector2d(0, 10);
@@ -321,7 +323,7 @@ class BrowserCompositorInvalidateLayerTreePerfTest
&BrowserCompositorInvalidateLayerTreePerfTest::ReleaseMailbox,
base::Unretained(this)));
- gpu::SyncToken next_sync_token(gpu::CommandBufferNamespace::GPU_IO, 0,
+ gpu::SyncToken next_sync_token(gpu::CommandBufferNamespace::GPU_IO,
gpu::CommandBufferId::FromUnsafeValue(1),
next_fence_sync_);
next_sync_token.SetVerifyFlush();
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc b/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc
index b6769a03e2a..6fffa7d88c6 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc
@@ -73,7 +73,8 @@ class LayerTreeHostBlendingPixelTest : public LayerTreeHostPixelResourceTest {
const viz::RendererSettings& renderer_settings,
double refresh_rate,
scoped_refptr<viz::ContextProvider> compositor_context_provider,
- scoped_refptr<viz::ContextProvider> worker_context_provider) override {
+ scoped_refptr<viz::RasterContextProvider> worker_context_provider)
+ override {
viz::RendererSettings modified_renderer_settings = renderer_settings;
modified_renderer_settings.force_antialiasing = force_antialiasing_;
modified_renderer_settings.force_blending_with_shaders =
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc
index de2ebdf02a1..23034639f72 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc
@@ -25,14 +25,14 @@
namespace cc {
namespace {
-typedef ParameterizedPixelResourceTest LayerTreeHostMasksPixelTest;
+using LayerTreeHostMasksPixelTest = ParameterizedPixelResourceTest;
INSTANTIATE_PIXEL_RESOURCE_TEST_CASE_P(LayerTreeHostMasksPixelTest);
class MaskContentLayerClient : public ContentLayerClient {
public:
explicit MaskContentLayerClient(const gfx::Size& bounds) : bounds_(bounds) {}
- ~MaskContentLayerClient() override {}
+ ~MaskContentLayerClient() override = default;
bool FillsBoundsCompletely() const override { return false; }
size_t GetApproximateUnsharedMemoryUsage() const override { return 0; }
@@ -181,7 +181,7 @@ class CheckerContentLayerClient : public ContentLayerClient {
SkColor color,
bool vertical)
: bounds_(bounds), color_(color), vertical_(vertical) {}
- ~CheckerContentLayerClient() override {}
+ ~CheckerContentLayerClient() override = default;
bool FillsBoundsCompletely() const override { return false; }
size_t GetApproximateUnsharedMemoryUsage() const override { return 0; }
gfx::Rect PaintableRegion() override { return gfx::Rect(bounds_); }
@@ -230,7 +230,7 @@ class CircleContentLayerClient : public ContentLayerClient {
public:
explicit CircleContentLayerClient(const gfx::Size& bounds)
: bounds_(bounds) {}
- ~CircleContentLayerClient() override {}
+ ~CircleContentLayerClient() override = default;
bool FillsBoundsCompletely() const override { return false; }
size_t GetApproximateUnsharedMemoryUsage() const override { return 0; }
gfx::Rect PaintableRegion() override { return gfx::Rect(bounds_); }
@@ -393,7 +393,7 @@ class StaticPictureLayer : private ContentLayerClient, public PictureLayer {
protected:
explicit StaticPictureLayer(scoped_refptr<DisplayItemList> display_list)
: PictureLayer(this), display_list_(std::move(display_list)) {}
- ~StaticPictureLayer() override {}
+ ~StaticPictureLayer() override = default;
private:
scoped_refptr<DisplayItemList> display_list_;
@@ -504,7 +504,8 @@ class LayerTreeHostMaskAsBlendingPixelTest
const viz::RendererSettings& renderer_settings,
double refresh_rate,
scoped_refptr<viz::ContextProvider> compositor_context_provider,
- scoped_refptr<viz::ContextProvider> worker_context_provider) override {
+ scoped_refptr<viz::RasterContextProvider> worker_context_provider)
+ override {
viz::RendererSettings modified_renderer_settings = renderer_settings;
modified_renderer_settings.force_antialiasing = use_antialiasing_;
modified_renderer_settings.force_blending_with_shaders = force_shaders_;
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc b/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc
index 27784afc7cb..c25cd6d79f3 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc
@@ -568,7 +568,8 @@ class LayerTreeHostReadbackColorSpacePixelTest
const viz::RendererSettings& renderer_settings,
double refresh_rate,
scoped_refptr<viz::ContextProvider> compositor_context_provider,
- scoped_refptr<viz::ContextProvider> worker_context_provider) override {
+ scoped_refptr<viz::RasterContextProvider> worker_context_provider)
+ override {
std::unique_ptr<viz::TestLayerTreeFrameSink> frame_sink =
LayerTreePixelTest::CreateLayerTreeFrameSink(
renderer_settings, refresh_rate, compositor_context_provider,
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc b/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc
index 8f21cb8fe2f..7156d699a1e 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc
@@ -12,7 +12,7 @@
#include "cc/test/layer_tree_pixel_test.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/test/test_layer_tree_frame_sink.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/client/raster_interface.h"
#if !defined(OS_ANDROID)
@@ -177,13 +177,13 @@ class LayerTreeHostTilesTestPartialInvalidation
void WillPrepareTilesOnThread(LayerTreeHostImpl* host_impl) override {
// Issue a GL finish before preparing tiles to ensure resources become
// available for use in a timely manner. Needed for the one-copy path.
- viz::ContextProvider* context_provider =
+ viz::RasterContextProvider* context_provider =
host_impl->layer_tree_frame_sink()->worker_context_provider();
if (!context_provider)
return;
- viz::ContextProvider::ScopedContextLock lock(context_provider);
- lock.ContextGL()->Finish();
+ viz::RasterContextProvider::ScopedRasterContextLock lock(context_provider);
+ lock.RasterInterface()->Finish();
}
protected:
diff --git a/chromium/cc/trees/layer_tree_host_unittest.cc b/chromium/cc/trees/layer_tree_host_unittest.cc
index 1e34e6d8ffb..94e20f1d7bd 100644
--- a/chromium/cc/trees/layer_tree_host_unittest.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest.cc
@@ -117,7 +117,8 @@ class LayerTreeHostTestSetNeedsCommitInsideLayout : public LayerTreeHostTest {
protected:
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
- void UpdateLayerTreeHost() override {
+ void UpdateLayerTreeHost(
+ LayerTreeHostClient::VisualStateUpdate requested_update) override {
// This shouldn't cause a second commit to happen.
layer_tree_host()->SetNeedsCommit();
}
@@ -163,7 +164,8 @@ class LayerTreeHostTestFrameOrdering : public LayerTreeHostTest {
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
- void UpdateLayerTreeHost() override {
+ void UpdateLayerTreeHost(
+ LayerTreeHostClient::VisualStateUpdate requested_update) override {
EXPECT_TRUE(CheckStep(MAIN_LAYOUT, &main_));
}
@@ -211,7 +213,8 @@ class LayerTreeHostTestSetNeedsUpdateInsideLayout : public LayerTreeHostTest {
protected:
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
- void UpdateLayerTreeHost() override {
+ void UpdateLayerTreeHost(
+ LayerTreeHostClient::VisualStateUpdate requested_update) override {
// This shouldn't cause a second commit to happen.
layer_tree_host()->SetNeedsUpdateLayers();
}
@@ -452,7 +455,8 @@ class LayerTreeHostContextCacheTest : public LayerTreeHostTest {
const viz::RendererSettings& renderer_settings,
double refresh_rate,
scoped_refptr<viz::ContextProvider> compositor_context_provider,
- scoped_refptr<viz::ContextProvider> worker_context_provider) override {
+ scoped_refptr<viz::RasterContextProvider> worker_context_provider)
+ override {
// Create the main viz::ContextProvider with a MockContextSupport.
auto main_support = std::make_unique<MockContextSupport>();
mock_main_context_support_ = main_support.get();
@@ -487,7 +491,7 @@ class LayerTreeHostContextCacheTest : public LayerTreeHostTest {
protected:
class MockContextSupport : public TestContextSupport {
public:
- MockContextSupport() {}
+ MockContextSupport() = default;
MOCK_METHOD1(SetAggressivelyFreeResources,
void(bool aggressively_free_resources));
};
@@ -2407,7 +2411,7 @@ SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestUndrawnLayersDamageLater);
// its damage is preserved until the next time it is drawn.
class LayerTreeHostTestDamageWithScale : public LayerTreeHostTest {
public:
- LayerTreeHostTestDamageWithScale() {}
+ LayerTreeHostTestDamageWithScale() = default;
void SetupTree() override {
client_.set_fill_with_nonsolid_color(true);
@@ -2512,7 +2516,7 @@ SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestDamageWithScale);
// to the impl side.
class LayerTreeHostTestCommit : public LayerTreeHostTest {
public:
- LayerTreeHostTestCommit() {}
+ LayerTreeHostTestCommit() = default;
void BeginTest() override {
layer_tree_host()->SetViewportSize(gfx::Size(20, 20));
@@ -2661,7 +2665,7 @@ SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestFrameTimeUpdatesAfterDraw);
// from LayerTreeHost to LayerTreeHostImpl in the MT compositor.
class LayerTreeHostTestStartPageScaleAnimation : public LayerTreeHostTest {
public:
- LayerTreeHostTestStartPageScaleAnimation() {}
+ LayerTreeHostTestStartPageScaleAnimation() = default;
void SetupTree() override {
LayerTreeHostTest::SetupTree();
@@ -2828,7 +2832,7 @@ MULTI_THREAD_TEST_F(LayerTreeHostTestSetVisible);
class LayerTreeHostTestDeviceScaleFactorScalesViewportAndLayers
: public LayerTreeHostTest {
public:
- LayerTreeHostTestDeviceScaleFactorScalesViewportAndLayers() {}
+ LayerTreeHostTestDeviceScaleFactorScalesViewportAndLayers() = default;
void BeginTest() override {
client_.set_fill_with_nonsolid_color(true);
@@ -3066,7 +3070,7 @@ class LayerTreeHostInvalidLocalSurfaceIdDefersCommit
bool IsCommitAllowed() const override { return local_surface_id_.is_valid(); }
private:
- viz::LocalSurfaceIdAllocator allocator_;
+ viz::ParentLocalSurfaceIdAllocator allocator_;
viz::LocalSurfaceId local_surface_id_;
};
@@ -3160,17 +3164,183 @@ class LayerTreeHostTestDeferCommitsInsideBeginMainFrameWithCommitAfter
void AfterTest() override {
EXPECT_EQ(1, commit_count_);
EXPECT_EQ(2, begin_main_frame_count_);
+ // The commit should not have been aborted.
+ EXPECT_EQ(1, ready_to_commit_count_);
+ }
+
+ void ReadyToCommitOnThread(LayerTreeHostImpl* host_impl) override {
+ ++ready_to_commit_count_;
}
private:
bool allow_commits_ = false;
int commit_count_ = 0;
int begin_main_frame_count_ = 0;
+ int ready_to_commit_count_ = 0;
};
SINGLE_AND_MULTI_THREAD_TEST_F(
LayerTreeHostTestDeferCommitsInsideBeginMainFrameWithCommitAfter);
+// This verifies that animate_only BeginFrames only run animation/layout
+// updates, i.e. abort commits after the animate stage and only request layer
+// tree updates for layout.
+//
+// The tests sends four Begin(Main)Frames in sequence: three animate_only
+// Begin(Main)Frames followed by a normal Begin(Main)Frame. The first three
+// should result in aborted commits, whereas the last one should complete the
+// previously aborted commits.
+//
+// Between BeginMainFrames 2 and 3, the client also requests a new commit
+// (SetNeedsCommit), but not between BeginMainFrames 1 and 2. In multi-threaded
+// mode, ProxyMain will run the animate pipeline stage only for BeginMainFrames
+// 1 and 3, as no new commit was requested between 1 and 2.
+//
+// The test uses the full-pipeline mode to ensure that each BeginFrame also
+// incurs a BeginMainFrame.
+class LayerTreeHostTestAnimateOnlyBeginFrames
+ : public LayerTreeHostTest,
+ public viz::ExternalBeginFrameSourceClient {
+ public:
+ LayerTreeHostTestAnimateOnlyBeginFrames()
+ : external_begin_frame_source_(this) {
+ UseBeginFrameSource(&external_begin_frame_source_);
+ }
+
+ void IssueBeginFrame(bool animate_only) {
+ ++begin_frame_count_;
+
+ last_begin_frame_time_ += viz::BeginFrameArgs::DefaultInterval();
+ uint64_t sequence_number = next_begin_frame_sequence_number_++;
+
+ auto args = viz::BeginFrameArgs::Create(
+ BEGINFRAME_FROM_HERE, viz::BeginFrameArgs::kManualSourceId,
+ sequence_number, last_begin_frame_time_,
+ last_begin_frame_time_ + viz::BeginFrameArgs::DefaultInterval(),
+ viz::BeginFrameArgs::DefaultInterval(), viz::BeginFrameArgs::NORMAL);
+ args.animate_only = animate_only;
+
+ external_begin_frame_source_.OnBeginFrame(args);
+ }
+
+ void PostIssueBeginFrame(bool animate_only) {
+ // Post a new task so that BeginFrame is not issued within same callstack.
+ ImplThreadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &LayerTreeHostTestAnimateOnlyBeginFrames::IssueBeginFrame,
+ base::Unretained(this), animate_only));
+ }
+
+ // viz::ExternalBeginFrameSourceClient implementation:
+ void OnNeedsBeginFrames(bool needs_begin_frames) override {
+ if (needs_begin_frames) {
+ EXPECT_EQ(0, begin_frame_count_);
+ // Send a first animation_only BeginFrame.
+ PostIssueBeginFrame(true);
+ }
+ }
+
+ // LayerTreeHostTest implementation:
+ void BeginTest() override {
+ PostSetNeedsCommitToMainThread();
+ // OnNeedsBeginFrames(true) will be called during tree initialization.
+ }
+
+ void WillBeginMainFrame() override { ++will_begin_main_frame_count_; }
+
+ void DidSendBeginMainFrameOnThread(LayerTreeHostImpl* host_impl) override {
+ ++sent_begin_main_frame_count_;
+ EXPECT_EQ(begin_frame_count_, sent_begin_main_frame_count_);
+ }
+
+ void DidFinishImplFrameOnThread(LayerTreeHostImpl* host_impl) override {
+ if (begin_frame_count_ < 3) {
+ if (begin_frame_count_ == 2) {
+ // Request another commit before sending the third BeginMainFrame.
+ PostSetNeedsCommitToMainThread();
+ }
+
+ // Send another animation_only BeginFrame.
+ PostIssueBeginFrame(true);
+ } else if (begin_frame_count_ == 3) {
+ PostIssueBeginFrame(false);
+ }
+ }
+
+ void UpdateLayerTreeHost(
+ LayerTreeHostClient::VisualStateUpdate requested_update) override {
+ ++update_layer_tree_host_count_;
+
+ if (begin_frame_count_ < 4) {
+ // First three BeginFrames are animate_only, so only kPrePaint updates are
+ // requested.
+ EXPECT_EQ(LayerTreeHostClient::VisualStateUpdate::kPrePaint,
+ requested_update);
+ } else {
+ EXPECT_EQ(4, begin_frame_count_);
+ // Last BeginFrame is normal, so all updates are requested.
+ EXPECT_EQ(LayerTreeHostClient::VisualStateUpdate::kAll, requested_update);
+ }
+ }
+
+ void DidCommit() override {
+ ++commit_count_;
+
+ // Fourth BeginMainFrame should lead to commit.
+ EXPECT_EQ(4, begin_frame_count_);
+ EXPECT_EQ(4, sent_begin_main_frame_count_);
+
+ EndTest();
+ }
+
+ void ReadyToCommitOnThread(LayerTreeHostImpl* host_impl) override {
+ ++ready_to_commit_count_;
+ }
+
+ void AfterTest() override {
+ EXPECT_EQ(1, commit_count_);
+ EXPECT_EQ(4, begin_frame_count_);
+ EXPECT_EQ(4, sent_begin_main_frame_count_);
+
+ if (HasImplThread()) {
+ // ProxyMain aborts the second BeginMainFrame before running the animate
+ // pipeline stage, since no further updates were made since the first one.
+ // Thus, we expect not to be called for the second BeginMainFrame.
+ EXPECT_EQ(3, will_begin_main_frame_count_);
+ EXPECT_EQ(3, update_layer_tree_host_count_);
+ } else {
+ EXPECT_EQ(4, will_begin_main_frame_count_);
+ EXPECT_EQ(4, update_layer_tree_host_count_);
+ }
+
+ // The final commit should not have been aborted.
+ EXPECT_EQ(1, ready_to_commit_count_);
+ }
+
+ protected:
+ void InitializeSettings(LayerTreeSettings* settings) override {
+ // Use full-pipeline mode to make BeginFrame handling deterministic.
+ EXPECT_FALSE(settings->wait_for_all_pipeline_stages_before_draw);
+ settings->wait_for_all_pipeline_stages_before_draw = true;
+ }
+
+ private:
+ viz::ExternalBeginFrameSource external_begin_frame_source_;
+
+ base::TimeTicks last_begin_frame_time_ = base::TimeTicks::Now();
+ uint64_t next_begin_frame_sequence_number_ =
+ viz::BeginFrameArgs::kStartingFrameNumber;
+ int commit_count_ = 0;
+ int begin_frame_count_ = 0;
+ int sent_begin_main_frame_count_ = 0;
+ int will_begin_main_frame_count_ = 0;
+ int update_layer_tree_host_count_ = 0;
+ int ready_to_commit_count_ = 0;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestAnimateOnlyBeginFrames);
+
class LayerTreeHostTestCompositeImmediatelyStateTransitions
: public LayerTreeHostTest {
public:
@@ -3402,7 +3572,7 @@ class OnDrawLayerTreeFrameSink : public viz::TestLayerTreeFrameSink {
public:
OnDrawLayerTreeFrameSink(
scoped_refptr<viz::ContextProvider> compositor_context_provider,
- scoped_refptr<viz::ContextProvider> worker_context_provider,
+ scoped_refptr<viz::RasterContextProvider> worker_context_provider,
viz::SharedBitmapManager* shared_bitmap_manager,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
const viz::RendererSettings& renderer_settings,
@@ -3446,7 +3616,8 @@ class LayerTreeHostTestAbortedCommitDoesntStallSynchronousCompositor
const viz::RendererSettings& renderer_settings,
double refresh_rate,
scoped_refptr<viz::ContextProvider> compositor_context_provider,
- scoped_refptr<viz::ContextProvider> worker_context_provider) override {
+ scoped_refptr<viz::RasterContextProvider> worker_context_provider)
+ override {
auto on_draw_callback = base::Bind(
&LayerTreeHostTestAbortedCommitDoesntStallSynchronousCompositor::
CallOnDraw,
@@ -4918,7 +5089,8 @@ class TestSwapPromise : public SwapPromise {
result_->did_activate_called = true;
}
- void WillSwap(viz::CompositorFrameMetadata* metadata) override {
+ void WillSwap(viz::CompositorFrameMetadata* compositor_frame_metadata,
+ RenderFrameMetadata* render_frame_metadata) override {
base::AutoLock lock(result_->lock);
EXPECT_FALSE(result_->did_swap_called);
EXPECT_FALSE(result_->did_not_swap_called);
@@ -5089,7 +5261,7 @@ MULTI_THREAD_TEST_F(LayerTreeHostTestBreakSwapPromise);
class LayerTreeHostTestKeepSwapPromise : public LayerTreeHostTest {
public:
- LayerTreeHostTestKeepSwapPromise() {}
+ LayerTreeHostTestKeepSwapPromise() = default;
void BeginTest() override {
layer_ = SolidColorLayer::Create();
@@ -5181,7 +5353,7 @@ SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestKeepSwapPromise);
class LayerTreeHostTestKeepSwapPromiseMFBA : public LayerTreeHostTest {
public:
- LayerTreeHostTestKeepSwapPromiseMFBA() {}
+ LayerTreeHostTestKeepSwapPromiseMFBA() = default;
void InitializeSettings(LayerTreeSettings* settings) override {
settings->main_frame_before_activation_enabled = true;
@@ -5348,7 +5520,7 @@ class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
layer_tree_host_impl),
set_needs_commit_count_(set_needs_commit_count) {}
- ~SimpleSwapPromiseMonitor() override {}
+ ~SimpleSwapPromiseMonitor() override = default;
void OnSetNeedsCommitOnMain() override { (*set_needs_commit_count_)++; }
@@ -5366,7 +5538,7 @@ class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
class LayerTreeHostTestSwapPromiseDuringCommit : public LayerTreeHostTest {
protected:
- LayerTreeHostTestSwapPromiseDuringCommit() {}
+ LayerTreeHostTestSwapPromiseDuringCommit() = default;
void WillBeginMainFrame() override {
if (TestEnded())
@@ -5634,7 +5806,7 @@ class LayerTreeHostWithGpuRasterizationTest : public LayerTreeHostTest {
const viz::RendererSettings& renderer_settings,
double refresh_rate,
scoped_refptr<viz::ContextProvider> ignored_compositor_context_provider,
- scoped_refptr<viz::ContextProvider> ignored_worker_context_provider)
+ scoped_refptr<viz::RasterContextProvider> ignored_worker_context_provider)
override {
auto context_provider = TestContextProvider::Create();
context_provider->UnboundTestContext3d()->SetMaxSamples(4);
@@ -6171,7 +6343,8 @@ class LayerTreeHostTestSynchronousCompositeSwapPromise
const viz::RendererSettings& renderer_settings,
double refresh_rate,
scoped_refptr<viz::ContextProvider> compositor_context_provider,
- scoped_refptr<viz::ContextProvider> worker_context_provider) override {
+ scoped_refptr<viz::RasterContextProvider> worker_context_provider)
+ override {
constexpr bool disable_display_vsync = false;
bool synchronous_composite =
!HasImplThread() &&
@@ -6518,7 +6691,7 @@ MULTI_THREAD_TEST_F(LayerTreeHostTestCrispUpAfterPinchEndsWithOneCopy);
class RasterizeWithGpuRasterizationCreatesResources : public LayerTreeHostTest {
protected:
- RasterizeWithGpuRasterizationCreatesResources() {}
+ RasterizeWithGpuRasterizationCreatesResources() = default;
void InitializeSettings(LayerTreeSettings* settings) override {
settings->gpu_rasterization_forced = true;
@@ -6590,7 +6763,7 @@ class GpuRasterizationRasterizesBorderTiles : public LayerTreeHostTest {
DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
LayerTreeHostImpl::FrameData* frame_data,
DrawResult draw_result) override {
- EXPECT_EQ(10u, host_impl->resource_provider()->num_resources());
+ EXPECT_EQ(15u, host_impl->resource_provider()->num_resources());
EndTest();
return draw_result;
}
@@ -7596,7 +7769,7 @@ class LayerTreeHostTestLocalSurfaceId : public LayerTreeHostTest {
void AfterTest() override {}
viz::LocalSurfaceId expected_local_surface_id_;
- viz::LocalSurfaceIdAllocator allocator_;
+ viz::ParentLocalSurfaceIdAllocator allocator_;
};
SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestLocalSurfaceId);
diff --git a/chromium/cc/trees/layer_tree_host_unittest_animation.cc b/chromium/cc/trees/layer_tree_host_unittest_animation.cc
index 6beaed50ab5..8f695e36da8 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_animation.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_animation.cc
@@ -574,7 +574,8 @@ class LayerTreeHostAnimationTestForceRedraw
layer_tree_host()->SetNeedsAnimate();
}
- void UpdateLayerTreeHost() override {
+ void UpdateLayerTreeHost(
+ LayerTreeHostClient::VisualStateUpdate requested_update) override {
layer_tree_host()->SetNeedsCommitWithForcedRedraw();
}
@@ -779,7 +780,7 @@ SINGLE_AND_MULTI_THREAD_TEST_F(
class LayerTreeHostAnimationTestScrollOffsetAnimationTakeover
: public LayerTreeHostAnimationTest {
public:
- LayerTreeHostAnimationTestScrollOffsetAnimationTakeover() {}
+ LayerTreeHostAnimationTestScrollOffsetAnimationTakeover() = default;
void SetupTree() override {
LayerTreeHostAnimationTest::SetupTree();
@@ -839,7 +840,7 @@ MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestScrollOffsetAnimationTakeover);
class LayerTreeHostAnimationTestScrollOffsetAnimationAdjusted
: public LayerTreeHostAnimationTest {
public:
- LayerTreeHostAnimationTestScrollOffsetAnimationAdjusted() {}
+ LayerTreeHostAnimationTestScrollOffsetAnimationAdjusted() = default;
void SetupTree() override {
LayerTreeHostAnimationTest::SetupTree();
@@ -1879,7 +1880,8 @@ class LayerTreeHostAnimationTestSetPotentiallyAnimatingOnLacDestruction
void DidCommit() override { PostSetNeedsCommitToMainThread(); }
- void UpdateLayerTreeHost() override {
+ void UpdateLayerTreeHost(
+ LayerTreeHostClient::VisualStateUpdate requested_update) override {
if (layer_tree_host()->SourceFrameNumber() == 2) {
// Destroy player.
timeline_->DetachPlayer(player_.get());
@@ -1955,7 +1957,8 @@ class LayerTreeHostAnimationTestRebuildPropertyTreesOnAnimationSetNeedsCommit
PostSetNeedsCommitToMainThread();
}
- void UpdateLayerTreeHost() override {
+ void UpdateLayerTreeHost(
+ LayerTreeHostClient::VisualStateUpdate requested_update) override {
if (layer_tree_host()->SourceFrameNumber() == 1) {
EXPECT_FALSE(layer_tree_host()->property_trees()->needs_rebuild);
AddAnimatedTransformToPlayer(player_child_.get(), 1.0, 5, 5);
diff --git a/chromium/cc/trees/layer_tree_host_unittest_checkerimaging.cc b/chromium/cc/trees/layer_tree_host_unittest_checkerimaging.cc
index 3a96d3b3bad..f71c658c3fa 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_checkerimaging.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_checkerimaging.cc
@@ -8,18 +8,40 @@
#include "cc/test/layer_tree_test.h"
#include "cc/test/skia_common.h"
#include "cc/trees/layer_tree_impl.h"
+#include "components/ukm/test_ukm_recorder.h"
#include "components/viz/test/begin_frame_args_test.h"
#include "components/viz/test/fake_external_begin_frame_source.h"
#include "components/viz/test/test_layer_tree_frame_sink.h"
namespace cc {
namespace {
+const char kRenderingEvent[] = "Compositor.Rendering";
+const char kCheckerboardImagesMetric[] = "CheckerboardedImagesCount";
class LayerTreeHostCheckerImagingTest : public LayerTreeTest {
public:
- void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+ LayerTreeHostCheckerImagingTest() : url_(GURL("https://example.com")) {}
+
+ void BeginTest() override {
+ layer_tree_host()->SetURLForUkm(url_);
+ PostSetNeedsCommitToMainThread();
+ }
void AfterTest() override {}
+ void VerifyUkmAndEndTest(LayerTreeHostImpl* impl) {
+ // Change the URL to ensure any accumulated metrics are flushed.
+ impl->ukm_manager()->SetSourceURL(GURL("chrome://test2"));
+
+ auto* recorder = static_cast<ukm::TestUkmRecorder*>(
+ impl->ukm_manager()->recorder_for_testing());
+ const auto& entries = recorder->GetEntriesByName(kRenderingEvent);
+ ASSERT_EQ(1u, entries.size());
+ auto* entry = entries[0];
+ recorder->ExpectEntrySourceHasUrl(entry, url_);
+ recorder->ExpectEntryMetric(entry, kCheckerboardImagesMetric, 1);
+ EndTest();
+ }
+
void InitializeSettings(LayerTreeSettings* settings) override {
settings->enable_checker_imaging = true;
settings->min_image_bytes_to_checker = 512 * 1024;
@@ -50,6 +72,7 @@ class LayerTreeHostCheckerImagingTest : public LayerTreeTest {
private:
// Accessed only on the main thread.
FakeContentLayerClient content_layer_client_;
+ GURL url_;
};
class LayerTreeHostCheckerImagingTestMergeWithMainFrame
@@ -118,7 +141,7 @@ class LayerTreeHostCheckerImagingTestMergeWithMainFrame
expected_update_rect.Union(gfx::Rect(600, 0, 50, 500));
EXPECT_EQ(sync_layer_impl->update_rect(), expected_update_rect);
- EndTest();
+ VerifyUkmAndEndTest(host_impl);
} break;
default:
NOTREACHED();
@@ -182,8 +205,9 @@ class LayerTreeHostCheckerImagingTestImplSideTree
void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
num_of_activations_++;
- if (num_of_activations_ == 2)
- EndTest();
+ if (num_of_activations_ == 2) {
+ VerifyUkmAndEndTest(host_impl);
+ }
}
void AfterTest() override {
diff --git a/chromium/cc/trees/layer_tree_host_unittest_context.cc b/chromium/cc/trees/layer_tree_host_unittest_context.cc
index 72f1e49482f..e7f884a5739 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_context.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_context.cc
@@ -6,6 +6,7 @@
#include <stdint.h>
#include "base/memory/ptr_util.h"
+#include "build/build_config.h"
#include "cc/layers/heads_up_display_layer.h"
#include "cc/layers/layer_impl.h"
#include "cc/layers/painted_scrollbar_layer.h"
@@ -38,6 +39,7 @@
#include "components/viz/common/resources/single_release_callback.h"
#include "components/viz/test/test_layer_tree_frame_sink.h"
#include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/raster_interface.h"
#include "media/base/media.h"
using media::VideoFrame;
@@ -86,7 +88,8 @@ class LayerTreeHostContextTest : public LayerTreeTest {
const viz::RendererSettings& renderer_settings,
double refresh_rate,
scoped_refptr<viz::ContextProvider> compositor_context_provider,
- scoped_refptr<viz::ContextProvider> worker_context_provider) override {
+ scoped_refptr<viz::RasterContextProvider> worker_context_provider)
+ override {
base::AutoLock lock(context3d_lock_);
std::unique_ptr<TestWebGraphicsContext3D> compositor_context3d =
@@ -897,11 +900,8 @@ class LayerTreeHostContextTestDontUseLostResources
gpu::Mailbox mailbox;
gl->GenMailboxCHROMIUM(mailbox.name);
- const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM();
- gl->ShallowFlushCHROMIUM();
-
gpu::SyncToken sync_token;
- gl->GenSyncTokenCHROMIUM(fence_sync, sync_token.GetData());
+ gl->GenSyncTokenCHROMIUM(sync_token.GetData());
scoped_refptr<Layer> root = Layer::Create();
root->SetBounds(gfx::Size(10, 10));
@@ -1349,7 +1349,11 @@ class UIResourceLostBeforeCommit : public UIResourceLostTestSimple {
UIResourceId test_id1_;
};
-SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostBeforeCommit);
+// http://crbug.com/803532 : Flaky on Win 7 (dbg).
+#if defined(NDEBUG) || defined(OS_WIN)
+SINGLE_THREAD_TEST_F(UIResourceLostBeforeCommit);
+#endif
+MULTI_THREAD_TEST_F(UIResourceLostBeforeCommit);
// Losing UI resource before the pending trees is activated but after the
// commit. Impl-side-painting only.
@@ -1605,11 +1609,7 @@ class LayerTreeHostContextTestLoseAfterSendingBeginMainFrame
SINGLE_AND_MULTI_THREAD_TEST_F(
LayerTreeHostContextTestLoseAfterSendingBeginMainFrame);
-// This test causes context loss on the worker context but not the compositor
-// context and checks that draw still occurs. The resources might be in a bad
-// state e.g. null sync tokens but that shouldn't cause the draw to fail.
-class LayerTreeHostContextTestLoseWorkerContextDuringPrepareTiles
- : public LayerTreeTest {
+class LayerTreeHostContextTestWorkerContextLostRecovery : public LayerTreeTest {
protected:
void SetupTree() override {
PaintFlags flags;
@@ -1628,27 +1628,31 @@ class LayerTreeHostContextTestLoseWorkerContextDuringPrepareTiles
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
void WillPrepareTilesOnThread(LayerTreeHostImpl* host_impl) override {
- viz::ContextProvider::ScopedContextLock scoped_context(
+ if (did_lose_context)
+ return;
+ did_lose_context = true;
+ viz::RasterContextProvider::ScopedRasterContextLock scoped_context(
host_impl->layer_tree_frame_sink()->worker_context_provider());
- gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL();
- gl->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
+ gpu::raster::RasterInterface* ri = scoped_context.RasterInterface();
+ ri->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
GL_INNOCENT_CONTEXT_RESET_ARB);
}
- void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
- ++num_draws_;
- }
+ void DidInitializeLayerTreeFrameSink() override { num_frame_sinks_++; }
void DidCommitAndDrawFrame() override { EndTest(); }
- void AfterTest() override { EXPECT_EQ(1, num_draws_); }
+ void AfterTest() override {
+ EXPECT_TRUE(did_lose_context);
+ EXPECT_EQ(num_frame_sinks_, 2);
+ }
FakeContentLayerClient client_;
- int num_draws_ = 0;
+ bool did_lose_context = false;
+ int num_frame_sinks_ = 0;
};
-MULTI_THREAD_TEST_F(
- LayerTreeHostContextTestLoseWorkerContextDuringPrepareTiles);
+MULTI_THREAD_TEST_F(LayerTreeHostContextTestWorkerContextLostRecovery);
} // namespace
} // namespace cc
diff --git a/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc
index 4574bd8de12..786c0dd3a93 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc
@@ -481,7 +481,8 @@ class LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest
const viz::RendererSettings& renderer_settings,
double refresh_rate,
scoped_refptr<viz::ContextProvider> compositor_context_provider,
- scoped_refptr<viz::ContextProvider> worker_context_provider) override {
+ scoped_refptr<viz::RasterContextProvider> worker_context_provider)
+ override {
auto frame_sink = LayerTreeHostCopyRequestTest::CreateLayerTreeFrameSink(
renderer_settings, refresh_rate, std::move(compositor_context_provider),
std::move(worker_context_provider));
@@ -1052,9 +1053,7 @@ class LayerTreeHostCopyRequestTestProvideTexture
gpu::Mailbox mailbox;
gl->GenMailboxCHROMIUM(mailbox.name);
- const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM();
- gl->ShallowFlushCHROMIUM();
- gl->GenSyncTokenCHROMIUM(fence_sync, sync_token_.GetData());
+ gl->GenSyncTokenCHROMIUM(sync_token_.GetData());
request->SetMailbox(mailbox, sync_token_);
EXPECT_TRUE(request->has_mailbox());
diff --git a/chromium/cc/trees/layer_tree_host_unittest_proxy.cc b/chromium/cc/trees/layer_tree_host_unittest_proxy.cc
index 12e028347fd..9d207e792be 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_proxy.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_proxy.cc
@@ -37,8 +37,8 @@ class LayerTreeHostProxyTest : public LayerTreeTest {
class LayerTreeHostProxyTestSetNeedsCommit : public LayerTreeHostProxyTest {
protected:
- LayerTreeHostProxyTestSetNeedsCommit() {}
- ~LayerTreeHostProxyTestSetNeedsCommit() override {}
+ LayerTreeHostProxyTestSetNeedsCommit() = default;
+ ~LayerTreeHostProxyTestSetNeedsCommit() override = default;
void BeginTest() override {
EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
@@ -74,8 +74,8 @@ MULTI_THREAD_TEST_F(LayerTreeHostProxyTestSetNeedsCommit);
class LayerTreeHostProxyTestSetNeedsAnimate : public LayerTreeHostProxyTest {
protected:
- LayerTreeHostProxyTestSetNeedsAnimate() {}
- ~LayerTreeHostProxyTestSetNeedsAnimate() override {}
+ LayerTreeHostProxyTestSetNeedsAnimate() = default;
+ ~LayerTreeHostProxyTestSetNeedsAnimate() override = default;
void BeginTest() override {
EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
@@ -110,8 +110,8 @@ MULTI_THREAD_TEST_F(LayerTreeHostProxyTestSetNeedsAnimate);
class LayerTreeHostProxyTestSetNeedsUpdateLayers
: public LayerTreeHostProxyTest {
protected:
- LayerTreeHostProxyTestSetNeedsUpdateLayers() {}
- ~LayerTreeHostProxyTestSetNeedsUpdateLayers() override {}
+ LayerTreeHostProxyTestSetNeedsUpdateLayers() = default;
+ ~LayerTreeHostProxyTestSetNeedsUpdateLayers() override = default;
void BeginTest() override {
EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
@@ -146,8 +146,9 @@ MULTI_THREAD_TEST_F(LayerTreeHostProxyTestSetNeedsUpdateLayers);
class LayerTreeHostProxyTestSetNeedsUpdateLayersWhileAnimating
: public LayerTreeHostProxyTest {
protected:
- LayerTreeHostProxyTestSetNeedsUpdateLayersWhileAnimating() {}
- ~LayerTreeHostProxyTestSetNeedsUpdateLayersWhileAnimating() override {}
+ LayerTreeHostProxyTestSetNeedsUpdateLayersWhileAnimating() = default;
+ ~LayerTreeHostProxyTestSetNeedsUpdateLayersWhileAnimating() override =
+ default;
void BeginTest() override { proxy()->SetNeedsAnimate(); }
@@ -191,8 +192,8 @@ MULTI_THREAD_TEST_F(LayerTreeHostProxyTestSetNeedsUpdateLayersWhileAnimating);
class LayerTreeHostProxyTestSetNeedsCommitWhileAnimating
: public LayerTreeHostProxyTest {
protected:
- LayerTreeHostProxyTestSetNeedsCommitWhileAnimating() {}
- ~LayerTreeHostProxyTestSetNeedsCommitWhileAnimating() override {}
+ LayerTreeHostProxyTestSetNeedsCommitWhileAnimating() = default;
+ ~LayerTreeHostProxyTestSetNeedsCommitWhileAnimating() override = default;
void BeginTest() override { proxy()->SetNeedsAnimate(); }
diff --git a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc
index 8298948e1ce..8a6d4e252b8 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -105,7 +105,8 @@ class LayerTreeHostScrollTestScrollSimple : public LayerTreeHostScrollTest {
PostSetNeedsCommitToMainThread();
}
- void UpdateLayerTreeHost() override {
+ void UpdateLayerTreeHost(
+ LayerTreeHostClient::VisualStateUpdate requested_update) override {
Layer* scroll_layer = layer_tree_host()->outer_viewport_scroll_layer();
if (!layer_tree_host()->SourceFrameNumber()) {
EXPECT_VECTOR_EQ(initial_scroll_, scroll_layer->scroll_offset());
@@ -473,20 +474,22 @@ class LayerTreeHostScrollTestFractionalScroll : public LayerTreeHostScrollTest {
break;
case 1:
EXPECT_VECTOR_EQ(
- gfx::ToFlooredVector2d(scroll_amount_),
+ gfx::ToRoundedVector2d(scroll_amount_),
ScrollTreeForLayer(scroll_layer)
->GetScrollOffsetBaseForTesting(scroll_layer->element_id()));
- EXPECT_VECTOR_EQ(gfx::Vector2dF(fmod(scroll_amount_.x(), 1.0f), 0.0f),
- ScrollDelta(scroll_layer));
+ EXPECT_VECTOR_EQ(
+ scroll_amount_ - gfx::ToRoundedVector2d(scroll_amount_),
+ ScrollDelta(scroll_layer));
PostSetNeedsCommitToMainThread();
break;
case 2:
EXPECT_VECTOR_EQ(
- gfx::ToFlooredVector2d(scroll_amount_ + scroll_amount_),
+ gfx::ToRoundedVector2d(scroll_amount_ + scroll_amount_),
ScrollTreeForLayer(scroll_layer)
->GetScrollOffsetBaseForTesting(scroll_layer->element_id()));
EXPECT_VECTOR_EQ(
- gfx::Vector2dF(fmod(2.0f * scroll_amount_.x(), 1.0f), 0.0f),
+ scroll_amount_ + scroll_amount_ -
+ gfx::ToRoundedVector2d(scroll_amount_ + scroll_amount_),
ScrollDelta(scroll_layer));
EndTest();
break;
@@ -646,7 +649,8 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest {
num_scrolls_++;
}
- void UpdateLayerTreeHost() override {
+ void UpdateLayerTreeHost(
+ LayerTreeHostClient::VisualStateUpdate requested_update) override {
EXPECT_VECTOR_EQ(gfx::Vector2d(),
expected_no_scroll_layer_->scroll_offset());
@@ -849,7 +853,8 @@ class LayerTreeHostScrollTestSimple : public LayerTreeHostScrollTest {
PostSetNeedsCommitToMainThread();
}
- void UpdateLayerTreeHost() override {
+ void UpdateLayerTreeHost(
+ LayerTreeHostClient::VisualStateUpdate requested_update) override {
Layer* scroll_layer = layer_tree_host()->outer_viewport_scroll_layer();
if (!layer_tree_host()->SourceFrameNumber()) {
EXPECT_VECTOR_EQ(initial_scroll_, scroll_layer->scroll_offset());
@@ -1117,7 +1122,7 @@ MULTI_THREAD_TEST_F(LayerTreeHostScrollTestImplOnlyScroll);
class LayerTreeHostScrollTestScrollZeroMaxScrollOffset
: public LayerTreeHostScrollTest {
public:
- LayerTreeHostScrollTestScrollZeroMaxScrollOffset() {}
+ LayerTreeHostScrollTestScrollZeroMaxScrollOffset() = default;
void BeginTest() override {
outer_viewport_container_layer_id_ =
@@ -1125,7 +1130,8 @@ class LayerTreeHostScrollTestScrollZeroMaxScrollOffset
PostSetNeedsCommitToMainThread();
}
- void UpdateLayerTreeHost() override {
+ void UpdateLayerTreeHost(
+ LayerTreeHostClient::VisualStateUpdate requested_update) override {
Layer* root = layer_tree_host()->root_layer();
Layer* scroll_layer = layer_tree_host()->outer_viewport_scroll_layer();
switch (layer_tree_host()->SourceFrameNumber()) {
@@ -1190,7 +1196,7 @@ SINGLE_AND_MULTI_THREAD_TEST_F(
class LayerTreeHostScrollTestScrollNonDrawnLayer
: public LayerTreeHostScrollTest {
public:
- LayerTreeHostScrollTestScrollNonDrawnLayer() {}
+ LayerTreeHostScrollTestScrollNonDrawnLayer() = default;
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
@@ -1240,7 +1246,7 @@ SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostScrollTestScrollNonDrawnLayer);
class LayerTreeHostScrollTestImplScrollUnderMainThreadScrollingParent
: public LayerTreeHostScrollTest {
public:
- LayerTreeHostScrollTestImplScrollUnderMainThreadScrollingParent() {}
+ LayerTreeHostScrollTestImplScrollUnderMainThreadScrollingParent() = default;
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
@@ -1548,7 +1554,8 @@ class LayerTreeHostScrollTestScrollMFBA : public LayerTreeHostScrollTest {
num_commits_++;
}
- void UpdateLayerTreeHost() override {
+ void UpdateLayerTreeHost(
+ LayerTreeHostClient::VisualStateUpdate requested_update) override {
Layer* scroll_layer = layer_tree_host()->outer_viewport_scroll_layer();
switch (layer_tree_host()->SourceFrameNumber()) {
case 0:
@@ -1861,7 +1868,7 @@ MULTI_THREAD_TEST_F(LayerTreeHostScrollTestScrollAbortedCommitMFBA);
class MockInputHandlerClient : public InputHandlerClient {
public:
- MockInputHandlerClient() {}
+ MockInputHandlerClient() = default;
MOCK_METHOD0(ReconcileElasticOverscrollAndRootScroll, void());
@@ -2052,7 +2059,8 @@ class LayerTreeHostScrollTestPropertyTreeUpdate
PostSetNeedsCommitToMainThread();
}
- void UpdateLayerTreeHost() override {
+ void UpdateLayerTreeHost(
+ LayerTreeHostClient::VisualStateUpdate requested_update) override {
Layer* scroll_layer = layer_tree_host()->inner_viewport_scroll_layer();
if (layer_tree_host()->SourceFrameNumber() == 0) {
EXPECT_VECTOR_EQ(initial_scroll_, scroll_layer->scroll_offset());
diff --git a/chromium/cc/trees/layer_tree_impl.cc b/chromium/cc/trees/layer_tree_impl.cc
index 5026d387692..46b0ad514a9 100644
--- a/chromium/cc/trees/layer_tree_impl.cc
+++ b/chromium/cc/trees/layer_tree_impl.cc
@@ -298,15 +298,37 @@ void LayerTreeImpl::BuildLayerListForTesting() {
void LayerTreeImpl::InvalidateRegionForImages(
const PaintImageIdFlatSet& images_to_invalidate) {
+ TRACE_EVENT_BEGIN1("cc", "LayerTreeImpl::InvalidateRegionForImages",
+ "total_layer_count", picture_layers_.size());
DCHECK(IsSyncTree());
- if (images_to_invalidate.empty())
- return;
-
- // TODO(khushalsagar): It might be better to keep track of layers with images
- // and only iterate through those here.
- for (auto* picture_layer : picture_layers_)
- picture_layer->InvalidateRegionForImages(images_to_invalidate);
+ size_t no_images_count = 0;
+ size_t no_invalidation_count = 0;
+ size_t invalidated_count = 0;
+ if (!images_to_invalidate.empty()) {
+ // TODO(khushalsagar): It might be better to keep track of layers with
+ // images and only iterate through those here.
+ for (auto* picture_layer : picture_layers_) {
+ auto result =
+ picture_layer->InvalidateRegionForImages(images_to_invalidate);
+ switch (result) {
+ case PictureLayerImpl::ImageInvalidationResult::kNoImages:
+ ++no_images_count;
+ break;
+ case PictureLayerImpl::ImageInvalidationResult::kNoInvalidation:
+ ++no_invalidation_count;
+ break;
+ case PictureLayerImpl::ImageInvalidationResult::kInvalidated:
+ ++invalidated_count;
+ break;
+ }
+ }
+ }
+ TRACE_EVENT_END1(
+ "cc", "LayerTreeImpl::InvalidateRegionForImages", "counts",
+ base::StringPrintf("no_images[%zu] no_invalidaton[%zu] invalidated[%zu]",
+ no_images_count, no_invalidation_count,
+ invalidated_count));
}
bool LayerTreeImpl::IsRootLayer(const LayerImpl* layer) const {
@@ -368,6 +390,7 @@ void LayerTreeImpl::SetPropertyTrees(PropertyTrees* property_trees) {
}
void LayerTreeImpl::PushPropertyTreesTo(LayerTreeImpl* target_tree) {
+ TRACE_EVENT0("cc", "LayerTreeImpl::PushPropertyTreesTo");
// Property trees may store damage status. We preserve the active tree
// damage status by pushing the damage status from active tree property
// trees to pending tree property trees or by moving it onto the layers.
@@ -405,6 +428,7 @@ void LayerTreeImpl::PushSurfaceIdsTo(LayerTreeImpl* target_tree) {
}
void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) {
+ TRACE_EVENT0("cc", "LayerTreeImpl::PushPropertiesTo");
// The request queue should have been processed and does not require a push.
DCHECK_EQ(ui_resource_request_queue_.size(), 0u);
@@ -1561,11 +1585,13 @@ void LayerTreeImpl::AppendSwapPromises(
new_swap_promises.clear();
}
-void LayerTreeImpl::FinishSwapPromises(viz::CompositorFrameMetadata* metadata) {
+void LayerTreeImpl::FinishSwapPromises(
+ viz::CompositorFrameMetadata* compositor_frame_metadata,
+ RenderFrameMetadata* render_frame_metadata) {
for (const auto& swap_promise : swap_promise_list_)
- swap_promise->WillSwap(metadata);
+ swap_promise->WillSwap(compositor_frame_metadata, render_frame_metadata);
for (const auto& swap_promise : pinned_swap_promise_list_)
- swap_promise->WillSwap(metadata);
+ swap_promise->WillSwap(compositor_frame_metadata, render_frame_metadata);
}
void LayerTreeImpl::ClearSwapPromises() {
@@ -1878,6 +1904,7 @@ static void FindClosestMatchingLayer(const gfx::PointF& screen_space_point,
LayerImpl* root_layer,
const Functor& func,
FindClosestMatchingLayerState* state) {
+ base::ElapsedTimer timer;
// We want to iterate from front to back when hit testing.
for (auto* layer : base::Reversed(*root_layer->layer_tree_impl())) {
if (!func(layer))
@@ -1906,6 +1933,12 @@ static void FindClosestMatchingLayer(const gfx::PointF& screen_space_point,
state->closest_match = layer;
}
}
+ if (const char* client_name = GetClientNameForMetrics()) {
+ UMA_HISTOGRAM_COUNTS_1M(
+ base::StringPrintf("Compositing.%s.HitTestTimeToFindClosestLayer",
+ client_name),
+ timer.Elapsed().InMicroseconds());
+ }
}
struct FindScrollingLayerOrDrawnScrollbarFunctor {
@@ -2090,6 +2123,10 @@ void LayerTreeImpl::UpdateImageDecodingHints(
host_impl_->UpdateImageDecodingHints(std::move(decoding_mode_map));
}
+bool LayerTreeImpl::IsActivelyScrolling() const {
+ return host_impl_->IsActivelyScrolling();
+}
+
void LayerTreeImpl::SetPendingPageScaleAnimation(
std::unique_ptr<PendingPageScaleAnimation> pending_animation) {
pending_page_scale_animation_ = std::move(pending_animation);
diff --git a/chromium/cc/trees/layer_tree_impl.h b/chromium/cc/trees/layer_tree_impl.h
index bb1da0821f7..e3848ff54ac 100644
--- a/chromium/cc/trees/layer_tree_impl.h
+++ b/chromium/cc/trees/layer_tree_impl.h
@@ -48,6 +48,7 @@ class LayerTreeResourceProvider;
class LayerTreeSettings;
class MemoryHistory;
class PictureLayerImpl;
+class RenderFrameMetadata;
class TaskRunnerProvider;
class TileManager;
class UIResourceRequest;
@@ -141,6 +142,7 @@ class CC_EXPORT LayerTreeImpl {
void UpdateImageDecodingHints(
base::flat_map<PaintImage::Id, PaintImage::DecodingMode>
decoding_mode_map);
+ bool IsActivelyScrolling() const;
// Tree specific methods exposed to layer-impl tree.
// ---------------------------------------------------------------------------
@@ -442,7 +444,9 @@ class CC_EXPORT LayerTreeImpl {
std::vector<std::unique_ptr<SwapPromise>> new_swap_promises);
void AppendSwapPromises(
std::vector<std::unique_ptr<SwapPromise>> new_swap_promises);
- void FinishSwapPromises(viz::CompositorFrameMetadata* metadata);
+ void FinishSwapPromises(
+ viz::CompositorFrameMetadata* compositor_frame_metadata,
+ RenderFrameMetadata* render_frame_metadata);
void ClearSwapPromises();
void BreakSwapPromises(SwapPromise::DidNotSwapReason reason);
@@ -552,6 +556,11 @@ class CC_EXPORT LayerTreeImpl {
LayerTreeLifecycle& lifecycle() { return lifecycle_; }
+ bool request_presentation_time() const { return request_presentation_time_; }
+ void set_request_presentation_time(bool value) {
+ request_presentation_time_ = value;
+ }
+
protected:
float ClampPageScaleFactorToLimits(float page_scale_factor) const;
void PushPageScaleFactorAndLimits(const float* page_scale_factor,
@@ -674,7 +683,10 @@ class CC_EXPORT LayerTreeImpl {
// lifecycle states. See: |LayerTreeLifecycle|.
LayerTreeLifecycle lifecycle_;
- private:
+ // If true LayerTreeHostImpl requests a presentation token for the current
+ // frame.
+ bool request_presentation_time_ = false;
+
DISALLOW_COPY_AND_ASSIGN(LayerTreeImpl);
};
diff --git a/chromium/cc/trees/layer_tree_impl_unittest.cc b/chromium/cc/trees/layer_tree_impl_unittest.cc
index 2be267a902f..38029c53c35 100644
--- a/chromium/cc/trees/layer_tree_impl_unittest.cc
+++ b/chromium/cc/trees/layer_tree_impl_unittest.cc
@@ -2285,7 +2285,9 @@ class PersistentSwapPromise
~PersistentSwapPromise() override = default;
void DidActivate() override {}
- MOCK_METHOD1(WillSwap, void(viz::CompositorFrameMetadata* metadata));
+ MOCK_METHOD2(WillSwap,
+ void(viz::CompositorFrameMetadata* compositor_frame_metadata,
+ RenderFrameMetadata* render_frame_metadata));
MOCK_METHOD0(DidSwap, void());
DidNotSwapAction DidNotSwap(DidNotSwapReason reason) override {
@@ -2304,7 +2306,8 @@ class NotPersistentSwapPromise
~NotPersistentSwapPromise() override = default;
void DidActivate() override {}
- void WillSwap(viz::CompositorFrameMetadata* metadata) override {}
+ void WillSwap(viz::CompositorFrameMetadata* compositor_frame_metadata,
+ RenderFrameMetadata* render_frame_metadata) override {}
void DidSwap() override {}
DidNotSwapAction DidNotSwap(DidNotSwapReason reason) override {
@@ -2342,9 +2345,9 @@ TEST_F(LayerTreeImplTest, PersistentSwapPromisesAreKeptAlive) {
for (size_t i = 0; i < persistent_promises.size(); ++i) {
SCOPED_TRACE(testing::Message() << "While checking case #" << i);
ASSERT_TRUE(persistent_promises[i]);
- EXPECT_CALL(*persistent_promises[i], WillSwap(testing::_));
+ EXPECT_CALL(*persistent_promises[i], WillSwap(testing::_, testing::_));
}
- host_impl().active_tree()->FinishSwapPromises(nullptr);
+ host_impl().active_tree()->FinishSwapPromises(nullptr, nullptr);
}
TEST_F(LayerTreeImplTest, NotPersistentSwapPromisesAreDroppedWhenSwapFails) {
diff --git a/chromium/cc/trees/layer_tree_settings.h b/chromium/cc/trees/layer_tree_settings.h
index 47a798b5801..b82941432df 100644
--- a/chromium/cc/trees/layer_tree_settings.h
+++ b/chromium/cc/trees/layer_tree_settings.h
@@ -40,7 +40,6 @@ class CC_EXPORT LayerTreeSettings {
bool can_use_lcd_text = true;
bool use_distance_field_text = false;
bool gpu_rasterization_forced = false;
- bool async_worker_context_enabled = false;
int gpu_rasterization_msaa_sample_count = 0;
float gpu_rasterization_skewport_target_time_in_seconds = 0.2f;
bool create_low_res_tiling = false;
@@ -126,12 +125,6 @@ class CC_EXPORT LayerTreeSettings {
// deadlines.
bool wait_for_all_pipeline_stages_before_draw = false;
- // On a low-end android devices where the GPU memory is low, we are reducing
- // the tile width to half in the cases where the content width > screen width.
- // This doesn't impact CPU tile size, and we should see an obvious GPU memory
- // saving.
- bool use_half_width_tiles_for_gpu_rasterization = false;
-
// Whether layer tree commits should be made directly to the active
// tree on the impl thread. If |false| LayerTreeHostImpl creates a
// pending layer tree and produces that as the 'sync tree' with
diff --git a/chromium/cc/trees/occlusion.cc b/chromium/cc/trees/occlusion.cc
index e86a1a05e32..d0f5f1f5525 100644
--- a/chromium/cc/trees/occlusion.cc
+++ b/chromium/cc/trees/occlusion.cc
@@ -9,8 +9,7 @@
namespace cc {
-Occlusion::Occlusion() {
-}
+Occlusion::Occlusion() = default;
Occlusion::Occlusion(const gfx::Transform& draw_transform,
const SimpleEnclosedRegion& occlusion_from_outside_target,
diff --git a/chromium/cc/trees/occlusion_tracker.cc b/chromium/cc/trees/occlusion_tracker.cc
index 3b5e2aa91f2..906eab95421 100644
--- a/chromium/cc/trees/occlusion_tracker.cc
+++ b/chromium/cc/trees/occlusion_tracker.cc
@@ -23,8 +23,7 @@ OcclusionTracker::OcclusionTracker(const gfx::Rect& screen_space_clip_rect)
: screen_space_clip_rect_(screen_space_clip_rect) {
}
-OcclusionTracker::~OcclusionTracker() {
-}
+OcclusionTracker::~OcclusionTracker() = default;
Occlusion OcclusionTracker::GetCurrentOcclusionForLayer(
const gfx::Transform& draw_transform) const {
diff --git a/chromium/cc/trees/property_animation_state.cc b/chromium/cc/trees/property_animation_state.cc
index 92f4b99d851..b82efc75ec4 100644
--- a/chromium/cc/trees/property_animation_state.cc
+++ b/chromium/cc/trees/property_animation_state.cc
@@ -8,14 +8,12 @@
namespace cc {
-PropertyAnimationState::PropertyAnimationState() {}
+PropertyAnimationState::PropertyAnimationState() = default;
PropertyAnimationState::PropertyAnimationState(
- const PropertyAnimationState& rhs)
- : currently_running(rhs.currently_running),
- potentially_animating(rhs.potentially_animating) {}
+ const PropertyAnimationState& rhs) = default;
-PropertyAnimationState::~PropertyAnimationState() {}
+PropertyAnimationState::~PropertyAnimationState() = default;
bool PropertyAnimationState::operator==(
const PropertyAnimationState& other) const {
diff --git a/chromium/cc/trees/property_tree.cc b/chromium/cc/trees/property_tree.cc
index f09843aefaa..707c91dc147 100644
--- a/chromium/cc/trees/property_tree.cc
+++ b/chromium/cc/trees/property_tree.cc
@@ -37,7 +37,7 @@ PropertyTree<T>::PropertyTree()
// but due to a gcc bug the generated destructor will have wrong symbol
// visibility in component build.
template <typename T>
-PropertyTree<T>::~PropertyTree() {}
+PropertyTree<T>::~PropertyTree() = default;
template <typename T>
PropertyTree<T>& PropertyTree<T>::operator=(const PropertyTree<T>&) = default;
@@ -735,7 +735,7 @@ EffectTree::EffectTree() {
render_surfaces_.push_back(nullptr);
}
-EffectTree::~EffectTree() {}
+EffectTree::~EffectTree() = default;
int EffectTree::Insert(const EffectNode& tree_node, int parent_id) {
int node_id = PropertyTree<EffectNode>::Insert(tree_node, parent_id);
@@ -1160,7 +1160,7 @@ ScrollTree::ScrollTree()
: currently_scrolling_node_id_(kInvalidNodeId),
scroll_offset_map_(ScrollTree::ScrollOffsetMap()) {}
-ScrollTree::~ScrollTree() {}
+ScrollTree::~ScrollTree() = default;
ScrollTree& ScrollTree::operator=(const ScrollTree& from) {
PropertyTree::operator=(from);
@@ -1351,18 +1351,23 @@ const gfx::ScrollOffset ScrollTree::current_scroll_offset(ElementId id) const {
gfx::ScrollOffset ScrollTree::PullDeltaForMainThread(
SyncedScrollOffset* scroll_offset) {
- // TODO(miletus): Remove all this temporary flooring machinery when
- // Blink fully supports fractional scrolls.
+ DCHECK(property_trees()->is_active);
+ // TODO(flackr): We should pass the fractional scroll deltas when Blink fully
+ // supports fractional scrolls.
+ // TODO(flackr): We should ideally round the fractional scrolls in the same
+ // direction as the scroll will be snapped but for common cases this is
+ // equivalent to rounding to the nearest integer offset.
gfx::ScrollOffset current_offset =
- scroll_offset->Current(property_trees()->is_active);
- gfx::ScrollOffset current_delta = property_trees()->is_active
- ? scroll_offset->Delta()
- : scroll_offset->PendingDelta().get();
- gfx::ScrollOffset floored_delta(floor(current_delta.x()),
- floor(current_delta.y()));
- gfx::ScrollOffset diff_delta = floored_delta - current_delta;
- gfx::ScrollOffset tmp_offset = current_offset + diff_delta;
- scroll_offset->SetCurrent(tmp_offset);
+ scroll_offset->Current(/* is_active_tree */ true);
+ gfx::ScrollOffset rounded_offset =
+ gfx::ScrollOffset(roundf(current_offset.x()), roundf(current_offset.y()));
+ // The calculation of the difference from the rounded active base is to
+ // represent the integer delta that the main thread should know about.
+ gfx::ScrollOffset active_base = scroll_offset->ActiveBase();
+ gfx::ScrollOffset diff_active_base =
+ gfx::ScrollOffset(active_base.x() - roundf(active_base.x()),
+ active_base.y() - roundf(active_base.y()));
+ scroll_offset->SetCurrent(rounded_offset + diff_active_base);
gfx::ScrollOffset delta = scroll_offset->PullDeltaForMainThread();
scroll_offset->SetCurrent(current_offset);
return delta;
@@ -1587,7 +1592,7 @@ PropertyTreesCachedData::PropertyTreesCachedData()
animation_scales.clear();
}
-PropertyTreesCachedData::~PropertyTreesCachedData() {}
+PropertyTreesCachedData::~PropertyTreesCachedData() = default;
PropertyTrees::PropertyTrees()
: needs_rebuild(true),
@@ -1603,7 +1608,7 @@ PropertyTrees::PropertyTrees()
scroll_tree.SetPropertyTrees(this);
}
-PropertyTrees::~PropertyTrees() {}
+PropertyTrees::~PropertyTrees() = default;
bool PropertyTrees::operator==(const PropertyTrees& other) const {
return transform_tree == other.transform_tree &&
diff --git a/chromium/cc/trees/property_tree_builder.cc b/chromium/cc/trees/property_tree_builder.cc
index 432b5ee54eb..afc24f39167 100644
--- a/chromium/cc/trees/property_tree_builder.cc
+++ b/chromium/cc/trees/property_tree_builder.cc
@@ -151,11 +151,11 @@ static const LayerList& LayerChildren(Layer* layer) {
return layer->children();
}
-static LayerImpl* ChildAt(LayerImpl* layer, int index) {
+static LayerImpl* LayerChildAt(LayerImpl* layer, int index) {
return layer->test_properties()->children[index];
}
-static Layer* ChildAt(Layer* layer, int index) {
+static Layer* LayerChildAt(Layer* layer, int index) {
return layer->child_at(index);
}
@@ -279,11 +279,11 @@ static int GetScrollParentId(const DataForRecursion<LayerType>& data,
return id;
}
-static Layer* Parent(Layer* layer) {
+static Layer* LayerParent(Layer* layer) {
return layer->parent();
}
-static LayerImpl* Parent(LayerImpl* layer) {
+static LayerImpl* LayerParent(LayerImpl* layer) {
return layer->test_properties()->parent;
}
@@ -352,8 +352,8 @@ void PropertyTreeBuilderContext<LayerType>::AddClipNodeIfNeeded(
template <typename LayerType>
static inline bool IsAtBoundaryOf3dRenderingContext(LayerType* layer) {
- return Parent(layer)
- ? SortingContextId(Parent(layer)) != SortingContextId(layer)
+ return LayerParent(layer)
+ ? SortingContextId(LayerParent(layer)) != SortingContextId(layer)
: Is3dSorted(layer);
}
@@ -387,7 +387,7 @@ bool PropertyTreeBuilderContext<LayerType>::AddTransformNodeIfNeeded(
LayerType* layer,
bool created_render_surface,
DataForRecursion<LayerType>* data_for_children) const {
- const bool is_root = !Parent(layer);
+ const bool is_root = !LayerParent(layer);
const bool is_page_scale_layer = layer == page_scale_layer_;
const bool is_overscroll_elasticity_layer =
layer == overscroll_elasticity_layer_;
@@ -430,8 +430,8 @@ bool PropertyTreeBuilderContext<LayerType>::AddTransformNodeIfNeeded(
// we track both a parent TransformNode (which is the parent in the
// TransformTree) and a 'source' TransformNode (which is the TransformNode
// for the parent in the Layer tree).
- source_index = Parent(layer)->transform_tree_index();
- source_offset = Parent(layer)->offset_to_transform_parent();
+ source_index = LayerParent(layer)->transform_tree_index();
+ source_offset = LayerParent(layer)->offset_to_transform_parent();
}
if (IsContainerForFixedPositionLayers(layer) || is_root) {
@@ -441,7 +441,7 @@ bool PropertyTreeBuilderContext<LayerType>::AddTransformNodeIfNeeded(
DCHECK(Transform(layer).IsIdentity());
if (!is_root) {
data_for_children->transform_tree_parent_fixed =
- Parent(layer)->transform_tree_index();
+ LayerParent(layer)->transform_tree_index();
}
} else {
data_for_children->transform_tree_parent_fixed =
@@ -646,8 +646,9 @@ static inline bool ForceRenderSurface(LayerImpl* layer) {
template <typename LayerType>
static inline bool LayerIsInExisting3DRenderingContext(LayerType* layer) {
- return Is3dSorted(layer) && Parent(layer) && Is3dSorted(Parent(layer)) &&
- (SortingContextId(Parent(layer)) == SortingContextId(layer));
+ return Is3dSorted(layer) && LayerParent(layer) &&
+ Is3dSorted(LayerParent(layer)) &&
+ (SortingContextId(LayerParent(layer)) == SortingContextId(layer));
}
static inline bool IsRootForIsolatedGroup(Layer* layer) {
@@ -754,7 +755,7 @@ bool ShouldCreateRenderSurface(LayerType* layer,
bool animation_axis_aligned) {
const bool preserves_2d_axis_alignment =
current_transform.Preserves2dAxisAlignment() && animation_axis_aligned;
- const bool is_root = !Parent(layer);
+ const bool is_root = !LayerParent(layer);
if (is_root)
return true;
@@ -896,7 +897,7 @@ bool UpdateSubtreeHasCopyRequestRecursive(LayerType* layer) {
if (HasCopyRequest(layer))
subtree_has_copy_request = true;
for (size_t i = 0; i < LayerChildren(layer).size(); ++i) {
- LayerType* current_child = ChildAt(layer, i);
+ LayerType* current_child = LayerChildAt(layer, i);
subtree_has_copy_request |=
UpdateSubtreeHasCopyRequestRecursive(current_child);
}
@@ -909,7 +910,7 @@ bool PropertyTreeBuilderContext<LayerType>::AddEffectNodeIfNeeded(
const DataForRecursion<LayerType>& data_from_ancestor,
LayerType* layer,
DataForRecursion<LayerType>* data_for_children) const {
- const bool is_root = !Parent(layer);
+ const bool is_root = !LayerParent(layer);
const bool has_transparency = EffectiveOpacity(layer) != 1.f;
const bool has_potential_opacity_animation =
HasPotentialOpacityAnimation(layer);
@@ -1056,6 +1057,16 @@ static inline OverscrollBehavior GetOverscrollBehavior(LayerImpl* layer) {
return layer->test_properties()->overscroll_behavior;
}
+static inline const base::Optional<SnapContainerData>& GetSnapContainerData(
+ Layer* layer) {
+ return layer->snap_container_data();
+}
+
+static inline const base::Optional<SnapContainerData>& GetSnapContainerData(
+ LayerImpl* layer) {
+ return layer->test_properties()->snap_container_data;
+}
+
template <typename LayerType>
void SetHasTransformNode(LayerType* layer, bool val) {
layer->SetHasTransformNode(val);
@@ -1068,7 +1079,7 @@ void PropertyTreeBuilderContext<LayerType>::AddScrollNodeIfNeeded(
DataForRecursion<LayerType>* data_for_children) const {
int parent_id = GetScrollParentId(data_from_ancestor, layer);
- bool is_root = !Parent(layer);
+ bool is_root = !LayerParent(layer);
bool scrollable = layer->scrollable();
bool contains_non_fast_scrollable_region =
!layer->non_fast_scrollable_region().IsEmpty();
@@ -1114,6 +1125,7 @@ void PropertyTreeBuilderContext<LayerType>::AddScrollNodeIfNeeded(
node.element_id = layer->element_id();
node.transform_id = data_for_children->transform_tree_parent;
node.overscroll_behavior = GetOverscrollBehavior(layer);
+ node.snap_container_data = GetSnapContainerData(layer);
node_id = scroll_tree_.Insert(node, parent_id);
data_for_children->scroll_tree_parent = node_id;
@@ -1141,18 +1153,18 @@ template <typename LayerType>
void SetBackfaceVisibilityTransform(LayerType* layer,
bool created_transform_node) {
if (layer->use_parent_backface_visibility()) {
- DCHECK(Parent(layer));
- DCHECK(!Parent(layer)->use_parent_backface_visibility());
+ DCHECK(LayerParent(layer));
+ DCHECK(!LayerParent(layer)->use_parent_backface_visibility());
layer->SetShouldCheckBackfaceVisibility(
- Parent(layer)->should_check_backface_visibility());
+ LayerParent(layer)->should_check_backface_visibility());
} else {
// A double-sided layer's backface can been shown when its visible.
// In addition, we need to check if (1) there might be a local 3D transform
// on the layer that might turn it to the backface, or (2) it is not drawn
// into a flattened space.
layer->SetShouldCheckBackfaceVisibility(
- !DoubleSided(layer) &&
- (created_transform_node || !ShouldFlattenTransform(Parent(layer))));
+ !DoubleSided(layer) && (created_transform_node ||
+ !ShouldFlattenTransform(LayerParent(layer))));
}
}
@@ -1212,7 +1224,7 @@ void PropertyTreeBuilderContext<LayerType>::BuildPropertyTreesInternal(
!has_non_axis_aligned_clip;
for (size_t i = 0; i < LayerChildren(layer).size(); ++i) {
- LayerType* current_child = ChildAt(layer, i);
+ LayerType* current_child = LayerChildAt(layer, i);
SetLayerPropertyChangedForChild(layer, current_child);
if (!ScrollParent(current_child)) {
BuildPropertyTreesInternal(current_child, data_for_children);
@@ -1224,9 +1236,9 @@ void PropertyTreeBuilderContext<LayerType>::BuildPropertyTreesInternal(
it != scroll_children_range.second; ++it) {
LayerType* scroll_child = it->second;
DCHECK_EQ(ScrollParent(scroll_child), layer);
- DCHECK(Parent(scroll_child));
+ DCHECK(LayerParent(scroll_child));
data_for_children.effect_tree_parent =
- Parent(scroll_child)->effect_tree_index();
+ LayerParent(scroll_child)->effect_tree_index();
BuildPropertyTreesInternal(scroll_child, data_for_children);
}
diff --git a/chromium/cc/trees/proxy.h b/chromium/cc/trees/proxy.h
index c68bdb5645b..6b45bd6ea6a 100644
--- a/chromium/cc/trees/proxy.h
+++ b/chromium/cc/trees/proxy.h
@@ -78,6 +78,8 @@ class CC_EXPORT Proxy {
virtual bool MainFrameWillHappenForTesting() = 0;
virtual void SetURLForUkm(const GURL& url) = 0;
+
+ virtual void ClearHistoryOnNavigation() = 0;
};
} // namespace cc
diff --git a/chromium/cc/trees/proxy_common.cc b/chromium/cc/trees/proxy_common.cc
index ab9c87be5b6..f80fd3553fb 100644
--- a/chromium/cc/trees/proxy_common.cc
+++ b/chromium/cc/trees/proxy_common.cc
@@ -8,8 +8,8 @@
namespace cc {
-BeginMainFrameAndCommitState::BeginMainFrameAndCommitState() {}
+BeginMainFrameAndCommitState::BeginMainFrameAndCommitState() = default;
-BeginMainFrameAndCommitState::~BeginMainFrameAndCommitState() {}
+BeginMainFrameAndCommitState::~BeginMainFrameAndCommitState() = default;
} // namespace cc
diff --git a/chromium/cc/trees/proxy_impl.cc b/chromium/cc/trees/proxy_impl.cc
index 9608efc3484..2d0bff308f8 100644
--- a/chromium/cc/trees/proxy_impl.cc
+++ b/chromium/cc/trees/proxy_impl.cc
@@ -88,7 +88,7 @@ ProxyImpl::ProxyImpl(base::WeakPtr<ProxyMain> proxy_main_weak_ptr,
ProxyImpl::BlockedMainCommitOnly::BlockedMainCommitOnly()
: layer_tree_host(nullptr) {}
-ProxyImpl::BlockedMainCommitOnly::~BlockedMainCommitOnly() {}
+ProxyImpl::BlockedMainCommitOnly::~BlockedMainCommitOnly() = default;
ProxyImpl::~ProxyImpl() {
TRACE_EVENT0("cc", "ProxyImpl::~ProxyImpl");
@@ -262,10 +262,7 @@ NOINLINE void ProxyImpl::DumpForBeginMainFrameHang() {
host_impl_->tile_manager()->ActivationStateAsValueInto(state.get());
state->EndDictionary();
- char stack_string[50000] = "";
- base::debug::Alias(&stack_string);
- strncpy(stack_string, state->ToString().c_str(), arraysize(stack_string) - 1);
-
+ DEBUG_ALIAS_FOR_CSTR(stack_string, state->ToString().c_str(), 50000);
base::debug::DumpWithoutCrashing();
}
@@ -411,8 +408,11 @@ void ProxyImpl::RenewTreePriority() {
host_impl_->pinch_gesture_active() ||
host_impl_->page_scale_animation_active() ||
host_impl_->IsActivelyScrolling();
- host_impl_->ukm_manager()->SetUserInteractionInProgress(
- user_interaction_in_progress);
+
+ if (host_impl_->ukm_manager()) {
+ host_impl_->ukm_manager()->SetUserInteractionInProgress(
+ user_interaction_in_progress);
+ }
// Schedule expiration if smoothness currently takes priority.
if (user_interaction_in_progress)
@@ -501,6 +501,17 @@ void ProxyImpl::NotifyImageDecodeRequestFinished() {
SetNeedsCommitOnImplThread();
}
+void ProxyImpl::DidPresentCompositorFrameOnImplThread(
+ const std::vector<int>& source_frames,
+ base::TimeTicks time,
+ base::TimeDelta refresh,
+ uint32_t flags) {
+ MainThreadTaskRunner()->PostTask(
+ FROM_HERE, base::BindOnce(&ProxyMain::DidPresentCompositorFrame,
+ proxy_main_weak_ptr_, source_frames, time,
+ refresh, flags));
+}
+
void ProxyImpl::WillBeginImplFrame(const viz::BeginFrameArgs& args) {
DCHECK(IsImplThread());
host_impl_->WillBeginImplFrame(args);
@@ -728,7 +739,9 @@ base::SingleThreadTaskRunner* ProxyImpl::MainThreadTaskRunner() {
void ProxyImpl::SetURLForUkm(const GURL& url) {
DCHECK(IsImplThread());
- DCHECK(host_impl_->ukm_manager());
+ if (!host_impl_->ukm_manager())
+ return;
+
// The active tree might still be from content for the previous page when the
// recorder is updated here, since new content will be pushed with the next
// main frame. But we should only get a few impl frames wrong here in that
@@ -738,4 +751,10 @@ void ProxyImpl::SetURLForUkm(const GURL& url) {
host_impl_->ukm_manager()->SetSourceURL(url);
}
+void ProxyImpl::ClearHistoryOnNavigation() {
+ DCHECK(IsImplThread());
+ DCHECK(IsMainThreadBlocked());
+ scheduler_->ClearHistoryOnNavigation();
+}
+
} // namespace cc
diff --git a/chromium/cc/trees/proxy_impl.h b/chromium/cc/trees/proxy_impl.h
index 40700e56331..eb68d84c01e 100644
--- a/chromium/cc/trees/proxy_impl.h
+++ b/chromium/cc/trees/proxy_impl.h
@@ -54,6 +54,7 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient,
base::TimeTicks main_thread_start_time,
bool hold_commit_for_activation);
void SetURLForUkm(const GURL& url);
+ void ClearHistoryOnNavigation();
void MainFrameWillHappenOnImplForTesting(CompletionEvent* completion,
bool* main_frame_will_happen);
@@ -98,6 +99,11 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient,
void OnDrawForLayerTreeFrameSink(bool resourceless_software_draw) override;
void NeedsImplSideInvalidation(bool needs_first_draw_on_activation) override;
void NotifyImageDecodeRequestFinished() override;
+ void DidPresentCompositorFrameOnImplThread(
+ const std::vector<int>& source_frames,
+ base::TimeTicks time,
+ base::TimeDelta refresh,
+ uint32_t flags) override;
// SchedulerClient implementation
void WillBeginImplFrame(const viz::BeginFrameArgs& args) override;
diff --git a/chromium/cc/trees/proxy_main.cc b/chromium/cc/trees/proxy_main.cc
index 8245573bd43..98c2e46c611 100644
--- a/chromium/cc/trees/proxy_main.cc
+++ b/chromium/cc/trees/proxy_main.cc
@@ -14,6 +14,7 @@
#include "cc/base/devtools_instrumentation.h"
#include "cc/benchmarks/benchmark_instrumentation.h"
#include "cc/resources/ui_resource_manager.h"
+#include "cc/trees/latency_info_swap_promise.h"
#include "cc/trees/layer_tree_frame_sink.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/mutator_host.h"
@@ -32,6 +33,7 @@ ProxyMain::ProxyMain(LayerTreeHost* layer_tree_host,
max_requested_pipeline_stage_(NO_PIPELINE_STAGE),
current_pipeline_stage_(NO_PIPELINE_STAGE),
final_pipeline_stage_(NO_PIPELINE_STAGE),
+ deferred_final_pipeline_stage_(NO_PIPELINE_STAGE),
commit_waits_for_activation_(false),
started_(false),
defer_commits_(false),
@@ -120,21 +122,45 @@ void ProxyMain::DidCompletePageScaleAnimation() {
void ProxyMain::BeginMainFrame(
std::unique_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) {
+ DCHECK(IsMainThread());
+ DCHECK_EQ(NO_PIPELINE_STAGE, current_pipeline_stage_);
+
+ base::TimeTicks begin_main_frame_start_time = base::TimeTicks::Now();
+
benchmark_instrumentation::ScopedBeginFrameTask begin_frame_task(
benchmark_instrumentation::kDoBeginFrame,
begin_main_frame_state->begin_frame_id);
- base::TimeTicks begin_main_frame_start_time = base::TimeTicks::Now();
-
- DCHECK(IsMainThread());
- DCHECK_EQ(NO_PIPELINE_STAGE, current_pipeline_stage_);
+ // If the commit finishes, LayerTreeHost will transfer its swap promises to
+ // LayerTreeImpl. The destructor of ScopedSwapPromiseChecker aborts the
+ // remaining swap promises.
+ ScopedAbortRemainingSwapPromises swap_promise_checker(
+ layer_tree_host_->GetSwapPromiseManager());
// We need to issue image decode callbacks whether or not we will abort this
// commit, since the request ids are only stored in |begin_main_frame_state|.
layer_tree_host_->ImageDecodesFinished(
std::move(begin_main_frame_state->completed_image_decode_requests));
- if (defer_commits_) {
+ 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
+ // paint or commit our updates. We still need to run layout though, as it can
+ // have side effects on page loading behavior.
+ bool skip_paint_and_commit =
+ begin_main_frame_state->begin_frame_args.animate_only;
+
+ // If commits are deferred, skip the entire pipeline.
+ bool skip_full_pipeline = defer_commits_;
+
+ // 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_paint_and_commit && final_pipeline_stage_ == NO_PIPELINE_STAGE;
+
+ if (skip_full_pipeline) {
TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit",
TRACE_EVENT_SCOPE_THREAD);
std::vector<std::unique_ptr<SwapPromise>> empty_swap_promises;
@@ -144,17 +170,16 @@ void ProxyMain::BeginMainFrame(
CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT,
begin_main_frame_start_time,
base::Passed(&empty_swap_promises)));
+ // When we stop deferring commits, we should resume any previously requested
+ // pipeline stages.
+ deferred_final_pipeline_stage_ =
+ std::max(final_pipeline_stage_, deferred_final_pipeline_stage_);
return;
}
- // If the commit finishes, LayerTreeHost will transfer its swap promises to
- // LayerTreeImpl. The destructor of ScopedSwapPromiseChecker aborts the
- // remaining swap promises.
- ScopedAbortRemainingSwapPromises swap_promise_checker(
- layer_tree_host_->GetSwapPromiseManager());
-
- final_pipeline_stage_ = max_requested_pipeline_stage_;
- max_requested_pipeline_stage_ = NO_PIPELINE_STAGE;
+ final_pipeline_stage_ =
+ std::max(final_pipeline_stage_, deferred_final_pipeline_stage_);
+ deferred_final_pipeline_stage_ = NO_PIPELINE_STAGE;
if (!layer_tree_host_->IsVisible()) {
TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
@@ -195,11 +220,15 @@ void ProxyMain::BeginMainFrame(
// See LayerTreeHostClient::MainFrameUpdate for more documentation on
// what this does.
- layer_tree_host_->RequestMainFrameUpdate();
+ layer_tree_host_->RequestMainFrameUpdate(
+ skip_paint_and_commit ? LayerTreeHost::VisualStateUpdate::kPrePaint
+ : LayerTreeHost::VisualStateUpdate::kAll);
// At this point the main frame may have deferred commits to avoid committing
// right now.
- if (defer_commits_) {
+ skip_paint_and_commit |= defer_commits_;
+
+ if (skip_paint_and_commit) {
TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit_InsideBeginMainFrame",
TRACE_EVENT_SCOPE_THREAD);
std::vector<std::unique_ptr<SwapPromise>> empty_swap_promises;
@@ -213,6 +242,9 @@ void ProxyMain::BeginMainFrame(
// We intentionally don't report CommitComplete() here since it was aborted
// prematurely and we're waiting to do another commit in the future.
layer_tree_host_->DidBeginMainFrame();
+ // When we stop deferring commits, we should resume any previously requested
+ // pipeline stages.
+ deferred_final_pipeline_stage_ = final_pipeline_stage_;
return;
}
@@ -263,6 +295,16 @@ void ProxyMain::BeginMainFrame(
return;
}
+ // Queue the LATENCY_BEGIN_FRAME_RENDERER_MAIN_COMPONENT swap promise only
+ // once we know we will commit since QueueSwapPromise itself requests a
+ // commit.
+ ui::LatencyInfo new_latency_info(ui::SourceEventType::FRAME);
+ new_latency_info.AddLatencyNumberWithTimestamp(
+ ui::LATENCY_BEGIN_FRAME_RENDERER_MAIN_COMPONENT, 0, 0,
+ begin_main_frame_state->begin_frame_args.frame_time, 1);
+ layer_tree_host_->QueueSwapPromise(
+ std::make_unique<LatencyInfoSwapPromise>(new_latency_info));
+
// Notify the impl thread that the main thread is ready to commit. This will
// begin the commit process, which is blocking from the main thread's
// point of view, but asynchronously performed on the impl thread,
@@ -289,6 +331,14 @@ void ProxyMain::BeginMainFrame(
layer_tree_host_->DidBeginMainFrame();
}
+void ProxyMain::DidPresentCompositorFrame(const std::vector<int>& source_frames,
+ base::TimeTicks time,
+ base::TimeDelta refresh,
+ uint32_t flags) {
+ layer_tree_host_->DidPresentCompositorFrame(source_frames, time, refresh,
+ flags);
+}
+
bool ProxyMain::IsStarted() const {
DCHECK(IsMainThread());
return started_;
@@ -547,4 +597,11 @@ void ProxyMain::SetURLForUkm(const GURL& url) {
base::Unretained(proxy_impl_.get()), url));
}
+void ProxyMain::ClearHistoryOnNavigation() {
+ // Must only be called from the impl thread during commit.
+ DCHECK(task_runner_provider_->IsImplThread());
+ DCHECK(task_runner_provider_->IsMainThreadBlocked());
+ proxy_impl_->ClearHistoryOnNavigation();
+}
+
} // namespace cc
diff --git a/chromium/cc/trees/proxy_main.h b/chromium/cc/trees/proxy_main.h
index df5551149c2..911e2347e7e 100644
--- a/chromium/cc/trees/proxy_main.h
+++ b/chromium/cc/trees/proxy_main.h
@@ -51,6 +51,10 @@ class CC_EXPORT ProxyMain : public Proxy {
void DidCompletePageScaleAnimation();
void BeginMainFrame(
std::unique_ptr<BeginMainFrameAndCommitState> begin_main_frame_state);
+ void DidPresentCompositorFrame(const std::vector<int>& source_frames,
+ base::TimeTicks time,
+ base::TimeDelta refresh,
+ uint32_t flags);
CommitPipelineStage max_requested_pipeline_stage() const {
return max_requested_pipeline_stage_;
@@ -89,6 +93,7 @@ class CC_EXPORT ProxyMain : public Proxy {
bool animate) override;
void RequestBeginMainFrameNotExpected(bool new_state) override;
void SetURLForUkm(const GURL& url) override;
+ void ClearHistoryOnNavigation() override;
// Returns |true| if the request was actually sent, |false| if one was
// already outstanding.
@@ -116,6 +121,9 @@ class CC_EXPORT ProxyMain : public Proxy {
// will stop. Only valid while we are executing the pipeline (i.e.,
// |current_pipeline_stage| is set to a pipeline stage).
CommitPipelineStage final_pipeline_stage_;
+ // The final_pipeline_stage_ that was requested before the last commit was
+ // deferred.
+ CommitPipelineStage deferred_final_pipeline_stage_;
bool commit_waits_for_activation_;
diff --git a/chromium/cc/trees/render_frame_metadata.cc b/chromium/cc/trees/render_frame_metadata.cc
new file mode 100644
index 00000000000..191b28c48ed
--- /dev/null
+++ b/chromium/cc/trees/render_frame_metadata.cc
@@ -0,0 +1,24 @@
+// Copyright 2018 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/render_frame_metadata.h"
+
+namespace cc {
+
+RenderFrameMetadata::RenderFrameMetadata() = default;
+
+RenderFrameMetadata::RenderFrameMetadata(const RenderFrameMetadata& other) =
+ default;
+
+RenderFrameMetadata::RenderFrameMetadata(RenderFrameMetadata&& other) = default;
+
+RenderFrameMetadata::~RenderFrameMetadata() {}
+
+RenderFrameMetadata& RenderFrameMetadata::operator=(
+ const RenderFrameMetadata&) = default;
+
+RenderFrameMetadata& RenderFrameMetadata::operator=(
+ RenderFrameMetadata&& other) = default;
+
+} // namespace cc
diff --git a/chromium/cc/trees/render_frame_metadata.h b/chromium/cc/trees/render_frame_metadata.h
new file mode 100644
index 00000000000..a5653103105
--- /dev/null
+++ b/chromium/cc/trees/render_frame_metadata.h
@@ -0,0 +1,30 @@
+// Copyright 2018 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_RENDER_FRAME_METADATA_H_
+#define CC_TREES_RENDER_FRAME_METADATA_H_
+
+#include "cc/cc_export.h"
+#include "ui/gfx/geometry/vector2d_f.h"
+
+namespace cc {
+
+class CC_EXPORT RenderFrameMetadata {
+ public:
+ RenderFrameMetadata();
+ RenderFrameMetadata(const RenderFrameMetadata& other);
+ RenderFrameMetadata(RenderFrameMetadata&& other);
+ ~RenderFrameMetadata();
+
+ RenderFrameMetadata& operator=(const RenderFrameMetadata&);
+ RenderFrameMetadata& operator=(RenderFrameMetadata&& other);
+
+ // Scroll offset and scale of the root layer. This can be used for tasks
+ // like positioning windowed plugins.
+ gfx::Vector2dF root_scroll_offset;
+};
+
+} // namespace cc
+
+#endif // CC_TREES_RENDER_FRAME_METADATA_H_
diff --git a/chromium/cc/trees/scroll_node.cc b/chromium/cc/trees/scroll_node.cc
index 941330248b0..5e42feb8818 100644
--- a/chromium/cc/trees/scroll_node.cc
+++ b/chromium/cc/trees/scroll_node.cc
@@ -29,6 +29,8 @@ ScrollNode::ScrollNode()
ScrollNode::ScrollNode(const ScrollNode& other) = default;
+ScrollNode::~ScrollNode() = default;
+
bool ScrollNode::operator==(const ScrollNode& other) const {
return id == other.id && parent_id == other.parent_id &&
scrollable == other.scrollable &&
@@ -44,7 +46,8 @@ bool ScrollNode::operator==(const ScrollNode& other) const {
user_scrollable_horizontal == other.user_scrollable_horizontal &&
user_scrollable_vertical == other.user_scrollable_vertical &&
element_id == other.element_id && transform_id == other.transform_id &&
- overscroll_behavior == other.overscroll_behavior;
+ overscroll_behavior == other.overscroll_behavior &&
+ snap_container_data == other.snap_container_data;
}
void ScrollNode::AsValueInto(base::trace_event::TracedValue* value) const {
diff --git a/chromium/cc/trees/scroll_node.h b/chromium/cc/trees/scroll_node.h
index 370c097b738..16e5c03688d 100644
--- a/chromium/cc/trees/scroll_node.h
+++ b/chromium/cc/trees/scroll_node.h
@@ -8,6 +8,7 @@
#include "cc/base/region.h"
#include "cc/cc_export.h"
#include "cc/input/overscroll_behavior.h"
+#include "cc/input/scroll_snap_data.h"
#include "cc/paint/filter_operations.h"
#include "ui/gfx/geometry/size.h"
@@ -22,6 +23,7 @@ namespace cc {
struct CC_EXPORT ScrollNode {
ScrollNode();
ScrollNode(const ScrollNode& other);
+ ~ScrollNode();
// The node index of this node in the scroll tree node vector.
int id;
@@ -59,6 +61,8 @@ struct CC_EXPORT ScrollNode {
OverscrollBehavior overscroll_behavior;
+ base::Optional<SnapContainerData> snap_container_data;
+
bool operator==(const ScrollNode& other) const;
void AsValueInto(base::trace_event::TracedValue* value) const;
};
diff --git a/chromium/cc/trees/single_thread_proxy.cc b/chromium/cc/trees/single_thread_proxy.cc
index f5c49b175ee..d8dfc289cdd 100644
--- a/chromium/cc/trees/single_thread_proxy.cc
+++ b/chromium/cc/trees/single_thread_proxy.cc
@@ -13,6 +13,7 @@
#include "cc/scheduler/commit_earlyout_reason.h"
#include "cc/scheduler/compositor_timing_history.h"
#include "cc/scheduler/scheduler.h"
+#include "cc/trees/latency_info_swap_promise.h"
#include "cc/trees/layer_tree_frame_sink.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_host_common.h"
@@ -465,6 +466,15 @@ void SingleThreadProxy::NotifyImageDecodeRequestFinished() {
SetNeedsCommitOnImplThread();
}
+void SingleThreadProxy::DidPresentCompositorFrameOnImplThread(
+ const std::vector<int>& source_frames,
+ base::TimeTicks time,
+ base::TimeDelta refresh,
+ uint32_t flags) {
+ layer_tree_host_->DidPresentCompositorFrame(source_frames, time, refresh,
+ flags);
+}
+
void SingleThreadProxy::RequestBeginMainFrameNotExpected(bool new_state) {
if (scheduler_on_impl_thread_) {
scheduler_on_impl_thread_->SetMainThreadWantsBeginMainFrameNotExpected(
@@ -618,6 +628,12 @@ bool SingleThreadProxy::MainFrameWillHappenForTesting() {
return scheduler_on_impl_thread_->MainFrameForTestingWillHappen();
}
+void SingleThreadProxy::ClearHistoryOnNavigation() {
+ DCHECK(task_runner_provider_->IsImplThread());
+ if (scheduler_on_impl_thread_)
+ scheduler_on_impl_thread_->ClearHistoryOnNavigation();
+}
+
void SingleThreadProxy::WillBeginImplFrame(const viz::BeginFrameArgs& args) {
DebugScopedSetImplThread impl(task_runner_provider_);
#if DCHECK_IS_ON()
@@ -660,6 +676,11 @@ void SingleThreadProxy::ScheduledActionBeginMainFrameNotExpectedUntil(
void SingleThreadProxy::BeginMainFrame(
const viz::BeginFrameArgs& begin_frame_args) {
+ // This checker assumes NotifyReadyToCommit in this stack causes a synchronous
+ // commit.
+ ScopedAbortRemainingSwapPromises swap_promise_checker(
+ layer_tree_host_->GetSwapPromiseManager());
+
if (scheduler_on_impl_thread_) {
scheduler_on_impl_thread_->NotifyBeginMainFrameStarted(
base::TimeTicks::Now());
@@ -676,11 +697,6 @@ void SingleThreadProxy::BeginMainFrame(
return;
}
- // This checker assumes NotifyReadyToCommit in this stack causes a synchronous
- // commit.
- ScopedAbortRemainingSwapPromises swap_promise_checker(
- layer_tree_host_->GetSwapPromiseManager());
-
if (!layer_tree_host_->IsVisible()) {
TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
BeginMainFrameAbortedOnImplThread(
@@ -700,7 +716,7 @@ void SingleThreadProxy::BeginMainFrame(
// At this point the main frame may have deferred commits to avoid committing
// right now.
- if (defer_commits_) {
+ if (defer_commits_ || begin_frame_args.animate_only) {
TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit_InsideBeginMainFrame",
TRACE_EVENT_SCOPE_THREAD);
BeginMainFrameAbortedOnImplThread(
@@ -709,6 +725,15 @@ void SingleThreadProxy::BeginMainFrame(
return;
}
+ // Queue the LATENCY_BEGIN_FRAME_UI_MAIN_COMPONENT swap promise only once we
+ // know we will commit since QueueSwapPromise itself requests a commit.
+ ui::LatencyInfo new_latency_info(ui::SourceEventType::FRAME);
+ new_latency_info.AddLatencyNumberWithTimestamp(
+ ui::LATENCY_BEGIN_FRAME_UI_MAIN_COMPONENT, 0, 0,
+ begin_frame_args.frame_time, 1);
+ layer_tree_host_->QueueSwapPromise(
+ std::make_unique<LatencyInfoSwapPromise>(new_latency_info));
+
DoPainting();
}
@@ -725,7 +750,10 @@ void SingleThreadProxy::DoBeginMainFrame(
layer_tree_host_->WillBeginMainFrame();
layer_tree_host_->BeginMainFrame(begin_frame_args);
layer_tree_host_->AnimateLayers(begin_frame_args.frame_time);
- layer_tree_host_->RequestMainFrameUpdate();
+ layer_tree_host_->RequestMainFrameUpdate(
+ begin_frame_args.animate_only
+ ? LayerTreeHost::VisualStateUpdate::kPrePaint
+ : LayerTreeHost::VisualStateUpdate::kAll);
}
void SingleThreadProxy::DoPainting() {
diff --git a/chromium/cc/trees/single_thread_proxy.h b/chromium/cc/trees/single_thread_proxy.h
index cf14f1129de..ab2f2943702 100644
--- a/chromium/cc/trees/single_thread_proxy.h
+++ b/chromium/cc/trees/single_thread_proxy.h
@@ -62,6 +62,7 @@ class CC_EXPORT SingleThreadProxy : public Proxy,
// layout tests. This will still get called in the latter case, but we don't
// need to record UKM in that case.
}
+ void ClearHistoryOnNavigation() override;
// Blink layout tests might call into this even though an unthreaded CC
// doesn't have BrowserControls itself.
@@ -116,6 +117,11 @@ class CC_EXPORT SingleThreadProxy : public Proxy,
void NeedsImplSideInvalidation(bool needs_first_draw_on_activation) override;
void RequestBeginMainFrameNotExpected(bool new_state) override;
void NotifyImageDecodeRequestFinished() override;
+ void DidPresentCompositorFrameOnImplThread(
+ const std::vector<int>& source_frames,
+ base::TimeTicks time,
+ base::TimeDelta refresh,
+ uint32_t flags) override;
void RequestNewLayerTreeFrameSink();
diff --git a/chromium/cc/trees/swap_promise.h b/chromium/cc/trees/swap_promise.h
index 81ec7cd0e36..0ab6136f570 100644
--- a/chromium/cc/trees/swap_promise.h
+++ b/chromium/cc/trees/swap_promise.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include "cc/cc_export.h"
+#include "cc/trees/render_frame_metadata.h"
#include "components/viz/common/quads/compositor_frame_metadata.h"
namespace cc {
@@ -61,7 +62,8 @@ class CC_EXPORT SwapPromise {
virtual ~SwapPromise() {}
virtual void DidActivate() = 0;
- virtual void WillSwap(viz::CompositorFrameMetadata* metadata) = 0;
+ virtual void WillSwap(viz::CompositorFrameMetadata* compositor_frame_metadata,
+ RenderFrameMetadata* render_frame_metadata) = 0;
virtual void DidSwap() = 0;
// Return |KEEP_ACTIVE| if this promise should remain active (should not be
// broken by the owner).
diff --git a/chromium/cc/trees/swap_promise_manager.cc b/chromium/cc/trees/swap_promise_manager.cc
index 124e2b3bbf5..939cc02d1f6 100644
--- a/chromium/cc/trees/swap_promise_manager.cc
+++ b/chromium/cc/trees/swap_promise_manager.cc
@@ -9,7 +9,7 @@
namespace cc {
-SwapPromiseManager::SwapPromiseManager() {}
+SwapPromiseManager::SwapPromiseManager() = default;
SwapPromiseManager::~SwapPromiseManager() {
DCHECK(swap_promise_monitors_.empty());
diff --git a/chromium/cc/trees/swap_promise_manager_unittest.cc b/chromium/cc/trees/swap_promise_manager_unittest.cc
index 02f4df2d0a7..85bfa97cdf8 100644
--- a/chromium/cc/trees/swap_promise_manager_unittest.cc
+++ b/chromium/cc/trees/swap_promise_manager_unittest.cc
@@ -18,7 +18,7 @@ class MockSwapPromiseMonitor : public SwapPromiseMonitor {
public:
explicit MockSwapPromiseMonitor(SwapPromiseManager* manager)
: SwapPromiseMonitor(manager, nullptr) {}
- ~MockSwapPromiseMonitor() override {}
+ ~MockSwapPromiseMonitor() override = default;
MOCK_METHOD0(OnSetNeedsCommitOnMain, void());
void OnSetNeedsRedrawOnImpl() override {}
@@ -27,11 +27,12 @@ class MockSwapPromiseMonitor : public SwapPromiseMonitor {
class MockSwapPromise : public SwapPromise {
public:
- MockSwapPromise() {}
- ~MockSwapPromise() override {}
+ MockSwapPromise() = default;
+ ~MockSwapPromise() override = default;
void DidActivate() override {}
- void WillSwap(viz::CompositorFrameMetadata* metadata) override {}
+ void WillSwap(viz::CompositorFrameMetadata* compositor_frame_metadata,
+ RenderFrameMetadata* render_frame_metadata) override {}
void DidSwap() override {}
DidNotSwapAction DidNotSwap(DidNotSwapReason reason) override {
return DidNotSwapAction::BREAK_PROMISE;
diff --git a/chromium/cc/trees/transform_node.cc b/chromium/cc/trees/transform_node.cc
index 5183bae77c7..5e7b6bf4890 100644
--- a/chromium/cc/trees/transform_node.cc
+++ b/chromium/cc/trees/transform_node.cc
@@ -119,7 +119,7 @@ TransformCachedNodeData::TransformCachedNodeData()
TransformCachedNodeData::TransformCachedNodeData(
const TransformCachedNodeData& other) = default;
-TransformCachedNodeData::~TransformCachedNodeData() {}
+TransformCachedNodeData::~TransformCachedNodeData() = default;
bool TransformCachedNodeData::operator==(
const TransformCachedNodeData& other) const {
diff --git a/chromium/cc/trees/tree_synchronizer.cc b/chromium/cc/trees/tree_synchronizer.cc
index 87efee06cab..7dadbbe1476 100644
--- a/chromium/cc/trees/tree_synchronizer.cc
+++ b/chromium/cc/trees/tree_synchronizer.cc
@@ -130,14 +130,18 @@ static void PushLayerPropertiesInternal(
void TreeSynchronizer::PushLayerProperties(LayerTreeImpl* pending_tree,
LayerTreeImpl* active_tree) {
- PushLayerPropertiesInternal(pending_tree->LayersThatShouldPushProperties(),
- active_tree);
+ const auto& layers = pending_tree->LayersThatShouldPushProperties();
+ TRACE_EVENT1("cc", "TreeSynchronizer::PushLayerPropertiesTo.Impl",
+ "layer_count", layers.size());
+ PushLayerPropertiesInternal(layers, active_tree);
}
void TreeSynchronizer::PushLayerProperties(LayerTreeHost* host_tree,
LayerTreeImpl* impl_tree) {
- PushLayerPropertiesInternal(host_tree->LayersThatShouldPushProperties(),
- impl_tree);
+ const auto& layers = host_tree->LayersThatShouldPushProperties();
+ TRACE_EVENT1("cc", "TreeSynchronizer::PushLayerPropertiesTo.Main",
+ "layer_count", layers.size());
+ PushLayerPropertiesInternal(layers, impl_tree);
}
} // namespace cc
diff --git a/chromium/cc/trees/tree_synchronizer_unittest.cc b/chromium/cc/trees/tree_synchronizer_unittest.cc
index 2afcaa63021..98f3b049e4b 100644
--- a/chromium/cc/trees/tree_synchronizer_unittest.cc
+++ b/chromium/cc/trees/tree_synchronizer_unittest.cc
@@ -84,7 +84,7 @@ class MockLayer : public Layer {
private:
explicit MockLayer(std::vector<int>* layer_impl_destruction_list)
: layer_impl_destruction_list_(layer_impl_destruction_list) {}
- ~MockLayer() override {}
+ ~MockLayer() override = default;
std::vector<int>* layer_impl_destruction_list_;
};
diff --git a/chromium/cc/trees/ukm_manager.cc b/chromium/cc/trees/ukm_manager.cc
index 8a817d5ed07..cf500c922b8 100644
--- a/chromium/cc/trees/ukm_manager.cc
+++ b/chromium/cc/trees/ukm_manager.cc
@@ -14,11 +14,15 @@ UkmManager::UkmManager(std::unique_ptr<ukm::UkmRecorder> recorder)
DCHECK(recorder_);
}
-UkmManager::~UkmManager() = default;
+UkmManager::~UkmManager() {
+ RecordCheckerboardUkm();
+ RecordRenderingUkm();
+}
void UkmManager::SetSourceURL(const GURL& url) {
// If we accumulating any metrics, record them before reseting the source.
RecordCheckerboardUkm();
+ RecordRenderingUkm();
source_id_ = recorder_->GetNewSourceID();
recorder_->UpdateSourceURL(source_id_, url);
@@ -46,6 +50,14 @@ void UkmManager::AddCheckerboardStatsForFrame(int64_t checkerboard_area,
num_of_frames_++;
}
+void UkmManager::AddCheckerboardedImages(int num_of_checkerboarded_images) {
+ if (user_interaction_in_progress_) {
+ num_of_images_checkerboarded_during_interaction_ +=
+ num_of_checkerboarded_images;
+ }
+ total_num_of_checkerboarded_images_ += num_of_checkerboarded_images;
+}
+
void UkmManager::RecordCheckerboardUkm() {
// Only make a recording if there was any visible area from PictureLayers,
// which can be checkerboarded.
@@ -57,6 +69,8 @@ void UkmManager::RecordCheckerboardUkm() {
.SetNumMissingTiles(num_missing_tiles_ / num_of_frames_)
.SetCheckerboardedContentAreaRatio(
(checkerboarded_content_area_ * 100) / total_visible_area_)
+ .SetCheckerboardedImagesCount(
+ num_of_images_checkerboarded_during_interaction_)
.Record(recorder_.get());
}
@@ -64,6 +78,17 @@ void UkmManager::RecordCheckerboardUkm() {
num_missing_tiles_ = 0;
num_of_frames_ = 0;
total_visible_area_ = 0;
+ num_of_images_checkerboarded_during_interaction_ = 0;
+}
+
+void UkmManager::RecordRenderingUkm() {
+ if (source_id_ == ukm::kInvalidSourceId)
+ return;
+
+ ukm::builders::Compositor_Rendering(source_id_)
+ .SetCheckerboardedImagesCount(total_num_of_checkerboarded_images_)
+ .Record(recorder_.get());
+ total_num_of_checkerboarded_images_ = 0;
}
} // namespace cc
diff --git a/chromium/cc/trees/ukm_manager.h b/chromium/cc/trees/ukm_manager.h
index 7521cccc013..fef49175828 100644
--- a/chromium/cc/trees/ukm_manager.h
+++ b/chromium/cc/trees/ukm_manager.h
@@ -29,22 +29,30 @@ class CC_EXPORT UkmManager {
void SetSourceURL(const GURL& url);
+ // These metrics are recorded while a user interaction is in progress.
void SetUserInteractionInProgress(bool in_progress);
void AddCheckerboardStatsForFrame(int64_t checkerboard_area,
int64_t num_missing_tiles,
int64_t total_visible_area);
+ // These metrics are recorded until the source URL changes.
+ void AddCheckerboardedImages(int num_of_checkerboarded_images);
+
ukm::UkmRecorder* recorder_for_testing() { return recorder_.get(); }
private:
void RecordCheckerboardUkm();
+ void RecordRenderingUkm();
bool user_interaction_in_progress_ = false;
+ int64_t num_of_images_checkerboarded_during_interaction_ = 0;
int64_t checkerboarded_content_area_ = 0;
int64_t num_missing_tiles_ = 0;
int64_t total_visible_area_ = 0;
int64_t num_of_frames_ = 0;
+ int total_num_of_checkerboarded_images_ = 0;
+
ukm::SourceId source_id_ = ukm::kInvalidSourceId;
std::unique_ptr<ukm::UkmRecorder> recorder_;
};
diff --git a/chromium/cc/trees/ukm_manager_unittest.cc b/chromium/cc/trees/ukm_manager_unittest.cc
index f9ad62bc27e..f69ab618536 100644
--- a/chromium/cc/trees/ukm_manager_unittest.cc
+++ b/chromium/cc/trees/ukm_manager_unittest.cc
@@ -14,9 +14,12 @@ const char kTestUrl1[] = "https://example.com/foo";
const char kTestUrl2[] = "https://example.com/bar";
const char kUserInteraction[] = "Compositor.UserInteraction";
+const char kRendering[] = "Compositor.Rendering";
+
const char kCheckerboardArea[] = "CheckerboardedContentArea";
const char kCheckerboardAreaRatio[] = "CheckerboardedContentAreaRatio";
const char kMissingTiles[] = "NumMissingTiles";
+const char kCheckerboardedImagesCount[] = "CheckerboardedImagesCount";
class UkmManagerTest : public testing::Test {
public:
@@ -36,6 +39,7 @@ TEST_F(UkmManagerTest, Basic) {
manager_->SetUserInteractionInProgress(true);
manager_->AddCheckerboardStatsForFrame(5, 1, 10);
manager_->AddCheckerboardStatsForFrame(15, 3, 30);
+ manager_->AddCheckerboardedImages(6);
manager_->SetUserInteractionInProgress(false);
// We should see a single entry for the interaction above.
@@ -49,6 +53,7 @@ TEST_F(UkmManagerTest, Basic) {
test_ukm_recorder_->ExpectEntryMetric(entry, kCheckerboardArea, 10);
test_ukm_recorder_->ExpectEntryMetric(entry, kMissingTiles, 2);
test_ukm_recorder_->ExpectEntryMetric(entry, kCheckerboardAreaRatio, 50);
+ test_ukm_recorder_->ExpectEntryMetric(entry, kCheckerboardedImagesCount, 6);
}
test_ukm_recorder_->Purge();
@@ -75,6 +80,16 @@ TEST_F(UkmManagerTest, Basic) {
test_ukm_recorder_->ExpectEntryMetric(entry, kCheckerboardArea, 20);
test_ukm_recorder_->ExpectEntryMetric(entry, kMissingTiles, 3);
test_ukm_recorder_->ExpectEntryMetric(entry, kCheckerboardAreaRatio, 20);
+ test_ukm_recorder_->ExpectEntryMetric(entry, kCheckerboardedImagesCount, 0);
+ }
+
+ // An entry for rendering is emitted when the URL changes.
+ const auto& entries_rendering =
+ test_ukm_recorder_->GetEntriesByName(kRendering);
+ EXPECT_EQ(1u, entries_rendering.size());
+ for (const auto* entry : entries_rendering) {
+ EXPECT_EQ(original_id, entry->source_id);
+ test_ukm_recorder_->ExpectEntryMetric(entry, kCheckerboardedImagesCount, 6);
}
}