diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-01-31 16:33:43 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-02-06 16:33:22 +0000 |
commit | da51f56cc21233c2d30f0fe0d171727c3102b2e0 (patch) | |
tree | 4e579ab70ce4b19bee7984237f3ce05a96d59d83 /chromium/cc/trees | |
parent | c8c2d1901aec01e934adf561a9fdf0cc776cdef8 (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')
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); } } |