tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SharedTextureD3D11.cpp (7525B)


      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/. */
      5 
      6 #include "SharedTextureD3D11.h"
      7 
      8 #include <d3d11.h>
      9 
     10 #include "mozilla/gfx/DeviceManagerDx.h"
     11 #include "mozilla/gfx/Logging.h"
     12 #include "mozilla/layers/CompositeProcessD3D11FencesHolderMap.h"
     13 #include "mozilla/layers/FenceD3D11.h"
     14 #include "mozilla/layers/ImageDataSerializer.h"
     15 #include "mozilla/webgpu/WebGPUParent.h"
     16 
     17 namespace mozilla::webgpu {
     18 
     19 // static
     20 UniquePtr<SharedTextureD3D11> SharedTextureD3D11::Create(
     21    WebGPUParent* aParent, const ffi::WGPUDeviceId aDeviceId,
     22    const uint32_t aWidth, const uint32_t aHeight,
     23    const struct ffi::WGPUTextureFormat aFormat,
     24    const ffi::WGPUTextureUsages aUsage) {
     25  auto* fencesHolderMap = layers::CompositeProcessD3D11FencesHolderMap::Get();
     26  if (!fencesHolderMap) {
     27    MOZ_ASSERT_UNREACHABLE("unexpected to be called");
     28    gfxCriticalNoteOnce << "Failed to get FencesHolderMap";
     29    return nullptr;
     30  }
     31 
     32  RefPtr<gfx::FileHandleWrapper> fenceHandle =
     33      aParent->GetDeviceFenceHandle(aDeviceId);
     34  if (!fenceHandle) {
     35    gfxCriticalNoteOnce << "Failed to get fenceHandle";
     36    return nullptr;
     37  }
     38 
     39  RefPtr<layers::FenceD3D11> fence =
     40      layers::FenceD3D11::CreateFromHandle(fenceHandle, /* aDevice */ nullptr);
     41  if (!fence) {
     42    gfxCriticalNoteOnce << "Failed create FenceD3D11";
     43    return nullptr;
     44  }
     45 
     46  const RefPtr<ID3D11Device> d3d11Device =
     47      gfx::DeviceManagerDx::Get()->GetCompositorDevice();
     48  if (!d3d11Device) {
     49    gfxCriticalNoteOnce << "CompositorDevice does not exist";
     50    return nullptr;
     51  }
     52 
     53  if (aFormat.tag != ffi::WGPUTextureFormat_Bgra8Unorm) {
     54    gfxCriticalNoteOnce << "Non supported format: " << aFormat.tag;
     55    return nullptr;
     56  }
     57 
     58  CD3D11_TEXTURE2D_DESC desc(
     59      DXGI_FORMAT_B8G8R8A8_UNORM, aWidth, aHeight, 1, 1,
     60      D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
     61 
     62  if (aUsage & WGPUTextureUsages_STORAGE_BINDING) {
     63    desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
     64  }
     65 
     66  desc.MiscFlags =
     67      D3D11_RESOURCE_MISC_SHARED_NTHANDLE | D3D11_RESOURCE_MISC_SHARED;
     68 
     69  RefPtr<ID3D11Texture2D> texture;
     70  HRESULT hr =
     71      d3d11Device->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture));
     72  if (FAILED(hr)) {
     73    gfxCriticalNoteOnce << "CreateTexture2D failed:  " << gfx::hexa(hr);
     74    return nullptr;
     75  }
     76 
     77  RefPtr<IDXGIResource1> resource;
     78  texture->QueryInterface((IDXGIResource1**)getter_AddRefs(resource));
     79  if (!resource) {
     80    gfxCriticalNoteOnce << "Failed to get IDXGIResource";
     81    return nullptr;
     82  }
     83 
     84  HANDLE sharedHandle;
     85  hr = resource->CreateSharedHandle(
     86      nullptr, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE, nullptr,
     87      &sharedHandle);
     88  if (FAILED(hr) || !sharedHandle) {
     89    gfxCriticalNoteOnce << "GetSharedHandle failed: " << gfx::hexa(hr);
     90    return nullptr;
     91  }
     92 
     93  RefPtr<gfx::FileHandleWrapper> handle =
     94      new gfx::FileHandleWrapper(UniqueFileHandle(sharedHandle));
     95 
     96  auto fencesHolderId = layers::CompositeProcessFencesHolderId::GetNext();
     97  fencesHolderMap->Register(fencesHolderId);
     98 
     99  return MakeUnique<SharedTextureD3D11>(aWidth, aHeight, aFormat, aUsage,
    100                                        texture, std::move(handle),
    101                                        fencesHolderId, std::move(fence));
    102 }
    103 
    104 SharedTextureD3D11::SharedTextureD3D11(
    105    const uint32_t aWidth, const uint32_t aHeight,
    106    const struct ffi::WGPUTextureFormat aFormat,
    107    const ffi::WGPUTextureUsages aUsage, const RefPtr<ID3D11Texture2D> aTexture,
    108    RefPtr<gfx::FileHandleWrapper>&& aSharedHandle,
    109    const layers::CompositeProcessFencesHolderId aFencesHolderId,
    110    RefPtr<layers::FenceD3D11>&& aWriteFence)
    111    : SharedTexture(aWidth, aHeight, aFormat, aUsage),
    112      mTexture(aTexture),
    113      mSharedHandle(std::move(aSharedHandle)),
    114      mFencesHolderId(aFencesHolderId),
    115      mWriteFence(std::move(aWriteFence)) {
    116  MOZ_ASSERT(mTexture);
    117 }
    118 
    119 SharedTextureD3D11::~SharedTextureD3D11() {
    120  auto* fencesHolderMap = layers::CompositeProcessD3D11FencesHolderMap::Get();
    121  if (fencesHolderMap) {
    122    fencesHolderMap->Unregister(mFencesHolderId);
    123  } else {
    124    gfxCriticalNoteOnce
    125        << "CompositeProcessD3D11FencesHolderMap does not exist";
    126  }
    127 }
    128 
    129 void* SharedTextureD3D11::GetSharedTextureHandle() {
    130  RefPtr<ID3D11Device> device;
    131  mTexture->GetDevice(getter_AddRefs(device));
    132  auto* fencesHolderMap = layers::CompositeProcessD3D11FencesHolderMap::Get();
    133  MOZ_ASSERT(fencesHolderMap);
    134 
    135  // XXX deliver fences to wgpu
    136  fencesHolderMap->WaitAllFencesAndForget(mFencesHolderId, device);
    137 
    138  return mSharedHandle->GetHandle();
    139 }
    140 
    141 Maybe<layers::SurfaceDescriptor> SharedTextureD3D11::ToSurfaceDescriptor() {
    142  MOZ_ASSERT(mSubmissionIndex > 0);
    143 
    144  mWriteFence->Update(mSubmissionIndex);
    145 
    146  auto* fencesHolderMap = layers::CompositeProcessD3D11FencesHolderMap::Get();
    147  MOZ_ASSERT(fencesHolderMap);
    148  fencesHolderMap->SetWriteFence(mFencesHolderId, mWriteFence);
    149 
    150  const auto format = gfx::SurfaceFormat::B8G8R8A8;
    151  return Some(layers::SurfaceDescriptorD3D10(
    152      mSharedHandle,
    153      /* gpuProcessTextureId */ Nothing(),
    154      /* arrayIndex */ 0, format, gfx::IntSize(mWidth, mHeight),
    155      gfx::ColorSpace2::SRGB, gfx::ColorRange::FULL,
    156      /* hasKeyedMutex */ false, Some(mFencesHolderId)));
    157 }
    158 
    159 void SharedTextureD3D11::GetSnapshot(const ipc::Shmem& aDestShmem,
    160                                     const gfx::IntSize& aSize) {
    161  RefPtr<ID3D11Device> device;
    162  mTexture->GetDevice(getter_AddRefs(device));
    163  if (!device) {
    164    MOZ_ASSERT_UNREACHABLE("unexpected to be called");
    165    gfxCriticalNoteOnce << "Failed to get ID3D11Device";
    166    return;
    167  }
    168 
    169  RefPtr<ID3D11DeviceContext> deviceContext;
    170  device->GetImmediateContext(getter_AddRefs(deviceContext));
    171  if (!deviceContext) {
    172    MOZ_ASSERT_UNREACHABLE("unexpected to be called");
    173    gfxCriticalNoteOnce << "Failed to get ID3D11DeviceContext";
    174    return;
    175  }
    176 
    177  D3D11_TEXTURE2D_DESC textureDesc = {0};
    178  mTexture->GetDesc(&textureDesc);
    179 
    180  textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
    181  textureDesc.Usage = D3D11_USAGE_STAGING;
    182  textureDesc.BindFlags = 0;
    183  textureDesc.MiscFlags = 0;
    184  textureDesc.MipLevels = 1;
    185 
    186  RefPtr<ID3D11Texture2D> cpuTexture;
    187  HRESULT hr = device->CreateTexture2D(&textureDesc, nullptr,
    188                                       getter_AddRefs(cpuTexture));
    189  if (FAILED(hr)) {
    190    MOZ_ASSERT_UNREACHABLE("unexpected to be called");
    191    gfxCriticalNote << "Failed to create ID3D11Texture2D: " << gfx::hexa(hr);
    192    return;
    193  }
    194 
    195  deviceContext->CopyResource(cpuTexture, mTexture);
    196 
    197  D3D11_MAPPED_SUBRESOURCE map;
    198  hr = deviceContext->Map(cpuTexture, 0, D3D11_MAP_READ, 0, &map);
    199  if (FAILED(hr)) {
    200    MOZ_ASSERT_UNREACHABLE("unexpected to be called");
    201    gfxCriticalNote << "Failed to map ID3D11Texture2D: " << gfx::hexa(hr);
    202    return;
    203  }
    204 
    205  const uint32_t stride = layers::ImageDataSerializer::ComputeRGBStride(
    206      gfx::SurfaceFormat::B8G8R8A8, aSize.width);
    207  uint8_t* src = static_cast<uint8_t*>(map.pData);
    208  uint8_t* dst = aDestShmem.get<uint8_t>();
    209 
    210  MOZ_ASSERT(stride * aSize.height <= aDestShmem.Size<uint8_t>());
    211  MOZ_ASSERT(map.RowPitch >= stride);
    212 
    213  for (int y = 0; y < aSize.height; y++) {
    214    memcpy(dst, src, stride);
    215    src += map.RowPitch;
    216    dst += stride;
    217  }
    218  deviceContext->Unmap(cpuTexture, 0);
    219 }
    220 
    221 }  // namespace mozilla::webgpu