Bug 1885602 - Part 5: Implement navigating to the SUMO help topic from the menu heade...
[gecko.git] / dom / webgpu / ExternalTextureD3D11.cpp
blob34be281b5b1f4375a16f0d49d166bf682c40b927
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"
8 #include <d3d11.h>
10 #include "mozilla/gfx/DeviceManagerDx.h"
11 #include "mozilla/gfx/Logging.h"
12 #include "mozilla/layers/ImageDataSerializer.h"
14 namespace mozilla::webgpu {
16 // static
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();
23 if (!d3d11Device) {
24 gfxCriticalNoteOnce << "CompositorDevice does not exist";
25 return nullptr;
28 if (aFormat.tag != ffi::WGPUTextureFormat_Bgra8Unorm) {
29 gfxCriticalNoteOnce << "Non supported format: " << aFormat.tag;
30 return nullptr;
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;
41 desc.MiscFlags =
42 D3D11_RESOURCE_MISC_SHARED_NTHANDLE | D3D11_RESOURCE_MISC_SHARED;
44 RefPtr<ID3D11Texture2D> texture;
45 HRESULT hr =
46 d3d11Device->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture));
47 if (FAILED(hr)) {
48 gfxCriticalNoteOnce << "CreateTexture2D failed: " << gfx::hexa(hr);
49 return nullptr;
52 RefPtr<IDXGIResource1> resource;
53 texture->QueryInterface((IDXGIResource1**)getter_AddRefs(resource));
54 if (!resource) {
55 gfxCriticalNoteOnce << "Failed to get IDXGIResource";
56 return 0;
59 HANDLE sharedHandle;
60 hr = resource->CreateSharedHandle(
61 nullptr, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE, nullptr,
62 &sharedHandle);
63 if (FAILED(hr)) {
64 gfxCriticalNoteOnce << "GetSharedHandle failed: " << gfx::hexa(hr);
65 return 0;
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),
81 mTexture(aTexture),
82 mSharedHandle(std::move(aSharedHandle)) {
83 MOZ_ASSERT(mTexture);
86 ExternalTextureD3D11::~ExternalTextureD3D11() {}
88 void* ExternalTextureD3D11::GetExternalTextureHandle() {
89 if (!mSharedHandle) {
90 return nullptr;
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(
100 mSharedHandle,
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));
112 if (!device) {
113 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
114 gfxCriticalNoteOnce << "Failed to get ID3D11Device";
115 return;
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";
123 return;
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));
138 if (FAILED(hr)) {
139 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
140 gfxCriticalNote << "Failed to create ID3D11Texture2D: " << gfx::hexa(hr);
141 return;
144 deviceContext->CopyResource(cpuTexture, mTexture);
146 D3D11_MAPPED_SUBRESOURCE map;
147 hr = deviceContext->Map(cpuTexture, 0, D3D11_MAP_READ, 0, &map);
148 if (FAILED(hr)) {
149 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
150 gfxCriticalNote << "Failed to map ID3D11Texture2D: " << gfx::hexa(hr);
151 return;
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);
163 src += map.RowPitch;
164 dst += stride;
168 } // namespace mozilla::webgpu