chromium/android_webview/browser/gfx/root_frame_sink.h

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef ANDROID_WEBVIEW_BROWSER_GFX_ROOT_FRAME_SINK_H_
#define ANDROID_WEBVIEW_BROWSER_GFX_ROOT_FRAME_SINK_H_

#include <memory>

#include "base/containers/flat_set.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread_checker.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/common/frame_timing_details_map.h"
#include "components/viz/common/quads/compositor_frame_metadata.h"
#include "components/viz/common/surfaces/local_surface_id.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom.h"

namespace viz {
class CompositorFrameSinkSupport;
class FrameSinkManagerImpl;
class ExternalBeginFrameSource;
}  // namespace viz

namespace android_webview {
class ChildFrame;

class RootFrameSinkClient {
 public:
  virtual ~RootFrameSinkClient() = default;

  virtual void SetNeedsBeginFrames(bool needs_begin_frame) = 0;
  virtual void Invalidate() = 0;
  virtual void ReturnResources(
      viz::FrameSinkId frame_sink_id,
      uint32_t layer_tree_frame_sink_id,
      std::vector<viz::ReturnedResource> resources) = 0;
  virtual void OnCompositorFrameTransitionDirectiveProcessed(
      viz::FrameSinkId frame_sink_id,
      uint32_t layer_tree_frame_sink_id,
      uint32_t sequence_id) = 0;
};

// This class holds per-AwContents classes on the viz thread that do not need
// access to the GPU. It is single-threaded and refcounted on the viz thread.
// This needs to be separate from classes for rendering which requires GPU
// to enable sending begin frames independently from access to GPU.
//
// Lifetime: WebView
class RootFrameSink : public base::RefCounted<RootFrameSink>,
                      public viz::mojom::CompositorFrameSinkClient,
                      public viz::ExternalBeginFrameSourceClient {
 public:
  using SetNeedsBeginFrameCallback = base::RepeatingCallback<void(bool)>;
  RootFrameSink(RootFrameSinkClient* client);

  RootFrameSink(const RootFrameSink&) = delete;
  RootFrameSink& operator=(const RootFrameSink&) = delete;

  const viz::FrameSinkId& root_frame_sink_id() const {
    return root_frame_sink_id_;
  }

  const viz::LocalSurfaceId& SubmitRootCompositorFrame(
      viz::CompositorFrame frame);
  void EvictRootSurface(const viz::LocalSurfaceId& local_surface_id);

  void AddChildFrameSinkId(const viz::FrameSinkId& frame_sink_id);
  void RemoveChildFrameSinkId(const viz::FrameSinkId& frame_sink_id);
  bool BeginFrame(const viz::BeginFrameArgs& args, bool had_input_event);
  void SetBeginFrameSourcePaused(bool paused);
  void SetNeedsDraw(bool needs_draw);
  void OnNewUncommittedFrame(const viz::SurfaceId& surface_id);
  bool IsChildSurface(const viz::FrameSinkId& frame_sink_id);
  void DettachClient();
  void EvictChildSurface(const viz::SurfaceId& surface_id);
  void SetContainedSurfaces(const base::flat_set<viz::SurfaceId>& ids);
  void InvalidateForOverlays();

  void SubmitChildCompositorFrame(ChildFrame* child_frame);
  viz::FrameTimingDetailsMap TakeChildFrameTimingDetailsMap();
  gfx::Size GetChildFrameSize();
  base::flat_set<base::PlatformThreadId> GetChildFrameRendererThreadIds();

  // viz::mojom::CompositorFrameSinkClient implementation.
  void DidReceiveCompositorFrameAck(
      std::vector<viz::ReturnedResource> resources) override;
  void OnBeginFrame(const viz::BeginFrameArgs& args,
                    const viz::FrameTimingDetailsMap& feedbacks,
                    bool frame_ack,
                    std::vector<viz::ReturnedResource> resources) override {}
  void OnBeginFramePausedChanged(bool paused) override {}
  void ReclaimResources(std::vector<viz::ReturnedResource> resources) override;
  void OnCompositorFrameTransitionDirectiveProcessed(
      uint32_t sequence_id) override {}
  void OnSurfaceEvicted(const viz::LocalSurfaceId& local_surface_id) override {}

  // viz::ExternalBeginFrameSourceClient overrides.
  void OnNeedsBeginFrames(bool needs_begin_frames) override;

  void OnCaptureStarted(const viz::FrameSinkId& frame_sink_id);

 private:
  friend class base::RefCounted<RootFrameSink>;
  class ChildCompositorFrameSink;

  ~RootFrameSink() override;
  viz::FrameSinkManagerImpl* GetFrameSinkManager();
  void ReturnResources(viz::FrameSinkId frame_sink_id,
                       uint32_t layer_tree_frame_sink_id,
                       std::vector<viz::ReturnedResource> resources);
  void OnCompositorFrameTransitionDirectiveProcessed(
      viz::FrameSinkId frame_sink_id,
      uint32_t layer_tree_frame_sink_id,
      uint32_t sequence_id);

  bool HasPendingDependency(const viz::SurfaceId& surface_id);
  void UpdateNeedsBeginFrames(bool needs_begin_frame);
  bool ProcessVisibleSurfacesInvalidation();

  const viz::FrameSinkId root_frame_sink_id_;
  base::flat_set<viz::FrameSinkId> child_frame_sink_ids_;
  std::unique_ptr<viz::CompositorFrameSinkSupport> support_;
  viz::ParentLocalSurfaceIdAllocator root_local_surface_id_allocator_;
  gfx::Size root_surface_size_;
  float root_device_scale_factor_ = 0.0f;
  viz::FrameTokenGenerator next_root_frame_token_;

  std::unique_ptr<viz::ExternalBeginFrameSource> begin_frame_source_;

  std::unique_ptr<ChildCompositorFrameSink> child_sink_support_;
  base::flat_set<base::PlatformThreadId> child_frame_renderer_thread_ids_;

  bool clients_need_begin_frames_ = false;
  bool needs_begin_frames_ = false;

  bool needs_draw_ = false;
  raw_ptr<RootFrameSinkClient> client_;
  base::flat_set<viz::SurfaceId> contained_surfaces_;
  std::map<viz::SurfaceId, uint64_t> last_invalidated_frame_index_;

  const bool use_new_invalidate_heuristic_;

  THREAD_CHECKER(thread_checker_);
};

using RootFrameSinkGetter =
    base::RepeatingCallback<scoped_refptr<RootFrameSink>()>;

}  // namespace android_webview

#endif  // ANDROID_WEBVIEW_BROWSER_GFX_ROOT_FRAME_SINK_H_