[go: nahoru, domu]

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_