1 /*
2  * Copyright (C) 2018 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 #include <android/surface_texture.h>
18 #include <android/surface_texture_jni.h>
19 
20 #define LOG_TAG "ASurfaceTexture"
21 
22 #include <utils/Log.h>
23 
24 #include <gui/Surface.h>
25 
26 #include <surfacetexture/surface_texture_platform.h>
27 #include <surfacetexture/SurfaceTexture.h>
28 
29 #include <mutex>
30 
31 #include <jni.h>
32 #include <nativehelper/JNIHelp.h>
33 #include <nativehelper/ScopedLocalRef.h>
34 
35 struct ASurfaceTexture {
36     android::sp<android::SurfaceTexture> consumer;
37     android::sp<android::IGraphicBufferProducer> producer;
38 };
39 
40 using namespace android;
41 
42 const char* const kSurfaceTextureClassPathName = "android/graphics/SurfaceTexture";
43 
44 struct fields_t {
45     jfieldID  surfaceTexture;
46     jfieldID  producer;
47 };
48 static fields_t fields;
49 static std::once_flag sInitFieldsOnce;
50 
51 #define ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID "mSurfaceTexture"
52 #define ANDROID_GRAPHICS_PRODUCER_JNI_ID "mProducer"
53 
SurfaceTexture_classInit(JNIEnv * env,jclass clazz)54 static void SurfaceTexture_classInit(JNIEnv* env, jclass clazz)
55 {
56     fields.surfaceTexture = env->GetFieldID(clazz,
57             ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID, "J");
58     if (fields.surfaceTexture == NULL) {
59         ALOGE("can't find android/graphics/SurfaceTexture.%s",
60                 ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID);
61     }
62     fields.producer = env->GetFieldID(clazz,
63             ANDROID_GRAPHICS_PRODUCER_JNI_ID, "J");
64     if (fields.producer == NULL) {
65         ALOGE("can't find android/graphics/SurfaceTexture.%s",
66                 ANDROID_GRAPHICS_PRODUCER_JNI_ID);
67     }
68 }
69 
FindClassOrDie(JNIEnv * env,const char * class_name)70 static inline jclass FindClassOrDie(JNIEnv* env, const char* class_name) {
71     jclass clazz = env->FindClass(class_name);
72     LOG_ALWAYS_FATAL_IF(clazz == NULL, "Unable to find class %s", class_name);
73     return clazz;
74 }
75 
register_android_graphics_SurfaceTexture(JNIEnv * env)76 static void register_android_graphics_SurfaceTexture(JNIEnv* env)
77 {
78     // Cache some fields.
79     ScopedLocalRef<jclass> klass(env, FindClassOrDie(env, kSurfaceTextureClassPathName));
80     SurfaceTexture_classInit(env, klass.get());
81 }
82 
android_SurfaceTexture_isInstanceOf(JNIEnv * env,jobject thiz)83 static bool android_SurfaceTexture_isInstanceOf(JNIEnv* env, jobject thiz) {
84     std::call_once(sInitFieldsOnce, [=]() {
85         register_android_graphics_SurfaceTexture(env);
86     });
87 
88     jclass surfaceTextureClass = env->FindClass(kSurfaceTextureClassPathName);
89     return env->IsInstanceOf(thiz, surfaceTextureClass);
90 }
91 
SurfaceTexture_getSurfaceTexture(JNIEnv * env,jobject thiz)92 static sp<SurfaceTexture> SurfaceTexture_getSurfaceTexture(JNIEnv* env, jobject thiz) {
93     std::call_once(sInitFieldsOnce, [=]() {
94         register_android_graphics_SurfaceTexture(env);
95     });
96 
97     return (SurfaceTexture*)env->GetLongField(thiz, fields.surfaceTexture);
98 }
99 
SurfaceTexture_getProducer(JNIEnv * env,jobject thiz)100 static sp<IGraphicBufferProducer> SurfaceTexture_getProducer(JNIEnv* env, jobject thiz) {
101     std::call_once(sInitFieldsOnce, [=]() {
102         register_android_graphics_SurfaceTexture(env);
103     });
104 
105     return (IGraphicBufferProducer*)env->GetLongField(thiz, fields.producer);
106 }
107 
108 // The following functions implement NDK API.
ASurfaceTexture_fromSurfaceTexture(JNIEnv * env,jobject surfacetexture)109 ASurfaceTexture* ASurfaceTexture_fromSurfaceTexture(JNIEnv* env, jobject surfacetexture) {
110     if (!surfacetexture || !android_SurfaceTexture_isInstanceOf(env, surfacetexture)) {
111         return nullptr;
112     }
113     ASurfaceTexture* ast = new ASurfaceTexture;
114     ast->consumer = SurfaceTexture_getSurfaceTexture(env, surfacetexture);
115     ast->producer = SurfaceTexture_getProducer(env, surfacetexture);
116     return ast;
117 }
118 
ASurfaceTexture_acquireANativeWindow(ASurfaceTexture * st)119 ANativeWindow* ASurfaceTexture_acquireANativeWindow(ASurfaceTexture* st) {
120     sp<Surface> surface = new Surface(st->producer);
121     ANativeWindow* win(surface.get());
122     ANativeWindow_acquire(win);
123     return win;
124 }
125 
ASurfaceTexture_release(ASurfaceTexture * st)126 void ASurfaceTexture_release(ASurfaceTexture* st) {
127     delete st;
128 }
129 
ASurfaceTexture_attachToGLContext(ASurfaceTexture * st,uint32_t tex)130 int ASurfaceTexture_attachToGLContext(ASurfaceTexture* st, uint32_t tex) {
131     return st->consumer->attachToContext(tex);
132 }
133 
ASurfaceTexture_detachFromGLContext(ASurfaceTexture * st)134 int ASurfaceTexture_detachFromGLContext(ASurfaceTexture* st) {
135     return st->consumer->detachFromContext();
136 }
137 
ASurfaceTexture_updateTexImage(ASurfaceTexture * st)138 int ASurfaceTexture_updateTexImage(ASurfaceTexture* st) {
139     return st->consumer->updateTexImage();
140 }
141 
ASurfaceTexture_getTransformMatrix(ASurfaceTexture * st,float mtx[16])142 void ASurfaceTexture_getTransformMatrix(ASurfaceTexture* st, float mtx[16]) {
143     st->consumer->getTransformMatrix(mtx);
144 }
145 
ASurfaceTexture_getTimestamp(ASurfaceTexture * st)146 int64_t ASurfaceTexture_getTimestamp(ASurfaceTexture* st) {
147     return st->consumer->getTimestamp();
148 }
149 
150 // The following functions are private/unstable API.
151 namespace android {
ASurfaceTexture_routeAcquireANativeWindow(ASurfaceTexture * st)152 ANativeWindow* ASurfaceTexture_routeAcquireANativeWindow(ASurfaceTexture* st) {
153     return ASurfaceTexture_acquireANativeWindow(st);
154 }
155 
ASurfaceTexture_routeAttachToGLContext(ASurfaceTexture * st,uint32_t texName)156 int ASurfaceTexture_routeAttachToGLContext(ASurfaceTexture* st, uint32_t texName) {
157     return ASurfaceTexture_attachToGLContext(st, texName);
158 }
159 
ASurfaceTexture_routeRelease(ASurfaceTexture * st)160 void ASurfaceTexture_routeRelease(ASurfaceTexture* st) {
161     return ASurfaceTexture_release(st);
162 }
163 
ASurfaceTexture_routeDetachFromGLContext(ASurfaceTexture * st)164 int ASurfaceTexture_routeDetachFromGLContext(ASurfaceTexture* st) {
165     return ASurfaceTexture_detachFromGLContext(st);
166 }
167 
ASurfaceTexture_routeUpdateTexImage(ASurfaceTexture * st)168 int ASurfaceTexture_routeUpdateTexImage(ASurfaceTexture* st) {
169     return ASurfaceTexture_updateTexImage(st);
170 }
171 
ASurfaceTexture_routeGetTransformMatrix(ASurfaceTexture * st,float mtx[16])172 void ASurfaceTexture_routeGetTransformMatrix(ASurfaceTexture* st, float mtx[16]) {
173     return ASurfaceTexture_getTransformMatrix(st, mtx);
174 }
175 
ASurfaceTexture_routeGetTimestamp(ASurfaceTexture * st)176 int64_t ASurfaceTexture_routeGetTimestamp(ASurfaceTexture* st) {
177     return ASurfaceTexture_getTimestamp(st);
178 }
179 
ASurfaceTexture_routeFromSurfaceTexture(JNIEnv * env,jobject surfacetexture)180 ASurfaceTexture* ASurfaceTexture_routeFromSurfaceTexture(JNIEnv* env, jobject surfacetexture) {
181     return ASurfaceTexture_fromSurfaceTexture(env, surfacetexture);
182 }
183 
ASurfaceTexture_getCurrentTextureTarget(ASurfaceTexture * st)184 unsigned int ASurfaceTexture_getCurrentTextureTarget(ASurfaceTexture* st) {
185     return st->consumer->getCurrentTextureTarget();
186 }
187 
ASurfaceTexture_takeConsumerOwnership(ASurfaceTexture * texture)188 void ASurfaceTexture_takeConsumerOwnership(ASurfaceTexture* texture) {
189     texture->consumer->takeConsumerOwnership();
190 }
191 
ASurfaceTexture_releaseConsumerOwnership(ASurfaceTexture * texture)192 void ASurfaceTexture_releaseConsumerOwnership(ASurfaceTexture* texture) {
193     texture->consumer->releaseConsumerOwnership();
194 }
195 
ASurfaceTexture_dequeueBuffer(ASurfaceTexture * st,int * outSlotid,android_dataspace * outDataspace,float * outTransformMatrix,bool * outNewContent,ASurfaceTexture_createReleaseFence createFence,ASurfaceTexture_fenceWait fenceWait,void * handle)196 AHardwareBuffer* ASurfaceTexture_dequeueBuffer(ASurfaceTexture* st, int* outSlotid,
197                                                android_dataspace* outDataspace,
198                                                float* outTransformMatrix, bool* outNewContent,
199                                                ASurfaceTexture_createReleaseFence createFence,
200                                                ASurfaceTexture_fenceWait fenceWait, void* handle) {
201     sp<GraphicBuffer> buffer;
202     *outNewContent = false;
203     bool queueEmpty;
204     do {
205         buffer = st->consumer->dequeueBuffer(outSlotid, outDataspace, outTransformMatrix,
206                                              &queueEmpty, createFence, fenceWait, handle);
207         if (!queueEmpty) {
208             *outNewContent = true;
209         }
210     } while (buffer.get() && (!queueEmpty));
211     AHardwareBuffer* result = nullptr;
212     if (buffer.get()) {
213       result = buffer->toAHardwareBuffer();
214       // add a reference to keep the hardware buffer alive, even if
215       // BufferQueueProducer is disconnected. This is needed, because
216       // sp reference is destroyed at the end of this function.
217       AHardwareBuffer_acquire(result);
218     }
219     return result;
220 }
221 
222 } // namespace android
223