blob: c0e4e0f56334023612c9a80bb0dcfa168d9367f4 [file] [log] [blame]
Jamie Gennis8ba32fa2010-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 Gennise5366c52011-01-12 20:22:41 -080018//#define LOG_NDEBUG 0
Jamie Gennis8ba32fa2010-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):
28 mSurfaceTexture(surfaceTexture), mReqWidth(1), mReqHeight(1),
29 mReqFormat(DEFAULT_FORMAT), mReqUsage(0), mMutex() {
30 // 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;
38}
39
40int SurfaceTextureClient::setSwapInterval(ANativeWindow* window, int interval) {
41 SurfaceTextureClient* c = getSelf(window);
42 return c->setSwapInterval(interval);
43}
44
45int SurfaceTextureClient::dequeueBuffer(ANativeWindow* window,
46 android_native_buffer_t** buffer) {
47 SurfaceTextureClient* c = getSelf(window);
48 return c->dequeueBuffer(buffer);
49}
50
51int SurfaceTextureClient::cancelBuffer(ANativeWindow* window,
52 android_native_buffer_t* buffer) {
53 SurfaceTextureClient* c = getSelf(window);
54 return c->cancelBuffer(buffer);
55}
56
57int SurfaceTextureClient::lockBuffer(ANativeWindow* window,
58 android_native_buffer_t* buffer) {
59 SurfaceTextureClient* c = getSelf(window);
60 return c->lockBuffer(buffer);
61}
62
63int SurfaceTextureClient::queueBuffer(ANativeWindow* window,
64 android_native_buffer_t* buffer) {
65 SurfaceTextureClient* c = getSelf(window);
66 return c->queueBuffer(buffer);
67}
68
69int SurfaceTextureClient::query(ANativeWindow* window, int what, int* value) {
70 SurfaceTextureClient* c = getSelf(window);
71 return c->query(what, value);
72}
73
74int SurfaceTextureClient::perform(ANativeWindow* window, int operation, ...) {
75 va_list args;
76 va_start(args, operation);
77 SurfaceTextureClient* c = getSelf(window);
78 return c->perform(operation, args);
79}
80
81int SurfaceTextureClient::setSwapInterval(int interval) {
82 return INVALID_OPERATION;
83}
84
85int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) {
Jamie Gennise5366c52011-01-12 20:22:41 -080086 LOGV("SurfaceTextureClient::dequeueBuffer");
Jamie Gennis8ba32fa2010-12-20 11:27:26 -080087 Mutex::Autolock lock(mMutex);
88 int buf = -1;
89 status_t err = mSurfaceTexture->dequeueBuffer(&buf);
90 if (err < 0) {
Jamie Gennis74917222011-01-28 12:03:52 -080091 LOGV("dequeueBuffer: ISurfaceTexture::dequeueBuffer failed: %d", err);
Jamie Gennis8ba32fa2010-12-20 11:27:26 -080092 return err;
93 }
94 sp<GraphicBuffer>& gbuf(mSlots[buf]);
95 if (gbuf == 0 || gbuf->getWidth() != mReqWidth ||
96 gbuf->getHeight() != mReqHeight ||
97 uint32_t(gbuf->getPixelFormat()) != mReqFormat ||
98 (gbuf->getUsage() & mReqUsage) != mReqUsage) {
99 gbuf = mSurfaceTexture->requestBuffer(buf, mReqWidth, mReqHeight,
100 mReqFormat, mReqUsage);
101 if (gbuf == 0) {
Jamie Gennise5366c52011-01-12 20:22:41 -0800102 LOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed");
Jamie Gennis8ba32fa2010-12-20 11:27:26 -0800103 return NO_MEMORY;
104 }
105 }
106 *buffer = gbuf.get();
107 return OK;
108}
109
110int SurfaceTextureClient::cancelBuffer(android_native_buffer_t* buffer) {
Jamie Gennise5366c52011-01-12 20:22:41 -0800111 LOGV("SurfaceTextureClient::cancelBuffer");
Jamie Gennis8ba32fa2010-12-20 11:27:26 -0800112 Mutex::Autolock lock(mMutex);
113 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
Jamie Gennis73e8b9e2011-01-15 13:05:24 -0800114 if (mSlots[i]->handle == buffer->handle) {
Jamie Gennis8ba32fa2010-12-20 11:27:26 -0800115 mSurfaceTexture->cancelBuffer(i);
116 return OK;
117 }
118 }
119 return BAD_VALUE;
120}
121
122int SurfaceTextureClient::lockBuffer(android_native_buffer_t* buffer) {
Jamie Gennise5366c52011-01-12 20:22:41 -0800123 LOGV("SurfaceTextureClient::lockBuffer");
Jamie Gennis8ba32fa2010-12-20 11:27:26 -0800124 Mutex::Autolock lock(mMutex);
125 return OK;
126}
127
128int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) {
Jamie Gennise5366c52011-01-12 20:22:41 -0800129 LOGV("SurfaceTextureClient::queueBuffer");
Jamie Gennis8ba32fa2010-12-20 11:27:26 -0800130 Mutex::Autolock lock(mMutex);
131 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
Jamie Gennis73e8b9e2011-01-15 13:05:24 -0800132 if (mSlots[i]->handle == buffer->handle) {
Jamie Gennis8ba32fa2010-12-20 11:27:26 -0800133 return mSurfaceTexture->queueBuffer(i);
134 }
135 }
136 LOGE("queueBuffer: unknown buffer queued");
137 return BAD_VALUE;
138}
139
140int SurfaceTextureClient::query(int what, int* value) {
Jamie Gennise5366c52011-01-12 20:22:41 -0800141 LOGV("SurfaceTextureClient::query");
Jamie Gennis8ba32fa2010-12-20 11:27:26 -0800142 Mutex::Autolock lock(mMutex);
143 // XXX: Implement this!
144 return INVALID_OPERATION;
145}
146
147int SurfaceTextureClient::perform(int operation, va_list args)
148{
149 int res = NO_ERROR;
150 switch (operation) {
151 case NATIVE_WINDOW_CONNECT:
152 res = dispatchConnect(args);
153 break;
154 case NATIVE_WINDOW_DISCONNECT:
155 res = dispatchDisconnect(args);
156 break;
157 case NATIVE_WINDOW_SET_USAGE:
158 res = dispatchSetUsage(args);
159 break;
160 case NATIVE_WINDOW_SET_CROP:
161 res = dispatchSetCrop(args);
162 break;
163 case NATIVE_WINDOW_SET_BUFFER_COUNT:
164 res = dispatchSetBufferCount(args);
165 break;
166 case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
167 res = dispatchSetBuffersGeometry(args);
168 break;
169 case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
170 res = dispatchSetBuffersTransform(args);
171 break;
172 default:
173 res = NAME_NOT_FOUND;
174 break;
175 }
176 return res;
177}
178
179int SurfaceTextureClient::dispatchConnect(va_list args) {
180 int api = va_arg(args, int);
181 return connect(api);
182}
183
184int SurfaceTextureClient::dispatchDisconnect(va_list args) {
185 int api = va_arg(args, int);
186 return disconnect(api);
187}
188
189int SurfaceTextureClient::dispatchSetUsage(va_list args) {
190 int usage = va_arg(args, int);
191 return setUsage(usage);
192}
193
194int SurfaceTextureClient::dispatchSetCrop(va_list args) {
195 android_native_rect_t const* rect = va_arg(args, android_native_rect_t*);
196 return setCrop(reinterpret_cast<Rect const*>(rect));
197}
198
199int SurfaceTextureClient::dispatchSetBufferCount(va_list args) {
200 size_t bufferCount = va_arg(args, size_t);
201 return setBufferCount(bufferCount);
202}
203
204int SurfaceTextureClient::dispatchSetBuffersGeometry(va_list args) {
205 int w = va_arg(args, int);
206 int h = va_arg(args, int);
207 int f = va_arg(args, int);
208 return setBuffersGeometry(w, h, f);
209}
210
211int SurfaceTextureClient::dispatchSetBuffersTransform(va_list args) {
212 int transform = va_arg(args, int);
213 return setBuffersTransform(transform);
214}
215
216int SurfaceTextureClient::connect(int api) {
Jamie Gennise5366c52011-01-12 20:22:41 -0800217 LOGV("SurfaceTextureClient::connect");
Jamie Gennis8ba32fa2010-12-20 11:27:26 -0800218 // XXX: Implement this!
219 return INVALID_OPERATION;
220}
221
222int SurfaceTextureClient::disconnect(int api) {
Jamie Gennise5366c52011-01-12 20:22:41 -0800223 LOGV("SurfaceTextureClient::disconnect");
Jamie Gennis8ba32fa2010-12-20 11:27:26 -0800224 // XXX: Implement this!
225 return INVALID_OPERATION;
226}
227
228int SurfaceTextureClient::setUsage(uint32_t reqUsage)
229{
Jamie Gennise5366c52011-01-12 20:22:41 -0800230 LOGV("SurfaceTextureClient::setUsage");
Jamie Gennis8ba32fa2010-12-20 11:27:26 -0800231 Mutex::Autolock lock(mMutex);
232 mReqUsage = reqUsage;
233 return OK;
234}
235
236int SurfaceTextureClient::setCrop(Rect const* rect)
237{
Jamie Gennise5366c52011-01-12 20:22:41 -0800238 LOGV("SurfaceTextureClient::setCrop");
Jamie Gennis8ba32fa2010-12-20 11:27:26 -0800239 Mutex::Autolock lock(mMutex);
240
241 // empty/invalid rects are not allowed
242 if (rect->isEmpty())
243 return BAD_VALUE;
244
245 status_t err = mSurfaceTexture->setCrop(*rect);
246 LOGE_IF(err, "ISurfaceTexture::setCrop(...) returned %s",
247 strerror(-err));
248
249 return err;
250}
251
252int SurfaceTextureClient::setBufferCount(int bufferCount)
253{
Jamie Gennise5366c52011-01-12 20:22:41 -0800254 LOGV("SurfaceTextureClient::setBufferCount");
Jamie Gennis8ba32fa2010-12-20 11:27:26 -0800255 Mutex::Autolock lock(mMutex);
256
257 status_t err = mSurfaceTexture->setBufferCount(bufferCount);
258 LOGE_IF(err, "ISurfaceTexture::setBufferCount(%d) returned %s",
259 bufferCount, strerror(-err));
260
261 if (err == NO_ERROR) {
262 freeAllBuffers();
263 }
264
265 return err;
266}
267
268int SurfaceTextureClient::setBuffersGeometry(int w, int h, int format)
269{
Jamie Gennise5366c52011-01-12 20:22:41 -0800270 LOGV("SurfaceTextureClient::setBuffersGeometry");
Jamie Gennis8ba32fa2010-12-20 11:27:26 -0800271 Mutex::Autolock lock(mMutex);
272
273 if (w<0 || h<0 || format<0)
274 return BAD_VALUE;
275
276 if ((w && !h) || (!w && h))
277 return BAD_VALUE;
278
279 mReqWidth = w;
280 mReqHeight = h;
281 mReqFormat = format;
282
283 return NO_ERROR;
284}
285
286int SurfaceTextureClient::setBuffersTransform(int transform)
287{
Jamie Gennise5366c52011-01-12 20:22:41 -0800288 LOGV("SurfaceTextureClient::setBuffersTransform");
Jamie Gennis8ba32fa2010-12-20 11:27:26 -0800289 Mutex::Autolock lock(mMutex);
290 status_t err = mSurfaceTexture->setTransform(transform);
291 return err;
292}
293
294void SurfaceTextureClient::freeAllBuffers() {
295 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
296 mSlots[i] = 0;
297 }
298}
299
300}; // namespace android