blob: 1762a4a1ce0a6748a3e84d971df41df6e77c2e3b [file] [log] [blame]
Daniel Lam6b091c52012-01-22 15:26:27 -08001/*
2 * Copyright (C) 2012 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 "BufferQueue"
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080018#define ATRACE_TAG ATRACE_TAG_GRAPHICS
Jamie Gennisfa5b40e2012-03-15 14:01:24 -070019//#define LOG_NDEBUG 0
Daniel Lam6b091c52012-01-22 15:26:27 -080020
21#define GL_GLEXT_PROTOTYPES
22#define EGL_EGLEXT_PROTOTYPES
23
24#include <EGL/egl.h>
25#include <EGL/eglext.h>
26
27#include <gui/BufferQueue.h>
Mathias Agopian90ac7992012-02-25 18:48:35 -080028#include <gui/ISurfaceComposer.h>
Daniel Lam6b091c52012-01-22 15:26:27 -080029#include <private/gui/ComposerService.h>
Daniel Lam6b091c52012-01-22 15:26:27 -080030
31#include <utils/Log.h>
Daniel Lameae59d22012-01-22 15:26:27 -080032#include <gui/SurfaceTexture.h>
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080033#include <utils/Trace.h>
Daniel Lam6b091c52012-01-22 15:26:27 -080034
35// This compile option causes SurfaceTexture to return the buffer that is currently
36// attached to the GL texture from dequeueBuffer when no other buffers are
37// available. It requires the drivers (Gralloc, GL, OMX IL, and Camera) to do
38// implicit cross-process synchronization to prevent the buffer from being
39// written to before the buffer has (a) been detached from the GL texture and
40// (b) all GL reads from the buffer have completed.
Daniel Lameae59d22012-01-22 15:26:27 -080041
42// During refactoring, do not support dequeuing the current buffer
43#undef ALLOW_DEQUEUE_CURRENT_BUFFER
44
Daniel Lam6b091c52012-01-22 15:26:27 -080045#ifdef ALLOW_DEQUEUE_CURRENT_BUFFER
46#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER true
47#warning "ALLOW_DEQUEUE_CURRENT_BUFFER enabled"
48#else
49#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER false
50#endif
51
52// Macros for including the BufferQueue name in log messages
Daniel Lameae59d22012-01-22 15:26:27 -080053#define ST_LOGV(x, ...) ALOGV("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
54#define ST_LOGD(x, ...) ALOGD("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
55#define ST_LOGI(x, ...) ALOGI("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
56#define ST_LOGW(x, ...) ALOGW("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
57#define ST_LOGE(x, ...) ALOGE("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
Daniel Lam6b091c52012-01-22 15:26:27 -080058
Mathias Agopian546ed2d2012-03-01 22:11:25 -080059#define ATRACE_BUFFER_INDEX(index) \
60 char ___traceBuf[1024]; \
61 snprintf(___traceBuf, 1024, "%s: %d", mConsumerName.string(), (index)); \
62 android::ScopedTrace ___bufTracer(ATRACE_TAG, ___traceBuf);
63
Daniel Lam6b091c52012-01-22 15:26:27 -080064namespace android {
65
66// Get an ID that's unique within this process.
67static int32_t createProcessUniqueId() {
68 static volatile int32_t globalCounter = 0;
69 return android_atomic_inc(&globalCounter);
70}
71
72BufferQueue::BufferQueue( bool allowSynchronousMode ) :
73 mDefaultWidth(1),
74 mDefaultHeight(1),
75 mPixelFormat(PIXEL_FORMAT_RGBA_8888),
76 mBufferCount(MIN_ASYNC_BUFFER_SLOTS),
77 mClientBufferCount(0),
78 mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS),
Daniel Lam6b091c52012-01-22 15:26:27 -080079 mSynchronousMode(false),
80 mAllowSynchronousMode(allowSynchronousMode),
81 mConnectedApi(NO_CONNECTED_API),
82 mAbandoned(false),
Daniel Lameae59d22012-01-22 15:26:27 -080083 mFrameCounter(0),
Daniel Lamb2675792012-02-23 14:35:13 -080084 mBufferHasBeenQueued(false),
85 mDefaultBufferFormat(0),
86 mConsumerUsageBits(0),
87 mTransformHint(0)
Daniel Lam6b091c52012-01-22 15:26:27 -080088{
89 // Choose a name using the PID and a process-unique ID.
Daniel Lameae59d22012-01-22 15:26:27 -080090 mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
Daniel Lam6b091c52012-01-22 15:26:27 -080091
92 ST_LOGV("BufferQueue");
93 sp<ISurfaceComposer> composer(ComposerService::getComposerService());
94 mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
Daniel Lam6b091c52012-01-22 15:26:27 -080095}
96
97BufferQueue::~BufferQueue() {
98 ST_LOGV("~BufferQueue");
99}
100
101status_t BufferQueue::setBufferCountServerLocked(int bufferCount) {
102 if (bufferCount > NUM_BUFFER_SLOTS)
103 return BAD_VALUE;
104
105 // special-case, nothing to do
106 if (bufferCount == mBufferCount)
107 return OK;
108
109 if (!mClientBufferCount &&
110 bufferCount >= mBufferCount) {
111 // easy, we just have more buffers
112 mBufferCount = bufferCount;
113 mServerBufferCount = bufferCount;
Dave Burke74ff8c22012-03-12 21:49:41 -0700114 mDequeueCondition.broadcast();
Daniel Lam6b091c52012-01-22 15:26:27 -0800115 } else {
116 // we're here because we're either
117 // - reducing the number of available buffers
118 // - or there is a client-buffer-count in effect
119
120 // less than 2 buffers is never allowed
121 if (bufferCount < 2)
122 return BAD_VALUE;
123
124 // when there is non client-buffer-count in effect, the client is not
125 // allowed to dequeue more than one buffer at a time,
126 // so the next time they dequeue a buffer, we know that they don't
127 // own one. the actual resizing will happen during the next
128 // dequeueBuffer.
129
130 mServerBufferCount = bufferCount;
Daniel Lamb2675792012-02-23 14:35:13 -0800131 mDequeueCondition.broadcast();
Daniel Lam6b091c52012-01-22 15:26:27 -0800132 }
133 return OK;
134}
135
Daniel Lameae59d22012-01-22 15:26:27 -0800136bool BufferQueue::isSynchronousMode() const {
137 Mutex::Autolock lock(mMutex);
138 return mSynchronousMode;
139}
140
141void BufferQueue::setConsumerName(const String8& name) {
142 Mutex::Autolock lock(mMutex);
143 mConsumerName = name;
144}
145
Daniel Lamb2675792012-02-23 14:35:13 -0800146status_t BufferQueue::setDefaultBufferFormat(uint32_t defaultFormat) {
147 Mutex::Autolock lock(mMutex);
148 mDefaultBufferFormat = defaultFormat;
149 return OK;
150}
151
152status_t BufferQueue::setConsumerUsageBits(uint32_t usage) {
153 Mutex::Autolock lock(mMutex);
154 mConsumerUsageBits = usage;
155 return OK;
156}
157
158status_t BufferQueue::setTransformHint(uint32_t hint) {
159 Mutex::Autolock lock(mMutex);
160 mTransformHint = hint;
161 return OK;
162}
163
Daniel Lam6b091c52012-01-22 15:26:27 -0800164status_t BufferQueue::setBufferCount(int bufferCount) {
165 ST_LOGV("setBufferCount: count=%d", bufferCount);
166 Mutex::Autolock lock(mMutex);
167
168 if (mAbandoned) {
169 ST_LOGE("setBufferCount: SurfaceTexture has been abandoned!");
170 return NO_INIT;
171 }
172 if (bufferCount > NUM_BUFFER_SLOTS) {
173 ST_LOGE("setBufferCount: bufferCount larger than slots available");
174 return BAD_VALUE;
175 }
176
177 // Error out if the user has dequeued buffers
178 for (int i=0 ; i<mBufferCount ; i++) {
179 if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
180 ST_LOGE("setBufferCount: client owns some buffers");
181 return -EINVAL;
182 }
183 }
184
185 const int minBufferSlots = mSynchronousMode ?
186 MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
187 if (bufferCount == 0) {
188 mClientBufferCount = 0;
189 bufferCount = (mServerBufferCount >= minBufferSlots) ?
190 mServerBufferCount : minBufferSlots;
191 return setBufferCountServerLocked(bufferCount);
192 }
193
194 if (bufferCount < minBufferSlots) {
195 ST_LOGE("setBufferCount: requested buffer count (%d) is less than "
196 "minimum (%d)", bufferCount, minBufferSlots);
197 return BAD_VALUE;
198 }
199
200 // here we're guaranteed that the client doesn't have dequeued buffers
201 // and will release all of its buffer references.
202 freeAllBuffersLocked();
203 mBufferCount = bufferCount;
204 mClientBufferCount = bufferCount;
Daniel Lameae59d22012-01-22 15:26:27 -0800205 mBufferHasBeenQueued = false;
Daniel Lam6b091c52012-01-22 15:26:27 -0800206 mQueue.clear();
Dave Burke74ff8c22012-03-12 21:49:41 -0700207 mDequeueCondition.broadcast();
Daniel Lam6b091c52012-01-22 15:26:27 -0800208 return OK;
209}
210
Daniel Lamb8560522012-01-30 15:51:27 -0800211int BufferQueue::query(int what, int* outValue)
212{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800213 ATRACE_CALL();
Daniel Lamb8560522012-01-30 15:51:27 -0800214 Mutex::Autolock lock(mMutex);
215
216 if (mAbandoned) {
217 ST_LOGE("query: SurfaceTexture has been abandoned!");
218 return NO_INIT;
219 }
220
221 int value;
222 switch (what) {
223 case NATIVE_WINDOW_WIDTH:
224 value = mDefaultWidth;
225 break;
226 case NATIVE_WINDOW_HEIGHT:
227 value = mDefaultHeight;
228 break;
229 case NATIVE_WINDOW_FORMAT:
230 value = mPixelFormat;
231 break;
232 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
233 value = mSynchronousMode ?
234 (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS;
235 break;
236 default:
237 return BAD_VALUE;
238 }
239 outValue[0] = value;
240 return NO_ERROR;
241}
242
Daniel Lam6b091c52012-01-22 15:26:27 -0800243status_t BufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800244 ATRACE_CALL();
Daniel Lam6b091c52012-01-22 15:26:27 -0800245 ST_LOGV("requestBuffer: slot=%d", slot);
246 Mutex::Autolock lock(mMutex);
247 if (mAbandoned) {
248 ST_LOGE("requestBuffer: SurfaceTexture has been abandoned!");
249 return NO_INIT;
250 }
251 if (slot < 0 || mBufferCount <= slot) {
252 ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d",
253 mBufferCount, slot);
254 return BAD_VALUE;
255 }
256 mSlots[slot].mRequestBufferCalled = true;
257 *buf = mSlots[slot].mGraphicBuffer;
258 return NO_ERROR;
259}
260
261status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
262 uint32_t format, uint32_t usage) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800263 ATRACE_CALL();
Daniel Lam6b091c52012-01-22 15:26:27 -0800264 ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);
265
266 if ((w && !h) || (!w && h)) {
267 ST_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
268 return BAD_VALUE;
269 }
270
271 status_t returnFlags(OK);
272 EGLDisplay dpy = EGL_NO_DISPLAY;
273 EGLSyncKHR fence = EGL_NO_SYNC_KHR;
274
275 { // Scope for the lock
276 Mutex::Autolock lock(mMutex);
277
Daniel Lamb2675792012-02-23 14:35:13 -0800278 if (format == 0) {
279 format = mDefaultBufferFormat;
280 }
281 // turn on usage bits the consumer requested
282 usage |= mConsumerUsageBits;
283
Daniel Lam6b091c52012-01-22 15:26:27 -0800284 int found = -1;
285 int foundSync = -1;
286 int dequeuedCount = 0;
287 bool tryAgain = true;
288 while (tryAgain) {
289 if (mAbandoned) {
290 ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
291 return NO_INIT;
292 }
293
294 // We need to wait for the FIFO to drain if the number of buffer
295 // needs to change.
296 //
297 // The condition "number of buffers needs to change" is true if
298 // - the client doesn't care about how many buffers there are
299 // - AND the actual number of buffer is different from what was
300 // set in the last setBufferCountServer()
301 // - OR -
302 // setBufferCountServer() was set to a value incompatible with
303 // the synchronization mode (for instance because the sync mode
304 // changed since)
305 //
306 // As long as this condition is true AND the FIFO is not empty, we
307 // wait on mDequeueCondition.
308
309 const int minBufferCountNeeded = mSynchronousMode ?
310 MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
311
312 const bool numberOfBuffersNeedsToChange = !mClientBufferCount &&
313 ((mServerBufferCount != mBufferCount) ||
314 (mServerBufferCount < minBufferCountNeeded));
315
316 if (!mQueue.isEmpty() && numberOfBuffersNeedsToChange) {
317 // wait for the FIFO to drain
318 mDequeueCondition.wait(mMutex);
319 // NOTE: we continue here because we need to reevaluate our
320 // whole state (eg: we could be abandoned or disconnected)
321 continue;
322 }
323
324 if (numberOfBuffersNeedsToChange) {
325 // here we're guaranteed that mQueue is empty
326 freeAllBuffersLocked();
327 mBufferCount = mServerBufferCount;
328 if (mBufferCount < minBufferCountNeeded)
329 mBufferCount = minBufferCountNeeded;
Daniel Lameae59d22012-01-22 15:26:27 -0800330 mBufferHasBeenQueued = false;
Daniel Lam6b091c52012-01-22 15:26:27 -0800331 returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
332 }
333
334 // look for a free buffer to give to the client
335 found = INVALID_BUFFER_SLOT;
336 foundSync = INVALID_BUFFER_SLOT;
337 dequeuedCount = 0;
338 for (int i = 0; i < mBufferCount; i++) {
339 const int state = mSlots[i].mBufferState;
340 if (state == BufferSlot::DEQUEUED) {
341 dequeuedCount++;
342 }
343
Daniel Lameae59d22012-01-22 15:26:27 -0800344 // this logic used to be if (FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER)
345 // but dequeuing the current buffer is disabled.
346 if (false) {
347 // This functionality has been temporarily removed so
348 // BufferQueue and SurfaceTexture can be refactored into
349 // separate objects
Daniel Lam6b091c52012-01-22 15:26:27 -0800350 } else {
351 if (state == BufferSlot::FREE) {
352 /* We return the oldest of the free buffers to avoid
353 * stalling the producer if possible. This is because
354 * the consumer may still have pending reads of the
355 * buffers in flight.
356 */
357 bool isOlder = mSlots[i].mFrameNumber <
358 mSlots[found].mFrameNumber;
359 if (found < 0 || isOlder) {
360 foundSync = i;
361 found = i;
362 }
363 }
364 }
365 }
366
367 // clients are not allowed to dequeue more than one buffer
368 // if they didn't set a buffer count.
369 if (!mClientBufferCount && dequeuedCount) {
370 ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without "
371 "setting the buffer count");
372 return -EINVAL;
373 }
374
375 // See whether a buffer has been queued since the last
376 // setBufferCount so we know whether to perform the
377 // MIN_UNDEQUEUED_BUFFERS check below.
Daniel Lameae59d22012-01-22 15:26:27 -0800378 if (mBufferHasBeenQueued) {
Daniel Lam6b091c52012-01-22 15:26:27 -0800379 // make sure the client is not trying to dequeue more buffers
380 // than allowed.
381 const int avail = mBufferCount - (dequeuedCount+1);
382 if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) {
383 ST_LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded "
384 "(dequeued=%d)",
385 MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode),
386 dequeuedCount);
387 return -EBUSY;
388 }
389 }
390
Daniel Lamc2c1f2f2012-03-07 14:11:29 -0800391 // if no buffer is found, wait for a buffer to be released
392 tryAgain = found == INVALID_BUFFER_SLOT;
Daniel Lam6b091c52012-01-22 15:26:27 -0800393 if (tryAgain) {
394 mDequeueCondition.wait(mMutex);
395 }
396 }
397
Daniel Lam6b091c52012-01-22 15:26:27 -0800398
399 if (found == INVALID_BUFFER_SLOT) {
400 // This should not happen.
401 ST_LOGE("dequeueBuffer: no available buffer slots");
402 return -EBUSY;
403 }
404
405 const int buf = found;
406 *outBuf = found;
407
Mathias Agopian546ed2d2012-03-01 22:11:25 -0800408 ATRACE_BUFFER_INDEX(buf);
409
Daniel Lam6b091c52012-01-22 15:26:27 -0800410 const bool useDefaultSize = !w && !h;
411 if (useDefaultSize) {
412 // use the default size
413 w = mDefaultWidth;
414 h = mDefaultHeight;
415 }
416
417 const bool updateFormat = (format != 0);
418 if (!updateFormat) {
419 // keep the current (or default) format
420 format = mPixelFormat;
421 }
422
423 // buffer is now in DEQUEUED (but can also be current at the same time,
424 // if we're in synchronous mode)
425 mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
426
427 const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
428 if ((buffer == NULL) ||
429 (uint32_t(buffer->width) != w) ||
430 (uint32_t(buffer->height) != h) ||
431 (uint32_t(buffer->format) != format) ||
432 ((uint32_t(buffer->usage) & usage) != usage))
433 {
434 usage |= GraphicBuffer::USAGE_HW_TEXTURE;
435 status_t error;
436 sp<GraphicBuffer> graphicBuffer(
437 mGraphicBufferAlloc->createGraphicBuffer(
438 w, h, format, usage, &error));
439 if (graphicBuffer == 0) {
440 ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer "
441 "failed");
442 return error;
443 }
444 if (updateFormat) {
445 mPixelFormat = format;
446 }
Daniel Lameae59d22012-01-22 15:26:27 -0800447
448 mSlots[buf].mAcquireCalled = false;
Daniel Lam6b091c52012-01-22 15:26:27 -0800449 mSlots[buf].mGraphicBuffer = graphicBuffer;
450 mSlots[buf].mRequestBufferCalled = false;
451 mSlots[buf].mFence = EGL_NO_SYNC_KHR;
Daniel Lameae59d22012-01-22 15:26:27 -0800452 mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
453
Daniel Lam6b091c52012-01-22 15:26:27 -0800454 returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
455 }
456
457 dpy = mSlots[buf].mEglDisplay;
458 fence = mSlots[buf].mFence;
459 mSlots[buf].mFence = EGL_NO_SYNC_KHR;
Daniel Lameae59d22012-01-22 15:26:27 -0800460 } // end lock scope
Daniel Lam6b091c52012-01-22 15:26:27 -0800461
462 if (fence != EGL_NO_SYNC_KHR) {
463 EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
464 // If something goes wrong, log the error, but return the buffer without
465 // synchronizing access to it. It's too late at this point to abort the
466 // dequeue operation.
467 if (result == EGL_FALSE) {
468 ALOGE("dequeueBuffer: error waiting for fence: %#x", eglGetError());
469 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
470 ALOGE("dequeueBuffer: timeout waiting for fence");
471 }
472 eglDestroySyncKHR(dpy, fence);
473 }
474
475 ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf,
476 mSlots[*outBuf].mGraphicBuffer->handle, returnFlags);
477
478 return returnFlags;
479}
480
481status_t BufferQueue::setSynchronousMode(bool enabled) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800482 ATRACE_CALL();
Daniel Lam6b091c52012-01-22 15:26:27 -0800483 ST_LOGV("setSynchronousMode: enabled=%d", enabled);
484 Mutex::Autolock lock(mMutex);
485
486 if (mAbandoned) {
487 ST_LOGE("setSynchronousMode: SurfaceTexture has been abandoned!");
488 return NO_INIT;
489 }
490
491 status_t err = OK;
492 if (!mAllowSynchronousMode && enabled)
493 return err;
494
495 if (!enabled) {
496 // going to asynchronous mode, drain the queue
497 err = drainQueueLocked();
498 if (err != NO_ERROR)
499 return err;
500 }
501
502 if (mSynchronousMode != enabled) {
503 // - if we're going to asynchronous mode, the queue is guaranteed to be
504 // empty here
505 // - if the client set the number of buffers, we're guaranteed that
506 // we have at least 3 (because we don't allow less)
507 mSynchronousMode = enabled;
Dave Burke74ff8c22012-03-12 21:49:41 -0700508 mDequeueCondition.broadcast();
Daniel Lam6b091c52012-01-22 15:26:27 -0800509 }
510 return err;
511}
512
513status_t BufferQueue::queueBuffer(int buf, int64_t timestamp,
Mathias Agopian851ef8f2012-03-29 17:10:08 -0700514 const Rect& crop, int scalingMode, uint32_t transform,
Daniel Lam6b091c52012-01-22 15:26:27 -0800515 uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800516 ATRACE_CALL();
Mathias Agopian546ed2d2012-03-01 22:11:25 -0800517 ATRACE_BUFFER_INDEX(buf);
518
Daniel Lam6b091c52012-01-22 15:26:27 -0800519 ST_LOGV("queueBuffer: slot=%d time=%lld", buf, timestamp);
520
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700521 sp<ConsumerListener> listener;
Daniel Lam6b091c52012-01-22 15:26:27 -0800522
523 { // scope for the lock
524 Mutex::Autolock lock(mMutex);
525 if (mAbandoned) {
526 ST_LOGE("queueBuffer: SurfaceTexture has been abandoned!");
527 return NO_INIT;
528 }
529 if (buf < 0 || buf >= mBufferCount) {
530 ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d",
531 mBufferCount, buf);
532 return -EINVAL;
533 } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
534 ST_LOGE("queueBuffer: slot %d is not owned by the client "
535 "(state=%d)", buf, mSlots[buf].mBufferState);
536 return -EINVAL;
Daniel Lam6b091c52012-01-22 15:26:27 -0800537 } else if (!mSlots[buf].mRequestBufferCalled) {
538 ST_LOGE("queueBuffer: slot %d was enqueued without requesting a "
539 "buffer", buf);
540 return -EINVAL;
541 }
542
543 if (mSynchronousMode) {
544 // In synchronous mode we queue all buffers in a FIFO.
545 mQueue.push_back(buf);
546
547 // Synchronous mode always signals that an additional frame should
548 // be consumed.
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700549 listener = mConsumerListener;
Daniel Lam6b091c52012-01-22 15:26:27 -0800550 } else {
551 // In asynchronous mode we only keep the most recent buffer.
552 if (mQueue.empty()) {
553 mQueue.push_back(buf);
554
555 // Asynchronous mode only signals that a frame should be
556 // consumed if no previous frame was pending. If a frame were
557 // pending then the consumer would have already been notified.
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700558 listener = mConsumerListener;
Daniel Lam6b091c52012-01-22 15:26:27 -0800559 } else {
560 Fifo::iterator front(mQueue.begin());
561 // buffer currently queued is freed
562 mSlots[*front].mBufferState = BufferSlot::FREE;
563 // and we record the new buffer index in the queued list
564 *front = buf;
565 }
566 }
567
Mathias Agopian851ef8f2012-03-29 17:10:08 -0700568 switch (scalingMode) {
569 case NATIVE_WINDOW_SCALING_MODE_FREEZE:
570 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
571 break;
572 default:
573 ST_LOGE("unknown scaling mode: %d (ignoring)", scalingMode);
574 scalingMode = mSlots[buf].mScalingMode;
575 break;
576 }
577
Daniel Lam6b091c52012-01-22 15:26:27 -0800578 mSlots[buf].mBufferState = BufferSlot::QUEUED;
Mathias Agopian851ef8f2012-03-29 17:10:08 -0700579 mSlots[buf].mCrop = crop;
580 mSlots[buf].mTransform = transform;
581 mSlots[buf].mScalingMode = scalingMode;
Daniel Lam6b091c52012-01-22 15:26:27 -0800582 mSlots[buf].mTimestamp = timestamp;
583 mFrameCounter++;
584 mSlots[buf].mFrameNumber = mFrameCounter;
585
Daniel Lameae59d22012-01-22 15:26:27 -0800586 mBufferHasBeenQueued = true;
Dave Burke74ff8c22012-03-12 21:49:41 -0700587 mDequeueCondition.broadcast();
Daniel Lam6b091c52012-01-22 15:26:27 -0800588
589 *outWidth = mDefaultWidth;
590 *outHeight = mDefaultHeight;
Daniel Lamb2675792012-02-23 14:35:13 -0800591 *outTransform = mTransformHint;
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800592
593 ATRACE_INT(mConsumerName.string(), mQueue.size());
Daniel Lam6b091c52012-01-22 15:26:27 -0800594 } // scope for the lock
595
596 // call back without lock held
597 if (listener != 0) {
598 listener->onFrameAvailable();
599 }
600 return OK;
601}
602
603void BufferQueue::cancelBuffer(int buf) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800604 ATRACE_CALL();
Daniel Lam6b091c52012-01-22 15:26:27 -0800605 ST_LOGV("cancelBuffer: slot=%d", buf);
606 Mutex::Autolock lock(mMutex);
607
608 if (mAbandoned) {
609 ST_LOGW("cancelBuffer: BufferQueue has been abandoned!");
610 return;
611 }
612
613 if (buf < 0 || buf >= mBufferCount) {
614 ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
615 mBufferCount, buf);
616 return;
617 } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
618 ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
619 buf, mSlots[buf].mBufferState);
620 return;
621 }
622 mSlots[buf].mBufferState = BufferSlot::FREE;
623 mSlots[buf].mFrameNumber = 0;
Dave Burke74ff8c22012-03-12 21:49:41 -0700624 mDequeueCondition.broadcast();
Daniel Lam6b091c52012-01-22 15:26:27 -0800625}
626
Daniel Lam6b091c52012-01-22 15:26:27 -0800627status_t BufferQueue::connect(int api,
628 uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800629 ATRACE_CALL();
Daniel Lam6b091c52012-01-22 15:26:27 -0800630 ST_LOGV("connect: api=%d", api);
631 Mutex::Autolock lock(mMutex);
632
633 if (mAbandoned) {
634 ST_LOGE("connect: BufferQueue has been abandoned!");
635 return NO_INIT;
636 }
637
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700638 if (mConsumerListener == NULL) {
639 ST_LOGE("connect: BufferQueue has no consumer!");
640 return NO_INIT;
641 }
642
Daniel Lam6b091c52012-01-22 15:26:27 -0800643 int err = NO_ERROR;
644 switch (api) {
645 case NATIVE_WINDOW_API_EGL:
646 case NATIVE_WINDOW_API_CPU:
647 case NATIVE_WINDOW_API_MEDIA:
648 case NATIVE_WINDOW_API_CAMERA:
649 if (mConnectedApi != NO_CONNECTED_API) {
650 ST_LOGE("connect: already connected (cur=%d, req=%d)",
651 mConnectedApi, api);
652 err = -EINVAL;
653 } else {
654 mConnectedApi = api;
655 *outWidth = mDefaultWidth;
656 *outHeight = mDefaultHeight;
657 *outTransform = 0;
658 }
659 break;
660 default:
661 err = -EINVAL;
662 break;
663 }
Daniel Lameae59d22012-01-22 15:26:27 -0800664
665 mBufferHasBeenQueued = false;
666
Daniel Lam6b091c52012-01-22 15:26:27 -0800667 return err;
668}
669
670status_t BufferQueue::disconnect(int api) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800671 ATRACE_CALL();
Daniel Lam6b091c52012-01-22 15:26:27 -0800672 ST_LOGV("disconnect: api=%d", api);
Daniel Lam6b091c52012-01-22 15:26:27 -0800673
674 int err = NO_ERROR;
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700675 sp<ConsumerListener> listener;
676
677 { // Scope for the lock
678 Mutex::Autolock lock(mMutex);
679
680 if (mAbandoned) {
681 // it is not really an error to disconnect after the surface
682 // has been abandoned, it should just be a no-op.
683 return NO_ERROR;
684 }
685
686 switch (api) {
687 case NATIVE_WINDOW_API_EGL:
688 case NATIVE_WINDOW_API_CPU:
689 case NATIVE_WINDOW_API_MEDIA:
690 case NATIVE_WINDOW_API_CAMERA:
691 if (mConnectedApi == api) {
692 drainQueueAndFreeBuffersLocked();
693 mConnectedApi = NO_CONNECTED_API;
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700694 mDequeueCondition.broadcast();
695 listener = mConsumerListener;
696 } else {
697 ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)",
698 mConnectedApi, api);
699 err = -EINVAL;
700 }
701 break;
702 default:
703 ST_LOGE("disconnect: unknown API %d", api);
Daniel Lam6b091c52012-01-22 15:26:27 -0800704 err = -EINVAL;
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700705 break;
706 }
Daniel Lam6b091c52012-01-22 15:26:27 -0800707 }
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700708
709 if (listener != NULL) {
710 listener->onBuffersReleased();
711 }
712
Daniel Lam6b091c52012-01-22 15:26:27 -0800713 return err;
714}
715
Daniel Lameae59d22012-01-22 15:26:27 -0800716void BufferQueue::dump(String8& result) const
717{
718 char buffer[1024];
719 BufferQueue::dump(result, "", buffer, 1024);
720}
721
722void BufferQueue::dump(String8& result, const char* prefix,
723 char* buffer, size_t SIZE) const
724{
725 Mutex::Autolock _l(mMutex);
Daniel Lameae59d22012-01-22 15:26:27 -0800726
727 String8 fifo;
728 int fifoSize = 0;
729 Fifo::const_iterator i(mQueue.begin());
730 while (i != mQueue.end()) {
731 snprintf(buffer, SIZE, "%02d ", *i++);
732 fifoSize++;
733 fifo.append(buffer);
734 }
735
736 snprintf(buffer, SIZE,
737 "%s-BufferQueue mBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
738 "mPixelFormat=%d, FIFO(%d)={%s}\n",
739 prefix, mBufferCount, mSynchronousMode, mDefaultWidth,
740 mDefaultHeight, mPixelFormat, fifoSize, fifo.string());
741 result.append(buffer);
742
743
744 struct {
745 const char * operator()(int state) const {
746 switch (state) {
747 case BufferSlot::DEQUEUED: return "DEQUEUED";
748 case BufferSlot::QUEUED: return "QUEUED";
749 case BufferSlot::FREE: return "FREE";
750 case BufferSlot::ACQUIRED: return "ACQUIRED";
751 default: return "Unknown";
752 }
753 }
754 } stateName;
755
756 for (int i=0 ; i<mBufferCount ; i++) {
757 const BufferSlot& slot(mSlots[i]);
758 snprintf(buffer, SIZE,
759 "%s%s[%02d] "
760 "state=%-8s, crop=[%d,%d,%d,%d], "
761 "transform=0x%02x, timestamp=%lld",
762 prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i,
763 stateName(slot.mBufferState),
764 slot.mCrop.left, slot.mCrop.top, slot.mCrop.right,
765 slot.mCrop.bottom, slot.mTransform, slot.mTimestamp
766 );
767 result.append(buffer);
768
769 const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
770 if (buf != NULL) {
771 snprintf(buffer, SIZE,
772 ", %p [%4ux%4u:%4u,%3X]",
773 buf->handle, buf->width, buf->height, buf->stride,
774 buf->format);
775 result.append(buffer);
776 }
777 result.append("\n");
778 }
779}
780
Daniel Lam6b091c52012-01-22 15:26:27 -0800781void BufferQueue::freeBufferLocked(int i) {
782 mSlots[i].mGraphicBuffer = 0;
783 mSlots[i].mBufferState = BufferSlot::FREE;
784 mSlots[i].mFrameNumber = 0;
Daniel Lameae59d22012-01-22 15:26:27 -0800785 mSlots[i].mAcquireCalled = false;
786
787 // destroy fence as BufferQueue now takes ownership
788 if (mSlots[i].mFence != EGL_NO_SYNC_KHR) {
789 eglDestroySyncKHR(mSlots[i].mEglDisplay, mSlots[i].mFence);
790 mSlots[i].mFence = EGL_NO_SYNC_KHR;
Daniel Lam6b091c52012-01-22 15:26:27 -0800791 }
792}
793
794void BufferQueue::freeAllBuffersLocked() {
795 ALOGW_IF(!mQueue.isEmpty(),
796 "freeAllBuffersLocked called but mQueue is not empty");
Daniel Lameae59d22012-01-22 15:26:27 -0800797 mQueue.clear();
798 mBufferHasBeenQueued = false;
Daniel Lam6b091c52012-01-22 15:26:27 -0800799 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
800 freeBufferLocked(i);
801 }
802}
803
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700804status_t BufferQueue::acquireBuffer(BufferItem *buffer) {
Mathias Agopian546ed2d2012-03-01 22:11:25 -0800805 ATRACE_CALL();
Daniel Lameae59d22012-01-22 15:26:27 -0800806 Mutex::Autolock _l(mMutex);
807 // check if queue is empty
808 // In asynchronous mode the list is guaranteed to be one buffer
809 // deep, while in synchronous mode we use the oldest buffer.
810 if (!mQueue.empty()) {
811 Fifo::iterator front(mQueue.begin());
812 int buf = *front;
813
Mathias Agopian546ed2d2012-03-01 22:11:25 -0800814 ATRACE_BUFFER_INDEX(buf);
815
Daniel Lameae59d22012-01-22 15:26:27 -0800816 if (mSlots[buf].mAcquireCalled) {
817 buffer->mGraphicBuffer = NULL;
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700818 } else {
Daniel Lameae59d22012-01-22 15:26:27 -0800819 buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer;
820 }
821 buffer->mCrop = mSlots[buf].mCrop;
822 buffer->mTransform = mSlots[buf].mTransform;
823 buffer->mScalingMode = mSlots[buf].mScalingMode;
824 buffer->mFrameNumber = mSlots[buf].mFrameNumber;
Daniel Lam3fcee502012-03-02 10:17:34 -0800825 buffer->mTimestamp = mSlots[buf].mTimestamp;
Daniel Lameae59d22012-01-22 15:26:27 -0800826 buffer->mBuf = buf;
827 mSlots[buf].mAcquireCalled = true;
828
829 mSlots[buf].mBufferState = BufferSlot::ACQUIRED;
830 mQueue.erase(front);
Dave Burke74ff8c22012-03-12 21:49:41 -0700831 mDequeueCondition.broadcast();
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800832
833 ATRACE_INT(mConsumerName.string(), mQueue.size());
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700834 } else {
Daniel Lamb2675792012-02-23 14:35:13 -0800835 // should be a better return code?
836 return -EINVAL;
Daniel Lameae59d22012-01-22 15:26:27 -0800837 }
838
839 return OK;
840}
841
842status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display,
843 EGLSyncKHR fence) {
Mathias Agopian546ed2d2012-03-01 22:11:25 -0800844 ATRACE_CALL();
845 ATRACE_BUFFER_INDEX(buf);
846
Daniel Lameae59d22012-01-22 15:26:27 -0800847 Mutex::Autolock _l(mMutex);
848
849 if (buf == INVALID_BUFFER_SLOT) {
850 return -EINVAL;
851 }
852
853 mSlots[buf].mEglDisplay = display;
854 mSlots[buf].mFence = fence;
855
856 // The current buffer becomes FREE if it was still in the queued
857 // state. If it has already been given to the client
858 // (synchronous mode), then it stays in DEQUEUED state.
859 if (mSlots[buf].mBufferState == BufferSlot::QUEUED
860 || mSlots[buf].mBufferState == BufferSlot::ACQUIRED) {
861 mSlots[buf].mBufferState = BufferSlot::FREE;
862 }
Dave Burke74ff8c22012-03-12 21:49:41 -0700863 mDequeueCondition.broadcast();
Daniel Lameae59d22012-01-22 15:26:27 -0800864
865 return OK;
866}
867
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700868status_t BufferQueue::consumerConnect(const sp<ConsumerListener>& consumerListener) {
869 ST_LOGV("consumerConnect");
Daniel Lameae59d22012-01-22 15:26:27 -0800870 Mutex::Autolock lock(mMutex);
Daniel Lamb2675792012-02-23 14:35:13 -0800871
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700872 if (mAbandoned) {
873 ST_LOGE("consumerConnect: BufferQueue has been abandoned!");
874 return NO_INIT;
875 }
Daniel Lamb2675792012-02-23 14:35:13 -0800876
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700877 mConsumerListener = consumerListener;
878
879 return OK;
880}
881
882status_t BufferQueue::consumerDisconnect() {
883 ST_LOGV("consumerDisconnect");
884 Mutex::Autolock lock(mMutex);
885
886 if (mConsumerListener == NULL) {
887 ST_LOGE("consumerDisconnect: No consumer is connected!");
888 return -EINVAL;
889 }
890
891 mAbandoned = true;
892 mConsumerListener = NULL;
Daniel Lamb2675792012-02-23 14:35:13 -0800893 mQueue.clear();
Daniel Lameae59d22012-01-22 15:26:27 -0800894 freeAllBuffersLocked();
Dave Burke74ff8c22012-03-12 21:49:41 -0700895 mDequeueCondition.broadcast();
Daniel Lameae59d22012-01-22 15:26:27 -0800896 return OK;
897}
898
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700899status_t BufferQueue::getReleasedBuffers(uint32_t* slotMask) {
900 ST_LOGV("getReleasedBuffers");
901 Mutex::Autolock lock(mMutex);
902
903 if (mAbandoned) {
904 ST_LOGE("getReleasedBuffers: BufferQueue has been abandoned!");
905 return NO_INIT;
906 }
907
908 uint32_t mask = 0;
909 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
910 if (!mSlots[i].mAcquireCalled) {
911 mask |= 1 << i;
912 }
913 }
914 *slotMask = mask;
915
916 ST_LOGV("getReleasedBuffers: returning mask %#x", mask);
917 return NO_ERROR;
918}
919
Daniel Lameae59d22012-01-22 15:26:27 -0800920status_t BufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h)
921{
922 ST_LOGV("setDefaultBufferSize: w=%d, h=%d", w, h);
923 if (!w || !h) {
924 ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)",
925 w, h);
926 return BAD_VALUE;
927 }
928
929 Mutex::Autolock lock(mMutex);
930 mDefaultWidth = w;
931 mDefaultHeight = h;
932 return OK;
933}
934
935status_t BufferQueue::setBufferCountServer(int bufferCount) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800936 ATRACE_CALL();
Daniel Lameae59d22012-01-22 15:26:27 -0800937 Mutex::Autolock lock(mMutex);
938 return setBufferCountServerLocked(bufferCount);
939}
940
Daniel Lam6b091c52012-01-22 15:26:27 -0800941void BufferQueue::freeAllBuffersExceptHeadLocked() {
942 ALOGW_IF(!mQueue.isEmpty(),
943 "freeAllBuffersExceptCurrentLocked called but mQueue is not empty");
944 int head = -1;
945 if (!mQueue.empty()) {
946 Fifo::iterator front(mQueue.begin());
947 head = *front;
948 }
Daniel Lameae59d22012-01-22 15:26:27 -0800949 mBufferHasBeenQueued = false;
Daniel Lam6b091c52012-01-22 15:26:27 -0800950 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
951 if (i != head) {
952 freeBufferLocked(i);
953 }
954 }
955}
956
957status_t BufferQueue::drainQueueLocked() {
958 while (mSynchronousMode && !mQueue.isEmpty()) {
959 mDequeueCondition.wait(mMutex);
960 if (mAbandoned) {
961 ST_LOGE("drainQueueLocked: BufferQueue has been abandoned!");
962 return NO_INIT;
963 }
964 if (mConnectedApi == NO_CONNECTED_API) {
965 ST_LOGE("drainQueueLocked: BufferQueue is not connected!");
966 return NO_INIT;
967 }
968 }
969 return NO_ERROR;
970}
971
972status_t BufferQueue::drainQueueAndFreeBuffersLocked() {
973 status_t err = drainQueueLocked();
974 if (err == NO_ERROR) {
975 if (mSynchronousMode) {
976 freeAllBuffersLocked();
977 } else {
978 freeAllBuffersExceptHeadLocked();
979 }
980 }
981 return err;
982}
983
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700984BufferQueue::ProxyConsumerListener::ProxyConsumerListener(
985 const wp<BufferQueue::ConsumerListener>& consumerListener):
986 mConsumerListener(consumerListener) {}
987
988BufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {}
989
990void BufferQueue::ProxyConsumerListener::onFrameAvailable() {
991 sp<BufferQueue::ConsumerListener> listener(mConsumerListener.promote());
992 if (listener != NULL) {
993 listener->onFrameAvailable();
994 }
995}
996
997void BufferQueue::ProxyConsumerListener::onBuffersReleased() {
998 sp<BufferQueue::ConsumerListener> listener(mConsumerListener.promote());
999 if (listener != NULL) {
1000 listener->onBuffersReleased();
1001 }
1002}
1003
Daniel Lam6b091c52012-01-22 15:26:27 -08001004}; // namespace android