Skip to content

Commit

Permalink
Bug 1486659 - p2: expose native GL blitter to Java. r=snorp
Browse files Browse the repository at this point in the history
  • Loading branch information
jhlin committed Dec 14, 2018
1 parent 53acaf1 commit 2f457e4
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 0 deletions.
150 changes: 150 additions & 0 deletions gfx/gl/AndroidSurfaceTexture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
1 change: 1 addition & 0 deletions gfx/gl/AndroidSurfaceTexture.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ namespace gl {

class AndroidSurfaceTexture {
public:
static void Init();
static void GetTransformMatrix(
java::sdk::SurfaceTexture::Param surfaceTexture,
mozilla::gfx::Matrix4x4* outMatrix);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
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";
Expand All @@ -36,6 +37,8 @@
private AtomicInteger mUseCount;
private boolean mFinalized;

private NativeGLBlitHelper mBlitter;

private GeckoSurfaceTexture(int handle) {
super(0);
init(handle, false);
Expand Down Expand Up @@ -122,6 +125,9 @@ public synchronized void updateTexImage() {

@Override
public synchronized void release() {
if (mBlitter != null) {
mBlitter.disposeNative();
}
try {
super.release();
synchronized (sSurfaceTextures) {
Expand Down Expand Up @@ -276,8 +282,28 @@ public static GeckoSurfaceTexture lookup(int handle) {
}
}

/* 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();
}
}
2 changes: 2 additions & 0 deletions widget/android/nsAppShell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

#include "AndroidBridge.h"
#include "AndroidBridgeUtilities.h"
#include "AndroidSurfaceTexture.h"
#include "GeneratedJNINatives.h"
#include <android/log.h>
#include <pthread.h>
Expand Down Expand Up @@ -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();
Expand Down

0 comments on commit 2f457e4

Please sign in to comment.