| Index: cc/blimp/layer_tree_host_remote.cc
|
| diff --git a/cc/blimp/layer_tree_host_remote.cc b/cc/blimp/layer_tree_host_remote.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b0158c13682a8e95112f71efb8bf28994eab47e6
|
| --- /dev/null
|
| +++ b/cc/blimp/layer_tree_host_remote.cc
|
| @@ -0,0 +1,415 @@
|
| +// Copyright 2016 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/blimp/layer_tree_host_remote.h"
|
| +
|
| +#include "base/atomic_sequence_num.h"
|
| +#include "base/memory/ptr_util.h"
|
| +#include "cc/animation/animation_host.h"
|
| +#include "cc/blimp/compositor_proto_state.h"
|
| +#include "cc/blimp/remote_compositor_bridge.h"
|
| +#include "cc/output/begin_frame_args.h"
|
| +#include "cc/output/compositor_frame_sink.h"
|
| +#include "cc/trees/layer_tree.h"
|
| +#include "cc/trees/layer_tree_host_client.h"
|
| +#include "cc/trees/layer_tree_host_common.h"
|
| +#include "cc/trees/task_runner_provider.h"
|
| +
|
| +namespace cc {
|
| +namespace {
|
| +// We use a 16ms default frame interval because the rate at which the engine
|
| +// produces main frames doesn't matter.
|
| +base::TimeDelta kDefaultFrameInterval = base::TimeDelta::FromMilliseconds(16);
|
| +
|
| +static base::StaticAtomicSequenceNumber s_layer_tree_host_sequence_number;
|
| +} // namespace
|
| +
|
| +LayerTreeHostRemote::InitParams::InitParams() = default;
|
| +
|
| +LayerTreeHostRemote::InitParams::~InitParams() = default;
|
| +
|
| +LayerTreeHostRemote::LayerTreeHostRemote(InitParams* params)
|
| + : LayerTreeHostRemote(
|
| + params,
|
| + base::MakeUnique<LayerTree>(std::move(params->animation_host),
|
| + this)) {}
|
| +
|
| +LayerTreeHostRemote::LayerTreeHostRemote(InitParams* params,
|
| + std::unique_ptr<LayerTree> layer_tree)
|
| + : id_(s_layer_tree_host_sequence_number.GetNext() + 1),
|
| + main_frame_requested_from_bridge_(false),
|
| + client_(params->client),
|
| + task_runner_provider_(
|
| + TaskRunnerProvider::Create(std::move(params->main_task_runner),
|
| + nullptr)),
|
| + remote_compositor_bridge_(std::move(params->remote_compositor_bridge)),
|
| + settings_(*params->settings),
|
| + layer_tree_(std::move(layer_tree)),
|
| + weak_factory_(this) {
|
| + DCHECK(task_runner_provider_->IsMainThread());
|
| + DCHECK(remote_compositor_bridge_);
|
| + DCHECK(client_);
|
| + remote_compositor_bridge_->BindToClient(this);
|
| +}
|
| +
|
| +LayerTreeHostRemote::~LayerTreeHostRemote() = default;
|
| +
|
| +int LayerTreeHostRemote::GetId() const {
|
| + return id_;
|
| +}
|
| +
|
| +int LayerTreeHostRemote::SourceFrameNumber() const {
|
| + return source_frame_number_;
|
| +}
|
| +
|
| +LayerTree* LayerTreeHostRemote::GetLayerTree() {
|
| + return layer_tree_.get();
|
| +}
|
| +
|
| +const LayerTree* LayerTreeHostRemote::GetLayerTree() const {
|
| + return layer_tree_.get();
|
| +}
|
| +
|
| +UIResourceManager* LayerTreeHostRemote::GetUIResourceManager() const {
|
| + // We shouldn't need a UIResourceManager. The layers which need this
|
| + // (UIResourceLayers and PaintedScrollbarLayers) are never used by the
|
| + // renderer compositor in remote mode.
|
| + NOTREACHED() << "UIResourceManager requested. Unsupported Layer type used";
|
| + return nullptr;
|
| +}
|
| +
|
| +TaskRunnerProvider* LayerTreeHostRemote::GetTaskRunnerProvider() const {
|
| + return task_runner_provider_.get();
|
| +}
|
| +
|
| +const LayerTreeSettings& LayerTreeHostRemote::GetSettings() const {
|
| + return settings_;
|
| +}
|
| +
|
| +void LayerTreeHostRemote::SetFrameSinkId(const FrameSinkId& frame_sink_id) {
|
| + // We don't need to care about SurfaceLayers. The Surfaces system is
|
| + // relevant on the client only.
|
| +}
|
| +
|
| +void LayerTreeHostRemote::SetLayerTreeMutator(
|
| + std::unique_ptr<LayerTreeMutator> mutator) {
|
| + // TODO(khushalsagar): Compositor-worker not supported. See crbug.com/650876.
|
| +}
|
| +
|
| +void LayerTreeHostRemote::QueueSwapPromise(
|
| + std::unique_ptr<SwapPromise> swap_promise) {
|
| + swap_promise_manager_.QueueSwapPromise(std::move(swap_promise));
|
| +}
|
| +
|
| +SwapPromiseManager* LayerTreeHostRemote::GetSwapPromiseManager() {
|
| + return &swap_promise_manager_;
|
| +}
|
| +
|
| +void LayerTreeHostRemote::SetHasGpuRasterizationTrigger(bool has_trigger) {
|
| + // TODO(khushalsagar) : Take care of Gpu raster. See crbug.com/650431.
|
| +}
|
| +
|
| +void LayerTreeHostRemote::SetVisible(bool visible) {
|
| + // The visibility of the compositor is controlled on the client, which is
|
| + // why this value is not sent there, since the client has the current true
|
| + // state.
|
| + visible_ = visible;
|
| +}
|
| +
|
| +bool LayerTreeHostRemote::IsVisible() const {
|
| + return visible_;
|
| +}
|
| +
|
| +void LayerTreeHostRemote::SetCompositorFrameSink(
|
| + std::unique_ptr<CompositorFrameSink> compositor_frame_sink) {
|
| + NOTREACHED()
|
| + << "The LayerTreeHostClient is never asked for a CompositorFrameSink";
|
| +}
|
| +
|
| +std::unique_ptr<CompositorFrameSink>
|
| +LayerTreeHostRemote::ReleaseCompositorFrameSink() {
|
| + // Since we never have a CompositorFrameSink, this is always a no-op.
|
| + return nullptr;
|
| +}
|
| +
|
| +void LayerTreeHostRemote::SetNeedsAnimate() {
|
| + MainFrameRequested(FramePipelineStage::ANIMATE);
|
| +}
|
| +
|
| +void LayerTreeHostRemote::SetNeedsUpdateLayers() {
|
| + MainFrameRequested(FramePipelineStage::UPDATE_LAYERS);
|
| +}
|
| +
|
| +void LayerTreeHostRemote::SetNeedsCommit() {
|
| + MainFrameRequested(FramePipelineStage::COMMIT);
|
| +}
|
| +
|
| +bool LayerTreeHostRemote::BeginMainFrameRequested() const {
|
| + return requested_pipeline_stage_for_next_frame_ != FramePipelineStage::NONE;
|
| +}
|
| +
|
| +bool LayerTreeHostRemote::CommitRequested() const {
|
| + return requested_pipeline_stage_for_next_frame_ == FramePipelineStage::COMMIT;
|
| +}
|
| +
|
| +void LayerTreeHostRemote::SetDeferCommits(bool defer_commits) {
|
| + defer_commits_ = defer_commits;
|
| + ScheduleMainFrameIfNecessary();
|
| +}
|
| +
|
| +void LayerTreeHostRemote::LayoutAndUpdateLayers() {
|
| + NOTREACHED() << "Only supported in single-threaded mode and this class"
|
| + << " does not support single-thread since it is out of process";
|
| +}
|
| +
|
| +void LayerTreeHostRemote::Composite(base::TimeTicks frame_begin_time) {
|
| + NOTREACHED() << "Only supported in single-threaded mode and this class"
|
| + << " does not support single-thread since it is out of process";
|
| +}
|
| +
|
| +void LayerTreeHostRemote::SetNeedsRedraw() {
|
| + // The engine shouldn't need to care about draws. CompositorFrames are never
|
| + // used here.
|
| + NOTREACHED();
|
| +}
|
| +
|
| +void LayerTreeHostRemote::SetNeedsRedrawRect(const gfx::Rect& damage_rect) {
|
| + // The engine shouldn't need to care about draws. CompositorFrames are never
|
| + // used here.
|
| + // TODO(khushalsagar): The caller could be waiting for an Ack for this redraw.
|
| + // We need a better solution for this. See crbug.com/651141.
|
| + NOTIMPLEMENTED();
|
| +}
|
| +
|
| +void LayerTreeHostRemote::SetNextCommitForcesRedraw() {
|
| + // Ideally the engine shouldn't need to care about draw requests at all. The
|
| + // compositor that produces CompositorFrames is on the client and draw
|
| + // requests should be made directly to it on the client itself.
|
| + NOTREACHED();
|
| +}
|
| +
|
| +void LayerTreeHostRemote::NotifyInputThrottledUntilCommit() {
|
| + // This notification is used in the case where the renderer handles an input
|
| + // event, and needs to send an Ack to the browser when the resulting main
|
| + // frame is committed. If the compositor is taking too long on the pending
|
| + // tree, the commit processing will be delayed blocking all input as a result.
|
| + // So this is used to have the compositor activate the pending tree faster, so
|
| + // the pending commit can be processed.
|
| + // In remote mode, we don't send such notifications to the client because the
|
| + // most likely bottleneck is the transport instead of raster. Also, input is
|
| + // queued on the client, so if raster does end up being a bottleneck, the
|
| + // input handling code on the client informs the LayerTreeHostInProcess
|
| + // directly.
|
| + NOTIMPLEMENTED();
|
| +}
|
| +
|
| +void LayerTreeHostRemote::UpdateTopControlsState(TopControlsState constraints,
|
| + TopControlsState current,
|
| + bool animate) {
|
| + NOTREACHED() << "Using TopControls animations is not supported";
|
| +}
|
| +
|
| +const base::WeakPtr<InputHandler>& LayerTreeHostRemote::GetInputHandler()
|
| + const {
|
| + // Input on the compositor thread is handled on the client, so this is always
|
| + // null.
|
| + return input_handler_weak_ptr_;
|
| +}
|
| +
|
| +void LayerTreeHostRemote::DidStopFlinging() {
|
| + // TODO(khushalsagar): This should not happen. See crbug.com/652000.
|
| + NOTIMPLEMENTED() << "We shouldn't be sending fling gestures to the engine";
|
| +}
|
| +
|
| +void LayerTreeHostRemote::SetDebugState(
|
| + const LayerTreeDebugState& debug_state) {
|
| + // TODO(khushalsagar): Figure out if we need to send these to the client.
|
| + NOTREACHED();
|
| +}
|
| +
|
| +const LayerTreeDebugState& LayerTreeHostRemote::GetDebugState() const {
|
| + return debug_state_;
|
| +}
|
| +
|
| +int LayerTreeHostRemote::ScheduleMicroBenchmark(
|
| + const std::string& benchmark_name,
|
| + std::unique_ptr<base::Value> value,
|
| + const MicroBenchmark::DoneCallback& callback) {
|
| + NOTREACHED();
|
| + return 0;
|
| +}
|
| +
|
| +bool LayerTreeHostRemote::SendMessageToMicroBenchmark(
|
| + int id,
|
| + std::unique_ptr<base::Value> value) {
|
| + NOTREACHED();
|
| + return false;
|
| +}
|
| +
|
| +SurfaceSequenceGenerator* LayerTreeHostRemote::GetSurfaceSequenceGenerator() {
|
| + // TODO(khushalsagar): Eliminate the use of this in blink. See
|
| + // crbug.com/650876.
|
| + return &surface_sequence_generator_;
|
| +}
|
| +
|
| +void LayerTreeHostRemote::SetNextCommitWaitsForActivation() {
|
| + // This is used only by layers that need resource synchronization, i.e.,
|
| + // texture and surface layers, both of which are not supported.
|
| + NOTIMPLEMENTED() << "Unsupported Layer type used";
|
| +}
|
| +
|
| +void LayerTreeHostRemote::ResetGpuRasterizationTracking() {
|
| + // TODO(khushalsagar): Take care of Gpu raster. See crbug.com/650431.
|
| +}
|
| +
|
| +void LayerTreeHostRemote::MainFrameRequested(
|
| + FramePipelineStage requested_pipeline_stage) {
|
| + DCHECK_NE(FramePipelineStage::NONE, requested_pipeline_stage);
|
| +
|
| + swap_promise_manager_.NotifySwapPromiseMonitorsOfSetNeedsCommit();
|
| +
|
| + // If we are inside a main frame update right now and the requested pipeline
|
| + // stage is higher than the pipeline stage that we are at, then we'll get to
|
| + // in this main frame update itself. Update the
|
| + // |max_pipeline_stage_for_current_frame_| to ensure we go through the
|
| + // requested pipeline stage.
|
| + if (current_pipeline_stage_ != FramePipelineStage::NONE &&
|
| + requested_pipeline_stage > current_pipeline_stage_) {
|
| + max_pipeline_stage_for_current_frame_ = std::max(
|
| + max_pipeline_stage_for_current_frame_, requested_pipeline_stage);
|
| + return;
|
| + }
|
| +
|
| + // Update the pipeline stage for the next frame and schedule an update if it
|
| + // has not been scheduled already.
|
| + requested_pipeline_stage_for_next_frame_ = std::max(
|
| + requested_pipeline_stage_for_next_frame_, requested_pipeline_stage);
|
| +
|
| + ScheduleMainFrameIfNecessary();
|
| +}
|
| +
|
| +void LayerTreeHostRemote::ScheduleMainFrameIfNecessary() {
|
| + // If the client hasn't asked for a main frame, don't schedule one.
|
| + if (requested_pipeline_stage_for_next_frame_ == FramePipelineStage::NONE)
|
| + return;
|
| +
|
| + // If the client does not want us to run main frame updates right now, don't
|
| + // schedule one.
|
| + if (defer_commits_)
|
| + return;
|
| +
|
| + // If a main frame request is already pending with the
|
| + // RemoteCompositorBridge, we don't need to scheduler another one.
|
| + if (main_frame_requested_from_bridge_)
|
| + return;
|
| +
|
| + remote_compositor_bridge_->ScheduleMainFrame();
|
| + main_frame_requested_from_bridge_ = true;
|
| +}
|
| +
|
| +void LayerTreeHostRemote::BeginMainFrame() {
|
| + DCHECK(main_frame_requested_from_bridge_);
|
| + DCHECK(task_runner_provider_->IsMainThread());
|
| +
|
| + main_frame_requested_from_bridge_ = false;
|
| +
|
| + // The client might have suspended main frames in the meantime. Early out now,
|
| + // we'll come back here when they enable main frames again.
|
| + if (defer_commits_)
|
| + return;
|
| +
|
| + DCHECK_EQ(current_pipeline_stage_, FramePipelineStage::NONE);
|
| + DCHECK_EQ(max_pipeline_stage_for_current_frame_, FramePipelineStage::NONE);
|
| + DCHECK_NE(requested_pipeline_stage_for_next_frame_, FramePipelineStage::NONE);
|
| +
|
| + // Start the main frame. It should go till the requested pipeline stage.
|
| + max_pipeline_stage_for_current_frame_ =
|
| + requested_pipeline_stage_for_next_frame_;
|
| + requested_pipeline_stage_for_next_frame_ = FramePipelineStage::NONE;
|
| +
|
| + client_->WillBeginMainFrame();
|
| +
|
| + current_pipeline_stage_ = FramePipelineStage::ANIMATE;
|
| + base::TimeTicks now = base::TimeTicks::Now();
|
| + client_->BeginMainFrame(BeginFrameArgs::Create(
|
| + BEGINFRAME_FROM_HERE, now, now + kDefaultFrameInterval,
|
| + kDefaultFrameInterval, BeginFrameArgs::NORMAL));
|
| + // We don't run any animations on the layer because threaded animations are
|
| + // disabled.
|
| + // TODO(khushalsagar): Revisit this when adding support for animations.
|
| + DCHECK(!layer_tree_->animation_host()->needs_push_properties());
|
| + client_->UpdateLayerTreeHost();
|
| +
|
| + current_pipeline_stage_ = FramePipelineStage::UPDATE_LAYERS;
|
| + LayerList layer_list;
|
| + if (max_pipeline_stage_for_current_frame_ >=
|
| + FramePipelineStage::UPDATE_LAYERS) {
|
| + // Pull updates for all layers from the client.
|
| + // TODO(khushalsagar): Investigate the data impact from updating all the
|
| + // layers. See crbug.com/650885.
|
| + LayerTreeHostCommon::CallFunctionForEveryLayer(
|
| + layer_tree_.get(),
|
| + [&layer_list](Layer* layer) { layer_list.push_back(layer); });
|
| +
|
| + bool content_is_suitable_for_gpu = false;
|
| + bool layers_updated =
|
| + layer_tree_->UpdateLayers(layer_list, &content_is_suitable_for_gpu);
|
| +
|
| + // If pulling layer updates resulted in any content updates, we need to go
|
| + // till the commit stage.
|
| + if (layers_updated)
|
| + max_pipeline_stage_for_current_frame_ = FramePipelineStage::COMMIT;
|
| + }
|
| +
|
| + current_pipeline_stage_ = FramePipelineStage::COMMIT;
|
| + client_->WillCommit();
|
| +
|
| + if (max_pipeline_stage_for_current_frame_ < current_pipeline_stage_) {
|
| + // There is nothing to commit so break the swap promises.
|
| + swap_promise_manager_.BreakSwapPromises(
|
| + SwapPromise::DidNotSwapReason::COMMIT_NO_UPDATE);
|
| +
|
| + // For the client, the commit was successful.
|
| + MainFrameComplete();
|
| + return;
|
| + }
|
| +
|
| + // TODO(khushalsagar): Serialize current state/reset dirty state tracking and
|
| + // return the result to the bridge instead.
|
| + std::unique_ptr<CompositorProtoState> compositor_state =
|
| + base::MakeUnique<CompositorProtoState>();
|
| + remote_compositor_bridge_->ProcessCompositorStateUpdate(
|
| + std::move(compositor_state));
|
| +
|
| + MainFrameComplete();
|
| +
|
| + // We can not wait for updates dispatched from the client about the state of
|
| + // drawing or swaps for frames sent. Since these calls can be used by the
|
| + // LayerTreeHostClient to throttle further frame updates, so dispatch them
|
| + // right after the update is processed by the bridge.
|
| + // TODO(khushalsagar): We can not really know what these callbacks end up
|
| + // being used for. Consider migrating clients to understand/cope with the fact
|
| + // that there is no actual compositing happening here.
|
| + task_runner_provider_->MainThreadTaskRunner()->PostTask(
|
| + FROM_HERE, base::Bind(&LayerTreeHostRemote::DispatchDrawAndSwapCallbacks,
|
| + weak_factory_.GetWeakPtr()));
|
| +}
|
| +
|
| +void LayerTreeHostRemote::MainFrameComplete() {
|
| + DCHECK_EQ(current_pipeline_stage_, FramePipelineStage::COMMIT);
|
| +
|
| + current_pipeline_stage_ = FramePipelineStage::NONE;
|
| + max_pipeline_stage_for_current_frame_ = FramePipelineStage::NONE;
|
| + source_frame_number_++;
|
| +
|
| + client_->DidCommit();
|
| + client_->DidBeginMainFrame();
|
| +}
|
| +
|
| +void LayerTreeHostRemote::DispatchDrawAndSwapCallbacks() {
|
| + client_->DidCommitAndDrawFrame();
|
| + client_->DidCompleteSwapBuffers();
|
| +}
|
| +
|
| +} // namespace cc
|
|
|