tor-browser

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

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