tor-browser

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

AndroidSurfaceTexture.cpp (6055B)


      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 "AndroidSurfaceTexture.h"
      8 
      9 #include "GLContextEGL.h"
     10 #include "GLBlitHelper.h"
     11 #include "GLImages.h"
     12 #include "mozilla/gfx/Logging.h"
     13 #include "mozilla/layers/LayersSurfaces.h"
     14 
     15 #ifdef MOZ_WIDGET_ANDROID
     16 #  include "mozilla/java/GeckoSurfaceTextureNatives.h"
     17 #  include "AndroidNativeWindow.h"
     18 #endif  // MOZ_WIDGET_ANDROID
     19 
     20 namespace mozilla {
     21 namespace gl {
     22 
     23 class AndroidSharedBlitGL final {
     24 public:
     25  explicit AndroidSharedBlitGL(const EGLNativeWindowType window) {
     26    StaticMutexAutoLock lock(sMutex);
     27 
     28    if (!sContext) {
     29      MOZ_ASSERT(sInstanceCount == 0);
     30      sContext = CreateContext();
     31      if (!sContext) {
     32        return;
     33      }
     34    }
     35 
     36    const auto& egl = *(sContext->mEgl);
     37    mTargetSurface =
     38        egl.fCreateWindowSurface(sContext->mSurfaceConfig, window, nullptr);
     39 
     40    ++sInstanceCount;
     41  }
     42 
     43  ~AndroidSharedBlitGL() {
     44    StaticMutexAutoLock lock(sMutex);
     45 
     46    if (mTargetSurface != EGL_NO_SURFACE) {
     47      const auto& egl = *(sContext->mEgl);
     48      egl.fDestroySurface(mTargetSurface);
     49    }
     50 
     51    // Destroy shared GL context when no one uses it.
     52    if (--sInstanceCount == 0) {
     53      sContext = nullptr;
     54    }
     55  }
     56 
     57 #ifdef MOZ_WIDGET_ANDROID
     58  void Blit(const java::GeckoSurfaceTexture::Ref& surfaceTexture,
     59            const gfx::IntSize& imageSize) {
     60    StaticMutexAutoLock lock(sMutex);
     61    MOZ_ASSERT(sContext);
     62 
     63    // Setting overide also makes conext and surface current.
     64    sContext->SetEGLSurfaceOverride(mTargetSurface);
     65    DebugOnly<bool> rv = sContext->BlitHelper()->Blit(
     66        surfaceTexture, imageSize, gfx::IntRect(gfx::IntPoint(0, 0), imageSize),
     67        OriginPos::TopLeft);
     68    MOZ_ASSERT(rv);
     69    sContext->SwapBuffers();
     70    // This method is called through binder IPC and could run on any thread in
     71    // the pool. Release the context and surface from this thread after use so
     72    // they can be bound to another thread later.
     73    UnmakeCurrent(sContext);
     74  }
     75 #endif
     76 
     77 private:
     78  static already_AddRefed<GLContextEGL> CreateContextImpl(bool aUseGles) {
     79    sMutex.AssertCurrentThreadOwns();
     80    MOZ_ASSERT(!sContext);
     81 
     82    nsCString ignored;
     83    const auto egl = gl::DefaultEglDisplay(&ignored);
     84    EGLConfig eglConfig;
     85    CreateConfig(*egl, &eglConfig, /* bpp */ 24, /* depth buffer? */ false,
     86                 aUseGles);
     87    auto gl = GLContextEGL::CreateGLContext(egl, {}, eglConfig, EGL_NO_SURFACE,
     88                                            true, eglConfig, &ignored);
     89    if (!gl) {
     90      NS_WARNING("Fail to create GL context for native blitter.");
     91      return nullptr;
     92    }
     93    gl->mOwningThreadId = Nothing();
     94 
     95    // Yield the current state made in constructor.
     96    UnmakeCurrent(gl);
     97    return gl.forget();
     98  }
     99 
    100  static already_AddRefed<GLContextEGL> CreateContext() {
    101    RefPtr<GLContextEGL> gl;
    102 #if !defined(MOZ_WIDGET_ANDROID)
    103    gl = CreateContextImpl(/* aUseGles */ false);
    104 #endif  // !defined(MOZ_WIDGET_ANDROID)
    105 
    106    if (!gl) {
    107      gl = CreateContextImpl(/* aUseGles */ true);
    108    }
    109    return gl.forget();
    110  }
    111 
    112  static bool UnmakeCurrent(GLContextEGL* const gl) {
    113    sMutex.AssertCurrentThreadOwns();
    114    MOZ_ASSERT(gl);
    115 
    116    if (!gl->IsCurrent()) {
    117      return true;
    118    }
    119    const auto& egl = *(gl->mEgl);
    120    return egl.fMakeCurrent(EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    121  }
    122 
    123  static StaticMutex sMutex MOZ_UNANNOTATED;
    124  static StaticRefPtr<GLContextEGL> sContext;
    125  static size_t sInstanceCount;
    126 
    127  EGLSurface mTargetSurface;
    128 };
    129 
    130 StaticMutex AndroidSharedBlitGL::sMutex;
    131 StaticRefPtr<GLContextEGL> AndroidSharedBlitGL::sContext;
    132 size_t AndroidSharedBlitGL::sInstanceCount = 0;
    133 
    134 // -
    135 #ifdef MOZ_WIDGET_ANDROID
    136 
    137 void AndroidSurfaceTexture::GetTransformMatrix(
    138    const java::sdk::SurfaceTexture::Ref& surfaceTexture,
    139    gfx::Matrix4x4* outMatrix) {
    140  JNIEnv* const env = jni::GetEnvForThread();
    141 
    142  auto jarray = jni::FloatArray::LocalRef::Adopt(env, env->NewFloatArray(16));
    143  surfaceTexture->GetTransformMatrix(jarray);
    144 
    145  jfloat* array = env->GetFloatArrayElements(jarray.Get(), nullptr);
    146 
    147  memcpy(&(outMatrix->_11), array, sizeof(float) * 16);
    148 
    149  env->ReleaseFloatArrayElements(jarray.Get(), array, 0);
    150 }
    151 
    152 class GLBlitterSupport final
    153    : public java::GeckoSurfaceTexture::NativeGLBlitHelper::Natives<
    154          GLBlitterSupport> {
    155 public:
    156  using Base =
    157      java::GeckoSurfaceTexture::NativeGLBlitHelper::Natives<GLBlitterSupport>;
    158  using Base::AttachNative;
    159  using Base::DisposeNative;
    160  using Base::GetNative;
    161 
    162  static java::GeckoSurfaceTexture::NativeGLBlitHelper::LocalRef NativeCreate(
    163      jlong sourceTextureHandle, jni::Object::Param targetSurface, jint width,
    164      jint height) {
    165    AndroidNativeWindow win(java::GeckoSurface::Ref::From(targetSurface));
    166    auto helper = java::GeckoSurfaceTexture::NativeGLBlitHelper::New();
    167    const auto& eglWindow = win.NativeWindow();
    168    GLBlitterSupport::AttachNative(
    169        helper,
    170        MakeUnique<GLBlitterSupport>(MakeUnique<AndroidSharedBlitGL>(eglWindow),
    171                                     sourceTextureHandle, width, height));
    172    return helper;
    173  }
    174 
    175  GLBlitterSupport(UniquePtr<AndroidSharedBlitGL>&& gl,
    176                   jlong sourceTextureHandle, jint width, jint height)
    177      : mGl(std::move(gl)),
    178        mSourceTextureHandle(sourceTextureHandle),
    179        mSize(width, height) {}
    180 
    181  void Blit() {
    182    auto surfaceTexture =
    183        java::GeckoSurfaceTexture::Lookup(mSourceTextureHandle);
    184    mGl->Blit(surfaceTexture, mSize);
    185  }
    186 
    187 private:
    188  const UniquePtr<AndroidSharedBlitGL> mGl;
    189  const AndroidSurfaceTextureHandle mSourceTextureHandle;
    190  const gfx::IntSize mSize;
    191 };
    192 
    193 void AndroidSurfaceTexture::Init() { GLBlitterSupport::Init(); }
    194 
    195 #endif  // MOZ_WIDGET_ANDROID
    196 
    197 }  // namespace gl
    198 }  // namespace mozilla