16714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis/*
26714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis * Copyright (C) 2010 The Android Open Source Project
36714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis *
46714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis * Licensed under the Apache License, Version 2.0 (the "License");
56714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis * you may not use this file except in compliance with the License.
66714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis * You may obtain a copy of the License at
76714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis *
86714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis *      http://www.apache.org/licenses/LICENSE-2.0
96714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis *
106714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis * Unless required by applicable law or agreed to in writing, software
116714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis * distributed under the License is distributed on an "AS IS" BASIS,
126714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis * See the License for the specific language governing permissions and
146714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis * limitations under the License.
156714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis */
166714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis
176714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis#define LOG_TAG "SurfaceTexture"
186714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis
196714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis#include <stdio.h>
206714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis
214bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner#include <EGL/egl.h>
224bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner#include <EGL/eglext.h>
23e3eae73abb5e429d9747f9c36ab025219e68bb26Mathias Agopian#include <GLES2/gl2.h>
24e3eae73abb5e429d9747f9c36ab025219e68bb26Mathias Agopian#include <GLES2/gl2ext.h>
25e3eae73abb5e429d9747f9c36ab025219e68bb26Mathias Agopian
26d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden#include <gui/GLConsumer.h>
2752800617946c456e78ed010c82d0ec4358368164Mathias Agopian#include <gui/Surface.h>
286714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis
29ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h"
306714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis
316714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis#include <utils/Log.h>
326714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis#include <utils/misc.h>
336714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis
346714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis#include "jni.h"
35376590d668e22a918439877b55faf075427b13f3Jamie Gennis#include "JNIHelp.h"
366714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis
376714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis// ----------------------------------------------------------------------------
386714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis
39afe9a4c67c2e2988c76232796f017a992a6f2a28Craig Donner#define EGL_PROTECTED_CONTENT_EXT 0x32C0
404bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner
416714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennisnamespace android {
426714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis
436714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennisstatic const char* const OutOfResourcesException =
44a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin    "android/view/Surface$OutOfResourcesException";
452b4bfa5efec7df408b4db127961cfc9aca9e57cfJamie Gennisstatic const char* const IllegalStateException = "java/lang/IllegalStateException";
46050316184b01c0d1a01c46afae7429b89a27c31btedboconst char* const kSurfaceTextureClassPathName = "android/graphics/SurfaceTexture";
476714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis
48376590d668e22a918439877b55faf075427b13f3Jamie Gennisstruct fields_t {
49376590d668e22a918439877b55faf075427b13f3Jamie Gennis    jfieldID  surfaceTexture;
500dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza    jfieldID  producer;
51c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin    jfieldID  frameAvailableListener;
52376590d668e22a918439877b55faf075427b13f3Jamie Gennis    jmethodID postEvent;
536714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis};
54376590d668e22a918439877b55faf075427b13f3Jamie Gennisstatic fields_t fields;
556714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis
56ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala// Get an ID that's unique within this process.
57ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvalastatic int32_t createProcessUniqueId() {
58ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala    static volatile int32_t globalCounter = 0;
59ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala    return android_atomic_inc(&globalCounter);
60ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala}
61ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala
624bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner// Check whether the current EGL context is protected.
634bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donnerstatic bool isProtectedContext() {
644bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner    EGLDisplay dpy = eglGetCurrentDisplay();
654bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner    EGLContext ctx = eglGetCurrentContext();
664bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner
67afe9a4c67c2e2988c76232796f017a992a6f2a28Craig Donner    if (dpy == EGL_NO_DISPLAY || ctx == EGL_NO_CONTEXT) {
684bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner        return false;
694bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner    }
704bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner
714bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner    EGLint isProtected = EGL_FALSE;
72afe9a4c67c2e2988c76232796f017a992a6f2a28Craig Donner    eglQueryContext(dpy, ctx, EGL_PROTECTED_CONTENT_EXT, &isProtected);
734bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner
744bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner    return isProtected;
754bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner}
764bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner
776714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis// ----------------------------------------------------------------------------
786714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis
79376590d668e22a918439877b55faf075427b13f3Jamie Gennisstatic void SurfaceTexture_setSurfaceTexture(JNIEnv* env, jobject thiz,
80d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden        const sp<GLConsumer>& surfaceTexture)
816714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis{
82d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    GLConsumer* const p =
8372aa313ff4c91e7b2aae3d37067f9201b2b0fdbeAshok Bhat        (GLConsumer*)env->GetLongField(thiz, fields.surfaceTexture);
846714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis    if (surfaceTexture.get()) {
85b1d90c8f60f71422196c337f1d078b68867f5710Mathias Agopian        surfaceTexture->incStrong((void*)SurfaceTexture_setSurfaceTexture);
866714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis    }
876714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis    if (p) {
88b1d90c8f60f71422196c337f1d078b68867f5710Mathias Agopian        p->decStrong((void*)SurfaceTexture_setSurfaceTexture);
896714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis    }
9072aa313ff4c91e7b2aae3d37067f9201b2b0fdbeAshok Bhat    env->SetLongField(thiz, fields.surfaceTexture, (jlong)surfaceTexture.get());
916714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis}
926714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis
930dc146be5a6cd0c33910d5b18885df46873a93cbDan Stozastatic void SurfaceTexture_setProducer(JNIEnv* env, jobject thiz,
940dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza        const sp<IGraphicBufferProducer>& producer)
9552a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian{
960dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza    IGraphicBufferProducer* const p =
970dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza        (IGraphicBufferProducer*)env->GetLongField(thiz, fields.producer);
980dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza    if (producer.get()) {
990dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza        producer->incStrong((void*)SurfaceTexture_setProducer);
10052a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian    }
10152a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian    if (p) {
1020dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza        p->decStrong((void*)SurfaceTexture_setProducer);
10352a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian    }
1040dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza    env->SetLongField(thiz, fields.producer, (jlong)producer.get());
10552a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian}
10652a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian
107c99db2bc460cc795947d99076da380e22a21e493Igor Murashkinstatic void SurfaceTexture_setFrameAvailableListener(JNIEnv* env,
108d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden        jobject thiz, sp<GLConsumer::FrameAvailableListener> listener)
1096714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis{
110d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    GLConsumer::FrameAvailableListener* const p =
111d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden        (GLConsumer::FrameAvailableListener*)
11272aa313ff4c91e7b2aae3d37067f9201b2b0fdbeAshok Bhat            env->GetLongField(thiz, fields.frameAvailableListener);
113c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin    if (listener.get()) {
114b1d90c8f60f71422196c337f1d078b68867f5710Mathias Agopian        listener->incStrong((void*)SurfaceTexture_setSurfaceTexture);
115c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin    }
116c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin    if (p) {
117b1d90c8f60f71422196c337f1d078b68867f5710Mathias Agopian        p->decStrong((void*)SurfaceTexture_setSurfaceTexture);
118c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin    }
11972aa313ff4c91e7b2aae3d37067f9201b2b0fdbeAshok Bhat    env->SetLongField(thiz, fields.frameAvailableListener, (jlong)listener.get());
120c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin}
121c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin
12252a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopiansp<GLConsumer> SurfaceTexture_getSurfaceTexture(JNIEnv* env, jobject thiz) {
12372aa313ff4c91e7b2aae3d37067f9201b2b0fdbeAshok Bhat    return (GLConsumer*)env->GetLongField(thiz, fields.surfaceTexture);
1246714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis}
1256714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis
12652a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopiansp<IGraphicBufferProducer> SurfaceTexture_getProducer(JNIEnv* env, jobject thiz) {
1270dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza    return (IGraphicBufferProducer*)env->GetLongField(thiz, fields.producer);
12852a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian}
12952a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian
13052a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopiansp<ANativeWindow> android_SurfaceTexture_getNativeWindow(JNIEnv* env, jobject thiz) {
131d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
13252a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian    sp<IGraphicBufferProducer> producer(SurfaceTexture_getProducer(env, thiz));
13352a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian    sp<Surface> surfaceTextureClient(surfaceTexture != NULL ? new Surface(producer) : NULL);
134846db33313aa0899fa7928256c6734964bd92520Glenn Kasten    return surfaceTextureClient;
135846db33313aa0899fa7928256c6734964bd92520Glenn Kasten}
136846db33313aa0899fa7928256c6734964bd92520Glenn Kasten
13752a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopianbool android_SurfaceTexture_isInstanceOf(JNIEnv* env, jobject thiz) {
138050316184b01c0d1a01c46afae7429b89a27c31btedbo    jclass surfaceTextureClass = env->FindClass(kSurfaceTextureClassPathName);
139050316184b01c0d1a01c46afae7429b89a27c31btedbo    return env->IsInstanceOf(thiz, surfaceTextureClass);
140050316184b01c0d1a01c46afae7429b89a27c31btedbo}
141050316184b01c0d1a01c46afae7429b89a27c31btedbo
1426714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis// ----------------------------------------------------------------------------
1436714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis
144d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFaddenclass JNISurfaceTextureContext : public GLConsumer::FrameAvailableListener
1456714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis{
146376590d668e22a918439877b55faf075427b13f3Jamie Gennispublic:
147376590d668e22a918439877b55faf075427b13f3Jamie Gennis    JNISurfaceTextureContext(JNIEnv* env, jobject weakThiz, jclass clazz);
148376590d668e22a918439877b55faf075427b13f3Jamie Gennis    virtual ~JNISurfaceTextureContext();
1492c34b5e8136eac0332dac294cb06a6a98eac1c14Dan Stoza    virtual void onFrameAvailable(const BufferItem& item);
150376590d668e22a918439877b55faf075427b13f3Jamie Gennis
151376590d668e22a918439877b55faf075427b13f3Jamie Gennisprivate:
1520a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis    static JNIEnv* getJNIEnv(bool* needsDetach);
1530a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis    static void detachJNI();
15484293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis
155376590d668e22a918439877b55faf075427b13f3Jamie Gennis    jobject mWeakThiz;
156376590d668e22a918439877b55faf075427b13f3Jamie Gennis    jclass mClazz;
157376590d668e22a918439877b55faf075427b13f3Jamie Gennis};
158376590d668e22a918439877b55faf075427b13f3Jamie Gennis
159376590d668e22a918439877b55faf075427b13f3Jamie GennisJNISurfaceTextureContext::JNISurfaceTextureContext(JNIEnv* env,
160376590d668e22a918439877b55faf075427b13f3Jamie Gennis        jobject weakThiz, jclass clazz) :
161376590d668e22a918439877b55faf075427b13f3Jamie Gennis    mWeakThiz(env->NewGlobalRef(weakThiz)),
162376590d668e22a918439877b55faf075427b13f3Jamie Gennis    mClazz((jclass)env->NewGlobalRef(clazz))
163376590d668e22a918439877b55faf075427b13f3Jamie Gennis{}
164376590d668e22a918439877b55faf075427b13f3Jamie Gennis
1650a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie GennisJNIEnv* JNISurfaceTextureContext::getJNIEnv(bool* needsDetach) {
1660a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis    *needsDetach = false;
1670a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis    JNIEnv* env = AndroidRuntime::getJNIEnv();
1680a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis    if (env == NULL) {
1699b311c900dcc3666febf52c1bed8eae7ce1f2815Andy McFadden        JavaVMAttachArgs args = {
1709b311c900dcc3666febf52c1bed8eae7ce1f2815Andy McFadden            JNI_VERSION_1_4, "JNISurfaceTextureContext", NULL };
1710a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis        JavaVM* vm = AndroidRuntime::getJavaVM();
1720a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis        int result = vm->AttachCurrentThread(&env, (void*) &args);
1730a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis        if (result != JNI_OK) {
1743762c311729fe9f3af085c14c5c1fb471d994c03Steve Block            ALOGE("thread attach failed: %#x", result);
1750a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis            return NULL;
1760a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis        }
1770a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis        *needsDetach = true;
1780a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis    }
1790a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis    return env;
1800a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis}
1810a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis
1820a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennisvoid JNISurfaceTextureContext::detachJNI() {
18384293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis    JavaVM* vm = AndroidRuntime::getJavaVM();
1840a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis    int result = vm->DetachCurrentThread();
18584293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis    if (result != JNI_OK) {
1863762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("thread detach failed: %#x", result);
18784293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis    }
18884293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis}
18984293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis
190376590d668e22a918439877b55faf075427b13f3Jamie GennisJNISurfaceTextureContext::~JNISurfaceTextureContext()
191376590d668e22a918439877b55faf075427b13f3Jamie Gennis{
1920a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis    bool needsDetach = false;
1930a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis    JNIEnv* env = getJNIEnv(&needsDetach);
19484293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis    if (env != NULL) {
19584293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis        env->DeleteGlobalRef(mWeakThiz);
19684293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis        env->DeleteGlobalRef(mClazz);
19784293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis    } else {
1988564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("leaking JNI object references");
19984293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis    }
2000a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis    if (needsDetach) {
2010a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis        detachJNI();
2020a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis    }
203376590d668e22a918439877b55faf075427b13f3Jamie Gennis}
204376590d668e22a918439877b55faf075427b13f3Jamie Gennis
2052c34b5e8136eac0332dac294cb06a6a98eac1c14Dan Stozavoid JNISurfaceTextureContext::onFrameAvailable(const BufferItem& /* item */)
206376590d668e22a918439877b55faf075427b13f3Jamie Gennis{
2070a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis    bool needsDetach = false;
2080a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis    JNIEnv* env = getJNIEnv(&needsDetach);
20984293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis    if (env != NULL) {
21084293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis        env->CallStaticVoidMethod(mClazz, fields.postEvent, mWeakThiz);
21184293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis    } else {
2128564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("onFrameAvailable event will not posted");
21384293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis    }
2140a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis    if (needsDetach) {
2150a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis        detachJNI();
2160a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis    }
217376590d668e22a918439877b55faf075427b13f3Jamie Gennis}
218376590d668e22a918439877b55faf075427b13f3Jamie Gennis
219376590d668e22a918439877b55faf075427b13f3Jamie Gennis// ----------------------------------------------------------------------------
220376590d668e22a918439877b55faf075427b13f3Jamie Gennis
22152a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian
22252a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian#define ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID "mSurfaceTexture"
2230dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza#define ANDROID_GRAPHICS_PRODUCER_JNI_ID "mProducer"
22452a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian#define ANDROID_GRAPHICS_FRAMEAVAILABLELISTENER_JNI_ID \
22552a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian                                         "mFrameAvailableListener"
22652a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian
227376590d668e22a918439877b55faf075427b13f3Jamie Gennisstatic void SurfaceTexture_classInit(JNIEnv* env, jclass clazz)
228376590d668e22a918439877b55faf075427b13f3Jamie Gennis{
229376590d668e22a918439877b55faf075427b13f3Jamie Gennis    fields.surfaceTexture = env->GetFieldID(clazz,
23072aa313ff4c91e7b2aae3d37067f9201b2b0fdbeAshok Bhat            ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID, "J");
231376590d668e22a918439877b55faf075427b13f3Jamie Gennis    if (fields.surfaceTexture == NULL) {
2323762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("can't find android/graphics/SurfaceTexture.%s",
233376590d668e22a918439877b55faf075427b13f3Jamie Gennis                ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID);
234376590d668e22a918439877b55faf075427b13f3Jamie Gennis    }
2350dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza    fields.producer = env->GetFieldID(clazz,
2360dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza            ANDROID_GRAPHICS_PRODUCER_JNI_ID, "J");
2370dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza    if (fields.producer == NULL) {
23852a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian        ALOGE("can't find android/graphics/SurfaceTexture.%s",
2390dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza                ANDROID_GRAPHICS_PRODUCER_JNI_ID);
24052a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian    }
241c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin    fields.frameAvailableListener = env->GetFieldID(clazz,
24272aa313ff4c91e7b2aae3d37067f9201b2b0fdbeAshok Bhat            ANDROID_GRAPHICS_FRAMEAVAILABLELISTENER_JNI_ID, "J");
243c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin    if (fields.frameAvailableListener == NULL) {
244c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin        ALOGE("can't find android/graphics/SurfaceTexture.%s",
245c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin                ANDROID_GRAPHICS_FRAMEAVAILABLELISTENER_JNI_ID);
246c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin    }
247376590d668e22a918439877b55faf075427b13f3Jamie Gennis
248376590d668e22a918439877b55faf075427b13f3Jamie Gennis    fields.postEvent = env->GetStaticMethodID(clazz, "postEventFromNative",
249c7282e57cd01f1576baac04356bf99bee34e4c18Jeff Brown            "(Ljava/lang/ref/WeakReference;)V");
250376590d668e22a918439877b55faf075427b13f3Jamie Gennis    if (fields.postEvent == NULL) {
2513762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("can't find android/graphics/SurfaceTexture.postEventFromNative");
252376590d668e22a918439877b55faf075427b13f3Jamie Gennis    }
253376590d668e22a918439877b55faf075427b13f3Jamie Gennis}
2546714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis
255493f2e11909e2d5839ca81ddc66d48d538192478Dan Stozastatic void SurfaceTexture_init(JNIEnv* env, jobject thiz, jboolean isDetached,
256e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian        jint texName, jboolean singleBufferMode, jobject weakThiz)
257376590d668e22a918439877b55faf075427b13f3Jamie Gennis{
2580dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza    sp<IGraphicBufferProducer> producer;
2590dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza    sp<IGraphicBufferConsumer> consumer;
2600dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza    BufferQueue::createBufferQueue(&producer, &consumer);
261e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian
262e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian    if (singleBufferMode) {
263e442b63c837c8852546f9fa7ba28985e8eea7290Pablo Ceballos        consumer->setMaxBufferCount(1);
264e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian    }
265e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian
266493f2e11909e2d5839ca81ddc66d48d538192478Dan Stoza    sp<GLConsumer> surfaceTexture;
267493f2e11909e2d5839ca81ddc66d48d538192478Dan Stoza    if (isDetached) {
268493f2e11909e2d5839ca81ddc66d48d538192478Dan Stoza        surfaceTexture = new GLConsumer(consumer, GL_TEXTURE_EXTERNAL_OES,
269e442b63c837c8852546f9fa7ba28985e8eea7290Pablo Ceballos                true, !singleBufferMode);
270493f2e11909e2d5839ca81ddc66d48d538192478Dan Stoza    } else {
271493f2e11909e2d5839ca81ddc66d48d538192478Dan Stoza        surfaceTexture = new GLConsumer(consumer, texName,
272e442b63c837c8852546f9fa7ba28985e8eea7290Pablo Ceballos                GL_TEXTURE_EXTERNAL_OES, true, !singleBufferMode);
273493f2e11909e2d5839ca81ddc66d48d538192478Dan Stoza    }
274493f2e11909e2d5839ca81ddc66d48d538192478Dan Stoza
2756714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis    if (surfaceTexture == 0) {
276376590d668e22a918439877b55faf075427b13f3Jamie Gennis        jniThrowException(env, OutOfResourcesException,
277376590d668e22a918439877b55faf075427b13f3Jamie Gennis                "Unable to create native SurfaceTexture");
278376590d668e22a918439877b55faf075427b13f3Jamie Gennis        return;
279376590d668e22a918439877b55faf075427b13f3Jamie Gennis    }
280ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala    surfaceTexture->setName(String8::format("SurfaceTexture-%d-%d-%d",
281ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala            (isDetached ? 0 : texName),
282ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala            getpid(),
283ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala            createProcessUniqueId()));
284ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala
2854bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner    // If the current context is protected, inform the producer.
2864bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner    if (isProtectedContext()) {
2874bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner        consumer->setConsumerUsageBits(GRALLOC_USAGE_PROTECTED);
2884bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner    }
2894bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner
290376590d668e22a918439877b55faf075427b13f3Jamie Gennis    SurfaceTexture_setSurfaceTexture(env, thiz, surfaceTexture);
2910dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza    SurfaceTexture_setProducer(env, thiz, producer);
292376590d668e22a918439877b55faf075427b13f3Jamie Gennis
293376590d668e22a918439877b55faf075427b13f3Jamie Gennis    jclass clazz = env->GetObjectClass(thiz);
294376590d668e22a918439877b55faf075427b13f3Jamie Gennis    if (clazz == NULL) {
295376590d668e22a918439877b55faf075427b13f3Jamie Gennis        jniThrowRuntimeException(env,
296376590d668e22a918439877b55faf075427b13f3Jamie Gennis                "Can't find android/graphics/SurfaceTexture");
2976714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis        return;
2986714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis    }
299376590d668e22a918439877b55faf075427b13f3Jamie Gennis
300376590d668e22a918439877b55faf075427b13f3Jamie Gennis    sp<JNISurfaceTextureContext> ctx(new JNISurfaceTextureContext(env, weakThiz,
301376590d668e22a918439877b55faf075427b13f3Jamie Gennis            clazz));
302376590d668e22a918439877b55faf075427b13f3Jamie Gennis    surfaceTexture->setFrameAvailableListener(ctx);
303c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin    SurfaceTexture_setFrameAvailableListener(env, thiz, ctx);
304376590d668e22a918439877b55faf075427b13f3Jamie Gennis}
305376590d668e22a918439877b55faf075427b13f3Jamie Gennis
306376590d668e22a918439877b55faf075427b13f3Jamie Gennisstatic void SurfaceTexture_finalize(JNIEnv* env, jobject thiz)
307376590d668e22a918439877b55faf075427b13f3Jamie Gennis{
308d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
309376590d668e22a918439877b55faf075427b13f3Jamie Gennis    surfaceTexture->setFrameAvailableListener(0);
310c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin    SurfaceTexture_setFrameAvailableListener(env, thiz, 0);
311376590d668e22a918439877b55faf075427b13f3Jamie Gennis    SurfaceTexture_setSurfaceTexture(env, thiz, 0);
3120dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza    SurfaceTexture_setProducer(env, thiz, 0);
3136714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis}
3146714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis
315050316184b01c0d1a01c46afae7429b89a27c31btedbostatic void SurfaceTexture_setDefaultBufferSize(
31652a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian        JNIEnv* env, jobject thiz, jint width, jint height) {
317d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
318050316184b01c0d1a01c46afae7429b89a27c31btedbo    surfaceTexture->setDefaultBufferSize(width, height);
319050316184b01c0d1a01c46afae7429b89a27c31btedbo}
320050316184b01c0d1a01c46afae7429b89a27c31btedbo
3212b4bfa5efec7df408b4db127961cfc9aca9e57cfJamie Gennisstatic void SurfaceTexture_updateTexImage(JNIEnv* env, jobject thiz)
3226714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis{
323d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
3242b4bfa5efec7df408b4db127961cfc9aca9e57cfJamie Gennis    status_t err = surfaceTexture->updateTexImage();
3252b4bfa5efec7df408b4db127961cfc9aca9e57cfJamie Gennis    if (err == INVALID_OPERATION) {
3262b4bfa5efec7df408b4db127961cfc9aca9e57cfJamie Gennis        jniThrowException(env, IllegalStateException, "Unable to update texture contents (see "
3272b4bfa5efec7df408b4db127961cfc9aca9e57cfJamie Gennis                "logcat for details)");
328721bfaa63d14f0ac858d32431ab2eff582143b0fJamie Gennis    } else if (err < 0) {
3292b4bfa5efec7df408b4db127961cfc9aca9e57cfJamie Gennis        jniThrowRuntimeException(env, "Error during updateTexImage (see logcat for details)");
3302b4bfa5efec7df408b4db127961cfc9aca9e57cfJamie Gennis    }
3316714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis}
3326714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis
333e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopianstatic void SurfaceTexture_releaseTexImage(JNIEnv* env, jobject thiz)
334e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian{
335e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
336e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian    status_t err = surfaceTexture->releaseTexImage();
337e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian    if (err == INVALID_OPERATION) {
338e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian        jniThrowException(env, IllegalStateException, "Unable to release texture contents (see "
339e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian                "logcat for details)");
340e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian    } else if (err < 0) {
341e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian        jniThrowRuntimeException(env, "Error during updateTexImage (see logcat for details)");
342e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian    }
343e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian}
344e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian
345c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennisstatic jint SurfaceTexture_detachFromGLContext(JNIEnv* env, jobject thiz)
346c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis{
347d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
348c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis    return surfaceTexture->detachFromContext();
349c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis}
350c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis
351c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennisstatic jint SurfaceTexture_attachToGLContext(JNIEnv* env, jobject thiz, jint tex)
352c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis{
353d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
354c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis    return surfaceTexture->attachToContext((GLuint)tex);
355c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis}
356c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis
357376590d668e22a918439877b55faf075427b13f3Jamie Gennisstatic void SurfaceTexture_getTransformMatrix(JNIEnv* env, jobject thiz,
358b0ba48c95ea8768a051100c5adb4c906caa1e080Jamie Gennis        jfloatArray jmtx)
359b0ba48c95ea8768a051100c5adb4c906caa1e080Jamie Gennis{
360d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
361b0ba48c95ea8768a051100c5adb4c906caa1e080Jamie Gennis    float* mtx = env->GetFloatArrayElements(jmtx, NULL);
362b0ba48c95ea8768a051100c5adb4c906caa1e080Jamie Gennis    surfaceTexture->getTransformMatrix(mtx);
363b0ba48c95ea8768a051100c5adb4c906caa1e080Jamie Gennis    env->ReleaseFloatArrayElements(jmtx, mtx, 0);
364b0ba48c95ea8768a051100c5adb4c906caa1e080Jamie Gennis}
365b0ba48c95ea8768a051100c5adb4c906caa1e080Jamie Gennis
366c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvalastatic jlong SurfaceTexture_getTimestamp(JNIEnv* env, jobject thiz)
367c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala{
368d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
369c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala    return surfaceTexture->getTimestamp();
370c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala}
371c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala
372ec46b4e1ca89d7c3a9ad70ded58da08b5e19f08fMathias Agopianstatic void SurfaceTexture_release(JNIEnv* env, jobject thiz)
373ec46b4e1ca89d7c3a9ad70ded58da08b5e19f08fMathias Agopian{
374d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
375ec46b4e1ca89d7c3a9ad70ded58da08b5e19f08fMathias Agopian    surfaceTexture->abandon();
376ec46b4e1ca89d7c3a9ad70ded58da08b5e19f08fMathias Agopian}
377ec46b4e1ca89d7c3a9ad70ded58da08b5e19f08fMathias Agopian
3786d8371e73ff6452be5a23089e7edeb8d6d96f065John Reckstatic jboolean SurfaceTexture_isReleased(JNIEnv* env, jobject thiz)
3796d8371e73ff6452be5a23089e7edeb8d6d96f065John Reck{
3806d8371e73ff6452be5a23089e7edeb8d6d96f065John Reck    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
3816d8371e73ff6452be5a23089e7edeb8d6d96f065John Reck    return surfaceTexture->isAbandoned();
3826d8371e73ff6452be5a23089e7edeb8d6d96f065John Reck}
3836d8371e73ff6452be5a23089e7edeb8d6d96f065John Reck
3846714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis// ----------------------------------------------------------------------------
3856714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis
38676f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gSurfaceTextureMethods[] = {
387c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis    {"nativeClassInit",            "()V",   (void*)SurfaceTexture_classInit },
388493f2e11909e2d5839ca81ddc66d48d538192478Dan Stoza    {"nativeInit",                 "(ZIZLjava/lang/ref/WeakReference;)V", (void*)SurfaceTexture_init },
389c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis    {"nativeFinalize",             "()V",   (void*)SurfaceTexture_finalize },
390050316184b01c0d1a01c46afae7429b89a27c31btedbo    {"nativeSetDefaultBufferSize", "(II)V", (void*)SurfaceTexture_setDefaultBufferSize },
3912b4bfa5efec7df408b4db127961cfc9aca9e57cfJamie Gennis    {"nativeUpdateTexImage",       "()V",   (void*)SurfaceTexture_updateTexImage },
392e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian    {"nativeReleaseTexImage",      "()V",   (void*)SurfaceTexture_releaseTexImage },
393c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis    {"nativeDetachFromGLContext",  "()I",   (void*)SurfaceTexture_detachFromGLContext },
394c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis    {"nativeAttachToGLContext",    "(I)I",   (void*)SurfaceTexture_attachToGLContext },
395c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis    {"nativeGetTransformMatrix",   "([F)V", (void*)SurfaceTexture_getTransformMatrix },
396c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis    {"nativeGetTimestamp",         "()J",   (void*)SurfaceTexture_getTimestamp },
397c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis    {"nativeRelease",              "()V",   (void*)SurfaceTexture_release },
3986d8371e73ff6452be5a23089e7edeb8d6d96f065John Reck    {"nativeIsReleased",           "()Z",   (void*)SurfaceTexture_isReleased },
3996714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis};
4006714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis
4016714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennisint register_android_graphics_SurfaceTexture(JNIEnv* env)
4026714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis{
403ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    return RegisterMethodsOrDie(env, kSurfaceTextureClassPathName, gSurfaceTextureMethods,
404ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe                                NELEM(gSurfaceTextureMethods));
4056714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis}
4066714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis
4076714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis} // namespace android
408