SurfaceTextureClient.cpp revision 749172269ac6b6f7a430e64f604e7f040524e0a1
1/*
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"
18//#define LOG_NDEBUG 0
19
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) {
86    LOGV("SurfaceTextureClient::dequeueBuffer");
87    Mutex::Autolock lock(mMutex);
88    int buf = -1;
89    status_t err = mSurfaceTexture->dequeueBuffer(&buf);
90    if (err < 0) {
91        LOGV("dequeueBuffer: ISurfaceTexture::dequeueBuffer failed: %d", err);
92        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) {
102            LOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed");
103            return NO_MEMORY;
104        }
105    }
106    *buffer = gbuf.get();
107    return OK;
108}
109
110int SurfaceTextureClient::cancelBuffer(android_native_buffer_t* buffer) {
111    LOGV("SurfaceTextureClient::cancelBuffer");
112    Mutex::Autolock lock(mMutex);
113    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
114        if (mSlots[i]->handle == buffer->handle) {
115            mSurfaceTexture->cancelBuffer(i);
116            return OK;
117        }
118    }
119    return BAD_VALUE;
120}
121
122int SurfaceTextureClient::lockBuffer(android_native_buffer_t* buffer) {
123    LOGV("SurfaceTextureClient::lockBuffer");
124    Mutex::Autolock lock(mMutex);
125    return OK;
126}
127
128int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) {
129    LOGV("SurfaceTextureClient::queueBuffer");
130    Mutex::Autolock lock(mMutex);
131    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
132        if (mSlots[i]->handle == buffer->handle) {
133            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) {
141    LOGV("SurfaceTextureClient::query");
142    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) {
217    LOGV("SurfaceTextureClient::connect");
218    // XXX: Implement this!
219    return INVALID_OPERATION;
220}
221
222int SurfaceTextureClient::disconnect(int api) {
223    LOGV("SurfaceTextureClient::disconnect");
224    // XXX: Implement this!
225    return INVALID_OPERATION;
226}
227
228int SurfaceTextureClient::setUsage(uint32_t reqUsage)
229{
230    LOGV("SurfaceTextureClient::setUsage");
231    Mutex::Autolock lock(mMutex);
232    mReqUsage = reqUsage;
233    return OK;
234}
235
236int SurfaceTextureClient::setCrop(Rect const* rect)
237{
238    LOGV("SurfaceTextureClient::setCrop");
239    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{
254    LOGV("SurfaceTextureClient::setBufferCount");
255    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{
270    LOGV("SurfaceTextureClient::setBuffersGeometry");
271    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{
288    LOGV("SurfaceTextureClient::setBuffersTransform");
289    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
301