1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "ExternalTextureD3D11.h"
10 #include "mozilla/gfx/DeviceManagerDx.h"
11 #include "mozilla/gfx/Logging.h"
12 #include "mozilla/layers/ImageDataSerializer.h"
14 namespace mozilla::webgpu
{
17 UniquePtr
<ExternalTextureD3D11
> ExternalTextureD3D11::Create(
18 const uint32_t aWidth
, const uint32_t aHeight
,
19 const struct ffi::WGPUTextureFormat aFormat
,
20 const ffi::WGPUTextureUsages aUsage
) {
21 const RefPtr
<ID3D11Device
> d3d11Device
=
22 gfx::DeviceManagerDx::Get()->GetCompositorDevice();
24 gfxCriticalNoteOnce
<< "CompositorDevice does not exist";
28 if (aFormat
.tag
!= ffi::WGPUTextureFormat_Bgra8Unorm
) {
29 gfxCriticalNoteOnce
<< "Non supported format: " << aFormat
.tag
;
33 CD3D11_TEXTURE2D_DESC
desc(
34 DXGI_FORMAT_B8G8R8A8_UNORM
, aWidth
, aHeight
, 1, 1,
35 D3D11_BIND_SHADER_RESOURCE
| D3D11_BIND_RENDER_TARGET
);
37 if (aUsage
& WGPUTextureUsages_STORAGE_BINDING
) {
38 desc
.BindFlags
|= D3D11_BIND_UNORDERED_ACCESS
;
42 D3D11_RESOURCE_MISC_SHARED_NTHANDLE
| D3D11_RESOURCE_MISC_SHARED
;
44 RefPtr
<ID3D11Texture2D
> texture
;
46 d3d11Device
->CreateTexture2D(&desc
, nullptr, getter_AddRefs(texture
));
48 gfxCriticalNoteOnce
<< "CreateTexture2D failed: " << gfx::hexa(hr
);
52 RefPtr
<IDXGIResource1
> resource
;
53 texture
->QueryInterface((IDXGIResource1
**)getter_AddRefs(resource
));
55 gfxCriticalNoteOnce
<< "Failed to get IDXGIResource";
60 hr
= resource
->CreateSharedHandle(
61 nullptr, DXGI_SHARED_RESOURCE_READ
| DXGI_SHARED_RESOURCE_WRITE
, nullptr,
64 gfxCriticalNoteOnce
<< "GetSharedHandle failed: " << gfx::hexa(hr
);
68 RefPtr
<gfx::FileHandleWrapper
> handle
=
69 new gfx::FileHandleWrapper(UniqueFileHandle(sharedHandle
));
71 return MakeUnique
<ExternalTextureD3D11
>(aWidth
, aHeight
, aFormat
, aUsage
,
72 texture
, std::move(handle
));
75 ExternalTextureD3D11::ExternalTextureD3D11(
76 const uint32_t aWidth
, const uint32_t aHeight
,
77 const struct ffi::WGPUTextureFormat aFormat
,
78 const ffi::WGPUTextureUsages aUsage
, const RefPtr
<ID3D11Texture2D
> aTexture
,
79 RefPtr
<gfx::FileHandleWrapper
>&& aSharedHandle
)
80 : ExternalTexture(aWidth
, aHeight
, aFormat
, aUsage
),
82 mSharedHandle(std::move(aSharedHandle
)) {
86 ExternalTextureD3D11::~ExternalTextureD3D11() {}
88 void* ExternalTextureD3D11::GetExternalTextureHandle() {
93 return mSharedHandle
->GetHandle();
96 Maybe
<layers::SurfaceDescriptor
> ExternalTextureD3D11::ToSurfaceDescriptor(
97 Maybe
<gfx::FenceInfo
>& aFenceInfo
) {
98 const auto format
= gfx::SurfaceFormat::B8G8R8A8
;
99 return Some(layers::SurfaceDescriptorD3D10(
101 /* gpuProcessTextureId */ Nothing(),
102 /* arrayIndex */ 0, format
, gfx::IntSize(mWidth
, mHeight
),
103 gfx::ColorSpace2::SRGB
, gfx::ColorRange::FULL
,
104 /* hasKeyedMutex */ false, aFenceInfo
,
105 /* gpuProcessQueryId */ Nothing()));
108 void ExternalTextureD3D11::GetSnapshot(const ipc::Shmem
& aDestShmem
,
109 const gfx::IntSize
& aSize
) {
110 RefPtr
<ID3D11Device
> device
;
111 mTexture
->GetDevice(getter_AddRefs(device
));
113 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
114 gfxCriticalNoteOnce
<< "Failed to get ID3D11Device";
118 RefPtr
<ID3D11DeviceContext
> deviceContext
;
119 device
->GetImmediateContext(getter_AddRefs(deviceContext
));
120 if (!deviceContext
) {
121 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
122 gfxCriticalNoteOnce
<< "Failed to get ID3D11DeviceContext";
126 D3D11_TEXTURE2D_DESC textureDesc
= {0};
127 mTexture
->GetDesc(&textureDesc
);
129 textureDesc
.CPUAccessFlags
= D3D11_CPU_ACCESS_READ
;
130 textureDesc
.Usage
= D3D11_USAGE_STAGING
;
131 textureDesc
.BindFlags
= 0;
132 textureDesc
.MiscFlags
= 0;
133 textureDesc
.MipLevels
= 1;
135 RefPtr
<ID3D11Texture2D
> cpuTexture
;
136 HRESULT hr
= device
->CreateTexture2D(&textureDesc
, nullptr,
137 getter_AddRefs(cpuTexture
));
139 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
140 gfxCriticalNote
<< "Failed to create ID3D11Texture2D: " << gfx::hexa(hr
);
144 deviceContext
->CopyResource(cpuTexture
, mTexture
);
146 D3D11_MAPPED_SUBRESOURCE map
;
147 hr
= deviceContext
->Map(cpuTexture
, 0, D3D11_MAP_READ
, 0, &map
);
149 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
150 gfxCriticalNote
<< "Failed to map ID3D11Texture2D: " << gfx::hexa(hr
);
154 const uint32_t stride
= layers::ImageDataSerializer::ComputeRGBStride(
155 gfx::SurfaceFormat::B8G8R8A8
, aSize
.width
);
156 uint8_t* src
= static_cast<uint8_t*>(map
.pData
);
157 uint8_t* dst
= aDestShmem
.get
<uint8_t>();
159 MOZ_ASSERT(stride
* aSize
.height
<= aDestShmem
.Size
<uint8_t>());
161 for (int y
= 0; y
< aSize
.height
; y
++) {
162 memcpy(dst
, src
, stride
);
168 } // namespace mozilla::webgpu