chromium/ui/gl/direct_composition_support.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 UI_GL_DIRECT_COMPOSITION_SUPPORT_H_
#define UI_GL_DIRECT_COMPOSITION_SUPPORT_H_

#include <windows.h>

#include <d3d11.h>
#include <dcomp.h>
#include <wrl/client.h>

#include "base/no_destructor.h"
#include "base/observer_list_threadsafe.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/mojom/dxgi_info.mojom.h"
#include "ui/gl/gl_export.h"
#include "ui/gl/gpu_switching_observer.h"

namespace gl {

// Initialize direct composition with the given d3d11 device.
GL_EXPORT void InitializeDirectComposition(
    Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device);

GL_EXPORT void ShutdownDirectComposition();

// Retrieves the global direct composition device. InitializeDirectComposition
// must be called on GPU process startup before the device is retrieved, and
// ShutdownDirectComposition must be called at process shutdown.
GL_EXPORT IDCompositionDevice3* GetDirectCompositionDevice();

// Retrieves the global d3d11 device used by direct composition.
// InitializeDirectComposition must be called on GPU process startup before the
// device is retrieved, and ShutdownDirectComposition must be called at process
// shutdown.
GL_EXPORT ID3D11Device* GetDirectCompositionD3D11Device();

// Returns true if direct composition is supported.  We prefer to use direct
// composition even without hardware overlays, because it allows us to bypass
// blitting by DWM to the window redirection surface by using a flip mode swap
// chain.  Overridden with --disable_direct_composition=1.
GL_EXPORT bool DirectCompositionSupported();

// Returns true if video overlays are supported and should be used. Overridden
// with --enable-direct-composition-video-overlays and
// --disable_direct_composition_video_overlays=1. This function is thread safe.
GL_EXPORT bool DirectCompositionOverlaysSupported();

// Returns true if hardware overlays are supported. This function is thread
// safe.
GL_EXPORT bool DirectCompositionHardwareOverlaysSupported();

// After this is called, overlay support is disabled during the current GPU
// process' lifetime.
GL_EXPORT void DisableDirectCompositionOverlays();

// Returns true if zero copy decode swap chain is supported.
GL_EXPORT bool DirectCompositionDecodeSwapChainSupported();

// Returns true if scaled hardware overlays are supported.
GL_EXPORT bool DirectCompositionScaledOverlaysSupported();

// Returns preferred overlay format set when detecting overlay support.
GL_EXPORT DXGI_FORMAT GetDirectCompositionSDROverlayFormat();

// Returns true if video processor auto HDR feature is supported.
GL_EXPORT bool VideoProcessorAutoHDRSupported();

// Returns true if video processor support handling the given format.
GL_EXPORT bool CheckVideoProcessorFormatSupport(DXGI_FORMAT format);

// Returns overlay support flags for the given format.
// Caller should check for DXGI_OVERLAY_SUPPORT_FLAG_DIRECT and
// DXGI_OVERLAY_SUPPORT_FLAG_SCALING bits.
// This function is thread safe.
GL_EXPORT UINT GetDirectCompositionOverlaySupportFlags(DXGI_FORMAT format);

// Returns true if swap chain tearing flag is supported.
GL_EXPORT bool DXGISwapChainTearingSupported();

// Returns true if tearing should be used for dcomp root and video swap chains.
GL_EXPORT bool DirectCompositionSwapChainTearingEnabled();

// Returns true if waitable swap chain should be used to reduce display latency.
GL_EXPORT bool DXGIWaitableSwapChainEnabled();

// Returns the value passed to SetMaximumFrameLatency for waitable swap chains.
GL_EXPORT UINT GetDXGIWaitableSwapChainMaxQueuedFrames();

// Returns true if there is an HDR capable display connected.
GL_EXPORT bool DirectCompositionSystemHDREnabled();

// Returns true if the window is displayed on an HDR capable display.
GL_EXPORT bool DirectCompositionMonitorHDREnabled(HWND window);

// Returns the collected DXGI information.
GL_EXPORT gfx::mojom::DXGIInfoPtr GetDirectCompositionHDRMonitorDXGIInfo();

// Returns true if there is support for |IDCompositionTexture|.
GL_EXPORT bool DirectCompositionTextureSupported();

// Set direct composition swap chain failure so that direct composition is
// marked as unsupported from now on.
GL_EXPORT void SetDirectCompositionSwapChainFailed();

struct DirectCompositionOverlayWorkarounds {
  // Whether software video overlays i.e. swap chains used without hardware
  // overlay/MPO support are used or not.
  bool disable_sw_video_overlays = false;

  // Whether decode swap chains i.e. zero copy swap chains created from video
  // decoder textures are used or not.
  bool disable_decode_swap_chain = false;

  // On Intel GPUs where YUV overlays are supported, BGRA8 overlays are
  // supported as well but IDXGIOutput3::CheckOverlaySupport() returns
  // unsupported. So allow manually enabling BGRA8 overlay support.
  bool enable_bgra8_overlays_with_yuv_overlay_support = false;

  // Forces to enable NV12 overlay support regardless of the query results from
  // IDXGIOutput3::CheckOverlaySupport().
  bool force_nv12_overlay_support = false;

  // Forces to enable RGBA101010A2 overlay support regardless of the query
  // results from IDXGIOutput3::CheckOverlaySupport().
  bool force_rgb10a2_overlay_support = false;

  // Enable NV12 overlay support only when
  // DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709 is supported.
  bool check_ycbcr_studio_g22_left_p709_for_nv12_support = false;
};
GL_EXPORT void SetDirectCompositionOverlayWorkarounds(
    const DirectCompositionOverlayWorkarounds& workarounds);

// Returns monitor size.
GL_EXPORT gfx::Size GetDirectCompositionPrimaryMonitorSize();

// Get the current number of all visible display monitors on the desktop.
GL_EXPORT int GetDirectCompositionNumMonitors();

// Testing helpers.
GL_EXPORT void SetDirectCompositionScaledOverlaysSupportedForTesting(
    bool value);
GL_EXPORT void SetDirectCompositionOverlayFormatUsedForTesting(
    DXGI_FORMAT format);
GL_EXPORT void SetDirectCompositionMonitorInfoForTesting(
    int num_monitors,
    const gfx::Size& primary_monitor_size);

class GL_EXPORT DirectCompositionOverlayCapsObserver
    : public base::CheckedObserver {
 public:
  virtual void OnOverlayCapsChanged() = 0;

 protected:
  DirectCompositionOverlayCapsObserver() = default;
  ~DirectCompositionOverlayCapsObserver() override = default;
};

// Upon receiving display notifications from ui::GpuSwitchingManager,
// DirectCompositionOverlayCapsMonitor updates its overlay caps with the new
// display setting and notifies DirectCompositionOverlayCapsObserver for the
// overlay cap change.
class GL_EXPORT DirectCompositionOverlayCapsMonitor
    : public ui::GpuSwitchingObserver {
 public:
  DirectCompositionOverlayCapsMonitor(
      const DirectCompositionOverlayCapsMonitor&) = delete;
  DirectCompositionOverlayCapsMonitor& operator=(
      const DirectCompositionOverlayCapsMonitor&) = delete;

  static DirectCompositionOverlayCapsMonitor* GetInstance();

  // DirectCompositionOverlayCapsMonitor is running on GpuMain thread.
  // AddObserver()/RemoveObserver() are thread safe.
  void AddObserver(DirectCompositionOverlayCapsObserver* observer);
  void RemoveObserver(DirectCompositionOverlayCapsObserver* observer);

  // Called when the overlay caps have changed.
  void NotifyOverlayCapsChanged();

  // Implements GpuSwitchingObserver.
  void OnGpuSwitched(gl::GpuPreference active_gpu_heuristic) override;
  void OnDisplayAdded() override;
  void OnDisplayRemoved() override;
  void OnDisplayMetricsChanged() override;

 private:
  friend class base::NoDestructor<DirectCompositionOverlayCapsMonitor>;

  DirectCompositionOverlayCapsMonitor();
  ~DirectCompositionOverlayCapsMonitor() override;

  scoped_refptr<
      base::ObserverListThreadSafe<DirectCompositionOverlayCapsObserver>>
      observer_list_;
};
}  // namespace gl

#endif  // UI_GL_DIRECT_COMPOSITION_SUPPORT_H_