#ifndef GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_D3D_IMAGE_BACKING_H_
#define GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_D3D_IMAGE_BACKING_H_
#include <windows.h>
#include <d3d11.h>
#include <d3d12.h>
#include <dcomp.h>
#include <dxgi1_2.h>
#include <wrl/client.h>
#include <array>
#include <vector>
#include "base/containers/flat_map.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/synchronization/waitable_event_watcher.h"
#include "base/types/pass_key.h"
#include "components/viz/common/resources/shared_image_format.h"
#include "gpu/command_buffer/service/dxgi_shared_handle_manager.h"
#include "gpu/command_buffer/service/memory_tracking.h"
#include "gpu/command_buffer/service/shared_context_state.h"
#include "gpu/command_buffer/service/shared_image/dawn_shared_texture_cache.h"
#include "gpu/command_buffer/service/shared_image/shared_image_format_service_utils.h"
#include "gpu/command_buffer/service/texture_manager.h"
#include "ui/gfx/gpu_memory_buffer_handle.h"
#include "ui/gfx/win/d3d_shared_fence.h"
#include "ui/gl/buildflags.h"
#include "ui/gl/scoped_egl_image.h"
namespace gfx {
class Size;
class ColorSpace;
}
namespace gpu {
class D3D11ImageSameAdapterCopyStrategy;
class SharedContextState;
struct Mailbox;
class GPU_GLES2_EXPORT D3DImageBacking final
: public ClearTrackingSharedImageBacking {
public:
friend class D3D11ImageSameAdapterCopyStrategy;
static std::unique_ptr<D3DImageBacking> Create(
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<ID3D11Texture2D> d3d11_texture,
scoped_refptr<DXGISharedHandleState> dxgi_shared_handle_state,
const GLFormatCaps& gl_format_caps,
GLenum texture_target,
size_t array_slice,
bool use_update_subresource1 = false,
bool want_dcomp_texture = false,
bool is_thread_safe = false,
bool share_dxgi_handle_with_other_backings = true);
static std::unique_ptr<D3DImageBacking> CreateFromD3D12Resource(
const Mailbox& mailbox,
const gfx::Size& size,
gpu::SharedImageUsageSet usage,
std::string debug_label,
Microsoft::WRL::ComPtr<ID3D12Resource> d3d12_resource);
static std::unique_ptr<D3DImageBacking> CreateFromSwapChainBuffers(
const Mailbox& mailbox,
viz::SharedImageFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
GrSurfaceOrigin surface_origin,
SkAlphaType alpha_type,
gpu::SharedImageUsageSet usage,
Microsoft::WRL::ComPtr<ID3D11Texture2D> back_buffer_texture,
Microsoft::WRL::ComPtr<ID3D11Texture2D> front_buffer_texture,
Microsoft::WRL::ComPtr<IDXGISwapChain1> swap_chain,
const GLFormatCaps& gl_format_caps);
D3DImageBacking(const D3DImageBacking&) = delete;
D3DImageBacking& operator=(const D3DImageBacking&) = delete;
~D3DImageBacking() override;
SharedImageBackingType GetType() const override;
void Update(std::unique_ptr<gfx::GpuFence> in_fence) override;
bool UploadFromMemory(const std::vector<SkPixmap>& pixmaps) override;
bool ReadbackToMemory(const std::vector<SkPixmap>& pixmaps) override;
void ReadbackToMemoryAsync(const std::vector<SkPixmap>& pixmaps,
base::OnceCallback<void(bool)> callback) override;
std::unique_ptr<DawnImageRepresentation> ProduceDawn(
SharedImageManager* manager,
MemoryTypeTracker* tracker,
const wgpu::Device& device,
wgpu::BackendType backend_type,
std::vector<wgpu::TextureFormat> view_formats,
scoped_refptr<SharedContextState> context_state) override;
void UpdateExternalFence(
scoped_refptr<gfx::D3DSharedFence> external_fence) override;
bool BeginAccessD3D11(Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device,
bool write_access,
bool is_overlay_access = false);
void EndAccessD3D11(Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device,
bool is_overlay_access = false);
wgpu::Texture BeginAccessDawn(const wgpu::Device& device,
wgpu::BackendType backend_type,
wgpu::TextureUsage usage,
wgpu::TextureUsage internal_usage,
std::vector<wgpu::TextureFormat> view_formats);
void EndAccessDawn(const wgpu::Device& device, wgpu::Texture texture);
std::vector<scoped_refptr<SkiaImageRepresentation::GraphiteTextureHolder>>
CreateGraphiteTextureHolders(
wgpu::Device device,
wgpu::Texture texture,
std::vector<skgpu::graphite::BackendTexture> backend_textures);
std::unique_ptr<DawnBufferRepresentation> ProduceDawnBuffer(
SharedImageManager* manager,
MemoryTypeTracker* tracker,
const wgpu::Device& device,
wgpu::BackendType backend_type,
scoped_refptr<SharedContextState> context_state) override;
wgpu::Buffer BeginAccessDawnBuffer(const wgpu::Device& device,
wgpu::BackendType backend_type,
wgpu::BufferUsage usage);
void EndAccessDawnBuffer(const wgpu::Device& device, wgpu::Buffer buffer);
std::unique_ptr<WebNNTensorRepresentation> ProduceWebNNTensor(
SharedImageManager* manager,
MemoryTypeTracker* tracker) override;
Microsoft::WRL::ComPtr<ID3D12Resource> GetD3D12Buffer() const;
std::optional<scoped_refptr<gfx::D3DSharedFence>> BeginAccessWebNN();
void EndAccessWebNN(scoped_refptr<gfx::D3DSharedFence> signaled_fence);
std::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage();
bool has_keyed_mutex() const {
return dxgi_shared_handle_state_ &&
dxgi_shared_handle_state_->has_keyed_mutex();
}
bool SupportsDeferredGraphiteSubmit() const;
class GLTextureHolder : public base::RefCounted<GLTextureHolder> {
public:
GLTextureHolder(
base::PassKey<D3DImageBacking>,
scoped_refptr<gles2::TexturePassthrough> texture_passthrough,
gl::ScopedEGLImage egl_image);
const scoped_refptr<gles2::TexturePassthrough>& texture_passthrough()
const {
return texture_passthrough_;
}
void* egl_image() const { return egl_image_.get(); }
void set_needs_rebind(bool needs_rebind) { needs_rebind_ = needs_rebind; }
bool BindEGLImageToTexture();
void MarkContextLost();
base::WeakPtr<GLTextureHolder> GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
private:
friend class base::RefCounted<GLTextureHolder>;
~GLTextureHolder();
const scoped_refptr<gles2::TexturePassthrough> texture_passthrough_;
const gl::ScopedEGLImage egl_image_;
bool needs_rebind_ = false;
base::WeakPtrFactory<GLTextureHolder> weak_ptr_factory_{this};
};
static scoped_refptr<GLTextureHolder> CreateGLTexture(
const GLFormatDesc& gl_format_desc,
Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture,
GLenum texture_target = GL_TEXTURE_2D,
unsigned array_slice = 0u,
unsigned plane_index = 0u);
bool HasStagingTextureForTesting() const;
Microsoft::WRL::ComPtr<IDXGISwapChain1> swap_chain_for_testing() const {
return swap_chain_;
}
Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture_for_testing() const {
AutoLock auto_lock(this);
return d3d11_texture_;
}
scoped_refptr<DXGISharedHandleState> dxgi_shared_handle_state_for_testing()
const {
return dxgi_shared_handle_state_;
}
protected:
std::unique_ptr<GLTexturePassthroughImageRepresentation>
ProduceGLTexturePassthrough(SharedImageManager* manager,
MemoryTypeTracker* tracker) override;
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;
#if BUILDFLAG(SKIA_USE_DAWN)
std::unique_ptr<SkiaGraphiteImageRepresentation> ProduceSkiaGraphite(
SharedImageManager* manager,
MemoryTypeTracker* tracker,
scoped_refptr<SharedContextState> context_state) override;
#endif
std::unique_ptr<VideoImageRepresentation> ProduceVideo(
SharedImageManager* manager,
MemoryTypeTracker* tracker,
VideoDevice device) override;
private:
using D3DSharedFenceSet = base::flat_set<scoped_refptr<gfx::D3DSharedFence>>;
D3DImageBacking(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<ID3D11Texture2D> d3d11_texture,
scoped_refptr<DXGISharedHandleState> dxgi_shared_handle_state,
const GLFormatCaps& gl_format_caps,
GLenum texture_target = GL_TEXTURE_2D,
size_t array_slice = 0u,
bool use_update_subresource1 = false,
bool want_dcomp_texture = false,
bool is_thread_safe = false,
bool share_dxgi_handle_with_other_backings = true);
D3DImageBacking(const Mailbox& mailbox,
const gfx::Size& size,
gpu::SharedImageUsageSet usage,
std::string debug_label,
Microsoft::WRL::ComPtr<ID3D12Resource> d3d12_resource);
bool use_cross_device_fence_synchronization() const {
return dxgi_shared_handle_state_ &&
!dxgi_shared_handle_state_->has_keyed_mutex();
}
void* GetEGLImage() const;
bool PresentSwapChain();
ID3D11Texture2D* GetOrCreateStagingTexture() EXCLUSIVE_LOCKS_REQUIRED(lock_);
bool CopyToStagingTexture() EXCLUSIVE_LOCKS_REQUIRED(lock_);
bool ReadbackFromStagingTexture(const std::vector<SkPixmap>& pixmaps)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
void OnCopyToStagingTextureDone(const std::vector<SkPixmap>& pixmaps,
base::OnceCallback<void(bool)> readback_cb);
bool ValidateBeginAccess(bool write_access) const
EXCLUSIVE_LOCKS_REQUIRED(lock_);
void BeginAccessCommon(bool write_access) EXCLUSIVE_LOCKS_REQUIRED(lock_);
void EndAccessCommon(const D3DSharedFenceSet& fences)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
void BeginDCompTextureAccess();
void EndDCompTextureAccess();
void CheckForDawnDeviceLoss(const wgpu::Device& device,
const wgpu::SharedTextureMemory& texture_memory)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
void InitPersistentGraphiteDawnAccess(
scoped_refptr<SharedContextState> context_state,
const wgpu::Device device,
const wgpu::SharedTextureMemory& shared_texture_memory,
const std::vector<wgpu::TextureFormat>& view_formats)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
wgpu::Texture GetOrCreateDawnTexture(
const wgpu::Device device,
const wgpu::SharedTextureMemory& shared_texture_memory,
wgpu::TextureUsage wgpu_usage,
wgpu::TextureUsage wgpu_internal_usage,
const std::vector<wgpu::TextureFormat>& view_formats)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
void NotifyGraphiteAboutInitializedStatus() EXCLUSIVE_LOCKS_REQUIRED(lock_);
void FlushGraphiteCommandsIfNeeded() EXCLUSIVE_LOCKS_REQUIRED(lock_);
void InvalidatePersistentGraphiteDawnAccess() EXCLUSIVE_LOCKS_REQUIRED(lock_);
std::vector<scoped_refptr<gfx::D3DSharedFence>> GetPendingWaitFences(
const Microsoft::WRL::ComPtr<ID3D11Device>& wait_d3d11_device,
const wgpu::Device& wait_dawn_device,
bool write_access) EXCLUSIVE_LOCKS_REQUIRED(lock_);
wgpu::SharedTextureMemory GetSharedTextureMemory(const wgpu::Device& device)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
int TrackBeginAccessToWGPUTexture(wgpu::Texture texture)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
int TrackEndAccessToWGPUTexture(wgpu::Texture texture)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
const Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture_;
Microsoft::WRL::ComPtr<ID3D11Texture2D> swap_chain_front_buffer_texture_;
const Microsoft::WRL::ComPtr<ID3D12Resource> d3d12_resource_;
const Microsoft::WRL::ComPtr<IDCompositionTexture> dcomp_texture_;
scoped_refptr<gfx::D3DSharedFence> dcomp_texture_available_fence_;
int num_dcomp_texture_readers_ = 0;
const scoped_refptr<DXGISharedHandleState> dxgi_shared_handle_state_;
const GLFormatCaps gl_format_caps_;
std::array<base::WeakPtr<GLTextureHolder>, 3> gl_texture_holders_
GUARDED_BY(lock_);
const GLenum texture_target_;
const size_t array_slice_;
Microsoft::WRL::ComPtr<IDXGISwapChain1> swap_chain_;
const bool use_update_subresource1_;
const bool share_dxgi_handle_with_other_backings_ = true;
Microsoft::WRL::ComPtr<ID3D11Texture2D> staging_texture_ GUARDED_BY(lock_);
Microsoft::WRL::ComPtr<ID3D11Device> texture_d3d11_device_;
Microsoft::WRL::ComPtr<ID3D11Device> angle_d3d11_device_;
D3D11_TEXTURE2D_DESC d3d11_texture_desc_;
bool in_write_access_ GUARDED_BY(lock_) = false;
int num_readers_ GUARDED_BY(lock_) = 0;
D3DSharedFenceSet read_fences_ GUARDED_BY(lock_);
D3DSharedFenceSet write_fences_ GUARDED_BY(lock_);
base::flat_map<Microsoft::WRL::ComPtr<ID3D11Device>,
scoped_refptr<gfx::D3DSharedFence>>
d3d11_signaled_fence_map_ GUARDED_BY(lock_);
scoped_refptr<DawnSharedTextureCache> dawn_shared_texture_cache_
GUARDED_BY(lock_);
wgpu::SharedBufferMemory dawn_shared_buffer_memory_ GUARDED_BY(lock_);
base::flat_map<WGPUTexture, int> wgpu_texture_ongoing_accesses_
GUARDED_BY(lock_);
base::flat_map<WGPUDevice, D3DSharedFenceSet> dawn_signaled_fences_map_
GUARDED_BY(lock_);
std::optional<base::WaitableEventWatcher> pending_copy_event_watcher_
GUARDED_BY(lock_);
class PersistentGraphiteDawnAccess;
scoped_refptr<PersistentGraphiteDawnAccess> persistent_graphite_dawn_access_;
class GraphiteTextureHolder;
base::WeakPtrFactory<D3DImageBacking> weak_ptr_factory_{this};
};
}
#endif