blob: 0f9c7c5c4ab5c35af745050e2c0cd63766aa9628 [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"
Daniel Lameae59d22012-01-22 15:26:27 -080018//#define LOG_NDEBUG 0
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080019#define ATRACE_TAG ATRACE_TAG_GRAPHICS
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
149void BufferQueue::setFrameAvailableListener(
150 const sp<FrameAvailableListener>& listener) {
151 ST_LOGV("setFrameAvailableListener");
152 Mutex::Autolock lock(mMutex);
153 mFrameAvailableListener = listener;
154}
155
Daniel Lamb2675792012-02-23 14:35:13 -0800156status_t BufferQueue::setDefaultBufferFormat(uint32_t defaultFormat) {
157 Mutex::Autolock lock(mMutex);
158 mDefaultBufferFormat = defaultFormat;
159 return OK;
160}
161
162status_t BufferQueue::setConsumerUsageBits(uint32_t usage) {
163 Mutex::Autolock lock(mMutex);
164 mConsumerUsageBits = usage;
165 return OK;
166}
167
168status_t BufferQueue::setTransformHint(uint32_t hint) {
169 Mutex::Autolock lock(mMutex);
170 mTransformHint = hint;
171 return OK;
172}
173
Daniel Lam6b091c52012-01-22 15:26:27 -0800174status_t BufferQueue::setBufferCount(int bufferCount) {
175 ST_LOGV("setBufferCount: count=%d", bufferCount);
176 Mutex::Autolock lock(mMutex);
177
178 if (mAbandoned) {
179 ST_LOGE("setBufferCount: SurfaceTexture has been abandoned!");
180 return NO_INIT;
181 }
182 if (bufferCount > NUM_BUFFER_SLOTS) {
183 ST_LOGE("setBufferCount: bufferCount larger than slots available");
184 return BAD_VALUE;
185 }
186
187 // Error out if the user has dequeued buffers
188 for (int i=0 ; i<mBufferCount ; i++) {
189 if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
190 ST_LOGE("setBufferCount: client owns some buffers");
191 return -EINVAL;
192 }
193 }
194
195 const int minBufferSlots = mSynchronousMode ?
196 MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
197 if (bufferCount == 0) {
198 mClientBufferCount = 0;
199 bufferCount = (mServerBufferCount >= minBufferSlots) ?
200 mServerBufferCount : minBufferSlots;
201 return setBufferCountServerLocked(bufferCount);
202 }
203
204 if (bufferCount < minBufferSlots) {
205 ST_LOGE("setBufferCount: requested buffer count (%d) is less than "
206 "minimum (%d)", bufferCount, minBufferSlots);
207 return BAD_VALUE;
208 }
209
210 // here we're guaranteed that the client doesn't have dequeued buffers
211 // and will release all of its buffer references.
212 freeAllBuffersLocked();
213 mBufferCount = bufferCount;
214 mClientBufferCount = bufferCount;
Daniel Lameae59d22012-01-22 15:26:27 -0800215 mBufferHasBeenQueued = false;
Daniel Lam6b091c52012-01-22 15:26:27 -0800216 mQueue.clear();
Dave Burke74ff8c22012-03-12 21:49:41 -0700217 mDequeueCondition.broadcast();
Daniel Lam6b091c52012-01-22 15:26:27 -0800218 return OK;
219}
220
Daniel Lamb8560522012-01-30 15:51:27 -0800221int BufferQueue::query(int what, int* outValue)
222{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800223 ATRACE_CALL();
Daniel Lamb8560522012-01-30 15:51:27 -0800224 Mutex::Autolock lock(mMutex);
225
226 if (mAbandoned) {
227 ST_LOGE("query: SurfaceTexture has been abandoned!");
228 return NO_INIT;
229 }
230
231 int value;
232 switch (what) {
233 case NATIVE_WINDOW_WIDTH:
234 value = mDefaultWidth;
235 break;
236 case NATIVE_WINDOW_HEIGHT:
237 value = mDefaultHeight;
238 break;
239 case NATIVE_WINDOW_FORMAT:
240 value = mPixelFormat;
241 break;
242 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
243 value = mSynchronousMode ?
244 (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS;
245 break;
246 default:
247 return BAD_VALUE;
248 }
249 outValue[0] = value;
250 return NO_ERROR;
251}
252
Daniel Lam6b091c52012-01-22 15:26:27 -0800253status_t BufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800254 ATRACE_CALL();
Daniel Lam6b091c52012-01-22 15:26:27 -0800255 ST_LOGV("requestBuffer: slot=%d", slot);
256 Mutex::Autolock lock(mMutex);
257 if (mAbandoned) {
258 ST_LOGE("requestBuffer: SurfaceTexture has been abandoned!");
259 return NO_INIT;
260 }
261 if (slot < 0 || mBufferCount <= slot) {
262 ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d",
263 mBufferCount, slot);
264 return BAD_VALUE;
265 }
266 mSlots[slot].mRequestBufferCalled = true;
267 *buf = mSlots[slot].mGraphicBuffer;
268 return NO_ERROR;
269}
270
271status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
272 uint32_t format, uint32_t usage) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800273 ATRACE_CALL();
Daniel Lam6b091c52012-01-22 15:26:27 -0800274 ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);
275
276 if ((w && !h) || (!w && h)) {
277 ST_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
278 return BAD_VALUE;
279 }
280
281 status_t returnFlags(OK);
282 EGLDisplay dpy = EGL_NO_DISPLAY;
283 EGLSyncKHR fence = EGL_NO_SYNC_KHR;
284
285 { // Scope for the lock
286 Mutex::Autolock lock(mMutex);
287
Daniel Lamb2675792012-02-23 14:35:13 -0800288 if (format == 0) {
289 format = mDefaultBufferFormat;
290 }
291 // turn on usage bits the consumer requested
292 usage |= mConsumerUsageBits;
293
Daniel Lam6b091c52012-01-22 15:26:27 -0800294 int found = -1;
295 int foundSync = -1;
296 int dequeuedCount = 0;
297 bool tryAgain = true;
298 while (tryAgain) {
299 if (mAbandoned) {
300 ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
301 return NO_INIT;
302 }
303
304 // We need to wait for the FIFO to drain if the number of buffer
305 // needs to change.
306 //
307 // The condition "number of buffers needs to change" is true if
308 // - the client doesn't care about how many buffers there are
309 // - AND the actual number of buffer is different from what was
310 // set in the last setBufferCountServer()
311 // - OR -
312 // setBufferCountServer() was set to a value incompatible with
313 // the synchronization mode (for instance because the sync mode
314 // changed since)
315 //
316 // As long as this condition is true AND the FIFO is not empty, we
317 // wait on mDequeueCondition.
318
319 const int minBufferCountNeeded = mSynchronousMode ?
320 MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
321
322 const bool numberOfBuffersNeedsToChange = !mClientBufferCount &&
323 ((mServerBufferCount != mBufferCount) ||
324 (mServerBufferCount < minBufferCountNeeded));
325
326 if (!mQueue.isEmpty() && numberOfBuffersNeedsToChange) {
327 // wait for the FIFO to drain
328 mDequeueCondition.wait(mMutex);
329 // NOTE: we continue here because we need to reevaluate our
330 // whole state (eg: we could be abandoned or disconnected)
331 continue;
332 }
333
334 if (numberOfBuffersNeedsToChange) {
335 // here we're guaranteed that mQueue is empty
336 freeAllBuffersLocked();
337 mBufferCount = mServerBufferCount;
338 if (mBufferCount < minBufferCountNeeded)
339 mBufferCount = minBufferCountNeeded;
Daniel Lameae59d22012-01-22 15:26:27 -0800340 mBufferHasBeenQueued = false;
Daniel Lam6b091c52012-01-22 15:26:27 -0800341 returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
342 }
343
344 // look for a free buffer to give to the client
345 found = INVALID_BUFFER_SLOT;
346 foundSync = INVALID_BUFFER_SLOT;
347 dequeuedCount = 0;
348 for (int i = 0; i < mBufferCount; i++) {
349 const int state = mSlots[i].mBufferState;
350 if (state == BufferSlot::DEQUEUED) {
351 dequeuedCount++;
352 }
353
Daniel Lameae59d22012-01-22 15:26:27 -0800354 // this logic used to be if (FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER)
355 // but dequeuing the current buffer is disabled.
356 if (false) {
357 // This functionality has been temporarily removed so
358 // BufferQueue and SurfaceTexture can be refactored into
359 // separate objects
Daniel Lam6b091c52012-01-22 15:26:27 -0800360 } else {
361 if (state == BufferSlot::FREE) {
362 /* We return the oldest of the free buffers to avoid
363 * stalling the producer if possible. This is because
364 * the consumer may still have pending reads of the
365 * buffers in flight.
366 */
367 bool isOlder = mSlots[i].mFrameNumber <
368 mSlots[found].mFrameNumber;
369 if (found < 0 || isOlder) {
370 foundSync = i;
371 found = i;
372 }
373 }
374 }
375 }
376
377 // clients are not allowed to dequeue more than one buffer
378 // if they didn't set a buffer count.
379 if (!mClientBufferCount && dequeuedCount) {
380 ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without "
381 "setting the buffer count");
382 return -EINVAL;
383 }
384
385 // See whether a buffer has been queued since the last
386 // setBufferCount so we know whether to perform the
387 // MIN_UNDEQUEUED_BUFFERS check below.
Daniel Lameae59d22012-01-22 15:26:27 -0800388 if (mBufferHasBeenQueued) {
Daniel Lam6b091c52012-01-22 15:26:27 -0800389 // make sure the client is not trying to dequeue more buffers
390 // than allowed.
391 const int avail = mBufferCount - (dequeuedCount+1);
392 if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) {
393 ST_LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded "
394 "(dequeued=%d)",
395 MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode),
396 dequeuedCount);
397 return -EBUSY;
398 }
399 }
400
Daniel Lamc2c1f2f2012-03-07 14:11:29 -0800401 // if no buffer is found, wait for a buffer to be released
402 tryAgain = found == INVALID_BUFFER_SLOT;
Daniel Lam6b091c52012-01-22 15:26:27 -0800403 if (tryAgain) {
404 mDequeueCondition.wait(mMutex);
405 }
406 }
407
Daniel Lam6b091c52012-01-22 15:26:27 -0800408
409 if (found == INVALID_BUFFER_SLOT) {
410 // This should not happen.
411 ST_LOGE("dequeueBuffer: no available buffer slots");
412 return -EBUSY;
413 }
414
415 const int buf = found;
416 *outBuf = found;
417
Mathias Agopian546ed2d2012-03-01 22:11:25 -0800418 ATRACE_BUFFER_INDEX(buf);
419
Daniel Lam6b091c52012-01-22 15:26:27 -0800420 const bool useDefaultSize = !w && !h;
421 if (useDefaultSize) {
422 // use the default size
423 w = mDefaultWidth;
424 h = mDefaultHeight;
425 }
426
427 const bool updateFormat = (format != 0);
428 if (!updateFormat) {
429 // keep the current (or default) format
430 format = mPixelFormat;
431 }
432
433 // buffer is now in DEQUEUED (but can also be current at the same time,
434 // if we're in synchronous mode)
435 mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
436
437 const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
438 if ((buffer == NULL) ||
439 (uint32_t(buffer->width) != w) ||
440 (uint32_t(buffer->height) != h) ||
441 (uint32_t(buffer->format) != format) ||
442 ((uint32_t(buffer->usage) & usage) != usage))
443 {
444 usage |= GraphicBuffer::USAGE_HW_TEXTURE;
445 status_t error;
446 sp<GraphicBuffer> graphicBuffer(
447 mGraphicBufferAlloc->createGraphicBuffer(
448 w, h, format, usage, &error));
449 if (graphicBuffer == 0) {
450 ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer "
451 "failed");
452 return error;
453 }
454 if (updateFormat) {
455 mPixelFormat = format;
456 }
Daniel Lameae59d22012-01-22 15:26:27 -0800457
458 mSlots[buf].mAcquireCalled = false;
Daniel Lam6b091c52012-01-22 15:26:27 -0800459 mSlots[buf].mGraphicBuffer = graphicBuffer;
460 mSlots[buf].mRequestBufferCalled = false;
461 mSlots[buf].mFence = EGL_NO_SYNC_KHR;
Daniel Lameae59d22012-01-22 15:26:27 -0800462 mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
463
464
465
466
Daniel Lam6b091c52012-01-22 15:26:27 -0800467 returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
468 }
469
470 dpy = mSlots[buf].mEglDisplay;
471 fence = mSlots[buf].mFence;
472 mSlots[buf].mFence = EGL_NO_SYNC_KHR;
Daniel Lameae59d22012-01-22 15:26:27 -0800473 } // end lock scope
Daniel Lam6b091c52012-01-22 15:26:27 -0800474
475 if (fence != EGL_NO_SYNC_KHR) {
476 EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
477 // If something goes wrong, log the error, but return the buffer without
478 // synchronizing access to it. It's too late at this point to abort the
479 // dequeue operation.
480 if (result == EGL_FALSE) {
481 ALOGE("dequeueBuffer: error waiting for fence: %#x", eglGetError());
482 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
483 ALOGE("dequeueBuffer: timeout waiting for fence");
484 }
485 eglDestroySyncKHR(dpy, fence);
Daniel Lameae59d22012-01-22 15:26:27 -0800486
Daniel Lam6b091c52012-01-22 15:26:27 -0800487 }
488
489 ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf,
490 mSlots[*outBuf].mGraphicBuffer->handle, returnFlags);
491
492 return returnFlags;
493}
494
495status_t BufferQueue::setSynchronousMode(bool enabled) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800496 ATRACE_CALL();
Daniel Lam6b091c52012-01-22 15:26:27 -0800497 ST_LOGV("setSynchronousMode: enabled=%d", enabled);
498 Mutex::Autolock lock(mMutex);
499
500 if (mAbandoned) {
501 ST_LOGE("setSynchronousMode: SurfaceTexture has been abandoned!");
502 return NO_INIT;
503 }
504
505 status_t err = OK;
506 if (!mAllowSynchronousMode && enabled)
507 return err;
508
509 if (!enabled) {
510 // going to asynchronous mode, drain the queue
511 err = drainQueueLocked();
512 if (err != NO_ERROR)
513 return err;
514 }
515
516 if (mSynchronousMode != enabled) {
517 // - if we're going to asynchronous mode, the queue is guaranteed to be
518 // empty here
519 // - if the client set the number of buffers, we're guaranteed that
520 // we have at least 3 (because we don't allow less)
521 mSynchronousMode = enabled;
Dave Burke74ff8c22012-03-12 21:49:41 -0700522 mDequeueCondition.broadcast();
Daniel Lam6b091c52012-01-22 15:26:27 -0800523 }
524 return err;
525}
526
527status_t BufferQueue::queueBuffer(int buf, int64_t timestamp,
528 uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800529 ATRACE_CALL();
Mathias Agopian546ed2d2012-03-01 22:11:25 -0800530 ATRACE_BUFFER_INDEX(buf);
531
Daniel Lam6b091c52012-01-22 15:26:27 -0800532 ST_LOGV("queueBuffer: slot=%d time=%lld", buf, timestamp);
533
534 sp<FrameAvailableListener> listener;
535
536 { // scope for the lock
537 Mutex::Autolock lock(mMutex);
538 if (mAbandoned) {
539 ST_LOGE("queueBuffer: SurfaceTexture has been abandoned!");
540 return NO_INIT;
541 }
542 if (buf < 0 || buf >= mBufferCount) {
543 ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d",
544 mBufferCount, buf);
545 return -EINVAL;
546 } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
547 ST_LOGE("queueBuffer: slot %d is not owned by the client "
548 "(state=%d)", buf, mSlots[buf].mBufferState);
549 return -EINVAL;
Daniel Lam6b091c52012-01-22 15:26:27 -0800550 } else if (!mSlots[buf].mRequestBufferCalled) {
551 ST_LOGE("queueBuffer: slot %d was enqueued without requesting a "
552 "buffer", buf);
553 return -EINVAL;
554 }
555
556 if (mSynchronousMode) {
557 // In synchronous mode we queue all buffers in a FIFO.
558 mQueue.push_back(buf);
559
560 // Synchronous mode always signals that an additional frame should
561 // be consumed.
562 listener = mFrameAvailableListener;
563 } else {
564 // In asynchronous mode we only keep the most recent buffer.
565 if (mQueue.empty()) {
566 mQueue.push_back(buf);
567
568 // Asynchronous mode only signals that a frame should be
569 // consumed if no previous frame was pending. If a frame were
570 // pending then the consumer would have already been notified.
571 listener = mFrameAvailableListener;
572 } else {
573 Fifo::iterator front(mQueue.begin());
574 // buffer currently queued is freed
575 mSlots[*front].mBufferState = BufferSlot::FREE;
576 // and we record the new buffer index in the queued list
577 *front = buf;
578 }
579 }
580
581 mSlots[buf].mBufferState = BufferSlot::QUEUED;
582 mSlots[buf].mCrop = mNextCrop;
583 mSlots[buf].mTransform = mNextTransform;
584 mSlots[buf].mScalingMode = mNextScalingMode;
585 mSlots[buf].mTimestamp = timestamp;
586 mFrameCounter++;
587 mSlots[buf].mFrameNumber = mFrameCounter;
588
Daniel Lameae59d22012-01-22 15:26:27 -0800589 mBufferHasBeenQueued = true;
Dave Burke74ff8c22012-03-12 21:49:41 -0700590 mDequeueCondition.broadcast();
Daniel Lam6b091c52012-01-22 15:26:27 -0800591
592 *outWidth = mDefaultWidth;
593 *outHeight = mDefaultHeight;
Daniel Lamb2675792012-02-23 14:35:13 -0800594 *outTransform = mTransformHint;
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800595
596 ATRACE_INT(mConsumerName.string(), mQueue.size());
Daniel Lam6b091c52012-01-22 15:26:27 -0800597 } // scope for the lock
598
599 // call back without lock held
600 if (listener != 0) {
601 listener->onFrameAvailable();
602 }
603 return OK;
604}
605
606void BufferQueue::cancelBuffer(int buf) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800607 ATRACE_CALL();
Daniel Lam6b091c52012-01-22 15:26:27 -0800608 ST_LOGV("cancelBuffer: slot=%d", buf);
609 Mutex::Autolock lock(mMutex);
610
611 if (mAbandoned) {
612 ST_LOGW("cancelBuffer: BufferQueue has been abandoned!");
613 return;
614 }
615
616 if (buf < 0 || buf >= mBufferCount) {
617 ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
618 mBufferCount, buf);
619 return;
620 } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
621 ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
622 buf, mSlots[buf].mBufferState);
623 return;
624 }
625 mSlots[buf].mBufferState = BufferSlot::FREE;
626 mSlots[buf].mFrameNumber = 0;
Dave Burke74ff8c22012-03-12 21:49:41 -0700627 mDequeueCondition.broadcast();
Daniel Lam6b091c52012-01-22 15:26:27 -0800628}
629
630status_t BufferQueue::setCrop(const Rect& crop) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800631 ATRACE_CALL();
Daniel Lam6b091c52012-01-22 15:26:27 -0800632 ST_LOGV("setCrop: crop=[%d,%d,%d,%d]", crop.left, crop.top, crop.right,
633 crop.bottom);
634
635 Mutex::Autolock lock(mMutex);
636 if (mAbandoned) {
637 ST_LOGE("setCrop: BufferQueue has been abandoned!");
638 return NO_INIT;
639 }
640 mNextCrop = crop;
641 return OK;
642}
643
644status_t BufferQueue::setTransform(uint32_t transform) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800645 ATRACE_CALL();
Daniel Lam6b091c52012-01-22 15:26:27 -0800646 ST_LOGV("setTransform: xform=%#x", transform);
647 Mutex::Autolock lock(mMutex);
648 if (mAbandoned) {
649 ST_LOGE("setTransform: BufferQueue has been abandoned!");
650 return NO_INIT;
651 }
652 mNextTransform = transform;
653 return OK;
654}
655
656status_t BufferQueue::setScalingMode(int mode) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800657 ATRACE_CALL();
Daniel Lam6b091c52012-01-22 15:26:27 -0800658 ST_LOGV("setScalingMode: mode=%d", mode);
659
660 switch (mode) {
661 case NATIVE_WINDOW_SCALING_MODE_FREEZE:
662 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
663 break;
664 default:
665 ST_LOGE("unknown scaling mode: %d", mode);
666 return BAD_VALUE;
667 }
668
669 Mutex::Autolock lock(mMutex);
670 mNextScalingMode = mode;
671 return OK;
672}
673
674status_t BufferQueue::connect(int api,
675 uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800676 ATRACE_CALL();
Daniel Lam6b091c52012-01-22 15:26:27 -0800677 ST_LOGV("connect: api=%d", api);
678 Mutex::Autolock lock(mMutex);
679
680 if (mAbandoned) {
681 ST_LOGE("connect: BufferQueue has been abandoned!");
682 return NO_INIT;
683 }
684
685 int err = NO_ERROR;
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 != NO_CONNECTED_API) {
692 ST_LOGE("connect: already connected (cur=%d, req=%d)",
693 mConnectedApi, api);
694 err = -EINVAL;
695 } else {
696 mConnectedApi = api;
697 *outWidth = mDefaultWidth;
698 *outHeight = mDefaultHeight;
699 *outTransform = 0;
700 }
701 break;
702 default:
703 err = -EINVAL;
704 break;
705 }
Daniel Lameae59d22012-01-22 15:26:27 -0800706
707 mBufferHasBeenQueued = false;
708
Daniel Lam6b091c52012-01-22 15:26:27 -0800709 return err;
710}
711
712status_t BufferQueue::disconnect(int api) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800713 ATRACE_CALL();
Daniel Lam6b091c52012-01-22 15:26:27 -0800714 ST_LOGV("disconnect: api=%d", api);
715 Mutex::Autolock lock(mMutex);
716
717 if (mAbandoned) {
718 // it is not really an error to disconnect after the surface
719 // has been abandoned, it should just be a no-op.
720 return NO_ERROR;
721 }
722
723 int err = NO_ERROR;
724 switch (api) {
725 case NATIVE_WINDOW_API_EGL:
726 case NATIVE_WINDOW_API_CPU:
727 case NATIVE_WINDOW_API_MEDIA:
728 case NATIVE_WINDOW_API_CAMERA:
729 if (mConnectedApi == api) {
730 drainQueueAndFreeBuffersLocked();
731 mConnectedApi = NO_CONNECTED_API;
732 mNextCrop.makeInvalid();
733 mNextScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
734 mNextTransform = 0;
Dave Burke74ff8c22012-03-12 21:49:41 -0700735 mDequeueCondition.broadcast();
Daniel Lam6b091c52012-01-22 15:26:27 -0800736 } else {
737 ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)",
738 mConnectedApi, api);
739 err = -EINVAL;
740 }
741 break;
742 default:
743 ST_LOGE("disconnect: unknown API %d", api);
744 err = -EINVAL;
745 break;
746 }
747 return err;
748}
749
Daniel Lameae59d22012-01-22 15:26:27 -0800750void BufferQueue::dump(String8& result) const
751{
752 char buffer[1024];
753 BufferQueue::dump(result, "", buffer, 1024);
754}
755
756void BufferQueue::dump(String8& result, const char* prefix,
757 char* buffer, size_t SIZE) const
758{
759 Mutex::Autolock _l(mMutex);
760 snprintf(buffer, SIZE,
761 "%snext : {crop=[%d,%d,%d,%d], transform=0x%02x}\n"
762 ,prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right,
763 mNextCrop.bottom, mNextTransform
764 );
765 result.append(buffer);
766
767 String8 fifo;
768 int fifoSize = 0;
769 Fifo::const_iterator i(mQueue.begin());
770 while (i != mQueue.end()) {
771 snprintf(buffer, SIZE, "%02d ", *i++);
772 fifoSize++;
773 fifo.append(buffer);
774 }
775
776 snprintf(buffer, SIZE,
777 "%s-BufferQueue mBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
778 "mPixelFormat=%d, FIFO(%d)={%s}\n",
779 prefix, mBufferCount, mSynchronousMode, mDefaultWidth,
780 mDefaultHeight, mPixelFormat, fifoSize, fifo.string());
781 result.append(buffer);
782
783
784 struct {
785 const char * operator()(int state) const {
786 switch (state) {
787 case BufferSlot::DEQUEUED: return "DEQUEUED";
788 case BufferSlot::QUEUED: return "QUEUED";
789 case BufferSlot::FREE: return "FREE";
790 case BufferSlot::ACQUIRED: return "ACQUIRED";
791 default: return "Unknown";
792 }
793 }
794 } stateName;
795
796 for (int i=0 ; i<mBufferCount ; i++) {
797 const BufferSlot& slot(mSlots[i]);
798 snprintf(buffer, SIZE,
799 "%s%s[%02d] "
800 "state=%-8s, crop=[%d,%d,%d,%d], "
801 "transform=0x%02x, timestamp=%lld",
802 prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i,
803 stateName(slot.mBufferState),
804 slot.mCrop.left, slot.mCrop.top, slot.mCrop.right,
805 slot.mCrop.bottom, slot.mTransform, slot.mTimestamp
806 );
807 result.append(buffer);
808
809 const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
810 if (buf != NULL) {
811 snprintf(buffer, SIZE,
812 ", %p [%4ux%4u:%4u,%3X]",
813 buf->handle, buf->width, buf->height, buf->stride,
814 buf->format);
815 result.append(buffer);
816 }
817 result.append("\n");
818 }
819}
820
Daniel Lam6b091c52012-01-22 15:26:27 -0800821void BufferQueue::freeBufferLocked(int i) {
822 mSlots[i].mGraphicBuffer = 0;
823 mSlots[i].mBufferState = BufferSlot::FREE;
824 mSlots[i].mFrameNumber = 0;
Daniel Lameae59d22012-01-22 15:26:27 -0800825 mSlots[i].mAcquireCalled = false;
826
827 // destroy fence as BufferQueue now takes ownership
828 if (mSlots[i].mFence != EGL_NO_SYNC_KHR) {
829 eglDestroySyncKHR(mSlots[i].mEglDisplay, mSlots[i].mFence);
830 mSlots[i].mFence = EGL_NO_SYNC_KHR;
Daniel Lam6b091c52012-01-22 15:26:27 -0800831 }
832}
833
834void BufferQueue::freeAllBuffersLocked() {
835 ALOGW_IF(!mQueue.isEmpty(),
836 "freeAllBuffersLocked called but mQueue is not empty");
Daniel Lameae59d22012-01-22 15:26:27 -0800837 mQueue.clear();
838 mBufferHasBeenQueued = false;
Daniel Lam6b091c52012-01-22 15:26:27 -0800839 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
840 freeBufferLocked(i);
841 }
842}
843
Daniel Lameae59d22012-01-22 15:26:27 -0800844status_t BufferQueue::acquire(BufferItem *buffer) {
Mathias Agopian546ed2d2012-03-01 22:11:25 -0800845 ATRACE_CALL();
Daniel Lameae59d22012-01-22 15:26:27 -0800846 Mutex::Autolock _l(mMutex);
847 // check if queue is empty
848 // In asynchronous mode the list is guaranteed to be one buffer
849 // deep, while in synchronous mode we use the oldest buffer.
850 if (!mQueue.empty()) {
851 Fifo::iterator front(mQueue.begin());
852 int buf = *front;
853
Mathias Agopian546ed2d2012-03-01 22:11:25 -0800854 ATRACE_BUFFER_INDEX(buf);
855
Daniel Lameae59d22012-01-22 15:26:27 -0800856 if (mSlots[buf].mAcquireCalled) {
857 buffer->mGraphicBuffer = NULL;
858 }
859 else {
860 buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer;
861 }
862 buffer->mCrop = mSlots[buf].mCrop;
863 buffer->mTransform = mSlots[buf].mTransform;
864 buffer->mScalingMode = mSlots[buf].mScalingMode;
865 buffer->mFrameNumber = mSlots[buf].mFrameNumber;
Daniel Lam3fcee502012-03-02 10:17:34 -0800866 buffer->mTimestamp = mSlots[buf].mTimestamp;
Daniel Lameae59d22012-01-22 15:26:27 -0800867 buffer->mBuf = buf;
868 mSlots[buf].mAcquireCalled = true;
869
870 mSlots[buf].mBufferState = BufferSlot::ACQUIRED;
871 mQueue.erase(front);
Dave Burke74ff8c22012-03-12 21:49:41 -0700872 mDequeueCondition.broadcast();
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800873
874 ATRACE_INT(mConsumerName.string(), mQueue.size());
Daniel Lameae59d22012-01-22 15:26:27 -0800875 }
876 else {
Daniel Lamb2675792012-02-23 14:35:13 -0800877 // should be a better return code?
878 return -EINVAL;
Daniel Lameae59d22012-01-22 15:26:27 -0800879 }
880
881 return OK;
882}
883
884status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display,
885 EGLSyncKHR fence) {
Mathias Agopian546ed2d2012-03-01 22:11:25 -0800886 ATRACE_CALL();
887 ATRACE_BUFFER_INDEX(buf);
888
Daniel Lameae59d22012-01-22 15:26:27 -0800889 Mutex::Autolock _l(mMutex);
890
891 if (buf == INVALID_BUFFER_SLOT) {
892 return -EINVAL;
893 }
894
895 mSlots[buf].mEglDisplay = display;
896 mSlots[buf].mFence = fence;
897
898 // The current buffer becomes FREE if it was still in the queued
899 // state. If it has already been given to the client
900 // (synchronous mode), then it stays in DEQUEUED state.
901 if (mSlots[buf].mBufferState == BufferSlot::QUEUED
902 || mSlots[buf].mBufferState == BufferSlot::ACQUIRED) {
903 mSlots[buf].mBufferState = BufferSlot::FREE;
904 }
Dave Burke74ff8c22012-03-12 21:49:41 -0700905 mDequeueCondition.broadcast();
Daniel Lameae59d22012-01-22 15:26:27 -0800906
907 return OK;
908}
909
910status_t BufferQueue::consumerDisconnect() {
911 Mutex::Autolock lock(mMutex);
Daniel Lamb2675792012-02-23 14:35:13 -0800912
Daniel Lameae59d22012-01-22 15:26:27 -0800913 mAbandoned = true;
Daniel Lamb2675792012-02-23 14:35:13 -0800914
915 mQueue.clear();
Daniel Lameae59d22012-01-22 15:26:27 -0800916 freeAllBuffersLocked();
Dave Burke74ff8c22012-03-12 21:49:41 -0700917 mDequeueCondition.broadcast();
Daniel Lameae59d22012-01-22 15:26:27 -0800918 return OK;
919}
920
921status_t BufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h)
922{
923 ST_LOGV("setDefaultBufferSize: w=%d, h=%d", w, h);
924 if (!w || !h) {
925 ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)",
926 w, h);
927 return BAD_VALUE;
928 }
929
930 Mutex::Autolock lock(mMutex);
931 mDefaultWidth = w;
932 mDefaultHeight = h;
933 return OK;
934}
935
936status_t BufferQueue::setBufferCountServer(int bufferCount) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800937 ATRACE_CALL();
Daniel Lameae59d22012-01-22 15:26:27 -0800938 Mutex::Autolock lock(mMutex);
939 return setBufferCountServerLocked(bufferCount);
940}
941
Daniel Lam6b091c52012-01-22 15:26:27 -0800942void BufferQueue::freeAllBuffersExceptHeadLocked() {
943 ALOGW_IF(!mQueue.isEmpty(),
944 "freeAllBuffersExceptCurrentLocked called but mQueue is not empty");
945 int head = -1;
946 if (!mQueue.empty()) {
947 Fifo::iterator front(mQueue.begin());
948 head = *front;
949 }
Daniel Lameae59d22012-01-22 15:26:27 -0800950 mBufferHasBeenQueued = false;
Daniel Lam6b091c52012-01-22 15:26:27 -0800951 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
952 if (i != head) {
953 freeBufferLocked(i);
954 }
955 }
956}
957
958status_t BufferQueue::drainQueueLocked() {
959 while (mSynchronousMode && !mQueue.isEmpty()) {
960 mDequeueCondition.wait(mMutex);
961 if (mAbandoned) {
962 ST_LOGE("drainQueueLocked: BufferQueue has been abandoned!");
963 return NO_INIT;
964 }
965 if (mConnectedApi == NO_CONNECTED_API) {
966 ST_LOGE("drainQueueLocked: BufferQueue is not connected!");
967 return NO_INIT;
968 }
969 }
970 return NO_ERROR;
971}
972
973status_t BufferQueue::drainQueueAndFreeBuffersLocked() {
974 status_t err = drainQueueLocked();
975 if (err == NO_ERROR) {
976 if (mSynchronousMode) {
977 freeAllBuffersLocked();
978 } else {
979 freeAllBuffersExceptHeadLocked();
980 }
981 }
982 return err;
983}
984
985}; // namespace android