chromium/android_webview/browser/gfx/begin_frame_source_webview.h

// Copyright 2020 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_BEGIN_FRAME_SOURCE_WEBVIEW_H_
#define ANDROID_WEBVIEW_BROWSER_GFX_BEGIN_FRAME_SOURCE_WEBVIEW_H_

#include <memory>

#include "base/android/scoped_java_ref.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/no_destructor.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/service/frame_sinks/external_begin_frame_source_android.h"

namespace android_webview {

// The BeginFrameSourceWebView implements ExternalBeginFrameSource by observing
// another begin_frame_source and provides AfterBeginFrame callback that called
// after BeginFrame is sent out to all observers. It supports hierarchy
// BeginFrameSourceWebView to provide AddBeginFrameCompletionCallback which will
// be forwarded to root begin frame source to ensure that callbacks called after
// all BeginFrames are sent.
//
// Lifetime: WebView
class BeginFrameSourceWebView : public viz::ExternalBeginFrameSource {
 public:
  BeginFrameSourceWebView();
  ~BeginFrameSourceWebView() override;

  // Sets parent of this BeginFrameSource
  void SetParentSource(BeginFrameSourceWebView* parent);
  bool inside_begin_frame() { return inside_begin_frame_; }

  // Schedules BeginFrame completion callback on root begin frame source.
  virtual void AddBeginFrameCompletionCallback(base::OnceClosure callback);

  // Returns last dispatched begin frame args.
  const viz::BeginFrameArgs& LastDispatchedBeginFrameArgs();

 protected:
  void ObserveBeginFrameSource(viz::BeginFrameSource* begin_frame_source);

  virtual void AfterBeginFrame() {}

 private:
  class BeginFrameObserver;
  class BeginFrameSourceClient : public viz::ExternalBeginFrameSourceClient {
   public:
    BeginFrameSourceClient(BeginFrameSourceWebView* owner);
    ~BeginFrameSourceClient();

    // ExternalBeginFrameSourceClient implementation.
    void OnNeedsBeginFrames(bool needs_begin_frames) override;

   private:
    const raw_ptr<BeginFrameSourceWebView> owner_;
  };

  void SendBeginFrame(const viz::BeginFrameArgs& args);
  void OnNeedsBeginFrames(bool needs_begin_frames);

  BeginFrameSourceClient bfs_client_;
  raw_ptr<viz::BeginFrameSource> observed_begin_frame_source_ = nullptr;
  raw_ptr<BeginFrameSourceWebView> parent_ = nullptr;
  std::unique_ptr<BeginFrameObserver> parent_observer_;
  bool inside_begin_frame_ = false;
};

// RootBeginFrameSourceWebView is subclass of BeginFrameSourceWebView that
// observes ExternalBeginFrameSourceAndroid to provide actual BeginFrames from
// Android Choreographer and implements the logic of
// AddBeginFrameCompletionCallback.
//
// Lifetime: Singleton
//
// There is only one RootBeginFrameSourceWebView, even if there are multiple
// displays with different VSync timings attached. Choreographer only uses the
// built-in display for frame timing.
class RootBeginFrameSourceWebView : public BeginFrameSourceWebView {
 public:
  static RootBeginFrameSourceWebView* GetInstance();

  void OnUpdateRefreshRate(JNIEnv* env,
                           const base::android::JavaParamRef<jobject>& obj,
                           float refresh_rate);

  // As this is implementation of root BeginFrameSourceWebView this is actual
  // implementation of scheduling callbacks.
  void AddBeginFrameCompletionCallback(base::OnceClosure callback) override;

 private:
  friend class base::NoDestructor<RootBeginFrameSourceWebView>;
  friend class BeginFrameSourceWebViewTest;

  RootBeginFrameSourceWebView();
  ~RootBeginFrameSourceWebView() override;

  void AfterBeginFrame() override;

  viz::ExternalBeginFrameSourceAndroid begin_frame_source_;
  std::vector<base::ScopedClosureRunner> after_begin_frame_callbacks_;
  base::android::ScopedJavaGlobalRef<jobject> j_object_;
};

}  // namespace android_webview

#endif  // ANDROID_WEBVIEW_BROWSER_GFX_BEGIN_FRAME_SOURCE_WEBVIEW_H_