SurfaceTexture.cpp revision 82bb813f112d9565faa990e32dbe833f96461892
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "SurfaceTexture" 18 19#include <stdio.h> 20 21#include <gui/SurfaceTexture.h> 22#include <gui/SurfaceTextureClient.h> 23 24#include <android_runtime/AndroidRuntime.h> 25 26#include <utils/Log.h> 27#include <utils/misc.h> 28 29#include "jni.h" 30#include "JNIHelp.h" 31 32// ---------------------------------------------------------------------------- 33 34namespace android { 35 36static const char* const OutOfResourcesException = 37 "android/graphics/SurfaceTexture$OutOfResourcesException"; 38static const char* const IllegalStateException = "java/lang/IllegalStateException"; 39const char* const kSurfaceTextureClassPathName = "android/graphics/SurfaceTexture"; 40 41struct fields_t { 42 jfieldID surfaceTexture; 43 jfieldID frameAvailableListener; 44 jmethodID postEvent; 45}; 46static fields_t fields; 47 48// ---------------------------------------------------------------------------- 49 50static void SurfaceTexture_setSurfaceTexture(JNIEnv* env, jobject thiz, 51 const sp<SurfaceTexture>& surfaceTexture) 52{ 53 SurfaceTexture* const p = 54 (SurfaceTexture*)env->GetIntField(thiz, fields.surfaceTexture); 55 if (surfaceTexture.get()) { 56 surfaceTexture->incStrong(thiz); 57 } 58 if (p) { 59 p->decStrong(thiz); 60 } 61 env->SetIntField(thiz, fields.surfaceTexture, (int)surfaceTexture.get()); 62} 63 64static void SurfaceTexture_setFrameAvailableListener(JNIEnv* env, 65 jobject thiz, sp<SurfaceTexture::FrameAvailableListener> listener) 66{ 67 SurfaceTexture::FrameAvailableListener* const p = 68 (SurfaceTexture::FrameAvailableListener*) 69 env->GetIntField(thiz, fields.frameAvailableListener); 70 if (listener.get()) { 71 listener->incStrong(thiz); 72 } 73 if (p) { 74 p->decStrong(thiz); 75 } 76 env->SetIntField(thiz, fields.frameAvailableListener, (int)listener.get()); 77} 78 79sp<SurfaceTexture> SurfaceTexture_getSurfaceTexture(JNIEnv* env, 80 jobject thiz) 81{ 82 return (SurfaceTexture*)env->GetIntField(thiz, fields.surfaceTexture); 83} 84 85sp<ANativeWindow> android_SurfaceTexture_getNativeWindow( 86 JNIEnv* env, jobject thiz) 87{ 88 sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 89 sp<SurfaceTextureClient> surfaceTextureClient(surfaceTexture != NULL ? 90 new SurfaceTextureClient(surfaceTexture->getBufferQueue()) : NULL); 91 return surfaceTextureClient; 92} 93 94bool android_SurfaceTexture_isInstanceOf(JNIEnv* env, jobject thiz) 95{ 96 jclass surfaceTextureClass = env->FindClass(kSurfaceTextureClassPathName); 97 return env->IsInstanceOf(thiz, surfaceTextureClass); 98} 99 100// ---------------------------------------------------------------------------- 101 102class JNISurfaceTextureContext : public SurfaceTexture::FrameAvailableListener 103{ 104public: 105 JNISurfaceTextureContext(JNIEnv* env, jobject weakThiz, jclass clazz); 106 virtual ~JNISurfaceTextureContext(); 107 virtual void onFrameAvailable(); 108 109private: 110 static JNIEnv* getJNIEnv(bool* needsDetach); 111 static void detachJNI(); 112 113 jobject mWeakThiz; 114 jclass mClazz; 115}; 116 117JNISurfaceTextureContext::JNISurfaceTextureContext(JNIEnv* env, 118 jobject weakThiz, jclass clazz) : 119 mWeakThiz(env->NewGlobalRef(weakThiz)), 120 mClazz((jclass)env->NewGlobalRef(clazz)) 121{} 122 123JNIEnv* JNISurfaceTextureContext::getJNIEnv(bool* needsDetach) { 124 *needsDetach = false; 125 JNIEnv* env = AndroidRuntime::getJNIEnv(); 126 if (env == NULL) { 127 JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL}; 128 JavaVM* vm = AndroidRuntime::getJavaVM(); 129 int result = vm->AttachCurrentThread(&env, (void*) &args); 130 if (result != JNI_OK) { 131 ALOGE("thread attach failed: %#x", result); 132 return NULL; 133 } 134 *needsDetach = true; 135 } 136 return env; 137} 138 139void JNISurfaceTextureContext::detachJNI() { 140 JavaVM* vm = AndroidRuntime::getJavaVM(); 141 int result = vm->DetachCurrentThread(); 142 if (result != JNI_OK) { 143 ALOGE("thread detach failed: %#x", result); 144 } 145} 146 147JNISurfaceTextureContext::~JNISurfaceTextureContext() 148{ 149 bool needsDetach = false; 150 JNIEnv* env = getJNIEnv(&needsDetach); 151 if (env != NULL) { 152 env->DeleteGlobalRef(mWeakThiz); 153 env->DeleteGlobalRef(mClazz); 154 } else { 155 ALOGW("leaking JNI object references"); 156 } 157 if (needsDetach) { 158 detachJNI(); 159 } 160} 161 162void JNISurfaceTextureContext::onFrameAvailable() 163{ 164 bool needsDetach = false; 165 JNIEnv* env = getJNIEnv(&needsDetach); 166 if (env != NULL) { 167 env->CallStaticVoidMethod(mClazz, fields.postEvent, mWeakThiz); 168 } else { 169 ALOGW("onFrameAvailable event will not posted"); 170 } 171 if (needsDetach) { 172 detachJNI(); 173 } 174} 175 176// ---------------------------------------------------------------------------- 177 178static void SurfaceTexture_classInit(JNIEnv* env, jclass clazz) 179{ 180 fields.surfaceTexture = env->GetFieldID(clazz, 181 ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID, "I"); 182 if (fields.surfaceTexture == NULL) { 183 ALOGE("can't find android/graphics/SurfaceTexture.%s", 184 ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID); 185 } 186 fields.frameAvailableListener = env->GetFieldID(clazz, 187 ANDROID_GRAPHICS_FRAMEAVAILABLELISTENER_JNI_ID, "I"); 188 if (fields.frameAvailableListener == NULL) { 189 ALOGE("can't find android/graphics/SurfaceTexture.%s", 190 ANDROID_GRAPHICS_FRAMEAVAILABLELISTENER_JNI_ID); 191 } 192 193 fields.postEvent = env->GetStaticMethodID(clazz, "postEventFromNative", 194 "(Ljava/lang/Object;)V"); 195 if (fields.postEvent == NULL) { 196 ALOGE("can't find android/graphics/SurfaceTexture.postEventFromNative"); 197 } 198} 199 200static void SurfaceTexture_init(JNIEnv* env, jobject thiz, jint texName, 201 jobject weakThiz, jboolean allowSynchronous) 202{ 203 sp<SurfaceTexture> surfaceTexture(new SurfaceTexture(texName, allowSynchronous)); 204 if (surfaceTexture == 0) { 205 jniThrowException(env, OutOfResourcesException, 206 "Unable to create native SurfaceTexture"); 207 return; 208 } 209 SurfaceTexture_setSurfaceTexture(env, thiz, surfaceTexture); 210 211 jclass clazz = env->GetObjectClass(thiz); 212 if (clazz == NULL) { 213 jniThrowRuntimeException(env, 214 "Can't find android/graphics/SurfaceTexture"); 215 return; 216 } 217 218 sp<JNISurfaceTextureContext> ctx(new JNISurfaceTextureContext(env, weakThiz, 219 clazz)); 220 surfaceTexture->setFrameAvailableListener(ctx); 221 SurfaceTexture_setFrameAvailableListener(env, thiz, ctx); 222} 223 224static void SurfaceTexture_finalize(JNIEnv* env, jobject thiz) 225{ 226 sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 227 surfaceTexture->setFrameAvailableListener(0); 228 SurfaceTexture_setFrameAvailableListener(env, thiz, 0); 229 SurfaceTexture_setSurfaceTexture(env, thiz, 0); 230} 231 232static void SurfaceTexture_setDefaultBufferSize( 233 JNIEnv* env, jobject thiz, jint width, jint height) 234{ 235 sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 236 surfaceTexture->setDefaultBufferSize(width, height); 237} 238 239static void SurfaceTexture_updateTexImage(JNIEnv* env, jobject thiz) 240{ 241 sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 242 status_t err = surfaceTexture->updateTexImage(); 243 if (err == INVALID_OPERATION) { 244 jniThrowException(env, IllegalStateException, "Unable to update texture contents (see " 245 "logcat for details)"); 246 } else if (err < 0) { 247 jniThrowRuntimeException(env, "Error during updateTexImage (see logcat for details)"); 248 } 249} 250 251static jint SurfaceTexture_detachFromGLContext(JNIEnv* env, jobject thiz) 252{ 253 sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 254 return surfaceTexture->detachFromContext(); 255} 256 257static jint SurfaceTexture_attachToGLContext(JNIEnv* env, jobject thiz, jint tex) 258{ 259 sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 260 return surfaceTexture->attachToContext((GLuint)tex); 261} 262 263static void SurfaceTexture_getTransformMatrix(JNIEnv* env, jobject thiz, 264 jfloatArray jmtx) 265{ 266 sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 267 float* mtx = env->GetFloatArrayElements(jmtx, NULL); 268 surfaceTexture->getTransformMatrix(mtx); 269 env->ReleaseFloatArrayElements(jmtx, mtx, 0); 270} 271 272static jlong SurfaceTexture_getTimestamp(JNIEnv* env, jobject thiz) 273{ 274 sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 275 return surfaceTexture->getTimestamp(); 276} 277 278static void SurfaceTexture_release(JNIEnv* env, jobject thiz) 279{ 280 sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 281 surfaceTexture->abandon(); 282} 283 284// ---------------------------------------------------------------------------- 285 286static JNINativeMethod gSurfaceTextureMethods[] = { 287 {"nativeClassInit", "()V", (void*)SurfaceTexture_classInit }, 288 {"nativeInit", "(ILjava/lang/Object;Z)V", (void*)SurfaceTexture_init }, 289 {"nativeFinalize", "()V", (void*)SurfaceTexture_finalize }, 290 {"nativeSetDefaultBufferSize", "(II)V", (void*)SurfaceTexture_setDefaultBufferSize }, 291 {"nativeUpdateTexImage", "()V", (void*)SurfaceTexture_updateTexImage }, 292 {"nativeDetachFromGLContext", "()I", (void*)SurfaceTexture_detachFromGLContext }, 293 {"nativeAttachToGLContext", "(I)I", (void*)SurfaceTexture_attachToGLContext }, 294 {"nativeGetTransformMatrix", "([F)V", (void*)SurfaceTexture_getTransformMatrix }, 295 {"nativeGetTimestamp", "()J", (void*)SurfaceTexture_getTimestamp }, 296 {"nativeRelease", "()V", (void*)SurfaceTexture_release }, 297}; 298 299int register_android_graphics_SurfaceTexture(JNIEnv* env) 300{ 301 int err = 0; 302 err = AndroidRuntime::registerNativeMethods(env, kSurfaceTextureClassPathName, 303 gSurfaceTextureMethods, NELEM(gSurfaceTextureMethods)); 304 return err; 305} 306 307} // namespace android 308