Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(663)

Unified Diff: cc/blimp/layer_tree_host_remote.cc

Issue 2362073002: cc/blimp: Add a LayerTreeHostRemote implementation. (Closed)
Patch Set: win Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..6c183577a228af628510b5ea2801ce232d714adb
--- /dev/null
+++ b/cc/blimp/layer_tree_host_remote.cc
@@ -0,0 +1,419 @@
+// 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/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);
+} // 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_(LayerTreeHost::GenerateHostId()),
+ source_frame_number_(0),
danakj 2016/09/30 22:37:13 can you move constant initializers like this out t
Khushal 2016/10/01 00:53:48 Done.
+ visible_(false),
+ defer_commits_(false),
+ main_frame_requested_from_bridge_(false),
+ current_pipeline_stage_(FramePipelineStage::NONE),
+ max_pipeline_stage_for_current_frame_(FramePipelineStage::NONE),
+ requested_pipeline_stage_for_next_frame_(FramePipelineStage::NONE),
+ 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() {
+ // 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::SetSurfaceClientId(uint32_t client_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));
danakj 2016/09/30 22:37:13 API feedback it's a bit weird that this class can
Khushal 2016/10/01 00:53:48 For this one you would have to talk to piman@, htt
danakj 2016/10/03 21:02:48 Thanks for the pointer.
+}
+
+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.
danakj 2016/09/30 22:37:13 ".. but we fake it for blink because .."
danakj 2016/09/30 22:38:31 oops i lied we shouldnt say blink here. "for the c
Khushal 2016/10/01 00:53:48 Not sure what you mean, we don't fake anything her
danakj 2016/10/03 21:02:48 What I mean by fake, this doesn't actually change
+ 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() {
+ NOTIMPLEMENTED() << "We shouldn't be sending fling gestures to the engine";
danakj 2016/09/30 22:37:13 NOTREACHED() unless we are sending fling gestures,
Khushal 2016/10/01 00:53:48 This will probably be a long running bug to unders
+}
+
+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.
+ MainTaskRunner()->PostTask(
danakj 2016/09/30 22:37:13 This is the only user of MainTaskRunner? Just use
Khushal 2016/10/01 00:53:48 Done.
+ FROM_HERE, base::Bind(&LayerTreeHostRemote::DispatchDrawAndSwapCallbacks,
+ weak_factory_.GetWeakPtr()));
+}
+
+base::SingleThreadTaskRunner* LayerTreeHostRemote::MainTaskRunner() {
+ return task_runner_provider_->MainThreadTaskRunner();
+}
+
+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

Powered by Google App Engine
This is Rietveld 408576698