diff options
Diffstat (limited to 'chromium/cc/trees')
38 files changed, 1950 insertions, 986 deletions
diff --git a/chromium/cc/trees/draw_property_utils.cc b/chromium/cc/trees/draw_property_utils.cc index d3c1958a13c..b888d085203 100644 --- a/chromium/cc/trees/draw_property_utils.cc +++ b/chromium/cc/trees/draw_property_utils.cc @@ -506,11 +506,12 @@ static void UpdatePageScaleFactorInternal(PropertyTrees* property_trees, float page_scale_factor, float device_scale_factor, gfx::Transform device_transform) { - if (property_trees->transform_tree.page_scale_factor() == page_scale_factor) + if (property_trees->transform_tree.page_scale_factor() == page_scale_factor || + !page_scale_layer) { return; + } property_trees->transform_tree.set_page_scale_factor(page_scale_factor); - DCHECK(page_scale_layer); DCHECK_GE(page_scale_layer->transform_tree_index(), TransformTree::kRootNodeId); TransformNode* node = property_trees->transform_tree.Node( @@ -648,7 +649,7 @@ static void SetSurfaceDrawTransform(const PropertyTrees* property_trees, const EffectNode* effect_node = effect_tree.Node(render_surface->EffectTreeIndex()); // The draw transform of root render surface is identity tranform. - if (transform_node->id == TransformTree::kRootNodeId) { + if (render_surface->EffectTreeIndex() == EffectTree::kContentsRootNodeId) { render_surface->SetDrawTransform(gfx::Transform()); return; } @@ -1004,7 +1005,7 @@ void ComputeDrawPropertiesOfVisibleLayers(const LayerImplList* layer_list, } void ComputeMaskDrawProperties(LayerImpl* mask_layer, - const PropertyTrees* property_trees) { + PropertyTrees* property_trees) { // Mask draw properties are used only for rastering, so most of the draw // properties computed for other layers are not needed. // Draw transform of a mask layer has to be a 2d scale. @@ -1016,8 +1017,17 @@ void ComputeMaskDrawProperties(LayerImpl* mask_layer, mask_layer->draw_properties().screen_space_transform = ScreenSpaceTransformInternal(mask_layer, property_trees->transform_tree); + + ConditionalClip clip = LayerClipRect(property_trees, mask_layer); + // is_clipped should be set before visible rect computation as it is used + // there. + mask_layer->draw_properties().is_clipped = clip.is_clipped; + mask_layer->draw_properties().clip_rect = + gfx::ToEnclosingRect(clip.clip_rect); + // Calculate actual visible layer rect for mask layers, since we could have + // tiled mask layers and the tile manager would need this info for rastering. mask_layer->draw_properties().visible_layer_rect = - gfx::Rect(mask_layer->bounds()); + LayerVisibleRect(property_trees, mask_layer); mask_layer->draw_properties().opacity = 1; } diff --git a/chromium/cc/trees/draw_property_utils.h b/chromium/cc/trees/draw_property_utils.h index 45ed01f6e88..6c843521df6 100644 --- a/chromium/cc/trees/draw_property_utils.h +++ b/chromium/cc/trees/draw_property_utils.h @@ -59,7 +59,7 @@ ComputeDrawPropertiesOfVisibleLayers(const LayerImplList* layer_list, PropertyTrees* property_trees); void CC_EXPORT ComputeMaskDrawProperties(LayerImpl* mask_layer, - const PropertyTrees* property_trees); + PropertyTrees* property_trees); void CC_EXPORT ComputeSurfaceDrawProperties(PropertyTrees* property_trees, RenderSurfaceImpl* render_surface); diff --git a/chromium/cc/trees/latency_info_swap_promise.cc b/chromium/cc/trees/latency_info_swap_promise.cc index 6ebf5352014..9b376030ed5 100644 --- a/chromium/cc/trees/latency_info_swap_promise.cc +++ b/chromium/cc/trees/latency_info_swap_promise.cc @@ -44,8 +44,7 @@ void LatencyInfoSwapPromise::DidSwap() {} SwapPromise::DidNotSwapAction LatencyInfoSwapPromise::DidNotSwap( DidNotSwapReason reason) { - latency_.AddLatencyNumber(DidNotSwapReasonToLatencyComponentType(reason), 0, - 0); + latency_.AddLatencyNumber(DidNotSwapReasonToLatencyComponentType(reason), 0); // TODO(miletus): Turn this back on once per-event LatencyInfo tracking // is enabled in GPU side. // DCHECK(latency_.terminated); diff --git a/chromium/cc/trees/latency_info_swap_promise_monitor.cc b/chromium/cc/trees/latency_info_swap_promise_monitor.cc index 7bca0d6ebf0..99ec2c686a4 100644 --- a/chromium/cc/trees/latency_info_swap_promise_monitor.cc +++ b/chromium/cc/trees/latency_info_swap_promise_monitor.cc @@ -21,7 +21,7 @@ bool AddRenderingScheduledComponent(ui::LatencyInfo* latency_info, : ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT; if (latency_info->FindLatency(type, 0, nullptr)) return false; - latency_info->AddLatencyNumber(type, 0, 0); + latency_info->AddLatencyNumber(type, 0); return true; } @@ -31,8 +31,7 @@ bool AddForwardingScrollUpdateToMainComponent(ui::LatencyInfo* latency_info) { nullptr)) return false; latency_info->AddLatencyNumber( - ui::INPUT_EVENT_LATENCY_FORWARD_SCROLL_UPDATE_TO_MAIN_COMPONENT, 0, - latency_info->trace_id()); + ui::INPUT_EVENT_LATENCY_FORWARD_SCROLL_UPDATE_TO_MAIN_COMPONENT, 0); return true; } @@ -70,29 +69,13 @@ void LatencyInfoSwapPromiseMonitor::OnSetNeedsRedrawOnImpl() { void LatencyInfoSwapPromiseMonitor::OnForwardScrollUpdateToMainThreadOnImpl() { if (AddForwardingScrollUpdateToMainComponent(latency_)) { - int64_t new_sequence_number = 0; - for (ui::LatencyInfo::LatencyMap::const_iterator it = - latency_->latency_components().begin(); - it != latency_->latency_components().end(); ++it) { - if (it->first.first == ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT) { - new_sequence_number = - ((static_cast<int64_t>(base::PlatformThread::CurrentId()) << 32) ^ - (reinterpret_cast<uint64_t>(this) << 32)) | - (it->second.sequence_number & 0xffffffff); - if (new_sequence_number == it->second.sequence_number) - return; - break; - } - } - if (!new_sequence_number) - return; ui::LatencyInfo new_latency; new_latency.CopyLatencyFrom( *latency_, ui::INPUT_EVENT_LATENCY_FORWARD_SCROLL_UPDATE_TO_MAIN_COMPONENT); new_latency.AddLatencyNumberWithTraceName( ui::LATENCY_BEGIN_SCROLL_LISTENER_UPDATE_MAIN_COMPONENT, 0, - new_sequence_number, "ScrollUpdate"); + "ScrollUpdate"); std::unique_ptr<SwapPromise> swap_promise( new LatencyInfoSwapPromise(new_latency)); host_impl_->QueueSwapPromiseForMainThreadScrollUpdate( diff --git a/chromium/cc/trees/layer_tree_frame_sink.cc b/chromium/cc/trees/layer_tree_frame_sink.cc index 5a1fb748c7b..e1a1b803b72 100644 --- a/chromium/cc/trees/layer_tree_frame_sink.cc +++ b/chromium/cc/trees/layer_tree_frame_sink.cc @@ -43,13 +43,11 @@ LayerTreeFrameSink::LayerTreeFrameSink( scoped_refptr<viz::ContextProvider> 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) + gpu::GpuMemoryBufferManager* gpu_memory_buffer_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), weak_ptr_factory_(this) { DETACH_FROM_THREAD(thread_checker_); } diff --git a/chromium/cc/trees/layer_tree_frame_sink.h b/chromium/cc/trees/layer_tree_frame_sink.h index f61c7a6c019..7f550dc9fe8 100644 --- a/chromium/cc/trees/layer_tree_frame_sink.h +++ b/chromium/cc/trees/layer_tree_frame_sink.h @@ -11,15 +11,15 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" +#include "base/single_thread_task_runner.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/quads/shared_bitmap.h" #include "components/viz/common/resources/returned_resource.h" +#include "components/viz/common/resources/shared_bitmap_reporter.h" #include "gpu/command_buffer/common/texture_in_use_response.h" -#include "mojo/public/cpp/system/buffer.h" #include "ui/gfx/color_space.h" namespace gpu { @@ -29,21 +29,20 @@ class GpuMemoryBufferManager; namespace viz { class CompositorFrame; class LocalSurfaceId; -class SharedBitmapManager; struct BeginFrameAck; } // namespace viz namespace cc { class LayerTreeFrameSinkClient; -class LayerTreeHostImpl; // An interface for submitting CompositorFrames to a display compositor // which will compose frames from multiple clients to show on screen to the // user. // If a context_provider() is present, frames should be submitted with // OpenGL resources (created with the context_provider()). If not, then -// SharedBitmap resources should be used. -class CC_EXPORT LayerTreeFrameSink : public viz::ContextLostObserver { +// SharedMemory resources should be used. +class CC_EXPORT LayerTreeFrameSink : public viz::SharedBitmapReporter, + public viz::ContextLostObserver { public: struct Capabilities { Capabilities() = default; @@ -74,8 +73,7 @@ class CC_EXPORT LayerTreeFrameSink : public viz::ContextLostObserver { scoped_refptr<viz::ContextProvider> 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); + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager); ~LayerTreeFrameSink() override; @@ -101,7 +99,7 @@ class CC_EXPORT LayerTreeFrameSink : public viz::ContextLostObserver { const Capabilities& capabilities() const { return capabilities_; } // The viz::ContextProviders may be null if frames should be submitted with - // software SharedBitmap resources. + // software SharedMemory resources. viz::ContextProvider* context_provider() const { return context_provider_.get(); } @@ -111,13 +109,6 @@ class CC_EXPORT LayerTreeFrameSink : public viz::ContextLostObserver { gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager() const { return gpu_memory_buffer_manager_; } - viz::SharedBitmapManager* shared_bitmap_manager() const { - return shared_bitmap_manager_; - } - - // Generate hit test region list based on LayerTreeHostImpl, the data will be - // submitted with compositor frame. - virtual void UpdateHitTestData(const LayerTreeHostImpl* host_impl) {} // If supported, this sets the viz::LocalSurfaceId the LayerTreeFrameSink will // use to submit a CompositorFrame. @@ -137,13 +128,10 @@ class CC_EXPORT LayerTreeFrameSink : public viz::ContextLostObserver { // the client did not lead to a CompositorFrame submission. virtual void DidNotProduceFrame(const viz::BeginFrameAck& ack) = 0; - // Associates a SharedBitmapId with a shared buffer handle. - virtual void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, - const viz::SharedBitmapId& id) = 0; - - // Disassociates a SharedBitmapId previously passed to - // DidAllocateSharedBitmap. - virtual void DidDeleteSharedBitmap(const viz::SharedBitmapId& id) = 0; + // viz::SharedBitmapReporter implementation. + void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, + const viz::SharedBitmapId& id) override = 0; + void DidDeleteSharedBitmap(const viz::SharedBitmapId& id) override = 0; protected: class ContextLostForwarder; @@ -158,7 +146,6 @@ class CC_EXPORT LayerTreeFrameSink : public viz::ContextLostObserver { 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_; std::unique_ptr<ContextLostForwarder> worker_context_lost_forwarder_; diff --git a/chromium/cc/trees/layer_tree_frame_sink_client.h b/chromium/cc/trees/layer_tree_frame_sink_client.h index a463b770007..d774db56e35 100644 --- a/chromium/cc/trees/layer_tree_frame_sink_client.h +++ b/chromium/cc/trees/layer_tree_frame_sink_client.h @@ -7,6 +7,7 @@ #include "base/callback.h" #include "base/memory/ref_counted.h" +#include "base/optional.h" #include "base/time/time.h" #include "cc/cc_export.h" #include "components/viz/common/resources/returned_resource.h" @@ -19,6 +20,7 @@ class Transform; namespace viz { class BeginFrameSource; +struct HitTestRegionList; } namespace cc { @@ -32,6 +34,12 @@ class CC_EXPORT LayerTreeFrameSinkClient { // binding to the client and then call again with a null while detaching. virtual void SetBeginFrameSource(viz::BeginFrameSource* source) = 0; + // Builds and returns a HitTestRegionList from the active LayerTreeImpl. To be + // called during SubmitCompositorFrame(). + // TODO(danakj): Just pass it into SubmitCompositorFrame(), with a + // LayerTreeSetting to enable it or not. + virtual base::Optional<viz::HitTestRegionList> BuildHitTestData() = 0; + // Returns resources sent to SubmitCompositorFrame to be reused or freed. virtual void ReclaimResources( const std::vector<viz::ReturnedResource>& resources) = 0; diff --git a/chromium/cc/trees/layer_tree_frame_sink_unittest.cc b/chromium/cc/trees/layer_tree_frame_sink_unittest.cc index 8ac72b45da5..781effb7740 100644 --- a/chromium/cc/trees/layer_tree_frame_sink_unittest.cc +++ b/chromium/cc/trees/layer_tree_frame_sink_unittest.cc @@ -4,6 +4,7 @@ #include "cc/trees/layer_tree_frame_sink.h" +#include "base/single_thread_task_runner.h" #include "base/test/test_simple_task_runner.h" #include "cc/test/fake_layer_tree_frame_sink_client.h" #include "components/viz/common/quads/compositor_frame.h" @@ -25,7 +26,6 @@ class StubLayerTreeFrameSink : public LayerTreeFrameSink { : LayerTreeFrameSink(std::move(context_provider), std::move(worker_context_provider), std::move(compositor_task_runner), - nullptr, nullptr) {} void SubmitCompositorFrame(viz::CompositorFrame frame) override { diff --git a/chromium/cc/trees/layer_tree_host.cc b/chromium/cc/trees/layer_tree_host.cc index d8bf091317a..b47182219c0 100644 --- a/chromium/cc/trees/layer_tree_host.cc +++ b/chromium/cc/trees/layer_tree_host.cc @@ -159,7 +159,7 @@ void LayerTreeHost::SetUIResourceManagerForTesting( } void LayerTreeHost::InitializeProxy(std::unique_ptr<Proxy> proxy) { - TRACE_EVENT0("cc", "LayerTreeHostInProcess::InitializeForReal"); + TRACE_EVENT0("cc", "LayerTreeHost::InitializeForReal"); DCHECK(task_runner_provider_); proxy_ = std::move(proxy); @@ -174,7 +174,7 @@ LayerTreeHost::~LayerTreeHost() { // Track when we're inside a main frame to see if compositor is being // destroyed midway which causes a crash. crbug.com/654672 DCHECK(!inside_main_frame_); - TRACE_EVENT0("cc", "LayerTreeHostInProcess::~LayerTreeHostInProcess"); + TRACE_EVENT0("cc", "LayerTreeHost::~LayerTreeHost"); // Clear any references into the LayerTreeHost. mutator_host_->SetMutatorHostClient(nullptr); @@ -280,25 +280,12 @@ void LayerTreeHost::RequestMainFrameUpdate(VisualStateUpdate requested_update) { // This function commits the LayerTreeHost to an impl tree. When modifying // this function, keep in mind that the function *runs* on the impl thread! Any // code that is logically a main thread operation, e.g. deletion of a Layer, -// should be delayed until the LayerTreeHostInProcess::CommitComplete, which -// will run after the commit, but on the main thread. +// should be delayed until the LayerTreeHost::CommitComplete, which will run +// after the commit, but on the main thread. void LayerTreeHost::FinishCommitOnImplThread( LayerTreeHostImpl* host_impl) { DCHECK(task_runner_provider_->IsImplThread()); - bool is_new_trace; - TRACE_EVENT_IS_NEW_TRACE(&is_new_trace); - if (is_new_trace && - frame_viewer_instrumentation::IsTracingLayerTreeSnapshots() && - root_layer()) { - // We'll be dumping layer trees as part of trace, so make sure - // PushPropertiesTo() propagates layer debug info to the impl side -- - // otherwise this won't happen for the layers that remain unchanged since - // tracing started. - LayerTreeHostCommon::CallFunctionForEveryLayer( - this, [](Layer* layer) { layer->SetNeedsPushProperties(); }); - } - LayerTreeImpl* sync_tree = host_impl->sync_tree(); sync_tree->lifecycle().AdvanceTo(LayerTreeLifecycle::kBeginningSync); @@ -341,7 +328,7 @@ void LayerTreeHost::FinishCommitOnImplThread( } { - TRACE_EVENT0("cc", "LayerTreeHostInProcess::PushProperties"); + TRACE_EVENT0("cc", "LayerTreeHost::PushProperties"); PushPropertyTreesTo(sync_tree); sync_tree->lifecycle().AdvanceTo(LayerTreeLifecycle::kSyncedPropertyTrees); @@ -377,7 +364,7 @@ void LayerTreeHost::FinishCommitOnImplThread( // TODO(pdr): Enforce this comment with DCHECKS and a lifecycle state. sync_tree->UpdatePropertyTreeAnimationFromMainThread(); - TRACE_EVENT0("cc", "LayerTreeHostInProcess::AnimationHost::PushProperties"); + TRACE_EVENT0("cc", "LayerTreeHost::AnimationHost::PushProperties"); DCHECK(host_impl->mutator_host()); mutator_host_->PushPropertiesTo(host_impl->mutator_host()); @@ -427,13 +414,29 @@ void LayerTreeHost::PushPropertyTreesTo(LayerTreeImpl* tree_impl) { void LayerTreeHost::WillCommit() { swap_promise_manager_.WillCommit(); client_->WillCommit(); + + if (frame_viewer_instrumentation::IsTracingLayerTreeSnapshots()) { + bool is_new_trace; + TRACE_EVENT_IS_NEW_TRACE(&is_new_trace); + if (is_new_trace) { + // We'll be dumping layer trees as part of trace, so make sure + // PushPropertiesTo() propagates layer debug info to the impl side -- + // otherwise this won't happen for the layers that remain unchanged since + // tracing started. + LayerTreeHostCommon::CallFunctionForEveryLayer( + this, [](Layer* layer) { layer->SetNeedsPushProperties(); }); + } + + for (Layer* layer : LayersThatShouldPushProperties()) + layer->UpdateDebugInfo(); + } } void LayerTreeHost::UpdateDeferCommitsInternal() { proxy_->SetDeferCommits(defer_commits_ || (settings_.enable_surface_synchronization && - !local_surface_id_.is_valid())); + !local_surface_id_from_parent_.is_valid())); } bool LayerTreeHost::IsUsingLayerLists() const { @@ -451,7 +454,7 @@ void LayerTreeHost::CommitComplete() { void LayerTreeHost::SetLayerTreeFrameSink( std::unique_ptr<LayerTreeFrameSink> surface) { - TRACE_EVENT0("cc", "LayerTreeHostInProcess::SetLayerTreeFrameSink"); + TRACE_EVENT0("cc", "LayerTreeHost::SetLayerTreeFrameSink"); DCHECK(surface); DCHECK(!new_layer_tree_frame_sink_); @@ -514,7 +517,7 @@ LayerTreeHost::CreateLayerTreeHostImpl( } void LayerTreeHost::DidLoseLayerTreeFrameSink() { - TRACE_EVENT0("cc", "LayerTreeHostInProcess::DidLoseLayerTreeFrameSink"); + TRACE_EVENT0("cc", "LayerTreeHost::DidLoseLayerTreeFrameSink"); DCHECK(task_runner_provider_->IsMainThread()); SetNeedsCommit(); } @@ -598,9 +601,9 @@ void LayerTreeHost::SetHasGpuRasterizationTrigger(bool has_trigger) { return; has_gpu_rasterization_trigger_ = has_trigger; - TRACE_EVENT_INSTANT1( - "cc", "LayerTreeHostInProcess::SetHasGpuRasterizationTrigger", - TRACE_EVENT_SCOPE_THREAD, "has_trigger", has_gpu_rasterization_trigger_); + TRACE_EVENT_INSTANT1("cc", "LayerTreeHost::SetHasGpuRasterizationTrigger", + TRACE_EVENT_SCOPE_THREAD, "has_trigger", + has_gpu_rasterization_trigger_); } void LayerTreeHost::ApplyPageScaleDeltaFromImplSide( @@ -745,8 +748,8 @@ void LayerTreeHost::RecordGpuRasterizationHistogram( } bool LayerTreeHost::DoUpdateLayers(Layer* root_layer) { - TRACE_EVENT1("cc", "LayerTreeHostInProcess::DoUpdateLayers", - "source_frame_number", SourceFrameNumber()); + TRACE_EVENT1("cc", "LayerTreeHost::DoUpdateLayers", "source_frame_number", + SourceFrameNumber()); UpdateHudLayer(debug_state_.ShowHudInfo()); @@ -777,11 +780,9 @@ bool LayerTreeHost::DoUpdateLayers(Layer* root_layer) { { base::AutoReset<bool> update_property_trees(&in_update_property_trees_, true); - TRACE_EVENT0("cc", - "LayerTreeHostInProcess::UpdateLayers::BuildPropertyTrees"); - TRACE_EVENT0( - TRACE_DISABLED_BY_DEFAULT("cc.debug.cdp-perf"), - "LayerTreeHostInProcessCommon::ComputeVisibleRectsWithPropertyTrees"); + TRACE_EVENT0("cc", "LayerTreeHost::UpdateLayers::BuildPropertyTrees"); + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.cdp-perf"), + "LayerTreeHostCommon::ComputeVisibleRectsWithPropertyTrees"); PropertyTrees* property_trees = &property_trees_; if (!IsUsingLayerLists()) { // In SPv2 the property trees should have been built by the @@ -791,15 +792,15 @@ bool LayerTreeHost::DoUpdateLayers(Layer* root_layer) { outer_viewport_scroll_layer(), overscroll_elasticity_layer(), elastic_overscroll_, page_scale_factor_, device_scale_factor_, gfx::Rect(device_viewport_size_), identity_transform, property_trees); - TRACE_EVENT_INSTANT1( - "cc", "LayerTreeHostInProcess::UpdateLayers_BuiltPropertyTrees", - TRACE_EVENT_SCOPE_THREAD, "property_trees", - property_trees->AsTracedValue()); + TRACE_EVENT_INSTANT1("cc", + "LayerTreeHost::UpdateLayers_BuiltPropertyTrees", + TRACE_EVENT_SCOPE_THREAD, "property_trees", + property_trees->AsTracedValue()); } else { - TRACE_EVENT_INSTANT1( - "cc", "LayerTreeHostInProcess::UpdateLayers_ReceivedPropertyTrees", - TRACE_EVENT_SCOPE_THREAD, "property_trees", - property_trees->AsTracedValue()); + TRACE_EVENT_INSTANT1("cc", + "LayerTreeHost::UpdateLayers_ReceivedPropertyTrees", + TRACE_EVENT_SCOPE_THREAD, "property_trees", + property_trees->AsTracedValue()); } draw_property_utils::UpdatePropertyTrees(this, property_trees); @@ -1054,9 +1055,8 @@ void LayerTreeHost::SetEventListenerProperties( void LayerTreeHost::SetViewportSizeAndScale( const gfx::Size& device_viewport_size, float device_scale_factor, - const viz::LocalSurfaceId& local_surface_id) { - if (settings_.enable_surface_synchronization) - SetLocalSurfaceId(local_surface_id); + const viz::LocalSurfaceId& local_surface_id_from_parent) { + SetLocalSurfaceIdFromParent(local_surface_id_from_parent); bool changed = false; if (device_viewport_size_ != device_viewport_size) { @@ -1083,7 +1083,9 @@ void LayerTreeHost::SetViewportSizeAndScale( #if defined(OS_MACOSX) // TODO(ccameron): This check is not valid on Aura or Mus yet, but should // be. - CHECK(!has_pushed_local_surface_id_ || !local_surface_id_.is_valid()); + CHECK(!has_pushed_local_surface_id_from_parent_ || + new_local_surface_id_request_ || + !local_surface_id_from_parent_.is_valid()); #endif } } @@ -1180,16 +1182,34 @@ void LayerTreeHost::SetContentSourceId(uint32_t id) { SetNeedsCommit(); } -void LayerTreeHost::SetLocalSurfaceId( - const viz::LocalSurfaceId& local_surface_id) { - if (local_surface_id_ == local_surface_id) +void LayerTreeHost::SetLocalSurfaceIdFromParent( + const viz::LocalSurfaceId& local_surface_id_from_parent) { + if (local_surface_id_from_parent_ == local_surface_id_from_parent) return; - local_surface_id_ = local_surface_id; - has_pushed_local_surface_id_ = false; + local_surface_id_from_parent_ = local_surface_id_from_parent; + has_pushed_local_surface_id_from_parent_ = false; UpdateDeferCommitsInternal(); SetNeedsCommit(); } +void LayerTreeHost::RequestNewLocalSurfaceId() { + // If surface synchronization is enabled, then we can still request a new + // viz::LocalSurfaceId but that request will be deferred until we have a valid + // viz::LocalSurfaceId from the parent. + DCHECK(settings_.enable_surface_synchronization || + local_surface_id_from_parent_.is_valid()); + if (new_local_surface_id_request_) + return; + new_local_surface_id_request_ = true; + SetNeedsCommit(); +} + +bool LayerTreeHost::TakeNewLocalSurfaceIdRequest() { + bool new_local_surface_id_request = new_local_surface_id_request_; + new_local_surface_id_request_ = false; + return new_local_surface_id_request; +} + void LayerTreeHost::RegisterLayer(Layer* layer) { DCHECK(!LayerById(layer->id())); DCHECK(!in_paint_layer_contents_); @@ -1375,8 +1395,11 @@ void LayerTreeHost::PushLayerTreePropertiesTo(LayerTreeImpl* tree_impl) { tree_impl->set_content_source_id(content_source_id_); - tree_impl->set_local_surface_id(local_surface_id_); - has_pushed_local_surface_id_ = true; + if (TakeNewLocalSurfaceIdRequest()) + tree_impl->RequestNewLocalSurfaceId(); + + tree_impl->SetLocalSurfaceIdFromParent(local_surface_id_from_parent_); + has_pushed_local_surface_id_from_parent_ = true; if (pending_page_scale_animation_) { tree_impl->SetPendingPageScaleAnimation( diff --git a/chromium/cc/trees/layer_tree_host.h b/chromium/cc/trees/layer_tree_host.h index 9aecadafd1e..2fbf3e6c021 100644 --- a/chromium/cc/trees/layer_tree_host.h +++ b/chromium/cc/trees/layer_tree_host.h @@ -292,9 +292,10 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { return event_listener_properties_[static_cast<size_t>(event_class)]; } - void SetViewportSizeAndScale(const gfx::Size& device_viewport_size, - float device_scale_factor, - const viz::LocalSurfaceId& local_surface_id); + void SetViewportSizeAndScale( + const gfx::Size& device_viewport_size, + float device_scale_factor, + const viz::LocalSurfaceId& local_surface_id_from_parent); void SetViewportVisibleRect(const gfx::Rect& visible_rect); @@ -337,9 +338,20 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // If this LayerTreeHost needs a valid viz::LocalSurfaceId then commits will // be deferred until a valid viz::LocalSurfaceId is provided. - void SetLocalSurfaceId(const viz::LocalSurfaceId& local_surface_id); - const viz::LocalSurfaceId& local_surface_id() const { - return local_surface_id_; + void SetLocalSurfaceIdFromParent( + const viz::LocalSurfaceId& local_surface_id_from_parent); + const viz::LocalSurfaceId& local_surface_id_from_parent() const { + return local_surface_id_from_parent_; + } + + // Requests the allocation of a new LocalSurfaceId on the compositor thread. + void RequestNewLocalSurfaceId(); + + // Returns the current state of the new LocalSurfaceId request and resets + // the state. + bool TakeNewLocalSurfaceIdRequest(); + bool new_local_surface_id_request_for_testing() const { + return new_local_surface_id_request_; } void SetRasterColorSpace(const gfx::ColorSpace& raster_color_space); @@ -418,7 +430,7 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { LayerListReverseIterator<Layer> rbegin(); LayerListReverseIterator<Layer> rend(); - // LayerTreeHostInProcess interface to Proxy. + // LayerTreeHost interface to Proxy. void WillBeginMainFrame(); void DidBeginMainFrame(); void BeginMainFrame(const viz::BeginFrameArgs& args); @@ -636,9 +648,10 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { gfx::ColorSpace raster_color_space_; uint32_t content_source_id_; - viz::LocalSurfaceId local_surface_id_; + viz::LocalSurfaceId local_surface_id_from_parent_; // Used to detect surface invariant violations. - bool has_pushed_local_surface_id_ = false; + bool has_pushed_local_surface_id_from_parent_ = false; + bool new_local_surface_id_request_ = false; bool defer_commits_ = false; SkColor background_color_ = SK_ColorWHITE; diff --git a/chromium/cc/trees/layer_tree_host_common_perftest.cc b/chromium/cc/trees/layer_tree_host_common_perftest.cc index f411b4efca1..e599a6b4c1d 100644 --- a/chromium/cc/trees/layer_tree_host_common_perftest.cc +++ b/chromium/cc/trees/layer_tree_host_common_perftest.cc @@ -40,7 +40,8 @@ class LayerTreeHostCommonPerfTest : public LayerTreeTest { void ReadTestFile(const std::string& name) { base::FilePath test_data_dir; - ASSERT_TRUE(PathService::Get(viz::Paths::DIR_TEST_DATA, &test_data_dir)); + ASSERT_TRUE( + base::PathService::Get(viz::Paths::DIR_TEST_DATA, &test_data_dir)); base::FilePath json_file = test_data_dir.AppendASCII(name + ".json"); ASSERT_TRUE(base::ReadFileToString(json_file, &json_)); } diff --git a/chromium/cc/trees/layer_tree_host_impl.cc b/chromium/cc/trees/layer_tree_host_impl.cc index 910862ce9a8..df0758ace5d 100644 --- a/chromium/cc/trees/layer_tree_host_impl.cc +++ b/chromium/cc/trees/layer_tree_host_impl.cc @@ -16,6 +16,8 @@ #include "base/auto_reset.h" #include "base/bind.h" +#include "base/compiler_specific.h" +#include "base/containers/adapters.h" #include "base/containers/flat_map.h" #include "base/json/json_writer.h" #include "base/memory/ptr_util.h" @@ -23,6 +25,7 @@ #include "base/numerics/safe_conversions.h" #include "base/stl_util.h" #include "base/strings/stringprintf.h" +#include "base/sys_info.h" #include "base/trace_event/trace_event_argument.h" #include "cc/base/devtools_instrumentation.h" #include "cc/base/histograms.h" @@ -82,6 +85,7 @@ #include "components/viz/common/frame_sinks/copy_output_request.h" #include "components/viz/common/frame_sinks/delay_based_time_source.h" #include "components/viz/common/gpu/texture_allocation.h" +#include "components/viz/common/hit_test/hit_test_region_list.h" #include "components/viz/common/quads/compositor_frame.h" #include "components/viz/common/quads/compositor_frame_metadata.h" #include "components/viz/common/quads/frame_deadline.h" @@ -90,6 +94,7 @@ #include "components/viz/common/quads/solid_color_draw_quad.h" #include "components/viz/common/quads/texture_draw_quad.h" #include "components/viz/common/resources/bitmap_allocation.h" +#include "components/viz/common/resources/platform_color.h" #include "components/viz/common/traced_value.h" #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/context_support.h" @@ -107,6 +112,53 @@ namespace cc { namespace { +// Used to accommodate finite precision when comparing scaled viewport and +// content widths. While this value may seem large, width=device-width on an N7 +// V1 saw errors of ~0.065 between computed window and content widths. +const float kMobileViewportWidthEpsilon = 0.15f; + +bool HasFixedPageScale(LayerTreeImpl* active_tree) { + return active_tree->min_page_scale_factor() == + active_tree->max_page_scale_factor(); +} + +bool HasMobileViewport(LayerTreeImpl* active_tree) { + float window_width_dip = active_tree->current_page_scale_factor() * + active_tree->ScrollableViewportSize().width(); + float content_width_css = active_tree->ScrollableSize().width(); + return content_width_css <= window_width_dip + kMobileViewportWidthEpsilon; +} + +bool IsMobileOptimized(LayerTreeImpl* active_tree) { + bool has_mobile_viewport = HasMobileViewport(active_tree); + bool has_fixed_page_scale = HasFixedPageScale(active_tree); + return has_fixed_page_scale || has_mobile_viewport; +} + +viz::ResourceFormat TileRasterBufferFormat( + const LayerTreeSettings& settings, + viz::ContextProvider* context_provider, + bool use_gpu_rasterization) { + // Software compositing always uses the native skia RGBA N32 format, but we + // just call it RGBA_8888 everywhere even though it can be BGRA ordering, + // because we don't need to communicate the actual ordering as the code all + // assumes the native skia format. + if (!context_provider) + return viz::RGBA_8888; + + // RGBA4444 overrides the defaults if specified, but only for gpu compositing. + // It is always supported on platforms where it is specified. + if (settings.use_rgba_4444) + return viz::RGBA_4444; + // Otherwise we use BGRA textures if we can but it depends on the context + // capabilities, and we have different preferences when rastering to textures + // vs uploading textures. + const gpu::Capabilities& caps = context_provider->ContextCapabilities(); + if (use_gpu_rasterization) + return viz::PlatformColor::BestSupportedRenderBufferFormat(caps); + return viz::PlatformColor::BestSupportedTextureFormat(caps); +} + // Small helper class that saves the current viewport location as the user sees // it and resets to the same location. class ViewportAnchor { @@ -212,7 +264,6 @@ LayerTreeHostImpl::LayerTreeHostImpl( : client_(client), task_runner_provider_(task_runner_provider), current_begin_frame_tracker_(BEGINFRAMETRACKER_FROM_HERE), - layer_tree_frame_sink_(nullptr), need_update_gpu_rasterization_status_(false), content_has_slow_paths_(false), content_has_non_aa_paint_(false), @@ -294,7 +345,9 @@ LayerTreeHostImpl::LayerTreeHostImpl( this, settings.top_controls_show_threshold, settings.top_controls_hide_threshold); - tile_manager_.SetDecodedImageTracker(&decoded_image_tracker_); + memory_pressure_listener_.reset( + new base::MemoryPressureListener(base::BindRepeating( + &LayerTreeHostImpl::OnMemoryPressure, base::Unretained(this)))); } LayerTreeHostImpl::~LayerTreeHostImpl() { @@ -882,8 +935,8 @@ bool LayerTreeHostImpl::HasDamage() const { // If we have a new LocalSurfaceId, we must always submit a CompositorFrame // because the parent is blocking on us. bool local_surface_id_changed = - settings_.enable_surface_synchronization && - (last_draw_local_surface_id_ != active_tree->local_surface_id()); + last_draw_local_surface_id_ != + child_local_surface_id_allocator_.GetCurrentLocalSurfaceId(); return root_surface_has_visible_damage || active_tree_->property_trees()->effect_tree.HasCopyRequests() || @@ -1448,6 +1501,7 @@ void LayerTreeHostImpl::UpdateTileManagerMemoryPolicy( void LayerTreeHostImpl::DidModifyTilePriorities() { // Mark priorities as dirty and schedule a PrepareTiles(). tile_priorities_dirty_ = true; + tile_manager_.DidModifyTilePriorities(); client_->SetNeedsPrepareTilesOnImplThread(); } @@ -1730,8 +1784,10 @@ void LayerTreeHostImpl::ReclaimResources( // If we're not visible, we likely released resources, so we want to // aggressively flush here to make sure those DeleteTextures make it to the // GPU process to free up the memory. - if (!visible_) - resource_provider_->FlushPendingDeletions(); + if (!visible_ && layer_tree_frame_sink_->context_provider()) { + auto* gl = layer_tree_frame_sink_->context_provider()->ContextGL(); + gl->ShallowFlushCHROMIUM(); + } } void LayerTreeHostImpl::OnDraw(const gfx::Transform& transform, @@ -1844,8 +1900,39 @@ RenderFrameMetadata LayerTreeHostImpl::MakeRenderFrameMetadata() { gfx::ScrollOffsetToVector2dF(active_tree_->TotalScrollOffset()); metadata.root_background_color = active_tree_->background_color(); metadata.is_scroll_offset_at_top = active_tree_->TotalScrollOffset().y() == 0; + metadata.device_scale_factor = active_tree_->painted_device_scale_factor() * + active_tree_->device_scale_factor(); + metadata.viewport_size_in_pixels = device_viewport_size(); + metadata.top_controls_height = + browser_controls_offset_manager_->TopControlsHeight(); + metadata.top_controls_shown_ratio = + browser_controls_offset_manager_->TopControlsShownRatio(); + metadata.bottom_controls_height = + browser_controls_offset_manager_->BottomControlsHeight(); + metadata.bottom_controls_shown_ratio = + browser_controls_offset_manager_->BottomControlsShownRatio(); + + bool allocate_new_local_surface_id = + last_draw_render_frame_metadata_ && + (last_draw_render_frame_metadata_->top_controls_height != + metadata.top_controls_height || + last_draw_render_frame_metadata_->top_controls_shown_ratio != + metadata.top_controls_shown_ratio || + last_draw_render_frame_metadata_->bottom_controls_height != + metadata.bottom_controls_height || + last_draw_render_frame_metadata_->bottom_controls_shown_ratio != + metadata.bottom_controls_shown_ratio); + + viz::LocalSurfaceId local_surface_id = + child_local_surface_id_allocator_.GetCurrentLocalSurfaceId(); + if (local_surface_id.is_valid()) { + if (allocate_new_local_surface_id) + local_surface_id = child_local_surface_id_allocator_.GenerateId(); + metadata.local_surface_id = local_surface_id; + } active_tree_->GetViewportSelection(&metadata.selection); + metadata.is_mobile_optimized = IsMobileOptimized(active_tree_.get()); return metadata; } @@ -1923,32 +2010,32 @@ bool LayerTreeHostImpl::DrawLayers(FrameData* frame) { active_tree()->FinishSwapPromises(&metadata, &frame_token_allocator_); if (render_frame_metadata_observer_) { - RenderFrameMetadata render_frame_metadata = MakeRenderFrameMetadata(); + last_draw_render_frame_metadata_ = MakeRenderFrameMetadata(); render_frame_metadata_observer_->OnRenderFrameSubmission( - std::move(render_frame_metadata)); + *last_draw_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); + ui::LATENCY_BEGIN_FRAME_UI_COMPOSITOR_COMPONENT, 0, frame_time, 1); } else { new_latency_info.AddLatencyNumberWithTimestamp( - ui::LATENCY_BEGIN_FRAME_RENDERER_COMPOSITOR_COMPONENT, 0, 0, frame_time, + ui::LATENCY_BEGIN_FRAME_RENDERER_COMPOSITOR_COMPONENT, 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::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 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; + std::vector<viz::ResourceId> resources; for (const auto& render_pass : frame->render_passes) { for (auto* quad : render_pass->quad_list) { for (viz::ResourceId resource_id : quad->resources) @@ -1962,8 +2049,9 @@ bool LayerTreeHostImpl::DrawLayers(FrameData* frame) { viz::CompositorFrame compositor_frame; compositor_frame.metadata = std::move(metadata); - resource_provider_->PrepareSendToParent(resources, - &compositor_frame.resource_list); + resource_provider_->PrepareSendToParent( + resources, &compositor_frame.resource_list, + layer_tree_frame_sink_->context_provider()); compositor_frame.render_pass_list = std::move(frame->render_passes); // TODO(fsamuel): Once all clients get their viz::LocalSurfaceId from their // parent, the viz::LocalSurfaceId should hang off CompositorFrameMetadata. @@ -1974,11 +2062,12 @@ bool LayerTreeHostImpl::DrawLayers(FrameData* frame) { // LocalSurfaceId might slip through, but single-thread-without-scheduler // mode is only used in tests so it doesn't matter. CHECK(!settings_.single_thread_proxy_scheduler || - active_tree()->local_surface_id().is_valid()); + active_tree()->local_surface_id_from_parent().is_valid()); layer_tree_frame_sink_->SetLocalSurfaceId( - active_tree()->local_surface_id()); - last_draw_local_surface_id_ = active_tree()->local_surface_id(); + child_local_surface_id_allocator_.GetCurrentLocalSurfaceId()); } + last_draw_local_surface_id_ = + child_local_surface_id_allocator_.GetCurrentLocalSurfaceId(); if (const char* client_name = GetClientNameForMetrics()) { size_t total_quad_count = 0; for (const auto& pass : compositor_frame.render_pass_list) @@ -2102,9 +2191,13 @@ void LayerTreeHostImpl::GetGpuRasterizationCapabilities( *supports_disable_msaa = caps.multisample_compatibility; if (!caps.msaa_is_slow && !caps.avoid_stencil_buffers) { // Skia may blacklist MSAA independently of Chrome. Query Skia for its max - // supported sample count. - SkColorType color_type = - ResourceFormatToClosestSkColorType(settings_.preferred_tile_format); + // supported sample count. Assume gpu compositing + gpu raster for this, as + // that is what we are hoping to use. + viz::ResourceFormat tile_format = TileRasterBufferFormat( + settings_, layer_tree_frame_sink_->context_provider(), + /*use_gpu_rasterization=*/true); + SkColorType color_type = ResourceFormatToClosestSkColorType( + /*gpu_compositing=*/true, tile_format); *max_msaa_samples = gr_context->maxSurfaceSampleCountForColorType(color_type); } @@ -2244,7 +2337,7 @@ bool LayerTreeHostImpl::WillBeginImplFrame(const viz::BeginFrameArgs& args) { void LayerTreeHostImpl::DidFinishImplFrame() { impl_thread_phase_ = ImplThreadPhase::IDLE; current_begin_frame_tracker_.Finish(); - decoded_image_tracker_.NotifyFrameFinished(); + tile_manager_.decoded_image_tracker().NotifyFrameFinished(); } void LayerTreeHostImpl::DidNotProduceFrame(const viz::BeginFrameAck& ack) { @@ -2302,6 +2395,100 @@ void LayerTreeHostImpl::SynchronouslyInitializeAllTiles() { single_thread_synchronous_task_graph_runner_->RunUntilIdle(); } +static uint32_t GetFlagsForSurfaceLayer(const SurfaceLayerImpl* layer) { + uint32_t flags = viz::HitTestRegionFlags::kHitTestMouse | + viz::HitTestRegionFlags::kHitTestTouch; + const auto& surface_id = layer->primary_surface_id(); + if (layer->is_clipped()) { + flags |= viz::HitTestRegionFlags::kHitTestAsk; + } + if (surface_id.local_surface_id().is_valid()) { + flags |= viz::HitTestRegionFlags::kHitTestChildSurface; + } else { + flags |= viz::HitTestRegionFlags::kHitTestMine; + } + return flags; +} + +static void PopulateHitTestRegion(viz::HitTestRegion* hit_test_region, + const LayerImpl* layer, + uint32_t flags, + const gfx::Rect& rect, + const viz::SurfaceId& surface_id, + float device_scale_factor) { + hit_test_region->frame_sink_id = surface_id.frame_sink_id(); + hit_test_region->flags = flags; + + hit_test_region->rect = rect; + // The transform of hit test region maps a point from parent hit test region + // to the local space. This is the inverse of screen space transform. Because + // hit test query wants the point in target to be in Pixel space, we + // counterscale the transform here. Note that the rect is scaled by dsf, so + // the point and the rect are still in the same space. + gfx::Transform surface_to_root_transform = layer->ScreenSpaceTransform(); + surface_to_root_transform.Scale(SK_MScalar1 / device_scale_factor, + SK_MScalar1 / device_scale_factor); + // TODO(sunxd): Avoid losing precision by not using inverse if possible. + bool ok = surface_to_root_transform.GetInverse(&hit_test_region->transform); + // Note: If |ok| is false, the |transform| is set to the identity before + // returning, which is what we want. + ALLOW_UNUSED_LOCAL(ok); +} + +base::Optional<viz::HitTestRegionList> LayerTreeHostImpl::BuildHitTestData() { + if (!settings_.build_hit_test_data) + return {}; + + base::Optional<viz::HitTestRegionList> hit_test_region_list(base::in_place); + hit_test_region_list->flags = viz::HitTestRegionFlags::kHitTestMine | + viz::HitTestRegionFlags::kHitTestMouse | + viz::HitTestRegionFlags::kHitTestTouch; + hit_test_region_list->bounds = DeviceViewport(); + hit_test_region_list->transform = DrawTransform(); + + float device_scale_factor = active_tree()->device_scale_factor(); + + Region overlapping_region; + for (const auto* layer : base::Reversed(*active_tree())) { + if (!layer->should_hit_test()) + continue; + + if (layer->is_surface_layer()) { + const auto* surface_layer = static_cast<const SurfaceLayerImpl*>(layer); + + if (!surface_layer->surface_hit_testable()) { + overlapping_region.Union(MathUtil::MapEnclosingClippedRect( + layer->ScreenSpaceTransform(), gfx::Rect(surface_layer->bounds()))); + continue; + } + + gfx::Rect content_rect( + gfx::ScaleToEnclosingRect(gfx::Rect(surface_layer->bounds()), + device_scale_factor, device_scale_factor)); + + gfx::Rect layer_screen_space_rect = MathUtil::MapEnclosingClippedRect( + surface_layer->ScreenSpaceTransform(), + gfx::Rect(surface_layer->bounds())); + if (overlapping_region.Contains(layer_screen_space_rect)) + continue; + + auto flag = GetFlagsForSurfaceLayer(surface_layer); + if (overlapping_region.Intersects(layer_screen_space_rect)) + flag |= viz::HitTestRegionFlags::kHitTestAsk; + auto surface_id = surface_layer->primary_surface_id(); + hit_test_region_list->regions.emplace_back(); + PopulateHitTestRegion(&hit_test_region_list->regions.back(), layer, flag, + content_rect, surface_id, device_scale_factor); + continue; + } + // TODO(sunxd): Submit all overlapping layer bounds as hit test regions. + overlapping_region.Union(MathUtil::MapEnclosingClippedRect( + layer->ScreenSpaceTransform(), gfx::Rect(layer->bounds()))); + } + + return hit_test_region_list; +} + 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 @@ -2310,8 +2497,6 @@ void LayerTreeHostImpl::DidLoseLayerTreeFrameSink() { if (!has_valid_layer_tree_frame_sink_) return; has_valid_layer_tree_frame_sink_ = false; - if (resource_provider_) - resource_provider_->DidLoseContextProvider(); client_->DidLoseLayerTreeFrameSinkOnImplThread(); } @@ -2502,6 +2687,14 @@ void LayerTreeHostImpl::ActivateSyncTree() { // Activation can change the root scroll offset, so inform the synchronous // input handler. UpdateRootLayerStateForSynchronousInputHandler(); + + // Update the child's LocalSurfaceId. + if (active_tree()->local_surface_id_from_parent().is_valid()) { + child_local_surface_id_allocator_.UpdateFromParent( + active_tree()->local_surface_id_from_parent()); + if (active_tree()->TakeNewLocalSurfaceIdRequest()) + child_local_surface_id_allocator_.GenerateId(); + } } void LayerTreeHostImpl::ActivateStateForImages() { @@ -2509,6 +2702,30 @@ void LayerTreeHostImpl::ActivateStateForImages() { tile_manager_.DidActivateSyncTree(); } +void LayerTreeHostImpl::OnMemoryPressure( + base::MemoryPressureListener::MemoryPressureLevel level) { + // Only work for low-end devices for now. + if (!base::SysInfo::IsLowEndDevice()) + return; + + switch (level) { + case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: + case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: + break; + case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL: + ReleaseTileResources(); + ReleaseTreeResources(); + ClearUIResources(); + if (image_decode_cache_) { + image_decode_cache_->SetShouldAggressivelyFreeResources(true); + image_decode_cache_->SetShouldAggressivelyFreeResources(false); + } + if (resource_pool_) + resource_pool_->OnPurgeMemory(); + break; + } +} + void LayerTreeHostImpl::SetVisible(bool visible) { DCHECK(task_runner_provider_->IsImplThread()); @@ -2599,20 +2816,21 @@ void LayerTreeHostImpl::RecreateTileResources() { void LayerTreeHostImpl::CreateTileManagerResources() { raster_buffer_provider_ = CreateRasterBufferProvider(); + viz::ResourceFormat tile_format = TileRasterBufferFormat( + settings_, layer_tree_frame_sink_->context_provider(), + use_gpu_rasterization_); + if (use_gpu_rasterization_) { - int max_texture_size = layer_tree_frame_sink_->context_provider() - ->ContextCapabilities() - .max_texture_size; image_decode_cache_ = std::make_unique<GpuImageDecodeCache>( layer_tree_frame_sink_->worker_context_provider(), use_oop_rasterization_, - viz::ResourceFormatToClosestSkColorType( - settings_.preferred_tile_format), - settings_.decoded_image_working_set_budget_bytes, max_texture_size); + viz::ResourceFormatToClosestSkColorType(/*gpu_compositing=*/true, + tile_format), + settings_.decoded_image_working_set_budget_bytes, max_texture_size_); } else { + bool gpu_compositing = !!layer_tree_frame_sink_->context_provider(); image_decode_cache_ = std::make_unique<SoftwareImageDecodeCache>( - viz::ResourceFormatToClosestSkColorType( - settings_.preferred_tile_format), + viz::ResourceFormatToClosestSkColorType(gpu_compositing, tile_format), settings_.decoded_image_working_set_budget_bytes); } @@ -2643,18 +2861,22 @@ LayerTreeHostImpl::CreateRasterBufferProvider() { if (!compositor_context_provider) return std::make_unique<BitmapRasterBufferProvider>(layer_tree_frame_sink_); + const gpu::Capabilities& caps = + compositor_context_provider->ContextCapabilities(); viz::RasterContextProvider* worker_context_provider = layer_tree_frame_sink_->worker_context_provider(); + + viz::ResourceFormat tile_format = TileRasterBufferFormat( + settings_, compositor_context_provider, use_gpu_rasterization_); + if (use_gpu_rasterization_) { DCHECK(worker_context_provider); int msaa_sample_count = use_msaa_ ? RequestedMSAASampleCount() : 0; return std::make_unique<GpuRasterBufferProvider>( compositor_context_provider, worker_context_provider, - resource_provider_.get(), settings_.resource_settings.use_gpu_memory_buffer_resources, - msaa_sample_count, settings_.preferred_tile_format, - settings_.max_gpu_raster_tile_size, + msaa_sample_count, tile_format, settings_.max_gpu_raster_tile_size, settings_.unpremultiply_and_dither_low_bit_depth_tiles, use_oop_rasterization_); } @@ -2670,21 +2892,18 @@ LayerTreeHostImpl::CreateRasterBufferProvider() { if (use_zero_copy) { return std::make_unique<ZeroCopyRasterBufferProvider>( - resource_provider_.get(), layer_tree_frame_sink_->gpu_memory_buffer_manager(), - compositor_context_provider, settings_.preferred_tile_format); + compositor_context_provider, tile_format); } const int max_copy_texture_chromium_size = - compositor_context_provider->ContextCapabilities() - .max_copy_texture_chromium_size; + caps.max_copy_texture_chromium_size; return std::make_unique<OneCopyRasterBufferProvider>( GetTaskRunner(), compositor_context_provider, worker_context_provider, - resource_provider_.get(), max_copy_texture_chromium_size, - settings_.use_partial_raster, + layer_tree_frame_sink_->gpu_memory_buffer_manager(), + max_copy_texture_chromium_size, settings_.use_partial_raster, settings_.resource_settings.use_gpu_memory_buffer_resources, - settings_.max_staging_buffer_usage_in_bytes, - settings_.preferred_tile_format); + settings_.max_staging_buffer_usage_in_bytes, tile_format); } void LayerTreeHostImpl::SetLayerTreeMutator( @@ -2711,7 +2930,7 @@ void LayerTreeHostImpl::QueueImageDecode(int request_id, image.GetKeyForFrame(image.frame_index()).ToString()); // Optimistically specify the current raster color space, since we assume that // it won't change. - decoded_image_tracker_.QueueImageDecode( + tile_manager_.decoded_image_tracker().QueueImageDecode( image, GetRasterColorSpace().color_space, base::Bind(&LayerTreeHostImpl::ImageDecodeFinished, base::Unretained(this), request_id)); @@ -2795,6 +3014,11 @@ void LayerTreeHostImpl::ReleaseLayerTreeFrameSink() { ClearUIResources(); resource_provider_ = nullptr; + if (layer_tree_frame_sink_->context_provider()) { + auto* gl = layer_tree_frame_sink_->context_provider()->ContextGL(); + gl->Finish(); + } + // Release any context visibility before we destroy the LayerTreeFrameSink. SetContextVisibility(false); @@ -2824,27 +3048,23 @@ bool LayerTreeHostImpl::InitializeRenderer( layer_tree_frame_sink_ = layer_tree_frame_sink; has_valid_layer_tree_frame_sink_ = true; - resource_provider_ = std::make_unique<LayerTreeResourceProvider>( - layer_tree_frame_sink_->context_provider(), - layer_tree_frame_sink_->shared_bitmap_manager(), - layer_tree_frame_sink_->gpu_memory_buffer_manager(), - layer_tree_frame_sink_->capabilities().delegated_sync_points_required, - settings_.resource_settings); - if (!layer_tree_frame_sink_->context_provider()) { - // This ResourcePool will vend software resources. - resource_pool_ = std::make_unique<ResourcePool>( - resource_provider_.get(), GetTaskRunner(), - ResourcePool::kDefaultExpirationDelay, ResourcePool::Mode::kSoftware, - settings_.disallow_non_exact_resource_reuse); + + auto* context_provider = layer_tree_frame_sink_->context_provider(); + if (context_provider) { + max_texture_size_ = + context_provider->ContextCapabilities().max_texture_size; } else { - // The ResourcePool will vend gpu resources. - resource_pool_ = std::make_unique<ResourcePool>( - resource_provider_.get(), GetTaskRunner(), - ResourcePool::kDefaultExpirationDelay, ResourcePool::Mode::kGpu, - settings_.disallow_non_exact_resource_reuse); + // Pick an arbitrary limit here similar to what hardware might. + max_texture_size_ = 16 * 1024; } - if (features::IsVizHitTestingSurfaceLayerEnabled()) - layer_tree_frame_sink_->UpdateHitTestData(this); + + resource_provider_ = std::make_unique<LayerTreeResourceProvider>( + layer_tree_frame_sink_->context_provider(), + layer_tree_frame_sink_->capabilities().delegated_sync_points_required); + resource_pool_ = std::make_unique<ResourcePool>( + resource_provider_.get(), layer_tree_frame_sink_->context_provider(), + GetTaskRunner(), ResourcePool::kDefaultExpirationDelay, + settings_.disallow_non_exact_resource_reuse); // TODO(piman): Make oop raster always supported: http://crbug.com/786591 use_oop_rasterization_ = settings_.enable_oop_rasterization; @@ -3128,9 +3348,15 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBeginImpl( scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollingOnMain; if (!scrolling_node) { - scroll_status.thread = SCROLL_IGNORED; - if (settings_.is_layer_tree_for_subframe) + if (settings_.is_layer_tree_for_subframe) { + TRACE_EVENT_INSTANT0("cc", "Ignored - No ScrollNode (OOPIF)", + TRACE_EVENT_SCOPE_THREAD); scroll_status.thread = SCROLL_UNKNOWN; + } else { + TRACE_EVENT_INSTANT0("cc", "Ignroed - No ScrollNode", + TRACE_EVENT_SCOPE_THREAD); + scroll_status.thread = SCROLL_IGNORED; + } scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNoScrollingLayer; return scroll_status; @@ -3140,6 +3366,9 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBeginImpl( browser_controls_offset_manager_->ScrollBegin(); + TRACE_EVENT_INSTANT1("cc", "SetCurrentlyScrollingNode ScrollBeginImpl", + TRACE_EVENT_SCOPE_THREAD, "isNull", + scrolling_node ? false : true); active_tree_->SetCurrentlyScrollingNode(scrolling_node); // TODO(majidvp): get rid of wheel_scrolling_ and set is_direct_manipulation // in input_handler_proxy instead. @@ -3152,6 +3381,8 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBeginImpl( // If the CurrentlyScrollingNode doesn't exist after distributing scroll // delta, no scroller can scroll in the given delta hint direction(s). if (!active_tree_->CurrentlyScrollingNode()) { + TRACE_EVENT_INSTANT0("cc", "Ignored - Didnt Scroll", + TRACE_EVENT_SCOPE_THREAD); scroll_status.thread = InputHandler::SCROLL_IGNORED; scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollingOnMain; @@ -3211,6 +3442,7 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBegin( if (layer_impl) { if (!IsInitialScrollHitTestReliable(layer_impl, device_viewport_point)) { + TRACE_EVENT_INSTANT0("cc", "Failed Hit Test", TRACE_EVENT_SCOPE_THREAD); scroll_status.thread = SCROLL_UNKNOWN; scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kFailedHitTest; @@ -3277,6 +3509,7 @@ bool LayerTreeHostImpl::IsInitialScrollHitTestReliable( InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimatedBegin( ScrollState* scroll_state) { + TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollAnimatedBegin"); InputHandler::ScrollStatus scroll_status; scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollingOnMain; @@ -3288,6 +3521,8 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimatedBegin( if (ScrollAnimationUpdateTarget(scroll_node, delta, base::TimeDelta())) { scroll_status.thread = SCROLL_ON_IMPL_THREAD; } else { + TRACE_EVENT_INSTANT0("cc", "Failed to create animation", + TRACE_EVENT_SCOPE_THREAD); scroll_status.thread = SCROLL_IGNORED; scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollable; @@ -3377,6 +3612,7 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimated( const gfx::Point& viewport_point, const gfx::Vector2dF& scroll_delta, base::TimeDelta delayed_by) { + TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollAnimated"); InputHandler::ScrollStatus scroll_status; scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollingOnMain; @@ -3403,6 +3639,8 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimated( if (ScrollAnimationUpdateTarget(scroll_node, delta, delayed_by)) { scroll_status.thread = SCROLL_ON_IMPL_THREAD; } else { + TRACE_EVENT_INSTANT0("cc", "Failed to update animation", + TRACE_EVENT_SCOPE_THREAD); scroll_status.thread = SCROLL_IGNORED; scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollable; @@ -3479,10 +3717,13 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimated( } scroll_state.set_is_ending(true); 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 - // we'll mark the scroll as handled and the scroll won't bubble. + if (scroll_status.thread == SCROLL_ON_IMPL_THREAD) { + // Update scroll_status.thread to SCROLL_IGNORED when there is no ongoing + // scroll animation, we can scroll on impl thread and yet, we couldn't + // create a new scroll animation. This happens when the scroller has hit its + // extent. + TRACE_EVENT_INSTANT0("cc", "Ignored - Scroller at extent", + TRACE_EVENT_SCOPE_THREAD); scroll_status.thread = SCROLL_IGNORED; scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollable; @@ -3746,8 +3987,13 @@ void LayerTreeHostImpl::DistributeScrollDelta(ScrollState* scroll_state) { } } } - active_tree_->SetCurrentlyScrollingNode( - current_scroll_chain.empty() ? nullptr : current_scroll_chain.back()); + + scroll_node = + current_scroll_chain.empty() ? nullptr : current_scroll_chain.back(); + TRACE_EVENT_INSTANT1("cc", "SetCurrentlyScrollingNode DistributeScrollDelta", + TRACE_EVENT_SCOPE_THREAD, "isNull", + scroll_node ? false : true); + active_tree_->SetCurrentlyScrollingNode(scroll_node); scroll_state->set_scroll_chain_and_layer_tree(current_scroll_chain, active_tree()); scroll_state->DistributeToScrollChainDescendant(); @@ -3803,8 +4049,27 @@ InputHandlerScrollResult LayerTreeHostImpl::ScrollBy( DCHECK(scroll_state); TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollBy"); - ScrollTree& scroll_tree = active_tree_->property_trees()->scroll_tree; + auto& scroll_tree = active_tree_->property_trees()->scroll_tree; + + ElementId provided_element = + scroll_state->data()->current_native_scrolling_element(); + const auto* provided_scroll_node = + scroll_tree.FindNodeFromElementId(provided_element); + + // If the currently scrolling node is not set, set it with + // |provided_scroll_node|. ScrollNode* scroll_node = scroll_tree.CurrentlyScrollingNode(); + if (scroll_node) { + // If |provided_scroll_node| is not null, make sure it matches + // |scroll_node|. + DCHECK(!provided_scroll_node || scroll_node == provided_scroll_node); + } else { + TRACE_EVENT_INSTANT1("cc", "SetCurrentlyScrollingNode ScrollBy", + TRACE_EVENT_SCOPE_THREAD, "isNull", + provided_scroll_node ? false : true); + active_tree_->SetCurrentlyScrollingNode(provided_scroll_node); + scroll_node = scroll_tree.CurrentlyScrollingNode(); + } if (!scroll_node) return InputHandlerScrollResult(); @@ -3825,13 +4090,15 @@ InputHandlerScrollResult LayerTreeHostImpl::ScrollBy( scroll_state->set_delta_consumed_for_scroll_sequence( did_lock_scrolling_layer_); scroll_state->set_is_direct_manipulation(!wheel_scrolling_); - scroll_state->set_current_native_scrolling_node( - active_tree()->property_trees()->scroll_tree.CurrentlyScrollingNode()); + scroll_state->set_current_native_scrolling_node(scroll_node); DistributeScrollDelta(scroll_state); ScrollNode* current_scrolling_node = scroll_state->current_native_scrolling_node(); + TRACE_EVENT_INSTANT1("cc", "SetCurrentlyScrollingNode ApplyDelta", + TRACE_EVENT_SCOPE_THREAD, "isNull", + current_scrolling_node ? false : true); active_tree_->SetCurrentlyScrollingNode(current_scrolling_node); did_lock_scrolling_layer_ = scroll_state->delta_consumed_for_scroll_sequence(); @@ -3898,10 +4165,10 @@ InputHandlerScrollResult LayerTreeHostImpl::ScrollBy( UpdateRootLayerStateForSynchronousInputHandler(); } - scroll_result.current_offset = ScrollOffsetToVector2dF( - scroll_tree.current_scroll_offset(scroll_node->element_id)); + scroll_result.current_visual_offset = + ScrollOffsetToVector2dF(GetVisualScrollOffset(*scroll_node)); float scale_factor = active_tree()->current_page_scale_factor(); - scroll_result.current_offset.Scale(scale_factor); + scroll_result.current_visual_offset.Scale(scale_factor); // Run animations which need to respond to updated scroll offset. mutator_host_->TickScrollAnimations( @@ -3917,6 +4184,9 @@ void LayerTreeHostImpl::RequestUpdateForSynchronousInputHandler() { void LayerTreeHostImpl::SetSynchronousInputHandlerRootScrollOffset( const gfx::ScrollOffset& root_offset) { + TRACE_EVENT2("cc", + "LayerTreeHostImpl::SetSynchronousInputHandlerRootScrollOffset", + "offset_x", root_offset.x(), "offset_y", root_offset.y()); bool changed = active_tree_->DistributeRootScrollOffset(root_offset); if (!changed) return; @@ -3936,9 +4206,7 @@ bool LayerTreeHostImpl::SnapAtScrollEnd() { 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 current_position = GetVisualScrollOffset(*scroll_node); gfx::ScrollOffset snap_position; if (!data.FindSnapPosition(current_position, did_scroll_x_for_scroll_gesture_, @@ -3947,12 +4215,43 @@ bool LayerTreeHostImpl::SnapAtScrollEnd() { return false; } - ScrollAnimationCreate( - scroll_node, ScrollOffsetToVector2dF(snap_position - current_position), - base::TimeDelta()); + gfx::Vector2dF delta = + ScrollOffsetToVector2dF(snap_position - current_position); + bool scrolls_main_viewport_scroll_layer = + scroll_node == ViewportMainScrollNode(); + if (scrolls_main_viewport_scroll_layer) { + // Flash the overlay scrollbar even if the scroll dalta is 0. + if (settings_.scrollbar_flash_after_any_scroll_update) { + FlashAllScrollbars(false); + } else { + ScrollbarAnimationController* animation_controller = + ScrollbarAnimationControllerForElementId(scroll_node->element_id); + if (animation_controller) + animation_controller->WillUpdateScroll(); + } + gfx::Vector2dF scaled_delta(delta); + scaled_delta.Scale(active_tree()->current_page_scale_factor()); + viewport()->ScrollAnimated(scaled_delta, base::TimeDelta()); + } else { + ScrollAnimationCreate(scroll_node, delta, base::TimeDelta()); + } return true; } +gfx::ScrollOffset LayerTreeHostImpl::GetVisualScrollOffset( + const ScrollNode& scroll_node) const { + const ScrollTree& scroll_tree = active_tree()->property_trees()->scroll_tree; + + bool scrolls_main_viewport_scroll_layer = + viewport()->MainScrollLayer() && + viewport()->MainScrollLayer()->scroll_tree_index() == scroll_node.id; + + if (scrolls_main_viewport_scroll_layer) + return viewport()->TotalScrollOffset(); + else + return scroll_tree.current_scroll_offset(scroll_node.element_id); +} + bool LayerTreeHostImpl::GetSnapFlingInfo( const gfx::Vector2dF& natural_displacement_in_viewport, gfx::Vector2dF* initial_offset, @@ -3966,9 +4265,8 @@ bool LayerTreeHostImpl::GetSnapFlingInfo( gfx::Vector2dF natural_displacement_in_content = gfx::ScaleVector2d(natural_displacement_in_viewport, 1.f / scale_factor); - const ScrollTree& scroll_tree = active_tree()->property_trees()->scroll_tree; - *initial_offset = ScrollOffsetToVector2dF( - scroll_tree.current_scroll_offset(scroll_node->element_id)); + *initial_offset = + ScrollOffsetToVector2dF(GetVisualScrollOffset(*scroll_node)); bool did_scroll_x = did_scroll_x_for_scroll_gesture_ || natural_displacement_in_content.x() != 0; @@ -3989,6 +4287,7 @@ bool LayerTreeHostImpl::GetSnapFlingInfo( } void LayerTreeHostImpl::ClearCurrentlyScrollingNode() { + TRACE_EVENT0("cc", "LayerTreeHostImpl::ClearCurrentlyScrollingNode"); active_tree_->ClearCurrentlyScrollingNode(); did_lock_scrolling_layer_ = false; scroll_affects_scroll_handler_ = false; @@ -4118,6 +4417,9 @@ void LayerTreeHostImpl::PinchGestureBegin() { client_->RenewTreePriority(); pinch_gesture_end_should_clear_scrolling_node_ = !CurrentlyScrollingNode(); + TRACE_EVENT_INSTANT1("cc", "SetCurrentlyScrollingNode PinchGestureBegin", + TRACE_EVENT_SCOPE_THREAD, "isNull", + OuterViewportScrollNode() ? false : true); active_tree_->SetCurrentlyScrollingNode(OuterViewportScrollNode()); browser_controls_offset_manager_->PinchBegin(); } @@ -4530,9 +4832,16 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid, return; } - viz::ResourceFormat format = resource_provider_->best_texture_format(); + viz::ResourceFormat format; switch (bitmap.GetFormat()) { case UIResourceBitmap::RGBA8: + if (layer_tree_frame_sink_->context_provider()) { + const gpu::Capabilities& caps = + layer_tree_frame_sink_->context_provider()->ContextCapabilities(); + format = viz::PlatformColor::BestSupportedTextureFormat(caps); + } else { + format = viz::RGBA_8888; + } break; case UIResourceBitmap::ALPHA_8: format = viz::ALPHA_8; @@ -4548,13 +4857,12 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid, // UIResources are assumed to be rastered in SRGB. const gfx::ColorSpace& color_space = gfx::ColorSpace::CreateSRGB(); - int max_texture_size = resource_provider_->max_texture_size(); - if (source_size.width() > max_texture_size || - source_size.height() > max_texture_size) { + if (source_size.width() > max_texture_size_ || + source_size.height() > max_texture_size_) { // Must resize the bitmap to fit within the max texture size. scaled = true; int edge = std::max(source_size.width(), source_size.height()); - float scale = static_cast<float>(max_texture_size - 1) / edge; + float scale = static_cast<float>(max_texture_size_ - 1) / edge; DCHECK_LT(scale, 1.f); upload_size = gfx::ScaleToCeiledSize(source_size, scale, scale); } @@ -4680,7 +4988,7 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid, shared_memory.get(), upload_size, format); layer_tree_frame_sink_->DidAllocateSharedBitmap(std::move(memory_handle), shared_bitmap_id); - transferable = viz::TransferableResource::MakeSoftware(shared_bitmap_id, 0, + transferable = viz::TransferableResource::MakeSoftware(shared_bitmap_id, upload_size, format); } transferable.color_space = color_space; @@ -4976,6 +5284,7 @@ void LayerTreeHostImpl::ElementIsAnimatingChanged( } void LayerTreeHostImpl::ScrollOffsetAnimationFinished() { + TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollOffsetAnimationFinished"); // TODO(majidvp): We should pass in the original starting scroll position here ScrollStateData scroll_state_data; ScrollState scroll_state(scroll_state_data); diff --git a/chromium/cc/trees/layer_tree_host_impl.h b/chromium/cc/trees/layer_tree_host_impl.h index 82d50cc888b..3f93eb51e60 100644 --- a/chromium/cc/trees/layer_tree_host_impl.h +++ b/chromium/cc/trees/layer_tree_host_impl.h @@ -17,6 +17,7 @@ #include "base/callback.h" #include "base/containers/flat_map.h" #include "base/macros.h" +#include "base/memory/memory_pressure_listener.h" #include "base/sequenced_task_runner.h" #include "base/time/time.h" #include "cc/base/synced_property.h" @@ -41,11 +42,13 @@ #include "cc/trees/layer_tree_settings.h" #include "cc/trees/managed_memory_policy.h" #include "cc/trees/mutator_host_client.h" +#include "cc/trees/render_frame_metadata.h" #include "cc/trees/task_runner_provider.h" #include "cc/trees/ukm_manager.h" #include "components/viz/common/frame_sinks/begin_frame_args.h" #include "components/viz/common/gpu/context_cache_controller.h" #include "components/viz/common/quads/render_pass.h" +#include "components/viz/common/surfaces/child_local_surface_id_allocator.h" #include "components/viz/common/surfaces/local_surface_id.h" #include "components/viz/common/surfaces/surface_id.h" #include "ui/gfx/geometry/rect.h" @@ -75,7 +78,6 @@ class PendingTreeDurationHistogramTimer; class PendingTreeRasterDurationHistogramTimer; class RasterTilePriorityQueue; class RasterBufferProvider; -class RenderFrameMetadata; class RenderFrameMetadataObserver; class RenderingStatsInstrumentation; class ResourcePool; @@ -425,6 +427,7 @@ class CC_EXPORT LayerTreeHostImpl void SetExternalTilePriorityConstraints( const gfx::Rect& viewport_rect, const gfx::Transform& transform) override; + base::Optional<viz::HitTestRegionList> BuildHitTestData() override; void DidLoseLayerTreeFrameSink() override; void DidReceiveCompositorFrameAck() override; void DidPresentCompositorFrame(uint32_t presentation_token, @@ -449,6 +452,7 @@ class CC_EXPORT LayerTreeHostImpl LayerTreeFrameSink* layer_tree_frame_sink() const { return layer_tree_frame_sink_; } + int max_texture_size() const { return max_texture_size_; } void ReleaseLayerTreeFrameSink(); std::string LayerListAsJson() const; @@ -531,7 +535,9 @@ class CC_EXPORT LayerTreeHostImpl ManagedMemoryPolicy ActualManagedMemoryPolicy() const; void SetViewportSize(const gfx::Size& device_viewport_size); - gfx::Size device_viewport_size() const { return device_viewport_size_; } + const gfx::Size& device_viewport_size() const { + return device_viewport_size_; + } void SetViewportVisibleRect(const gfx::Rect& visible_rect); gfx::Rect viewport_visible_rect() const { return viewport_visible_rect_; } @@ -596,6 +602,10 @@ class CC_EXPORT LayerTreeHostImpl virtual bool IsUIResourceOpaque(UIResourceId uid) const; + // This method gets the scroll offset for a regular scroller, or the combined + // visual and layout offsets of the viewport. + gfx::ScrollOffset GetVisualScrollOffset(const ScrollNode& scroll_node) const; + bool GetSnapFlingInfo(const gfx::Vector2dF& natural_displacement_in_viewport, gfx::Vector2dF* initial_offset, gfx::Vector2dF* target_offset) const override; @@ -851,6 +861,9 @@ class CC_EXPORT LayerTreeHostImpl // active tree. void ActivateStateForImages(); + void OnMemoryPressure( + base::MemoryPressureListener::MemoryPressureLevel level); + std::unordered_map<UIResourceId, UIResourceData> ui_resource_map_; // UIResources are held here once requested to be deleted until they are // released from the display compositor, then the backing can be deleted. @@ -861,7 +874,14 @@ class CC_EXPORT LayerTreeHostImpl // associated with them anymore, as that is freed at the time of eviction. std::set<UIResourceId> evicted_ui_resources_; - LayerTreeFrameSink* layer_tree_frame_sink_; + // These are valid when has_valid_layer_tree_frame_sink_ is true. + // + // A pointer used for communicating with and submitting output to the display + // compositor. + LayerTreeFrameSink* layer_tree_frame_sink_ = nullptr; + // The maximum size (either width or height) that any texture can be. Also + // holds a reasonable value for software compositing bitmaps. + int max_texture_size_ = 0; // The following scoped variables must not outlive the // |layer_tree_frame_sink_|. @@ -921,7 +941,6 @@ class CC_EXPORT LayerTreeHostImpl const bool is_synchronous_single_threaded_; TileManager tile_manager_; - DecodedImageTracker decoded_image_tracker_; gfx::Vector2dF accumulated_root_overscroll_; @@ -1053,10 +1072,14 @@ class CC_EXPORT LayerTreeHostImpl uint32_t last_presentation_token_ = 0u; viz::LocalSurfaceId last_draw_local_surface_id_; + base::Optional<RenderFrameMetadata> last_draw_render_frame_metadata_; + viz::ChildLocalSurfaceIdAllocator child_local_surface_id_allocator_; const int default_color_space_id_; const gfx::ColorSpace default_color_space_; + std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; + 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 4c4570ee4d7..b7fdefd87dc 100644 --- a/chromium/cc/trees/layer_tree_host_impl_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_impl_unittest.cc @@ -10,14 +10,17 @@ #include <cmath> #include <utility> +#include "base/base_switches.h" #include "base/bind.h" #include "base/command_line.h" #include "base/location.h" +#include "base/memory/memory_pressure_listener.h" #include "base/memory/ptr_util.h" #include "base/optional.h" #include "base/run_loop.h" #include "base/test/histogram_tester.h" #include "base/threading/thread_task_runner_handle.h" +#include "build/build_config.h" #include "cc/animation/animation_host.h" #include "cc/animation/animation_id_provider.h" #include "cc/animation/transform_operations.h" @@ -69,11 +72,13 @@ #include "components/viz/common/quads/solid_color_draw_quad.h" #include "components/viz/common/quads/texture_draw_quad.h" #include "components/viz/common/quads/tile_draw_quad.h" +#include "components/viz/common/surfaces/frame_sink_id.h" #include "components/viz/service/display/gl_renderer.h" #include "components/viz/test/begin_frame_args_test.h" #include "components/viz/test/fake_output_surface.h" #include "components/viz/test/test_layer_tree_frame_sink.h" #include "components/viz/test/test_web_graphics_context_3d.h" +#include "gpu/GLES2/gl2extchromium.h" #include "media/base/media.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -180,7 +185,7 @@ class LayerTreeHostImplTest : public testing::Test, } void DidActivateSyncTree() override { // Make sure the active tree always has a valid LocalSurfaceId. - host_impl_->active_tree()->set_local_surface_id( + host_impl_->active_tree()->SetLocalSurfaceIdFromParent( viz::LocalSurfaceId(1, base::UnguessableToken::Deserialize(2u, 3u))); } void WillPrepareTiles() override {} @@ -242,7 +247,7 @@ class LayerTreeHostImplTest : public testing::Test, bool init = host_impl_->InitializeRenderer(layer_tree_frame_sink_.get()); host_impl_->SetViewportSize(gfx::Size(10, 10)); host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f); - host_impl_->active_tree()->set_local_surface_id( + host_impl_->active_tree()->SetLocalSurfaceIdFromParent( viz::LocalSurfaceId(1, base::UnguessableToken::Deserialize(2u, 3u))); // Set the viz::BeginFrameArgs so that methods which use it are able to. host_impl_->WillBeginImplFrame(viz::CreateBeginFrameArgsForTesting( @@ -1063,15 +1068,23 @@ TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) { status.main_thread_scrolling_reasons); } +class LostGLES2Interface : public viz::TestGLES2Interface { + public: + LostGLES2Interface() = default; + + void InitializeTestContext() override { + LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, + GL_INNOCENT_CONTEXT_RESET_ARB); + } +}; + TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) { - std::unique_ptr<TestWebGraphicsContext3D> context_owned = - TestWebGraphicsContext3D::Create(); - context_owned->set_context_lost(true); + auto gl_owned = std::make_unique<LostGLES2Interface>(); // Initialization will fail. - EXPECT_FALSE(CreateHostImpl( - DefaultSettings(), - FakeLayerTreeFrameSink::Create3d(std::move(context_owned)))); + EXPECT_FALSE( + CreateHostImpl(DefaultSettings(), + FakeLayerTreeFrameSink::Create3d(std::move(gl_owned)))); SetupScrollAndContentsLayers(gfx::Size(100, 100)); @@ -1643,7 +1656,7 @@ TEST_F(LayerTreeHostImplTest, GetSnapFlingInfoWhenZoomed) { InputHandlerScrollResult result = host_impl_->ScrollBy(UpdateState(scroll_position, delta).get()); EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 20), overflow->CurrentScrollOffset()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(4, 4), result.current_offset); + EXPECT_VECTOR_EQ(gfx::Vector2dF(4, 4), result.current_visual_offset); gfx::Vector2dF initial_offset, target_offset; EXPECT_TRUE(host_impl_->GetSnapFlingInfo(gfx::Vector2dF(10, 10), @@ -2589,8 +2602,7 @@ TEST_F(LayerTreeHostImplTest, ImplPinchZoomWheelBubbleBetweenViewports) { TEST_F(LayerTreeHostImplTest, ScrollWithSwapPromises) { ui::LatencyInfo latency_info; latency_info.set_trace_id(5); - latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, - 1234); + latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0); std::unique_ptr<SwapPromise> swap_promise( new LatencyInfoSwapPromise(latency_info)); @@ -3532,7 +3544,7 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { host_impl_->active_tree()->BuildPropertyTreesForTesting(); host_impl_->active_tree()->DidBecomeActive(); host_impl_->active_tree()->HandleScrollbarShowRequestsFromMain(); - host_impl_->active_tree()->set_local_surface_id( + host_impl_->active_tree()->SetLocalSurfaceIdFromParent( viz::LocalSurfaceId(1, base::UnguessableToken::Deserialize(2u, 3u))); DrawFrame(); @@ -4884,11 +4896,9 @@ class MissingTextureAnimatingLayer : public DidDrawCheckLayer { bool tile_missing, bool had_incomplete_tile, bool animating, - ResourceProvider* resource_provider, scoped_refptr<AnimationTimeline> timeline) { return base::WrapUnique(new MissingTextureAnimatingLayer( - tree_impl, id, tile_missing, had_incomplete_tile, animating, - resource_provider, timeline)); + tree_impl, id, tile_missing, had_incomplete_tile, animating, timeline)); } void AppendQuads(viz::RenderPass* render_pass, @@ -4906,7 +4916,6 @@ class MissingTextureAnimatingLayer : public DidDrawCheckLayer { bool tile_missing, bool had_incomplete_tile, bool animating, - ResourceProvider* resource_provider, scoped_refptr<AnimationTimeline> timeline) : DidDrawCheckLayer(tree_impl, id), tile_missing_(tile_missing), @@ -4946,8 +4955,7 @@ static void CreateLayerFromState( static int layer_id = 2; root->test_properties()->AddChild(MissingTextureAnimatingLayer::Create( root->layer_tree_impl(), layer_id++, state.has_missing_tile, - state.has_incomplete_tile, state.is_animating, - root->layer_tree_impl()->resource_provider(), timeline)); + state.has_incomplete_tile, state.is_animating, timeline)); auto* layer = static_cast<DidDrawCheckLayer*>(root->test_properties()->children.back()); if (state.has_copy_request) @@ -6692,9 +6700,11 @@ TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimatedLatchToChild) { EXPECT_EQ(gfx::ScrollOffset(0, 50), child_layer->CurrentScrollOffset()); host_impl_->DidFinishImplFrame(); - // Second ScrollAnimated should still latch to the grand_child_layer. + // Second ScrollAnimated should still latch to the grand_child_layer. Since it + // is already at its extent and no scrolling happens, the scroll result must + // be ignored. EXPECT_EQ( - InputHandler::SCROLL_ON_IMPL_THREAD, + InputHandler::SCROLL_IGNORED, host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, -100)).thread); begin_frame_args.frame_time = @@ -8364,15 +8374,10 @@ class BlendStateCheckLayer : public LayerImpl { 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(), viz::RGBA_8888); - } - resource_provider->AllocateForTesting(resource_id_); + resource_id_ = resource_provider->ImportResource( + viz::TransferableResource::MakeSoftware( + viz::SharedBitmap::GenerateId(), gfx::Size(1, 1), viz::RGBA_8888), + viz::SingleReleaseCallback::Create(base::DoNothing())); SetBounds(gfx::Size(10, 10)); SetDrawsContent(true); } @@ -9053,10 +9058,11 @@ class FakeDrawableLayerImpl : public LayerImpl { // submitted to the LayerTreeFrameSink, where it should request to swap only // the sub-buffer that is damaged. TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) { + auto gl_owned = std::make_unique<viz::TestGLES2Interface>(); + gl_owned->set_have_post_sub_buffer(true); scoped_refptr<viz::TestContextProvider> context_provider( - viz::TestContextProvider::Create()); + viz::TestContextProvider::Create(std::move(gl_owned))); context_provider->BindToCurrentThread(); - context_provider->TestContext3d()->set_have_post_sub_buffer(true); std::unique_ptr<FakeLayerTreeFrameSink> layer_tree_frame_sink( FakeLayerTreeFrameSink::Create3d(context_provider)); @@ -9090,7 +9096,7 @@ TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) { root->test_properties()->AddChild(std::move(child)); layer_tree_host_impl->active_tree()->SetRootLayerForTesting(std::move(root)); layer_tree_host_impl->active_tree()->BuildPropertyTreesForTesting(); - layer_tree_host_impl->active_tree()->set_local_surface_id( + layer_tree_host_impl->active_tree()->SetLocalSurfaceIdFromParent( viz::LocalSurfaceId(1, base::UnguessableToken::Deserialize(2u, 3u))); TestFrameData frame; @@ -9190,11 +9196,10 @@ class FakeLayerWithQuads : public LayerImpl { }; TEST_F(LayerTreeHostImplTest, LayersFreeTextures) { - std::unique_ptr<TestWebGraphicsContext3D> context = - TestWebGraphicsContext3D::Create(); - TestWebGraphicsContext3D* context3d = context.get(); + auto gl_owned = std::make_unique<viz::TestGLES2Interface>(); + viz::TestGLES2Interface* gl = gl_owned.get(); std::unique_ptr<LayerTreeFrameSink> layer_tree_frame_sink( - FakeLayerTreeFrameSink::Create3d(std::move(context))); + FakeLayerTreeFrameSink::Create3d(std::move(gl_owned))); CreateHostImpl(DefaultSettings(), std::move(layer_tree_frame_sink)); std::unique_ptr<LayerImpl> root_layer = @@ -9215,27 +9220,21 @@ TEST_F(LayerTreeHostImplTest, LayersFreeTextures) { host_impl_->active_tree()->SetRootLayerForTesting(std::move(root_layer)); host_impl_->active_tree()->BuildPropertyTreesForTesting(); - EXPECT_EQ(0u, context3d->NumTextures()); + EXPECT_EQ(0u, gl->NumTextures()); TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); - EXPECT_GT(context3d->NumTextures(), 0u); + EXPECT_GT(gl->NumTextures(), 0u); // Kill the layer tree. host_impl_->active_tree()->DetachLayers(); // There should be no textures left in use after. - EXPECT_EQ(0u, context3d->NumTextures()); + EXPECT_EQ(0u, gl->NumTextures()); } -class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D { - public: - MOCK_METHOD1(useProgram, void(GLuint program)); - MOCK_METHOD4(drawElements, - void(GLenum mode, GLsizei count, GLenum type, GLintptr offset)); -}; TEST_F(LayerTreeHostImplTest, HasTransparentBackground) { SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1)); @@ -9548,8 +9547,7 @@ TEST_F(LayerTreeHostImplTest, MemoryLimits) { AnimationHost::CreateForTesting(ThreadInstance::IMPL), 0, nullptr); // Gpu compositing. - layer_tree_frame_sink_ = - FakeLayerTreeFrameSink::Create3d(TestWebGraphicsContext3D::Create()); + layer_tree_frame_sink_ = FakeLayerTreeFrameSink::Create3d(); host_impl_->SetVisible(true); host_impl_->InitializeRenderer(layer_tree_frame_sink_.get()); { @@ -9712,58 +9710,58 @@ TEST_F(LayerTreeHostImplTestPrepareTiles, PrepareTilesWhenInvisible) { } TEST_F(LayerTreeHostImplTest, UIResourceManagement) { - std::unique_ptr<TestWebGraphicsContext3D> context = - TestWebGraphicsContext3D::Create(); - TestWebGraphicsContext3D* context3d = context.get(); + auto gl_owned = std::make_unique<viz::TestGLES2Interface>(); + viz::TestGLES2Interface* gl = gl_owned.get(); + std::unique_ptr<FakeLayerTreeFrameSink> layer_tree_frame_sink = - FakeLayerTreeFrameSink::Create3d(); + FakeLayerTreeFrameSink::Create3d(std::move(gl_owned)); CreateHostImpl(DefaultSettings(), std::move(layer_tree_frame_sink)); - EXPECT_EQ(0u, context3d->NumTextures()); + EXPECT_EQ(0u, gl->NumTextures()); UIResourceId ui_resource_id = 1; bool is_opaque = false; UIResourceBitmap bitmap(gfx::Size(1, 1), is_opaque); host_impl_->CreateUIResource(ui_resource_id, bitmap); - EXPECT_EQ(1u, context3d->NumTextures()); + EXPECT_EQ(1u, gl->NumTextures()); viz::ResourceId id1 = host_impl_->ResourceIdForUIResource(ui_resource_id); EXPECT_NE(0u, id1); // Multiple requests with the same id is allowed. The previous texture is // deleted. host_impl_->CreateUIResource(ui_resource_id, bitmap); - EXPECT_EQ(1u, context3d->NumTextures()); + EXPECT_EQ(1u, gl->NumTextures()); viz::ResourceId id2 = host_impl_->ResourceIdForUIResource(ui_resource_id); EXPECT_NE(0u, id2); EXPECT_NE(id1, id2); // Deleting invalid UIResourceId is allowed and does not change state. host_impl_->DeleteUIResource(-1); - EXPECT_EQ(1u, context3d->NumTextures()); + EXPECT_EQ(1u, gl->NumTextures()); // Should return zero for invalid UIResourceId. Number of textures should // not change. EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1)); - EXPECT_EQ(1u, context3d->NumTextures()); + EXPECT_EQ(1u, gl->NumTextures()); host_impl_->DeleteUIResource(ui_resource_id); EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id)); - EXPECT_EQ(0u, context3d->NumTextures()); + EXPECT_EQ(0u, gl->NumTextures()); // Should not change state for multiple deletion on one UIResourceId host_impl_->DeleteUIResource(ui_resource_id); - EXPECT_EQ(0u, context3d->NumTextures()); + EXPECT_EQ(0u, gl->NumTextures()); } TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) { - std::unique_ptr<TestWebGraphicsContext3D> context = - TestWebGraphicsContext3D::Create(); - TestWebGraphicsContext3D* context3d = context.get(); - context3d->set_support_compressed_texture_etc1(true); + auto gl_owned = std::make_unique<viz::TestGLES2Interface>(); + gl_owned->set_support_compressed_texture_etc1(true); + viz::TestGLES2Interface* gl = gl_owned.get(); + CreateHostImpl(DefaultSettings(), - FakeLayerTreeFrameSink::Create3d(std::move(context))); + FakeLayerTreeFrameSink::Create3d(std::move(gl_owned))); - EXPECT_EQ(0u, context3d->NumTextures()); + EXPECT_EQ(0u, gl->NumTextures()); gfx::Size size(4, 4); // SkImageInfo has no support for ETC1. The |info| below contains the right @@ -9776,7 +9774,7 @@ TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) { UIResourceBitmap bitmap(std::move(pixel_ref), size); UIResourceId ui_resource_id = 1; host_impl_->CreateUIResource(ui_resource_id, bitmap); - EXPECT_EQ(1u, context3d->NumTextures()); + EXPECT_EQ(1u, gl->NumTextures()); viz::ResourceId id1 = host_impl_->ResourceIdForUIResource(ui_resource_id); EXPECT_NE(0u, id1); } @@ -9854,9 +9852,8 @@ TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) { constexpr double refresh_rate = 60.0; auto layer_tree_frame_sink = std::make_unique<viz::TestLayerTreeFrameSink>( context_provider, viz::TestContextProvider::CreateWorker(), nullptr, - nullptr, viz::RendererSettings(), - base::ThreadTaskRunnerHandle::Get().get(), synchronous_composite, - disable_display_vsync, refresh_rate); + viz::RendererSettings(), base::ThreadTaskRunnerHandle::Get().get(), + synchronous_composite, disable_display_vsync, refresh_rate); layer_tree_frame_sink->SetClient(&test_client); CreateHostImpl(DefaultSettings(), std::move(layer_tree_frame_sink)); @@ -10257,8 +10254,7 @@ TEST_F(LayerTreeHostImplLatencyInfoRendererTest, // 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); + latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0); std::unique_ptr<SwapPromise> swap_promise( new LatencyInfoSwapPromise(latency_info)); host_impl_->active_tree()->QueuePinnedSwapPromise(std::move(swap_promise)); @@ -10313,8 +10309,7 @@ TEST_F(LayerTreeHostImplLatencyInfoUITest, // 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); + latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0); std::unique_ptr<SwapPromise> swap_promise( new LatencyInfoSwapPromise(latency_info)); host_impl_->active_tree()->QueuePinnedSwapPromise(std::move(swap_promise)); @@ -11626,6 +11621,52 @@ TEST_F(LayerTreeHostImplTest, OnDrawConstraintSetNeedsRedraw) { EXPECT_FALSE(last_on_draw_frame_->has_no_damage); } +// TODO(gyuyoung): OnMemoryPressure disabled on ASAN, TSAN, Android, windows +// due to the test failure. Will be handled on +// http://crbug.com/839687. +#if defined(OS_WIN) || defined(OS_ANDROID) || defined(ADDRESS_SANITIZER) || \ + defined(THREAD_SANITIZER) || defined(MEMORY_SANITIZER) || \ + defined(LEAK_SANITIZER) +#define MAYBE_OnMemoryPressure DISABLED_OnMemoryPressure +#else +#define MAYBE_OnMemoryPressure OnMemoryPressure +#endif + +TEST_F(LayerTreeHostImplTest, MAYBE_OnMemoryPressure) { + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableLowEndDeviceMode); + + const gfx::Size viewport_size(100, 100); + host_impl_->SetViewportSize(viewport_size); + host_impl_->CreatePendingTree(); + scoped_refptr<FakeRasterSource> raster_source( + FakeRasterSource::CreateFilled(viewport_size)); + std::unique_ptr<FakePictureLayerImpl> layer( + FakePictureLayerImpl::CreateWithRasterSource(host_impl_->pending_tree(), + 11, raster_source)); + layer->SetBounds(viewport_size); + layer->SetDrawsContent(true); + host_impl_->pending_tree()->SetRootLayerForTesting(std::move(layer)); + host_impl_->pending_tree()->BuildPropertyTreesForTesting(); + host_impl_->ActivateSyncTree(); + const gfx::Transform draw_transform; + host_impl_->OnDraw(draw_transform, gfx::Rect(viewport_size), false); + + std::unique_ptr<base::ProcessMetrics> metric( + base::ProcessMetrics::CreateCurrentProcessMetrics()); + size_t current_memory_usage = metric->GetMallocUsage(); + + base::MemoryPressureListener::SimulatePressureNotification( + base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL); + base::RunLoop().RunUntilIdle(); + + size_t memory_usage_after_memory_pressure = metric->GetMallocUsage(); + + // Memory usage after the memory pressure should be less than previous one. + EXPECT_LT(memory_usage_after_memory_pressure, current_memory_usage); + EXPECT_FALSE(host_impl_->use_gpu_rasterization()); +} + // We will force the touch event handler to be passive if we touch on a layer // which is the current scrolling layer. TEST_F(LayerTreeHostImplTest, TouchInsideFlingLayer) { @@ -13464,8 +13505,7 @@ TEST_F(LayerTreeHostImplTest, RecomputeGpuRasterOnLayerTreeFrameSinkChange) { host_impl_->SetVisible(true); // InitializeRenderer with a gpu-raster enabled output surface. - auto gpu_raster_layer_tree_frame_sink = - FakeLayerTreeFrameSink::Create3d(TestWebGraphicsContext3D::Create()); + auto gpu_raster_layer_tree_frame_sink = FakeLayerTreeFrameSink::Create3d(); host_impl_->InitializeRenderer(gpu_raster_layer_tree_frame_sink.get()); EXPECT_TRUE(host_impl_->use_gpu_rasterization()); @@ -13743,7 +13783,10 @@ TEST_F(LayerTreeHostImplTest, CheckerImagingTileInvalidation) { std::unique_ptr<FakeRecordingSource> recording_source = FakeRecordingSource::CreateFilledRecordingSource(layer_size); PaintImage checkerable_image = - CreateDiscardablePaintImage(gfx::Size(500, 500)); + PaintImageBuilder::WithCopy( + CreateDiscardablePaintImage(gfx::Size(500, 500))) + .set_decoding_mode(PaintImage::DecodingMode::kAsync) + .TakePaintImage(); recording_source->add_draw_image(checkerable_image, gfx::Point(0, 0)); SkColor non_solid_color = SkColorSetARGB(128, 45, 56, 67); @@ -13773,6 +13816,11 @@ TEST_F(LayerTreeHostImplTest, CheckerImagingTileInvalidation) { root->SetDrawsContent(true); pending_tree->BuildPropertyTreesForTesting(); + // Update the decoding state map for the tracker so it knows the correct + // decoding preferences for the image. + host_impl_->tile_manager()->checker_image_tracker().UpdateImageDecodingHints( + raster_source->TakeDecodingModeMap()); + // CompleteCommit which should perform a PrepareTiles, adding tilings for the // root layer, each one having a raster task. host_impl_->CommitComplete(); @@ -14251,5 +14299,211 @@ TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToRenderFrameMetadata) { EXPECT_TRUE(selection_2.end.visible()); } +// Tests ScrollBy() to see if the method sets the scroll tree's currently +// scrolling node and the ScrollState properly. +TEST_F(LayerTreeHostImplTest, ScrollByScrollingNode) { + SetupScrollAndContentsLayers(gfx::Size(100, 100)); + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + + // Create a ScrollState object with no scrolling element. + ScrollStateData scroll_state_data; + scroll_state_data.set_current_native_scrolling_element(ElementId()); + std::unique_ptr<ScrollState> scroll_state(new ScrollState(scroll_state_data)); + + ScrollTree& scroll_tree = + host_impl_->active_tree()->property_trees()->scroll_tree; + + EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, + host_impl_ + ->ScrollBegin(BeginState(gfx::Point()).get(), + InputHandler::TOUCHSCREEN) + .thread); + + ScrollNode* scroll_node = scroll_tree.CurrentlyScrollingNode(); + EXPECT_TRUE(scroll_node); + + host_impl_->ScrollBy(scroll_state.get()); + + // Check to see the scroll tree's currently scrolling node is + // still the same. |scroll_state|'s scrolling node should match + // it. + EXPECT_EQ(scroll_node, scroll_tree.CurrentlyScrollingNode()); + EXPECT_EQ(scroll_state->data()->current_native_scrolling_node(), + scroll_tree.CurrentlyScrollingNode()); + EXPECT_EQ(scroll_state->data()->current_native_scrolling_element(), + scroll_tree.CurrentlyScrollingNode()->element_id); + + // Set the scroll tree's currently scrolling node to null. Calling + // ScrollBy() should set the node to the one inside |scroll_state|. + host_impl_->active_tree()->SetCurrentlyScrollingNode(nullptr); + EXPECT_FALSE(scroll_tree.CurrentlyScrollingNode()); + + host_impl_->ScrollBy(scroll_state.get()); + + EXPECT_EQ(scroll_node, scroll_tree.CurrentlyScrollingNode()); + EXPECT_EQ(scroll_state->data()->current_native_scrolling_node(), + scroll_tree.CurrentlyScrollingNode()); + EXPECT_EQ(scroll_state->data()->current_native_scrolling_element(), + scroll_tree.CurrentlyScrollingNode()->element_id); +} + +class HitTestRegionListGeneratingLayerTreeHostImplTest + : public LayerTreeHostImplTest { + public: + bool CreateHostImpl( + const LayerTreeSettings& settings, + std::unique_ptr<LayerTreeFrameSink> layer_tree_frame_sink) override { + // Enable hit test data generation with the CompositorFrame. + LayerTreeSettings new_settings = settings; + new_settings.build_hit_test_data = true; + return CreateHostImplWithTaskRunnerProvider( + new_settings, std::move(layer_tree_frame_sink), &task_runner_provider_); + } +}; + +// When disabled, no HitTestRegionList should be generated. +// Test to ensure that hit test data is created correctly from the active layer +// tree. +TEST_F(LayerTreeHostImplTest, DisabledBuildHitTestData) { + // Setup surface layers in LayerTreeHostImpl. + host_impl_->CreatePendingTree(); + host_impl_->ActivateSyncTree(); + host_impl_->SetViewportSize(gfx::Size(1024, 768)); + + std::unique_ptr<LayerImpl> root = + LayerImpl::Create(host_impl_->active_tree(), 1); + std::unique_ptr<SurfaceLayerImpl> surface_child = + SurfaceLayerImpl::Create(host_impl_->active_tree(), 3); + + surface_child->SetPosition(gfx::PointF(50, 50)); + surface_child->SetBounds(gfx::Size(100, 100)); + surface_child->SetDrawsContent(true); + surface_child->SetSurfaceHitTestable(true); + + root->test_properties()->AddChild(std::move(surface_child)); + host_impl_->active_tree()->SetRootLayerForTesting(std::move(root)); + + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + + base::Optional<viz::HitTestRegionList> hit_test_region_list = + host_impl_->BuildHitTestData(); + EXPECT_FALSE(hit_test_region_list); +} + +// Test to ensure that hit test data is created correctly from the active layer +// tree. +TEST_F(HitTestRegionListGeneratingLayerTreeHostImplTest, BuildHitTestData) { + // Setup surface layers in LayerTreeHostImpl. + host_impl_->CreatePendingTree(); + host_impl_->ActivateSyncTree(); + + // The structure of the layer tree: + // +-Root (1024x768) + // +---intermediate_layer (200, 300), 200x200 + // +-----surface_child1 (50, 50), 100x100, Rotate(45) + // +---surface_child2 (450, 300), 100x100 + // +---overlapping_layer (500, 350), 200x200 + std::unique_ptr<LayerImpl> intermediate_layer = + LayerImpl::Create(host_impl_->active_tree(), 2); + std::unique_ptr<SurfaceLayerImpl> surface_child1 = + SurfaceLayerImpl::Create(host_impl_->active_tree(), 3); + std::unique_ptr<SurfaceLayerImpl> surface_child2 = + SurfaceLayerImpl::Create(host_impl_->active_tree(), 4); + std::unique_ptr<LayerImpl> overlapping_layer = + LayerImpl::Create(host_impl_->active_tree(), 5); + + host_impl_->SetViewportSize(gfx::Size(1024, 768)); + + intermediate_layer->SetPosition(gfx::PointF(200, 300)); + intermediate_layer->SetBounds(gfx::Size(200, 200)); + + surface_child1->SetPosition(gfx::PointF(50, 50)); + surface_child1->SetBounds(gfx::Size(100, 100)); + gfx::Transform rotate; + rotate.Rotate(45); + surface_child1->test_properties()->transform = rotate; + surface_child1->SetDrawsContent(true); + surface_child1->SetSurfaceHitTestable(true); + + surface_child2->SetPosition(gfx::PointF(450, 300)); + surface_child2->SetBounds(gfx::Size(100, 100)); + surface_child2->SetDrawsContent(true); + surface_child2->SetSurfaceHitTestable(true); + + overlapping_layer->SetPosition(gfx::PointF(500, 350)); + overlapping_layer->SetBounds(gfx::Size(200, 200)); + overlapping_layer->SetDrawsContent(true); + + viz::LocalSurfaceId child_local_surface_id(2, + base::UnguessableToken::Create()); + viz::FrameSinkId frame_sink_id(2, 0); + viz::SurfaceId child_surface_id(frame_sink_id, child_local_surface_id); + surface_child1->SetPrimarySurfaceId(child_surface_id, base::nullopt); + surface_child2->SetPrimarySurfaceId(child_surface_id, base::nullopt); + + std::unique_ptr<LayerImpl> root = + LayerImpl::Create(host_impl_->active_tree(), 1); + host_impl_->active_tree()->SetRootLayerForTesting(std::move(root)); + intermediate_layer->test_properties()->AddChild(std::move(surface_child1)); + host_impl_->active_tree() + ->root_layer_for_testing() + ->test_properties() + ->AddChild(std::move(intermediate_layer)); + host_impl_->active_tree() + ->root_layer_for_testing() + ->test_properties() + ->AddChild(std::move(surface_child2)); + host_impl_->active_tree() + ->root_layer_for_testing() + ->test_properties() + ->AddChild(std::move(overlapping_layer)); + + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + + constexpr gfx::Rect kFrameRect(0, 0, 1024, 768); + + base::Optional<viz::HitTestRegionList> hit_test_region_list = + host_impl_->BuildHitTestData(); + // Generating HitTestRegionList should have been enabled for this test. + ASSERT_TRUE(hit_test_region_list); + + // Since surface_child2 draws in front of surface_child1, it should also be in + // the front of the hit test region list. + uint32_t expected_flags = viz::HitTestRegionFlags::kHitTestMouse | + viz::HitTestRegionFlags::kHitTestTouch | + viz::HitTestRegionFlags::kHitTestMine; + EXPECT_EQ(expected_flags, hit_test_region_list->flags); + EXPECT_EQ(kFrameRect, hit_test_region_list->bounds); + EXPECT_EQ(2u, hit_test_region_list->regions.size()); + + EXPECT_EQ(child_surface_id.frame_sink_id(), + hit_test_region_list->regions[1].frame_sink_id); + expected_flags = viz::HitTestRegionFlags::kHitTestMouse | + viz::HitTestRegionFlags::kHitTestTouch | + viz::HitTestRegionFlags::kHitTestChildSurface; + EXPECT_EQ(expected_flags, hit_test_region_list->regions[1].flags); + gfx::Transform child1_transform; + child1_transform.Rotate(-45); + child1_transform.Translate(-250, -350); + EXPECT_TRUE(child1_transform.ApproximatelyEqual( + hit_test_region_list->regions[1].transform)); + EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), + hit_test_region_list->regions[1].rect.ToString()); + + EXPECT_EQ(child_surface_id.frame_sink_id(), + hit_test_region_list->regions[0].frame_sink_id); + expected_flags = viz::HitTestRegionFlags::kHitTestMouse | + viz::HitTestRegionFlags::kHitTestTouch | + viz::HitTestRegionFlags::kHitTestChildSurface | + viz::HitTestRegionFlags::kHitTestAsk; + EXPECT_EQ(expected_flags, hit_test_region_list->regions[0].flags); + gfx::Transform child2_transform; + child2_transform.Translate(-450, -300); + EXPECT_TRUE(child2_transform.ApproximatelyEqual( + hit_test_region_list->regions[0].transform)); + EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), + hit_test_region_list->regions[0].rect.ToString()); +} + } // namespace } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_perftest.cc b/chromium/cc/trees/layer_tree_host_perftest.cc index 92765547065..871e1a10a17 100644 --- a/chromium/cc/trees/layer_tree_host_perftest.cc +++ b/chromium/cc/trees/layer_tree_host_perftest.cc @@ -59,9 +59,8 @@ class LayerTreeHostPerfTest : public LayerTreeTest { !layer_tree_host()->GetSettings().single_thread_proxy_scheduler; return std::make_unique<viz::TestLayerTreeFrameSink>( compositor_context_provider, std::move(worker_context_provider), - shared_bitmap_manager(), gpu_memory_buffer_manager(), renderer_settings, - ImplThreadTaskRunner(), synchronous_composite, disable_display_vsync, - refresh_rate); + gpu_memory_buffer_manager(), renderer_settings, ImplThreadTaskRunner(), + synchronous_composite, disable_display_vsync, refresh_rate); } void BeginTest() override { @@ -140,7 +139,8 @@ class LayerTreeHostPerfTestJsonReader : public LayerTreeHostPerfTest { void ReadTestFile(const std::string& name) { base::FilePath test_data_dir; - ASSERT_TRUE(PathService::Get(viz::Paths::DIR_TEST_DATA, &test_data_dir)); + ASSERT_TRUE( + base::PathService::Get(viz::Paths::DIR_TEST_DATA, &test_data_dir)); base::FilePath json_file = test_data_dir.AppendASCII(name + ".json"); ASSERT_TRUE(base::ReadFileToString(json_file, &json_)); } diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc b/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc index c0706014c1a..378d4338879 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc @@ -37,8 +37,8 @@ TEST_F(LayerTreeHostFiltersPixelTest, BackgroundFilterBlur) { 2.f, SkBlurImageFilter::kClamp_TileMode)); blur->SetBackgroundFilters(filters); -#if defined(OS_WIN) - // Windows has 436 pixels off by 1: crbug.com/259915 +#if defined(OS_WIN) || defined(ARCH_CPU_ARM64) + // Windows and ARM64 have 436 pixels off by 1: crbug.com/259915 float percentage_pixels_large_error = 1.09f; // 436px / (200*200) float percentage_pixels_small_error = 0.0f; float average_error_allowed_in_bad_pixels = 1.f; @@ -79,9 +79,14 @@ TEST_F(LayerTreeHostFiltersPixelTest, BackgroundFilterBlurOutsets) { 5.f, SkBlurImageFilter::kClamp_TileMode)); blur->SetBackgroundFilters(filters); -#if defined(OS_WIN) +#if defined(OS_WIN) || defined(_MIPS_ARCH_LOONGSON) || defined(ARCH_CPU_ARM64) +#if defined(OS_WIN) || defined(ARCH_CPU_ARM64) // Windows has 5.9325% pixels by at most 2: crbug.com/259922 float percentage_pixels_large_error = 6.0f; +#else + // Loongson has 8.685% pixels by at most 2: crbug.com/819110 + float percentage_pixels_large_error = 8.7f; +#endif float percentage_pixels_small_error = 0.0f; float average_error_allowed_in_bad_pixels = 2.f; int large_error_allowed = 2; @@ -141,12 +146,17 @@ TEST_F(LayerTreeHostFiltersPixelTest, BackgroundFilterBlurOffAxis) { 2.f, SkBlurImageFilter::kClamp_TileMode)); blur->SetBackgroundFilters(filters); +#if defined(OS_WIN) || defined(ARCH_CPU_ARM64) #if defined(OS_WIN) // Windows has 116 pixels off by at most 2: crbug.com/225027 float percentage_pixels_large_error = 0.3f; // 116px / (200*200), rounded up + int large_error_allowed = 2; +#else + float percentage_pixels_large_error = 0.25f; // 96px / (200*200), rounded up + int large_error_allowed = 1; +#endif float percentage_pixels_small_error = 0.0f; float average_error_allowed_in_bad_pixels = 1.f; - int large_error_allowed = 2; int small_error_allowed = 0; pixel_comparator_.reset(new FuzzyPixelComparator( true, // discard_alpha @@ -414,12 +424,21 @@ class ImageScaledBackgroundFilter : public LayerTreeHostFiltersPixelTest { filters.Append(FilterOperation::CreateGrayscaleFilter(1.0f)); filter->SetBackgroundFilters(filters); +#if defined(OS_WIN) || defined(_MIPS_ARCH_LOONGSON) || defined(ARCH_CPU_ARM64) #if defined(OS_WIN) // Windows has 153 pixels off by at most 2: crbug.com/225027 float percentage_pixels_large_error = 0.3825f; // 153px / (200*200) + int large_error_allowed = 2; +#elif defined(_MIPS_ARCH_LOONGSON) + // Loongson has 2 pixels off by at most 2: crbug.com/819075 + float percentage_pixels_large_error = 0.005f; // 2px / (200*200) + int large_error_allowed = 2; +#else + float percentage_pixels_large_error = 0.0325f; // 13px / (200*200) + int large_error_allowed = 1; +#endif float percentage_pixels_small_error = 0.0f; float average_error_allowed_in_bad_pixels = 1.f; - int large_error_allowed = 2; int small_error_allowed = 0; pixel_comparator_.reset(new FuzzyPixelComparator( true, // discard_alpha @@ -726,8 +745,8 @@ class RotatedDropShadowFilterTest : public LayerTreeHostFiltersPixelTest { background->AddChild(child); -#if defined(OS_WIN) - // Windows has 3 pixels off by 1: crbug.com/259915 +#if defined(OS_WIN) || defined(ARCH_CPU_ARM64) + // Windows and ARM64 have 3 pixels off by 1: crbug.com/259915 float percentage_pixels_large_error = 0.00333334f; // 3px / (300*300) float percentage_pixels_small_error = 0.0f; float average_error_allowed_in_bad_pixels = 1.f; @@ -941,9 +960,15 @@ class BlurFilterWithClip : public LayerTreeHostFiltersPixelTest { // Force the allocation a larger textures. set_enlarge_texture_amount(gfx::Size(50, 50)); +#if defined(OS_WIN) || defined(ARCH_CPU_ARM64) #if defined(OS_WIN) // Windows has 1880 pixels off by 1: crbug.com/259915 float percentage_pixels_large_error = 4.7f; // 1880px / (200*200) +#else + // Differences in floating point calculation on ARM means a small percentage + // of pixels will have small differences. + float percentage_pixels_large_error = 2.76f; // 1104px / (200*200) +#endif float percentage_pixels_small_error = 0.0f; float average_error_allowed_in_bad_pixels = 1.f; int large_error_allowed = 2; diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc index 02e0e7bf246..6a6cfa4d11e 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc @@ -312,13 +312,13 @@ TEST_P(LayerTreeHostMasksForBackgroundFiltersPixelTest, float average_error_allowed_in_bad_pixels = 100.0f; int large_error_allowed = 256; int small_error_allowed = 0; - pixel_comparator_.reset(new FuzzyPixelComparator( + pixel_comparator_ = std::make_unique<FuzzyPixelComparator>( true, // discard_alpha percentage_pixels_large_error, percentage_pixels_small_error, average_error_allowed_in_bad_pixels, large_error_allowed, - small_error_allowed)); + small_error_allowed); RunPixelResourceTest(background, base::FilePath( @@ -363,13 +363,13 @@ TEST_P(LayerTreeHostMasksForBackgroundFiltersPixelTest, float average_error_allowed_in_bad_pixels = 256.0f; int large_error_allowed = 256; int small_error_allowed = 0; - pixel_comparator_.reset(new FuzzyPixelComparator( + pixel_comparator_ = std::make_unique<FuzzyPixelComparator>( true, // discard_alpha percentage_pixels_large_error, percentage_pixels_small_error, average_error_allowed_in_bad_pixels, large_error_allowed, - small_error_allowed)); + small_error_allowed); RunPixelResourceTest(background, base::FilePath( @@ -428,13 +428,21 @@ class LayerTreeHostMaskAsBlendingPixelTest average_error_allowed_in_bad_pixels = 3.5f; large_error_allowed = 15; small_error_allowed = 1; + } else { +#if defined(ARCH_CPU_ARM64) + // Differences in floating point calculation on ARM means a small + // percentage of pixels will be off by 1. + percentage_pixels_error = 0.112f; + average_error_allowed_in_bad_pixels = 1.f; + large_error_allowed = 1; +#endif } - pixel_comparator_.reset(new FuzzyPixelComparator( + pixel_comparator_ = std::make_unique<FuzzyPixelComparator>( false, // discard_alpha percentage_pixels_error, percentage_pixels_small_error, average_error_allowed_in_bad_pixels, large_error_allowed, - small_error_allowed)); + small_error_allowed); } static scoped_refptr<Layer> CreateCheckerboardLayer(const gfx::Size& bounds) { @@ -714,6 +722,59 @@ TEST_P(LayerTreeHostMaskAsBlendingPixelTest, RotatedClippedCircleUnderflow) { "mask_as_blending_rotated_circle_underflow.png"))); } +TEST_P(LayerTreeHostMasksForBackgroundFiltersPixelTest, + MaskOfLayerWithBackgroundFilterAndBlend) { + scoped_refptr<SolidColorLayer> background = + CreateSolidColorLayer(gfx::Rect(128, 128), SK_ColorWHITE); + + gfx::Size picture_bounds(128, 128); + CheckerContentLayerClient picture_client_vertical(picture_bounds, + SK_ColorGREEN, true); + scoped_refptr<PictureLayer> picture_vertical = + PictureLayer::Create(&picture_client_vertical); + picture_vertical->SetBounds(picture_bounds); + picture_vertical->SetIsDrawable(true); + + CheckerContentLayerClient picture_client_horizontal(picture_bounds, + SK_ColorMAGENTA, false); + scoped_refptr<PictureLayer> picture_horizontal = + PictureLayer::Create(&picture_client_horizontal); + picture_horizontal->SetBounds(picture_bounds); + picture_horizontal->SetIsDrawable(true); + picture_horizontal->SetContentsOpaque(false); + picture_horizontal->SetBlendMode(SkBlendMode::kMultiply); + + FilterOperations filters; + filters.Append(FilterOperation::CreateGrayscaleFilter(1.0)); + picture_horizontal->SetBackgroundFilters(filters); + + background->AddChild(picture_vertical); + background->AddChild(picture_horizontal); + + gfx::Size mask_bounds(128, 128); + CircleContentLayerClient mask_client(mask_bounds); + scoped_refptr<PictureLayer> mask = PictureLayer::Create(&mask_client); + mask->SetBounds(mask_bounds); + mask->SetIsDrawable(true); + mask->SetLayerMaskType(mask_type_); + picture_horizontal->SetMaskLayer(mask.get()); + + float percentage_pixels_large_error = 0.062f; // 0.062%, ~10px / (128*128) + float percentage_pixels_small_error = 0.0f; + float average_error_allowed_in_bad_pixels = 200.0f; + int large_error_allowed = 256; + int small_error_allowed = 0; + pixel_comparator_ = std::make_unique<FuzzyPixelComparator>( + true, // discard_alpha + percentage_pixels_large_error, percentage_pixels_small_error, + average_error_allowed_in_bad_pixels, large_error_allowed, + small_error_allowed); + + RunPixelResourceTest(background, + base::FilePath(FILE_PATH_LITERAL( + "mask_of_background_filter_and_blend.png"))); +} + } // namespace } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_scrollbars.cc b/chromium/cc/trees/layer_tree_host_pixeltest_scrollbars.cc index a4f98ae353a..b251df562ab 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_scrollbars.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_scrollbars.cc @@ -150,7 +150,7 @@ TEST_F(LayerTreeHostScrollbarsPixelTest, HugeTransformScale) { background->AddChild(layer); scoped_refptr<TestInProcessContextProvider> context( - new TestInProcessContextProvider(nullptr, false)); + new TestInProcessContextProvider(/*enable_oop_rasterization=*/false)); context->BindToCurrentThread(); int max_texture_size = 0; context->ContextGL()->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc b/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc index bf42914b95d..eabe1909a4f 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc @@ -60,13 +60,13 @@ class LayerTreeHostTilesPixelTest : public LayerTreePixelTest { case PARTIAL_GPU_LOW_BIT_DEPTH: settings->gpu_rasterization_forced = true; settings->use_partial_raster = true; - settings->preferred_tile_format = viz::RGBA_4444; + settings->use_rgba_4444 = true; settings->unpremultiply_and_dither_low_bit_depth_tiles = true; break; case FULL_GPU_LOW_BIT_DEPTH: settings->gpu_rasterization_forced = true; settings->use_partial_raster = false; - settings->preferred_tile_format = viz::RGBA_4444; + settings->use_rgba_4444 = true; settings->unpremultiply_and_dither_low_bit_depth_tiles = true; break; } diff --git a/chromium/cc/trees/layer_tree_host_unittest.cc b/chromium/cc/trees/layer_tree_host_unittest.cc index acbd577abcd..e66bf23fa85 100644 --- a/chromium/cc/trees/layer_tree_host_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_unittest.cc @@ -65,6 +65,7 @@ #include "components/viz/service/display/output_surface.h" #include "components/viz/test/begin_frame_args_test.h" #include "components/viz/test/fake_output_surface.h" +#include "components/viz/test/test_gles2_interface.h" #include "components/viz/test/test_layer_tree_frame_sink.h" #include "components/viz/test/test_web_graphics_context_3d.h" #include "gpu/GLES2/gl2extchromium.h" @@ -460,14 +461,14 @@ class LayerTreeHostContextCacheTest : public LayerTreeHostTest { // Create the main viz::ContextProvider with a MockContextSupport. auto main_support = std::make_unique<MockContextSupport>(); mock_main_context_support_ = main_support.get(); - auto test_main_context_provider = viz::TestContextProvider::Create( - viz::TestWebGraphicsContext3D::Create(), std::move(main_support)); + auto test_main_context_provider = + viz::TestContextProvider::Create(std::move(main_support)); // Create the main viz::ContextProvider with a MockContextSupport. auto worker_support = std::make_unique<MockContextSupport>(); mock_worker_context_support_ = worker_support.get(); - auto test_worker_context_provider = viz::TestContextProvider::CreateWorker( - viz::TestWebGraphicsContext3D::Create(), std::move(worker_support)); + auto test_worker_context_provider = + viz::TestContextProvider::CreateWorker(std::move(worker_support)); // At init, visibility is set to true, so SetAggressivelyFreeResources will // be disabled. @@ -563,7 +564,8 @@ class LayerTreeHostFreesWorkerContextResourcesOnZeroMemoryLimitSynchronous } }; -SINGLE_AND_MULTI_THREAD_TEST_F( +// Android Webview only runs in multi-threaded compositing mode. +MULTI_THREAD_TEST_F( LayerTreeHostFreesWorkerContextResourcesOnZeroMemoryLimitSynchronous); // Test if the LTH successfully frees main and worker resources when the @@ -1231,9 +1233,12 @@ class LayerTreeHostTestEarlyDamageCheckStops : public LayerTreeHostTest { } } + void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override { + PostSetNeedsCommitToMainThread(); + } + void DidInvalidateLayerTreeFrameSink(LayerTreeHostImpl* impl) override { int frame_number = impl->active_tree()->source_frame_number(); - // Frames 0 and 1 invalidate because the early damage check is not enabled // during this setup. But frames 1 and 2 are not damaged, so the early // check should prevent frame 2 from invalidating. @@ -1250,8 +1255,6 @@ class LayerTreeHostTestEarlyDamageCheckStops : public LayerTreeHostTest { EndTest(); return; } - - PostSetNeedsCommitToMainThread(); } void AfterTest() override { @@ -1269,9 +1272,7 @@ class LayerTreeHostTestEarlyDamageCheckStops : public LayerTreeHostTest { // This behavior is specific to Android WebView, which only uses // multi-threaded compositor. -// Flaky on Win7 Tests (dbg)(1). https://crbug.com/813578 -// Flaky on linux_chromium_tsan_rel_ng. https://crbug.com/822473 -// MULTI_THREAD_TEST_F(LayerTreeHostTestEarlyDamageCheckStops); +MULTI_THREAD_TEST_F(LayerTreeHostTestEarlyDamageCheckStops); // Verify CanDraw() is false until first commit. class LayerTreeHostTestCantDrawBeforeCommit : public LayerTreeHostTest { @@ -2241,7 +2242,7 @@ class LayerTreeHostTestNoExtraCommitFromScrollbarInvalidate // a second commit as a result. layer_tree_host()->SetViewportSizeAndScale( layer_tree_host()->device_viewport_size(), 4.f, - layer_tree_host()->local_surface_id()); + layer_tree_host()->local_surface_id_from_parent()); break; default: // No extra commits. @@ -2286,7 +2287,7 @@ class LayerTreeHostTestDeviceScaleFactorChange : public LayerTreeHostTest { if (layer_tree_host()->SourceFrameNumber() == 1) { layer_tree_host()->SetViewportSizeAndScale( layer_tree_host()->device_viewport_size(), 4.f, - layer_tree_host()->local_surface_id()); + layer_tree_host()->local_surface_id_from_parent()); } } @@ -3811,7 +3812,6 @@ class OnDrawLayerTreeFrameSink : public viz::TestLayerTreeFrameSink { OnDrawLayerTreeFrameSink( scoped_refptr<viz::ContextProvider> compositor_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, base::SingleThreadTaskRunner* task_runner, @@ -3820,7 +3820,6 @@ class OnDrawLayerTreeFrameSink : public viz::TestLayerTreeFrameSink { base::Closure invalidate_callback) : TestLayerTreeFrameSink(std::move(compositor_context_provider), std::move(worker_context_provider), - shared_bitmap_manager, gpu_memory_buffer_manager, renderer_settings, task_runner, @@ -3862,8 +3861,8 @@ class LayerTreeHostTestAbortedCommitDoesntStallSynchronousCompositor base::Unretained(this)); auto frame_sink = std::make_unique<OnDrawLayerTreeFrameSink>( compositor_context_provider, std::move(worker_context_provider), - shared_bitmap_manager(), gpu_memory_buffer_manager(), renderer_settings, - ImplThreadTaskRunner(), false /* synchronous_composite */, refresh_rate, + gpu_memory_buffer_manager(), renderer_settings, ImplThreadTaskRunner(), + false /* synchronous_composite */, refresh_rate, std::move(on_draw_callback)); layer_tree_frame_sink_ = frame_sink.get(); return std::move(frame_sink); @@ -5710,19 +5709,22 @@ class LayerTreeHostTestBreakSwapPromiseForVisibility void SetVisibleFalseAndQueueSwapPromise() { layer_tree_host()->SetVisible(false); - std::unique_ptr<SwapPromise> swap_promise( - new TestSwapPromise(&swap_promise_result_)); + auto swap_promise = + std::make_unique<TestSwapPromise>(&swap_promise_result_); layer_tree_host()->GetSwapPromiseManager()->QueueSwapPromise( std::move(swap_promise)); } void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl, const viz::BeginFrameArgs& args) override { - MainThreadTaskRunner()->PostTask( - FROM_HERE, - base::BindOnce(&LayerTreeHostTestBreakSwapPromiseForVisibility:: - SetVisibleFalseAndQueueSwapPromise, - base::Unretained(this))); + if (!sent_queue_request_) { + sent_queue_request_ = true; + MainThreadTaskRunner()->PostTask( + FROM_HERE, + base::BindOnce(&LayerTreeHostTestBreakSwapPromiseForVisibility:: + SetVisibleFalseAndQueueSwapPromise, + base::Unretained(this))); + } } void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* host_impl, @@ -5742,11 +5744,10 @@ class LayerTreeHostTestBreakSwapPromiseForVisibility } TestSwapPromiseResult swap_promise_result_; + bool sent_queue_request_ = false; }; -// Flaky: https://crbug.com/657910 -// SINGLE_AND_MULTI_THREAD_TEST_F( -// LayerTreeHostTestBreakSwapPromiseForVisibility); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestBreakSwapPromiseForVisibility); class SimpleSwapPromiseMonitor : public SwapPromiseMonitor { public: @@ -5895,41 +5896,43 @@ class LayerTreeHostTestHighResRequiredAfterEvictingUIResources LayerTreeHostTest::SetupTree(); ui_resource_ = FakeScopedUIResource::Create(layer_tree_host()->GetUIResourceManager()); - client_.set_bounds(layer_tree_host()->root_layer()->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override { + if (TestEnded()) + return; + host_impl->EvictAllUIResources(); // Existence of evicted UI resources will trigger NEW_CONTENT_TAKES_PRIORITY // mode. Active tree should require high-res to draw after entering this // mode to ensure that high-res tiles are also required for a pending tree // to be activated. EXPECT_TRUE(host_impl->RequiresHighResToDraw()); + + MainThreadTaskRunner()->PostTask( + FROM_HERE, + base::BindOnce( + &LayerTreeHostTestHighResRequiredAfterEvictingUIResources:: + DeleteResourceAndEndTest, + base::Unretained(this))); } - void DidCommit() override { - int frame = layer_tree_host()->SourceFrameNumber(); - switch (frame) { - case 1: - PostSetNeedsCommitToMainThread(); - break; - case 2: - ui_resource_ = nullptr; - EndTest(); - break; - } + void DeleteResourceAndEndTest() { + // This must be destroyed before the test ends and tears down the + // LayerTreeHost. It causes another commit+activation though, which + // may run before the test exits. + ui_resource_ = nullptr; + EndTest(); } void AfterTest() override {} - FakeContentLayerClient client_; std::unique_ptr<FakeScopedUIResource> ui_resource_; }; -// This test is flaky, see http://crbug.com/386199 -// MULTI_THREAD_TEST_F(LayerTreeHostTestHighResRequiredAfterEvictingUIResources) +MULTI_THREAD_TEST_F(LayerTreeHostTestHighResRequiredAfterEvictingUIResources); class LayerTreeHostTestGpuRasterizationDefault : public LayerTreeHostTest { protected: @@ -6323,10 +6326,6 @@ class LayerTreeHostTestWillBeginImplFrameHasDidFinishImplFrame : will_begin_impl_frame_count_(0), did_finish_impl_frame_count_(0) {} void BeginTest() override { - // Test terminates when a main frame is no longer expected so request that - // this message is actually sent. - layer_tree_host()->RequestBeginMainFrameNotExpected(true); - PostSetNeedsCommitToMainThread(); } @@ -6341,27 +6340,20 @@ class LayerTreeHostTestWillBeginImplFrameHasDidFinishImplFrame did_finish_impl_frame_count_++; EXPECT_EQ(will_begin_impl_frame_count_, did_finish_impl_frame_count_); - // Request a number of commits to cause multiple impl frames. We expect to - // get one more impl frames than the number of commits requested because - // after a commit it takes one frame to become idle. - if (did_finish_impl_frame_count_ < kExpectedNumImplFrames - 1) - PostSetNeedsCommitToMainThread(); + // Trigger a new impl frame until we are done testing. + if (did_finish_impl_frame_count_ < kExpectedNumImplFrames) + PostSetNeedsRedrawToMainThread(); + else + EndTest(); } - void BeginMainFrameNotExpectedSoon() override { EndTest(); } - void AfterTest() override { EXPECT_GT(will_begin_impl_frame_count_, 0); EXPECT_GT(did_finish_impl_frame_count_, 0); EXPECT_EQ(will_begin_impl_frame_count_, did_finish_impl_frame_count_); - // TODO(mithro): Figure out why the multithread version of this test - // sometimes has one more frame then expected. Possibly related to - // http://crbug.com/443185 - if (!HasImplThread()) { - EXPECT_EQ(will_begin_impl_frame_count_, kExpectedNumImplFrames); - EXPECT_EQ(did_finish_impl_frame_count_, kExpectedNumImplFrames); - } + EXPECT_EQ(will_begin_impl_frame_count_, kExpectedNumImplFrames); + EXPECT_EQ(did_finish_impl_frame_count_, kExpectedNumImplFrames); } private: @@ -6593,9 +6585,8 @@ class LayerTreeHostTestSynchronousCompositeSwapPromise !layer_tree_host()->GetSettings().single_thread_proxy_scheduler; return std::make_unique<viz::TestLayerTreeFrameSink>( compositor_context_provider, std::move(worker_context_provider), - shared_bitmap_manager(), gpu_memory_buffer_manager(), renderer_settings, - ImplThreadTaskRunner(), synchronous_composite, disable_display_vsync, - refresh_rate); + gpu_memory_buffer_manager(), renderer_settings, ImplThreadTaskRunner(), + synchronous_composite, disable_display_vsync, refresh_rate); } void BeginTest() override { @@ -7400,478 +7391,6 @@ class LayerTreeHostTestUpdateCopyRequests : public LayerTreeHostTest { SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestUpdateCopyRequests); -class LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin - : public LayerTreeTest { - protected: - void SetupTree() override { - // The masked layer has bounds 50x50, but it has a child that causes - // the surface bounds to be larger. It also has a parent that clips the - // masked layer and its surface. - - scoped_refptr<Layer> root = Layer::Create(); - - scoped_refptr<FakePictureLayer> content_layer = - FakePictureLayer::Create(&client_); - - std::unique_ptr<RecordingSource> recording_source = - FakeRecordingSource::CreateFilledRecordingSource(gfx::Size(100, 100)); - PaintFlags paint1, paint2; - static_cast<FakeRecordingSource*>(recording_source.get()) - ->add_draw_rect_with_flags(gfx::Rect(0, 0, 100, 90), paint1); - static_cast<FakeRecordingSource*>(recording_source.get()) - ->add_draw_rect_with_flags(gfx::Rect(0, 90, 100, 10), paint2); - client_.set_fill_with_nonsolid_color(true); - static_cast<FakeRecordingSource*>(recording_source.get())->Rerecord(); - - scoped_refptr<FakePictureLayer> mask_layer = - FakePictureLayer::CreateWithRecordingSource( - &client_, std::move(recording_source)); - content_layer->SetMaskLayer(mask_layer.get()); - - gfx::Size root_size(100, 100); - root->SetBounds(root_size); - - gfx::Size layer_size(100, 100); - content_layer->SetBounds(layer_size); - - gfx::Size mask_size(100, 100); - mask_layer->SetBounds(mask_size); - mask_layer->SetLayerMaskType(Layer::LayerMaskType::MULTI_TEXTURE_MASK); - mask_layer_id_ = mask_layer->id(); - - layer_tree_host()->SetRootLayer(root); - LayerTreeTest::SetupTree(); - scoped_refptr<Layer> outer_viewport_scroll_layer = Layer::Create(); - outer_viewport_scroll_layer->SetBounds(layer_size); - CreateVirtualViewportLayers(root.get(), outer_viewport_scroll_layer, - gfx::Size(50, 50), gfx::Size(50, 50), - layer_tree_host()); - layer_tree_host()->outer_viewport_container_layer()->SetMasksToBounds(true); - outer_viewport_scroll_layer->AddChild(content_layer); - - client_.set_bounds(root->bounds()); - outer_viewport_scroll_layer->SetScrollOffset(gfx::ScrollOffset(50, 50)); - } - - void BeginTest() override { PostSetNeedsCommitToMainThread(); } - - DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, - LayerTreeHostImpl::FrameData* frame_data, - DrawResult draw_result) override { - EXPECT_EQ(2u, frame_data->render_passes.size()); - viz::RenderPass* root_pass = frame_data->render_passes.back().get(); - EXPECT_EQ(2u, root_pass->quad_list.size()); - - // There's a solid color quad under everything. - EXPECT_EQ(viz::DrawQuad::SOLID_COLOR, - root_pass->quad_list.back()->material); - - EXPECT_EQ(viz::DrawQuad::RENDER_PASS, - root_pass->quad_list.front()->material); - const viz::RenderPassDrawQuad* render_pass_quad = - viz::RenderPassDrawQuad::MaterialCast(root_pass->quad_list.front()); - EXPECT_EQ(gfx::Rect(50, 50, 50, 50).ToString(), - render_pass_quad->rect.ToString()); - if (host_impl->settings().enable_mask_tiling) { - PictureLayerImpl* mask_layer_impl = static_cast<PictureLayerImpl*>( - host_impl->active_tree()->LayerById(mask_layer_id_)); - gfx::SizeF texture_size( - mask_layer_impl->CalculateTileSize(mask_layer_impl->bounds())); - EXPECT_EQ( - gfx::RectF(50.f / texture_size.width(), 50.f / texture_size.height(), - 50.f / texture_size.width(), 50.f / texture_size.height()) - .ToString(), - render_pass_quad->mask_uv_rect.ToString()); - } else { - EXPECT_EQ(gfx::ScaleRect(gfx::RectF(50.f, 50.f, 50.f, 50.f), 1.f / 100.f) - .ToString(), - render_pass_quad->mask_uv_rect.ToString()); - } - EndTest(); - return draw_result; - } - - void AfterTest() override {} - - int mask_layer_id_; - FakeContentLayerClient client_; -}; - -class LayerTreeTestSingleTextureMaskLayerForSurfaceWithContentRectNotAtOrigin - : public LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->enable_mask_tiling = false; - } -}; - -SINGLE_AND_MULTI_THREAD_TEST_F( - LayerTreeTestSingleTextureMaskLayerForSurfaceWithContentRectNotAtOrigin); - -class LayerTreeTestMultiTextureMaskLayerForSurfaceWithContentRectNotAtOrigin - : public LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->enable_mask_tiling = true; - } -}; - -SINGLE_AND_MULTI_THREAD_TEST_F( - LayerTreeTestMultiTextureMaskLayerForSurfaceWithContentRectNotAtOrigin); - -class LayerTreeTestMaskLayerForSurfaceWithClippedLayer : public LayerTreeTest { - protected: - void SetupTree() override { - // The masked layer has bounds 50x50, but it has a child that causes - // the surface bounds to be larger. It also has a parent that clips the - // masked layer and its surface. - - scoped_refptr<Layer> root = Layer::Create(); - - scoped_refptr<Layer> clipping_layer = Layer::Create(); - root->AddChild(clipping_layer); - - scoped_refptr<FakePictureLayer> content_layer = - FakePictureLayer::Create(&client_); - clipping_layer->AddChild(content_layer); - - scoped_refptr<FakePictureLayer> content_child_layer = - FakePictureLayer::Create(&client_); - content_layer->AddChild(content_child_layer); - - std::unique_ptr<RecordingSource> recording_source = - FakeRecordingSource::CreateFilledRecordingSource(gfx::Size(50, 50)); - PaintFlags paint1, paint2; - static_cast<FakeRecordingSource*>(recording_source.get()) - ->add_draw_rect_with_flags(gfx::Rect(0, 0, 50, 40), paint1); - static_cast<FakeRecordingSource*>(recording_source.get()) - ->add_draw_rect_with_flags(gfx::Rect(0, 40, 50, 10), paint2); - client_.set_fill_with_nonsolid_color(true); - static_cast<FakeRecordingSource*>(recording_source.get())->Rerecord(); - - scoped_refptr<FakePictureLayer> mask_layer = - FakePictureLayer::CreateWithRecordingSource( - &client_, std::move(recording_source)); - content_layer->SetMaskLayer(mask_layer.get()); - - gfx::Size root_size(100, 100); - root->SetBounds(root_size); - - gfx::PointF clipping_origin(20.f, 10.f); - gfx::Size clipping_size(10, 20); - clipping_layer->SetBounds(clipping_size); - clipping_layer->SetPosition(clipping_origin); - clipping_layer->SetMasksToBounds(true); - - gfx::Size layer_size(50, 50); - content_layer->SetBounds(layer_size); - content_layer->SetPosition(gfx::PointF() - - clipping_origin.OffsetFromOrigin()); - - gfx::Size child_size(50, 50); - content_child_layer->SetBounds(child_size); - content_child_layer->SetPosition(gfx::PointF(20.f, 0.f)); - - gfx::Size mask_size(50, 50); - mask_layer->SetBounds(mask_size); - mask_layer->SetLayerMaskType(Layer::LayerMaskType::MULTI_TEXTURE_MASK); - mask_layer_id_ = mask_layer->id(); - - layer_tree_host()->SetRootLayer(root); - LayerTreeTest::SetupTree(); - client_.set_bounds(root->bounds()); - } - - void BeginTest() override { PostSetNeedsCommitToMainThread(); } - - DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, - LayerTreeHostImpl::FrameData* frame_data, - DrawResult draw_result) override { - EXPECT_EQ(2u, frame_data->render_passes.size()); - viz::RenderPass* root_pass = frame_data->render_passes.back().get(); - EXPECT_EQ(2u, root_pass->quad_list.size()); - - // There's a solid color quad under everything. - EXPECT_EQ(viz::DrawQuad::SOLID_COLOR, - root_pass->quad_list.back()->material); - - // The surface is clipped to 10x20. - EXPECT_EQ(viz::DrawQuad::RENDER_PASS, - root_pass->quad_list.front()->material); - const viz::RenderPassDrawQuad* render_pass_quad = - viz::RenderPassDrawQuad::MaterialCast(root_pass->quad_list.front()); - EXPECT_EQ(gfx::Rect(20, 10, 10, 20).ToString(), - render_pass_quad->rect.ToString()); - // The masked layer is 50x50, but the surface size is 10x20. So the texture - // coords in the mask are scaled by 10/50 and 20/50. - // The surface is clipped to (20,10) so the mask texture coords are offset - // by 20/50 and 10/50 - if (host_impl->settings().enable_mask_tiling) { - PictureLayerImpl* mask_layer_impl = static_cast<PictureLayerImpl*>( - host_impl->active_tree()->LayerById(mask_layer_id_)); - gfx::SizeF texture_size( - mask_layer_impl->CalculateTileSize(mask_layer_impl->bounds())); - EXPECT_EQ( - gfx::RectF(20.f / texture_size.width(), 10.f / texture_size.height(), - 10.f / texture_size.width(), 20.f / texture_size.height()) - .ToString(), - render_pass_quad->mask_uv_rect.ToString()); - } else { - EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f), 1.f / 50.f) - .ToString(), - render_pass_quad->mask_uv_rect.ToString()); - } - EndTest(); - return draw_result; - } - - void AfterTest() override {} - - int mask_layer_id_; - FakeContentLayerClient client_; -}; - -class LayerTreeTestSingleTextureMaskLayerForSurfaceWithClippedLayer - : public LayerTreeTestMaskLayerForSurfaceWithClippedLayer { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->enable_mask_tiling = false; - } -}; - -SINGLE_AND_MULTI_THREAD_TEST_F( - LayerTreeTestSingleTextureMaskLayerForSurfaceWithClippedLayer); - -class LayerTreeTestMultiTextureMaskLayerForSurfaceWithClippedLayer - : public LayerTreeTestMaskLayerForSurfaceWithClippedLayer { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->enable_mask_tiling = true; - } -}; - -SINGLE_AND_MULTI_THREAD_TEST_F( - LayerTreeTestMultiTextureMaskLayerForSurfaceWithClippedLayer); - -class LayerTreeTestMaskLayerWithScaling : public LayerTreeTest { - protected: - void SetupTree() override { - // Root - // | - // +-- Scaling Layer (adds a 2x scale) - // | - // +-- Content Layer - // +--Mask - - scoped_refptr<Layer> root = Layer::Create(); - - scoped_refptr<Layer> scaling_layer = Layer::Create(); - root->AddChild(scaling_layer); - - scoped_refptr<FakePictureLayer> content_layer = - FakePictureLayer::Create(&client_); - scaling_layer->AddChild(content_layer); - - std::unique_ptr<RecordingSource> recording_source = - FakeRecordingSource::CreateFilledRecordingSource(gfx::Size(100, 100)); - PaintFlags paint1, paint2; - static_cast<FakeRecordingSource*>(recording_source.get()) - ->add_draw_rect_with_flags(gfx::Rect(0, 0, 100, 10), paint1); - static_cast<FakeRecordingSource*>(recording_source.get()) - ->add_draw_rect_with_flags(gfx::Rect(0, 10, 100, 90), paint2); - client_.set_fill_with_nonsolid_color(true); - static_cast<FakeRecordingSource*>(recording_source.get())->Rerecord(); - - scoped_refptr<FakePictureLayer> mask_layer = - FakePictureLayer::CreateWithRecordingSource( - &client_, std::move(recording_source)); - content_layer->SetMaskLayer(mask_layer.get()); - - gfx::Size root_size(100, 100); - root->SetBounds(root_size); - - gfx::Size scaling_layer_size(50, 50); - scaling_layer->SetBounds(scaling_layer_size); - gfx::Transform scale; - scale.Scale(2.f, 2.f); - scaling_layer->SetTransform(scale); - - content_layer->SetBounds(scaling_layer_size); - - mask_layer->SetBounds(scaling_layer_size); - mask_layer->SetLayerMaskType(Layer::LayerMaskType::MULTI_TEXTURE_MASK); - - layer_tree_host()->SetRootLayer(root); - LayerTreeTest::SetupTree(); - client_.set_bounds(root->bounds()); - } - - void BeginTest() override { PostSetNeedsCommitToMainThread(); } - - DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, - LayerTreeHostImpl::FrameData* frame_data, - DrawResult draw_result) override { - EXPECT_EQ(2u, frame_data->render_passes.size()); - viz::RenderPass* root_pass = frame_data->render_passes.back().get(); - EXPECT_EQ(2u, root_pass->quad_list.size()); - - // There's a solid color quad under everything. - EXPECT_EQ(viz::DrawQuad::SOLID_COLOR, - root_pass->quad_list.back()->material); - - EXPECT_EQ(viz::DrawQuad::RENDER_PASS, - root_pass->quad_list.front()->material); - const viz::RenderPassDrawQuad* render_pass_quad = - viz::RenderPassDrawQuad::MaterialCast(root_pass->quad_list.front()); - switch (host_impl->active_tree()->source_frame_number()) { - case 0: - // Check that the tree scaling is correctly taken into account for the - // mask, that should fully map onto the quad. - EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), - render_pass_quad->rect.ToString()); - if (host_impl->settings().enable_mask_tiling) { - EXPECT_EQ( - gfx::RectF(0.f, 0.f, 100.f / 128.f, 100.f / 128.f).ToString(), - render_pass_quad->mask_uv_rect.ToString()); - } else { - EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), - render_pass_quad->mask_uv_rect.ToString()); - } - break; - case 1: - // Applying a DSF should change the render surface size, but won't - // affect which part of the mask is used. - EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(), - render_pass_quad->rect.ToString()); - if (host_impl->settings().enable_mask_tiling) { - EXPECT_EQ( - gfx::RectF(0.f, 0.f, 100.f / 128.f, 100.f / 128.f).ToString(), - render_pass_quad->mask_uv_rect.ToString()); - } else { - EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), - render_pass_quad->mask_uv_rect.ToString()); - } - EndTest(); - break; - } - return draw_result; - } - - void DidCommit() override { - switch (layer_tree_host()->SourceFrameNumber()) { - case 1: - gfx::Size double_root_size(200, 200); - layer_tree_host()->SetViewportSizeAndScale(double_root_size, 2.f, - viz::LocalSurfaceId()); - break; - } - } - - void AfterTest() override {} - - FakeContentLayerClient client_; -}; - -class LayerTreeTestSingleTextureMaskLayerWithScaling - : public LayerTreeTestMaskLayerWithScaling { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->enable_mask_tiling = false; - settings->layer_transforms_should_scale_layer_contents = true; - } -}; - -SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeTestSingleTextureMaskLayerWithScaling); - -class LayerTreeTestMultiTextureMaskLayerWithScaling - : public LayerTreeTestMaskLayerWithScaling { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->enable_mask_tiling = true; - settings->layer_transforms_should_scale_layer_contents = true; - } -}; - -SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeTestMultiTextureMaskLayerWithScaling); - -class LayerTreeTestMaskWithNonExactTextureSize : public LayerTreeTest { - protected: - void SetupTree() override { - // The masked layer has bounds 100x100, but is allocated a 120x150 texture. - - scoped_refptr<Layer> root = Layer::Create(); - - scoped_refptr<FakePictureLayer> content_layer = - FakePictureLayer::Create(&client_); - root->AddChild(content_layer); - - std::unique_ptr<RecordingSource> recording_source = - FakeRecordingSource::CreateFilledRecordingSource(gfx::Size(100, 100)); - PaintFlags paint1, paint2; - static_cast<FakeRecordingSource*>(recording_source.get()) - ->add_draw_rect_with_flags(gfx::Rect(0, 0, 100, 90), paint1); - static_cast<FakeRecordingSource*>(recording_source.get()) - ->add_draw_rect_with_flags(gfx::Rect(0, 90, 100, 10), paint2); - client_.set_fill_with_nonsolid_color(true); - static_cast<FakeRecordingSource*>(recording_source.get())->Rerecord(); - - scoped_refptr<FakePictureLayer> mask_layer = - FakePictureLayer::CreateWithRecordingSource( - &client_, std::move(recording_source)); - content_layer->SetMaskLayer(mask_layer.get()); - - gfx::Size root_size(100, 100); - root->SetBounds(root_size); - - gfx::Size layer_size(100, 100); - content_layer->SetBounds(layer_size); - - gfx::Size mask_size(100, 100); - gfx::Size mask_texture_size(120, 150); - mask_layer->SetBounds(mask_size); - mask_layer->SetLayerMaskType(Layer::LayerMaskType::SINGLE_TEXTURE_MASK); - mask_layer->set_fixed_tile_size(mask_texture_size); - - layer_tree_host()->SetRootLayer(root); - LayerTreeTest::SetupTree(); - client_.set_bounds(root->bounds()); - } - - void BeginTest() override { PostSetNeedsCommitToMainThread(); } - - DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, - LayerTreeHostImpl::FrameData* frame_data, - DrawResult draw_result) override { - EXPECT_EQ(2u, frame_data->render_passes.size()); - viz::RenderPass* root_pass = frame_data->render_passes.back().get(); - EXPECT_EQ(2u, root_pass->quad_list.size()); - - // There's a solid color quad under everything. - EXPECT_EQ(viz::DrawQuad::SOLID_COLOR, - root_pass->quad_list.back()->material); - - // The surface is 100x100 - EXPECT_EQ(viz::DrawQuad::RENDER_PASS, - root_pass->quad_list.front()->material); - const viz::RenderPassDrawQuad* render_pass_quad = - viz::RenderPassDrawQuad::MaterialCast(root_pass->quad_list.front()); - EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), - render_pass_quad->rect.ToString()); - // The mask layer is 100x100, but is backed by a 120x150 image. - EXPECT_EQ(gfx::RectF(0.0f, 0.0f, 100.f / 120.0f, 100.f / 150.0f).ToString(), - render_pass_quad->mask_uv_rect.ToString()); - EndTest(); - return draw_result; - } - - void AfterTest() override {} - - int mask_layer_id_; - FakeContentLayerClient client_; -}; - -SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeTestMaskWithNonExactTextureSize); - class LayerTreeTestPageScaleFlags : public LayerTreeTest { protected: void SetupTree() override { @@ -7993,6 +7512,25 @@ class LayerTreeHostTestPaintedDeviceScaleFactor : public LayerTreeHostTest { }; SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestPaintedDeviceScaleFactor); +// Makes sure that presentation-time requests are correctly propagated to the +// frame's metadata. +class LayerTreeHostTestPresentationTimeRequest : public LayerTreeHostTest { + protected: + void BeginTest() override { + layer_tree_host()->RequestPresentationTimeForNextFrame(base::DoNothing()); + PostSetNeedsCommitToMainThread(); + } + + void DisplayReceivedCompositorFrameOnThread( + const viz::CompositorFrame& frame) override { + EXPECT_NE(0u, frame.metadata.presentation_token); + EndTest(); + } + + void AfterTest() override {} +}; +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestPresentationTimeRequest); + // Makes sure that viz::LocalSurfaceId is propagated to the LayerTreeFrameSink. class LayerTreeHostTestLocalSurfaceId : public LayerTreeHostTest { protected: @@ -8001,7 +7539,7 @@ class LayerTreeHostTestLocalSurfaceId : public LayerTreeHostTest { } void BeginTest() override { - expected_local_surface_id_ = allocator_.GenerateId(); + expected_local_surface_id_ = allocator_.GetCurrentLocalSurfaceId(); PostSetLocalSurfaceIdToMainThread(expected_local_surface_id_); } @@ -8010,7 +7548,7 @@ class LayerTreeHostTestLocalSurfaceId : public LayerTreeHostTest { DrawResult draw_result) override { EXPECT_EQ(DRAW_SUCCESS, draw_result); EXPECT_EQ(expected_local_surface_id_, - host_impl->active_tree()->local_surface_id()); + host_impl->active_tree()->local_surface_id_from_parent()); return draw_result; } @@ -8025,9 +7563,56 @@ class LayerTreeHostTestLocalSurfaceId : public LayerTreeHostTest { viz::LocalSurfaceId expected_local_surface_id_; viz::ParentLocalSurfaceIdAllocator allocator_; }; - SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestLocalSurfaceId); +// Makes sure that viz::LocalSurfaceId allocation requests propagate all the way +// to LayerTreeFrameSink. +class LayerTreeHostTestRequestNewLocalSurfaceId : public LayerTreeHostTest { + protected: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->enable_surface_synchronization = true; + } + + void BeginTest() override { + expected_parent_local_surface_id_ = allocator_.GetCurrentLocalSurfaceId(); + PostSetLocalSurfaceIdToMainThread(expected_parent_local_surface_id_); + PostRequestNewLocalSurfaceIdToMainThread(); + } + + DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, + LayerTreeHostImpl::FrameData* frame_data, + DrawResult draw_result) override { + EXPECT_EQ(DRAW_SUCCESS, draw_result); + EXPECT_EQ(expected_parent_local_surface_id_, + host_impl->active_tree()->local_surface_id_from_parent()); + return draw_result; + } + + void DisplayReceivedLocalSurfaceIdOnThread( + const viz::LocalSurfaceId& local_surface_id) override { + viz::LocalSurfaceId child_local_surface_id( + expected_parent_local_surface_id_.parent_sequence_number(), + expected_parent_local_surface_id_.child_sequence_number() + 1, + expected_parent_local_surface_id_.embed_token()); + EXPECT_NE(expected_parent_local_surface_id_, local_surface_id); + EXPECT_EQ(child_local_surface_id, local_surface_id); + } + + // This gets called after DispllayReceivedLocalSurfaceIdOnThread. + void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override { + // Verify that the request bit doesn't stick after we submit a frame. + EXPECT_FALSE( + host_impl->active_tree()->new_local_surface_id_request_for_testing()); + EndTest(); + } + + void AfterTest() override {} + + viz::LocalSurfaceId expected_parent_local_surface_id_; + viz::ParentLocalSurfaceIdAllocator allocator_; +}; +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestRequestNewLocalSurfaceId); + // The GPU image decode controller hands images off to Skia for rasterization. // When used with large images, the images in question could be deleted before // Skia was done with them, causing a crash. This test performs an end-to-end @@ -8144,6 +7729,20 @@ SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestSubmitFrameMetadata); class LayerTreeHostTestSubmitFrameResources : public LayerTreeHostTest { protected: + std::unique_ptr<viz::TestLayerTreeFrameSink> CreateLayerTreeFrameSink( + const viz::RendererSettings& renderer_settings, + double refresh_rate, + scoped_refptr<viz::ContextProvider> compositor_context_provider, + scoped_refptr<viz::RasterContextProvider> worker_context_provider) + override { + auto gl_owned = std::make_unique<viz::TestGLES2Interface>(); + gl_owned->set_have_extension_egl_image(true); + auto provider = viz::TestContextProvider::Create(std::move(gl_owned)); + return LayerTreeTest::CreateLayerTreeFrameSink( + renderer_settings, refresh_rate, std::move(provider), + std::move(worker_context_provider)); + } + void BeginTest() override { PostSetNeedsCommitToMainThread(); } DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, @@ -8154,15 +7753,12 @@ class LayerTreeHostTestSubmitFrameResources : public LayerTreeHostTest { viz::RenderPass* child_pass = AddRenderPass(&frame->render_passes, 2, gfx::Rect(3, 3, 10, 10), gfx::Transform(), FilterOperations()); - gpu::SyncToken mailbox_sync_token; - AddOneOfEveryQuadType(child_pass, host_impl->resource_provider(), 0, - &mailbox_sync_token); + AddOneOfEveryQuadType(child_pass, host_impl->resource_provider(), 0); viz::RenderPass* pass = AddRenderPass(&frame->render_passes, 1, gfx::Rect(3, 3, 10, 10), gfx::Transform(), FilterOperations()); - AddOneOfEveryQuadType(pass, host_impl->resource_provider(), child_pass->id, - &mailbox_sync_token); + AddOneOfEveryQuadType(pass, host_impl->resource_provider(), child_pass->id); return draw_result; } @@ -8293,11 +7889,9 @@ class LayerTreeHostTestQueueImageDecode : public LayerTreeHostTest { void ReadyToCommitOnThread(LayerTreeHostImpl* impl) override { if (one_commit_done_) return; - EXPECT_TRUE( + EXPECT_FALSE( impl->tile_manager()->checker_image_tracker().ShouldCheckerImage( image_, WhichTree::PENDING_TREE)); - // Reset the tracker as if it has never seen this image. - impl->tile_manager()->checker_image_tracker().ClearTracker(true); } void CommitCompleteOnThread(LayerTreeHostImpl* impl) override { diff --git a/chromium/cc/trees/layer_tree_host_unittest_checkerimaging.cc b/chromium/cc/trees/layer_tree_host_unittest_checkerimaging.cc index f71c658c3fa..929c6658fe8 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_checkerimaging.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_checkerimaging.cc @@ -60,6 +60,9 @@ class LayerTreeHostCheckerImagingTest : public LayerTreeTest { content_layer_client_.set_fill_with_nonsolid_color(true); PaintImage checkerable_image = CreateDiscardablePaintImage(gfx::Size(450, 450)); + checkerable_image = PaintImageBuilder::WithCopy(checkerable_image) + .set_decoding_mode(PaintImage::DecodingMode::kAsync) + .TakePaintImage(); content_layer_client_.add_draw_image(checkerable_image, gfx::Point(0, 0), PaintFlags()); diff --git a/chromium/cc/trees/layer_tree_host_unittest_context.cc b/chromium/cc/trees/layer_tree_host_unittest_context.cc index 024ca0204ab..f3ec645e85a 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_context.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_context.cc @@ -34,6 +34,7 @@ #include "cc/trees/single_thread_proxy.h" #include "components/viz/common/resources/single_release_callback.h" #include "components/viz/test/test_context_provider.h" +#include "components/viz/test/test_gles2_interface.h" #include "components/viz/test/test_layer_tree_frame_sink.h" #include "components/viz/test/test_shared_bitmap_manager.h" #include "components/viz/test/test_web_graphics_context_3d.h" @@ -56,7 +57,6 @@ class LayerTreeHostContextTest : public LayerTreeTest { public: LayerTreeHostContextTest() : LayerTreeTest(), - context3d_(nullptr), times_to_fail_create_(0), times_to_lose_during_commit_(0), times_to_lose_during_draw_(0), @@ -72,15 +72,15 @@ class LayerTreeHostContextTest : public LayerTreeTest { void LoseContext() { // CreateDisplayLayerTreeFrameSink happens on a different thread, so lock - // context3d_ to make sure we don't set it to null after recreating it + // gl_ to make sure we don't set it to null after recreating it // there. - base::AutoLock lock(context3d_lock_); + base::AutoLock lock(gl_lock_); // For sanity-checking tests, they should only call this when the // context is not lost. - CHECK(context3d_); - context3d_->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, - GL_INNOCENT_CONTEXT_RESET_ARB); - context3d_ = nullptr; + CHECK(gl_); + gl_->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, + GL_INNOCENT_CONTEXT_RESET_ARB); + gl_ = nullptr; } std::unique_ptr<viz::TestLayerTreeFrameSink> CreateLayerTreeFrameSink( @@ -89,26 +89,26 @@ class LayerTreeHostContextTest : public LayerTreeTest { scoped_refptr<viz::ContextProvider> compositor_context_provider, scoped_refptr<viz::RasterContextProvider> worker_context_provider) override { - base::AutoLock lock(context3d_lock_); + base::AutoLock lock(gl_lock_); - std::unique_ptr<viz::TestWebGraphicsContext3D> compositor_context3d = - viz::TestWebGraphicsContext3D::Create(); + auto gl_owned = std::make_unique<viz::TestGLES2Interface>(); if (context_should_support_io_surface_) { - compositor_context3d->set_have_extension_io_surface(true); - compositor_context3d->set_have_extension_egl_image(true); + gl_owned->set_have_extension_io_surface(true); + gl_owned->set_have_extension_egl_image(true); } - context3d_ = compositor_context3d.get(); + gl_ = gl_owned.get(); + + auto provider = viz::TestContextProvider::Create(std::move(gl_owned)); if (times_to_fail_create_) { --times_to_fail_create_; ExpectCreateToFail(); - context3d_->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, - GL_INNOCENT_CONTEXT_RESET_ARB); + gl_->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, + GL_INNOCENT_CONTEXT_RESET_ARB); } return LayerTreeTest::CreateLayerTreeFrameSink( - renderer_settings, refresh_rate, - viz::TestContextProvider::Create(std::move(compositor_context3d)), + renderer_settings, refresh_rate, std::move(provider), std::move(worker_context_provider)); } @@ -158,10 +158,10 @@ class LayerTreeHostContextTest : public LayerTreeTest { void ExpectCreateToFail() { ++times_to_expect_create_failed_; } protected: - // Protects use of context3d_ so LoseContext and + // Protects use of gl_ so LoseContext and // CreateDisplayLayerTreeFrameSink can both use it on different threads. - base::Lock context3d_lock_; - viz::TestWebGraphicsContext3D* context3d_; + base::Lock gl_lock_; + viz::TestGLES2Interface* gl_ = nullptr; int times_to_fail_create_; int times_to_lose_during_commit_; @@ -887,7 +887,7 @@ class LayerTreeHostContextTestDontUseLostResources shared_bitmap_manager_ = std::make_unique<viz::TestSharedBitmapManager>(); child_resource_provider_ = FakeResourceProvider::CreateLayerTreeResourceProvider( - child_context_provider_.get(), shared_bitmap_manager_.get()); + child_context_provider_.get()); } static void EmptyReleaseCallback(const gpu::SyncToken& sync_token, @@ -1008,7 +1008,7 @@ class LayerTreeHostContextTestDontUseLostResources if (host_impl->active_tree()->source_frame_number() == 2) { // Lose the context after draw on the second commit. This will cause // a third commit to recover. - context3d_->set_times_bind_texture_succeeds(0); + gl_->set_times_bind_texture_succeeds(0); } return draw_result; } @@ -1042,7 +1042,7 @@ class LayerTreeHostContextTestDontUseLostResources scoped_refptr<viz::TestContextProvider> child_context_provider_; std::unique_ptr<viz::SharedBitmapManager> shared_bitmap_manager_; - std::unique_ptr<ResourceProvider> child_resource_provider_; + std::unique_ptr<LayerTreeResourceProvider> child_resource_provider_; scoped_refptr<VideoFrame> color_video_frame_; scoped_refptr<VideoFrame> hw_video_frame_; @@ -1345,8 +1345,9 @@ class UIResourceLostBeforeCommit : public UIResourceLostTestSimple { UIResourceId test_id1_; }; -// http://crbug.com/803532 : Flaky on Win 7 (dbg). -#if defined(NDEBUG) || !defined(OS_WIN) +// http://crbug.com/803532 : Flaky on Win 7 (dbg) and linux tsan +#if (defined(NDEBUG) || !defined(OS_WIN)) && \ + (!defined(THREAD_SANITIZER) || !defined(OS_LINUX)) SINGLE_THREAD_TEST_F(UIResourceLostBeforeCommit); #endif MULTI_THREAD_TEST_F(UIResourceLostBeforeCommit); @@ -1479,7 +1480,7 @@ class UIResourceLostEviction : public UIResourceLostTestSimple { void DidSetVisibleOnImplTree(LayerTreeHostImpl* impl, bool visible) override { if (!visible) { // All resources should have been evicted. - ASSERT_EQ(0u, context3d_->NumTextures()); + ASSERT_EQ(0u, gl_->NumTextures()); EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id())); EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource2_->id())); EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource3_->id())); @@ -1499,7 +1500,7 @@ class UIResourceLostEviction : public UIResourceLostTestSimple { case 1: // The first two resources should have been created on LTHI after the // commit. - ASSERT_EQ(2u, context3d_->NumTextures()); + ASSERT_EQ(2u, gl_->NumTextures()); EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource2_->id())); EXPECT_EQ(1, ui_resource_->resource_create_count); @@ -1507,7 +1508,7 @@ class UIResourceLostEviction : public UIResourceLostTestSimple { EXPECT_TRUE(impl->CanDraw()); // Evict all UI resources. This will trigger a commit. impl->EvictAllUIResources(); - ASSERT_EQ(0u, context3d_->NumTextures()); + ASSERT_EQ(0u, gl_->NumTextures()); EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id())); EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource2_->id())); EXPECT_EQ(1, ui_resource_->resource_create_count); @@ -1516,7 +1517,7 @@ class UIResourceLostEviction : public UIResourceLostTestSimple { break; case 2: // The first two resources should have been recreated. - ASSERT_EQ(2u, context3d_->NumTextures()); + ASSERT_EQ(2u, gl_->NumTextures()); EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); EXPECT_EQ(2, ui_resource_->resource_create_count); EXPECT_EQ(1, ui_resource_->lost_resource_count); @@ -1528,7 +1529,7 @@ class UIResourceLostEviction : public UIResourceLostTestSimple { case 3: // The first resource should have been recreated after visibility was // restored. - ASSERT_EQ(2u, context3d_->NumTextures()); + ASSERT_EQ(2u, gl_->NumTextures()); EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); EXPECT_EQ(3, ui_resource_->resource_create_count); EXPECT_EQ(2, ui_resource_->lost_resource_count); diff --git a/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc index edc62a8e36a..fcc95241448 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc @@ -1049,63 +1049,6 @@ class LayerTreeHostCopyRequestTestCreatesTexture SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostCopyRequestTestCreatesTexture); -class LayerTreeHostCopyRequestTestProvideTexture - : public LayerTreeHostCopyRequestTestCountTextures { - protected: - void BeginTest() override { - external_context_provider_ = viz::TestContextProvider::Create(); - EXPECT_EQ(external_context_provider_->BindToCurrentThread(), - gpu::ContextResult::kSuccess); - LayerTreeHostCopyRequestTestCountTextures::BeginTest(); - } - - void CopyOutputCallback(std::unique_ptr<viz::CopyOutputResult> result) { - EXPECT_FALSE(result->IsEmpty()); - EXPECT_EQ(result->format(), viz::CopyOutputResult::Format::RGBA_TEXTURE); - ASSERT_NE(nullptr, result->GetTextureResult()); - - std::unique_ptr<viz::SingleReleaseCallback> release_callback = - result->TakeTextureOwnership(); - ASSERT_TRUE(release_callback); - release_callback->Run(gpu::SyncToken(), false); - } - - void RequestCopy(Layer* layer) override { - // Request a copy to a provided texture. This should not create a new - // texture. - std::unique_ptr<viz::CopyOutputRequest> request = - std::make_unique<viz::CopyOutputRequest>( - viz::CopyOutputRequest::ResultFormat::RGBA_TEXTURE, - base::BindOnce( - &LayerTreeHostCopyRequestTestProvideTexture::CopyOutputCallback, - base::Unretained(this))); - - gpu::gles2::GLES2Interface* gl = external_context_provider_->ContextGL(); - gpu::Mailbox mailbox; - gl->GenMailboxCHROMIUM(mailbox.name); - - gl->GenSyncTokenCHROMIUM(sync_token_.GetData()); - - request->SetMailbox(mailbox, sync_token_); - EXPECT_TRUE(request->has_mailbox()); - - copy_layer_->RequestCopyOfOutput(std::move(request)); - } - - void AfterTest() override { - // Expect the compositor to have waited for the sync point provided with the - // mailbox. - EXPECT_EQ(sync_token_, waited_sync_token_after_readback_); - // Except the copy to have *not* made another texture. - EXPECT_EQ(num_textures_without_readback_, num_textures_with_readback_); - } - - scoped_refptr<viz::TestContextProvider> external_context_provider_; - gpu::SyncToken sync_token_; -}; - -SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostCopyRequestTestProvideTexture); - class LayerTreeHostCopyRequestTestDestroyBeforeCopy : public LayerTreeHostCopyRequestTest { protected: diff --git a/chromium/cc/trees/layer_tree_host_unittest_masks.cc b/chromium/cc/trees/layer_tree_host_unittest_masks.cc new file mode 100644 index 00000000000..b1615f0eb7e --- /dev/null +++ b/chromium/cc/trees/layer_tree_host_unittest_masks.cc @@ -0,0 +1,666 @@ +// 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/layer_tree_host.h" + +#include "cc/test/fake_picture_layer.h" +#include "cc/test/fake_recording_source.h" +#include "cc/test/layer_tree_test.h" +#include "cc/trees/layer_tree_impl.h" +#include "components/viz/common/quads/render_pass_draw_quad.h" + +namespace cc { +namespace { + +class LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin + : public LayerTreeTest { + protected: + void SetupTree() override { + // The masked layer has bounds 50x50, but it has a child that causes + // the surface bounds to be larger. It also has a parent that clips the + // masked layer and its surface. + + scoped_refptr<Layer> root = Layer::Create(); + + scoped_refptr<FakePictureLayer> content_layer = + FakePictureLayer::Create(&client_); + + std::unique_ptr<RecordingSource> recording_source = + FakeRecordingSource::CreateFilledRecordingSource(gfx::Size(100, 100)); + PaintFlags paint1, paint2; + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 0, 100, 90), paint1); + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 90, 100, 10), paint2); + client_.set_fill_with_nonsolid_color(true); + static_cast<FakeRecordingSource*>(recording_source.get())->Rerecord(); + + scoped_refptr<FakePictureLayer> mask_layer = + FakePictureLayer::CreateWithRecordingSource( + &client_, std::move(recording_source)); + content_layer->SetMaskLayer(mask_layer.get()); + + gfx::Size root_size(100, 100); + root->SetBounds(root_size); + + gfx::Size layer_size(100, 100); + content_layer->SetBounds(layer_size); + + gfx::Size mask_size(100, 100); + mask_layer->SetBounds(mask_size); + mask_layer->SetLayerMaskType(Layer::LayerMaskType::MULTI_TEXTURE_MASK); + mask_layer_id_ = mask_layer->id(); + + layer_tree_host()->SetRootLayer(root); + LayerTreeTest::SetupTree(); + scoped_refptr<Layer> outer_viewport_scroll_layer = Layer::Create(); + outer_viewport_scroll_layer->SetBounds(layer_size); + CreateVirtualViewportLayers(root.get(), outer_viewport_scroll_layer, + gfx::Size(50, 50), gfx::Size(50, 50), + layer_tree_host()); + layer_tree_host()->outer_viewport_container_layer()->SetMasksToBounds(true); + outer_viewport_scroll_layer->AddChild(content_layer); + + client_.set_bounds(root->bounds()); + outer_viewport_scroll_layer->SetScrollOffset(gfx::ScrollOffset(50, 50)); + } + + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, + LayerTreeHostImpl::FrameData* frame_data, + DrawResult draw_result) override { + EXPECT_EQ(2u, frame_data->render_passes.size()); + viz::RenderPass* root_pass = frame_data->render_passes.back().get(); + EXPECT_EQ(2u, root_pass->quad_list.size()); + + // There's a solid color quad under everything. + EXPECT_EQ(viz::DrawQuad::SOLID_COLOR, + root_pass->quad_list.back()->material); + + EXPECT_EQ(viz::DrawQuad::RENDER_PASS, + root_pass->quad_list.front()->material); + const viz::RenderPassDrawQuad* render_pass_quad = + viz::RenderPassDrawQuad::MaterialCast(root_pass->quad_list.front()); + gfx::Rect rect_in_target_space = MathUtil::MapEnclosingClippedRect( + render_pass_quad->shared_quad_state->quad_to_target_transform, + render_pass_quad->rect); + EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(), + rect_in_target_space.ToString()); + if (host_impl->settings().enable_mask_tiling) { + PictureLayerImpl* mask_layer_impl = static_cast<PictureLayerImpl*>( + host_impl->active_tree()->LayerById(mask_layer_id_)); + gfx::SizeF texture_size( + mask_layer_impl->CalculateTileSize(mask_layer_impl->bounds())); + EXPECT_EQ( + gfx::RectF(50.f / texture_size.width(), 50.f / texture_size.height(), + 50.f / texture_size.width(), 50.f / texture_size.height()) + .ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } else { + EXPECT_EQ(gfx::ScaleRect(gfx::RectF(50.f, 50.f, 50.f, 50.f), 1.f / 100.f) + .ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } + EndTest(); + return draw_result; + } + + void AfterTest() override {} + + int mask_layer_id_; + FakeContentLayerClient client_; +}; + +class LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin_Untiled + : public LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin { + public: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->enable_mask_tiling = false; + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin_Untiled); + +class LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin_Tiled + : public LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin { + public: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->enable_mask_tiling = true; + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin_Tiled); + +class LayerTreeTestMaskLayerForSurfaceWithClippedLayer : public LayerTreeTest { + protected: + void SetupTree() override { + // The masked layer has bounds 50x50, but it has a child that causes + // the surface bounds to be larger. It also has a parent that clips the + // masked layer and its surface. + + scoped_refptr<Layer> root = Layer::Create(); + + scoped_refptr<Layer> clipping_layer = Layer::Create(); + root->AddChild(clipping_layer); + + scoped_refptr<FakePictureLayer> content_layer = + FakePictureLayer::Create(&client_); + clipping_layer->AddChild(content_layer); + + scoped_refptr<FakePictureLayer> content_child_layer = + FakePictureLayer::Create(&client_); + content_layer->AddChild(content_child_layer); + + std::unique_ptr<RecordingSource> recording_source = + FakeRecordingSource::CreateFilledRecordingSource(gfx::Size(50, 50)); + PaintFlags paint1, paint2; + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 0, 50, 40), paint1); + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 40, 50, 10), paint2); + client_.set_fill_with_nonsolid_color(true); + static_cast<FakeRecordingSource*>(recording_source.get())->Rerecord(); + + scoped_refptr<FakePictureLayer> mask_layer = + FakePictureLayer::CreateWithRecordingSource( + &client_, std::move(recording_source)); + content_layer->SetMaskLayer(mask_layer.get()); + + gfx::Size root_size(100, 100); + root->SetBounds(root_size); + + gfx::PointF clipping_origin(20.f, 10.f); + gfx::Size clipping_size(10, 20); + clipping_layer->SetBounds(clipping_size); + clipping_layer->SetPosition(clipping_origin); + clipping_layer->SetMasksToBounds(true); + + gfx::Size layer_size(50, 50); + content_layer->SetBounds(layer_size); + content_layer->SetPosition(gfx::PointF() - + clipping_origin.OffsetFromOrigin()); + + gfx::Size child_size(50, 50); + content_child_layer->SetBounds(child_size); + content_child_layer->SetPosition(gfx::PointF(20.f, 0.f)); + + gfx::Size mask_size(50, 50); + mask_layer->SetBounds(mask_size); + mask_layer->SetLayerMaskType(Layer::LayerMaskType::MULTI_TEXTURE_MASK); + mask_layer_id_ = mask_layer->id(); + + layer_tree_host()->SetRootLayer(root); + LayerTreeTest::SetupTree(); + client_.set_bounds(root->bounds()); + } + + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, + LayerTreeHostImpl::FrameData* frame_data, + DrawResult draw_result) override { + EXPECT_EQ(2u, frame_data->render_passes.size()); + viz::RenderPass* root_pass = frame_data->render_passes.back().get(); + EXPECT_EQ(2u, root_pass->quad_list.size()); + + // There's a solid color quad under everything. + EXPECT_EQ(viz::DrawQuad::SOLID_COLOR, + root_pass->quad_list.back()->material); + + // The surface is clipped to 10x20. + EXPECT_EQ(viz::DrawQuad::RENDER_PASS, + root_pass->quad_list.front()->material); + const viz::RenderPassDrawQuad* render_pass_quad = + viz::RenderPassDrawQuad::MaterialCast(root_pass->quad_list.front()); + gfx::Rect rect_in_target_space = MathUtil::MapEnclosingClippedRect( + render_pass_quad->shared_quad_state->quad_to_target_transform, + render_pass_quad->rect); + EXPECT_EQ(gfx::Rect(20, 10, 10, 20).ToString(), + rect_in_target_space.ToString()); + // The masked layer is 50x50, but the surface size is 10x20. So the texture + // coords in the mask are scaled by 10/50 and 20/50. + // The surface is clipped to (20,10) so the mask texture coords are offset + // by 20/50 and 10/50 + if (host_impl->settings().enable_mask_tiling) { + PictureLayerImpl* mask_layer_impl = static_cast<PictureLayerImpl*>( + host_impl->active_tree()->LayerById(mask_layer_id_)); + gfx::SizeF texture_size( + mask_layer_impl->CalculateTileSize(mask_layer_impl->bounds())); + EXPECT_EQ( + gfx::RectF(20.f / texture_size.width(), 10.f / texture_size.height(), + 10.f / texture_size.width(), 20.f / texture_size.height()) + .ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } else { + EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f), 1.f / 50.f) + .ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } + EndTest(); + return draw_result; + } + + void AfterTest() override {} + + int mask_layer_id_; + FakeContentLayerClient client_; +}; + +class LayerTreeTestMaskLayerForSurfaceWithClippedLayer_Untiled + : public LayerTreeTestMaskLayerForSurfaceWithClippedLayer { + public: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->enable_mask_tiling = false; + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeTestMaskLayerForSurfaceWithClippedLayer_Untiled); + +class LayerTreeTestMaskLayerForSurfaceWithClippedLayer_Tiled + : public LayerTreeTestMaskLayerForSurfaceWithClippedLayer { + public: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->enable_mask_tiling = true; + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeTestMaskLayerForSurfaceWithClippedLayer_Tiled); + +class LayerTreeTestMaskLayerForSurfaceWithDifferentScale + : public LayerTreeTest { + protected: + void SetupTree() override { + // The masked layer has bounds 50x50, but it has a child that causes + // the surface bounds to be larger. It also has a parent that clips the + // masked layer and its surface. + + scoped_refptr<Layer> root = Layer::Create(); + + scoped_refptr<Layer> clipping_scaling_layer = Layer::Create(); + root->AddChild(clipping_scaling_layer); + + scoped_refptr<FakePictureLayer> content_layer = + FakePictureLayer::Create(&client_); + clipping_scaling_layer->AddChild(content_layer); + + scoped_refptr<FakePictureLayer> content_child_layer = + FakePictureLayer::Create(&client_); + content_layer->AddChild(content_child_layer); + + std::unique_ptr<RecordingSource> recording_source = + FakeRecordingSource::CreateFilledRecordingSource(gfx::Size(50, 50)); + PaintFlags paint1, paint2; + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 0, 50, 40), paint1); + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 40, 50, 10), paint2); + client_.set_fill_with_nonsolid_color(true); + static_cast<FakeRecordingSource*>(recording_source.get())->Rerecord(); + + scoped_refptr<FakePictureLayer> mask_layer = + FakePictureLayer::CreateWithRecordingSource( + &client_, std::move(recording_source)); + content_layer->SetMaskLayer(mask_layer.get()); + + gfx::Size root_size(100, 100); + root->SetBounds(root_size); + + gfx::Transform scale; + scale.Scale(2, 2); + gfx::PointF clipping_origin(20.f, 10.f); + gfx::Size clipping_size(10, 20); + clipping_scaling_layer->SetBounds(clipping_size); + clipping_scaling_layer->SetPosition(clipping_origin); + // This changes scale between contributing layer and render surface to 2. + clipping_scaling_layer->SetTransform(scale); + clipping_scaling_layer->SetMasksToBounds(true); + + gfx::Size layer_size(50, 50); + content_layer->SetBounds(layer_size); + content_layer->SetPosition(gfx::PointF() - + clipping_origin.OffsetFromOrigin()); + + gfx::Size child_size(50, 50); + content_child_layer->SetBounds(child_size); + content_child_layer->SetPosition(gfx::PointF(20.f, 0.f)); + + gfx::Size mask_size(50, 50); + mask_layer->SetBounds(mask_size); + mask_layer->SetLayerMaskType(Layer::LayerMaskType::MULTI_TEXTURE_MASK); + // Setting will change transform on mask layer will make it not adjust + // raster scale, which will remain 1. This means the mask_layer and render + // surface will have a scale of 2 during draw time. + mask_layer->SetHasWillChangeTransformHint(true); + mask_layer_id_ = mask_layer->id(); + + layer_tree_host()->SetRootLayer(root); + LayerTreeTest::SetupTree(); + client_.set_bounds(root->bounds()); + } + + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, + LayerTreeHostImpl::FrameData* frame_data, + DrawResult draw_result) override { + EXPECT_EQ(2u, frame_data->render_passes.size()); + viz::RenderPass* root_pass = frame_data->render_passes.back().get(); + EXPECT_EQ(2u, root_pass->quad_list.size()); + + // There's a solid color quad under everything. + EXPECT_EQ(viz::DrawQuad::SOLID_COLOR, + root_pass->quad_list.back()->material); + + // The surface is clipped to 10x20, and then scaled by 2, which ends up + // being 20x40. + EXPECT_EQ(viz::DrawQuad::RENDER_PASS, + root_pass->quad_list.front()->material); + const viz::RenderPassDrawQuad* render_pass_quad = + viz::RenderPassDrawQuad::MaterialCast(root_pass->quad_list.front()); + gfx::Rect rect_in_target_space = MathUtil::MapEnclosingClippedRect( + render_pass_quad->shared_quad_state->quad_to_target_transform, + render_pass_quad->rect); + EXPECT_EQ(gfx::Rect(20, 10, 20, 40).ToString(), + rect_in_target_space.ToString()); + gfx::Rect visible_rect_in_target_space = MathUtil::MapEnclosingClippedRect( + render_pass_quad->shared_quad_state->quad_to_target_transform, + render_pass_quad->visible_rect); + EXPECT_EQ(gfx::Rect(20, 10, 20, 40).ToString(), + visible_rect_in_target_space.ToString()); + // The masked layer is 50x50, but the surface size is 10x20. So the texture + // coords in the mask are scaled by 10/50 and 20/50. + // The surface is clipped to (20,10) so the mask texture coords are offset + // by 20/50 and 10/50 + if (host_impl->settings().enable_mask_tiling) { + PictureLayerImpl* mask_layer_impl = static_cast<PictureLayerImpl*>( + host_impl->active_tree()->LayerById(mask_layer_id_)); + gfx::SizeF texture_size( + mask_layer_impl->CalculateTileSize(mask_layer_impl->bounds())); + EXPECT_EQ( + gfx::RectF(20.f / texture_size.width(), 10.f / texture_size.height(), + 10.f / texture_size.width(), 20.f / texture_size.height()) + .ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } else { + EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f), 1.f / 50.f) + .ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } + EndTest(); + return draw_result; + } + + void AfterTest() override {} + + int mask_layer_id_; + FakeContentLayerClient client_; +}; + +class LayerTreeTestMaskLayerForSurfaceWithDifferentScale_Untiled + : public LayerTreeTestMaskLayerForSurfaceWithDifferentScale { + public: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->enable_mask_tiling = false; + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeTestMaskLayerForSurfaceWithDifferentScale_Untiled); + +class LayerTreeTestMaskLayerForSurfaceWithDifferentScale_Tiled + : public LayerTreeTestMaskLayerForSurfaceWithDifferentScale { + public: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->enable_mask_tiling = true; + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeTestMaskLayerForSurfaceWithDifferentScale_Tiled); + +class LayerTreeTestMaskLayerWithScaling : public LayerTreeTest { + protected: + void SetupTree() override { + // Root + // | + // +-- Scaling Layer (adds a 2x scale) + // | + // +-- Content Layer + // +--Mask + + scoped_refptr<Layer> root = Layer::Create(); + + scoped_refptr<Layer> scaling_layer = Layer::Create(); + root->AddChild(scaling_layer); + + scoped_refptr<FakePictureLayer> content_layer = + FakePictureLayer::Create(&client_); + scaling_layer->AddChild(content_layer); + + std::unique_ptr<RecordingSource> recording_source = + FakeRecordingSource::CreateFilledRecordingSource(gfx::Size(100, 100)); + PaintFlags paint1, paint2; + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 0, 100, 10), paint1); + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 10, 100, 90), paint2); + client_.set_fill_with_nonsolid_color(true); + static_cast<FakeRecordingSource*>(recording_source.get())->Rerecord(); + + scoped_refptr<FakePictureLayer> mask_layer = + FakePictureLayer::CreateWithRecordingSource( + &client_, std::move(recording_source)); + content_layer->SetMaskLayer(mask_layer.get()); + + gfx::Size root_size(100, 100); + root->SetBounds(root_size); + + gfx::Size scaling_layer_size(50, 50); + scaling_layer->SetBounds(scaling_layer_size); + gfx::Transform scale; + scale.Scale(2.f, 2.f); + scaling_layer->SetTransform(scale); + + content_layer->SetBounds(scaling_layer_size); + + mask_layer->SetBounds(scaling_layer_size); + mask_layer->SetLayerMaskType(Layer::LayerMaskType::MULTI_TEXTURE_MASK); + + layer_tree_host()->SetRootLayer(root); + LayerTreeTest::SetupTree(); + client_.set_bounds(root->bounds()); + } + + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, + LayerTreeHostImpl::FrameData* frame_data, + DrawResult draw_result) override { + EXPECT_EQ(2u, frame_data->render_passes.size()); + viz::RenderPass* root_pass = frame_data->render_passes.back().get(); + EXPECT_EQ(2u, root_pass->quad_list.size()); + + // There's a solid color quad under everything. + EXPECT_EQ(viz::DrawQuad::SOLID_COLOR, + root_pass->quad_list.back()->material); + + EXPECT_EQ(viz::DrawQuad::RENDER_PASS, + root_pass->quad_list.front()->material); + const viz::RenderPassDrawQuad* render_pass_quad = + viz::RenderPassDrawQuad::MaterialCast(root_pass->quad_list.front()); + switch (host_impl->active_tree()->source_frame_number()) { + case 0: + // Check that the tree scaling is correctly taken into account for the + // mask, that should fully map onto the quad. + EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), + render_pass_quad->rect.ToString()); + if (host_impl->settings().enable_mask_tiling) { + EXPECT_EQ( + gfx::RectF(0.f, 0.f, 100.f / 128.f, 100.f / 128.f).ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } else { + EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } + break; + case 1: + // Applying a DSF should change the render surface size, but won't + // affect which part of the mask is used. + EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(), + render_pass_quad->rect.ToString()); + if (host_impl->settings().enable_mask_tiling) { + EXPECT_EQ( + gfx::RectF(0.f, 0.f, 100.f / 128.f, 100.f / 128.f).ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } else { + EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), + render_pass_quad->mask_uv_rect.ToString()); + } + EndTest(); + break; + } + return draw_result; + } + + void DidCommit() override { + switch (layer_tree_host()->SourceFrameNumber()) { + case 1: + gfx::Size double_root_size(200, 200); + layer_tree_host()->SetViewportSizeAndScale(double_root_size, 2.f, + viz::LocalSurfaceId()); + break; + } + } + + void AfterTest() override {} + + FakeContentLayerClient client_; +}; + +class LayerTreeTestMaskLayerWithScaling_Untiled + : public LayerTreeTestMaskLayerWithScaling { + public: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->enable_mask_tiling = false; + settings->layer_transforms_should_scale_layer_contents = true; + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeTestMaskLayerWithScaling_Untiled); + +class LayerTreeTestMaskLayerWithScaling_Tiled + : public LayerTreeTestMaskLayerWithScaling { + public: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->enable_mask_tiling = true; + settings->layer_transforms_should_scale_layer_contents = true; + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeTestMaskLayerWithScaling_Tiled); + +class LayerTreeTestMaskWithNonExactTextureSize : public LayerTreeTest { + protected: + void SetupTree() override { + // The masked layer has bounds 100x100, but is allocated a 120x150 texture. + + scoped_refptr<Layer> root = Layer::Create(); + + scoped_refptr<FakePictureLayer> content_layer = + FakePictureLayer::Create(&client_); + root->AddChild(content_layer); + + std::unique_ptr<RecordingSource> recording_source = + FakeRecordingSource::CreateFilledRecordingSource(gfx::Size(100, 100)); + PaintFlags paint1, paint2; + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 0, 100, 90), paint1); + static_cast<FakeRecordingSource*>(recording_source.get()) + ->add_draw_rect_with_flags(gfx::Rect(0, 90, 100, 10), paint2); + client_.set_fill_with_nonsolid_color(true); + static_cast<FakeRecordingSource*>(recording_source.get())->Rerecord(); + + scoped_refptr<FakePictureLayer> mask_layer = + FakePictureLayer::CreateWithRecordingSource( + &client_, std::move(recording_source)); + content_layer->SetMaskLayer(mask_layer.get()); + + gfx::Size root_size(100, 100); + root->SetBounds(root_size); + + gfx::Size layer_size(100, 100); + content_layer->SetBounds(layer_size); + + gfx::Size mask_size(100, 100); + gfx::Size mask_texture_size(120, 150); + mask_layer->SetBounds(mask_size); + mask_layer->SetLayerMaskType(Layer::LayerMaskType::SINGLE_TEXTURE_MASK); + mask_layer->set_fixed_tile_size(mask_texture_size); + + layer_tree_host()->SetRootLayer(root); + LayerTreeTest::SetupTree(); + client_.set_bounds(root->bounds()); + } + + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, + LayerTreeHostImpl::FrameData* frame_data, + DrawResult draw_result) override { + EXPECT_EQ(2u, frame_data->render_passes.size()); + viz::RenderPass* root_pass = frame_data->render_passes.back().get(); + EXPECT_EQ(2u, root_pass->quad_list.size()); + + // There's a solid color quad under everything. + EXPECT_EQ(viz::DrawQuad::SOLID_COLOR, + root_pass->quad_list.back()->material); + + // The surface is 100x100 + EXPECT_EQ(viz::DrawQuad::RENDER_PASS, + root_pass->quad_list.front()->material); + const viz::RenderPassDrawQuad* render_pass_quad = + viz::RenderPassDrawQuad::MaterialCast(root_pass->quad_list.front()); + EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), + render_pass_quad->rect.ToString()); + // The mask layer is 100x100, but is backed by a 120x150 image. + EXPECT_EQ(gfx::RectF(0.0f, 0.0f, 100.f / 120.0f, 100.f / 150.0f).ToString(), + render_pass_quad->mask_uv_rect.ToString()); + EndTest(); + return draw_result; + } + + void AfterTest() override {} + + int mask_layer_id_; + FakeContentLayerClient client_; +}; + +class LayerTreeTestMaskWithNonExactTextureSize_Untiled + : public LayerTreeTestMaskWithNonExactTextureSize { + public: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->enable_mask_tiling = false; + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeTestMaskWithNonExactTextureSize_Untiled); + +class LayerTreeTestMaskWithNonExactTextureSize_Tiled + : public LayerTreeTestMaskWithNonExactTextureSize { + public: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->enable_mask_tiling = true; + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeTestMaskWithNonExactTextureSize_Tiled); + +} // namespace +} // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_unittest_picture.cc b/chromium/cc/trees/layer_tree_host_unittest_picture.cc index 40aeeb1acb3..205d1f2c648 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_picture.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_picture.cc @@ -41,14 +41,16 @@ class LayerTreeHostPictureTestTwinLayer } void BeginTest() override { - activates_ = 0; + // Commit and activate to produce a pending (recycled) layer and an active + // layer. PostSetNeedsCommitToMainThread(); } void DidCommit() override { switch (layer_tree_host()->SourceFrameNumber()) { case 1: - // Activate while there are pending and active twins in place. + // Activate reusing an existing recycled pending layer, to an already + // existing active layer. layer_tree_host()->SetNeedsCommit(); break; case 2: @@ -66,12 +68,9 @@ class LayerTreeHostPictureTestTwinLayer break; } case 4: - // Active while there are pending and active twins again. + // Activate while there are pending and active twins again. layer_tree_host()->SetNeedsCommit(); break; - case 5: - EndTest(); - break; } } @@ -131,11 +130,14 @@ class LayerTreeHostPictureTestTwinLayer } ++activates_; + if (activates_ == 5) + EndTest(); } - void AfterTest() override { EXPECT_EQ(5, activates_); } + void AfterTest() override {} + + int activates_ = 0; - int activates_; int picture_id1_; int picture_id2_; }; diff --git a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc index 68982f6f0cf..dc45563a2c7 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc @@ -1250,7 +1250,7 @@ class LayerTreeHostScrollTestImplScrollUnderMainThreadScrollingParent layer_tree_host() ->inner_viewport_scroll_layer() ->AddMainThreadScrollingReasons( - MainThreadScrollingReason::kNonFastScrollableRegion); + MainThreadScrollingReason::kScrollbarScrolling); } void DrawLayersOnThread(LayerTreeHostImpl* impl) override { @@ -1268,7 +1268,7 @@ class LayerTreeHostScrollTestImplScrollUnderMainThreadScrollingParent impl->TryScroll(gfx::PointF(1.f, 1.f), InputHandler::TOUCHSCREEN, scroll_tree, inner_scroll_node); EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread); - EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion, + EXPECT_EQ(MainThreadScrollingReason::kScrollbarScrolling, status.main_thread_scrolling_reasons); status = impl->TryScroll(gfx::PointF(1.f, 1.f), InputHandler::TOUCHSCREEN, diff --git a/chromium/cc/trees/layer_tree_impl.cc b/chromium/cc/trees/layer_tree_impl.cc index fa670feff83..a6b06c59e26 100644 --- a/chromium/cc/trees/layer_tree_impl.cc +++ b/chromium/cc/trees/layer_tree_impl.cc @@ -468,8 +468,11 @@ void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) { target_tree->elastic_overscroll()->PushPendingToActive(); target_tree->set_content_source_id(content_source_id()); + target_tree->set_request_presentation_time(request_presentation_time()); - target_tree->set_local_surface_id(local_surface_id()); + if (TakeNewLocalSurfaceIdRequest()) + target_tree->RequestNewLocalSurfaceId(); + target_tree->SetLocalSurfaceIdFromParent(local_surface_id_from_parent()); target_tree->pending_page_scale_animation_ = std::move(pending_page_scale_animation_); @@ -963,6 +966,21 @@ void LayerTreeImpl::SetDeviceScaleFactor(float device_scale_factor) { host_impl_->SetNeedUpdateGpuRasterizationStatus(); } +void LayerTreeImpl::SetLocalSurfaceIdFromParent( + const viz::LocalSurfaceId& local_surface_id_from_parent) { + local_surface_id_from_parent_ = local_surface_id_from_parent; +} + +void LayerTreeImpl::RequestNewLocalSurfaceId() { + new_local_surface_id_request_ = true; +} + +bool LayerTreeImpl::TakeNewLocalSurfaceIdRequest() { + bool new_local_surface_id_request = new_local_surface_id_request_; + new_local_surface_id_request_ = false; + return new_local_surface_id_request; +} + void LayerTreeImpl::SetRasterColorSpace( int raster_color_space_id, const gfx::ColorSpace& raster_color_space) { @@ -1085,7 +1103,7 @@ bool LayerTreeImpl::UpdateDrawProperties( device_scale_factor(), current_page_scale_factor(), PageScaleLayer(), InnerViewportScrollLayer(), OuterViewportScrollLayer(), elastic_overscroll()->Current(IsActiveTree()), - OverscrollElasticityLayer(), resource_provider()->max_texture_size(), + OverscrollElasticityLayer(), max_texture_size(), settings().layer_transforms_should_scale_layer_contents, &render_surface_list_, &property_trees_); LayerTreeHostCommon::CalculateDrawProperties(&inputs); @@ -1376,6 +1394,10 @@ LayerTreeFrameSink* LayerTreeImpl::layer_tree_frame_sink() { return host_impl_->layer_tree_frame_sink(); } +int LayerTreeImpl::max_texture_size() const { + return host_impl_->max_texture_size(); +} + const LayerTreeSettings& LayerTreeImpl::settings() const { return host_impl_->settings(); } @@ -1388,10 +1410,6 @@ viz::ContextProvider* LayerTreeImpl::context_provider() const { return host_impl_->layer_tree_frame_sink()->context_provider(); } -viz::SharedBitmapManager* LayerTreeImpl::shared_bitmap_manager() const { - return host_impl_->layer_tree_frame_sink()->shared_bitmap_manager(); -} - LayerTreeResourceProvider* LayerTreeImpl::resource_provider() const { return host_impl_->resource_provider(); } diff --git a/chromium/cc/trees/layer_tree_impl.h b/chromium/cc/trees/layer_tree_impl.h index 62c31dbd0a1..11e406e78d4 100644 --- a/chromium/cc/trees/layer_tree_impl.h +++ b/chromium/cc/trees/layer_tree_impl.h @@ -106,10 +106,10 @@ class CC_EXPORT LayerTreeImpl { // Methods called by the layer tree that pass-through or access LTHI. // --------------------------------------------------------------------------- LayerTreeFrameSink* layer_tree_frame_sink(); + int max_texture_size() const; const LayerTreeSettings& settings() const; const LayerTreeDebugState& debug_state() const; viz::ContextProvider* context_provider() const; - viz::SharedBitmapManager* shared_bitmap_manager() const; LayerTreeResourceProvider* resource_provider() const; TileManager* tile_manager() const; ImageDecodeCache* image_decode_cache() const; @@ -299,11 +299,15 @@ class CC_EXPORT LayerTreeImpl { void set_content_source_id(uint32_t id) { content_source_id_ = id; } uint32_t content_source_id() { return content_source_id_; } - void set_local_surface_id(const viz::LocalSurfaceId& id) { - local_surface_id_ = id; + void SetLocalSurfaceIdFromParent(const viz::LocalSurfaceId& id); + const viz::LocalSurfaceId& local_surface_id_from_parent() const { + return local_surface_id_from_parent_; } - const viz::LocalSurfaceId& local_surface_id() const { - return local_surface_id_; + + void RequestNewLocalSurfaceId(); + bool TakeNewLocalSurfaceIdRequest(); + bool new_local_surface_id_request_for_testing() const { + return new_local_surface_id_request_; } void SetRasterColorSpace(int raster_color_space_id, @@ -608,7 +612,8 @@ class CC_EXPORT LayerTreeImpl { gfx::ColorSpace raster_color_space_; uint32_t content_source_id_; - viz::LocalSurfaceId local_surface_id_; + viz::LocalSurfaceId local_surface_id_from_parent_; + bool new_local_surface_id_request_ = false; scoped_refptr<SyncedElasticOverscroll> elastic_overscroll_; diff --git a/chromium/cc/trees/layer_tree_settings.cc b/chromium/cc/trees/layer_tree_settings.cc index 08137e0e846..3f3000b41bf 100644 --- a/chromium/cc/trees/layer_tree_settings.cc +++ b/chromium/cc/trees/layer_tree_settings.cc @@ -15,8 +15,7 @@ LayerTreeSettings::LayerTreeSettings() minimum_occlusion_tracking_size(gfx::Size(160, 160)), memory_policy(64 * 1024 * 1024, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, - ManagedMemoryPolicy::kDefaultNumResourcesLimit), - preferred_tile_format(viz::PlatformColor::BestTextureFormat()) {} + ManagedMemoryPolicy::kDefaultNumResourcesLimit) {} LayerTreeSettings::LayerTreeSettings(const LayerTreeSettings& other) = default; LayerTreeSettings::~LayerTreeSettings() = default; diff --git a/chromium/cc/trees/layer_tree_settings.h b/chromium/cc/trees/layer_tree_settings.h index 2584543f863..50b8805bc7a 100644 --- a/chromium/cc/trees/layer_tree_settings.h +++ b/chromium/cc/trees/layer_tree_settings.h @@ -93,7 +93,7 @@ class CC_EXPORT LayerTreeSettings { ManagedMemoryPolicy memory_policy; size_t decoded_image_working_set_budget_bytes = 128 * 1024 * 1024; int max_preraster_distance_in_screen_pixels = 1000; - viz::ResourceFormat preferred_tile_format; + bool use_rgba_4444 = false; bool unpremultiply_and_dither_low_bit_depth_tiles = false; bool enable_mask_tiling = true; @@ -156,6 +156,10 @@ class CC_EXPORT LayerTreeSettings { // Whether SetViewportSizeAndScale should update the painted scale factor or // the device scale factor. bool use_painted_device_scale_factor = false; + + // Whether a HitTestRegionList should be built from the active layer tree when + // submitting a CompositorFrame. + bool build_hit_test_data = false; }; } // namespace cc diff --git a/chromium/cc/trees/mutator_host.h b/chromium/cc/trees/mutator_host.h index e4aae914bae..18b7fe5118c 100644 --- a/chromium/cc/trees/mutator_host.h +++ b/chromium/cc/trees/mutator_host.h @@ -129,7 +129,6 @@ class MutatorHost { virtual size_t CompositedAnimationsCount() const = 0; virtual size_t MainThreadAnimationsCount() const = 0; - virtual size_t MainThreadCompositableAnimationsCount() const = 0; virtual bool CurrentFrameHadRAF() const = 0; virtual bool NextFrameHasPendingRAF() const = 0; }; diff --git a/chromium/cc/trees/proxy_impl.cc b/chromium/cc/trees/proxy_impl.cc index 4c4cdd4c632..06b051455ed 100644 --- a/chromium/cc/trees/proxy_impl.cc +++ b/chromium/cc/trees/proxy_impl.cc @@ -367,10 +367,6 @@ size_t ProxyImpl::MainThreadAnimationsCount() const { return host_impl_->mutator_host()->MainThreadAnimationsCount(); } -size_t ProxyImpl::MainThreadCompositableAnimationsCount() const { - return host_impl_->mutator_host()->MainThreadCompositableAnimationsCount(); -} - bool ProxyImpl::CurrentFrameHadRAF() const { return host_impl_->mutator_host()->CurrentFrameHadRAF(); } diff --git a/chromium/cc/trees/proxy_impl.h b/chromium/cc/trees/proxy_impl.h index 0e3347383df..467f0e616d8 100644 --- a/chromium/cc/trees/proxy_impl.h +++ b/chromium/cc/trees/proxy_impl.h @@ -125,7 +125,6 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient, base::TimeTicks time) override; size_t CompositedAnimationsCount() const override; size_t MainThreadAnimationsCount() const override; - size_t MainThreadCompositableAnimationsCount() const override; bool CurrentFrameHadRAF() const override; bool NextFrameHasPendingRAF() const override; diff --git a/chromium/cc/trees/proxy_main.cc b/chromium/cc/trees/proxy_main.cc index 7b7589167bb..668e674e30d 100644 --- a/chromium/cc/trees/proxy_main.cc +++ b/chromium/cc/trees/proxy_main.cc @@ -300,7 +300,7 @@ void ProxyMain::BeginMainFrame( // commit. ui::LatencyInfo new_latency_info(ui::SourceEventType::FRAME); new_latency_info.AddLatencyNumberWithTimestamp( - ui::LATENCY_BEGIN_FRAME_RENDERER_MAIN_COMPONENT, 0, 0, + ui::LATENCY_BEGIN_FRAME_RENDERER_MAIN_COMPONENT, 0, begin_main_frame_state->begin_frame_args.frame_time, 1); layer_tree_host_->QueueSwapPromise( std::make_unique<LatencyInfoSwapPromise>(new_latency_info)); diff --git a/chromium/cc/trees/render_frame_metadata.cc b/chromium/cc/trees/render_frame_metadata.cc index 4466cb928c1..5678f5c8987 100644 --- a/chromium/cc/trees/render_frame_metadata.cc +++ b/chromium/cc/trees/render_frame_metadata.cc @@ -21,7 +21,15 @@ bool RenderFrameMetadata::HasAlwaysUpdateMetadataChanged( const RenderFrameMetadata& rfm2) { return rfm1.root_background_color != rfm2.root_background_color || rfm1.is_scroll_offset_at_top != rfm2.is_scroll_offset_at_top || - rfm1.selection != rfm2.selection; + rfm1.selection != rfm2.selection || + rfm1.is_mobile_optimized != rfm2.is_mobile_optimized || + rfm1.device_scale_factor != rfm2.device_scale_factor || + rfm1.viewport_size_in_pixels != rfm2.viewport_size_in_pixels || + rfm1.local_surface_id != rfm2.local_surface_id || + rfm1.top_controls_height != rfm2.top_controls_height || + rfm1.top_controls_shown_ratio != rfm2.top_controls_shown_ratio || + rfm1.bottom_controls_height != rfm2.bottom_controls_height || + rfm1.bottom_controls_shown_ratio != rfm2.bottom_controls_shown_ratio; } RenderFrameMetadata& RenderFrameMetadata::operator=( @@ -30,14 +38,22 @@ RenderFrameMetadata& RenderFrameMetadata::operator=( RenderFrameMetadata& RenderFrameMetadata::operator=( RenderFrameMetadata&& other) = default; -bool RenderFrameMetadata::operator==(const RenderFrameMetadata& other) { +bool RenderFrameMetadata::operator==(const RenderFrameMetadata& other) const { return root_scroll_offset == other.root_scroll_offset && root_background_color == other.root_background_color && is_scroll_offset_at_top == other.is_scroll_offset_at_top && - selection == other.selection; + selection == other.selection && + is_mobile_optimized == other.is_mobile_optimized && + device_scale_factor == other.device_scale_factor && + viewport_size_in_pixels == other.viewport_size_in_pixels && + local_surface_id == other.local_surface_id && + top_controls_height == other.top_controls_height && + top_controls_shown_ratio == other.top_controls_shown_ratio && + bottom_controls_height == other.bottom_controls_height && + bottom_controls_shown_ratio == other.bottom_controls_shown_ratio; } -bool RenderFrameMetadata::operator!=(const RenderFrameMetadata& other) { +bool RenderFrameMetadata::operator!=(const RenderFrameMetadata& other) const { return !operator==(other); } diff --git a/chromium/cc/trees/render_frame_metadata.h b/chromium/cc/trees/render_frame_metadata.h index 0a20fa8d73c..d07d7d4bfc6 100644 --- a/chromium/cc/trees/render_frame_metadata.h +++ b/chromium/cc/trees/render_frame_metadata.h @@ -8,7 +8,9 @@ #include "base/optional.h" #include "cc/cc_export.h" #include "components/viz/common/quads/selection.h" +#include "components/viz/common/surfaces/local_surface_id.h" #include "third_party/skia/include/core/SkColor.h" +#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/vector2d_f.h" #include "ui/gfx/selection_bound.h" @@ -29,8 +31,8 @@ class CC_EXPORT RenderFrameMetadata { RenderFrameMetadata& operator=(const RenderFrameMetadata&); RenderFrameMetadata& operator=(RenderFrameMetadata&& other); - bool operator==(const RenderFrameMetadata& other); - bool operator!=(const RenderFrameMetadata& other); + bool operator==(const RenderFrameMetadata& other) const; + bool operator!=(const RenderFrameMetadata& other) const; // Indicates whether the scroll offset of the root layer is at top, i.e., // whether scroll_offset.y() == 0. @@ -48,6 +50,32 @@ class CC_EXPORT RenderFrameMetadata { // Selection region relative to the current viewport. If the selection is // empty or otherwise unused, the bound types will indicate such. viz::Selection<gfx::SelectionBound> selection; + + // Determines whether the page is mobile optimized or not, which means at + // least one of the following has to be true: + // - page has a width=device-width or narrower viewport. + // - page prevents zooming in or out (i.e. min and max page scale factors + // are the same). + bool is_mobile_optimized = false; + + // The device scale factor used to generate a CompositorFrame. + float device_scale_factor = 1.f; + + // The size of the viewport used to generate a CompositorFrame. + gfx::Size viewport_size_in_pixels; + + // The last viz::LocalSurfaceId used to submit a CompositorFrame. + base::Optional<viz::LocalSurfaceId> local_surface_id; + + // Used to position the Android location top bar and page content, whose + // precise position is computed by the renderer compositor. + float top_controls_height = 0.f; + float top_controls_shown_ratio = 0.f; + + // Used to position Android bottom bar, whose position is computed by the + // renderer compositor. + float bottom_controls_height = 0.f; + float bottom_controls_shown_ratio = 0.f; }; } // namespace cc diff --git a/chromium/cc/trees/single_thread_proxy.cc b/chromium/cc/trees/single_thread_proxy.cc index 541e264e720..28c45b6196b 100644 --- a/chromium/cc/trees/single_thread_proxy.cc +++ b/chromium/cc/trees/single_thread_proxy.cc @@ -381,10 +381,6 @@ size_t SingleThreadProxy::MainThreadAnimationsCount() const { return 0; } -size_t SingleThreadProxy::MainThreadCompositableAnimationsCount() const { - return 0; -} - bool SingleThreadProxy::CurrentFrameHadRAF() const { return false; } @@ -748,8 +744,8 @@ void SingleThreadProxy::BeginMainFrame( // 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); + ui::LATENCY_BEGIN_FRAME_UI_MAIN_COMPONENT, 0, begin_frame_args.frame_time, + 1); layer_tree_host_->QueueSwapPromise( std::make_unique<LatencyInfoSwapPromise>(new_latency_info)); @@ -839,7 +835,9 @@ void SingleThreadProxy::ScheduledActionPrepareTiles() { } void SingleThreadProxy::ScheduledActionInvalidateLayerTreeFrameSink() { - NOTREACHED(); + // This is an Android WebView codepath, which only uses multi-thread + // compositor. So this should not occur in single-thread mode. + NOTREACHED() << "Android Webview use-case, so multi-thread only"; } void SingleThreadProxy::ScheduledActionPerformImplSideInvalidation() { diff --git a/chromium/cc/trees/single_thread_proxy.h b/chromium/cc/trees/single_thread_proxy.h index 07b8ca1f53c..f505320da40 100644 --- a/chromium/cc/trees/single_thread_proxy.h +++ b/chromium/cc/trees/single_thread_proxy.h @@ -92,7 +92,6 @@ class CC_EXPORT SingleThreadProxy : public Proxy, base::TimeTicks time) override; size_t CompositedAnimationsCount() const override; size_t MainThreadAnimationsCount() const override; - size_t MainThreadCompositableAnimationsCount() const override; bool CurrentFrameHadRAF() const override; bool NextFrameHasPendingRAF() const override; |