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