blob: 3600b76fa665a5234014634f8c57d6ef97d59ef5 [file] [log] [blame]
Jamie Gennis6714efc2010-12-20 12:09:37 -08001/*
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
Andy McFaddend47f7d82012-12-18 09:48:38 -080021#include <gui/GLConsumer.h>
Mathias Agopian52800612013-02-14 17:11:20 -080022#include <gui/Surface.h>
Jamie Gennis6714efc2010-12-20 12:09:37 -080023
24#include <android_runtime/AndroidRuntime.h>
25
26#include <utils/Log.h>
27#include <utils/misc.h>
28
Jamie Gennis6714efc2010-12-20 12:09:37 -080029#include "jni.h"
Jamie Gennis376590d2011-01-13 14:43:36 -080030#include "JNIHelp.h"
Jamie Gennis6714efc2010-12-20 12:09:37 -080031
32// ----------------------------------------------------------------------------
33
34namespace android {
35
36static const char* const OutOfResourcesException =
37 "android/graphics/SurfaceTexture$OutOfResourcesException";
Jamie Gennis2b4bfa52012-04-13 14:48:22 -070038static const char* const IllegalStateException = "java/lang/IllegalStateException";
tedbo05031612011-06-06 16:02:47 -070039const char* const kSurfaceTextureClassPathName = "android/graphics/SurfaceTexture";
Jamie Gennis6714efc2010-12-20 12:09:37 -080040
Jamie Gennis376590d2011-01-13 14:43:36 -080041struct fields_t {
42 jfieldID surfaceTexture;
Igor Murashkinc99db2b2012-10-29 13:38:10 -070043 jfieldID frameAvailableListener;
Jamie Gennis376590d2011-01-13 14:43:36 -080044 jmethodID postEvent;
Jamie Gennis6714efc2010-12-20 12:09:37 -080045};
Jamie Gennis376590d2011-01-13 14:43:36 -080046static fields_t fields;
Jamie Gennis6714efc2010-12-20 12:09:37 -080047
48// ----------------------------------------------------------------------------
49
Jamie Gennis376590d2011-01-13 14:43:36 -080050static void SurfaceTexture_setSurfaceTexture(JNIEnv* env, jobject thiz,
Andy McFaddend47f7d82012-12-18 09:48:38 -080051 const sp<GLConsumer>& surfaceTexture)
Jamie Gennis6714efc2010-12-20 12:09:37 -080052{
Andy McFaddend47f7d82012-12-18 09:48:38 -080053 GLConsumer* const p =
54 (GLConsumer*)env->GetIntField(thiz, fields.surfaceTexture);
Jamie Gennis6714efc2010-12-20 12:09:37 -080055 if (surfaceTexture.get()) {
Mathias Agopianb1d90c82013-03-06 17:45:42 -080056 surfaceTexture->incStrong((void*)SurfaceTexture_setSurfaceTexture);
Jamie Gennis6714efc2010-12-20 12:09:37 -080057 }
58 if (p) {
Mathias Agopianb1d90c82013-03-06 17:45:42 -080059 p->decStrong((void*)SurfaceTexture_setSurfaceTexture);
Jamie Gennis6714efc2010-12-20 12:09:37 -080060 }
Jamie Gennis376590d2011-01-13 14:43:36 -080061 env->SetIntField(thiz, fields.surfaceTexture, (int)surfaceTexture.get());
Jamie Gennis6714efc2010-12-20 12:09:37 -080062}
63
Igor Murashkinc99db2b2012-10-29 13:38:10 -070064static void SurfaceTexture_setFrameAvailableListener(JNIEnv* env,
Andy McFaddend47f7d82012-12-18 09:48:38 -080065 jobject thiz, sp<GLConsumer::FrameAvailableListener> listener)
Jamie Gennis6714efc2010-12-20 12:09:37 -080066{
Andy McFaddend47f7d82012-12-18 09:48:38 -080067 GLConsumer::FrameAvailableListener* const p =
68 (GLConsumer::FrameAvailableListener*)
Igor Murashkinc99db2b2012-10-29 13:38:10 -070069 env->GetIntField(thiz, fields.frameAvailableListener);
70 if (listener.get()) {
Mathias Agopianb1d90c82013-03-06 17:45:42 -080071 listener->incStrong((void*)SurfaceTexture_setSurfaceTexture);
Igor Murashkinc99db2b2012-10-29 13:38:10 -070072 }
73 if (p) {
Mathias Agopianb1d90c82013-03-06 17:45:42 -080074 p->decStrong((void*)SurfaceTexture_setSurfaceTexture);
Igor Murashkinc99db2b2012-10-29 13:38:10 -070075 }
76 env->SetIntField(thiz, fields.frameAvailableListener, (int)listener.get());
77}
78
Andy McFaddend47f7d82012-12-18 09:48:38 -080079sp<GLConsumer> SurfaceTexture_getSurfaceTexture(JNIEnv* env,
Igor Murashkinc99db2b2012-10-29 13:38:10 -070080 jobject thiz)
81{
Andy McFaddend47f7d82012-12-18 09:48:38 -080082 return (GLConsumer*)env->GetIntField(thiz, fields.surfaceTexture);
Jamie Gennis6714efc2010-12-20 12:09:37 -080083}
84
Glenn Kasten846db332011-03-04 11:44:32 -080085sp<ANativeWindow> android_SurfaceTexture_getNativeWindow(
86 JNIEnv* env, jobject thiz)
87{
Andy McFaddend47f7d82012-12-18 09:48:38 -080088 sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
Mathias Agopian52800612013-02-14 17:11:20 -080089 sp<Surface> surfaceTextureClient(surfaceTexture != NULL ?
90 new Surface(surfaceTexture->getBufferQueue()) : NULL);
Glenn Kasten846db332011-03-04 11:44:32 -080091 return surfaceTextureClient;
92}
93
tedbo05031612011-06-06 16:02:47 -070094bool android_SurfaceTexture_isInstanceOf(JNIEnv* env, jobject thiz)
95{
96 jclass surfaceTextureClass = env->FindClass(kSurfaceTextureClassPathName);
97 return env->IsInstanceOf(thiz, surfaceTextureClass);
98}
99
Jamie Gennis6714efc2010-12-20 12:09:37 -0800100// ----------------------------------------------------------------------------
101
Andy McFaddend47f7d82012-12-18 09:48:38 -0800102class JNISurfaceTextureContext : public GLConsumer::FrameAvailableListener
Jamie Gennis6714efc2010-12-20 12:09:37 -0800103{
Jamie Gennis376590d2011-01-13 14:43:36 -0800104public:
105 JNISurfaceTextureContext(JNIEnv* env, jobject weakThiz, jclass clazz);
106 virtual ~JNISurfaceTextureContext();
107 virtual void onFrameAvailable();
Jamie Gennis6714efc2010-12-20 12:09:37 -0800108
Jamie Gennis376590d2011-01-13 14:43:36 -0800109private:
Jamie Gennis0a8fd9b2011-06-20 18:39:35 -0700110 static JNIEnv* getJNIEnv(bool* needsDetach);
111 static void detachJNI();
Jamie Gennis84293fb2011-06-17 16:35:35 -0700112
Jamie Gennis376590d2011-01-13 14:43:36 -0800113 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
Jamie Gennis0a8fd9b2011-06-20 18:39:35 -0700123JNIEnv* 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) {
Steve Block3762c312012-01-06 19:20:56 +0000131 ALOGE("thread attach failed: %#x", result);
Jamie Gennis0a8fd9b2011-06-20 18:39:35 -0700132 return NULL;
133 }
134 *needsDetach = true;
Jamie Gennis84293fb2011-06-17 16:35:35 -0700135 }
136 return env;
137}
138
Jamie Gennis0a8fd9b2011-06-20 18:39:35 -0700139void JNISurfaceTextureContext::detachJNI() {
140 JavaVM* vm = AndroidRuntime::getJavaVM();
141 int result = vm->DetachCurrentThread();
142 if (result != JNI_OK) {
Steve Block3762c312012-01-06 19:20:56 +0000143 ALOGE("thread detach failed: %#x", result);
Jamie Gennis0a8fd9b2011-06-20 18:39:35 -0700144 }
145}
146
Jamie Gennis376590d2011-01-13 14:43:36 -0800147JNISurfaceTextureContext::~JNISurfaceTextureContext()
148{
Jamie Gennis0a8fd9b2011-06-20 18:39:35 -0700149 bool needsDetach = false;
150 JNIEnv* env = getJNIEnv(&needsDetach);
Jamie Gennis84293fb2011-06-17 16:35:35 -0700151 if (env != NULL) {
152 env->DeleteGlobalRef(mWeakThiz);
153 env->DeleteGlobalRef(mClazz);
154 } else {
Steve Block8564c8d2012-01-05 23:22:43 +0000155 ALOGW("leaking JNI object references");
Jamie Gennis84293fb2011-06-17 16:35:35 -0700156 }
Jamie Gennis0a8fd9b2011-06-20 18:39:35 -0700157 if (needsDetach) {
158 detachJNI();
159 }
Jamie Gennis6714efc2010-12-20 12:09:37 -0800160}
161
Jamie Gennis376590d2011-01-13 14:43:36 -0800162void JNISurfaceTextureContext::onFrameAvailable()
Jamie Gennis6714efc2010-12-20 12:09:37 -0800163{
Jamie Gennis0a8fd9b2011-06-20 18:39:35 -0700164 bool needsDetach = false;
165 JNIEnv* env = getJNIEnv(&needsDetach);
Jamie Gennis84293fb2011-06-17 16:35:35 -0700166 if (env != NULL) {
167 env->CallStaticVoidMethod(mClazz, fields.postEvent, mWeakThiz);
168 } else {
Steve Block8564c8d2012-01-05 23:22:43 +0000169 ALOGW("onFrameAvailable event will not posted");
Jamie Gennis84293fb2011-06-17 16:35:35 -0700170 }
Jamie Gennis0a8fd9b2011-06-20 18:39:35 -0700171 if (needsDetach) {
172 detachJNI();
173 }
Jamie Gennis376590d2011-01-13 14:43:36 -0800174}
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) {
Steve Block3762c312012-01-06 19:20:56 +0000183 ALOGE("can't find android/graphics/SurfaceTexture.%s",
Jamie Gennis376590d2011-01-13 14:43:36 -0800184 ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID);
185 }
Igor Murashkinc99db2b2012-10-29 13:38:10 -0700186 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 }
Jamie Gennis376590d2011-01-13 14:43:36 -0800192
193 fields.postEvent = env->GetStaticMethodID(clazz, "postEventFromNative",
194 "(Ljava/lang/Object;)V");
195 if (fields.postEvent == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000196 ALOGE("can't find android/graphics/SurfaceTexture.postEventFromNative");
Jamie Gennis376590d2011-01-13 14:43:36 -0800197 }
Jamie Gennis376590d2011-01-13 14:43:36 -0800198}
199
200static void SurfaceTexture_init(JNIEnv* env, jobject thiz, jint texName,
Grace Kloba0904d0a2011-06-23 21:21:47 -0700201 jobject weakThiz, jboolean allowSynchronous)
Jamie Gennis376590d2011-01-13 14:43:36 -0800202{
Mathias Agopianb5509292013-07-12 22:06:31 -0700203 sp<BufferQueue> bq = new BufferQueue(allowSynchronous);
204 sp<GLConsumer> surfaceTexture(new GLConsumer(bq, texName));
Jamie Gennis376590d2011-01-13 14:43:36 -0800205 if (surfaceTexture == 0) {
206 jniThrowException(env, OutOfResourcesException,
207 "Unable to create native SurfaceTexture");
208 return;
209 }
210 SurfaceTexture_setSurfaceTexture(env, thiz, surfaceTexture);
211
212 jclass clazz = env->GetObjectClass(thiz);
213 if (clazz == NULL) {
214 jniThrowRuntimeException(env,
215 "Can't find android/graphics/SurfaceTexture");
216 return;
217 }
218
219 sp<JNISurfaceTextureContext> ctx(new JNISurfaceTextureContext(env, weakThiz,
220 clazz));
221 surfaceTexture->setFrameAvailableListener(ctx);
Igor Murashkinc99db2b2012-10-29 13:38:10 -0700222 SurfaceTexture_setFrameAvailableListener(env, thiz, ctx);
Jamie Gennis376590d2011-01-13 14:43:36 -0800223}
224
225static void SurfaceTexture_finalize(JNIEnv* env, jobject thiz)
226{
Andy McFaddend47f7d82012-12-18 09:48:38 -0800227 sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
Jamie Gennis376590d2011-01-13 14:43:36 -0800228 surfaceTexture->setFrameAvailableListener(0);
Igor Murashkinc99db2b2012-10-29 13:38:10 -0700229 SurfaceTexture_setFrameAvailableListener(env, thiz, 0);
Jamie Gennis376590d2011-01-13 14:43:36 -0800230 SurfaceTexture_setSurfaceTexture(env, thiz, 0);
231}
232
tedbo05031612011-06-06 16:02:47 -0700233static void SurfaceTexture_setDefaultBufferSize(
234 JNIEnv* env, jobject thiz, jint width, jint height)
235{
Andy McFaddend47f7d82012-12-18 09:48:38 -0800236 sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
tedbo05031612011-06-06 16:02:47 -0700237 surfaceTexture->setDefaultBufferSize(width, height);
238}
239
Jamie Gennis2b4bfa52012-04-13 14:48:22 -0700240static void SurfaceTexture_updateTexImage(JNIEnv* env, jobject thiz)
Jamie Gennis376590d2011-01-13 14:43:36 -0800241{
Andy McFaddend47f7d82012-12-18 09:48:38 -0800242 sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
Jamie Gennis2b4bfa52012-04-13 14:48:22 -0700243 status_t err = surfaceTexture->updateTexImage();
244 if (err == INVALID_OPERATION) {
245 jniThrowException(env, IllegalStateException, "Unable to update texture contents (see "
246 "logcat for details)");
Jamie Gennis721bfaa62012-04-13 19:14:37 -0700247 } else if (err < 0) {
Jamie Gennis2b4bfa52012-04-13 14:48:22 -0700248 jniThrowRuntimeException(env, "Error during updateTexImage (see logcat for details)");
249 }
Jamie Gennis6714efc2010-12-20 12:09:37 -0800250}
251
Jamie Gennisc6d99302012-04-05 11:34:02 -0700252static jint SurfaceTexture_detachFromGLContext(JNIEnv* env, jobject thiz)
253{
Andy McFaddend47f7d82012-12-18 09:48:38 -0800254 sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
Jamie Gennisc6d99302012-04-05 11:34:02 -0700255 return surfaceTexture->detachFromContext();
256}
257
258static jint SurfaceTexture_attachToGLContext(JNIEnv* env, jobject thiz, jint tex)
259{
Andy McFaddend47f7d82012-12-18 09:48:38 -0800260 sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
Jamie Gennisc6d99302012-04-05 11:34:02 -0700261 return surfaceTexture->attachToContext((GLuint)tex);
262}
263
Jamie Gennis376590d2011-01-13 14:43:36 -0800264static void SurfaceTexture_getTransformMatrix(JNIEnv* env, jobject thiz,
Jamie Gennisb0ba48c2011-01-09 18:22:05 -0800265 jfloatArray jmtx)
266{
Andy McFaddend47f7d82012-12-18 09:48:38 -0800267 sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
Jamie Gennisb0ba48c2011-01-09 18:22:05 -0800268 float* mtx = env->GetFloatArrayElements(jmtx, NULL);
269 surfaceTexture->getTransformMatrix(mtx);
270 env->ReleaseFloatArrayElements(jmtx, mtx, 0);
271}
272
Eino-Ville Talvalac5f94d82011-02-18 11:02:42 -0800273static jlong SurfaceTexture_getTimestamp(JNIEnv* env, jobject thiz)
274{
Andy McFaddend47f7d82012-12-18 09:48:38 -0800275 sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
Eino-Ville Talvalac5f94d82011-02-18 11:02:42 -0800276 return surfaceTexture->getTimestamp();
277}
278
Mathias Agopianec46b4e2011-08-03 15:18:36 -0700279static void SurfaceTexture_release(JNIEnv* env, jobject thiz)
280{
Andy McFaddend47f7d82012-12-18 09:48:38 -0800281 sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
Mathias Agopianec46b4e2011-08-03 15:18:36 -0700282 surfaceTexture->abandon();
283}
284
Jamie Gennis6714efc2010-12-20 12:09:37 -0800285// ----------------------------------------------------------------------------
286
Jamie Gennis6714efc2010-12-20 12:09:37 -0800287static JNINativeMethod gSurfaceTextureMethods[] = {
Jamie Gennisc6d99302012-04-05 11:34:02 -0700288 {"nativeClassInit", "()V", (void*)SurfaceTexture_classInit },
289 {"nativeInit", "(ILjava/lang/Object;Z)V", (void*)SurfaceTexture_init },
290 {"nativeFinalize", "()V", (void*)SurfaceTexture_finalize },
tedbo05031612011-06-06 16:02:47 -0700291 {"nativeSetDefaultBufferSize", "(II)V", (void*)SurfaceTexture_setDefaultBufferSize },
Jamie Gennis2b4bfa52012-04-13 14:48:22 -0700292 {"nativeUpdateTexImage", "()V", (void*)SurfaceTexture_updateTexImage },
Jamie Gennisc6d99302012-04-05 11:34:02 -0700293 {"nativeDetachFromGLContext", "()I", (void*)SurfaceTexture_detachFromGLContext },
294 {"nativeAttachToGLContext", "(I)I", (void*)SurfaceTexture_attachToGLContext },
295 {"nativeGetTransformMatrix", "([F)V", (void*)SurfaceTexture_getTransformMatrix },
296 {"nativeGetTimestamp", "()J", (void*)SurfaceTexture_getTimestamp },
297 {"nativeRelease", "()V", (void*)SurfaceTexture_release },
Jamie Gennis6714efc2010-12-20 12:09:37 -0800298};
299
Jamie Gennis6714efc2010-12-20 12:09:37 -0800300int register_android_graphics_SurfaceTexture(JNIEnv* env)
301{
302 int err = 0;
303 err = AndroidRuntime::registerNativeMethods(env, kSurfaceTextureClassPathName,
304 gSurfaceTextureMethods, NELEM(gSurfaceTextureMethods));
305 return err;
306}
307
308} // namespace android