chromium/components/viz/common/overlay_state/win/overlay_state_service.h

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

#ifndef COMPONENTS_VIZ_COMMON_OVERLAY_STATE_WIN_OVERLAY_STATE_SERVICE_H_
#define COMPONENTS_VIZ_COMMON_OVERLAY_STATE_WIN_OVERLAY_STATE_SERVICE_H_

#include <memory>

#include "base/no_destructor.h"
#include "base/task/sequenced_task_runner.h"
#include "components/viz/common/overlay_state/win/overlay_state_aggregator.h"
#include "components/viz/common/viz_common_export.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/ipc/common/gpu_channel.mojom.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/remote_set.h"

namespace viz {

using OverlayStateObserver = gpu::mojom::OverlayStateObserver;

// The OverlayStateService allows a MediaFoundationRendererClient, running in
// a Renderer process, to understand whether the quads associated with its
// video presentation textures are being promoted to a Direct Composition layer
// by Viz. This allows the MediaFoundationRendererClient to determine the
// appropriate presentation mode to use as the Windowless Swapchain mode
// requires Direct Composition support to work.
//
// The mailbox associated with a texture is used as the common identifier
// between the overlay processor in Viz & the MediaFoundationRendererClient.
// Further the quad associated with the mailbox has it's associated
// TransferResource tagged with 'wants_promotion_hint' to ensure that the
// overlay processor only sends the OverlayStateService hints for mailboxes of
// interest.
//
// The OverlayStateService aggregates hints to help ensure minimal IPC overhead
// in keeping the MediaFoundationRendererClient informed of the current
// promotion state.
class VIZ_COMMON_EXPORT OverlayStateService {
 public:
  static OverlayStateService* GetInstance();
  void Initialize(scoped_refptr<base::SequencedTaskRunner> task_runner);
  bool IsInitialized();

  void RegisterObserver(mojo::PendingRemote<gpu::mojom::OverlayStateObserver>
                            promotion_hint_observer,
                        const gpu::Mailbox& mailbox);
  void SetPromotionHint(const gpu::Mailbox& mailbox, bool promoted);
  void MailboxDestroyed(const gpu::Mailbox& mailbox);

 private:
  friend class base::NoDestructor<OverlayStateService>;
  OverlayStateService();
  ~OverlayStateService();
  OverlayStateService(const OverlayStateService&) = delete;
  OverlayStateService& operator=(const OverlayStateService&) = delete;

  void OnBoundObserverDisconnect(const gpu::Mailbox& mailbox,
                                 mojo::RemoteSetElementId);
  void OnStateChanged(const gpu::Mailbox& mailbox,
                      OverlayStateAggregator::PromotionState promoted);
  void OnStateChangedOnTaskRunnerSequence(
      const gpu::Mailbox& mailbox,
      OverlayStateAggregator::PromotionState promoted);
  void SetPromotionHintOnTaskRunnerSequence(const gpu::Mailbox& mailbox,
                                            bool promoted);
  void MailboxDestroyedOnTaskRunnerSequence(const gpu::Mailbox& mailbox);

  struct MailboxState {
    MailboxState();
    ~MailboxState();
    OverlayStateAggregator aggregator_;
    mojo::RemoteSet<OverlayStateObserver> observer_set_;
  };

  bool initialized_ = false;
  base::flat_map<gpu::Mailbox, std::unique_ptr<MailboxState>> mailboxes_;
  scoped_refptr<base::SequencedTaskRunner> task_runner_;
};

}  // namespace viz

#endif  // COMPONENTS_VIZ_COMMON_OVERLAY_STATE_WIN_OVERLAY_STATE_SERVICE_H_