blob: 6280097b16a1119d8b7007ba80fbb41d98b096e3 [file] [log] [blame]
// Copyright 2011 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_in_process.h"
#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <memory>
#include <stack>
#include <string>
#include <unordered_map>
#include "base/atomic_sequence_num.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_math.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_event_argument.h"
#include "cc/base/math_util.h"
#include "cc/blimp/client_picture_cache.h"
#include "cc/blimp/engine_picture_cache.h"
#include "cc/blimp/image_serialization_processor.h"
#include "cc/blimp/picture_data.h"
#include "cc/blimp/picture_data_conversions.h"
#include "cc/debug/devtools_instrumentation.h"
#include "cc/debug/frame_viewer_instrumentation.h"
#include "cc/debug/rendering_stats_instrumentation.h"
#include "cc/input/layer_selection_bound.h"
#include "cc/input/page_scale_animation.h"
#include "cc/layers/heads_up_display_layer.h"
#include "cc/layers/heads_up_display_layer_impl.h"
#include "cc/layers/layer.h"
#include "cc/layers/layer_iterator.h"
#include "cc/layers/painted_scrollbar_layer.h"
#include "cc/resources/ui_resource_manager.h"
#include "cc/trees/draw_property_utils.h"
#include "cc/trees/layer_tree_host_client.h"
#include "cc/trees/layer_tree_host_common.h"
#include "cc/trees/layer_tree_host_impl.h"
#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/mutator_host.h"
#include "cc/trees/property_tree_builder.h"
#include "cc/trees/proxy_main.h"
#include "cc/trees/single_thread_proxy.h"
#include "cc/trees/swap_promise_manager.h"
#include "cc/trees/tree_synchronizer.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/geometry/vector2d_conversions.h"
namespace {
static base::StaticAtomicSequenceNumber s_layer_tree_host_sequence_number;
}
namespace cc {
LayerTreeHostInProcess::InitParams::InitParams() {}
LayerTreeHostInProcess::InitParams::~InitParams() {}
std::unique_ptr<LayerTreeHostInProcess> LayerTreeHostInProcess::CreateThreaded(
scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner,
InitParams* params) {
DCHECK(params->main_task_runner.get());
DCHECK(impl_task_runner.get());
DCHECK(params->settings);
std::unique_ptr<LayerTreeHostInProcess> layer_tree_host(
new LayerTreeHostInProcess(params, CompositorMode::THREADED));
layer_tree_host->InitializeThreaded(params->main_task_runner,
impl_task_runner);
return layer_tree_host;
}
std::unique_ptr<LayerTreeHostInProcess>
LayerTreeHostInProcess::CreateSingleThreaded(
LayerTreeHostSingleThreadClient* single_thread_client,
InitParams* params) {
DCHECK(params->settings);
std::unique_ptr<LayerTreeHostInProcess> layer_tree_host(
new LayerTreeHostInProcess(params, CompositorMode::SINGLE_THREADED));
layer_tree_host->InitializeSingleThreaded(single_thread_client,
params->main_task_runner);
return layer_tree_host;
}
LayerTreeHostInProcess::LayerTreeHostInProcess(InitParams* params,
CompositorMode mode)
: LayerTreeHostInProcess(
params,
mode,
base::MakeUnique<LayerTree>(params->mutator_host, this)) {}
LayerTreeHostInProcess::LayerTreeHostInProcess(
InitParams* params,
CompositorMode mode,
std::unique_ptr<LayerTree> layer_tree)
: micro_benchmark_controller_(this),
layer_tree_(std::move(layer_tree)),
compositor_mode_(mode),
ui_resource_manager_(base::MakeUnique<UIResourceManager>()),
client_(params->client),
source_frame_number_(0),
rendering_stats_instrumentation_(RenderingStatsInstrumentation::Create()),
settings_(*params->settings),
debug_state_(settings_.initial_debug_state),
visible_(false),
has_gpu_rasterization_trigger_(false),
content_is_suitable_for_gpu_rasterization_(true),
gpu_rasterization_histogram_recorded_(false),
did_complete_scale_animation_(false),
id_(s_layer_tree_host_sequence_number.GetNext() + 1),
task_graph_runner_(params->task_graph_runner),
image_serialization_processor_(params->image_serialization_processor) {
DCHECK(task_graph_runner_);
DCHECK(layer_tree_);
DCHECK_NE(compositor_mode_, CompositorMode::REMOTE);
rendering_stats_instrumentation_->set_record_rendering_stats(
debug_state_.RecordRenderingStats());
}
void LayerTreeHostInProcess::InitializeThreaded(
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
task_runner_provider_ =
TaskRunnerProvider::Create(main_task_runner, impl_task_runner);
std::unique_ptr<ProxyMain> proxy_main =
ProxyMain::CreateThreaded(this, task_runner_provider_.get());
InitializeProxy(std::move(proxy_main));
}
void LayerTreeHostInProcess::InitializeSingleThreaded(
LayerTreeHostSingleThreadClient* single_thread_client,
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner) {
task_runner_provider_ = TaskRunnerProvider::Create(main_task_runner, nullptr);
InitializeProxy(SingleThreadProxy::Create(this, single_thread_client,
task_runner_provider_.get()));
}
void LayerTreeHostInProcess::InitializeForTesting(
std::unique_ptr<TaskRunnerProvider> task_runner_provider,
std::unique_ptr<Proxy> proxy_for_testing) {
task_runner_provider_ = std::move(task_runner_provider);
InitializePictureCacheForTesting();
InitializeProxy(std::move(proxy_for_testing));
}
void LayerTreeHostInProcess::InitializePictureCacheForTesting() {
if (!image_serialization_processor_)
return;
// Initialize both engine and client cache to ensure serialization tests
// with a single LayerTreeHostInProcess can work correctly.
engine_picture_cache_ =
image_serialization_processor_->CreateEnginePictureCache();
layer_tree_->set_engine_picture_cache(engine_picture_cache_.get());
client_picture_cache_ =
image_serialization_processor_->CreateClientPictureCache();
layer_tree_->set_client_picture_cache(client_picture_cache_.get());
}
void LayerTreeHostInProcess::SetTaskRunnerProviderForTesting(
std::unique_ptr<TaskRunnerProvider> task_runner_provider) {
DCHECK(!task_runner_provider_);
task_runner_provider_ = std::move(task_runner_provider);
}
void LayerTreeHostInProcess::SetUIResourceManagerForTesting(
std::unique_ptr<UIResourceManager> ui_resource_manager) {
ui_resource_manager_ = std::move(ui_resource_manager);
}
void LayerTreeHostInProcess::InitializeProxy(std::unique_ptr<Proxy> proxy) {
TRACE_EVENT0("cc", "LayerTreeHostInProcess::InitializeForReal");
DCHECK(task_runner_provider_);
proxy_ = std::move(proxy);
proxy_->Start();
layer_tree_->mutator_host()->SetSupportsScrollAnimations(
proxy_->SupportsImplScrolling());
}
LayerTreeHostInProcess::~LayerTreeHostInProcess() {
TRACE_EVENT0("cc", "LayerTreeHostInProcess::~LayerTreeHostInProcess");
// Clear any references into the LayerTreeHostInProcess.
layer_tree_.reset();
if (proxy_) {
DCHECK(task_runner_provider_->IsMainThread());
proxy_->Stop();
// Proxy must be destroyed before the Task Runner Provider.
proxy_ = nullptr;
}
}
int LayerTreeHostInProcess::GetId() const {
return id_;
}
int LayerTreeHostInProcess::SourceFrameNumber() const {
return source_frame_number_;
}
LayerTree* LayerTreeHostInProcess::GetLayerTree() {
return layer_tree_.get();
}
const LayerTree* LayerTreeHostInProcess::GetLayerTree() const {
return layer_tree_.get();
}
UIResourceManager* LayerTreeHostInProcess::GetUIResourceManager() const {
return ui_resource_manager_.get();
}
TaskRunnerProvider* LayerTreeHostInProcess::GetTaskRunnerProvider() const {
return task_runner_provider_.get();
}
SwapPromiseManager* LayerTreeHostInProcess::GetSwapPromiseManager() {
return &swap_promise_manager_;
}
const LayerTreeSettings& LayerTreeHostInProcess::GetSettings() const {
return settings_;
}
void LayerTreeHostInProcess::SetFrameSinkId(const FrameSinkId& frame_sink_id) {
surface_sequence_generator_.set_frame_sink_id(frame_sink_id);
}
void LayerTreeHostInProcess::QueueSwapPromise(
std::unique_ptr<SwapPromise> swap_promise) {
swap_promise_manager_.QueueSwapPromise(std::move(swap_promise));
}
SurfaceSequenceGenerator*
LayerTreeHostInProcess::GetSurfaceSequenceGenerator() {
return &surface_sequence_generator_;
}
void LayerTreeHostInProcess::WillBeginMainFrame() {
devtools_instrumentation::WillBeginMainThreadFrame(GetId(),
SourceFrameNumber());
client_->WillBeginMainFrame();
}
void LayerTreeHostInProcess::DidBeginMainFrame() {
client_->DidBeginMainFrame();
}
void LayerTreeHostInProcess::BeginMainFrameNotExpectedSoon() {
client_->BeginMainFrameNotExpectedSoon();
}
void LayerTreeHostInProcess::BeginMainFrame(const BeginFrameArgs& args) {
client_->BeginMainFrame(args);
}
void LayerTreeHostInProcess::DidStopFlinging() {
proxy_->MainThreadHasStoppedFlinging();
}
const LayerTreeDebugState& LayerTreeHostInProcess::GetDebugState() const {
return debug_state_;
}
void LayerTreeHostInProcess::RequestMainFrameUpdate() {
client_->UpdateLayerTreeHost();
}
// 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.
void LayerTreeHostInProcess::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() &&
layer_tree_->root_layer()) {
LayerTreeHostCommon::CallFunctionForEveryLayer(
layer_tree_.get(), [](Layer* layer) { layer->DidBeginTracing(); });
}
LayerTreeImpl* sync_tree = host_impl->sync_tree();
if (next_commit_forces_redraw_) {
sync_tree->ForceRedrawNextActivation();
next_commit_forces_redraw_ = false;
}
if (next_commit_forces_recalculate_raster_scales_) {
sync_tree->ForceRecalculateRasterScales();
next_commit_forces_recalculate_raster_scales_ = false;
}
sync_tree->set_source_frame_number(SourceFrameNumber());
if (layer_tree_->needs_full_tree_sync())
TreeSynchronizer::SynchronizeTrees(layer_tree_->root_layer(), sync_tree);
float page_scale_delta = 1.f;
if (reflected_main_frame_state_)
page_scale_delta = reflected_main_frame_state_->page_scale_delta;
layer_tree_->PushPropertiesTo(sync_tree, page_scale_delta);
sync_tree->PassSwapPromises(swap_promise_manager_.TakeSwapPromises());
host_impl->SetHasGpuRasterizationTrigger(has_gpu_rasterization_trigger_);
host_impl->SetContentIsSuitableForGpuRasterization(
content_is_suitable_for_gpu_rasterization_);
RecordGpuRasterizationHistogram();
host_impl->SetViewportSize(layer_tree_->device_viewport_size());
sync_tree->SetDeviceScaleFactor(layer_tree_->device_scale_factor());
host_impl->SetDebugState(debug_state_);
sync_tree->set_ui_resource_request_queue(
ui_resource_manager_->TakeUIResourcesRequests());
{
TRACE_EVENT0("cc", "LayerTreeHostInProcess::PushProperties");
TreeSynchronizer::PushLayerProperties(layer_tree_.get(), sync_tree);
if (reflected_main_frame_state_) {
for (const auto& scroll_update : reflected_main_frame_state_->scrolls) {
int layer_id = scroll_update.layer_id;
gfx::Vector2dF scroll_delta = scroll_update.scroll_delta;
PropertyTrees* property_trees = layer_tree_->property_trees();
property_trees->scroll_tree.SetScrollOffset(
layer_id, gfx::ScrollOffsetWithDelta(
layer_tree_->LayerById(layer_id)->scroll_offset(),
scroll_delta));
}
}
// This must happen after synchronizing property trees and after pushing
// properties, which updates the clobber_active_value flag.
sync_tree->UpdatePropertyTreeScrollOffset(layer_tree_->property_trees());
// This must happen after synchronizing property trees and after push
// properties, which updates property tree indices, but before animation
// host pushes properties as animation host push properties can change
// Animation::InEffect and we want the old InEffect value for updating
// property tree scrolling and animation.
sync_tree->UpdatePropertyTreeScrollingAndAnimationFromMainThread();
TRACE_EVENT0("cc", "LayerTreeHostInProcess::AnimationHost::PushProperties");
DCHECK(host_impl->mutator_host());
layer_tree_->mutator_host()->PushPropertiesTo(host_impl->mutator_host());
}
micro_benchmark_controller_.ScheduleImplBenchmarks(host_impl);
layer_tree_->property_trees()->ResetAllChangeTracking();
reflected_main_frame_state_ = nullptr;
}
void LayerTreeHostInProcess::WillCommit() {
swap_promise_manager_.WillCommit();
client_->WillCommit();
}
void LayerTreeHostInProcess::UpdateHudLayer() {}
void LayerTreeHostInProcess::CommitComplete() {
source_frame_number_++;
client_->DidCommit();
if (did_complete_scale_animation_) {
client_->DidCompletePageScaleAnimation();
did_complete_scale_animation_ = false;
}
}
void LayerTreeHostInProcess::SetCompositorFrameSink(
std::unique_ptr<CompositorFrameSink> surface) {
TRACE_EVENT0("cc", "LayerTreeHostInProcess::SetCompositorFrameSink");
DCHECK(surface);
DCHECK(!new_compositor_frame_sink_);
new_compositor_frame_sink_ = std::move(surface);
proxy_->SetCompositorFrameSink(new_compositor_frame_sink_.get());
}
std::unique_ptr<CompositorFrameSink>
LayerTreeHostInProcess::ReleaseCompositorFrameSink() {
DCHECK(!visible_);
DidLoseCompositorFrameSink();
proxy_->ReleaseCompositorFrameSink();
return std::move(current_compositor_frame_sink_);
}
void LayerTreeHostInProcess::RequestNewCompositorFrameSink() {
client_->RequestNewCompositorFrameSink();
}
void LayerTreeHostInProcess::DidInitializeCompositorFrameSink() {
DCHECK(new_compositor_frame_sink_);
current_compositor_frame_sink_ = std::move(new_compositor_frame_sink_);
client_->DidInitializeCompositorFrameSink();
}
void LayerTreeHostInProcess::DidFailToInitializeCompositorFrameSink() {
DCHECK(new_compositor_frame_sink_);
// Note: It is safe to drop all output surface references here as
// LayerTreeHostImpl will not keep a pointer to either the old or
// new CompositorFrameSink after failing to initialize the new one.
current_compositor_frame_sink_ = nullptr;
new_compositor_frame_sink_ = nullptr;
client_->DidFailToInitializeCompositorFrameSink();
}
std::unique_ptr<LayerTreeHostImpl>
LayerTreeHostInProcess::CreateLayerTreeHostImpl(
LayerTreeHostImplClient* client) {
DCHECK(task_runner_provider_->IsImplThread());
const bool supports_impl_scrolling = task_runner_provider_->HasImplThread();
std::unique_ptr<MutatorHost> mutator_host_impl =
layer_tree_->mutator_host()->CreateImplInstance(supports_impl_scrolling);
std::unique_ptr<LayerTreeHostImpl> host_impl = LayerTreeHostImpl::Create(
settings_, client, task_runner_provider_.get(),
rendering_stats_instrumentation_.get(), task_graph_runner_,
std::move(mutator_host_impl), id_);
host_impl->SetHasGpuRasterizationTrigger(has_gpu_rasterization_trigger_);
host_impl->SetContentIsSuitableForGpuRasterization(
content_is_suitable_for_gpu_rasterization_);
task_graph_runner_ = NULL;
input_handler_weak_ptr_ = host_impl->AsWeakPtr();
return host_impl;
}
void LayerTreeHostInProcess::DidLoseCompositorFrameSink() {
TRACE_EVENT0("cc", "LayerTreeHostInProcess::DidLoseCompositorFrameSink");
DCHECK(task_runner_provider_->IsMainThread());
SetNeedsCommit();
}
void LayerTreeHostInProcess::SetDeferCommits(bool defer_commits) {
proxy_->SetDeferCommits(defer_commits);
}
DISABLE_CFI_PERF
void LayerTreeHostInProcess::SetNeedsAnimate() {
proxy_->SetNeedsAnimate();
swap_promise_manager_.NotifySwapPromiseMonitorsOfSetNeedsCommit();
}
DISABLE_CFI_PERF
void LayerTreeHostInProcess::SetNeedsUpdateLayers() {
proxy_->SetNeedsUpdateLayers();
swap_promise_manager_.NotifySwapPromiseMonitorsOfSetNeedsCommit();
}
void LayerTreeHostInProcess::SetNeedsCommit() {
proxy_->SetNeedsCommit();
swap_promise_manager_.NotifySwapPromiseMonitorsOfSetNeedsCommit();
}
void LayerTreeHostInProcess::SetNeedsRecalculateRasterScales() {
next_commit_forces_recalculate_raster_scales_ = true;
proxy_->SetNeedsCommit();
}
void LayerTreeHostInProcess::SetNeedsRedrawRect(const gfx::Rect& damage_rect) {
proxy_->SetNeedsRedraw(damage_rect);
}
bool LayerTreeHostInProcess::CommitRequested() const {
return proxy_->CommitRequested();
}
bool LayerTreeHostInProcess::BeginMainFrameRequested() const {
return proxy_->BeginMainFrameRequested();
}
void LayerTreeHostInProcess::SetNextCommitWaitsForActivation() {
proxy_->SetNextCommitWaitsForActivation();
}
void LayerTreeHostInProcess::SetNextCommitForcesRedraw() {
next_commit_forces_redraw_ = true;
proxy_->SetNeedsUpdateLayers();
}
void LayerTreeHostInProcess::SetAnimationEvents(
std::unique_ptr<MutatorEvents> events) {
DCHECK(task_runner_provider_->IsMainThread());
layer_tree_->mutator_host()->SetAnimationEvents(std::move(events));
}
void LayerTreeHostInProcess::SetDebugState(
const LayerTreeDebugState& debug_state) {
LayerTreeDebugState new_debug_state =
LayerTreeDebugState::Unite(settings_.initial_debug_state, debug_state);
if (LayerTreeDebugState::Equal(debug_state_, new_debug_state))
return;
debug_state_ = new_debug_state;
rendering_stats_instrumentation_->set_record_rendering_stats(
debug_state_.RecordRenderingStats());
SetNeedsCommit();
}
void LayerTreeHostInProcess::ResetGpuRasterizationTracking() {
content_is_suitable_for_gpu_rasterization_ = true;
gpu_rasterization_histogram_recorded_ = false;
}
void LayerTreeHostInProcess::SetHasGpuRasterizationTrigger(bool has_trigger) {
if (has_trigger == has_gpu_rasterization_trigger_)
return;
has_gpu_rasterization_trigger_ = has_trigger;
TRACE_EVENT_INSTANT1(
"cc", "LayerTreeHostInProcess::SetHasGpuRasterizationTrigger",
TRACE_EVENT_SCOPE_THREAD, "has_trigger", has_gpu_rasterization_trigger_);
}
void LayerTreeHostInProcess::ApplyPageScaleDeltaFromImplSide(
float page_scale_delta) {
DCHECK(CommitRequested());
if (page_scale_delta == 1.f)
return;
float page_scale = layer_tree_->page_scale_factor() * page_scale_delta;
layer_tree_->SetPageScaleFromImplSide(page_scale);
}
void LayerTreeHostInProcess::SetVisible(bool visible) {
if (visible_ == visible)
return;
visible_ = visible;
proxy_->SetVisible(visible);
}
bool LayerTreeHostInProcess::IsVisible() const {
return visible_;
}
void LayerTreeHostInProcess::NotifyInputThrottledUntilCommit() {
proxy_->NotifyInputThrottledUntilCommit();
}
void LayerTreeHostInProcess::LayoutAndUpdateLayers() {
DCHECK(IsSingleThreaded());
// This function is only valid when not using the scheduler.
DCHECK(!settings_.single_thread_proxy_scheduler);
RequestMainFrameUpdate();
UpdateLayers();
}
void LayerTreeHostInProcess::Composite(base::TimeTicks frame_begin_time) {
DCHECK(IsSingleThreaded());
// This function is only valid when not using the scheduler.
DCHECK(!settings_.single_thread_proxy_scheduler);
SingleThreadProxy* proxy = static_cast<SingleThreadProxy*>(proxy_.get());
proxy->CompositeImmediately(frame_begin_time);
}
bool LayerTreeHostInProcess::UpdateLayers() {
if (!layer_tree_->root_layer())
return false;
DCHECK(!layer_tree_->root_layer()->parent());
bool result = DoUpdateLayers(layer_tree_->root_layer());
micro_benchmark_controller_.DidUpdateLayers();
return result || next_commit_forces_redraw_;
}
void LayerTreeHostInProcess::DidCompletePageScaleAnimation() {
did_complete_scale_animation_ = true;
}
void LayerTreeHostInProcess::RecordGpuRasterizationHistogram() {
// Gpu rasterization is only supported for Renderer compositors.
// Checking for IsSingleThreaded() to exclude Browser compositors.
if (gpu_rasterization_histogram_recorded_ || IsSingleThreaded())
return;
// Record how widely gpu rasterization is enabled.
// This number takes device/gpu whitelisting/backlisting into account.
// Note that we do not consider the forced gpu rasterization mode, which is
// mostly used for debugging purposes.
UMA_HISTOGRAM_BOOLEAN("Renderer4.GpuRasterizationEnabled",
settings_.gpu_rasterization_enabled);
if (settings_.gpu_rasterization_enabled) {
UMA_HISTOGRAM_BOOLEAN("Renderer4.GpuRasterizationTriggered",
has_gpu_rasterization_trigger_);
UMA_HISTOGRAM_BOOLEAN("Renderer4.GpuRasterizationSuitableContent",
content_is_suitable_for_gpu_rasterization_);
// Record how many pages actually get gpu rasterization when enabled.
UMA_HISTOGRAM_BOOLEAN("Renderer4.GpuRasterizationUsed",
(has_gpu_rasterization_trigger_ &&
content_is_suitable_for_gpu_rasterization_));
}
gpu_rasterization_histogram_recorded_ = true;
}
bool LayerTreeHostInProcess::DoUpdateLayers(Layer* root_layer) {
TRACE_EVENT1("cc", "LayerTreeHostInProcess::DoUpdateLayers",
"source_frame_number", SourceFrameNumber());
layer_tree_->UpdateHudLayer(debug_state_.ShowHudInfo());
UpdateHudLayer();
Layer* root_scroll =
PropertyTreeBuilder::FindFirstScrollableLayer(root_layer);
Layer* page_scale_layer = layer_tree_->page_scale_layer();
if (!page_scale_layer && root_scroll)
page_scale_layer = root_scroll->parent();
if (layer_tree_->hud_layer()) {
layer_tree_->hud_layer()->PrepareForCalculateDrawProperties(
layer_tree_->device_viewport_size(),
layer_tree_->device_scale_factor());
}
gfx::Transform identity_transform;
LayerList update_layer_list;
{
TRACE_EVENT0("cc",
"LayerTreeHostInProcess::UpdateLayers::BuildPropertyTrees");
TRACE_EVENT0(
TRACE_DISABLED_BY_DEFAULT("cc.debug.cdp-perf"),
"LayerTreeHostInProcessCommon::ComputeVisibleRectsWithPropertyTrees");
PropertyTreeBuilder::PreCalculateMetaInformation(root_layer);
bool can_render_to_separate_surface = true;
PropertyTrees* property_trees = layer_tree_->property_trees();
if (!settings_.use_layer_lists) {
// If use_layer_lists is set, then the property trees should have been
// built by the client already.
PropertyTreeBuilder::BuildPropertyTrees(
root_layer, page_scale_layer,
layer_tree_->inner_viewport_scroll_layer(),
layer_tree_->outer_viewport_scroll_layer(),
layer_tree_->overscroll_elasticity_layer(),
layer_tree_->elastic_overscroll(), layer_tree_->page_scale_factor(),
layer_tree_->device_scale_factor(),
gfx::Rect(layer_tree_->device_viewport_size()), identity_transform,
property_trees);
TRACE_EVENT_INSTANT1(
"cc", "LayerTreeHostInProcess::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());
}
draw_property_utils::UpdatePropertyTrees(property_trees,
can_render_to_separate_surface);
draw_property_utils::FindLayersThatNeedUpdates(
layer_tree_.get(), property_trees, &update_layer_list);
}
for (const auto& layer : update_layer_list)
layer->SavePaintProperties();
bool content_is_suitable_for_gpu = true;
bool did_paint_content = layer_tree_->UpdateLayers(
update_layer_list, &content_is_suitable_for_gpu);
if (content_is_suitable_for_gpu) {
++num_consecutive_frames_suitable_for_gpu_;
if (num_consecutive_frames_suitable_for_gpu_ >=
kNumFramesToConsiderBeforeGpuRasterization) {
content_is_suitable_for_gpu_rasterization_ = true;
}
} else {
num_consecutive_frames_suitable_for_gpu_ = 0;
content_is_suitable_for_gpu_rasterization_ = false;
}
return did_paint_content;
}
void LayerTreeHostInProcess::ApplyViewportDeltas(ScrollAndScaleSet* info) {
gfx::Vector2dF inner_viewport_scroll_delta;
if (info->inner_viewport_scroll.layer_id != Layer::INVALID_ID)
inner_viewport_scroll_delta = info->inner_viewport_scroll.scroll_delta;
if (inner_viewport_scroll_delta.IsZero() && info->page_scale_delta == 1.f &&
info->elastic_overscroll_delta.IsZero() && !info->top_controls_delta)
return;
// Preemptively apply the scroll offset and scale delta here before sending
// it to the client. If the client comes back and sets it to the same
// value, then the layer can early out without needing a full commit.
if (layer_tree_->inner_viewport_scroll_layer()) {
layer_tree_->inner_viewport_scroll_layer()->SetScrollOffsetFromImplSide(
gfx::ScrollOffsetWithDelta(
layer_tree_->inner_viewport_scroll_layer()->scroll_offset(),
inner_viewport_scroll_delta));
}
ApplyPageScaleDeltaFromImplSide(info->page_scale_delta);
layer_tree_->SetElasticOverscrollFromImplSide(
layer_tree_->elastic_overscroll() + info->elastic_overscroll_delta);
// TODO(ccameron): pass the elastic overscroll here so that input events
// may be translated appropriately.
client_->ApplyViewportDeltas(inner_viewport_scroll_delta, gfx::Vector2dF(),
info->elastic_overscroll_delta,
info->page_scale_delta,
info->top_controls_delta);
SetNeedsUpdateLayers();
}
void LayerTreeHostInProcess::ApplyScrollAndScale(ScrollAndScaleSet* info) {
for (auto& swap_promise : info->swap_promises) {
TRACE_EVENT_WITH_FLOW1("input,benchmark", "LatencyInfo.Flow",
TRACE_ID_DONT_MANGLE(swap_promise->TraceId()),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
"step", "Main thread scroll update");
swap_promise_manager_.QueueSwapPromise(std::move(swap_promise));
}
if (layer_tree_->root_layer()) {
for (size_t i = 0; i < info->scrolls.size(); ++i) {
Layer* layer = layer_tree_->LayerById(info->scrolls[i].layer_id);
if (!layer)
continue;
layer->SetScrollOffsetFromImplSide(gfx::ScrollOffsetWithDelta(
layer->scroll_offset(), info->scrolls[i].scroll_delta));
SetNeedsUpdateLayers();
}
for (size_t i = 0; i < info->scrollbars.size(); ++i) {
Layer* layer = layer_tree_->LayerById(info->scrollbars[i].layer_id);
if (!layer)
continue;
layer->SetScrollbarsHiddenFromImplSide(info->scrollbars[i].hidden);
}
}
// This needs to happen after scroll deltas have been sent to prevent top
// controls from clamping the layout viewport both on the compositor and
// on the main thread.
ApplyViewportDeltas(info);
}
void LayerTreeHostInProcess::SetReflectedMainFrameState(
std::unique_ptr<ReflectedMainFrameState> reflected_main_frame_state) {
DCHECK(IsThreaded());
reflected_main_frame_state_ = std::move(reflected_main_frame_state);
SetNeedsCommit();
}
const base::WeakPtr<InputHandler>& LayerTreeHostInProcess::GetInputHandler()
const {
return input_handler_weak_ptr_;
}
void LayerTreeHostInProcess::UpdateBrowserControlsState(
BrowserControlsState constraints,
BrowserControlsState current,
bool animate) {
// Browser controls are only used in threaded mode.
DCHECK(IsThreaded());
proxy_->UpdateBrowserControlsState(constraints, current, animate);
}
void LayerTreeHostInProcess::AnimateLayers(base::TimeTicks monotonic_time) {
MutatorHost* mutator_host = layer_tree_->mutator_host();
std::unique_ptr<MutatorEvents> events = mutator_host->CreateEvents();
if (mutator_host->AnimateLayers(monotonic_time))
mutator_host->UpdateAnimationState(true, events.get());
if (!events->IsEmpty())
layer_tree_->property_trees()->needs_rebuild = true;
}
int LayerTreeHostInProcess::ScheduleMicroBenchmark(
const std::string& benchmark_name,
std::unique_ptr<base::Value> value,
const MicroBenchmark::DoneCallback& callback) {
return micro_benchmark_controller_.ScheduleRun(benchmark_name,
std::move(value), callback);
}
bool LayerTreeHostInProcess::SendMessageToMicroBenchmark(
int id,
std::unique_ptr<base::Value> value) {
return micro_benchmark_controller_.SendMessage(id, std::move(value));
}
void LayerTreeHostInProcess::SetLayerTreeMutator(
std::unique_ptr<LayerTreeMutator> mutator) {
proxy_->SetMutator(std::move(mutator));
}
bool LayerTreeHostInProcess::IsSingleThreaded() const {
DCHECK(compositor_mode_ != CompositorMode::SINGLE_THREADED ||
!task_runner_provider_->HasImplThread());
return compositor_mode_ == CompositorMode::SINGLE_THREADED;
}
bool LayerTreeHostInProcess::IsThreaded() const {
DCHECK(compositor_mode_ != CompositorMode::THREADED ||
task_runner_provider_->HasImplThread());
return compositor_mode_ == CompositorMode::THREADED;
}
} // namespace cc