tor-browser

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

SharedSurfaceEGL.cpp (8756B)


      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 "SharedSurfaceEGL.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 "SharedSurface.h"
     16 
     17 #if defined(MOZ_WIDGET_ANDROID)
     18 #  include "AndroidNativeWindow.h"
     19 #  include "mozilla/java/SurfaceAllocatorWrappers.h"
     20 #  include "mozilla/java/GeckoSurfaceTextureWrappers.h"
     21 #endif  // defined(MOZ_WIDGET_ANDROID)
     22 
     23 namespace mozilla {
     24 namespace gl {
     25 
     26 static bool HasEglImageExtensions(const GLContextEGL& gl) {
     27  const auto& egl = *(gl.mEgl);
     28  return egl.HasKHRImageBase() &&
     29         egl.IsExtensionSupported(EGLExtension::KHR_gl_texture_2D_image) &&
     30         (gl.IsExtensionSupported(GLContext::OES_EGL_image_external) ||
     31          gl.IsExtensionSupported(GLContext::OES_EGL_image));
     32 }
     33 
     34 /*static*/
     35 UniquePtr<SurfaceFactory_EGLImage> SurfaceFactory_EGLImage::Create(
     36    GLContext& gl_) {
     37  auto& gl = *GLContextEGL::Cast(&gl_);
     38  if (!HasEglImageExtensions(gl)) return nullptr;
     39 
     40  const auto partialDesc = PartialSharedSurfaceDesc{
     41      &gl, SharedSurfaceType::EGLImageShare, layers::TextureType::EGLImage,
     42      false,  // Can't recycle, as mSync changes never update TextureHost.
     43  };
     44  return AsUnique(new SurfaceFactory_EGLImage(partialDesc));
     45 }
     46 
     47 // -
     48 
     49 /*static*/
     50 UniquePtr<SharedSurface_EGLImage> SharedSurface_EGLImage::Create(
     51    const SharedSurfaceDesc& desc) {
     52  const auto& gle = GLContextEGL::Cast(desc.gl);
     53  const auto& context = gle->mContext;
     54  const auto& egl = *(gle->mEgl);
     55 
     56  auto fb = MozFramebuffer::Create(desc.gl, desc.size, 0, false);
     57  if (!fb) return nullptr;
     58 
     59  const auto buffer = reinterpret_cast<EGLClientBuffer>(fb->ColorTex());
     60  const auto image =
     61      egl.fCreateImage(context, LOCAL_EGL_GL_TEXTURE_2D, buffer, nullptr);
     62  if (!image) return nullptr;
     63 
     64  return AsUnique(new SharedSurface_EGLImage(desc, std::move(fb), image));
     65 }
     66 
     67 SharedSurface_EGLImage::SharedSurface_EGLImage(const SharedSurfaceDesc& desc,
     68                                               UniquePtr<MozFramebuffer>&& fb,
     69                                               const EGLImage image)
     70    : SharedSurface(desc, std::move(fb)),
     71      mMutex("SharedSurface_EGLImage mutex"),
     72      mEglDisplay(GLContextEGL::Cast(desc.gl)->mEgl),
     73      mImage(image) {}
     74 
     75 SharedSurface_EGLImage::~SharedSurface_EGLImage() {
     76  if (auto display = mEglDisplay.lock()) {
     77    display->fDestroyImage(mImage);
     78 
     79    if (mSync) {
     80      // We can't call this unless we have the ext, but we will always have
     81      // the ext if we have something to destroy.
     82      display->fDestroySync(mSync);
     83    }
     84  }
     85 }
     86 
     87 void SharedSurface_EGLImage::ProducerReleaseImpl() {
     88  const auto& gl = GLContextEGL::Cast(mDesc.gl);
     89  const auto& egl = gl->mEgl;
     90 
     91  MutexAutoLock lock(mMutex);
     92  gl->MakeCurrent();
     93 
     94  if (egl->IsExtensionSupported(EGLExtension::KHR_fence_sync) &&
     95      gl->IsExtensionSupported(GLContext::OES_EGL_sync)) {
     96    if (mSync) {
     97      MOZ_ALWAYS_TRUE(egl->fDestroySync(mSync));
     98      mSync = 0;
     99    }
    100 
    101    mSync = egl->fCreateSync(LOCAL_EGL_SYNC_FENCE, nullptr);
    102    if (mSync) {
    103      gl->fFlush();
    104      return;
    105    }
    106  }
    107 
    108  MOZ_ASSERT(!mSync);
    109  gl->fFinish();
    110 }
    111 
    112 void SharedSurface_EGLImage::ProducerReadAcquireImpl() {
    113  const auto& gle = GLContextEGL::Cast(mDesc.gl);
    114  const auto& egl = gle->mEgl;
    115  // Wait on the fence, because presumably we're going to want to read this
    116  // surface
    117  if (mSync) {
    118    egl->fClientWaitSync(mSync, 0, LOCAL_EGL_FOREVER);
    119  }
    120 }
    121 
    122 Maybe<layers::SurfaceDescriptor> SharedSurface_EGLImage::ToSurfaceDescriptor() {
    123  return Some(layers::EGLImageDescriptor((uintptr_t)mImage, (uintptr_t)mSync,
    124                                         mDesc.size, true));
    125 }
    126 
    127 ////////////////////////////////////////////////////////////////////////
    128 
    129 #ifdef MOZ_WIDGET_ANDROID
    130 
    131 /*static*/
    132 UniquePtr<SharedSurface_SurfaceTexture> SharedSurface_SurfaceTexture::Create(
    133    const SharedSurfaceDesc& desc) {
    134  const auto& size = desc.size;
    135 
    136  jni::Object::LocalRef surfaceObj;
    137  const bool useSingleBuffer =
    138      desc.gl->Renderer() != GLRenderer::AndroidEmulator;
    139 
    140  if (useSingleBuffer) {
    141    surfaceObj =
    142        java::SurfaceAllocator::AcquireSurface(size.width, size.height, true);
    143  }
    144 
    145  if (!surfaceObj) {
    146    // Try multi-buffer mode
    147    surfaceObj =
    148        java::SurfaceAllocator::AcquireSurface(size.width, size.height, false);
    149  }
    150 
    151  if (!surfaceObj) {
    152    // Give up
    153    NS_WARNING("Failed to allocate SurfaceTexture!");
    154    return nullptr;
    155  }
    156  const auto surface = java::GeckoSurface::Ref::From(surfaceObj);
    157 
    158  AndroidNativeWindow window(surface);
    159  const auto& gle = GLContextEGL::Cast(desc.gl);
    160  MOZ_ASSERT(gle);
    161  const auto eglSurface = gle->CreateCompatibleSurface(window.NativeWindow());
    162  if (!eglSurface) return nullptr;
    163 
    164  return AsUnique(new SharedSurface_SurfaceTexture(desc, surface, eglSurface));
    165 }
    166 
    167 SharedSurface_SurfaceTexture::SharedSurface_SurfaceTexture(
    168    const SharedSurfaceDesc& desc, java::GeckoSurface::Param surface,
    169    const EGLSurface eglSurface)
    170    : SharedSurface(desc, nullptr),
    171      mSurface(surface),
    172      mEglSurface(eglSurface),
    173      mEglDisplay(GLContextEGL::Cast(desc.gl)->mEgl) {}
    174 
    175 SharedSurface_SurfaceTexture::~SharedSurface_SurfaceTexture() {
    176  if (mOrigEglSurface) {
    177    // We are about to destroy mEglSurface.
    178    // Make sure gl->SetEGLSurfaceOverride() doesn't keep a reference
    179    // to the surface.
    180    UnlockProd();
    181  }
    182 
    183  std::shared_ptr<EglDisplay> display = mEglDisplay.lock();
    184  if (display) {
    185    display->fDestroySurface(mEglSurface);
    186  }
    187  java::SurfaceAllocator::DisposeSurface(mSurface);
    188 }
    189 
    190 void SharedSurface_SurfaceTexture::LockProdImpl() {
    191  MOZ_RELEASE_ASSERT(mSurface->GetAvailable());
    192 
    193  GLContextEGL* gl = GLContextEGL::Cast(mDesc.gl);
    194  mOrigEglSurface = gl->GetEGLSurfaceOverride();
    195  gl->SetEGLSurfaceOverride(mEglSurface);
    196 }
    197 
    198 void SharedSurface_SurfaceTexture::UnlockProdImpl() {
    199  MOZ_RELEASE_ASSERT(mSurface->GetAvailable());
    200 
    201  GLContextEGL* gl = GLContextEGL::Cast(mDesc.gl);
    202  MOZ_ASSERT(gl->GetEGLSurfaceOverride() == mEglSurface);
    203 
    204  gl->SetEGLSurfaceOverride(mOrigEglSurface);
    205  mOrigEglSurface = nullptr;
    206 }
    207 
    208 void SharedSurface_SurfaceTexture::ProducerReadReleaseImpl() {
    209  // This GeckoSurfaceTexture is not SurfaceTexture of this class's GeckoSurface
    210  // when current process is content process. In this case, SurfaceTexture of
    211  // this class's GeckoSurface does not exist in this process. It exists in
    212  // compositor's process. Then GeckoSurfaceTexture in this process is a sync
    213  // surface that copies back the SurfaceTextrure from compositor's process. It
    214  // was added by Bug 1486659. Then SurfaceTexture::UpdateTexImage() becomes
    215  // very heavy weight, since it does copy back the SurfaceTextrure from
    216  // compositor's process.
    217  java::GeckoSurfaceTexture::LocalRef surfaceTexture =
    218      java::GeckoSurfaceTexture::Lookup(mSurface->GetHandle());
    219  if (!surfaceTexture) {
    220    NS_ERROR("Didn't find GeckoSurfaceTexture in ProducerReadReleaseImpl");
    221    return;
    222  }
    223  surfaceTexture->UpdateTexImage();
    224  // Non single buffer mode Surface does not need ReleaseTexImage() call.
    225  // When SurfaceTexture is sync Surface, it might not be single buffer mode.
    226  if (surfaceTexture->IsSingleBuffer()) {
    227    surfaceTexture->ReleaseTexImage();
    228  }
    229 }
    230 
    231 void SharedSurface_SurfaceTexture::Commit() {
    232  MOZ_RELEASE_ASSERT(mSurface->GetAvailable());
    233 
    234  LockProdImpl();
    235  mDesc.gl->SwapBuffers();
    236  UnlockProdImpl();
    237  mSurface->SetAvailable(false);
    238 }
    239 
    240 void SharedSurface_SurfaceTexture::WaitForBufferOwnership() {
    241  mSurface->SetAvailable(true);
    242 }
    243 
    244 bool SharedSurface_SurfaceTexture::IsBufferAvailable() const {
    245  return mSurface->GetAvailable();
    246 }
    247 
    248 bool SharedSurface_SurfaceTexture::IsValid() const {
    249  return !mSurface->IsReleased();
    250 }
    251 
    252 Maybe<layers::SurfaceDescriptor>
    253 SharedSurface_SurfaceTexture::ToSurfaceDescriptor() {
    254  return Some(layers::SurfaceTextureDescriptor(
    255      mSurface->GetHandle(), mDesc.size, gfx::SurfaceFormat::R8G8B8A8,
    256      false /* Do NOT override colorspace */, false /* NOT continuous */,
    257      Nothing() /* Do not override transform */));
    258 }
    259 
    260 SurfaceFactory_SurfaceTexture::SurfaceFactory_SurfaceTexture(GLContext& gl)
    261    : SurfaceFactory({&gl, SharedSurfaceType::AndroidSurfaceTexture,
    262                      layers::TextureType::AndroidNativeWindow, true}) {}
    263 
    264 #endif  // MOZ_WIDGET_ANDROID
    265 
    266 }  // namespace gl
    267 
    268 } /* namespace mozilla */