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

Unified Diff: cc/blimp/layer_tree_host_remote.cc

Issue 2362073002: cc/blimp: Add a LayerTreeHostRemote implementation. (Closed)
Patch Set: source frame number 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..94e0d05c6fc4c0882c80e7fa9aece58974bfe673
--- /dev/null
+++ b/cc/blimp/layer_tree_host_remote.cc
@@ -0,0 +1,395 @@
+// 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)
+ : 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),
+ visible_(false),
+ defer_commits_(false),
+ main_frame_requested_from_state_sink_(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)),
+ compositor_proto_state_sink_(
+ std::move(params->compositor_proto_state_sink)),
+ settings_(*params->settings),
+ layer_tree_(std::move(layer_tree)),
+ ui_resource_manager_(base::MakeUnique<UIResourceManager>()),
danakj 2016/09/26 21:36:53 why is it a pointer?
Khushal 2016/09/27 01:07:49 I just did that because LTHInProcess also had a pt
+ weak_factory_(this) {
+ DCHECK(task_runner_provider_->IsMainThread());
+ DCHECK(compositor_proto_state_sink_);
+ DCHECK(client_);
+ compositor_proto_state_sink_->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 really need a UIResourceManager. The layers which need this
+ // are never used.
+ LOG(ERROR) << "UIResourceManager requested.";
danakj 2016/09/26 21:36:52 How about notreached and return null then?
Khushal 2016/09/27 01:07:48 This is used by Painted scrollbars only, which bli
danakj 2016/09/27 20:32:43 My response would be "let's find out then" but I i
Khushal 2016/09/27 23:46:56 Okay, so we have turned turn off the use of Painte
+ 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
danakj 2016/09/26 21:36:52 Can we NOTREACHED?
Khushal 2016/09/27 01:07:49 The renderer will always call this still, even if
+ // relevant on the client only.
+}
+
+void LayerTreeHostRemote::SetLayerTreeMutator(
+ std::unique_ptr<LayerTreeMutator> mutator) {
+ // Compositor-worker not supported.
danakj 2016/09/26 21:36:52 Can we NOTREACHED?
Khushal 2016/09/27 01:07:49 I think this is all setup code which will still ru
danakj 2016/09/27 20:32:43 Perhaps we should be turning the setup code off if
Khushal 2016/09/27 23:46:56 Sure, we can do it in blink also. For all the feat
+}
+
+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.
danakj 2016/09/26 21:36:52 Can you point at a bug?
Khushal 2016/09/27 01:07:49 Done.
+}
+
+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.
danakj 2016/09/26 21:36:52 What do you mean by it should always be true? Call
Khushal 2016/09/27 01:07:49 I was just adding this comment to point out why we
+ 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";
danakj 2016/09/26 21:36:53 "We" is a bit ambiguous here. "The LayerTreeHostCl
Khushal 2016/09/27 01:07:49 Done.
+}
+
+std::unique_ptr<CompositorFrameSink>
+LayerTreeHostRemote::ReleaseCompositorFrameSink() {
+ // Since we never have a CompositorFrameSink, this is always a no-op.
danakj 2016/09/26 21:36:52 Can we NOTREACHED? ps anything that is NOTREACHED
Khushal 2016/09/27 01:07:49 Well, the API says can be called safely anytime, s
danakj 2016/09/27 20:32:43 I thought this is only used by browser compositors
Khushal 2016/09/27 23:46:56 Its not there right now but I don't think its wron
+ 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";
danakj 2016/09/26 21:36:52 ".. and this class does not support single-thread
Khushal 2016/09/27 01:07:49 Done.
+}
+
+void LayerTreeHostRemote::Composite(base::TimeTicks frame_begin_time) {
+ NOTREACHED() << "Only supported in single-threaded mode";
danakj 2016/09/26 21:36:52 ditto
Khushal 2016/09/27 01:07:49 Done.
+}
+
+void LayerTreeHostRemote::SetNeedsRedraw() {
+ // The engine shouldn't need to care about draws. CompositorFrames are never
danakj 2016/09/26 21:36:53 I don't know about this. This causes the composito
Khushal 2016/09/27 01:07:49 Its redundant in the blimp case. The RenderWidget
danakj 2016/09/27 20:32:43 Ok actually it looks like browser compositors (ui:
Khushal 2016/09/27 23:46:56 I would be happier to keep consistency with the th
danakj 2016/09/28 00:32:50 Leaving it empty feels like a landmine to me, I'd
Khushal 2016/09/28 19:47:16 Done. I'll remove it from the threaded one as well
+ // used here.
+}
+
+void LayerTreeHostRemote::SetNeedsRedrawRect(const gfx::Rect& damage_rect) {
+ // The engine shouldn't need to care about draws. CompositorFrames are never
danakj 2016/09/26 21:36:52 Same.
danakj 2016/09/27 20:32:43 However RenderWidget calls this when it wants a re
Khushal 2016/09/27 23:46:56 Ah, good point. Thanks for pointing that case out.
danakj 2016/09/28 00:32:50 It sounds sketchy in that it's likely to interfere
Khushal 2016/09/28 19:47:16 In this case rather than the client, its elements
+ // used here.
+}
+
+void LayerTreeHostRemote::SetNextCommitForcesRedraw() {
+ // The engine shouldn't need to care about draws. CompositorFrames are never
danakj 2016/09/26 21:36:53 This is for testing, to ensure that it completes a
Khushal 2016/09/27 01:07:48 Still no need to send anything to the client thoug
danakj 2016/09/27 20:32:43 I guess it depends if you're running a pixel test.
Khushal 2016/09/27 23:46:56 For pixel tests my plan was to have an implementat
danakj 2016/09/28 00:32:50 I'm thinking more like gpu pixel tests: https://ww
Khushal 2016/09/28 19:47:16 Ah, okay. Can you point me to where this is done?
danakj 2016/09/29 23:59:35 Yes it's the screenshots thing. It's also interest
Khushal 2016/09/30 02:11:18 There is a super-basic complete end-to-end integra
+ // used here.
+}
+
+void LayerTreeHostRemote::NotifyInputThrottledUntilCommit() {
+ // We don't throttle commits right now so this is not relevant.
danakj 2016/09/26 21:36:52 NOTREACHED?
Khushal 2016/09/27 01:07:50 NOTIMPLEMENTED is better I think. The engine will
danakj 2016/09/27 20:32:43 OK I'm not actually sure how this will interact wi
Khushal 2016/09/27 23:46:56 So this was when I had looked at the code a while
danakj 2016/09/28 00:32:50 OK Cool that all sounds good, can you put this in
Khushal 2016/09/28 19:47:16 Done. Didn't add where on the client because that'
+}
+
+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_;
danakj 2016/09/26 21:36:53 This is kinda awk, maybe follow up to make this re
Khushal 2016/09/27 01:07:49 Sounds good. I'll clean up in the next patch.
+}
+
+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;
danakj 2016/09/26 21:36:53 How does this get to the client? Should it not Set
Khushal 2016/09/27 01:07:49 If there is a need to see debug info, then that ca
danakj 2016/09/27 20:32:43 Ok, why store it at all then? How does inspector
Khushal 2016/09/27 23:46:56 Because things take a const&. I looked through the
danakj 2016/09/28 00:32:50 I can see why you made a member then, but why repl
Khushal 2016/09/28 19:47:16 Good point. I made it a NOTREACHED for now. Will c
+}
+
+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();
danakj 2016/09/26 21:36:53 Or NOTREACHED?
Khushal 2016/09/27 01:07:49 I don't think we want to say that calling this met
danakj 2016/09/27 20:32:43 My thot is that if it doesn't work to use NOTREACH
Khushal 2016/09/27 23:46:56 Okay, you're right. This one's used by Gpu benchma
+ return 0;
+}
+
+bool LayerTreeHostRemote::SendMessageToMicroBenchmark(
+ int id,
+ std::unique_ptr<base::Value> value) {
+ NOTIMPLEMENTED();
danakj 2016/09/26 21:36:53 Or NOTREACHED?
Khushal 2016/09/27 01:07:49 Same.
+ return false;
+}
+
+SurfaceSequenceGenerator* LayerTreeHostRemote::GetSurfaceSequenceGenerator() {
+ return &surface_sequence_generator_;
danakj 2016/09/26 21:36:53 This is for surfacelayer also like below. So why s
Khushal 2016/09/27 01:07:49 Yeah, it won't work. I still wasn't sure if I shou
danakj 2016/09/27 20:32:43 We shouldn't crash, the code that calls this shoul
Khushal 2016/09/27 23:46:56 Fair point. Added a TODO to turn this off in blink
+}
+
+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() {}
danakj 2016/09/26 21:36:52 TODO? Is there a bug to link to?
Khushal 2016/09/27 01:07:49 Done.
+
+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,
danakj 2016/09/26 21:36:53 I don't think you mean CompositorFrameSink
Khushal 2016/09/27 01:07:49 Done. So I was hoping that this name wouldn't cau
+ // 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_);
danakj 2016/09/26 21:36:52 can you write these in the same order you'd write
Khushal 2016/09/27 01:07:48 Done. I was actually looking for comments above th
+ 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.
danakj 2016/09/26 21:36:53 Do you really want all layers? Is this something t
Khushal 2016/09/27 01:07:50 I'm glad you asked. So in the regular case we do h
danakj 2016/09/27 20:32:43 I think not optimizing this will make the initial
Khushal 2016/09/27 23:46:56 Thanks. Added a TODO.
+ 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_ =
danakj 2016/09/26 21:36:52 This is a weird way to write if (layers_updated)
Khushal 2016/09/27 01:07:49 Done.
+ 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);
+
+ // For the client, the commit was successful.
+ MainFrameComplete();
+ 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));
+
+ MainFrameComplete();
+
+ // We can not wait for updates dispatched from the client about the state of
danakj 2016/09/26 21:36:53 Why can't you wait?
Khushal 2016/09/27 01:07:49 Because it used to end up throttling updates from
danakj 2016/09/27 20:32:43 OK Can you TODO pointing at a bug with this inform
Khushal 2016/09/27 23:46:56 Done.
+ // 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.
+ GetMainTaskRunner()->PostTask(
+ FROM_HERE, base::Bind(&LayerTreeHostRemote::DispatchDrawAndSwapCallbacks,
+ weak_factory_.GetWeakPtr()));
+}
+
+base::SingleThreadTaskRunner* LayerTreeHostRemote::GetMainTaskRunner() {
+ 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