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