1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/thebes/nsSurfaceTexture.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,247 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +// vim:set ts=2 sts=2 sw=2 et cin: 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifdef MOZ_WIDGET_ANDROID 1.11 + 1.12 +#include <set> 1.13 +#include <map> 1.14 +#include <android/log.h> 1.15 +#include "nsSurfaceTexture.h" 1.16 +#include "AndroidBridge.h" 1.17 +#include "nsThreadUtils.h" 1.18 +#include "mozilla/gfx/Matrix.h" 1.19 + 1.20 +using namespace mozilla; 1.21 + 1.22 +// UGH 1.23 +static std::map<int, nsSurfaceTexture*> sInstances; 1.24 +static int sNextID = 0; 1.25 + 1.26 +static class JNIFunctions { 1.27 +public: 1.28 + 1.29 + JNIFunctions() : mInitialized(false) 1.30 + { 1.31 + } 1.32 + 1.33 + bool EnsureInitialized() 1.34 + { 1.35 + if (mInitialized) 1.36 + return true; 1.37 + 1.38 + JNIEnv* env = GetJNIForThread(); 1.39 + 1.40 + AutoLocalJNIFrame jniFrame(env); 1.41 + 1.42 + jSurfaceTextureClass = (jclass)env->NewGlobalRef(env->FindClass("android/graphics/SurfaceTexture")); 1.43 + jSurfaceTexture_Ctor = env->GetMethodID(jSurfaceTextureClass, "<init>", "(I)V"); 1.44 + jSurfaceTexture_updateTexImage = env->GetMethodID(jSurfaceTextureClass, "updateTexImage", "()V"); 1.45 + jSurfaceTexture_getTransformMatrix = env->GetMethodID(jSurfaceTextureClass, "getTransformMatrix", "([F)V"); 1.46 + 1.47 + mInitialized = true; 1.48 + return true; 1.49 + } 1.50 + 1.51 + jobject CreateSurfaceTexture(GLuint aTexture) 1.52 + { 1.53 + if (!EnsureInitialized()) 1.54 + return nullptr; 1.55 + 1.56 + JNIEnv* env = GetJNIForThread(); 1.57 + 1.58 + AutoLocalJNIFrame jniFrame(env); 1.59 + 1.60 + return env->NewGlobalRef(env->NewObject(jSurfaceTextureClass, jSurfaceTexture_Ctor, (int) aTexture)); 1.61 + } 1.62 + 1.63 + void ReleaseSurfaceTexture(jobject aSurfaceTexture) 1.64 + { 1.65 + JNIEnv* env = GetJNIForThread(); 1.66 + 1.67 + env->DeleteGlobalRef(aSurfaceTexture); 1.68 + } 1.69 + 1.70 + void UpdateTexImage(jobject aSurfaceTexture) 1.71 + { 1.72 + JNIEnv* env = GetJNIForThread(); 1.73 + 1.74 + AutoLocalJNIFrame jniFrame(env); 1.75 + env->CallVoidMethod(aSurfaceTexture, jSurfaceTexture_updateTexImage); 1.76 + } 1.77 + 1.78 + bool GetTransformMatrix(jobject aSurfaceTexture, gfx::Matrix4x4& aMatrix) 1.79 + { 1.80 + JNIEnv* env = GetJNIForThread(); 1.81 + 1.82 + AutoLocalJNIFrame jniFrame(env); 1.83 + 1.84 + jfloatArray jarray = env->NewFloatArray(16); 1.85 + env->CallVoidMethod(aSurfaceTexture, jSurfaceTexture_getTransformMatrix, jarray); 1.86 + 1.87 + jfloat* array = env->GetFloatArrayElements(jarray, nullptr); 1.88 + 1.89 + aMatrix._11 = array[0]; 1.90 + aMatrix._12 = array[1]; 1.91 + aMatrix._13 = array[2]; 1.92 + aMatrix._14 = array[3]; 1.93 + 1.94 + aMatrix._21 = array[4]; 1.95 + aMatrix._22 = array[5]; 1.96 + aMatrix._23 = array[6]; 1.97 + aMatrix._24 = array[7]; 1.98 + 1.99 + aMatrix._31 = array[8]; 1.100 + aMatrix._32 = array[9]; 1.101 + aMatrix._33 = array[10]; 1.102 + aMatrix._34 = array[11]; 1.103 + 1.104 + aMatrix._41 = array[12]; 1.105 + aMatrix._42 = array[13]; 1.106 + aMatrix._43 = array[14]; 1.107 + aMatrix._44 = array[15]; 1.108 + 1.109 + env->ReleaseFloatArrayElements(jarray, array, 0); 1.110 + 1.111 + return false; 1.112 + } 1.113 + 1.114 +private: 1.115 + bool mInitialized; 1.116 + 1.117 + jclass jSurfaceTextureClass; 1.118 + jmethodID jSurfaceTexture_Ctor; 1.119 + jmethodID jSurfaceTexture_updateTexImage; 1.120 + jmethodID jSurfaceTexture_getTransformMatrix; 1.121 + 1.122 +} sJNIFunctions; 1.123 + 1.124 +nsSurfaceTexture* 1.125 +nsSurfaceTexture::Create(GLuint aTexture) 1.126 +{ 1.127 + // Right now we only support creating this on the main thread because 1.128 + // of the JNIEnv assumptions in JNIHelper and elsewhere 1.129 + if (!NS_IsMainThread()) 1.130 + return nullptr; 1.131 + 1.132 + nsSurfaceTexture* st = new nsSurfaceTexture(); 1.133 + if (!st->Init(aTexture)) { 1.134 + printf_stderr("Failed to initialize nsSurfaceTexture"); 1.135 + delete st; 1.136 + st = nullptr; 1.137 + } 1.138 + 1.139 + return st; 1.140 +} 1.141 + 1.142 +nsSurfaceTexture* 1.143 +nsSurfaceTexture::Find(int id) 1.144 +{ 1.145 + std::map<int, nsSurfaceTexture*>::iterator it; 1.146 + 1.147 + it = sInstances.find(id); 1.148 + if (it == sInstances.end()) 1.149 + return nullptr; 1.150 + 1.151 + return it->second; 1.152 +} 1.153 + 1.154 +bool 1.155 +nsSurfaceTexture::Check() 1.156 +{ 1.157 + return sJNIFunctions.EnsureInitialized(); 1.158 +} 1.159 + 1.160 +bool 1.161 +nsSurfaceTexture::Init(GLuint aTexture) 1.162 +{ 1.163 + if (!sJNIFunctions.EnsureInitialized()) 1.164 + return false; 1.165 + 1.166 + JNIEnv* env = GetJNIForThread(); 1.167 + 1.168 + mSurfaceTexture = sJNIFunctions.CreateSurfaceTexture(aTexture); 1.169 + if (!mSurfaceTexture) 1.170 + return false; 1.171 + 1.172 + mNativeWindow = AndroidBridge::Bridge()->AcquireNativeWindowFromSurfaceTexture(env, mSurfaceTexture); 1.173 + 1.174 + mID = ++sNextID; 1.175 + sInstances.insert(std::pair<int, nsSurfaceTexture*>(mID, this)); 1.176 + 1.177 + return true; 1.178 +} 1.179 + 1.180 +nsSurfaceTexture::nsSurfaceTexture() 1.181 + : mSurfaceTexture(nullptr), mNativeWindow(nullptr) 1.182 +{ 1.183 +} 1.184 + 1.185 +nsSurfaceTexture::~nsSurfaceTexture() 1.186 +{ 1.187 + sInstances.erase(mID); 1.188 + 1.189 + mFrameAvailableCallback = nullptr; 1.190 + 1.191 + if (mNativeWindow) { 1.192 + AndroidBridge::Bridge()->ReleaseNativeWindowForSurfaceTexture(mSurfaceTexture); 1.193 + mNativeWindow = nullptr; 1.194 + } 1.195 + 1.196 + JNIEnv* env = GetJNIForThread(); 1.197 + 1.198 + if (mSurfaceTexture) { 1.199 + mozilla::widget::android::GeckoAppShell::UnregisterSurfaceTextureFrameListener(mSurfaceTexture); 1.200 + 1.201 + env->DeleteGlobalRef(mSurfaceTexture); 1.202 + mSurfaceTexture = nullptr; 1.203 + } 1.204 +} 1.205 + 1.206 +void* 1.207 +nsSurfaceTexture::GetNativeWindow() 1.208 +{ 1.209 + return mNativeWindow; 1.210 +} 1.211 + 1.212 +void 1.213 +nsSurfaceTexture::UpdateTexImage() 1.214 +{ 1.215 + sJNIFunctions.UpdateTexImage(mSurfaceTexture); 1.216 +} 1.217 + 1.218 +bool 1.219 +nsSurfaceTexture::GetTransformMatrix(gfx::Matrix4x4& aMatrix) 1.220 +{ 1.221 + return sJNIFunctions.GetTransformMatrix(mSurfaceTexture, aMatrix); 1.222 +} 1.223 + 1.224 +void 1.225 +nsSurfaceTexture::SetFrameAvailableCallback(nsIRunnable* aRunnable) 1.226 +{ 1.227 + if (aRunnable) 1.228 + mozilla::widget::android::GeckoAppShell::RegisterSurfaceTextureFrameListener(mSurfaceTexture, mID); 1.229 + else 1.230 + mozilla::widget::android::GeckoAppShell::UnregisterSurfaceTextureFrameListener(mSurfaceTexture); 1.231 + 1.232 + mFrameAvailableCallback = aRunnable; 1.233 +} 1.234 + 1.235 +void 1.236 +nsSurfaceTexture::NotifyFrameAvailable() 1.237 +{ 1.238 + if (mFrameAvailableCallback) { 1.239 + // Proxy to main thread if we aren't on it 1.240 + if (!NS_IsMainThread()) { 1.241 + // Proxy to main thread 1.242 + nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &nsSurfaceTexture::NotifyFrameAvailable); 1.243 + NS_DispatchToCurrentThread(event); 1.244 + } else { 1.245 + mFrameAvailableCallback->Run(); 1.246 + } 1.247 + } 1.248 +} 1.249 + 1.250 +#endif // MOZ_WIDGET_ANDROID