blob: ebe4484873999387990798ee3561c025f6b150e8 [file] [log] [blame]
Stan Iliev5d6bdb02020-01-13 11:19:44 -05001/*
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
35struct ASurfaceTexture {
36 android::sp<android::SurfaceTexture> consumer;
37 android::sp<android::IGraphicBufferProducer> producer;
38};
39
40using namespace android;
41
42const char* const kSurfaceTextureClassPathName = "android/graphics/SurfaceTexture";
43
44struct fields_t {
45 jfieldID surfaceTexture;
46 jfieldID producer;
47};
48static fields_t fields;
49static std::once_flag sInitFieldsOnce;
50
51#define ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID "mSurfaceTexture"
52#define ANDROID_GRAPHICS_PRODUCER_JNI_ID "mProducer"
53
54static 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
70static 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
76static 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
83static 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
92static 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
100static 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.
109ASurfaceTexture* 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
119ANativeWindow* 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
126void ASurfaceTexture_release(ASurfaceTexture* st) {
127 delete st;
128}
129
130int ASurfaceTexture_attachToGLContext(ASurfaceTexture* st, uint32_t tex) {
131 return st->consumer->attachToContext(tex);
132}
133
134int ASurfaceTexture_detachFromGLContext(ASurfaceTexture* st) {
135 return st->consumer->detachFromContext();
136}
137
138int ASurfaceTexture_updateTexImage(ASurfaceTexture* st) {
139 return st->consumer->updateTexImage();
140}
141
142void ASurfaceTexture_getTransformMatrix(ASurfaceTexture* st, float mtx[16]) {
143 st->consumer->getTransformMatrix(mtx);
144}
145
146int64_t ASurfaceTexture_getTimestamp(ASurfaceTexture* st) {
147 return st->consumer->getTimestamp();
148}
149
150// The following functions are private/unstable API.
151namespace android {
Alec Mouri271de042020-04-27 22:38:19 -0700152ANativeWindow* ASurfaceTexture_routeAcquireANativeWindow(ASurfaceTexture* st) {
153 return ASurfaceTexture_acquireANativeWindow(st);
154}
155
156int ASurfaceTexture_routeAttachToGLContext(ASurfaceTexture* st, uint32_t texName) {
157 return ASurfaceTexture_attachToGLContext(st, texName);
158}
159
160void ASurfaceTexture_routeRelease(ASurfaceTexture* st) {
161 return ASurfaceTexture_release(st);
162}
163
164int ASurfaceTexture_routeDetachFromGLContext(ASurfaceTexture* st) {
165 return ASurfaceTexture_detachFromGLContext(st);
166}
167
168int ASurfaceTexture_routeUpdateTexImage(ASurfaceTexture* st) {
169 return ASurfaceTexture_updateTexImage(st);
170}
171
172void ASurfaceTexture_routeGetTransformMatrix(ASurfaceTexture* st, float mtx[16]) {
173 return ASurfaceTexture_getTransformMatrix(st, mtx);
174}
175
176int64_t ASurfaceTexture_routeGetTimestamp(ASurfaceTexture* st) {
177 return ASurfaceTexture_getTimestamp(st);
178}
179
180ASurfaceTexture* ASurfaceTexture_routeFromSurfaceTexture(JNIEnv* env, jobject surfacetexture) {
181 return ASurfaceTexture_fromSurfaceTexture(env, surfacetexture);
182}
Stan Iliev5d6bdb02020-01-13 11:19:44 -0500183
184unsigned int ASurfaceTexture_getCurrentTextureTarget(ASurfaceTexture* st) {
185 return st->consumer->getCurrentTextureTarget();
186}
187
188void ASurfaceTexture_takeConsumerOwnership(ASurfaceTexture* texture) {
189 texture->consumer->takeConsumerOwnership();
190}
191
192void ASurfaceTexture_releaseConsumerOwnership(ASurfaceTexture* texture) {
193 texture->consumer->releaseConsumerOwnership();
194}
195
196AHardwareBuffer* 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));
Stan Iliev0702f1d2020-07-16 17:09:57 -0400211 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;
Stan Iliev5d6bdb02020-01-13 11:19:44 -0500220}
221
222} // namespace android