• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
34 namespace android {
35 
36 static const char* const OutOfResourcesException =
37     "android/graphics/SurfaceTexture$OutOfResourcesException";
38 static const char* const IllegalStateException = "java/lang/IllegalStateException";
39 const char* const kSurfaceTextureClassPathName = "android/graphics/SurfaceTexture";
40 
41 struct fields_t {
42     jfieldID  surfaceTexture;
43     jmethodID postEvent;
44 };
45 static fields_t fields;
46 
47 // ----------------------------------------------------------------------------
48 
SurfaceTexture_setSurfaceTexture(JNIEnv * env,jobject thiz,const sp<SurfaceTexture> & surfaceTexture)49 static void SurfaceTexture_setSurfaceTexture(JNIEnv* env, jobject thiz,
50         const sp<SurfaceTexture>& surfaceTexture)
51 {
52     SurfaceTexture* const p =
53         (SurfaceTexture*)env->GetIntField(thiz, fields.surfaceTexture);
54     if (surfaceTexture.get()) {
55         surfaceTexture->incStrong(thiz);
56     }
57     if (p) {
58         p->decStrong(thiz);
59     }
60     env->SetIntField(thiz, fields.surfaceTexture, (int)surfaceTexture.get());
61 }
62 
SurfaceTexture_getSurfaceTexture(JNIEnv * env,jobject thiz)63 sp<SurfaceTexture> SurfaceTexture_getSurfaceTexture(JNIEnv* env, jobject thiz)
64 {
65     sp<SurfaceTexture> surfaceTexture(
66         (SurfaceTexture*)env->GetIntField(thiz, fields.surfaceTexture));
67     return surfaceTexture;
68 }
69 
android_SurfaceTexture_getNativeWindow(JNIEnv * env,jobject thiz)70 sp<ANativeWindow> android_SurfaceTexture_getNativeWindow(
71         JNIEnv* env, jobject thiz)
72 {
73     sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
74     sp<SurfaceTextureClient> surfaceTextureClient(surfaceTexture != NULL ?
75             new SurfaceTextureClient(surfaceTexture) : NULL);
76     return surfaceTextureClient;
77 }
78 
android_SurfaceTexture_isInstanceOf(JNIEnv * env,jobject thiz)79 bool android_SurfaceTexture_isInstanceOf(JNIEnv* env, jobject thiz)
80 {
81     jclass surfaceTextureClass = env->FindClass(kSurfaceTextureClassPathName);
82     return env->IsInstanceOf(thiz, surfaceTextureClass);
83 }
84 
85 // ----------------------------------------------------------------------------
86 
87 class JNISurfaceTextureContext : public SurfaceTexture::FrameAvailableListener
88 {
89 public:
90     JNISurfaceTextureContext(JNIEnv* env, jobject weakThiz, jclass clazz);
91     virtual ~JNISurfaceTextureContext();
92     virtual void onFrameAvailable();
93 
94 private:
95     static JNIEnv* getJNIEnv(bool* needsDetach);
96     static void detachJNI();
97 
98     jobject mWeakThiz;
99     jclass mClazz;
100 };
101 
JNISurfaceTextureContext(JNIEnv * env,jobject weakThiz,jclass clazz)102 JNISurfaceTextureContext::JNISurfaceTextureContext(JNIEnv* env,
103         jobject weakThiz, jclass clazz) :
104     mWeakThiz(env->NewGlobalRef(weakThiz)),
105     mClazz((jclass)env->NewGlobalRef(clazz))
106 {}
107 
getJNIEnv(bool * needsDetach)108 JNIEnv* JNISurfaceTextureContext::getJNIEnv(bool* needsDetach) {
109     *needsDetach = false;
110     JNIEnv* env = AndroidRuntime::getJNIEnv();
111     if (env == NULL) {
112         JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL};
113         JavaVM* vm = AndroidRuntime::getJavaVM();
114         int result = vm->AttachCurrentThread(&env, (void*) &args);
115         if (result != JNI_OK) {
116             ALOGE("thread attach failed: %#x", result);
117             return NULL;
118         }
119         *needsDetach = true;
120     }
121     return env;
122 }
123 
detachJNI()124 void JNISurfaceTextureContext::detachJNI() {
125     JavaVM* vm = AndroidRuntime::getJavaVM();
126     int result = vm->DetachCurrentThread();
127     if (result != JNI_OK) {
128         ALOGE("thread detach failed: %#x", result);
129     }
130 }
131 
~JNISurfaceTextureContext()132 JNISurfaceTextureContext::~JNISurfaceTextureContext()
133 {
134     bool needsDetach = false;
135     JNIEnv* env = getJNIEnv(&needsDetach);
136     if (env != NULL) {
137         env->DeleteGlobalRef(mWeakThiz);
138         env->DeleteGlobalRef(mClazz);
139     } else {
140         ALOGW("leaking JNI object references");
141     }
142     if (needsDetach) {
143         detachJNI();
144     }
145 }
146 
onFrameAvailable()147 void JNISurfaceTextureContext::onFrameAvailable()
148 {
149     bool needsDetach = false;
150     JNIEnv* env = getJNIEnv(&needsDetach);
151     if (env != NULL) {
152         env->CallStaticVoidMethod(mClazz, fields.postEvent, mWeakThiz);
153     } else {
154         ALOGW("onFrameAvailable event will not posted");
155     }
156     if (needsDetach) {
157         detachJNI();
158     }
159 }
160 
161 // ----------------------------------------------------------------------------
162 
SurfaceTexture_classInit(JNIEnv * env,jclass clazz)163 static void SurfaceTexture_classInit(JNIEnv* env, jclass clazz)
164 {
165     fields.surfaceTexture = env->GetFieldID(clazz,
166             ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID, "I");
167     if (fields.surfaceTexture == NULL) {
168         ALOGE("can't find android/graphics/SurfaceTexture.%s",
169                 ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID);
170     }
171 
172     fields.postEvent = env->GetStaticMethodID(clazz, "postEventFromNative",
173             "(Ljava/lang/Object;)V");
174     if (fields.postEvent == NULL) {
175         ALOGE("can't find android/graphics/SurfaceTexture.postEventFromNative");
176     }
177 }
178 
SurfaceTexture_init(JNIEnv * env,jobject thiz,jint texName,jobject weakThiz,jboolean allowSynchronous)179 static void SurfaceTexture_init(JNIEnv* env, jobject thiz, jint texName,
180         jobject weakThiz, jboolean allowSynchronous)
181 {
182     sp<SurfaceTexture> surfaceTexture(new SurfaceTexture(texName, allowSynchronous));
183     if (surfaceTexture == 0) {
184         jniThrowException(env, OutOfResourcesException,
185                 "Unable to create native SurfaceTexture");
186         return;
187     }
188     SurfaceTexture_setSurfaceTexture(env, thiz, surfaceTexture);
189 
190     jclass clazz = env->GetObjectClass(thiz);
191     if (clazz == NULL) {
192         jniThrowRuntimeException(env,
193                 "Can't find android/graphics/SurfaceTexture");
194         return;
195     }
196 
197     sp<JNISurfaceTextureContext> ctx(new JNISurfaceTextureContext(env, weakThiz,
198             clazz));
199     surfaceTexture->setFrameAvailableListener(ctx);
200 }
201 
SurfaceTexture_finalize(JNIEnv * env,jobject thiz)202 static void SurfaceTexture_finalize(JNIEnv* env, jobject thiz)
203 {
204     sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
205     surfaceTexture->setFrameAvailableListener(0);
206     SurfaceTexture_setSurfaceTexture(env, thiz, 0);
207 }
208 
SurfaceTexture_setDefaultBufferSize(JNIEnv * env,jobject thiz,jint width,jint height)209 static void SurfaceTexture_setDefaultBufferSize(
210         JNIEnv* env, jobject thiz, jint width, jint height)
211 {
212     sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
213     surfaceTexture->setDefaultBufferSize(width, height);
214 }
215 
SurfaceTexture_updateTexImage(JNIEnv * env,jobject thiz)216 static void SurfaceTexture_updateTexImage(JNIEnv* env, jobject thiz)
217 {
218     sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
219     status_t err = surfaceTexture->updateTexImage();
220     if (err == INVALID_OPERATION) {
221         jniThrowException(env, IllegalStateException, "Unable to update texture contents (see "
222                 "logcat for details)");
223     } else if (err < 0) {
224         jniThrowRuntimeException(env, "Error during updateTexImage (see logcat for details)");
225     }
226 }
227 
SurfaceTexture_detachFromGLContext(JNIEnv * env,jobject thiz)228 static jint SurfaceTexture_detachFromGLContext(JNIEnv* env, jobject thiz)
229 {
230     sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
231     return surfaceTexture->detachFromContext();
232 }
233 
SurfaceTexture_attachToGLContext(JNIEnv * env,jobject thiz,jint tex)234 static jint SurfaceTexture_attachToGLContext(JNIEnv* env, jobject thiz, jint tex)
235 {
236     sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
237     return surfaceTexture->attachToContext((GLuint)tex);
238 }
239 
SurfaceTexture_getTransformMatrix(JNIEnv * env,jobject thiz,jfloatArray jmtx)240 static void SurfaceTexture_getTransformMatrix(JNIEnv* env, jobject thiz,
241         jfloatArray jmtx)
242 {
243     sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
244     float* mtx = env->GetFloatArrayElements(jmtx, NULL);
245     surfaceTexture->getTransformMatrix(mtx);
246     env->ReleaseFloatArrayElements(jmtx, mtx, 0);
247 }
248 
SurfaceTexture_getTimestamp(JNIEnv * env,jobject thiz)249 static jlong SurfaceTexture_getTimestamp(JNIEnv* env, jobject thiz)
250 {
251     sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
252     return surfaceTexture->getTimestamp();
253 }
254 
SurfaceTexture_release(JNIEnv * env,jobject thiz)255 static void SurfaceTexture_release(JNIEnv* env, jobject thiz)
256 {
257     sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
258     surfaceTexture->abandon();
259 }
260 
261 // ----------------------------------------------------------------------------
262 
263 static JNINativeMethod gSurfaceTextureMethods[] = {
264     {"nativeClassInit",            "()V",   (void*)SurfaceTexture_classInit },
265     {"nativeInit",                 "(ILjava/lang/Object;Z)V", (void*)SurfaceTexture_init },
266     {"nativeFinalize",             "()V",   (void*)SurfaceTexture_finalize },
267     {"nativeSetDefaultBufferSize", "(II)V", (void*)SurfaceTexture_setDefaultBufferSize },
268     {"nativeUpdateTexImage",       "()V",   (void*)SurfaceTexture_updateTexImage },
269     {"nativeDetachFromGLContext",  "()I",   (void*)SurfaceTexture_detachFromGLContext },
270     {"nativeAttachToGLContext",    "(I)I",   (void*)SurfaceTexture_attachToGLContext },
271     {"nativeGetTransformMatrix",   "([F)V", (void*)SurfaceTexture_getTransformMatrix },
272     {"nativeGetTimestamp",         "()J",   (void*)SurfaceTexture_getTimestamp },
273     {"nativeRelease",              "()V",   (void*)SurfaceTexture_release },
274 };
275 
register_android_graphics_SurfaceTexture(JNIEnv * env)276 int register_android_graphics_SurfaceTexture(JNIEnv* env)
277 {
278     int err = 0;
279     err = AndroidRuntime::registerNativeMethods(env, kSurfaceTextureClassPathName,
280             gSurfaceTextureMethods, NELEM(gSurfaceTextureMethods));
281     return err;
282 }
283 
284 } // namespace android
285