tor-browser

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

SharedSurfaceAndroidHardwareBuffer.cpp (5188B)


      1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
      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 "SharedSurfaceAndroidHardwareBuffer.h"
      7 
      8 #include "GLBlitHelper.h"
      9 #include "GLContextEGL.h"
     10 #include "GLContextProvider.h"
     11 #include "GLLibraryEGL.h"
     12 #include "GLReadTexImageHelper.h"
     13 #include "MozFramebuffer.h"
     14 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor, etc
     15 #include "mozilla/layers/AndroidHardwareBuffer.h"
     16 #include "ScopedGLHelpers.h"
     17 #include "SharedSurface.h"
     18 
     19 namespace mozilla {
     20 namespace gl {
     21 
     22 /*static*/
     23 UniquePtr<SharedSurface_AndroidHardwareBuffer>
     24 SharedSurface_AndroidHardwareBuffer::Create(const SharedSurfaceDesc& desc) {
     25  const auto& gle = GLContextEGL::Cast(desc.gl);
     26  const auto& egl = gle->mEgl;
     27 
     28  RefPtr<layers::AndroidHardwareBuffer> buffer =
     29      layers::AndroidHardwareBuffer::Create(desc.size,
     30                                            gfx::SurfaceFormat::R8G8B8A8);
     31  if (!buffer) {
     32    return nullptr;
     33  }
     34 
     35  const EGLint attrs[] = {
     36      LOCAL_EGL_IMAGE_PRESERVED,
     37      LOCAL_EGL_TRUE,
     38      LOCAL_EGL_NONE,
     39      LOCAL_EGL_NONE,
     40  };
     41 
     42  EGLClientBuffer clientBuffer =
     43      egl->mLib->fGetNativeClientBufferANDROID(buffer->GetNativeBuffer());
     44  const auto image = egl->fCreateImage(
     45      EGL_NO_CONTEXT, LOCAL_EGL_NATIVE_BUFFER_ANDROID, clientBuffer, attrs);
     46  if (!image) {
     47    return nullptr;
     48  }
     49 
     50  auto tex = MakeUnique<Texture>(*desc.gl);
     51  {
     52    ScopedBindTexture texture(gle, tex->name, LOCAL_GL_TEXTURE_2D);
     53    gle->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER,
     54                        LOCAL_GL_LINEAR);
     55    gle->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER,
     56                        LOCAL_GL_LINEAR);
     57    gle->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S,
     58                        LOCAL_GL_CLAMP_TO_EDGE);
     59    gle->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T,
     60                        LOCAL_GL_CLAMP_TO_EDGE);
     61    gle->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, image);
     62    egl->fDestroyImage(image);
     63  }
     64 
     65  const GLenum target = LOCAL_GL_TEXTURE_2D;
     66  auto fb = MozFramebuffer::CreateForBacking(desc.gl, desc.size, 0, false,
     67                                             target, tex->name);
     68  if (!fb) {
     69    return nullptr;
     70  }
     71 
     72  return AsUnique(new SharedSurface_AndroidHardwareBuffer(
     73      desc, std::move(fb), std::move(tex), buffer));
     74 }
     75 
     76 SharedSurface_AndroidHardwareBuffer::SharedSurface_AndroidHardwareBuffer(
     77    const SharedSurfaceDesc& desc, UniquePtr<MozFramebuffer> fb,
     78    UniquePtr<Texture> tex, RefPtr<layers::AndroidHardwareBuffer> buffer)
     79    : SharedSurface(desc, std::move(fb)),
     80      mTex(std::move(tex)),
     81      mAndroidHardwareBuffer(buffer) {}
     82 
     83 SharedSurface_AndroidHardwareBuffer::~SharedSurface_AndroidHardwareBuffer() {
     84  const auto& gl = mDesc.gl;
     85  if (!gl || !gl->MakeCurrent()) {
     86    return;
     87  }
     88  const auto& gle = GLContextEGL::Cast(gl);
     89  const auto& egl = gle->mEgl;
     90 
     91  if (mSync) {
     92    egl->fDestroySync(mSync);
     93    mSync = 0;
     94  }
     95 }
     96 
     97 void SharedSurface_AndroidHardwareBuffer::ProducerReleaseImpl() {
     98  const auto& gl = mDesc.gl;
     99  if (!gl || !gl->MakeCurrent()) {
    100    return;
    101  }
    102  const auto& gle = GLContextEGL::Cast(gl);
    103  const auto& egl = gle->mEgl;
    104 
    105  if (mSync) {
    106    MOZ_ALWAYS_TRUE(egl->fDestroySync(mSync));
    107    mSync = 0;
    108  }
    109 
    110  mSync = egl->fCreateSync(LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
    111  MOZ_ASSERT(mSync);
    112  int rawFd = egl->fDupNativeFenceFDANDROID(mSync);
    113  if (rawFd >= 0) {
    114    mAndroidHardwareBuffer->SetAcquireFence(UniqueFileHandle(rawFd));
    115  }
    116 
    117  gl->fFlush();
    118 }
    119 
    120 Maybe<layers::SurfaceDescriptor>
    121 SharedSurface_AndroidHardwareBuffer::ToSurfaceDescriptor() {
    122  return Some(layers::SurfaceDescriptorAndroidHardwareBuffer(
    123      mAndroidHardwareBuffer->mId, mAndroidHardwareBuffer->mSize,
    124      mAndroidHardwareBuffer->mFormat));
    125 }
    126 
    127 void SharedSurface_AndroidHardwareBuffer::WaitForBufferOwnership() {
    128  UniqueFileHandle fenceFd = mAndroidHardwareBuffer->GetAndResetReleaseFence();
    129  if (!fenceFd) {
    130    return;
    131  }
    132 
    133  const auto& gle = GLContextEGL::Cast(mDesc.gl);
    134  const auto& egl = gle->mEgl;
    135 
    136  const EGLint attribs[] = {LOCAL_EGL_SYNC_NATIVE_FENCE_FD_ANDROID,
    137                            fenceFd.get(), LOCAL_EGL_NONE};
    138 
    139  EGLSync sync = egl->fCreateSync(LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
    140  if (!sync) {
    141    gfxCriticalNote << "Failed to create EGLSync from fd";
    142    return;
    143  }
    144  // Release fd here, since it is owned by EGLSync
    145  (void)fenceFd.release();
    146 
    147  egl->fClientWaitSync(sync, 0, LOCAL_EGL_FOREVER);
    148  egl->fDestroySync(sync);
    149 }
    150 
    151 /*static*/
    152 UniquePtr<SurfaceFactory_AndroidHardwareBuffer>
    153 SurfaceFactory_AndroidHardwareBuffer::Create(GLContext& gl) {
    154  const auto partialDesc = PartialSharedSurfaceDesc{
    155      &gl,
    156      SharedSurfaceType::AndroidHardwareBuffer,
    157      layers::TextureType::AndroidHardwareBuffer,
    158      true,
    159  };
    160  return AsUnique(new SurfaceFactory_AndroidHardwareBuffer(partialDesc));
    161 }
    162 
    163 }  // namespace gl
    164 
    165 } /* namespace mozilla */