cc: Introduce LayerContext
This introduces new LayerContext and LayerContextClient abstractions in
cc as well as their corresponding mojom interfaces in Viz. These types
sit between a client-side LayerTreeHost and a corresponding
LayerTreeHostImpl which may reside in another process. They will be used
to experiment with GPU-side layer trees.
This CL only introduces minimal boilerplate and plumbing for a client to
construct a new client-side VizLayerContext over an established
CompositorFrameSink endpoint, to control a GPU-side LayerTreeHost owned
by that sink within Viz.
Test coverage and actual frame production from a LayerContext are done
in a follow-up CL.
Bug: 1431762
Change-Id: I86e9150aa034fe77300036816c8e2c5ae3999c55
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4418567
Reviewed-by: Alexander Cooper <alcooper@chromium.org>
Auto-Submit: Ken Rockot <rockot@google.com>
Reviewed-by: Jonathan Ross <jonross@chromium.org>
Reviewed-by: Will Harris <wfh@chromium.org>
Code-Coverage: Findit <findit-for-me@appspot.gserviceaccount.com>
Commit-Queue: Alexander Cooper <alcooper@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1130132}
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index 05e11fe..d59e047 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -366,6 +366,8 @@
"trees/latency_info_swap_promise.h",
"trees/latency_info_swap_promise_monitor.cc",
"trees/latency_info_swap_promise_monitor.h",
+ "trees/layer_context.h",
+ "trees/layer_context_client.h",
"trees/layer_tree_frame_sink.cc",
"trees/layer_tree_frame_sink.h",
"trees/layer_tree_frame_sink_client.h",
@@ -381,6 +383,8 @@
"trees/layer_tree_mutator.h",
"trees/layer_tree_settings.cc",
"trees/layer_tree_settings.h",
+ "trees/local_layer_context.cc",
+ "trees/local_layer_context.h",
"trees/managed_memory_policy.cc",
"trees/managed_memory_policy.h",
"trees/mobile_optimized_viewport_util.cc",
diff --git a/cc/mojo_embedder/BUILD.gn b/cc/mojo_embedder/BUILD.gn
index 32c65d2..152c647 100644
--- a/cc/mojo_embedder/BUILD.gn
+++ b/cc/mojo_embedder/BUILD.gn
@@ -9,6 +9,8 @@
sources = [
"async_layer_tree_frame_sink.cc",
"async_layer_tree_frame_sink.h",
+ "viz_layer_context.cc",
+ "viz_layer_context.h",
]
defines = [ "CC_MOJO_EMBEDDER_IMPLEMENTATION" ]
diff --git a/cc/mojo_embedder/viz_layer_context.cc b/cc/mojo_embedder/viz_layer_context.cc
new file mode 100644
index 0000000..8b74d2cab
--- /dev/null
+++ b/cc/mojo_embedder/viz_layer_context.cc
@@ -0,0 +1,49 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/mojo_embedder/viz_layer_context.h"
+
+#include <utility>
+
+#include "base/check.h"
+#include "cc/trees/layer_context_client.h"
+#include "services/viz/public/mojom/compositing/layer_context.mojom.h"
+
+namespace cc::mojo_embedder {
+
+VizLayerContext::VizLayerContext(viz::mojom::CompositorFrameSink& frame_sink,
+ cc::LayerContextClient* client)
+ : client_(client) {
+ CHECK(client_);
+ auto context = viz::mojom::PendingLayerContext::New();
+ context->receiver = service_.BindNewEndpointAndPassReceiver();
+ context->client = client_receiver_.BindNewEndpointAndPassRemote();
+ frame_sink.BindLayerContext(std::move(context));
+}
+
+VizLayerContext::~VizLayerContext() = default;
+
+void VizLayerContext::SetTargetLocalSurfaceId(const viz::LocalSurfaceId& id) {
+ service_->SetTargetLocalSurfaceId(id);
+}
+
+void VizLayerContext::SetVisible(bool visible) {
+ service_->SetVisible(visible);
+}
+
+void VizLayerContext::Commit(const CommitState& state) {
+ // TODO(https://crbug.com/1431762): Push actual commit data. For now we only
+ // update basic parameters required for any LayerTreeHost drawing.
+ auto update = viz::mojom::LayerTreeUpdate::New();
+ update->device_viewport = state.device_viewport_rect;
+ update->device_scale_factor = state.device_scale_factor;
+ update->local_surface_id_from_parent = state.local_surface_id_from_parent;
+ service_->Commit(std::move(update));
+}
+
+void VizLayerContext::OnRequestCommitForFrame(const viz::BeginFrameArgs& args) {
+ client_->OnRequestCommitForFrame(args);
+}
+
+} // namespace cc::mojo_embedder
diff --git a/cc/mojo_embedder/viz_layer_context.h b/cc/mojo_embedder/viz_layer_context.h
new file mode 100644
index 0000000..dd24603
--- /dev/null
+++ b/cc/mojo_embedder/viz_layer_context.h
@@ -0,0 +1,51 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_MOJO_EMBEDDER_VIZ_LAYER_CONTEXT_H_
+#define CC_MOJO_EMBEDDER_VIZ_LAYER_CONTEXT_H_
+
+#include "base/memory/raw_ptr.h"
+#include "cc/mojo_embedder/mojo_embedder_export.h"
+#include "cc/trees/layer_context.h"
+#include "mojo/public/cpp/bindings/associated_receiver.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
+#include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom.h"
+#include "services/viz/public/mojom/compositing/layer_context.mojom.h"
+
+namespace cc {
+class LayerContextClient;
+} // namespace cc
+
+namespace cc::mojo_embedder {
+
+// A client-side implementation of LayerContext which runs over a Mojo
+// connection to a GPU-side LayerContext backend within Viz.
+class CC_MOJO_EMBEDDER_EXPORT VizLayerContext
+ : public LayerContext,
+ public viz::mojom::LayerContextClient {
+ public:
+ // Constructs a VizLayerContext which submits content on behalf of
+ // `frame_sink`. `client` must outlive this object.
+ VizLayerContext(viz::mojom::CompositorFrameSink& frame_sink,
+ cc::LayerContextClient* client);
+ ~VizLayerContext() override;
+
+ // LayerContext:
+ void SetTargetLocalSurfaceId(const viz::LocalSurfaceId& id) override;
+ void SetVisible(bool visible) override;
+ void Commit(const CommitState& state) override;
+
+ // viz::mojom::LayerContextClient:
+ void OnRequestCommitForFrame(const viz::BeginFrameArgs& args) override;
+
+ private:
+ raw_ptr<cc::LayerContextClient> client_;
+ mojo::AssociatedReceiver<viz::mojom::LayerContextClient> client_receiver_{
+ this};
+ mojo::AssociatedRemote<viz::mojom::LayerContext> service_;
+};
+
+} // namespace cc::mojo_embedder
+
+#endif // CC_MOJO_EMBEDDER_VIZ_LAYER_CONTEXT_H_
diff --git a/cc/slim/test_frame_sink_impl.cc b/cc/slim/test_frame_sink_impl.cc
index 84f9e7a7..af27c9d 100644
--- a/cc/slim/test_frame_sink_impl.cc
+++ b/cc/slim/test_frame_sink_impl.cc
@@ -17,6 +17,7 @@
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom.h"
+#include "services/viz/public/mojom/compositing/layer_context.mojom.h"
namespace cc::slim {
@@ -49,6 +50,7 @@
void DidDeleteSharedBitmap(const gpu::Mailbox& id) override {}
void InitializeCompositorFrameSinkType(
viz::mojom::CompositorFrameSinkType type) override {}
+ void BindLayerContext(viz::mojom::PendingLayerContextPtr context) override {}
#if BUILDFLAG(IS_ANDROID)
void SetThreadIds(const std::vector<int32_t>& thread_ids) override {}
#endif
diff --git a/cc/trees/layer_context.h b/cc/trees/layer_context.h
new file mode 100644
index 0000000..95726a1
--- /dev/null
+++ b/cc/trees/layer_context.h
@@ -0,0 +1,35 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_TREES_LAYER_CONTEXT_H_
+#define CC_TREES_LAYER_CONTEXT_H_
+
+#include "cc/cc_export.h"
+#include "cc/trees/commit_state.h"
+#include "components/viz/common/surfaces/local_surface_id.h"
+
+namespace cc {
+
+// LayerContext provides an opaque interface through which a LayerTreeHost can
+// control a backing LayerTreeHostImpl, potentially on another thread or in
+// another process.
+class CC_EXPORT LayerContext {
+ public:
+ virtual ~LayerContext() = default;
+
+ // Indicates that a new LocalSurfaceId has been set for the frame sink hosting
+ // this tree.
+ virtual void SetTargetLocalSurfaceId(const viz::LocalSurfaceId& id) = 0;
+
+ // Globally controls the visibility of layers within the tree.
+ virtual void SetVisible(bool visible) = 0;
+
+ // Flushes pending updates to the backing LayerTreeHostImpl. `state`
+ // represents the pending CommitState for the client-side LayerTreeHost.
+ virtual void Commit(const CommitState& state) = 0;
+};
+
+} // namespace cc
+
+#endif // CC_TREES_LAYER_CONTEXT_H_
diff --git a/cc/trees/layer_context_client.h b/cc/trees/layer_context_client.h
new file mode 100644
index 0000000..2514c245
--- /dev/null
+++ b/cc/trees/layer_context_client.h
@@ -0,0 +1,27 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_TREES_LAYER_CONTEXT_CLIENT_H_
+#define CC_TREES_LAYER_CONTEXT_CLIENT_H_
+
+#include "cc/cc_export.h"
+#include "components/viz/common/frame_sinks/begin_frame_args.h"
+
+namespace cc {
+
+// Interface used by LayerContext to push requests to its corresponding
+// client-side LayerTreeHost.
+class CC_EXPORT LayerContextClient {
+ public:
+ virtual ~LayerContextClient() = default;
+
+ // Indicates that the compositor will produce a new display frame soon and
+ // that the client should commit a new layer tree ASAP. `args` correspond to
+ // the impending display frame that the compositor wants to produce.
+ virtual void OnRequestCommitForFrame(const viz::BeginFrameArgs& args) = 0;
+};
+
+} // namespace cc
+
+#endif // CC_TREES_LAYER_CONTEXT_CLIENT_H_
diff --git a/cc/trees/local_layer_context.cc b/cc/trees/local_layer_context.cc
new file mode 100644
index 0000000..0238c079
--- /dev/null
+++ b/cc/trees/local_layer_context.cc
@@ -0,0 +1,151 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/trees/local_layer_context.h"
+
+#include <memory>
+
+#include "base/task/single_thread_task_runner.h"
+#include "cc/raster/categorized_worker_pool.h"
+#include "cc/trees/commit_state.h"
+#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/layer_tree_settings.h"
+
+namespace cc {
+
+namespace {
+
+LayerListSettings CreateSettings() {
+ LayerListSettings settings;
+ settings.commit_to_active_tree = true;
+ return settings;
+}
+
+LayerTreeHost::InitParams CreateInitParams(LocalLayerContext& context,
+ const LayerListSettings& settings,
+ MutatorHost* mutator_host) {
+ LayerTreeHost::InitParams params;
+ params.client = &context;
+ params.settings = &settings;
+ params.task_graph_runner = CategorizedWorkerPool::GetOrCreate();
+ params.main_task_runner = base::SingleThreadTaskRunner::GetCurrentDefault();
+ params.mutator_host = mutator_host;
+ return params;
+}
+
+} // namespace
+
+LocalLayerContext::LocalLayerContext(MutatorHost* mutator_host)
+ : mutator_host_(mutator_host),
+ layer_list_settings_(CreateSettings()),
+ host_(LayerTreeHost::CreateSingleThreaded(
+ this,
+ CreateInitParams(*this, layer_list_settings_, mutator_host_))) {}
+
+LocalLayerContext::~LocalLayerContext() = default;
+
+void LocalLayerContext::SetTargetLocalSurfaceId(const viz::LocalSurfaceId& id) {
+ host_->SetTargetLocalSurfaceId(id);
+}
+
+void LocalLayerContext::SetVisible(bool visible) {
+ host_->SetVisible(visible);
+}
+
+void LocalLayerContext::Commit(const CommitState& state) {
+ // TODO(https://crbug.com/1431762): Actually update the tree contents.
+ host_->SetViewportRectAndScale(state.device_viewport_rect,
+ state.device_scale_factor,
+ state.local_surface_id_from_parent);
+}
+
+void LocalLayerContext::WillBeginMainFrame() {}
+
+void LocalLayerContext::DidBeginMainFrame() {}
+
+void LocalLayerContext::WillUpdateLayers() {}
+
+void LocalLayerContext::DidUpdateLayers() {}
+
+void LocalLayerContext::BeginMainFrame(const viz::BeginFrameArgs& args) {}
+
+void LocalLayerContext::OnDeferMainFrameUpdatesChanged(bool) {}
+
+void LocalLayerContext::OnDeferCommitsChanged(
+ bool defer_status,
+ PaintHoldingReason reason,
+ absl::optional<PaintHoldingCommitTrigger> trigger) {}
+
+void LocalLayerContext::OnCommitRequested() {}
+
+void LocalLayerContext::BeginMainFrameNotExpectedSoon() {}
+
+void LocalLayerContext::BeginMainFrameNotExpectedUntil(base::TimeTicks time) {}
+
+void LocalLayerContext::UpdateLayerTreeHost() {}
+
+void LocalLayerContext::ApplyViewportChanges(
+ const ApplyViewportChangesArgs& args) {}
+
+void LocalLayerContext::UpdateCompositorScrollState(
+ const CompositorCommitData& commit_data) {}
+
+void LocalLayerContext::RequestNewLayerTreeFrameSink() {}
+
+void LocalLayerContext::DidInitializeLayerTreeFrameSink() {}
+
+void LocalLayerContext::DidFailToInitializeLayerTreeFrameSink() {}
+
+void LocalLayerContext::WillCommit(const CommitState&) {}
+
+void LocalLayerContext::DidCommit(base::TimeTicks commit_start_time,
+ base::TimeTicks commit_finish_time) {}
+
+void LocalLayerContext::DidCommitAndDrawFrame() {}
+
+void LocalLayerContext::DidReceiveCompositorFrameAck() {}
+
+void LocalLayerContext::DidCompletePageScaleAnimation() {}
+
+void LocalLayerContext::DidPresentCompositorFrame(
+ uint32_t frame_token,
+ const gfx::PresentationFeedback& feedback) {}
+
+void LocalLayerContext::RecordStartOfFrameMetrics() {}
+
+void LocalLayerContext::RecordEndOfFrameMetrics(
+ base::TimeTicks frame_begin_time,
+ ActiveFrameSequenceTrackers trackers) {}
+
+std::unique_ptr<BeginMainFrameMetrics>
+LocalLayerContext::GetBeginMainFrameMetrics() {
+ return nullptr;
+}
+
+std::unique_ptr<WebVitalMetrics> LocalLayerContext::GetWebVitalMetrics() {
+ return nullptr;
+}
+
+void LocalLayerContext::NotifyThroughputTrackerResults(
+ CustomTrackerResults results) {}
+
+void LocalLayerContext::DidObserveFirstScrollDelay(
+ base::TimeDelta first_scroll_delay,
+ base::TimeTicks first_scroll_timestamp) {}
+
+void LocalLayerContext::RunPaintBenchmark(int repeat_count,
+ PaintBenchmarkResult& result) {}
+
+void LocalLayerContext::ScheduleAnimationForWebTests() {}
+
+void LocalLayerContext::FrameIntervalUpdated(base::TimeDelta interval) {}
+
+void LocalLayerContext::DidSubmitCompositorFrame() {}
+
+void LocalLayerContext::DidLoseLayerTreeFrameSink() {}
+
+void LocalLayerContext::FrameSinksToThrottleUpdated(
+ const base::flat_set<viz::FrameSinkId>& ids) {}
+
+} // namespace cc
diff --git a/cc/trees/local_layer_context.h b/cc/trees/local_layer_context.h
new file mode 100644
index 0000000..106a711
--- /dev/null
+++ b/cc/trees/local_layer_context.h
@@ -0,0 +1,98 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_TREES_LOCAL_LAYER_CONTEXT_H_
+#define CC_TREES_LOCAL_LAYER_CONTEXT_H_
+
+#include <memory>
+
+#include "base/memory/raw_ptr.h"
+#include "cc/cc_export.h"
+#include "cc/trees/layer_context.h"
+#include "cc/trees/layer_tree_host_client.h"
+#include "cc/trees/layer_tree_host_single_thread_client.h"
+#include "cc/trees/layer_tree_settings.h"
+
+namespace cc {
+
+class LayerTreeHost;
+class MutatorHost;
+
+// LocalLayerContext owns and manages a LayerTreeHostImpl to be controlled
+// indirectly by a client's corresponding LayerTreeHost.
+class CC_EXPORT LocalLayerContext : public LayerContext,
+ public LayerTreeHostClient,
+ public LayerTreeHostSingleThreadClient {
+ public:
+ explicit LocalLayerContext(MutatorHost* mutator_host);
+ ~LocalLayerContext() override;
+
+ // LayerContext:
+ void SetTargetLocalSurfaceId(const viz::LocalSurfaceId& id) override;
+ void SetVisible(bool visible) override;
+ void Commit(const CommitState& state) override;
+
+ // LayerTreeHostClient:
+ void WillBeginMainFrame() override;
+ void DidBeginMainFrame() override;
+ void WillUpdateLayers() override;
+ void DidUpdateLayers() override;
+ void BeginMainFrame(const viz::BeginFrameArgs& args) override;
+ void OnDeferMainFrameUpdatesChanged(bool) override;
+ void OnDeferCommitsChanged(
+ bool defer_status,
+ PaintHoldingReason reason,
+ absl::optional<PaintHoldingCommitTrigger> trigger) override;
+ void OnCommitRequested() override;
+ void BeginMainFrameNotExpectedSoon() override;
+ void BeginMainFrameNotExpectedUntil(base::TimeTicks time) override;
+ void UpdateLayerTreeHost() override;
+ void ApplyViewportChanges(const ApplyViewportChangesArgs& args) override;
+ void UpdateCompositorScrollState(
+ const CompositorCommitData& commit_data) override;
+ void RequestNewLayerTreeFrameSink() override;
+ void DidInitializeLayerTreeFrameSink() override;
+ void DidFailToInitializeLayerTreeFrameSink() override;
+ void WillCommit(const CommitState&) override;
+ void DidCommit(base::TimeTicks commit_start_time,
+ base::TimeTicks commit_finish_time) override;
+ void DidCommitAndDrawFrame() override;
+ void DidReceiveCompositorFrameAck() override;
+ void DidCompletePageScaleAnimation() override;
+ void DidPresentCompositorFrame(
+ uint32_t frame_token,
+ const gfx::PresentationFeedback& feedback) override;
+ void RecordStartOfFrameMetrics() override;
+ void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time,
+ ActiveFrameSequenceTrackers trackers) override;
+ std::unique_ptr<BeginMainFrameMetrics> GetBeginMainFrameMetrics() override;
+ std::unique_ptr<WebVitalMetrics> GetWebVitalMetrics() override;
+ void NotifyThroughputTrackerResults(CustomTrackerResults results) override;
+ void DidObserveFirstScrollDelay(
+ base::TimeDelta first_scroll_delay,
+ base::TimeTicks first_scroll_timestamp) override;
+ void RunPaintBenchmark(int repeat_count,
+ PaintBenchmarkResult& result) override;
+
+ // LayerTreeHostSingleThreadClient:
+ void ScheduleAnimationForWebTests() override;
+ void FrameIntervalUpdated(base::TimeDelta interval) override;
+ void DidSubmitCompositorFrame() override;
+ void DidLoseLayerTreeFrameSink() override;
+ void FrameSinksToThrottleUpdated(
+ const base::flat_set<viz::FrameSinkId>& ids) override;
+
+ private:
+ const raw_ptr<MutatorHost> mutator_host_;
+
+ // The concrete LayerTreeHost which the client is controlling.
+ // TODO(https://crbug.com/1431762): Own and manage a LayerTreeHostImpl
+ // directly instead of proxying through a single-threaded LayerTreeHost.
+ const LayerListSettings layer_list_settings_;
+ std::unique_ptr<LayerTreeHost> host_;
+};
+
+} // namespace cc
+
+#endif // CC_TREES_LOCAL_LAYER_CONTEXT_H_