blob: 7f1d9cbf22c5eb6398271a38a0578a210aabc9da [file] [log] [blame]
Jamie Gennis68e4a7a2010-12-20 11:27:26 -08001/*
2 * Copyright (C) 2010 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#define LOG_TAG "SurfaceTextureClient"
Jamie Gennise8d0e8a2011-01-12 20:22:41 -080018//#define LOG_NDEBUG 0
Jamie Gennis68e4a7a2010-12-20 11:27:26 -080019
20#include <gui/SurfaceTextureClient.h>
21
22#include <utils/Log.h>
23
24namespace android {
25
26SurfaceTextureClient::SurfaceTextureClient(
27 const sp<ISurfaceTexture>& surfaceTexture):
Jamie Gennis83bac212011-02-02 15:31:47 -080028 mSurfaceTexture(surfaceTexture), mAllocator(0), mReqWidth(1),
29 mReqHeight(1), mReqFormat(DEFAULT_FORMAT), mReqUsage(0), mMutex() {
Jamie Gennis68e4a7a2010-12-20 11:27:26 -080030 // Initialize the ANativeWindow function pointers.
31 ANativeWindow::setSwapInterval = setSwapInterval;
32 ANativeWindow::dequeueBuffer = dequeueBuffer;
33 ANativeWindow::cancelBuffer = cancelBuffer;
34 ANativeWindow::lockBuffer = lockBuffer;
35 ANativeWindow::queueBuffer = queueBuffer;
36 ANativeWindow::query = query;
37 ANativeWindow::perform = perform;
Jamie Gennis83bac212011-02-02 15:31:47 -080038
39 // Get a reference to the allocator.
40 mAllocator = mSurfaceTexture->getAllocator();
Jamie Gennis68e4a7a2010-12-20 11:27:26 -080041}
42
Jamie Gennisf95a9f02011-03-14 15:08:53 -070043sp<ISurfaceTexture> SurfaceTextureClient::getISurfaceTexture() const {
44 return mSurfaceTexture;
45}
46
Jamie Gennis68e4a7a2010-12-20 11:27:26 -080047int SurfaceTextureClient::setSwapInterval(ANativeWindow* window, int interval) {
48 SurfaceTextureClient* c = getSelf(window);
49 return c->setSwapInterval(interval);
50}
51
52int SurfaceTextureClient::dequeueBuffer(ANativeWindow* window,
53 android_native_buffer_t** buffer) {
54 SurfaceTextureClient* c = getSelf(window);
55 return c->dequeueBuffer(buffer);
56}
57
58int SurfaceTextureClient::cancelBuffer(ANativeWindow* window,
59 android_native_buffer_t* buffer) {
60 SurfaceTextureClient* c = getSelf(window);
61 return c->cancelBuffer(buffer);
62}
63
64int SurfaceTextureClient::lockBuffer(ANativeWindow* window,
65 android_native_buffer_t* buffer) {
66 SurfaceTextureClient* c = getSelf(window);
67 return c->lockBuffer(buffer);
68}
69
70int SurfaceTextureClient::queueBuffer(ANativeWindow* window,
71 android_native_buffer_t* buffer) {
72 SurfaceTextureClient* c = getSelf(window);
73 return c->queueBuffer(buffer);
74}
75
76int SurfaceTextureClient::query(ANativeWindow* window, int what, int* value) {
77 SurfaceTextureClient* c = getSelf(window);
78 return c->query(what, value);
79}
80
81int SurfaceTextureClient::perform(ANativeWindow* window, int operation, ...) {
82 va_list args;
83 va_start(args, operation);
84 SurfaceTextureClient* c = getSelf(window);
85 return c->perform(operation, args);
86}
87
88int SurfaceTextureClient::setSwapInterval(int interval) {
89 return INVALID_OPERATION;
90}
91
92int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) {
Jamie Gennise8d0e8a2011-01-12 20:22:41 -080093 LOGV("SurfaceTextureClient::dequeueBuffer");
Jamie Gennis68e4a7a2010-12-20 11:27:26 -080094 Mutex::Autolock lock(mMutex);
95 int buf = -1;
96 status_t err = mSurfaceTexture->dequeueBuffer(&buf);
97 if (err < 0) {
Jamie Gennis69130622011-01-28 12:03:52 -080098 LOGV("dequeueBuffer: ISurfaceTexture::dequeueBuffer failed: %d", err);
Jamie Gennis68e4a7a2010-12-20 11:27:26 -080099 return err;
100 }
101 sp<GraphicBuffer>& gbuf(mSlots[buf]);
102 if (gbuf == 0 || gbuf->getWidth() != mReqWidth ||
103 gbuf->getHeight() != mReqHeight ||
104 uint32_t(gbuf->getPixelFormat()) != mReqFormat ||
105 (gbuf->getUsage() & mReqUsage) != mReqUsage) {
106 gbuf = mSurfaceTexture->requestBuffer(buf, mReqWidth, mReqHeight,
107 mReqFormat, mReqUsage);
108 if (gbuf == 0) {
Jamie Gennise8d0e8a2011-01-12 20:22:41 -0800109 LOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed");
Jamie Gennis68e4a7a2010-12-20 11:27:26 -0800110 return NO_MEMORY;
111 }
112 }
113 *buffer = gbuf.get();
114 return OK;
115}
116
117int SurfaceTextureClient::cancelBuffer(android_native_buffer_t* buffer) {
Jamie Gennise8d0e8a2011-01-12 20:22:41 -0800118 LOGV("SurfaceTextureClient::cancelBuffer");
Jamie Gennis68e4a7a2010-12-20 11:27:26 -0800119 Mutex::Autolock lock(mMutex);
120 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
Jamie Gennis4559ea42011-01-15 13:05:24 -0800121 if (mSlots[i]->handle == buffer->handle) {
Jamie Gennis68e4a7a2010-12-20 11:27:26 -0800122 mSurfaceTexture->cancelBuffer(i);
123 return OK;
124 }
125 }
126 return BAD_VALUE;
127}
128
129int SurfaceTextureClient::lockBuffer(android_native_buffer_t* buffer) {
Jamie Gennise8d0e8a2011-01-12 20:22:41 -0800130 LOGV("SurfaceTextureClient::lockBuffer");
Jamie Gennis68e4a7a2010-12-20 11:27:26 -0800131 Mutex::Autolock lock(mMutex);
132 return OK;
133}
134
135int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) {
Jamie Gennise8d0e8a2011-01-12 20:22:41 -0800136 LOGV("SurfaceTextureClient::queueBuffer");
Jamie Gennis68e4a7a2010-12-20 11:27:26 -0800137 Mutex::Autolock lock(mMutex);
138 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
Jamie Gennis4559ea42011-01-15 13:05:24 -0800139 if (mSlots[i]->handle == buffer->handle) {
Jamie Gennis68e4a7a2010-12-20 11:27:26 -0800140 return mSurfaceTexture->queueBuffer(i);
141 }
142 }
143 LOGE("queueBuffer: unknown buffer queued");
144 return BAD_VALUE;
145}
146
147int SurfaceTextureClient::query(int what, int* value) {
Jamie Gennise8d0e8a2011-01-12 20:22:41 -0800148 LOGV("SurfaceTextureClient::query");
Jamie Gennis68e4a7a2010-12-20 11:27:26 -0800149 Mutex::Autolock lock(mMutex);
Jamie Gennis96dcc972011-02-27 14:10:20 -0800150 switch (what) {
151 case NATIVE_WINDOW_WIDTH:
152 case NATIVE_WINDOW_HEIGHT:
153 // XXX: How should SurfaceTexture behave if setBuffersGeometry didn't
154 // override the size?
155 *value = 0;
156 return NO_ERROR;
157 case NATIVE_WINDOW_FORMAT:
158 *value = DEFAULT_FORMAT;
159 return NO_ERROR;
160 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
161 *value = MIN_UNDEQUEUED_BUFFERS;
162 return NO_ERROR;
Jamie Gennisd2acedf2011-03-08 12:18:54 -0800163 case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
164 // SurfaceTextureClient currently never queues frames to SurfaceFlinger.
165 *value = 0;
166 return NO_ERROR;
Jamie Gennisc4ca7c52011-03-14 15:00:06 -0700167 case NATIVE_WINDOW_CONCRETE_TYPE:
168 *value = NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT;
169 return NO_ERROR;
Jamie Gennis96dcc972011-02-27 14:10:20 -0800170 }
171 return BAD_VALUE;
Jamie Gennis68e4a7a2010-12-20 11:27:26 -0800172}
173
174int SurfaceTextureClient::perform(int operation, va_list args)
175{
176 int res = NO_ERROR;
177 switch (operation) {
178 case NATIVE_WINDOW_CONNECT:
179 res = dispatchConnect(args);
180 break;
181 case NATIVE_WINDOW_DISCONNECT:
182 res = dispatchDisconnect(args);
183 break;
184 case NATIVE_WINDOW_SET_USAGE:
185 res = dispatchSetUsage(args);
186 break;
187 case NATIVE_WINDOW_SET_CROP:
188 res = dispatchSetCrop(args);
189 break;
190 case NATIVE_WINDOW_SET_BUFFER_COUNT:
191 res = dispatchSetBufferCount(args);
192 break;
193 case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
194 res = dispatchSetBuffersGeometry(args);
195 break;
196 case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
197 res = dispatchSetBuffersTransform(args);
198 break;
199 default:
200 res = NAME_NOT_FOUND;
201 break;
202 }
203 return res;
204}
205
206int SurfaceTextureClient::dispatchConnect(va_list args) {
207 int api = va_arg(args, int);
208 return connect(api);
209}
210
211int SurfaceTextureClient::dispatchDisconnect(va_list args) {
212 int api = va_arg(args, int);
213 return disconnect(api);
214}
215
216int SurfaceTextureClient::dispatchSetUsage(va_list args) {
217 int usage = va_arg(args, int);
218 return setUsage(usage);
219}
220
221int SurfaceTextureClient::dispatchSetCrop(va_list args) {
222 android_native_rect_t const* rect = va_arg(args, android_native_rect_t*);
223 return setCrop(reinterpret_cast<Rect const*>(rect));
224}
225
226int SurfaceTextureClient::dispatchSetBufferCount(va_list args) {
227 size_t bufferCount = va_arg(args, size_t);
228 return setBufferCount(bufferCount);
229}
230
231int SurfaceTextureClient::dispatchSetBuffersGeometry(va_list args) {
232 int w = va_arg(args, int);
233 int h = va_arg(args, int);
234 int f = va_arg(args, int);
235 return setBuffersGeometry(w, h, f);
236}
237
238int SurfaceTextureClient::dispatchSetBuffersTransform(va_list args) {
239 int transform = va_arg(args, int);
240 return setBuffersTransform(transform);
241}
242
243int SurfaceTextureClient::connect(int api) {
Jamie Gennise8d0e8a2011-01-12 20:22:41 -0800244 LOGV("SurfaceTextureClient::connect");
Jamie Gennis68e4a7a2010-12-20 11:27:26 -0800245 // XXX: Implement this!
246 return INVALID_OPERATION;
247}
248
249int SurfaceTextureClient::disconnect(int api) {
Jamie Gennise8d0e8a2011-01-12 20:22:41 -0800250 LOGV("SurfaceTextureClient::disconnect");
Jamie Gennis68e4a7a2010-12-20 11:27:26 -0800251 // XXX: Implement this!
252 return INVALID_OPERATION;
253}
254
255int SurfaceTextureClient::setUsage(uint32_t reqUsage)
256{
Jamie Gennise8d0e8a2011-01-12 20:22:41 -0800257 LOGV("SurfaceTextureClient::setUsage");
Jamie Gennis68e4a7a2010-12-20 11:27:26 -0800258 Mutex::Autolock lock(mMutex);
259 mReqUsage = reqUsage;
260 return OK;
261}
262
263int SurfaceTextureClient::setCrop(Rect const* rect)
264{
Jamie Gennise8d0e8a2011-01-12 20:22:41 -0800265 LOGV("SurfaceTextureClient::setCrop");
Jamie Gennis68e4a7a2010-12-20 11:27:26 -0800266 Mutex::Autolock lock(mMutex);
267
Jamie Gennis2ece4cd2011-01-28 18:21:54 -0800268 Rect realRect;
269 if (rect == NULL || rect->isEmpty()) {
270 realRect = Rect(0, 0);
271 } else {
272 realRect = *rect;
273 }
Jamie Gennis68e4a7a2010-12-20 11:27:26 -0800274
275 status_t err = mSurfaceTexture->setCrop(*rect);
Jamie Gennis2ece4cd2011-01-28 18:21:54 -0800276 LOGE_IF(err, "ISurfaceTexture::setCrop(...) returned %s", strerror(-err));
Jamie Gennis68e4a7a2010-12-20 11:27:26 -0800277
278 return err;
279}
280
281int SurfaceTextureClient::setBufferCount(int bufferCount)
282{
Jamie Gennise8d0e8a2011-01-12 20:22:41 -0800283 LOGV("SurfaceTextureClient::setBufferCount");
Jamie Gennis68e4a7a2010-12-20 11:27:26 -0800284 Mutex::Autolock lock(mMutex);
285
286 status_t err = mSurfaceTexture->setBufferCount(bufferCount);
287 LOGE_IF(err, "ISurfaceTexture::setBufferCount(%d) returned %s",
288 bufferCount, strerror(-err));
289
290 if (err == NO_ERROR) {
291 freeAllBuffers();
292 }
293
294 return err;
295}
296
297int SurfaceTextureClient::setBuffersGeometry(int w, int h, int format)
298{
Jamie Gennise8d0e8a2011-01-12 20:22:41 -0800299 LOGV("SurfaceTextureClient::setBuffersGeometry");
Jamie Gennis68e4a7a2010-12-20 11:27:26 -0800300 Mutex::Autolock lock(mMutex);
301
302 if (w<0 || h<0 || format<0)
303 return BAD_VALUE;
304
305 if ((w && !h) || (!w && h))
306 return BAD_VALUE;
307
308 mReqWidth = w;
309 mReqHeight = h;
310 mReqFormat = format;
311
Jamie Gennis2ece4cd2011-01-28 18:21:54 -0800312 status_t err = mSurfaceTexture->setCrop(Rect(0, 0));
313 LOGE_IF(err, "ISurfaceTexture::setCrop(...) returned %s", strerror(-err));
314
315 return err;
Jamie Gennis68e4a7a2010-12-20 11:27:26 -0800316}
317
318int SurfaceTextureClient::setBuffersTransform(int transform)
319{
Jamie Gennise8d0e8a2011-01-12 20:22:41 -0800320 LOGV("SurfaceTextureClient::setBuffersTransform");
Jamie Gennis68e4a7a2010-12-20 11:27:26 -0800321 Mutex::Autolock lock(mMutex);
322 status_t err = mSurfaceTexture->setTransform(transform);
323 return err;
324}
325
326void SurfaceTextureClient::freeAllBuffers() {
327 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
328 mSlots[i] = 0;
329 }
330}
331
332}; // namespace android