chromium/gpu/command_buffer/service/shared_image/dxgi_swap_chain_image_backing.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 GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_DXGI_SWAP_CHAIN_IMAGE_BACKING_H_
#define GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_DXGI_SWAP_CHAIN_IMAGE_BACKING_H_

#include <windows.h>

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

#include <utility>

#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/service/shared_image/d3d_image_backing.h"
#include "gpu/command_buffer/service/shared_image/shared_image_backing.h"
#include "gpu/command_buffer/service/shared_image/shared_image_representation.h"
#include "third_party/skia/include/core/SkAlphaType.h"
#include "third_party/skia/include/gpu/GrTypes.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/gpu_fence.h"
#include "ui/gl/buildflags.h"

namespace gpu {

class D3DImageBacking;
class SharedContextState;
class SharedImageManager;
class MemoryTypeTracker;

class GPU_GLES2_EXPORT DXGISwapChainImageBacking
    : public ClearTrackingSharedImageBacking {
 public:
  static std::unique_ptr<DXGISwapChainImageBacking> Create(
      Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device,
      const Mailbox& mailbox,
      viz::SharedImageFormat format,
      DXGI_FORMAT internal_format,
      const gfx::Size& size,
      const gfx::ColorSpace& color_space,
      GrSurfaceOrigin surface_origin,
      SkAlphaType alpha_type,
      gpu::SharedImageUsageSet usage,
      std::string debug_label);

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

  ~DXGISwapChainImageBacking() override;

  // SharedImageBacking implementation.
  SharedImageBackingType GetType() const override;
  void Update(std::unique_ptr<gfx::GpuFence> in_fence) override;

 protected:
  std::unique_ptr<OverlayImageRepresentation> ProduceOverlay(
      SharedImageManager* manager,
      MemoryTypeTracker* tracker) override;

  std::unique_ptr<SkiaGaneshImageRepresentation> ProduceSkiaGanesh(
      SharedImageManager* manager,
      MemoryTypeTracker* tracker,
      scoped_refptr<SharedContextState> context_state) override;

  std::unique_ptr<SkiaGraphiteImageRepresentation> ProduceSkiaGraphite(
      SharedImageManager* manager,
      MemoryTypeTracker* tracker,
      scoped_refptr<SharedContextState> context_state) override;

 private:
  DXGISwapChainImageBacking(
      const Mailbox& mailbox,
      viz::SharedImageFormat format,
      const gfx::Size& size,
      const gfx::ColorSpace& color_space,
      GrSurfaceOrigin surface_origin,
      SkAlphaType alpha_type,
      gpu::SharedImageUsageSet usage,
      std::string debug_label,
      Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device,
      Microsoft::WRL::ComPtr<IDXGISwapChain1> dxgi_swap_chain,
      int buffers_need_alpha_initialization_count);

  friend class DXGISwapChainOverlayImageRepresentation;
  bool Present(bool should_synchronize_present_with_vblank);
  std::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage() {
    return std::make_optional<gl::DCLayerOverlayImage>(size(),
                                                       dxgi_swap_chain_);
  }

  friend class SkiaGLImageRepresentationDXGISwapChain;
  // Called by the Skia representation to indicate where it intends to draw.
  bool DidBeginWriteAccess(const gfx::Rect& swap_rect);

  friend class DawnRepresentationDXGISwapChain;
  wgpu::Texture BeginAccessDawn(const wgpu::Device& device,
                                wgpu::TextureUsage usage,
                                wgpu::TextureUsage internal_usage,
                                const gfx::Rect& update_rect);
  void EndAccessDawn(const wgpu::Device& device, wgpu::Texture texture);

  std::optional<gfx::Rect> pending_swap_rect_;

  Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device_;
  Microsoft::WRL::ComPtr<IDXGISwapChain1> dxgi_swap_chain_;

  // Holds a gles2::TexturePassthrough and corresponding egl image.
  scoped_refptr<D3DImageBacking::GLTextureHolder> gl_texture_holder_;

  // SharedTextureMemory is created from DXGISwapChain's backbuffer texture.
  // This |shared_texture_memory_| wraps the ComPtr<ID3D11Texture> instead of
  // creating from a share HANDLE.
  wgpu::SharedTextureMemory shared_texture_memory_;

  // Count of buffers in |dxgi_swap_chain_| that need to have their alpha
  // channels be cleared to opaque before use. If positive at the start of write
  // access, this count will be decremented and the back buffer cleared.
  // This value should be initialized to 0 or the swap chain's buffer count. It
  // assumes DXGI swap chains cycle through its buffers in order, so after
  // calling present |buffer_count - 1| times, |GetBuffer(0)| will have referred
  // to every buffer once.
  int buffers_need_alpha_initialization_count_ = 0;

  bool first_swap_ = true;
};

}  // namespace gpu

#endif  // GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_DXGI_SWAP_CHAIN_IMAGE_BACKING_H_