2014-10-18 03:34:01 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
// vim:set ts=2 sts=2 sw=2 et cin:
|
|
|
|
/* 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/. */
|
|
|
|
|
|
|
|
#ifdef MOZ_WIDGET_ANDROID
|
|
|
|
|
|
|
|
#include <set>
|
|
|
|
#include <map>
|
|
|
|
#include <android/log.h>
|
2014-10-21 17:53:00 +04:00
|
|
|
#include "AndroidSurfaceTexture.h"
|
|
|
|
#include "gfxImageSurface.h"
|
2014-10-18 03:34:01 +04:00
|
|
|
#include "AndroidBridge.h"
|
|
|
|
#include "nsThreadUtils.h"
|
|
|
|
#include "mozilla/gfx/Matrix.h"
|
2014-10-21 17:53:00 +04:00
|
|
|
#include "GeneratedJNIWrappers.h"
|
2014-10-18 03:34:01 +04:00
|
|
|
|
|
|
|
using namespace mozilla;
|
2014-10-21 17:53:00 +04:00
|
|
|
using namespace mozilla::widget::android;
|
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
namespace gl {
|
2014-10-18 03:34:01 +04:00
|
|
|
|
|
|
|
// UGH
|
2014-10-21 17:53:00 +04:00
|
|
|
static std::map<int, AndroidSurfaceTexture*> sInstances;
|
2014-10-18 03:34:01 +04:00
|
|
|
static int sNextID = 0;
|
|
|
|
|
|
|
|
static class JNIFunctions {
|
|
|
|
public:
|
|
|
|
|
|
|
|
JNIFunctions() : mInitialized(false)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool EnsureInitialized()
|
|
|
|
{
|
|
|
|
if (mInitialized)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
JNIEnv* env = GetJNIForThread();
|
|
|
|
|
|
|
|
AutoLocalJNIFrame jniFrame(env);
|
|
|
|
|
|
|
|
jSurfaceTextureClass = (jclass)env->NewGlobalRef(env->FindClass("android/graphics/SurfaceTexture"));
|
|
|
|
jSurfaceTexture_Ctor = env->GetMethodID(jSurfaceTextureClass, "<init>", "(I)V");
|
|
|
|
jSurfaceTexture_updateTexImage = env->GetMethodID(jSurfaceTextureClass, "updateTexImage", "()V");
|
|
|
|
jSurfaceTexture_getTransformMatrix = env->GetMethodID(jSurfaceTextureClass, "getTransformMatrix", "([F)V");
|
|
|
|
|
2014-10-21 17:53:00 +04:00
|
|
|
jSurfaceClass = (jclass)env->NewGlobalRef(env->FindClass("android/view/Surface"));
|
|
|
|
jSurface_Ctor = env->GetMethodID(jSurfaceClass, "<init>", "(Landroid/graphics/SurfaceTexture;)V");
|
|
|
|
|
2014-10-18 03:34:01 +04:00
|
|
|
mInitialized = true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
jobject CreateSurfaceTexture(GLuint aTexture)
|
|
|
|
{
|
|
|
|
if (!EnsureInitialized())
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
JNIEnv* env = GetJNIForThread();
|
|
|
|
|
|
|
|
AutoLocalJNIFrame jniFrame(env);
|
|
|
|
|
|
|
|
return env->NewGlobalRef(env->NewObject(jSurfaceTextureClass, jSurfaceTexture_Ctor, (int) aTexture));
|
|
|
|
}
|
|
|
|
|
2014-10-21 17:53:00 +04:00
|
|
|
jobject CreateSurface(jobject aSurfaceTexture)
|
|
|
|
{
|
|
|
|
if (!EnsureInitialized())
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
JNIEnv* env = GetJNIForThread();
|
|
|
|
AutoLocalJNIFrame jniFrame(env);
|
|
|
|
return env->NewGlobalRef(env->NewObject(jSurfaceClass, jSurface_Ctor, aSurfaceTexture));
|
|
|
|
}
|
|
|
|
|
2014-10-18 03:34:01 +04:00
|
|
|
void ReleaseSurfaceTexture(jobject aSurfaceTexture)
|
|
|
|
{
|
|
|
|
JNIEnv* env = GetJNIForThread();
|
|
|
|
|
|
|
|
env->DeleteGlobalRef(aSurfaceTexture);
|
|
|
|
}
|
|
|
|
|
|
|
|
void UpdateTexImage(jobject aSurfaceTexture)
|
|
|
|
{
|
|
|
|
JNIEnv* env = GetJNIForThread();
|
|
|
|
|
|
|
|
AutoLocalJNIFrame jniFrame(env);
|
|
|
|
env->CallVoidMethod(aSurfaceTexture, jSurfaceTexture_updateTexImage);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool GetTransformMatrix(jobject aSurfaceTexture, gfx::Matrix4x4& aMatrix)
|
|
|
|
{
|
|
|
|
JNIEnv* env = GetJNIForThread();
|
|
|
|
|
|
|
|
AutoLocalJNIFrame jniFrame(env);
|
|
|
|
|
|
|
|
jfloatArray jarray = env->NewFloatArray(16);
|
|
|
|
env->CallVoidMethod(aSurfaceTexture, jSurfaceTexture_getTransformMatrix, jarray);
|
|
|
|
|
|
|
|
jfloat* array = env->GetFloatArrayElements(jarray, nullptr);
|
|
|
|
|
|
|
|
aMatrix._11 = array[0];
|
|
|
|
aMatrix._12 = array[1];
|
|
|
|
aMatrix._13 = array[2];
|
|
|
|
aMatrix._14 = array[3];
|
|
|
|
|
|
|
|
aMatrix._21 = array[4];
|
|
|
|
aMatrix._22 = array[5];
|
|
|
|
aMatrix._23 = array[6];
|
|
|
|
aMatrix._24 = array[7];
|
|
|
|
|
|
|
|
aMatrix._31 = array[8];
|
|
|
|
aMatrix._32 = array[9];
|
|
|
|
aMatrix._33 = array[10];
|
|
|
|
aMatrix._34 = array[11];
|
|
|
|
|
|
|
|
aMatrix._41 = array[12];
|
|
|
|
aMatrix._42 = array[13];
|
|
|
|
aMatrix._43 = array[14];
|
|
|
|
aMatrix._44 = array[15];
|
|
|
|
|
|
|
|
env->ReleaseFloatArrayElements(jarray, array, 0);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool mInitialized;
|
|
|
|
|
|
|
|
jclass jSurfaceTextureClass;
|
|
|
|
jmethodID jSurfaceTexture_Ctor;
|
|
|
|
jmethodID jSurfaceTexture_updateTexImage;
|
|
|
|
jmethodID jSurfaceTexture_getTransformMatrix;
|
|
|
|
|
2014-10-21 17:53:00 +04:00
|
|
|
jclass jSurfaceClass;
|
|
|
|
jmethodID jSurface_Ctor;
|
|
|
|
|
2014-10-18 03:34:01 +04:00
|
|
|
} sJNIFunctions;
|
|
|
|
|
2014-10-21 17:53:00 +04:00
|
|
|
AndroidSurfaceTexture*
|
|
|
|
AndroidSurfaceTexture::Create(GLuint aTexture)
|
2014-10-18 03:34:01 +04:00
|
|
|
{
|
2014-10-21 17:53:00 +04:00
|
|
|
if (AndroidBridge::Bridge()->GetAPIVersion() < 14 /* Ice Cream Sandwich */) {
|
2014-10-18 03:34:01 +04:00
|
|
|
return nullptr;
|
2014-10-21 17:53:00 +04:00
|
|
|
}
|
2014-10-18 03:34:01 +04:00
|
|
|
|
2014-10-21 17:53:00 +04:00
|
|
|
AndroidSurfaceTexture* st = new AndroidSurfaceTexture();
|
2014-10-18 03:34:01 +04:00
|
|
|
if (!st->Init(aTexture)) {
|
2014-10-21 17:53:00 +04:00
|
|
|
printf_stderr("Failed to initialize AndroidSurfaceTexture");
|
2014-10-18 03:34:01 +04:00
|
|
|
delete st;
|
|
|
|
st = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return st;
|
|
|
|
}
|
|
|
|
|
2014-10-21 17:53:00 +04:00
|
|
|
AndroidSurfaceTexture*
|
|
|
|
AndroidSurfaceTexture::Find(int id)
|
2014-10-18 03:34:01 +04:00
|
|
|
{
|
2014-10-21 17:53:00 +04:00
|
|
|
std::map<int, AndroidSurfaceTexture*>::iterator it;
|
2014-10-18 03:34:01 +04:00
|
|
|
|
|
|
|
it = sInstances.find(id);
|
|
|
|
if (it == sInstances.end())
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
return it->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2014-10-21 17:53:00 +04:00
|
|
|
AndroidSurfaceTexture::Check()
|
2014-10-18 03:34:01 +04:00
|
|
|
{
|
|
|
|
return sJNIFunctions.EnsureInitialized();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2014-10-21 17:53:00 +04:00
|
|
|
AndroidSurfaceTexture::Init(GLuint aTexture)
|
2014-10-18 03:34:01 +04:00
|
|
|
{
|
|
|
|
if (!sJNIFunctions.EnsureInitialized())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
JNIEnv* env = GetJNIForThread();
|
|
|
|
|
|
|
|
mSurfaceTexture = sJNIFunctions.CreateSurfaceTexture(aTexture);
|
2014-10-21 17:53:00 +04:00
|
|
|
if (!mSurfaceTexture) {
|
2014-10-18 03:34:01 +04:00
|
|
|
return false;
|
2014-10-21 17:53:00 +04:00
|
|
|
}
|
2014-10-18 03:34:01 +04:00
|
|
|
|
2014-10-21 17:53:00 +04:00
|
|
|
mSurface = sJNIFunctions.CreateSurface(mSurfaceTexture);
|
|
|
|
if (!mSurface) {
|
|
|
|
return false;
|
|
|
|
}
|
2014-10-18 03:34:01 +04:00
|
|
|
|
|
|
|
mID = ++sNextID;
|
2014-10-21 17:53:00 +04:00
|
|
|
sInstances.insert(std::pair<int, AndroidSurfaceTexture*>(mID, this));
|
|
|
|
|
|
|
|
mTexture = aTexture;
|
2014-10-18 03:34:01 +04:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-10-21 17:53:00 +04:00
|
|
|
AndroidSurfaceTexture::AndroidSurfaceTexture()
|
|
|
|
: mTexture(0), mSurfaceTexture(nullptr), mSurface(nullptr)
|
2014-10-18 03:34:01 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-10-21 17:53:00 +04:00
|
|
|
AndroidSurfaceTexture::~AndroidSurfaceTexture()
|
2014-10-18 03:34:01 +04:00
|
|
|
{
|
|
|
|
sInstances.erase(mID);
|
|
|
|
|
|
|
|
mFrameAvailableCallback = nullptr;
|
|
|
|
|
|
|
|
JNIEnv* env = GetJNIForThread();
|
|
|
|
|
|
|
|
if (mSurfaceTexture) {
|
2014-10-21 17:53:00 +04:00
|
|
|
GeckoAppShell::UnregisterSurfaceTextureFrameListener(mSurfaceTexture);
|
2014-10-18 03:34:01 +04:00
|
|
|
|
|
|
|
env->DeleteGlobalRef(mSurfaceTexture);
|
|
|
|
mSurfaceTexture = nullptr;
|
|
|
|
}
|
|
|
|
|
2014-10-21 17:53:00 +04:00
|
|
|
if (mSurface) {
|
|
|
|
env->DeleteGlobalRef(mSurface);
|
|
|
|
mSurface = nullptr;
|
|
|
|
}
|
2014-10-18 03:34:01 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-10-21 17:53:00 +04:00
|
|
|
AndroidSurfaceTexture::UpdateTexImage()
|
2014-10-18 03:34:01 +04:00
|
|
|
{
|
|
|
|
sJNIFunctions.UpdateTexImage(mSurfaceTexture);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2014-10-21 17:53:00 +04:00
|
|
|
AndroidSurfaceTexture::GetTransformMatrix(gfx::Matrix4x4& aMatrix)
|
2014-10-18 03:34:01 +04:00
|
|
|
{
|
|
|
|
return sJNIFunctions.GetTransformMatrix(mSurfaceTexture, aMatrix);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-10-21 17:53:00 +04:00
|
|
|
AndroidSurfaceTexture::SetFrameAvailableCallback(nsIRunnable* aRunnable)
|
2014-10-18 03:34:01 +04:00
|
|
|
{
|
|
|
|
if (aRunnable)
|
2014-10-21 17:53:00 +04:00
|
|
|
GeckoAppShell::RegisterSurfaceTextureFrameListener(mSurfaceTexture, mID);
|
2014-10-18 03:34:01 +04:00
|
|
|
else
|
2014-10-21 17:53:00 +04:00
|
|
|
GeckoAppShell::UnregisterSurfaceTextureFrameListener(mSurfaceTexture);
|
2014-10-18 03:34:01 +04:00
|
|
|
|
|
|
|
mFrameAvailableCallback = aRunnable;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-10-21 17:53:00 +04:00
|
|
|
AndroidSurfaceTexture::NotifyFrameAvailable()
|
2014-10-18 03:34:01 +04:00
|
|
|
{
|
|
|
|
if (mFrameAvailableCallback) {
|
|
|
|
// Proxy to main thread if we aren't on it
|
|
|
|
if (!NS_IsMainThread()) {
|
2014-10-21 17:53:00 +04:00
|
|
|
// Proxy to main thread
|
|
|
|
nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &AndroidSurfaceTexture::NotifyFrameAvailable);
|
2014-10-18 03:34:01 +04:00
|
|
|
NS_DispatchToCurrentThread(event);
|
|
|
|
} else {
|
|
|
|
mFrameAvailableCallback->Run();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-21 17:53:00 +04:00
|
|
|
} // gl
|
|
|
|
} // mozilla
|
|
|
|
|
2014-10-18 03:34:01 +04:00
|
|
|
#endif // MOZ_WIDGET_ANDROID
|