tor-browser

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

SharedTextureDMABuf.cpp (6218B)


      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 "SharedTextureDMABuf.h"
      7 
      8 #include <gbm.h>
      9 
     10 #include "mozilla/gfx/Logging.h"
     11 #include "mozilla/layers/ImageDataSerializer.h"
     12 #include "mozilla/webgpu/WebGPUParent.h"
     13 #include "mozilla/widget/DMABufDevice.h"
     14 #include "mozilla/widget/DMABufSurface.h"
     15 
     16 namespace mozilla::webgpu {
     17 
     18 // static
     19 UniquePtr<SharedTextureDMABuf> SharedTextureDMABuf::Create(
     20    WebGPUParent* aParent, const ffi::WGPUDeviceId aDeviceId,
     21    const uint32_t aWidth, const uint32_t aHeight,
     22    const struct ffi::WGPUTextureFormat aFormat,
     23    const ffi::WGPUTextureUsages aUsage) {
     24  if (aFormat.tag != ffi::WGPUTextureFormat_Bgra8Unorm) {
     25    gfxCriticalNoteOnce << "Non supported format: " << aFormat.tag;
     26    return nullptr;
     27  }
     28 
     29  auto* context = aParent->GetContext();
     30  uint64_t memorySize = 0;
     31  ffi::WGPUVkImageHandle* vkImage = wgpu_vkimage_create_with_dma_buf(
     32      context, aDeviceId, aWidth, aHeight, &memorySize);
     33  if (!vkImage) {
     34    gfxCriticalNoteOnce << "Failed to create VkImage";
     35    return nullptr;
     36  }
     37  UniquePtr<VkImageHandle> handle =
     38      MakeUnique<VkImageHandle>(aParent, aDeviceId, vkImage);
     39 
     40  const auto dmaBufInfo = wgpu_vkimage_get_dma_buf_info(vkImage);
     41  if (!dmaBufInfo.is_valid) {
     42    gfxCriticalNoteOnce << "Invalid DMABufInfo";
     43    return nullptr;
     44  }
     45 
     46  MOZ_ASSERT(dmaBufInfo.plane_count <= 3);
     47 
     48  if (dmaBufInfo.plane_count > 3) {
     49    gfxCriticalNoteOnce << "Invalid plane count";
     50    return nullptr;
     51  }
     52 
     53  auto rawFd = wgpu_vkimage_get_file_descriptor(context, aDeviceId, vkImage);
     54  if (rawFd < 0) {
     55    gfxCriticalNoteOnce << "Failed to get fd fom VkDeviceMemory";
     56    return nullptr;
     57  }
     58 
     59  RefPtr<gfx::FileHandleWrapper> fd =
     60      new gfx::FileHandleWrapper(UniqueFileHandle(rawFd));
     61 
     62  RefPtr<DMABufSurface> surface = DMABufSurfaceRGBA::CreateDMABufSurface(
     63      std::move(fd), dmaBufInfo, aWidth, aHeight);
     64  if (!surface) {
     65    MOZ_ASSERT_UNREACHABLE("unexpected to be called");
     66    return nullptr;
     67  }
     68 
     69  layers::SurfaceDescriptor desc;
     70  if (!surface->Serialize(desc)) {
     71    MOZ_ASSERT_UNREACHABLE("unexpected to be called");
     72    return nullptr;
     73  }
     74 
     75  const auto sdType = desc.type();
     76  if (sdType != layers::SurfaceDescriptor::TSurfaceDescriptorDMABuf) {
     77    MOZ_ASSERT_UNREACHABLE("unexpected to be called");
     78    return nullptr;
     79  }
     80 
     81  return MakeUnique<SharedTextureDMABuf>(
     82      aParent, aDeviceId, std::move(handle), aWidth, aHeight, aFormat, aUsage,
     83      std::move(surface), desc.get_SurfaceDescriptorDMABuf());
     84 }
     85 
     86 SharedTextureDMABuf::SharedTextureDMABuf(
     87    WebGPUParent* aParent, const ffi::WGPUDeviceId aDeviceId,
     88    UniquePtr<VkImageHandle>&& aVkImageHandle, const uint32_t aWidth,
     89    const uint32_t aHeight, const struct ffi::WGPUTextureFormat aFormat,
     90    const ffi::WGPUTextureUsages aUsage, RefPtr<DMABufSurface>&& aSurface,
     91    const layers::SurfaceDescriptorDMABuf& aSurfaceDescriptor)
     92    : SharedTexture(aWidth, aHeight, aFormat, aUsage),
     93      mParent(aParent),
     94      mDeviceId(aDeviceId),
     95      mVkImageHandle(std::move(aVkImageHandle)),
     96      mSurface(std::move(aSurface)),
     97      mSurfaceDescriptor(aSurfaceDescriptor) {}
     98 
     99 SharedTextureDMABuf::~SharedTextureDMABuf() {}
    100 
    101 void SharedTextureDMABuf::CleanForRecycling() {
    102  mSemaphoreFds.Clear();
    103  mVkSemaphoreHandles.Clear();
    104 }
    105 
    106 Maybe<layers::SurfaceDescriptor> SharedTextureDMABuf::ToSurfaceDescriptor() {
    107  layers::SurfaceDescriptor sd;
    108  if (!mSurface->Serialize(sd)) {
    109    return Nothing();
    110  }
    111 
    112  if (sd.type() != layers::SurfaceDescriptor::TSurfaceDescriptorDMABuf) {
    113    return Nothing();
    114  }
    115 
    116  auto& sdDMABuf = sd.get_SurfaceDescriptorDMABuf();
    117  sdDMABuf.semaphoreFd() = mSemaphoreFds.LastElement();
    118 
    119  return Some(sd);
    120 }
    121 
    122 void SharedTextureDMABuf::GetSnapshot(const ipc::Shmem& aDestShmem,
    123                                      const gfx::IntSize& aSize) {
    124  const RefPtr<gfx::SourceSurface> surface = mSurface->GetAsSourceSurface();
    125  if (!surface) {
    126    MOZ_ASSERT_UNREACHABLE("unexpected to be called");
    127    gfxCriticalNoteOnce << "Failed to get SourceSurface from DMABufSurface";
    128    return;
    129  }
    130 
    131  const RefPtr<gfx::DataSourceSurface> dataSurface = surface->GetDataSurface();
    132  if (!dataSurface) {
    133    MOZ_ASSERT_UNREACHABLE("unexpected to be called");
    134    return;
    135  }
    136 
    137  gfx::DataSourceSurface::ScopedMap map(dataSurface,
    138                                        gfx::DataSourceSurface::READ);
    139  if (!map.IsMapped()) {
    140    MOZ_ASSERT_UNREACHABLE("unexpected to be called");
    141    return;
    142  }
    143 
    144  const uint32_t stride = layers::ImageDataSerializer::ComputeRGBStride(
    145      gfx::SurfaceFormat::B8G8R8A8, aSize.width);
    146  uint8_t* src = static_cast<uint8_t*>(map.GetData());
    147  uint8_t* dst = aDestShmem.get<uint8_t>();
    148 
    149  MOZ_ASSERT(stride * aSize.height <= aDestShmem.Size<uint8_t>());
    150  MOZ_ASSERT(static_cast<uint32_t>(map.GetStride()) >= stride);
    151 
    152  for (int y = 0; y < aSize.height; y++) {
    153    memcpy(dst, src, stride);
    154    src += map.GetStride();
    155    dst += stride;
    156  }
    157 }
    158 
    159 UniqueFileHandle SharedTextureDMABuf::CloneDmaBufFd() {
    160  return mSurfaceDescriptor.fds()[0]->ClonePlatformHandle();
    161 }
    162 
    163 const ffi::WGPUVkImageHandle* SharedTextureDMABuf::GetHandle() {
    164  return mVkImageHandle->Get();
    165 }
    166 
    167 void SharedTextureDMABuf::onBeforeQueueSubmit(RawId aQueueId) {
    168  if (!mParent) {
    169    return;
    170  }
    171 
    172  auto* context = mParent->GetContext();
    173  if (!context) {
    174    return;
    175  }
    176 
    177  ffi::WGPUVkSemaphoreHandle* vkSemaphore =
    178      wgpu_vksemaphore_create_signal_semaphore(context, aQueueId);
    179  if (!vkSemaphore) {
    180    gfxCriticalNoteOnce << "Failed to create VkSemaphore";
    181    return;
    182  }
    183 
    184  auto rawFd =
    185      wgpu_vksemaphore_get_file_descriptor(context, mDeviceId, vkSemaphore);
    186  if (rawFd < 0) {
    187    gfxCriticalNoteOnce << "Failed to get fd from VkSemaphore";
    188    return;
    189  }
    190 
    191  mVkSemaphoreHandles.AppendElement(
    192      MakeUnique<VkSemaphoreHandle>(mParent, mDeviceId, vkSemaphore));
    193  mSemaphoreFds.AppendElement(
    194      new gfx::FileHandleWrapper(UniqueFileHandle(rawFd)));
    195 }
    196 
    197 }  // namespace mozilla::webgpu