Bug 1486659 - p2: expose native GL blitter to Java. r=snorp

Differential Revision: https://phabricator.services.mozilla.com/D11938

--HG--
extra : moz-landing-system : lando
This commit is contained in:
John Lin 2018-12-14 21:34:11 +00:00
Родитель a1926ace73
Коммит 82531b5e45
4 изменённых файлов: 179 добавлений и 0 удалений

Просмотреть файл

@ -8,6 +8,13 @@
#include "AndroidSurfaceTexture.h"
#include "GeneratedJNINatives.h"
#include "AndroidNativeWindow.h"
#include "GLContextEGL.h"
#include "GLBlitHelper.h"
#include "GLImages.h"
using namespace mozilla;
namespace mozilla {
@ -28,6 +35,149 @@ void AndroidSurfaceTexture::GetTransformMatrix(
env->ReleaseFloatArrayElements(jarray.Get(), array, 0);
}
class SharedGL {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedGL);
SharedGL(AndroidNativeWindow& window) {
MutexAutoLock lock(sMutex);
if (!sContext) {
MOZ_ASSERT(sInstanceCount == 0);
sContext = CreateContext();
if (!sContext) {
return;
}
}
InitSurface(window);
++sInstanceCount;
}
void Blit(const AndroidSurfaceTextureHandle& sourceTextureHandle,
const gfx::IntSize& imageSize) {
MutexAutoLock lock(sMutex);
MOZ_ASSERT(sContext);
// Setting overide also makes conext and surface current.
sContext->SetEGLSurfaceOverride(mTargetSurface);
RefPtr<layers::SurfaceTextureImage> img = new layers::SurfaceTextureImage(
sourceTextureHandle, imageSize, false, OriginPos::TopLeft);
sContext->BlitHelper()->BlitImage(img, imageSize, OriginPos::BottomLeft);
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);
}
private:
~SharedGL() {
MutexAutoLock lock(sMutex);
if (mTargetSurface != EGL_NO_SURFACE) {
GLLibraryEGL::Get()->fDestroySurface(EGL_DISPLAY(), mTargetSurface);
}
// Destroy shared GL context when no one uses it.
if (--sInstanceCount == 0) {
sContext = nullptr;
}
}
static already_AddRefed<GLContextEGL> CreateContext() {
sMutex.AssertCurrentThreadOwns();
MOZ_ASSERT(!sContext);
auto* egl = gl::GLLibraryEGL::Get();
EGLDisplay eglDisplay = egl->fGetDisplay(EGL_DEFAULT_DISPLAY);
EGLConfig eglConfig;
CreateConfig(&eglConfig, /* bpp */ 24, /* depth buffer? */ false);
EGLint attributes[] = {LOCAL_EGL_CONTEXT_CLIENT_VERSION, 2, LOCAL_EGL_NONE};
EGLContext eglContext =
egl->fCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, attributes);
RefPtr<GLContextEGL> gl = new GLContextEGL(
CreateContextFlags::NONE, SurfaceCaps::Any(),
/* offscreen? */ false, eglConfig, EGL_NO_SURFACE, eglContext);
if (!gl->Init()) {
NS_WARNING("Fail to create GL context for native blitter.");
return nullptr;
}
// Yield the current state made in constructor.
UnmakeCurrent(gl);
return gl.forget();
}
void InitSurface(AndroidNativeWindow& window) {
sMutex.AssertCurrentThreadOwns();
MOZ_ASSERT(sContext);
mTargetSurface = gl::GLLibraryEGL::Get()->fCreateWindowSurface(
sContext->GetEGLDisplay(), sContext->mConfig, window.NativeWindow(), 0);
}
static bool UnmakeCurrent(RefPtr<GLContextEGL>& gl) {
sMutex.AssertCurrentThreadOwns();
MOZ_ASSERT(gl);
if (!gl->IsCurrent()) {
return true;
}
return gl::GLLibraryEGL::Get()->fMakeCurrent(
EGL_DISPLAY(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
}
static Mutex sMutex;
static RefPtr<GLContextEGL> sContext;
static size_t sInstanceCount;
EGLSurface mTargetSurface;
};
Mutex SharedGL::sMutex("SharedGLContext::sMutex");
RefPtr<GLContextEGL> SharedGL::sContext(nullptr);
size_t SharedGL::sInstanceCount = 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 Create(
jint sourceTextureHandle, jni::Object::Param targetSurface, jint width,
jint height) {
AndroidNativeWindow win(java::GeckoSurface::Ref::From(targetSurface));
auto helper = java::GeckoSurfaceTexture::NativeGLBlitHelper::New();
RefPtr<SharedGL> gl = new SharedGL(win);
GLBlitterSupport::AttachNative(
helper, MakeUnique<GLBlitterSupport>(std::move(gl), sourceTextureHandle,
width, height));
return helper;
}
GLBlitterSupport(RefPtr<SharedGL>&& gl, jint sourceTextureHandle, jint width,
jint height)
: mGl(gl),
mSourceTextureHandle(sourceTextureHandle),
mSize(width, height) {}
void Blit() { mGl->Blit(mSourceTextureHandle, mSize); }
private:
const RefPtr<SharedGL> mGl;
const AndroidSurfaceTextureHandle mSourceTextureHandle;
const gfx::IntSize mSize;
};
void AndroidSurfaceTexture::Init() { GLBlitterSupport::Init(); }
} // namespace gl
} // namespace mozilla
#endif // MOZ_WIDGET_ANDROID

Просмотреть файл

@ -18,6 +18,7 @@ namespace gl {
class AndroidSurfaceTexture {
public:
static void Init();
static void GetTransformMatrix(
java::sdk::SurfaceTexture::Param surfaceTexture,
mozilla::gfx::Matrix4x4* outMatrix);

Просмотреть файл

@ -15,6 +15,7 @@ import java.util.HashMap;
import java.util.LinkedList;
import org.mozilla.gecko.annotation.WrapForJNI;
import org.mozilla.gecko.mozglue.JNIObject;
/* package */ final class GeckoSurfaceTexture extends SurfaceTexture {
private static final String LOGTAG = "GeckoSurfaceTexture";
@ -36,6 +37,8 @@ import org.mozilla.gecko.annotation.WrapForJNI;
private AtomicInteger mUseCount;
private boolean mFinalized;
private NativeGLBlitHelper mBlitter;
private GeckoSurfaceTexture(int handle) {
super(0);
init(handle, false);
@ -122,6 +125,9 @@ import org.mozilla.gecko.annotation.WrapForJNI;
@Override
public synchronized void release() {
if (mBlitter != null) {
mBlitter.disposeNative();
}
try {
super.release();
synchronized (sSurfaceTextures) {
@ -276,8 +282,28 @@ import org.mozilla.gecko.annotation.WrapForJNI;
}
}
/* package */ synchronized void configureSnapshot(GeckoSurface target, int width, int height) {
mBlitter = NativeGLBlitHelper.create(mHandle, target, width, height);
}
/* package */ synchronized void takeSnapshot() {
mBlitter.blit();
}
public interface Callbacks {
void onUpdateTexImage();
void onReleaseTexImage();
}
@WrapForJNI
public static class NativeGLBlitHelper extends JNIObject {
public native static NativeGLBlitHelper create(int textureHandle,
GeckoSurface targetSurface,
int width,
int height);
public native void blit();
@Override
protected native void disposeNative();
}
}

Просмотреть файл

@ -40,6 +40,7 @@
#include "AndroidBridge.h"
#include "AndroidBridgeUtilities.h"
#include "AndroidSurfaceTexture.h"
#include "GeneratedJNINatives.h"
#include <android/log.h>
#include <pthread.h>
@ -411,6 +412,7 @@ nsAppShell::nsAppShell()
mozilla::widget::Telemetry::Init();
mozilla::widget::WebExecutorSupport::Init();
nsWindow::InitNatives();
mozilla::gl::AndroidSurfaceTexture::Init();
if (jni::IsFennec()) {
BrowserLocaleManagerSupport::Init();