widget/gonk/nativewindow/GonkBufferQueueKK.cpp

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

mercurial