1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * Copyright (C) 2012 The Android Open Source Project
4 * Copyright (C) 2013 Mozilla Foundation
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #define LOG_TAG "GonkBufferQueue"
20 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
21 //#define LOG_NDEBUG 0
22
23 #define GL_GLEXT_PROTOTYPES
24 #define EGL_EGLEXT_PROTOTYPES
25
26 #include <utils/Log.h>
27 #include <utils/Trace.h>
28 #include <utils/CallStack.h>
29 #include <cutils/compiler.h>
30
31 #include "mozilla/layers/GrallocTextureClient.h"
32 #include "mozilla/layers/ImageBridgeChild.h"
33 #include "GonkBufferQueueKK.h"
34
35 #define ATRACE_BUFFER_INDEX(index)
36
37 using namespace mozilla;
38 using namespace mozilla::gfx;
39 using namespace mozilla::layers;
40
41 namespace android {
42
43 // Get an ID that's unique within this process.
createProcessUniqueId()44 static int32_t createProcessUniqueId() {
45 static volatile int32_t globalCounter = 0;
46 return android_atomic_inc(&globalCounter);
47 }
48
scalingModeName(int scalingMode)49 static const char* scalingModeName(int scalingMode) {
50 switch (scalingMode) {
51 case NATIVE_WINDOW_SCALING_MODE_FREEZE: return "FREEZE";
52 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: return "SCALE_TO_WINDOW";
53 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: return "SCALE_CROP";
54 default: return "Unknown";
55 }
56 }
57
GonkBufferQueue(bool allowSynchronousMode,const sp<IGraphicBufferAlloc> & allocator)58 GonkBufferQueue::GonkBufferQueue(bool allowSynchronousMode,
59 const sp<IGraphicBufferAlloc>& allocator) :
60 mDefaultWidth(1),
61 mDefaultHeight(1),
62 mMaxAcquiredBufferCount(1),
63 mDefaultMaxBufferCount(2),
64 mOverrideMaxBufferCount(0),
65 mSynchronousMode(true),
66 mConsumerControlledByApp(false),
67 mDequeueBufferCannotBlock(false),
68 mUseAsyncBuffer(true),
69 mConnectedApi(NO_CONNECTED_API),
70 mAbandoned(false),
71 mFrameCounter(0),
72 mBufferHasBeenQueued(false),
73 mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
74 mConsumerUsageBits(0),
75 mTransformHint(0)
76 {
77 // Choose a name using the PID and a process-unique ID.
78 mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
79
80 ALOGV("GonkBufferQueue");
81 }
82
~GonkBufferQueue()83 GonkBufferQueue::~GonkBufferQueue() {
84 ALOGV("~GonkBufferQueue");
85 }
86
setDefaultMaxBufferCountLocked(int count)87 status_t GonkBufferQueue::setDefaultMaxBufferCountLocked(int count) {
88 if (count < 2 || count > NUM_BUFFER_SLOTS)
89 return BAD_VALUE;
90
91 mDefaultMaxBufferCount = count;
92 mDequeueCondition.broadcast();
93
94 return NO_ERROR;
95 }
96
setConsumerName(const String8 & name)97 void GonkBufferQueue::setConsumerName(const String8& name) {
98 Mutex::Autolock lock(mMutex);
99 mConsumerName = name;
100 }
101
setDefaultBufferFormat(uint32_t defaultFormat)102 status_t GonkBufferQueue::setDefaultBufferFormat(uint32_t defaultFormat) {
103 Mutex::Autolock lock(mMutex);
104 mDefaultBufferFormat = defaultFormat;
105 return NO_ERROR;
106 }
107
setConsumerUsageBits(uint32_t usage)108 status_t GonkBufferQueue::setConsumerUsageBits(uint32_t usage) {
109 Mutex::Autolock lock(mMutex);
110 mConsumerUsageBits = usage;
111 return NO_ERROR;
112 }
113
setTransformHint(uint32_t hint)114 status_t GonkBufferQueue::setTransformHint(uint32_t hint) {
115 ALOGV("setTransformHint: %02x", hint);
116 Mutex::Autolock lock(mMutex);
117 mTransformHint = hint;
118 return NO_ERROR;
119 }
120
121 already_AddRefed<TextureClient>
getTextureClientFromBuffer(ANativeWindowBuffer * buffer)122 GonkBufferQueue::getTextureClientFromBuffer(ANativeWindowBuffer* buffer)
123 {
124 Mutex::Autolock _l(mMutex);
125 if (buffer == NULL) {
126 ALOGE("getSlotFromBufferLocked: encountered NULL buffer");
127 return nullptr;
128 }
129
130 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
131 if (mSlots[i].mGraphicBuffer != NULL && mSlots[i].mGraphicBuffer->handle == buffer->handle) {
132 RefPtr<TextureClient> client(mSlots[i].mTextureClient);
133 return client.forget();
134 }
135 }
136 ALOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle);
137 return nullptr;
138 }
139
getSlotFromTextureClientLocked(TextureClient * client) const140 int GonkBufferQueue::getSlotFromTextureClientLocked(
141 TextureClient* client) const
142 {
143 if (client == NULL) {
144 ALOGE("getSlotFromBufferLocked: encountered NULL buffer");
145 return BAD_VALUE;
146 }
147
148 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
149 if (mSlots[i].mTextureClient == client) {
150 return i;
151 }
152 }
153 ALOGE("getSlotFromBufferLocked: unknown TextureClient: %p", client);
154 return BAD_VALUE;
155 }
156
setBufferCount(int bufferCount)157 status_t GonkBufferQueue::setBufferCount(int bufferCount) {
158 ALOGV("setBufferCount: count=%d", bufferCount);
159
160 sp<IConsumerListener> listener;
161 {
162 Mutex::Autolock lock(mMutex);
163
164 if (mAbandoned) {
165 ALOGE("setBufferCount: GonkBufferQueue has been abandoned!");
166 return NO_INIT;
167 }
168 if (bufferCount > NUM_BUFFER_SLOTS) {
169 ALOGE("setBufferCount: bufferCount too large (max %d)",
170 NUM_BUFFER_SLOTS);
171 return BAD_VALUE;
172 }
173
174 // Error out if the user has dequeued buffers
175 for (int i=0 ; i<NUM_BUFFER_SLOTS; i++) {
176 if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
177 ALOGE("setBufferCount: client owns some buffers");
178 return -EINVAL;
179 }
180 }
181
182 if (bufferCount == 0) {
183 mOverrideMaxBufferCount = 0;
184 mDequeueCondition.broadcast();
185 return NO_ERROR;
186 }
187
188 // fine to assume async to false before we're setting the buffer count
189 const int minBufferSlots = getMinMaxBufferCountLocked(false);
190 if (bufferCount < minBufferSlots) {
191 ALOGE("setBufferCount: requested buffer count (%d) is less than "
192 "minimum (%d)", bufferCount, minBufferSlots);
193 return BAD_VALUE;
194 }
195
196 // here we're guaranteed that the client doesn't have dequeued buffers
197 // and will release all of its buffer references. We don't clear the
198 // queue, however, so currently queued buffers still get displayed.
199 // XXX: Should this use drainQueueAndFreeBuffersLocked instead?
200 freeAllBuffersLocked();
201 mOverrideMaxBufferCount = bufferCount;
202 mDequeueCondition.broadcast();
203 listener = mConsumerListener;
204 } // scope for lock
205
206 if (listener != NULL) {
207 listener->onBuffersReleased();
208 }
209
210 return NO_ERROR;
211 }
212
query(int what,int * outValue)213 int GonkBufferQueue::query(int what, int* outValue)
214 {
215 ATRACE_CALL();
216 Mutex::Autolock lock(mMutex);
217
218 if (mAbandoned) {
219 ALOGE("query: GonkBufferQueue has been abandoned!");
220 return NO_INIT;
221 }
222
223 int value;
224 switch (what) {
225 case NATIVE_WINDOW_WIDTH:
226 value = mDefaultWidth;
227 break;
228 case NATIVE_WINDOW_HEIGHT:
229 value = mDefaultHeight;
230 break;
231 case NATIVE_WINDOW_FORMAT:
232 value = mDefaultBufferFormat;
233 break;
234 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
235 value = getMinUndequeuedBufferCount(false);
236 break;
237 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
238 value = (mQueue.size() >= 2);
239 break;
240 case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
241 value = mConsumerUsageBits;
242 break;
243 default:
244 return BAD_VALUE;
245 }
246 outValue[0] = value;
247 return NO_ERROR;
248 }
249
requestBuffer(int slot,sp<GraphicBuffer> * buf)250 status_t GonkBufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
251 ATRACE_CALL();
252 ALOGV("requestBuffer: slot=%d", slot);
253 Mutex::Autolock lock(mMutex);
254 if (mAbandoned) {
255 ALOGE("requestBuffer: GonkBufferQueue has been abandoned!");
256 return NO_INIT;
257 }
258 if (slot < 0 || slot >= NUM_BUFFER_SLOTS) {
259 ALOGE("requestBuffer: slot index out of range [0, %d]: %d",
260 NUM_BUFFER_SLOTS, slot);
261 return BAD_VALUE;
262 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
263 ALOGE("requestBuffer: slot %d is not owned by the client (state=%d)",
264 slot, mSlots[slot].mBufferState);
265 return BAD_VALUE;
266 }
267 mSlots[slot].mRequestBufferCalled = true;
268 *buf = mSlots[slot].mGraphicBuffer;
269 return NO_ERROR;
270 }
271
dequeueBuffer(int * outBuf,sp<Fence> * outFence,bool async,uint32_t w,uint32_t h,uint32_t format,uint32_t usage)272 status_t GonkBufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence, bool async,
273 uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
274 ATRACE_CALL();
275 ALOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);
276
277 if ((w && !h) || (!w && h)) {
278 ALOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
279 return BAD_VALUE;
280 }
281
282 status_t returnFlags(OK);
283 int buf = INVALID_BUFFER_SLOT;
284
285 { // Scope for the lock
286 Mutex::Autolock lock(mMutex);
287
288 if (format == 0) {
289 format = mDefaultBufferFormat;
290 }
291 // turn on usage bits the consumer requested
292 usage |= mConsumerUsageBits;
293
294 int found = -1;
295 bool tryAgain = true;
296 while (tryAgain) {
297 if (mAbandoned) {
298 ALOGE("dequeueBuffer: GonkBufferQueue has been abandoned!");
299 return NO_INIT;
300 }
301
302 const int maxBufferCount = getMaxBufferCountLocked(async);
303 if (async && mOverrideMaxBufferCount) {
304 // FIXME: some drivers are manually setting the buffer-count (which they
305 // shouldn't), so we do this extra test here to handle that case.
306 // This is TEMPORARY, until we get this fixed.
307 if (mOverrideMaxBufferCount < maxBufferCount) {
308 ALOGE("dequeueBuffer: async mode is invalid with buffercount override");
309 return BAD_VALUE;
310 }
311 }
312
313 // Free up any buffers that are in slots beyond the max buffer
314 // count.
315 //for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) {
316 // assert(mSlots[i].mBufferState == BufferSlot::FREE);
317 // if (mSlots[i].mGraphicBuffer != NULL) {
318 // freeBufferLocked(i);
319 // returnFlags |= IGraphicBufferProducer::RELEASE_ALL_BUFFERS;
320 // }
321 //}
322
323 // look for a free buffer to give to the client
324 found = INVALID_BUFFER_SLOT;
325 int dequeuedCount = 0;
326 int acquiredCount = 0;
327 for (int i = 0; i < maxBufferCount; i++) {
328 const int state = mSlots[i].mBufferState;
329 switch (state) {
330 case BufferSlot::DEQUEUED:
331 dequeuedCount++;
332 break;
333 case BufferSlot::ACQUIRED:
334 acquiredCount++;
335 break;
336 case BufferSlot::FREE:
337 /* We return the oldest of the free buffers to avoid
338 * stalling the producer if possible. This is because
339 * the consumer may still have pending reads of the
340 * buffers in flight.
341 */
342 if ((found < 0) ||
343 mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) {
344 found = i;
345 }
346 break;
347 }
348 }
349
350 // clients are not allowed to dequeue more than one buffer
351 // if they didn't set a buffer count.
352 if (!mOverrideMaxBufferCount && dequeuedCount) {
353 ALOGE("dequeueBuffer: can't dequeue multiple buffers without "
354 "setting the buffer count");
355 return -EINVAL;
356 }
357
358 // See whether a buffer has been queued since the last
359 // setBufferCount so we know whether to perform the min undequeued
360 // buffers check below.
361 if (mBufferHasBeenQueued) {
362 // make sure the client is not trying to dequeue more buffers
363 // than allowed.
364 const int newUndequeuedCount = maxBufferCount - (dequeuedCount+1);
365 const int minUndequeuedCount = getMinUndequeuedBufferCount(async);
366 if (newUndequeuedCount < minUndequeuedCount) {
367 ALOGE("dequeueBuffer: min undequeued buffer count (%d) "
368 "exceeded (dequeued=%d undequeudCount=%d)",
369 minUndequeuedCount, dequeuedCount,
370 newUndequeuedCount);
371 return -EBUSY;
372 }
373 }
374
375 // If no buffer is found, wait for a buffer to be released or for
376 // the max buffer count to change.
377 tryAgain = found == INVALID_BUFFER_SLOT;
378 if (tryAgain) {
379 // return an error if we're in "cannot block" mode (producer and consumer
380 // are controlled by the application) -- however, the consumer is allowed
381 // to acquire briefly an extra buffer (which could cause us to have to wait here)
382 // and that's okay because we know the wait will be brief (it happens
383 // if we dequeue a buffer while the consumer has acquired one but not released
384 // the old one yet -- for e.g.: see GLConsumer::updateTexImage()).
385 if (mDequeueBufferCannotBlock && (acquiredCount <= mMaxAcquiredBufferCount)) {
386 ALOGE("dequeueBuffer: would block! returning an error instead.");
387 return WOULD_BLOCK;
388 }
389 mDequeueCondition.wait(mMutex);
390 }
391 }
392
393
394 if (found == INVALID_BUFFER_SLOT) {
395 // This should not happen.
396 ALOGE("dequeueBuffer: no available buffer slots");
397 return -EBUSY;
398 }
399
400 buf = found;
401 *outBuf = found;
402
403 const bool useDefaultSize = !w && !h;
404 if (useDefaultSize) {
405 // use the default size
406 w = mDefaultWidth;
407 h = mDefaultHeight;
408 }
409
410 mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
411
412 const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
413 if ((buffer == NULL) ||
414 (uint32_t(buffer->width) != w) ||
415 (uint32_t(buffer->height) != h) ||
416 (uint32_t(buffer->format) != format) ||
417 ((uint32_t(buffer->usage) & usage) != usage))
418 {
419 mSlots[buf].mAcquireCalled = false;
420 mSlots[buf].mGraphicBuffer = NULL;
421 mSlots[buf].mRequestBufferCalled = false;
422 mSlots[buf].mFence = Fence::NO_FENCE;
423 if (mSlots[buf].mTextureClient) {
424 mSlots[buf].mTextureClient->ClearRecycleCallback();
425 // release TextureClient in ImageBridge thread
426 RefPtr<TextureClientReleaseTask> task =
427 MakeAndAddRef<TextureClientReleaseTask>(mSlots[buf].mTextureClient);
428 mSlots[buf].mTextureClient = NULL;
429 ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(task.forget());
430 }
431 returnFlags |= IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION;
432 }
433
434
435 if (CC_UNLIKELY(mSlots[buf].mFence == NULL)) {
436 ALOGE("dequeueBuffer: about to return a NULL fence from mSlot. "
437 "buf=%d, w=%d, h=%d, format=%d",
438 buf, buffer->width, buffer->height, buffer->format);
439 }
440 *outFence = mSlots[buf].mFence;
441 mSlots[buf].mFence = Fence::NO_FENCE;
442 } // end lock scope
443
444 if (returnFlags & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
445
446 RefPtr<LayersIPCChannel> allocator = ImageBridgeChild::GetSingleton();
447 usage |= GraphicBuffer::USAGE_HW_TEXTURE;
448 GrallocTextureData* texData = GrallocTextureData::Create(IntSize(w, h), format,
449 gfx::BackendType::NONE, usage,
450 allocator);
451 if (!texData) {
452 return -ENOMEM;
453 }
454
455 RefPtr<TextureClient> textureClient = new TextureClient(texData, TextureFlags::RECYCLE | TextureFlags::DEALLOCATE_CLIENT, allocator);
456
457 { // Scope for the lock
458 Mutex::Autolock lock(mMutex);
459
460 if (mAbandoned) {
461 ALOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
462 return NO_INIT;
463 }
464
465 mSlots[buf].mGraphicBuffer = texData->GetGraphicBuffer();
466 mSlots[buf].mTextureClient = textureClient;
467 ALOGD("dequeueBuffer: returning slot=%d buf=%p ", buf,
468 mSlots[buf].mGraphicBuffer->handle);
469
470 }
471
472 }
473
474 ALOGV("dequeueBuffer: returning slot=%d/%llu buf=%p flags=%#x", *outBuf,
475 mSlots[*outBuf].mFrameNumber,
476 mSlots[*outBuf].mGraphicBuffer->handle, returnFlags);
477
478 return returnFlags;
479 }
480
setSynchronousMode(bool enabled)481 status_t GonkBufferQueue::setSynchronousMode(bool enabled) {
482 ALOGV("setSynchronousMode: enabled=%d", enabled);
483 Mutex::Autolock lock(mMutex);
484
485 if (mAbandoned) {
486 ALOGE("setSynchronousMode: BufferQueue has been abandoned!");
487 return NO_INIT;
488 }
489
490 if (mSynchronousMode != enabled) {
491 mSynchronousMode = enabled;
492 mDequeueCondition.broadcast();
493 }
494 return OK;
495 }
496
queueBuffer(int buf,const QueueBufferInput & input,QueueBufferOutput * output)497 status_t GonkBufferQueue::queueBuffer(int buf,
498 const QueueBufferInput& input, QueueBufferOutput* output) {
499 ATRACE_CALL();
500
501 Rect crop;
502 uint32_t transform;
503 int scalingMode;
504 int64_t timestamp;
505 bool isAutoTimestamp;
506 bool async;
507 sp<Fence> fence;
508
509 input.deflate(×tamp, &isAutoTimestamp, &crop, &scalingMode, &transform,
510 &async, &fence);
511
512 if (fence == NULL) {
513 ALOGE("queueBuffer: fence is NULL");
514 return BAD_VALUE;
515 }
516
517 ALOGV("queueBuffer: slot=%d time=%#llx crop=[%d,%d,%d,%d] tr=%#x "
518 "scale=%s",
519 buf, timestamp, crop.left, crop.top, crop.right, crop.bottom,
520 transform, scalingModeName(scalingMode));
521
522 switch (scalingMode) {
523 case NATIVE_WINDOW_SCALING_MODE_FREEZE:
524 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
525 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
526 case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
527 break;
528 default:
529 ALOGE("unknown scaling mode: %d", scalingMode);
530 return -EINVAL;
531 }
532
533 sp<IConsumerListener> listener;
534
535 { // scope for the lock
536 Mutex::Autolock lock(mMutex);
537
538 if (mAbandoned) {
539 ALOGE("queueBuffer: GonkBufferQueue has been abandoned!");
540 return NO_INIT;
541 }
542
543 const int maxBufferCount = getMaxBufferCountLocked(async);
544 if (async && mOverrideMaxBufferCount) {
545 // FIXME: some drivers are manually setting the buffer-count (which they
546 // shouldn't), so we do this extra test here to handle that case.
547 // This is TEMPORARY, until we get this fixed.
548 if (mOverrideMaxBufferCount < maxBufferCount) {
549 ALOGE("queueBuffer: async mode is invalid with buffercount override");
550 return BAD_VALUE;
551 }
552 }
553 if (buf < 0 || buf >= maxBufferCount) {
554 ALOGE("queueBuffer: slot index out of range [0, %d]: %d",
555 maxBufferCount, buf);
556 return -EINVAL;
557 } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
558 ALOGE("queueBuffer: slot %d is not owned by the client "
559 "(state=%d)", buf, mSlots[buf].mBufferState);
560 return -EINVAL;
561 } else if (!mSlots[buf].mRequestBufferCalled) {
562 ALOGE("queueBuffer: slot %d was enqueued without requesting a "
563 "buffer", buf);
564 return -EINVAL;
565 }
566
567 ALOGV("queueBuffer: slot=%d/%llu time=%#llx crop=[%d,%d,%d,%d] "
568 "tr=%#x scale=%s",
569 buf, mFrameCounter + 1, timestamp,
570 crop.left, crop.top, crop.right, crop.bottom,
571 transform, scalingModeName(scalingMode));
572
573 const sp<GraphicBuffer>& graphicBuffer(mSlots[buf].mGraphicBuffer);
574 Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
575 Rect croppedCrop;
576 crop.intersect(bufferRect, &croppedCrop);
577 if (croppedCrop != crop) {
578 ALOGE("queueBuffer: crop rect is not contained within the "
579 "buffer in slot %d", buf);
580 return -EINVAL;
581 }
582
583 mSlots[buf].mFence = fence;
584 mSlots[buf].mBufferState = BufferSlot::QUEUED;
585 mFrameCounter++;
586 mSlots[buf].mFrameNumber = mFrameCounter;
587
588 BufferItem item;
589 item.mAcquireCalled = mSlots[buf].mAcquireCalled;
590 item.mGraphicBuffer = mSlots[buf].mGraphicBuffer;
591 item.mCrop = crop;
592 item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
593 item.mTransformToDisplayInverse = bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
594 item.mScalingMode = scalingMode;
595 item.mTimestamp = timestamp;
596 item.mIsAutoTimestamp = isAutoTimestamp;
597 item.mFrameNumber = mFrameCounter;
598 item.mBuf = buf;
599 item.mFence = fence;
600 item.mIsDroppable = mDequeueBufferCannotBlock || async;
601
602 if (mQueue.empty()) {
603 // when the queue is empty, we can ignore "mDequeueBufferCannotBlock", and
604 // simply queue this buffer.
605 mQueue.push_back(item);
606 } else {
607 // when the queue is not empty, we need to look at the front buffer
608 // state and see if we need to replace it.
609 Fifo::iterator front(mQueue.begin());
610 if (front->mIsDroppable || !mSynchronousMode) {
611 // buffer slot currently queued is marked free if still tracked
612 if (stillTracking(front)) {
613 mSlots[front->mBuf].mBufferState = BufferSlot::FREE;
614 // reset the frame number of the freed buffer so that it is the first in
615 // line to be dequeued again.
616 mSlots[front->mBuf].mFrameNumber = 0;
617 }
618 // and we record the new buffer in the queued list
619 *front = item;
620 } else {
621 mQueue.push_back(item);
622 }
623 }
624 // always signals that an additional frame should be consumed
625 // to handle max acquired buffer count reached case.
626 listener = mConsumerListener;
627
628 mBufferHasBeenQueued = true;
629 mDequeueCondition.broadcast();
630
631 output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint,
632 mQueue.size());
633
634 } // scope for the lock
635
636 // call back without lock held
637 if (listener != 0) {
638 listener->onFrameAvailable();
639 }
640 return NO_ERROR;
641 }
642
cancelBuffer(int buf,const sp<Fence> & fence)643 void GonkBufferQueue::cancelBuffer(int buf, const sp<Fence>& fence) {
644 ATRACE_CALL();
645 ALOGV("cancelBuffer: slot=%d", buf);
646 Mutex::Autolock lock(mMutex);
647
648 if (mAbandoned) {
649 ALOGW("cancelBuffer: GonkBufferQueue has been abandoned!");
650 return;
651 }
652
653 if (buf < 0 || buf >= NUM_BUFFER_SLOTS) {
654 ALOGE("cancelBuffer: slot index out of range [0, %d]: %d",
655 NUM_BUFFER_SLOTS, buf);
656 return;
657 } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
658 ALOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
659 buf, mSlots[buf].mBufferState);
660 return;
661 } else if (fence == NULL) {
662 ALOGE("cancelBuffer: fence is NULL");
663 return;
664 }
665 mSlots[buf].mBufferState = BufferSlot::FREE;
666 mSlots[buf].mFrameNumber = 0;
667 mSlots[buf].mFence = fence;
668 mDequeueCondition.broadcast();
669 }
670
671
connect(const sp<IBinder> & token,int api,bool producerControlledByApp,QueueBufferOutput * output)672 status_t GonkBufferQueue::connect(const sp<IBinder>& token,
673 int api, bool producerControlledByApp, QueueBufferOutput* output) {
674 ATRACE_CALL();
675 ALOGV("connect: api=%d producerControlledByApp=%s", api,
676 producerControlledByApp ? "true" : "false");
677 Mutex::Autolock lock(mMutex);
678
679 retry:
680 if (mAbandoned) {
681 ALOGE("connect: GonkBufferQueue has been abandoned!");
682 return NO_INIT;
683 }
684
685 if (mConsumerListener == NULL) {
686 ALOGE("connect: GonkBufferQueue has no consumer!");
687 return NO_INIT;
688 }
689
690 if (mConnectedApi != NO_CONNECTED_API) {
691 ALOGE("connect: already connected (cur=%d, req=%d)",
692 mConnectedApi, api);
693 return -EINVAL;
694 }
695
696 // If we disconnect and reconnect quickly, we can be in a state where our slots are
697 // empty but we have many buffers in the queue. This can cause us to run out of
698 // memory if we outrun the consumer. Wait here if it looks like we have too many
699 // buffers queued up.
700 int maxBufferCount = getMaxBufferCountLocked(false); // worst-case, i.e. largest value
701 if (mQueue.size() > (size_t) maxBufferCount) {
702 // TODO: make this bound tighter?
703 ALOGV("queue size is %d, waiting", mQueue.size());
704 mDequeueCondition.wait(mMutex);
705 goto retry;
706 }
707
708 int err = NO_ERROR;
709 switch (api) {
710 case NATIVE_WINDOW_API_EGL:
711 case NATIVE_WINDOW_API_CPU:
712 case NATIVE_WINDOW_API_MEDIA:
713 case NATIVE_WINDOW_API_CAMERA:
714 mConnectedApi = api;
715 output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint, mQueue.size());
716
717 // set-up a death notification so that we can disconnect
718 // automatically when/if the remote producer dies.
719 if (token != NULL && token->remoteBinder() != NULL) {
720 status_t err = token->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
721 if (err == NO_ERROR) {
722 mConnectedProducerToken = token;
723 } else {
724 ALOGE("linkToDeath failed: %s (%d)", strerror(-err), err);
725 }
726 }
727 break;
728 default:
729 err = -EINVAL;
730 break;
731 }
732
733 mBufferHasBeenQueued = false;
734 mDequeueBufferCannotBlock = mConsumerControlledByApp && producerControlledByApp;
735
736 return err;
737 }
738
binderDied(const wp<IBinder> & who)739 void GonkBufferQueue::binderDied(const wp<IBinder>& who) {
740 // If we're here, it means that a producer we were connected to died.
741 // We're GUARANTEED that we still are connected to it because it has no other way
742 // to get disconnected -- or -- we wouldn't be here because we're removing this
743 // callback upon disconnect. Therefore, it's okay to read mConnectedApi without
744 // synchronization here.
745 int api = mConnectedApi;
746 this->disconnect(api);
747 }
748
disconnect(int api)749 status_t GonkBufferQueue::disconnect(int api) {
750 ATRACE_CALL();
751 ALOGV("disconnect: api=%d", api);
752
753 int err = NO_ERROR;
754 sp<IConsumerListener> listener;
755
756 { // Scope for the lock
757 Mutex::Autolock lock(mMutex);
758
759 if (mAbandoned) {
760 // it is not really an error to disconnect after the surface
761 // has been abandoned, it should just be a no-op.
762 return NO_ERROR;
763 }
764
765 switch (api) {
766 case NATIVE_WINDOW_API_EGL:
767 case NATIVE_WINDOW_API_CPU:
768 case NATIVE_WINDOW_API_MEDIA:
769 case NATIVE_WINDOW_API_CAMERA:
770 if (mConnectedApi == api) {
771 freeAllBuffersLocked();
772 mConnectedApi = NO_CONNECTED_API;
773 mDequeueCondition.broadcast();
774 listener = mConsumerListener;
775 } else {
776 ALOGE("disconnect: connected to another api (cur=%d, req=%d)",
777 mConnectedApi, api);
778 err = -EINVAL;
779 }
780 break;
781 default:
782 ALOGE("disconnect: unknown API %d", api);
783 err = -EINVAL;
784 break;
785 }
786 }
787
788 if (listener != NULL) {
789 listener->onBuffersReleased();
790 }
791
792 return err;
793 }
794
dumpToString(String8 & result,const char * prefix) const795 void GonkBufferQueue::dumpToString(String8& result, const char* prefix) const {
796 Mutex::Autolock _l(mMutex);
797
798 String8 fifo;
799 int fifoSize = 0;
800 Fifo::const_iterator i(mQueue.begin());
801 while (i != mQueue.end()) {
802 fifo.appendFormat("%02d:%p crop=[%d,%d,%d,%d], "
803 "xform=0x%02x, time=%#llx, scale=%s\n",
804 i->mBuf, i->mGraphicBuffer.get(),
805 i->mCrop.left, i->mCrop.top, i->mCrop.right,
806 i->mCrop.bottom, i->mTransform, i->mTimestamp,
807 scalingModeName(i->mScalingMode)
808 );
809 i++;
810 fifoSize++;
811 }
812
813
814 result.appendFormat(
815 "%s-BufferQueue mMaxAcquiredBufferCount=%d, mDequeueBufferCannotBlock=%d, default-size=[%dx%d], "
816 "default-format=%d, transform-hint=%02x, FIFO(%d)={%s}\n",
817 prefix, mMaxAcquiredBufferCount, mDequeueBufferCannotBlock, mDefaultWidth,
818 mDefaultHeight, mDefaultBufferFormat, mTransformHint,
819 fifoSize, fifo.string());
820
821 struct {
822 const char * operator()(int state) const {
823 switch (state) {
824 case BufferSlot::DEQUEUED: return "DEQUEUED";
825 case BufferSlot::QUEUED: return "QUEUED";
826 case BufferSlot::FREE: return "FREE";
827 case BufferSlot::ACQUIRED: return "ACQUIRED";
828 default: return "Unknown";
829 }
830 }
831 } stateName;
832
833 // just trim the free buffers to not spam the dump
834 int maxBufferCount = 0;
835 for (int i=NUM_BUFFER_SLOTS-1 ; i>=0 ; i--) {
836 const BufferSlot& slot(mSlots[i]);
837 if ((slot.mBufferState != BufferSlot::FREE) || (slot.mGraphicBuffer != NULL)) {
838 maxBufferCount = i+1;
839 break;
840 }
841 }
842
843 for (int i=0 ; i<maxBufferCount ; i++) {
844 const BufferSlot& slot(mSlots[i]);
845 const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
846 result.appendFormat(
847 "%s%s[%02d:%p] state=%-8s",
848 prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i, buf.get(),
849 stateName(slot.mBufferState)
850 );
851
852 if (buf != NULL) {
853 result.appendFormat(
854 ", %p [%4ux%4u:%4u,%3X]",
855 buf->handle, buf->width, buf->height, buf->stride,
856 buf->format);
857 }
858 result.append("\n");
859 }
860 }
861
freeAllBuffersLocked()862 void GonkBufferQueue::freeAllBuffersLocked()
863 {
864 ALOGW_IF(!mQueue.isEmpty(),
865 "freeAllBuffersLocked called but mQueue is not empty");
866 mQueue.clear();
867 mBufferHasBeenQueued = false;
868 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
869 mSlots[i].mGraphicBuffer = 0;
870 if (mSlots[i].mTextureClient) {
871 mSlots[i].mTextureClient->ClearRecycleCallback();
872 // release TextureClient in ImageBridge thread
873 RefPtr<TextureClientReleaseTask> task =
874 MakeAndAddRef<TextureClientReleaseTask>(mSlots[i].mTextureClient);
875 mSlots[i].mTextureClient = NULL;
876 ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(task.forget());
877 }
878 if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) {
879 mSlots[i].mNeedsCleanupOnRelease = true;
880 }
881 mSlots[i].mBufferState = BufferSlot::FREE;
882 mSlots[i].mFrameNumber = 0;
883 mSlots[i].mAcquireCalled = false;
884 // destroy fence as GonkBufferQueue now takes ownership
885 mSlots[i].mFence = Fence::NO_FENCE;
886 }
887 }
888
acquireBuffer(BufferItem * buffer,nsecs_t expectedPresent)889 status_t GonkBufferQueue::acquireBuffer(BufferItem *buffer, nsecs_t expectedPresent) {
890 ATRACE_CALL();
891 Mutex::Autolock _l(mMutex);
892
893 // Check that the consumer doesn't currently have the maximum number of
894 // buffers acquired. We allow the max buffer count to be exceeded by one
895 // buffer, so that the consumer can successfully set up the newly acquired
896 // buffer before releasing the old one.
897 int numAcquiredBuffers = 0;
898 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
899 if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) {
900 numAcquiredBuffers++;
901 }
902 }
903 if (numAcquiredBuffers >= mMaxAcquiredBufferCount+1) {
904 ALOGE("acquireBuffer: max acquired buffer count reached: %d (max=%d)",
905 numAcquiredBuffers, mMaxAcquiredBufferCount);
906 return INVALID_OPERATION;
907 }
908
909 // check if queue is empty
910 // In asynchronous mode the list is guaranteed to be one buffer
911 // deep, while in synchronous mode we use the oldest buffer.
912 if (mQueue.empty()) {
913 return NO_BUFFER_AVAILABLE;
914 }
915
916 Fifo::iterator front(mQueue.begin());
917
918 // If expectedPresent is specified, we may not want to return a buffer yet.
919 // If it's specified and there's more than one buffer queued, we may
920 // want to drop a buffer.
921 if (expectedPresent != 0) {
922 const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second
923
924 // The "expectedPresent" argument indicates when the buffer is expected
925 // to be presented on-screen. If the buffer's desired-present time
926 // is earlier (less) than expectedPresent, meaning it'll be displayed
927 // on time or possibly late if we show it ASAP, we acquire and return
928 // it. If we don't want to display it until after the expectedPresent
929 // time, we return PRESENT_LATER without acquiring it.
930 //
931 // To be safe, we don't defer acquisition if expectedPresent is
932 // more than one second in the future beyond the desired present time
933 // (i.e. we'd be holding the buffer for a long time).
934 //
935 // NOTE: code assumes monotonic time values from the system clock are
936 // positive.
937
938 // Start by checking to see if we can drop frames. We skip this check
939 // if the timestamps are being auto-generated by Surface -- if the
940 // app isn't generating timestamps explicitly, they probably don't
941 // want frames to be discarded based on them.
942 while (mQueue.size() > 1 && !mQueue[0].mIsAutoTimestamp) {
943 // If entry[1] is timely, drop entry[0] (and repeat). We apply
944 // an additional criteria here: we only drop the earlier buffer if
945 // our desiredPresent falls within +/- 1 second of the expected
946 // present. Otherwise, bogus desiredPresent times (e.g. 0 or
947 // a small relative timestamp), which normally mean "ignore the
948 // timestamp and acquire immediately", would cause us to drop
949 // frames.
950 //
951 // We may want to add an additional criteria: don't drop the
952 // earlier buffer if entry[1]'s fence hasn't signaled yet.
953 //
954 // (Vector front is [0], back is [size()-1])
955 const BufferItem& bi(mQueue[1]);
956 nsecs_t desiredPresent = bi.mTimestamp;
957 if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC ||
958 desiredPresent > expectedPresent) {
959 // This buffer is set to display in the near future, or
960 // desiredPresent is garbage. Either way we don't want to
961 // drop the previous buffer just to get this on screen sooner.
962 ALOGV("pts nodrop: des=%lld expect=%lld (%lld) now=%lld",
963 desiredPresent, expectedPresent, desiredPresent - expectedPresent,
964 systemTime(CLOCK_MONOTONIC));
965 break;
966 }
967 ALOGV("pts drop: queue1des=%lld expect=%lld size=%d",
968 desiredPresent, expectedPresent, mQueue.size());
969 if (stillTracking(front)) {
970 // front buffer is still in mSlots, so mark the slot as free
971 mSlots[front->mBuf].mBufferState = BufferSlot::FREE;
972 }
973 mQueue.erase(front);
974 front = mQueue.begin();
975 }
976
977 // See if the front buffer is due.
978 nsecs_t desiredPresent = front->mTimestamp;
979 if (desiredPresent > expectedPresent &&
980 desiredPresent < expectedPresent + MAX_REASONABLE_NSEC) {
981 ALOGV("pts defer: des=%lld expect=%lld (%lld) now=%lld",
982 desiredPresent, expectedPresent, desiredPresent - expectedPresent,
983 systemTime(CLOCK_MONOTONIC));
984 return PRESENT_LATER;
985 }
986
987 ALOGV("pts accept: des=%lld expect=%lld (%lld) now=%lld",
988 desiredPresent, expectedPresent, desiredPresent - expectedPresent,
989 systemTime(CLOCK_MONOTONIC));
990 }
991
992 int buf = front->mBuf;
993 buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer;
994 buffer->mFrameNumber = mSlots[buf].mFrameNumber;
995 buffer->mBuf = buf;
996 buffer->mFence = mSlots[buf].mFence;
997 ATRACE_BUFFER_INDEX(buf);
998
999 ALOGV("acquireBuffer: acquiring { slot=%d/%llu, buffer=%p }",
1000 front->mBuf, front->mFrameNumber,
1001 front->mGraphicBuffer->handle);
1002 // if front buffer still being tracked update slot state
1003 if (stillTracking(front)) {
1004 mSlots[buf].mAcquireCalled = true;
1005 mSlots[buf].mNeedsCleanupOnRelease = false;
1006 mSlots[buf].mBufferState = BufferSlot::ACQUIRED;
1007 mSlots[buf].mFence = Fence::NO_FENCE;
1008 }
1009
1010 // If the buffer has previously been acquired by the consumer, set
1011 // mGraphicBuffer to NULL to avoid unnecessarily remapping this
1012 // buffer on the consumer side.
1013 //if (buffer->mAcquireCalled) {
1014 // buffer->mGraphicBuffer = NULL;
1015 //}
1016
1017 mQueue.erase(front);
1018 mDequeueCondition.broadcast();
1019
1020 return NO_ERROR;
1021 }
1022
releaseBuffer(int buf,uint64_t frameNumber,const sp<Fence> & fence)1023 status_t GonkBufferQueue::releaseBuffer(int buf, uint64_t frameNumber, const sp<Fence>& fence) {
1024 ATRACE_CALL();
1025
1026 if (buf == INVALID_BUFFER_SLOT || fence == NULL) {
1027 return BAD_VALUE;
1028 }
1029
1030 Mutex::Autolock _l(mMutex);
1031
1032 // If the frame number has changed because buffer has been reallocated,
1033 // we can ignore this releaseBuffer for the old buffer.
1034 //if (frameNumber != mSlots[buf].mFrameNumber) {
1035 // return STALE_BUFFER_SLOT;
1036 //}
1037
1038
1039 // Internal state consistency checks:
1040 // Make sure this buffers hasn't been queued while we were owning it (acquired)
1041 Fifo::iterator front(mQueue.begin());
1042 Fifo::const_iterator const end(mQueue.end());
1043 while (front != end) {
1044 if (front->mBuf == buf) {
1045 LOG_ALWAYS_FATAL("[%s] received new buffer(#%lld) on slot #%d that has not yet been "
1046 "acquired", mConsumerName.string(), frameNumber, buf);
1047 break; // never reached
1048 }
1049 front++;
1050 }
1051
1052 // The buffer can now only be released if its in the acquired state
1053 if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) {
1054 mSlots[buf].mFence = fence;
1055 mSlots[buf].mBufferState = BufferSlot::FREE;
1056 } else if (mSlots[buf].mNeedsCleanupOnRelease) {
1057 ALOGV("releasing a stale buf %d its state was %d", buf, mSlots[buf].mBufferState);
1058 mSlots[buf].mNeedsCleanupOnRelease = false;
1059 return STALE_BUFFER_SLOT;
1060 } else {
1061 ALOGE("attempted to release buf %d but its state was %d", buf, mSlots[buf].mBufferState);
1062 return -EINVAL;
1063 }
1064
1065 mDequeueCondition.broadcast();
1066 return NO_ERROR;
1067 }
1068
consumerConnect(const sp<IConsumerListener> & consumerListener,bool controlledByApp)1069 status_t GonkBufferQueue::consumerConnect(const sp<IConsumerListener>& consumerListener,
1070 bool controlledByApp) {
1071 ALOGV("consumerConnect controlledByApp=%s",
1072 controlledByApp ? "true" : "false");
1073 Mutex::Autolock lock(mMutex);
1074
1075 if (mAbandoned) {
1076 ALOGE("consumerConnect: GonkBufferQueue has been abandoned!");
1077 return NO_INIT;
1078 }
1079 if (consumerListener == NULL) {
1080 ALOGE("consumerConnect: consumerListener may not be NULL");
1081 return BAD_VALUE;
1082 }
1083
1084 mConsumerListener = consumerListener;
1085 mConsumerControlledByApp = controlledByApp;
1086
1087 return NO_ERROR;
1088 }
1089
consumerDisconnect()1090 status_t GonkBufferQueue::consumerDisconnect() {
1091 ALOGV("consumerDisconnect");
1092 Mutex::Autolock lock(mMutex);
1093
1094 if (mConsumerListener == NULL) {
1095 ALOGE("consumerDisconnect: No consumer is connected!");
1096 return -EINVAL;
1097 }
1098
1099 mAbandoned = true;
1100 mConsumerListener = NULL;
1101 mQueue.clear();
1102 freeAllBuffersLocked();
1103 mDequeueCondition.broadcast();
1104 return NO_ERROR;
1105 }
1106
getReleasedBuffers(uint32_t * slotMask)1107 status_t GonkBufferQueue::getReleasedBuffers(uint32_t* slotMask) {
1108 ALOGV("getReleasedBuffers");
1109 Mutex::Autolock lock(mMutex);
1110
1111 if (mAbandoned) {
1112 ALOGE("getReleasedBuffers: GonkBufferQueue has been abandoned!");
1113 return NO_INIT;
1114 }
1115
1116 uint32_t mask = 0;
1117 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
1118 if (!mSlots[i].mAcquireCalled) {
1119 mask |= 1 << i;
1120 }
1121 }
1122
1123 // Remove buffers in flight (on the queue) from the mask where acquire has
1124 // been called, as the consumer will not receive the buffer address, so
1125 // it should not free these slots.
1126 Fifo::iterator front(mQueue.begin());
1127 while (front != mQueue.end()) {
1128 if (front->mAcquireCalled)
1129 mask &= ~(1 << front->mBuf);
1130 front++;
1131 }
1132
1133 *slotMask = mask;
1134
1135 ALOGV("getReleasedBuffers: returning mask %#x", mask);
1136 return NO_ERROR;
1137 }
1138
setDefaultBufferSize(uint32_t w,uint32_t h)1139 status_t GonkBufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h) {
1140 ALOGV("setDefaultBufferSize: w=%d, h=%d", w, h);
1141 if (!w || !h) {
1142 ALOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)",
1143 w, h);
1144 return BAD_VALUE;
1145 }
1146
1147 Mutex::Autolock lock(mMutex);
1148 mDefaultWidth = w;
1149 mDefaultHeight = h;
1150 return NO_ERROR;
1151 }
1152
setDefaultMaxBufferCount(int bufferCount)1153 status_t GonkBufferQueue::setDefaultMaxBufferCount(int bufferCount) {
1154 ATRACE_CALL();
1155 Mutex::Autolock lock(mMutex);
1156 return setDefaultMaxBufferCountLocked(bufferCount);
1157 }
1158
disableAsyncBuffer()1159 status_t GonkBufferQueue::disableAsyncBuffer() {
1160 ATRACE_CALL();
1161 Mutex::Autolock lock(mMutex);
1162 if (mConsumerListener != NULL) {
1163 ALOGE("disableAsyncBuffer: consumer already connected!");
1164 return INVALID_OPERATION;
1165 }
1166 mUseAsyncBuffer = false;
1167 return NO_ERROR;
1168 }
1169
setMaxAcquiredBufferCount(int maxAcquiredBuffers)1170 status_t GonkBufferQueue::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
1171 ATRACE_CALL();
1172 Mutex::Autolock lock(mMutex);
1173 if (maxAcquiredBuffers < 1 || maxAcquiredBuffers > MAX_MAX_ACQUIRED_BUFFERS) {
1174 ALOGE("setMaxAcquiredBufferCount: invalid count specified: %d",
1175 maxAcquiredBuffers);
1176 return BAD_VALUE;
1177 }
1178 if (mConnectedApi != NO_CONNECTED_API) {
1179 return INVALID_OPERATION;
1180 }
1181 mMaxAcquiredBufferCount = maxAcquiredBuffers;
1182 return NO_ERROR;
1183 }
1184
getMinUndequeuedBufferCount(bool async) const1185 int GonkBufferQueue::getMinUndequeuedBufferCount(bool async) const {
1186 // if dequeueBuffer is allowed to error out, we don't have to
1187 // add an extra buffer.
1188 if (!mUseAsyncBuffer)
1189 return mMaxAcquiredBufferCount;
1190
1191 // we're in async mode, or we want to prevent the app to
1192 // deadlock itself, we throw-in an extra buffer to guarantee it.
1193 if (mDequeueBufferCannotBlock || async || !mSynchronousMode)
1194 return mMaxAcquiredBufferCount + 1;
1195
1196 return mMaxAcquiredBufferCount;
1197 }
1198
getMinMaxBufferCountLocked(bool async) const1199 int GonkBufferQueue::getMinMaxBufferCountLocked(bool async) const {
1200 return getMinUndequeuedBufferCount(async) + 1;
1201 }
1202
getMaxBufferCountLocked(bool async) const1203 int GonkBufferQueue::getMaxBufferCountLocked(bool async) const {
1204 int minMaxBufferCount = getMinMaxBufferCountLocked(async);
1205
1206 int maxBufferCount = mDefaultMaxBufferCount;
1207 if (maxBufferCount < minMaxBufferCount) {
1208 maxBufferCount = minMaxBufferCount;
1209 }
1210 if (mOverrideMaxBufferCount != 0) {
1211 assert(mOverrideMaxBufferCount >= minMaxBufferCount);
1212 maxBufferCount = mOverrideMaxBufferCount;
1213 }
1214
1215 // Any buffers that are dequeued by the producer or sitting in the queue
1216 // waiting to be consumed need to have their slots preserved. Such
1217 // buffers will temporarily keep the max buffer count up until the slots
1218 // no longer need to be preserved.
1219 for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) {
1220 BufferSlot::BufferState state = mSlots[i].mBufferState;
1221 if (state == BufferSlot::QUEUED || state == BufferSlot::DEQUEUED) {
1222 maxBufferCount = i + 1;
1223 }
1224 }
1225
1226 return maxBufferCount;
1227 }
1228
stillTracking(const BufferItem * item) const1229 bool GonkBufferQueue::stillTracking(const BufferItem *item) const {
1230 const BufferSlot &slot = mSlots[item->mBuf];
1231
1232 ALOGV("stillTracking?: item: { slot=%d/%llu, buffer=%p }, "
1233 "slot: { slot=%d/%llu, buffer=%p }",
1234 item->mBuf, item->mFrameNumber,
1235 (item->mGraphicBuffer.get() ? item->mGraphicBuffer->handle : 0),
1236 item->mBuf, slot.mFrameNumber,
1237 (slot.mGraphicBuffer.get() ? slot.mGraphicBuffer->handle : 0));
1238
1239 // Compare item with its original buffer slot. We can check the slot
1240 // as the buffer would not be moved to a different slot by the producer.
1241 return (slot.mGraphicBuffer != NULL &&
1242 item->mGraphicBuffer->handle == slot.mGraphicBuffer->handle);
1243 }
1244
ProxyConsumerListener(const wp<ConsumerListener> & consumerListener)1245 GonkBufferQueue::ProxyConsumerListener::ProxyConsumerListener(
1246 const wp<ConsumerListener>& consumerListener):
1247 mConsumerListener(consumerListener) {}
1248
~ProxyConsumerListener()1249 GonkBufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {}
1250
onFrameAvailable()1251 void GonkBufferQueue::ProxyConsumerListener::onFrameAvailable() {
1252 sp<ConsumerListener> listener(mConsumerListener.promote());
1253 if (listener != NULL) {
1254 listener->onFrameAvailable();
1255 }
1256 }
1257
onBuffersReleased()1258 void GonkBufferQueue::ProxyConsumerListener::onBuffersReleased() {
1259 sp<ConsumerListener> listener(mConsumerListener.promote());
1260 if (listener != NULL) {
1261 listener->onBuffersReleased();
1262 }
1263 }
1264
1265 }; // namespace android
1266