blob: ffc5fa02a93fc955f3159123d32d0c3ade699c79 [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 mNextTransform(0),
80 mNextScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
81 mSynchronousMode(false),
82 mAllowSynchronousMode(allowSynchronousMode),
83 mConnectedApi(NO_CONNECTED_API),
84 mAbandoned(false),
Daniel Lameae59d22012-01-22 15:26:27 -080085 mFrameCounter(0),
Daniel Lamb2675792012-02-23 14:35:13 -080086 mBufferHasBeenQueued(false),
87 mDefaultBufferFormat(0),
88 mConsumerUsageBits(0),
89 mTransformHint(0)
Daniel Lam6b091c52012-01-22 15:26:27 -080090{
91 // Choose a name using the PID and a process-unique ID.
Daniel Lameae59d22012-01-22 15:26:27 -080092 mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
Daniel Lam6b091c52012-01-22 15:26:27 -080093
94 ST_LOGV("BufferQueue");
95 sp<ISurfaceComposer> composer(ComposerService::getComposerService());
96 mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
97 mNextCrop.makeInvalid();
98}
99
100BufferQueue::~BufferQueue() {
101 ST_LOGV("~BufferQueue");
102}
103
104status_t BufferQueue::setBufferCountServerLocked(int bufferCount) {
105 if (bufferCount > NUM_BUFFER_SLOTS)
106 return BAD_VALUE;
107
108 // special-case, nothing to do
109 if (bufferCount == mBufferCount)
110 return OK;
111
112 if (!mClientBufferCount &&
113 bufferCount >= mBufferCount) {
114 // easy, we just have more buffers
115 mBufferCount = bufferCount;
116 mServerBufferCount = bufferCount;
Dave Burke74ff8c22012-03-12 21:49:41 -0700117 mDequeueCondition.broadcast();
Daniel Lam6b091c52012-01-22 15:26:27 -0800118 } else {
119 // we're here because we're either
120 // - reducing the number of available buffers
121 // - or there is a client-buffer-count in effect
122
123 // less than 2 buffers is never allowed
124 if (bufferCount < 2)
125 return BAD_VALUE;
126
127 // when there is non client-buffer-count in effect, the client is not
128 // allowed to dequeue more than one buffer at a time,
129 // so the next time they dequeue a buffer, we know that they don't
130 // own one. the actual resizing will happen during the next
131 // dequeueBuffer.
132
133 mServerBufferCount = bufferCount;
Daniel Lamb2675792012-02-23 14:35:13 -0800134 mDequeueCondition.broadcast();
Daniel Lam6b091c52012-01-22 15:26:27 -0800135 }
136 return OK;
137}
138
Daniel Lameae59d22012-01-22 15:26:27 -0800139bool BufferQueue::isSynchronousMode() const {
140 Mutex::Autolock lock(mMutex);
141 return mSynchronousMode;
142}
143
144void BufferQueue::setConsumerName(const String8& name) {
145 Mutex::Autolock lock(mMutex);
146 mConsumerName = name;
147}
148
Daniel Lamb2675792012-02-23 14:35:13 -0800149status_t BufferQueue::setDefaultBufferFormat(uint32_t defaultFormat) {
150 Mutex::Autolock lock(mMutex);
151 mDefaultBufferFormat = defaultFormat;
152 return OK;
153}
154
155status_t BufferQueue::setConsumerUsageBits(uint32_t usage) {
156 Mutex::Autolock lock(mMutex);
157 mConsumerUsageBits = usage;
158 return OK;
159}
160
161status_t BufferQueue::setTransformHint(uint32_t hint) {
162 Mutex::Autolock lock(mMutex);
163 mTransformHint = hint;
164 return OK;
165}
166
Daniel Lam6b091c52012-01-22 15:26:27 -0800167status_t BufferQueue::setBufferCount(int bufferCount) {
168 ST_LOGV("setBufferCount: count=%d", bufferCount);
169 Mutex::Autolock lock(mMutex);
170
171 if (mAbandoned) {
172 ST_LOGE("setBufferCount: SurfaceTexture has been abandoned!");
173 return NO_INIT;
174 }
175 if (bufferCount > NUM_BUFFER_SLOTS) {
176 ST_LOGE("setBufferCount: bufferCount larger than slots available");
177 return BAD_VALUE;
178 }
179
180 // Error out if the user has dequeued buffers
181 for (int i=0 ; i<mBufferCount ; i++) {
182 if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
183 ST_LOGE("setBufferCount: client owns some buffers");
184 return -EINVAL;
185 }
186 }
187
188 const int minBufferSlots = mSynchronousMode ?
189 MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
190 if (bufferCount == 0) {
191 mClientBufferCount = 0;
192 bufferCount = (mServerBufferCount >= minBufferSlots) ?
193 mServerBufferCount : minBufferSlots;
194 return setBufferCountServerLocked(bufferCount);
195 }
196
197 if (bufferCount < minBufferSlots) {
198 ST_LOGE("setBufferCount: requested buffer count (%d) is less than "
199 "minimum (%d)", bufferCount, minBufferSlots);
200 return BAD_VALUE;
201 }
202
203 // here we're guaranteed that the client doesn't have dequeued buffers
204 // and will release all of its buffer references.
205 freeAllBuffersLocked();
206 mBufferCount = bufferCount;
207 mClientBufferCount = bufferCount;
Daniel Lameae59d22012-01-22 15:26:27 -0800208 mBufferHasBeenQueued = false;
Daniel Lam6b091c52012-01-22 15:26:27 -0800209 mQueue.clear();
Dave Burke74ff8c22012-03-12 21:49:41 -0700210 mDequeueCondition.broadcast();
Daniel Lam6b091c52012-01-22 15:26:27 -0800211 return OK;
212}
213
Daniel Lamb8560522012-01-30 15:51:27 -0800214int BufferQueue::query(int what, int* outValue)
215{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800216 ATRACE_CALL();
Daniel Lamb8560522012-01-30 15:51:27 -0800217 Mutex::Autolock lock(mMutex);
218
219 if (mAbandoned) {
220 ST_LOGE("query: SurfaceTexture has been abandoned!");
221 return NO_INIT;
222 }
223
224 int value;
225 switch (what) {
226 case NATIVE_WINDOW_WIDTH:
227 value = mDefaultWidth;
228 break;
229 case NATIVE_WINDOW_HEIGHT:
230 value = mDefaultHeight;
231 break;
232 case NATIVE_WINDOW_FORMAT:
233 value = mPixelFormat;
234 break;
235 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
236 value = mSynchronousMode ?
237 (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS;
238 break;
239 default:
240 return BAD_VALUE;
241 }
242 outValue[0] = value;
243 return NO_ERROR;
244}
245
Daniel Lam6b091c52012-01-22 15:26:27 -0800246status_t BufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800247 ATRACE_CALL();
Daniel Lam6b091c52012-01-22 15:26:27 -0800248 ST_LOGV("requestBuffer: slot=%d", slot);
249 Mutex::Autolock lock(mMutex);
250 if (mAbandoned) {
251 ST_LOGE("requestBuffer: SurfaceTexture has been abandoned!");
252 return NO_INIT;
253 }
254 if (slot < 0 || mBufferCount <= slot) {
255 ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d",
256 mBufferCount, slot);
257 return BAD_VALUE;
258 }
259 mSlots[slot].mRequestBufferCalled = true;
260 *buf = mSlots[slot].mGraphicBuffer;
261 return NO_ERROR;
262}
263
264status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
265 uint32_t format, uint32_t usage) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800266 ATRACE_CALL();
Daniel Lam6b091c52012-01-22 15:26:27 -0800267 ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);
268
269 if ((w && !h) || (!w && h)) {
270 ST_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
271 return BAD_VALUE;
272 }
273
274 status_t returnFlags(OK);
275 EGLDisplay dpy = EGL_NO_DISPLAY;
276 EGLSyncKHR fence = EGL_NO_SYNC_KHR;
277
278 { // Scope for the lock
279 Mutex::Autolock lock(mMutex);
280
Daniel Lamb2675792012-02-23 14:35:13 -0800281 if (format == 0) {
282 format = mDefaultBufferFormat;
283 }
284 // turn on usage bits the consumer requested
285 usage |= mConsumerUsageBits;
286
Daniel Lam6b091c52012-01-22 15:26:27 -0800287 int found = -1;
288 int foundSync = -1;
289 int dequeuedCount = 0;
290 bool tryAgain = true;
291 while (tryAgain) {
292 if (mAbandoned) {
293 ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
294 return NO_INIT;
295 }
296
297 // We need to wait for the FIFO to drain if the number of buffer
298 // needs to change.
299 //
300 // The condition "number of buffers needs to change" is true if
301 // - the client doesn't care about how many buffers there are
302 // - AND the actual number of buffer is different from what was
303 // set in the last setBufferCountServer()
304 // - OR -
305 // setBufferCountServer() was set to a value incompatible with
306 // the synchronization mode (for instance because the sync mode
307 // changed since)
308 //
309 // As long as this condition is true AND the FIFO is not empty, we
310 // wait on mDequeueCondition.
311
312 const int minBufferCountNeeded = mSynchronousMode ?
313 MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
314
315 const bool numberOfBuffersNeedsToChange = !mClientBufferCount &&
316 ((mServerBufferCount != mBufferCount) ||
317 (mServerBufferCount < minBufferCountNeeded));
318
319 if (!mQueue.isEmpty() && numberOfBuffersNeedsToChange) {
320 // wait for the FIFO to drain
321 mDequeueCondition.wait(mMutex);
322 // NOTE: we continue here because we need to reevaluate our
323 // whole state (eg: we could be abandoned or disconnected)
324 continue;
325 }
326
327 if (numberOfBuffersNeedsToChange) {
328 // here we're guaranteed that mQueue is empty
329 freeAllBuffersLocked();
330 mBufferCount = mServerBufferCount;
331 if (mBufferCount < minBufferCountNeeded)
332 mBufferCount = minBufferCountNeeded;
Daniel Lameae59d22012-01-22 15:26:27 -0800333 mBufferHasBeenQueued = false;
Daniel Lam6b091c52012-01-22 15:26:27 -0800334 returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
335 }
336
337 // look for a free buffer to give to the client
338 found = INVALID_BUFFER_SLOT;
339 foundSync = INVALID_BUFFER_SLOT;
340 dequeuedCount = 0;
341 for (int i = 0; i < mBufferCount; i++) {
342 const int state = mSlots[i].mBufferState;
343 if (state == BufferSlot::DEQUEUED) {
344 dequeuedCount++;
345 }
346
Daniel Lameae59d22012-01-22 15:26:27 -0800347 // this logic used to be if (FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER)
348 // but dequeuing the current buffer is disabled.
349 if (false) {
350 // This functionality has been temporarily removed so
351 // BufferQueue and SurfaceTexture can be refactored into
352 // separate objects
Daniel Lam6b091c52012-01-22 15:26:27 -0800353 } else {
354 if (state == BufferSlot::FREE) {
355 /* We return the oldest of the free buffers to avoid
356 * stalling the producer if possible. This is because
357 * the consumer may still have pending reads of the
358 * buffers in flight.
359 */
360 bool isOlder = mSlots[i].mFrameNumber <
361 mSlots[found].mFrameNumber;
362 if (found < 0 || isOlder) {
363 foundSync = i;
364 found = i;
365 }
366 }
367 }
368 }
369
370 // clients are not allowed to dequeue more than one buffer
371 // if they didn't set a buffer count.
372 if (!mClientBufferCount && dequeuedCount) {
373 ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without "
374 "setting the buffer count");
375 return -EINVAL;
376 }
377
378 // See whether a buffer has been queued since the last
379 // setBufferCount so we know whether to perform the
380 // MIN_UNDEQUEUED_BUFFERS check below.
Daniel Lameae59d22012-01-22 15:26:27 -0800381 if (mBufferHasBeenQueued) {
Daniel Lam6b091c52012-01-22 15:26:27 -0800382 // make sure the client is not trying to dequeue more buffers
383 // than allowed.
384 const int avail = mBufferCount - (dequeuedCount+1);
385 if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) {
386 ST_LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded "
387 "(dequeued=%d)",
388 MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode),
389 dequeuedCount);
390 return -EBUSY;
391 }
392 }
393
Daniel Lamc2c1f2f2012-03-07 14:11:29 -0800394 // if no buffer is found, wait for a buffer to be released
395 tryAgain = found == INVALID_BUFFER_SLOT;
Daniel Lam6b091c52012-01-22 15:26:27 -0800396 if (tryAgain) {
397 mDequeueCondition.wait(mMutex);
398 }
399 }
400
Daniel Lam6b091c52012-01-22 15:26:27 -0800401
402 if (found == INVALID_BUFFER_SLOT) {
403 // This should not happen.
404 ST_LOGE("dequeueBuffer: no available buffer slots");
405 return -EBUSY;
406 }
407
408 const int buf = found;
409 *outBuf = found;
410
Mathias Agopian546ed2d2012-03-01 22:11:25 -0800411 ATRACE_BUFFER_INDEX(buf);
412
Daniel Lam6b091c52012-01-22 15:26:27 -0800413 const bool useDefaultSize = !w && !h;
414 if (useDefaultSize) {
415 // use the default size
416 w = mDefaultWidth;
417 h = mDefaultHeight;
418 }
419
420 const bool updateFormat = (format != 0);
421 if (!updateFormat) {
422 // keep the current (or default) format
423 format = mPixelFormat;
424 }
425
426 // buffer is now in DEQUEUED (but can also be current at the same time,
427 // if we're in synchronous mode)
428 mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
429
430 const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
431 if ((buffer == NULL) ||
432 (uint32_t(buffer->width) != w) ||
433 (uint32_t(buffer->height) != h) ||
434 (uint32_t(buffer->format) != format) ||
435 ((uint32_t(buffer->usage) & usage) != usage))
436 {
437 usage |= GraphicBuffer::USAGE_HW_TEXTURE;
438 status_t error;
439 sp<GraphicBuffer> graphicBuffer(
440 mGraphicBufferAlloc->createGraphicBuffer(
441 w, h, format, usage, &error));
442 if (graphicBuffer == 0) {
443 ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer "
444 "failed");
445 return error;
446 }
447 if (updateFormat) {
448 mPixelFormat = format;
449 }
Daniel Lameae59d22012-01-22 15:26:27 -0800450
451 mSlots[buf].mAcquireCalled = false;
Daniel Lam6b091c52012-01-22 15:26:27 -0800452 mSlots[buf].mGraphicBuffer = graphicBuffer;
453 mSlots[buf].mRequestBufferCalled = false;
454 mSlots[buf].mFence = EGL_NO_SYNC_KHR;
Daniel Lameae59d22012-01-22 15:26:27 -0800455 mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
456
457
458
459
Daniel Lam6b091c52012-01-22 15:26:27 -0800460 returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
461 }
462
463 dpy = mSlots[buf].mEglDisplay;
464 fence = mSlots[buf].mFence;
465 mSlots[buf].mFence = EGL_NO_SYNC_KHR;
Daniel Lameae59d22012-01-22 15:26:27 -0800466 } // end lock scope
Daniel Lam6b091c52012-01-22 15:26:27 -0800467
468 if (fence != EGL_NO_SYNC_KHR) {
469 EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
470 // If something goes wrong, log the error, but return the buffer without
471 // synchronizing access to it. It's too late at this point to abort the
472 // dequeue operation.
473 if (result == EGL_FALSE) {
474 ALOGE("dequeueBuffer: error waiting for fence: %#x", eglGetError());
475 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
476 ALOGE("dequeueBuffer: timeout waiting for fence");
477 }
478 eglDestroySyncKHR(dpy, fence);
Daniel Lameae59d22012-01-22 15:26:27 -0800479
Daniel Lam6b091c52012-01-22 15:26:27 -0800480 }
481
482 ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf,
483 mSlots[*outBuf].mGraphicBuffer->handle, returnFlags);
484
485 return returnFlags;
486}
487
488status_t BufferQueue::setSynchronousMode(bool enabled) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800489 ATRACE_CALL();
Daniel Lam6b091c52012-01-22 15:26:27 -0800490 ST_LOGV("setSynchronousMode: enabled=%d", enabled);
491 Mutex::Autolock lock(mMutex);
492
493 if (mAbandoned) {
494 ST_LOGE("setSynchronousMode: SurfaceTexture has been abandoned!");
495 return NO_INIT;
496 }
497
498 status_t err = OK;
499 if (!mAllowSynchronousMode && enabled)
500 return err;
501
502 if (!enabled) {
503 // going to asynchronous mode, drain the queue
504 err = drainQueueLocked();
505 if (err != NO_ERROR)
506 return err;
507 }
508
509 if (mSynchronousMode != enabled) {
510 // - if we're going to asynchronous mode, the queue is guaranteed to be
511 // empty here
512 // - if the client set the number of buffers, we're guaranteed that
513 // we have at least 3 (because we don't allow less)
514 mSynchronousMode = enabled;
Dave Burke74ff8c22012-03-12 21:49:41 -0700515 mDequeueCondition.broadcast();
Daniel Lam6b091c52012-01-22 15:26:27 -0800516 }
517 return err;
518}
519
520status_t BufferQueue::queueBuffer(int buf, int64_t timestamp,
521 uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800522 ATRACE_CALL();
Mathias Agopian546ed2d2012-03-01 22:11:25 -0800523 ATRACE_BUFFER_INDEX(buf);
524
Daniel Lam6b091c52012-01-22 15:26:27 -0800525 ST_LOGV("queueBuffer: slot=%d time=%lld", buf, timestamp);
526
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700527 sp<ConsumerListener> listener;
Daniel Lam6b091c52012-01-22 15:26:27 -0800528
529 { // scope for the lock
530 Mutex::Autolock lock(mMutex);
531 if (mAbandoned) {
532 ST_LOGE("queueBuffer: SurfaceTexture has been abandoned!");
533 return NO_INIT;
534 }
535 if (buf < 0 || buf >= mBufferCount) {
536 ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d",
537 mBufferCount, buf);
538 return -EINVAL;
539 } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
540 ST_LOGE("queueBuffer: slot %d is not owned by the client "
541 "(state=%d)", buf, mSlots[buf].mBufferState);
542 return -EINVAL;
Daniel Lam6b091c52012-01-22 15:26:27 -0800543 } else if (!mSlots[buf].mRequestBufferCalled) {
544 ST_LOGE("queueBuffer: slot %d was enqueued without requesting a "
545 "buffer", buf);
546 return -EINVAL;
547 }
548
549 if (mSynchronousMode) {
550 // In synchronous mode we queue all buffers in a FIFO.
551 mQueue.push_back(buf);
552
553 // Synchronous mode always signals that an additional frame should
554 // be consumed.
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700555 listener = mConsumerListener;
Daniel Lam6b091c52012-01-22 15:26:27 -0800556 } else {
557 // In asynchronous mode we only keep the most recent buffer.
558 if (mQueue.empty()) {
559 mQueue.push_back(buf);
560
561 // Asynchronous mode only signals that a frame should be
562 // consumed if no previous frame was pending. If a frame were
563 // pending then the consumer would have already been notified.
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700564 listener = mConsumerListener;
Daniel Lam6b091c52012-01-22 15:26:27 -0800565 } else {
566 Fifo::iterator front(mQueue.begin());
567 // buffer currently queued is freed
568 mSlots[*front].mBufferState = BufferSlot::FREE;
569 // and we record the new buffer index in the queued list
570 *front = buf;
571 }
572 }
573
574 mSlots[buf].mBufferState = BufferSlot::QUEUED;
575 mSlots[buf].mCrop = mNextCrop;
576 mSlots[buf].mTransform = mNextTransform;
577 mSlots[buf].mScalingMode = mNextScalingMode;
578 mSlots[buf].mTimestamp = timestamp;
579 mFrameCounter++;
580 mSlots[buf].mFrameNumber = mFrameCounter;
581
Daniel Lameae59d22012-01-22 15:26:27 -0800582 mBufferHasBeenQueued = true;
Dave Burke74ff8c22012-03-12 21:49:41 -0700583 mDequeueCondition.broadcast();
Daniel Lam6b091c52012-01-22 15:26:27 -0800584
585 *outWidth = mDefaultWidth;
586 *outHeight = mDefaultHeight;
Daniel Lamb2675792012-02-23 14:35:13 -0800587 *outTransform = mTransformHint;
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800588
589 ATRACE_INT(mConsumerName.string(), mQueue.size());
Daniel Lam6b091c52012-01-22 15:26:27 -0800590 } // scope for the lock
591
592 // call back without lock held
593 if (listener != 0) {
594 listener->onFrameAvailable();
595 }
596 return OK;
597}
598
599void BufferQueue::cancelBuffer(int buf) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800600 ATRACE_CALL();
Daniel Lam6b091c52012-01-22 15:26:27 -0800601 ST_LOGV("cancelBuffer: slot=%d", buf);
602 Mutex::Autolock lock(mMutex);
603
604 if (mAbandoned) {
605 ST_LOGW("cancelBuffer: BufferQueue has been abandoned!");
606 return;
607 }
608
609 if (buf < 0 || buf >= mBufferCount) {
610 ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
611 mBufferCount, buf);
612 return;
613 } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
614 ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
615 buf, mSlots[buf].mBufferState);
616 return;
617 }
618 mSlots[buf].mBufferState = BufferSlot::FREE;
619 mSlots[buf].mFrameNumber = 0;
Dave Burke74ff8c22012-03-12 21:49:41 -0700620 mDequeueCondition.broadcast();
Daniel Lam6b091c52012-01-22 15:26:27 -0800621}
622
623status_t BufferQueue::setCrop(const Rect& crop) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800624 ATRACE_CALL();
Daniel Lam6b091c52012-01-22 15:26:27 -0800625 ST_LOGV("setCrop: crop=[%d,%d,%d,%d]", crop.left, crop.top, crop.right,
626 crop.bottom);
627
628 Mutex::Autolock lock(mMutex);
629 if (mAbandoned) {
630 ST_LOGE("setCrop: BufferQueue has been abandoned!");
631 return NO_INIT;
632 }
633 mNextCrop = crop;
634 return OK;
635}
636
637status_t BufferQueue::setTransform(uint32_t transform) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800638 ATRACE_CALL();
Daniel Lam6b091c52012-01-22 15:26:27 -0800639 ST_LOGV("setTransform: xform=%#x", transform);
640 Mutex::Autolock lock(mMutex);
641 if (mAbandoned) {
642 ST_LOGE("setTransform: BufferQueue has been abandoned!");
643 return NO_INIT;
644 }
645 mNextTransform = transform;
646 return OK;
647}
648
649status_t BufferQueue::setScalingMode(int mode) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800650 ATRACE_CALL();
Daniel Lam6b091c52012-01-22 15:26:27 -0800651 ST_LOGV("setScalingMode: mode=%d", mode);
652
653 switch (mode) {
654 case NATIVE_WINDOW_SCALING_MODE_FREEZE:
655 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
656 break;
657 default:
658 ST_LOGE("unknown scaling mode: %d", mode);
659 return BAD_VALUE;
660 }
661
662 Mutex::Autolock lock(mMutex);
663 mNextScalingMode = mode;
664 return OK;
665}
666
667status_t BufferQueue::connect(int api,
668 uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800669 ATRACE_CALL();
Daniel Lam6b091c52012-01-22 15:26:27 -0800670 ST_LOGV("connect: api=%d", api);
671 Mutex::Autolock lock(mMutex);
672
673 if (mAbandoned) {
674 ST_LOGE("connect: BufferQueue has been abandoned!");
675 return NO_INIT;
676 }
677
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700678 if (mConsumerListener == NULL) {
679 ST_LOGE("connect: BufferQueue has no consumer!");
680 return NO_INIT;
681 }
682
Daniel Lam6b091c52012-01-22 15:26:27 -0800683 int err = NO_ERROR;
684 switch (api) {
685 case NATIVE_WINDOW_API_EGL:
686 case NATIVE_WINDOW_API_CPU:
687 case NATIVE_WINDOW_API_MEDIA:
688 case NATIVE_WINDOW_API_CAMERA:
689 if (mConnectedApi != NO_CONNECTED_API) {
690 ST_LOGE("connect: already connected (cur=%d, req=%d)",
691 mConnectedApi, api);
692 err = -EINVAL;
693 } else {
694 mConnectedApi = api;
695 *outWidth = mDefaultWidth;
696 *outHeight = mDefaultHeight;
697 *outTransform = 0;
698 }
699 break;
700 default:
701 err = -EINVAL;
702 break;
703 }
Daniel Lameae59d22012-01-22 15:26:27 -0800704
705 mBufferHasBeenQueued = false;
706
Daniel Lam6b091c52012-01-22 15:26:27 -0800707 return err;
708}
709
710status_t BufferQueue::disconnect(int api) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800711 ATRACE_CALL();
Daniel Lam6b091c52012-01-22 15:26:27 -0800712 ST_LOGV("disconnect: api=%d", api);
Daniel Lam6b091c52012-01-22 15:26:27 -0800713
714 int err = NO_ERROR;
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700715 sp<ConsumerListener> listener;
716
717 { // Scope for the lock
718 Mutex::Autolock lock(mMutex);
719
720 if (mAbandoned) {
721 // it is not really an error to disconnect after the surface
722 // has been abandoned, it should just be a no-op.
723 return NO_ERROR;
724 }
725
726 switch (api) {
727 case NATIVE_WINDOW_API_EGL:
728 case NATIVE_WINDOW_API_CPU:
729 case NATIVE_WINDOW_API_MEDIA:
730 case NATIVE_WINDOW_API_CAMERA:
731 if (mConnectedApi == api) {
732 drainQueueAndFreeBuffersLocked();
733 mConnectedApi = NO_CONNECTED_API;
734 mNextCrop.makeInvalid();
735 mNextScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
736 mNextTransform = 0;
737 mDequeueCondition.broadcast();
738 listener = mConsumerListener;
739 } else {
740 ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)",
741 mConnectedApi, api);
742 err = -EINVAL;
743 }
744 break;
745 default:
746 ST_LOGE("disconnect: unknown API %d", api);
Daniel Lam6b091c52012-01-22 15:26:27 -0800747 err = -EINVAL;
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700748 break;
749 }
Daniel Lam6b091c52012-01-22 15:26:27 -0800750 }
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700751
752 if (listener != NULL) {
753 listener->onBuffersReleased();
754 }
755
Daniel Lam6b091c52012-01-22 15:26:27 -0800756 return err;
757}
758
Daniel Lameae59d22012-01-22 15:26:27 -0800759void BufferQueue::dump(String8& result) const
760{
761 char buffer[1024];
762 BufferQueue::dump(result, "", buffer, 1024);
763}
764
765void BufferQueue::dump(String8& result, const char* prefix,
766 char* buffer, size_t SIZE) const
767{
768 Mutex::Autolock _l(mMutex);
769 snprintf(buffer, SIZE,
770 "%snext : {crop=[%d,%d,%d,%d], transform=0x%02x}\n"
771 ,prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right,
772 mNextCrop.bottom, mNextTransform
773 );
774 result.append(buffer);
775
776 String8 fifo;
777 int fifoSize = 0;
778 Fifo::const_iterator i(mQueue.begin());
779 while (i != mQueue.end()) {
780 snprintf(buffer, SIZE, "%02d ", *i++);
781 fifoSize++;
782 fifo.append(buffer);
783 }
784
785 snprintf(buffer, SIZE,
786 "%s-BufferQueue mBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
787 "mPixelFormat=%d, FIFO(%d)={%s}\n",
788 prefix, mBufferCount, mSynchronousMode, mDefaultWidth,
789 mDefaultHeight, mPixelFormat, fifoSize, fifo.string());
790 result.append(buffer);
791
792
793 struct {
794 const char * operator()(int state) const {
795 switch (state) {
796 case BufferSlot::DEQUEUED: return "DEQUEUED";
797 case BufferSlot::QUEUED: return "QUEUED";
798 case BufferSlot::FREE: return "FREE";
799 case BufferSlot::ACQUIRED: return "ACQUIRED";
800 default: return "Unknown";
801 }
802 }
803 } stateName;
804
805 for (int i=0 ; i<mBufferCount ; i++) {
806 const BufferSlot& slot(mSlots[i]);
807 snprintf(buffer, SIZE,
808 "%s%s[%02d] "
809 "state=%-8s, crop=[%d,%d,%d,%d], "
810 "transform=0x%02x, timestamp=%lld",
811 prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i,
812 stateName(slot.mBufferState),
813 slot.mCrop.left, slot.mCrop.top, slot.mCrop.right,
814 slot.mCrop.bottom, slot.mTransform, slot.mTimestamp
815 );
816 result.append(buffer);
817
818 const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
819 if (buf != NULL) {
820 snprintf(buffer, SIZE,
821 ", %p [%4ux%4u:%4u,%3X]",
822 buf->handle, buf->width, buf->height, buf->stride,
823 buf->format);
824 result.append(buffer);
825 }
826 result.append("\n");
827 }
828}
829
Daniel Lam6b091c52012-01-22 15:26:27 -0800830void BufferQueue::freeBufferLocked(int i) {
831 mSlots[i].mGraphicBuffer = 0;
832 mSlots[i].mBufferState = BufferSlot::FREE;
833 mSlots[i].mFrameNumber = 0;
Daniel Lameae59d22012-01-22 15:26:27 -0800834 mSlots[i].mAcquireCalled = false;
835
836 // destroy fence as BufferQueue now takes ownership
837 if (mSlots[i].mFence != EGL_NO_SYNC_KHR) {
838 eglDestroySyncKHR(mSlots[i].mEglDisplay, mSlots[i].mFence);
839 mSlots[i].mFence = EGL_NO_SYNC_KHR;
Daniel Lam6b091c52012-01-22 15:26:27 -0800840 }
841}
842
843void BufferQueue::freeAllBuffersLocked() {
844 ALOGW_IF(!mQueue.isEmpty(),
845 "freeAllBuffersLocked called but mQueue is not empty");
Daniel Lameae59d22012-01-22 15:26:27 -0800846 mQueue.clear();
847 mBufferHasBeenQueued = false;
Daniel Lam6b091c52012-01-22 15:26:27 -0800848 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
849 freeBufferLocked(i);
850 }
851}
852
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700853status_t BufferQueue::acquireBuffer(BufferItem *buffer) {
Mathias Agopian546ed2d2012-03-01 22:11:25 -0800854 ATRACE_CALL();
Daniel Lameae59d22012-01-22 15:26:27 -0800855 Mutex::Autolock _l(mMutex);
856 // check if queue is empty
857 // In asynchronous mode the list is guaranteed to be one buffer
858 // deep, while in synchronous mode we use the oldest buffer.
859 if (!mQueue.empty()) {
860 Fifo::iterator front(mQueue.begin());
861 int buf = *front;
862
Mathias Agopian546ed2d2012-03-01 22:11:25 -0800863 ATRACE_BUFFER_INDEX(buf);
864
Daniel Lameae59d22012-01-22 15:26:27 -0800865 if (mSlots[buf].mAcquireCalled) {
866 buffer->mGraphicBuffer = NULL;
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700867 } else {
Daniel Lameae59d22012-01-22 15:26:27 -0800868 buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer;
869 }
870 buffer->mCrop = mSlots[buf].mCrop;
871 buffer->mTransform = mSlots[buf].mTransform;
872 buffer->mScalingMode = mSlots[buf].mScalingMode;
873 buffer->mFrameNumber = mSlots[buf].mFrameNumber;
Daniel Lam3fcee502012-03-02 10:17:34 -0800874 buffer->mTimestamp = mSlots[buf].mTimestamp;
Daniel Lameae59d22012-01-22 15:26:27 -0800875 buffer->mBuf = buf;
876 mSlots[buf].mAcquireCalled = true;
877
878 mSlots[buf].mBufferState = BufferSlot::ACQUIRED;
879 mQueue.erase(front);
Dave Burke74ff8c22012-03-12 21:49:41 -0700880 mDequeueCondition.broadcast();
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800881
882 ATRACE_INT(mConsumerName.string(), mQueue.size());
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700883 } else {
Daniel Lamb2675792012-02-23 14:35:13 -0800884 // should be a better return code?
885 return -EINVAL;
Daniel Lameae59d22012-01-22 15:26:27 -0800886 }
887
888 return OK;
889}
890
891status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display,
892 EGLSyncKHR fence) {
Mathias Agopian546ed2d2012-03-01 22:11:25 -0800893 ATRACE_CALL();
894 ATRACE_BUFFER_INDEX(buf);
895
Daniel Lameae59d22012-01-22 15:26:27 -0800896 Mutex::Autolock _l(mMutex);
897
898 if (buf == INVALID_BUFFER_SLOT) {
899 return -EINVAL;
900 }
901
902 mSlots[buf].mEglDisplay = display;
903 mSlots[buf].mFence = fence;
904
905 // The current buffer becomes FREE if it was still in the queued
906 // state. If it has already been given to the client
907 // (synchronous mode), then it stays in DEQUEUED state.
908 if (mSlots[buf].mBufferState == BufferSlot::QUEUED
909 || mSlots[buf].mBufferState == BufferSlot::ACQUIRED) {
910 mSlots[buf].mBufferState = BufferSlot::FREE;
911 }
Dave Burke74ff8c22012-03-12 21:49:41 -0700912 mDequeueCondition.broadcast();
Daniel Lameae59d22012-01-22 15:26:27 -0800913
914 return OK;
915}
916
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700917status_t BufferQueue::consumerConnect(const sp<ConsumerListener>& consumerListener) {
918 ST_LOGV("consumerConnect");
Daniel Lameae59d22012-01-22 15:26:27 -0800919 Mutex::Autolock lock(mMutex);
Daniel Lamb2675792012-02-23 14:35:13 -0800920
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700921 if (mAbandoned) {
922 ST_LOGE("consumerConnect: BufferQueue has been abandoned!");
923 return NO_INIT;
924 }
Daniel Lamb2675792012-02-23 14:35:13 -0800925
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700926 mConsumerListener = consumerListener;
927
928 return OK;
929}
930
931status_t BufferQueue::consumerDisconnect() {
932 ST_LOGV("consumerDisconnect");
933 Mutex::Autolock lock(mMutex);
934
935 if (mConsumerListener == NULL) {
936 ST_LOGE("consumerDisconnect: No consumer is connected!");
937 return -EINVAL;
938 }
939
940 mAbandoned = true;
941 mConsumerListener = NULL;
Daniel Lamb2675792012-02-23 14:35:13 -0800942 mQueue.clear();
Daniel Lameae59d22012-01-22 15:26:27 -0800943 freeAllBuffersLocked();
Dave Burke74ff8c22012-03-12 21:49:41 -0700944 mDequeueCondition.broadcast();
Daniel Lameae59d22012-01-22 15:26:27 -0800945 return OK;
946}
947
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700948status_t BufferQueue::getReleasedBuffers(uint32_t* slotMask) {
949 ST_LOGV("getReleasedBuffers");
950 Mutex::Autolock lock(mMutex);
951
952 if (mAbandoned) {
953 ST_LOGE("getReleasedBuffers: BufferQueue has been abandoned!");
954 return NO_INIT;
955 }
956
957 uint32_t mask = 0;
958 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
959 if (!mSlots[i].mAcquireCalled) {
960 mask |= 1 << i;
961 }
962 }
963 *slotMask = mask;
964
965 ST_LOGV("getReleasedBuffers: returning mask %#x", mask);
966 return NO_ERROR;
967}
968
Daniel Lameae59d22012-01-22 15:26:27 -0800969status_t BufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h)
970{
971 ST_LOGV("setDefaultBufferSize: w=%d, h=%d", w, h);
972 if (!w || !h) {
973 ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)",
974 w, h);
975 return BAD_VALUE;
976 }
977
978 Mutex::Autolock lock(mMutex);
979 mDefaultWidth = w;
980 mDefaultHeight = h;
981 return OK;
982}
983
984status_t BufferQueue::setBufferCountServer(int bufferCount) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800985 ATRACE_CALL();
Daniel Lameae59d22012-01-22 15:26:27 -0800986 Mutex::Autolock lock(mMutex);
987 return setBufferCountServerLocked(bufferCount);
988}
989
Daniel Lam6b091c52012-01-22 15:26:27 -0800990void BufferQueue::freeAllBuffersExceptHeadLocked() {
991 ALOGW_IF(!mQueue.isEmpty(),
992 "freeAllBuffersExceptCurrentLocked called but mQueue is not empty");
993 int head = -1;
994 if (!mQueue.empty()) {
995 Fifo::iterator front(mQueue.begin());
996 head = *front;
997 }
Daniel Lameae59d22012-01-22 15:26:27 -0800998 mBufferHasBeenQueued = false;
Daniel Lam6b091c52012-01-22 15:26:27 -0800999 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
1000 if (i != head) {
1001 freeBufferLocked(i);
1002 }
1003 }
1004}
1005
1006status_t BufferQueue::drainQueueLocked() {
1007 while (mSynchronousMode && !mQueue.isEmpty()) {
1008 mDequeueCondition.wait(mMutex);
1009 if (mAbandoned) {
1010 ST_LOGE("drainQueueLocked: BufferQueue has been abandoned!");
1011 return NO_INIT;
1012 }
1013 if (mConnectedApi == NO_CONNECTED_API) {
1014 ST_LOGE("drainQueueLocked: BufferQueue is not connected!");
1015 return NO_INIT;
1016 }
1017 }
1018 return NO_ERROR;
1019}
1020
1021status_t BufferQueue::drainQueueAndFreeBuffersLocked() {
1022 status_t err = drainQueueLocked();
1023 if (err == NO_ERROR) {
1024 if (mSynchronousMode) {
1025 freeAllBuffersLocked();
1026 } else {
1027 freeAllBuffersExceptHeadLocked();
1028 }
1029 }
1030 return err;
1031}
1032
Jamie Gennisfa5b40e2012-03-15 14:01:24 -07001033BufferQueue::ProxyConsumerListener::ProxyConsumerListener(
1034 const wp<BufferQueue::ConsumerListener>& consumerListener):
1035 mConsumerListener(consumerListener) {}
1036
1037BufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {}
1038
1039void BufferQueue::ProxyConsumerListener::onFrameAvailable() {
1040 sp<BufferQueue::ConsumerListener> listener(mConsumerListener.promote());
1041 if (listener != NULL) {
1042 listener->onFrameAvailable();
1043 }
1044}
1045
1046void BufferQueue::ProxyConsumerListener::onBuffersReleased() {
1047 sp<BufferQueue::ConsumerListener> listener(mConsumerListener.promote());
1048 if (listener != NULL) {
1049 listener->onBuffersReleased();
1050 }
1051}
1052
Daniel Lam6b091c52012-01-22 15:26:27 -08001053}; // namespace android