forked from mirrors/gecko-dev
		
	 63eead4dae
			
		
	
	
		63eead4dae
		
	
	
	
	
		
			
			When available, we should use the [`EGL_KHR_no_config_context` extension] inside of
`GLContextEGL::CreateEGLPBufferOffscreenContext`. The usage of this extension will be necessary to
accommodate incoming upstream changes in ANGLE, which have [migrated away][incoming-breakage] from
[our usage of `EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE` in
`gfx/webrender_bindings/RenderCompositorANGLE.cpp`][what-will-be-broken] in favor of this standard
extension. Luckily it's forwards-compatible to start consuming it now!
This revision changes a few things that are linked:
- Separate assignment and usage of a surface context from that of a context.
- Rename `GLContextEGL::mConfig` to `mSurfaceConfig` to better reflect its usage; it's only ever
  used to create surfaces, not contexts.
Split out from @jgilbert's D164308 and D164309.
[`EGL_KHR_no_config_context` extension]: https://registry.khronos.org/EGL/extensions/KHR/EGL_KHR_no_config_context.txt
[incoming-breakage]: ad8e4d99a9
[what-will-be-broken]: https://searchfox.org/mozilla-central/rev/b19830c6b22f73758862d34d2c64f57735890e90/gfx/webrender_bindings/RenderCompositorANGLE.cpp#668
Differential Revision: https://phabricator.services.mozilla.com/D166708
		
	
			
		
			
				
	
	
		
			197 lines
		
	
	
	
		
			5.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			197 lines
		
	
	
	
		
			5.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| #include "AndroidSurfaceTexture.h"
 | |
| 
 | |
| #include "GLContextEGL.h"
 | |
| #include "GLBlitHelper.h"
 | |
| #include "GLImages.h"
 | |
| #include "mozilla/gfx/Logging.h"
 | |
| #include "mozilla/layers/LayersSurfaces.h"
 | |
| 
 | |
| #ifdef MOZ_WIDGET_ANDROID
 | |
| #  include "mozilla/java/GeckoSurfaceTextureNatives.h"
 | |
| #  include "AndroidNativeWindow.h"
 | |
| #endif  // MOZ_WIDGET_ANDROID
 | |
| 
 | |
| namespace mozilla {
 | |
| namespace gl {
 | |
| 
 | |
| class AndroidSharedBlitGL final {
 | |
|  public:
 | |
|   explicit AndroidSharedBlitGL(const EGLNativeWindowType window) {
 | |
|     StaticMutexAutoLock lock(sMutex);
 | |
| 
 | |
|     if (!sContext) {
 | |
|       MOZ_ASSERT(sInstanceCount == 0);
 | |
|       sContext = CreateContext();
 | |
|       if (!sContext) {
 | |
|         return;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     const auto& egl = *(sContext->mEgl);
 | |
|     mTargetSurface =
 | |
|         egl.fCreateWindowSurface(sContext->mSurfaceConfig, window, nullptr);
 | |
| 
 | |
|     ++sInstanceCount;
 | |
|   }
 | |
| 
 | |
|   ~AndroidSharedBlitGL() {
 | |
|     StaticMutexAutoLock lock(sMutex);
 | |
| 
 | |
|     if (mTargetSurface != EGL_NO_SURFACE) {
 | |
|       const auto& egl = *(sContext->mEgl);
 | |
|       egl.fDestroySurface(mTargetSurface);
 | |
|     }
 | |
| 
 | |
|     // Destroy shared GL context when no one uses it.
 | |
|     if (--sInstanceCount == 0) {
 | |
|       sContext = nullptr;
 | |
|     }
 | |
|   }
 | |
| 
 | |
| #ifdef MOZ_WIDGET_ANDROID
 | |
|   void Blit(const java::GeckoSurfaceTexture::Ref& surfaceTexture,
 | |
|             const gfx::IntSize& imageSize) {
 | |
|     StaticMutexAutoLock lock(sMutex);
 | |
|     MOZ_ASSERT(sContext);
 | |
| 
 | |
|     // Setting overide also makes conext and surface current.
 | |
|     sContext->SetEGLSurfaceOverride(mTargetSurface);
 | |
|     DebugOnly<bool> rv = sContext->BlitHelper()->Blit(surfaceTexture, imageSize,
 | |
|                                                       OriginPos::TopLeft);
 | |
|     MOZ_ASSERT(rv);
 | |
|     sContext->SwapBuffers();
 | |
|     // This method is called through binder IPC and could run on any thread in
 | |
|     // the pool. Release the context and surface from this thread after use so
 | |
|     // they can be bound to another thread later.
 | |
|     UnmakeCurrent(sContext);
 | |
|   }
 | |
| #endif
 | |
| 
 | |
|  private:
 | |
|   static already_AddRefed<GLContextEGL> CreateContextImpl(bool aUseGles) {
 | |
|     sMutex.AssertCurrentThreadOwns();
 | |
|     MOZ_ASSERT(!sContext);
 | |
| 
 | |
|     nsCString ignored;
 | |
|     const auto egl = gl::DefaultEglDisplay(&ignored);
 | |
|     EGLConfig eglConfig;
 | |
|     CreateConfig(*egl, &eglConfig, /* bpp */ 24, /* depth buffer? */ false,
 | |
|                  aUseGles);
 | |
|     auto gl = GLContextEGL::CreateGLContext(egl, {}, eglConfig, EGL_NO_SURFACE,
 | |
|                                             true, eglConfig, &ignored);
 | |
|     if (!gl) {
 | |
|       NS_WARNING("Fail to create GL context for native blitter.");
 | |
|       return nullptr;
 | |
|     }
 | |
|     gl->mOwningThreadId = Nothing();
 | |
| 
 | |
|     // Yield the current state made in constructor.
 | |
|     UnmakeCurrent(gl);
 | |
|     return gl.forget();
 | |
|   }
 | |
| 
 | |
|   static already_AddRefed<GLContextEGL> CreateContext() {
 | |
|     RefPtr<GLContextEGL> gl;
 | |
| #if !defined(MOZ_WIDGET_ANDROID)
 | |
|     gl = CreateContextImpl(/* aUseGles */ false);
 | |
| #endif  // !defined(MOZ_WIDGET_ANDROID)
 | |
| 
 | |
|     if (!gl) {
 | |
|       gl = CreateContextImpl(/* aUseGles */ true);
 | |
|     }
 | |
|     return gl.forget();
 | |
|   }
 | |
| 
 | |
|   static bool UnmakeCurrent(GLContextEGL* const gl) {
 | |
|     sMutex.AssertCurrentThreadOwns();
 | |
|     MOZ_ASSERT(gl);
 | |
| 
 | |
|     if (!gl->IsCurrent()) {
 | |
|       return true;
 | |
|     }
 | |
|     const auto& egl = *(gl->mEgl);
 | |
|     return egl.fMakeCurrent(EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
 | |
|   }
 | |
| 
 | |
|   static StaticMutex sMutex MOZ_UNANNOTATED;
 | |
|   static StaticRefPtr<GLContextEGL> sContext;
 | |
|   static size_t sInstanceCount;
 | |
| 
 | |
|   EGLSurface mTargetSurface;
 | |
| };
 | |
| 
 | |
| StaticMutex AndroidSharedBlitGL::sMutex;
 | |
| StaticRefPtr<GLContextEGL> AndroidSharedBlitGL::sContext;
 | |
| size_t AndroidSharedBlitGL::sInstanceCount = 0;
 | |
| 
 | |
| // -
 | |
| #ifdef MOZ_WIDGET_ANDROID
 | |
| 
 | |
| void AndroidSurfaceTexture::GetTransformMatrix(
 | |
|     java::sdk::SurfaceTexture::Param surfaceTexture,
 | |
|     gfx::Matrix4x4* outMatrix) {
 | |
|   JNIEnv* const env = jni::GetEnvForThread();
 | |
| 
 | |
|   auto jarray = jni::FloatArray::LocalRef::Adopt(env, env->NewFloatArray(16));
 | |
|   surfaceTexture->GetTransformMatrix(jarray);
 | |
| 
 | |
|   jfloat* array = env->GetFloatArrayElements(jarray.Get(), nullptr);
 | |
| 
 | |
|   memcpy(&(outMatrix->_11), array, sizeof(float) * 16);
 | |
| 
 | |
|   env->ReleaseFloatArrayElements(jarray.Get(), array, 0);
 | |
| }
 | |
| 
 | |
| class GLBlitterSupport final
 | |
|     : public java::GeckoSurfaceTexture::NativeGLBlitHelper::Natives<
 | |
|           GLBlitterSupport> {
 | |
|  public:
 | |
|   using Base =
 | |
|       java::GeckoSurfaceTexture::NativeGLBlitHelper::Natives<GLBlitterSupport>;
 | |
|   using Base::AttachNative;
 | |
|   using Base::DisposeNative;
 | |
|   using Base::GetNative;
 | |
| 
 | |
|   static java::GeckoSurfaceTexture::NativeGLBlitHelper::LocalRef NativeCreate(
 | |
|       jlong sourceTextureHandle, jni::Object::Param targetSurface, jint width,
 | |
|       jint height) {
 | |
|     AndroidNativeWindow win(java::GeckoSurface::Ref::From(targetSurface));
 | |
|     auto helper = java::GeckoSurfaceTexture::NativeGLBlitHelper::New();
 | |
|     const auto& eglWindow = win.NativeWindow();
 | |
|     GLBlitterSupport::AttachNative(
 | |
|         helper,
 | |
|         MakeUnique<GLBlitterSupport>(MakeUnique<AndroidSharedBlitGL>(eglWindow),
 | |
|                                      sourceTextureHandle, width, height));
 | |
|     return helper;
 | |
|   }
 | |
| 
 | |
|   GLBlitterSupport(UniquePtr<AndroidSharedBlitGL>&& gl,
 | |
|                    jlong sourceTextureHandle, jint width, jint height)
 | |
|       : mGl(std::move(gl)),
 | |
|         mSourceTextureHandle(sourceTextureHandle),
 | |
|         mSize(width, height) {}
 | |
| 
 | |
|   void Blit() {
 | |
|     auto surfaceTexture =
 | |
|         java::GeckoSurfaceTexture::Lookup(mSourceTextureHandle);
 | |
|     mGl->Blit(surfaceTexture, mSize);
 | |
|   }
 | |
| 
 | |
|  private:
 | |
|   const UniquePtr<AndroidSharedBlitGL> mGl;
 | |
|   const AndroidSurfaceTextureHandle mSourceTextureHandle;
 | |
|   const gfx::IntSize mSize;
 | |
| };
 | |
| 
 | |
| void AndroidSurfaceTexture::Init() { GLBlitterSupport::Init(); }
 | |
| 
 | |
| #endif  // MOZ_WIDGET_ANDROID
 | |
| 
 | |
| }  // namespace gl
 | |
| }  // namespace mozilla
 |