AndroidHardwareBuffer.cpp (9636B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "AndroidHardwareBuffer.h" 8 9 #include "mozilla/gfx/2D.h" 10 #include "mozilla/gfx/gfxVars.h" 11 #include "mozilla/layers/ImageBridgeChild.h" 12 #include "mozilla/layers/TextureClientSharedSurface.h" 13 #include "mozilla/TimeStamp.h" 14 #include "mozilla/UniquePtrExtensions.h" 15 16 namespace mozilla { 17 namespace layers { 18 19 static uint32_t ToAHardwareBuffer_Format(gfx::SurfaceFormat aFormat) { 20 switch (aFormat) { 21 case gfx::SurfaceFormat::R8G8B8A8: 22 case gfx::SurfaceFormat::B8G8R8A8: 23 return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM; 24 25 case gfx::SurfaceFormat::R8G8B8X8: 26 case gfx::SurfaceFormat::B8G8R8X8: 27 return AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM; 28 29 case gfx::SurfaceFormat::R5G6B5_UINT16: 30 return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM; 31 32 default: 33 MOZ_ASSERT_UNREACHABLE("Unsupported SurfaceFormat"); 34 return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM; 35 } 36 } 37 38 StaticAutoPtr<AndroidHardwareBufferApi> AndroidHardwareBufferApi::sInstance; 39 40 /* static */ 41 void AndroidHardwareBufferApi::Init() { 42 MOZ_ASSERT(XRE_IsGPUProcess()); 43 44 sInstance = new AndroidHardwareBufferApi(); 45 if (!sInstance->Load()) { 46 sInstance = nullptr; 47 } 48 } 49 50 /* static */ 51 void AndroidHardwareBufferApi::Shutdown() { sInstance = nullptr; } 52 53 AndroidHardwareBufferApi::AndroidHardwareBufferApi() {} 54 55 bool AndroidHardwareBufferApi::Load() { 56 mAHardwareBuffer_allocate = AHardwareBuffer_allocate; 57 mAHardwareBuffer_acquire = AHardwareBuffer_acquire; 58 mAHardwareBuffer_release = AHardwareBuffer_release; 59 mAHardwareBuffer_describe = AHardwareBuffer_describe; 60 mAHardwareBuffer_lock = AHardwareBuffer_lock; 61 mAHardwareBuffer_unlock = AHardwareBuffer_unlock; 62 mAHardwareBuffer_sendHandleToUnixSocket = 63 AHardwareBuffer_sendHandleToUnixSocket; 64 mAHardwareBuffer_recvHandleFromUnixSocket = 65 AHardwareBuffer_recvHandleFromUnixSocket; 66 return true; 67 } 68 69 void AndroidHardwareBufferApi::Allocate(const AHardwareBuffer_Desc* aDesc, 70 AHardwareBuffer** aOutBuffer) { 71 mAHardwareBuffer_allocate(aDesc, aOutBuffer); 72 } 73 74 void AndroidHardwareBufferApi::Acquire(AHardwareBuffer* aBuffer) { 75 mAHardwareBuffer_acquire(aBuffer); 76 } 77 78 void AndroidHardwareBufferApi::Release(AHardwareBuffer* aBuffer) { 79 mAHardwareBuffer_release(aBuffer); 80 } 81 82 void AndroidHardwareBufferApi::Describe(const AHardwareBuffer* aBuffer, 83 AHardwareBuffer_Desc* aOutDesc) { 84 mAHardwareBuffer_describe(aBuffer, aOutDesc); 85 } 86 87 int AndroidHardwareBufferApi::Lock(AHardwareBuffer* aBuffer, uint64_t aUsage, 88 int32_t aFence, const ARect* aRect, 89 void** aOutVirtualAddress) { 90 return mAHardwareBuffer_lock(aBuffer, aUsage, aFence, aRect, 91 aOutVirtualAddress); 92 } 93 94 int AndroidHardwareBufferApi::Unlock(AHardwareBuffer* aBuffer, 95 int32_t* aFence) { 96 return mAHardwareBuffer_unlock(aBuffer, aFence); 97 } 98 99 int AndroidHardwareBufferApi::SendHandleToUnixSocket( 100 const AHardwareBuffer* aBuffer, int aSocketFd) { 101 return mAHardwareBuffer_sendHandleToUnixSocket(aBuffer, aSocketFd); 102 } 103 104 int AndroidHardwareBufferApi::RecvHandleFromUnixSocket( 105 int aSocketFd, AHardwareBuffer** aOutBuffer) { 106 return mAHardwareBuffer_recvHandleFromUnixSocket(aSocketFd, aOutBuffer); 107 } 108 109 /* static */ 110 uint64_t AndroidHardwareBuffer::GetNextId() { 111 static std::atomic<uint64_t> sNextId = 0; 112 uint64_t id = ++sNextId; 113 return id; 114 } 115 116 /* static */ 117 already_AddRefed<AndroidHardwareBuffer> AndroidHardwareBuffer::Create( 118 gfx::IntSize aSize, gfx::SurfaceFormat aFormat) { 119 if (!AndroidHardwareBufferApi::Get()) { 120 return nullptr; 121 } 122 123 if (aFormat != gfx::SurfaceFormat::R8G8B8A8 && 124 aFormat != gfx::SurfaceFormat::R8G8B8X8 && 125 aFormat != gfx::SurfaceFormat::B8G8R8A8 && 126 aFormat != gfx::SurfaceFormat::B8G8R8X8 && 127 aFormat != gfx::SurfaceFormat::R5G6B5_UINT16) { 128 return nullptr; 129 } 130 131 AHardwareBuffer_Desc desc = {}; 132 desc.width = aSize.width; 133 desc.height = aSize.height; 134 desc.layers = 1; // number of images 135 desc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | 136 AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN | 137 AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | 138 AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT; 139 desc.format = ToAHardwareBuffer_Format(aFormat); 140 141 AHardwareBuffer* nativeBuffer = nullptr; 142 AndroidHardwareBufferApi::Get()->Allocate(&desc, &nativeBuffer); 143 if (!nativeBuffer) { 144 return nullptr; 145 } 146 147 AHardwareBuffer_Desc bufferInfo = {}; 148 AndroidHardwareBufferApi::Get()->Describe(nativeBuffer, &bufferInfo); 149 150 RefPtr<AndroidHardwareBuffer> buffer = new AndroidHardwareBuffer( 151 nativeBuffer, aSize, bufferInfo.stride, aFormat, GetNextId()); 152 AndroidHardwareBufferManager::Get()->Register(buffer); 153 return buffer.forget(); 154 } 155 156 AndroidHardwareBuffer::AndroidHardwareBuffer(AHardwareBuffer* aNativeBuffer, 157 gfx::IntSize aSize, 158 uint32_t aStride, 159 gfx::SurfaceFormat aFormat, 160 uint64_t aId) 161 : mSize(aSize), 162 mStride(aStride), 163 mFormat(aFormat), 164 mId(aId), 165 mNativeBuffer(aNativeBuffer), 166 mIsRegistered(false) { 167 MOZ_ASSERT(mNativeBuffer); 168 #ifdef DEBUG 169 AHardwareBuffer_Desc bufferInfo = {}; 170 AndroidHardwareBufferApi::Get()->Describe(mNativeBuffer, &bufferInfo); 171 MOZ_ASSERT(mSize.width == (int32_t)bufferInfo.width); 172 MOZ_ASSERT(mSize.height == (int32_t)bufferInfo.height); 173 MOZ_ASSERT(mStride == bufferInfo.stride); 174 MOZ_ASSERT(ToAHardwareBuffer_Format(mFormat) == bufferInfo.format); 175 #endif 176 } 177 178 AndroidHardwareBuffer::~AndroidHardwareBuffer() { 179 if (mIsRegistered) { 180 AndroidHardwareBufferManager::Get()->Unregister(this); 181 } 182 AndroidHardwareBufferApi::Get()->Release(mNativeBuffer); 183 } 184 185 int AndroidHardwareBuffer::Lock(uint64_t aUsage, const ARect* aRect, 186 void** aOutVirtualAddress) { 187 UniqueFileHandle fd = GetAndResetReleaseFence(); 188 return AndroidHardwareBufferApi::Get()->Lock(mNativeBuffer, aUsage, fd.get(), 189 aRect, aOutVirtualAddress); 190 } 191 192 int AndroidHardwareBuffer::Unlock() { 193 int rawFd = -1; 194 // XXX All tested recent Android devices did not return valid fence. 195 int ret = AndroidHardwareBufferApi::Get()->Unlock(mNativeBuffer, &rawFd); 196 if (ret != 0) { 197 return ret; 198 } 199 200 SetAcquireFence(UniqueFileHandle(rawFd)); 201 return 0; 202 } 203 204 void AndroidHardwareBuffer::SetReleaseFence(UniqueFileHandle&& aFenceFd) { 205 MonitorAutoLock lock(AndroidHardwareBufferManager::Get()->GetMonitor()); 206 SetReleaseFence(std::move(aFenceFd), lock); 207 } 208 209 void AndroidHardwareBuffer::SetReleaseFence(UniqueFileHandle&& aFenceFd, 210 const MonitorAutoLock& aAutoLock) { 211 mReleaseFenceFd = std::move(aFenceFd); 212 } 213 214 void AndroidHardwareBuffer::SetAcquireFence(UniqueFileHandle&& aFenceFd) { 215 MonitorAutoLock lock(AndroidHardwareBufferManager::Get()->GetMonitor()); 216 217 mAcquireFenceFd = std::move(aFenceFd); 218 } 219 220 UniqueFileHandle AndroidHardwareBuffer::GetAndResetReleaseFence() { 221 MonitorAutoLock lock(AndroidHardwareBufferManager::Get()->GetMonitor()); 222 return std::move(mReleaseFenceFd); 223 } 224 225 UniqueFileHandle AndroidHardwareBuffer::GetAndResetAcquireFence() { 226 MonitorAutoLock lock(AndroidHardwareBufferManager::Get()->GetMonitor()); 227 return std::move(mAcquireFenceFd); 228 } 229 230 UniqueFileHandle AndroidHardwareBuffer::GetAcquireFence() const { 231 MonitorAutoLock lock(AndroidHardwareBufferManager::Get()->GetMonitor()); 232 if (!mAcquireFenceFd) { 233 return UniqueFileHandle(); 234 } 235 236 return DuplicateFileHandle(mAcquireFenceFd); 237 } 238 239 StaticAutoPtr<AndroidHardwareBufferManager> 240 AndroidHardwareBufferManager::sInstance; 241 242 /* static */ 243 void AndroidHardwareBufferManager::Init() { 244 MOZ_ASSERT(XRE_IsGPUProcess()); 245 246 sInstance = new AndroidHardwareBufferManager(); 247 } 248 249 /* static */ 250 void AndroidHardwareBufferManager::Shutdown() { sInstance = nullptr; } 251 252 AndroidHardwareBufferManager::AndroidHardwareBufferManager() 253 : mMonitor("AndroidHardwareBufferManager.mMonitor") {} 254 255 void AndroidHardwareBufferManager::Register( 256 RefPtr<AndroidHardwareBuffer> aBuffer) { 257 MonitorAutoLock lock(mMonitor); 258 259 aBuffer->mIsRegistered = true; 260 ThreadSafeWeakPtr<AndroidHardwareBuffer> weak(aBuffer); 261 262 #ifdef DEBUG 263 const auto it = mBuffers.find(aBuffer->mId); 264 MOZ_ASSERT(it == mBuffers.end()); 265 #endif 266 mBuffers.emplace(aBuffer->mId, weak); 267 } 268 269 void AndroidHardwareBufferManager::Unregister(AndroidHardwareBuffer* aBuffer) { 270 MonitorAutoLock lock(mMonitor); 271 272 const auto it = mBuffers.find(aBuffer->mId); 273 MOZ_ASSERT(it != mBuffers.end()); 274 if (it == mBuffers.end()) { 275 gfxCriticalNote << "AndroidHardwareBuffer id mismatch happened"; 276 return; 277 } 278 mBuffers.erase(it); 279 } 280 281 already_AddRefed<AndroidHardwareBuffer> AndroidHardwareBufferManager::GetBuffer( 282 uint64_t aBufferId) { 283 MonitorAutoLock lock(mMonitor); 284 285 const auto it = mBuffers.find(aBufferId); 286 if (it == mBuffers.end()) { 287 return nullptr; 288 } 289 auto buffer = RefPtr<AndroidHardwareBuffer>(it->second); 290 return buffer.forget(); 291 } 292 293 } // namespace layers 294 } // namespace mozilla