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

Unified Diff: cc/blimp/layer_tree_host_remote.cc

Issue 2362073002: cc/blimp: Add a LayerTreeHostRemote implementation. (Closed)
Patch Set: 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..7d6fa55ab541aa4f5809d4b546e530f25ddba911
--- /dev/null
+++ b/cc/blimp/layer_tree_host_remote.cc
@@ -0,0 +1,374 @@
+// 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/compositor_proto_state_sink.h"
+#include "cc/output/begin_frame_args.h"
+#include "cc/output/compositor_frame_sink.h"
+#include "cc/resources/ui_resource_manager.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)
+ : id_(LayerTreeHost::GenerateHostId()),
+ source_frame_number_(0),
+ visible_(false),
+ defer_commits_(false),
+ client_(params->client),
+ task_runner_provider_(
+ TaskRunnerProvider::Create(std::move(params->main_task_runner),
+ nullptr)),
+ compositor_proto_state_sink_(
+ std::move(params->compositor_proto_state_sink)),
+ settings_(*params->settings),
+ layer_tree_(base::MakeUnique<LayerTree>(std::move(params->animation_host),
+ nullptr)),
+ ui_resource_manager_(base::MakeUnique<UIResourceManager>()),
+ weak_factory_(this) {
+ DCHECK(task_runner_provider_->IsMainThread());
+ DCHECK(compositor_proto_state_sink_);
+ DCHECK(client_);
+}
+
+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 really need a UIResourceManager. The layers which need this
+ // are never used.
+ LOG(ERROR) << "UIResourceManager requested.";
+ return ui_resource_manager_.get();
+}
+
+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) {
+ // Compositor-worker not supported.
+}
+
+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.
+}
+
+void LayerTreeHostRemote::SetVisible(bool visible) {
+ // The visibility is controlled on the client. The value here should always be
+ // true and changes only during page transitions.
+ visible_ = visible;
+}
+
+bool LayerTreeHostRemote::IsVisible() const {
+ return visible_;
+}
+
+void LayerTreeHostRemote::SetCompositorFrameSink(
+ std::unique_ptr<CompositorFrameSink> compositor_frame_sink) {
+ NOTREACHED() << "We never ask the client 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";
+}
+
+void LayerTreeHostRemote::Composite(base::TimeTicks frame_begin_time) {
+ NOTREACHED() << "Only supported in single-threaded mode";
+}
+
+void LayerTreeHostRemote::SetNeedsRedraw() {
+ // The engine shouldn't need to care about draws. CompositorFrames are never
+ // used here.
+}
+
+void LayerTreeHostRemote::SetNeedsRedrawRect(const gfx::Rect& damage_rect) {
+ // The engine shouldn't need to care about draws. CompositorFrames are never
+ // used here.
+}
+
+void LayerTreeHostRemote::SetNextCommitForcesRedraw() {
+ // The engine shouldn't need to care about draws. CompositorFrames are never
+ // used here.
+}
+
+void LayerTreeHostRemote::NotifyInputThrottledUntilCommit() {
+ // We don't throttle commits right now so this is not relevant.
+}
+
+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";
+}
+
+void LayerTreeHostRemote::SetDebugState(
+ const LayerTreeDebugState& debug_state) {
+ debug_state_ = debug_state;
+}
+
+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) {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+bool LayerTreeHostRemote::SendMessageToMicroBenchmark(
+ int id,
+ std::unique_ptr<base::Value> value) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+SurfaceSequenceGenerator* LayerTreeHostRemote::GetSurfaceSequenceGenerator() {
+ 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() {}
+
+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 CompositorFrameSink,
+ // we don't need to scheduler another one.
+ if (main_frame_requested_from_state_sink_)
+ return;
+
+ compositor_proto_state_sink_->ScheduleMainFrame();
+ main_frame_requested_from_state_sink_ = true;
+}
+
+void LayerTreeHostRemote::BeginMainFrame() {
+ DCHECK(main_frame_requested_from_state_sink_);
+
+ main_frame_requested_from_state_sink_ = 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(FramePipelineStage::NONE, current_pipeline_stage_);
+ DCHECK_EQ(FramePipelineStage::NONE, max_pipeline_stage_for_current_frame_);
+ DCHECK_NE(FramePipelineStage::NONE, requested_pipeline_stage_for_next_frame_);
+
+ // 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.
+ 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.
+ max_pipeline_stage_for_current_frame_ =
+ layers_updated ? FramePipelineStage::COMMIT
+ : max_pipeline_stage_for_current_frame_;
+ }
+
+ 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);
+
+ current_pipeline_stage_ = FramePipelineStage::NONE;
+ max_pipeline_stage_for_current_frame_ = FramePipelineStage::NONE;
+
+ // For the client, the commit was successful.
+ client_->DidCommit();
+ client_->DidBeginMainFrame();
+ return;
+ }
+
+ // TODO(khushalsagar): Serialize current state/reset dirty state tracking and
+ // return the result to the state sink instead.
+ std::unique_ptr<CompositorProtoState> compositor_state =
+ base::MakeUnique<CompositorProtoState>();
+ compositor_proto_state_sink_->ProcessCompositorStateUpdate(
+ std::move(compositor_state));
+
+ client_->DidCommit();
+ client_->DidBeginMainFrame();
+
+ // 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 state sink.
+ // 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::DispatchDrawAndSwapCallbacks() {
+ client_->DidCommitAndDrawFrame();
+ client_->DidCompleteSwapBuffers();
+}
+
+} // namespace cc
« cc/BUILD.gn ('K') | « cc/blimp/layer_tree_host_remote.h ('k') | cc/trees/layer_tree_host.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698