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