1 /*
2 * Copyright 2014 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 #include <inttypes.h>
18
19 #define LOG_TAG "BufferQueueProducer"
20 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
21 //#define LOG_NDEBUG 0
22
23 #define EGL_EGLEXT_PROTOTYPES
24
25 #include <gui/BufferItem.h>
26 #include <gui/BufferQueueCore.h>
27 #include <gui/BufferQueueProducer.h>
28 #include <gui/IConsumerListener.h>
29 #include <gui/IGraphicBufferAlloc.h>
30 #include <gui/IProducerListener.h>
31
32 #include <utils/Log.h>
33 #include <utils/Trace.h>
34
35 namespace android {
36
BufferQueueProducer(const sp<BufferQueueCore> & core)37 BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core) :
38 mCore(core),
39 mSlots(core->mSlots),
40 mConsumerName(),
41 mStickyTransform(0) {}
42
~BufferQueueProducer()43 BufferQueueProducer::~BufferQueueProducer() {}
44
requestBuffer(int slot,sp<GraphicBuffer> * buf)45 status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
46 ATRACE_CALL();
47 BQ_LOGV("requestBuffer: slot %d", slot);
48 Mutex::Autolock lock(mCore->mMutex);
49
50 if (mCore->mIsAbandoned) {
51 BQ_LOGE("requestBuffer: BufferQueue has been abandoned");
52 return NO_INIT;
53 }
54
55 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
56 BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)",
57 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
58 return BAD_VALUE;
59 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
60 BQ_LOGE("requestBuffer: slot %d is not owned by the producer "
61 "(state = %d)", slot, mSlots[slot].mBufferState);
62 return BAD_VALUE;
63 }
64
65 mSlots[slot].mRequestBufferCalled = true;
66 *buf = mSlots[slot].mGraphicBuffer;
67 return NO_ERROR;
68 }
69
setBufferCount(int bufferCount)70 status_t BufferQueueProducer::setBufferCount(int bufferCount) {
71 ATRACE_CALL();
72 BQ_LOGV("setBufferCount: count = %d", bufferCount);
73
74 sp<IConsumerListener> listener;
75 { // Autolock scope
76 Mutex::Autolock lock(mCore->mMutex);
77 mCore->waitWhileAllocatingLocked();
78
79 if (mCore->mIsAbandoned) {
80 BQ_LOGE("setBufferCount: BufferQueue has been abandoned");
81 return NO_INIT;
82 }
83
84 if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
85 BQ_LOGE("setBufferCount: bufferCount %d too large (max %d)",
86 bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
87 return BAD_VALUE;
88 }
89
90 // There must be no dequeued buffers when changing the buffer count.
91 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
92 if (mSlots[s].mBufferState == BufferSlot::DEQUEUED) {
93 BQ_LOGE("setBufferCount: buffer owned by producer");
94 return BAD_VALUE;
95 }
96 }
97
98 if (bufferCount == 0) {
99 mCore->mOverrideMaxBufferCount = 0;
100 mCore->mDequeueCondition.broadcast();
101 return NO_ERROR;
102 }
103
104 const int minBufferSlots = mCore->getMinMaxBufferCountLocked(false);
105 if (bufferCount < minBufferSlots) {
106 BQ_LOGE("setBufferCount: requested buffer count %d is less than "
107 "minimum %d", bufferCount, minBufferSlots);
108 return BAD_VALUE;
109 }
110
111 // Here we are guaranteed that the producer doesn't have any dequeued
112 // buffers and will release all of its buffer references. We don't
113 // clear the queue, however, so that currently queued buffers still
114 // get displayed.
115 mCore->freeAllBuffersLocked();
116 mCore->mOverrideMaxBufferCount = bufferCount;
117 mCore->mDequeueCondition.broadcast();
118 listener = mCore->mConsumerListener;
119 } // Autolock scope
120
121 // Call back without lock held
122 if (listener != NULL) {
123 listener->onBuffersReleased();
124 }
125
126 return NO_ERROR;
127 }
128
waitForFreeSlotThenRelock(const char * caller,bool async,int * found,status_t * returnFlags) const129 status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller,
130 bool async, int* found, status_t* returnFlags) const {
131 bool tryAgain = true;
132 while (tryAgain) {
133 if (mCore->mIsAbandoned) {
134 BQ_LOGE("%s: BufferQueue has been abandoned", caller);
135 return NO_INIT;
136 }
137
138 const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
139 if (async && mCore->mOverrideMaxBufferCount) {
140 // FIXME: Some drivers are manually setting the buffer count
141 // (which they shouldn't), so we do this extra test here to
142 // handle that case. This is TEMPORARY until we get this fixed.
143 if (mCore->mOverrideMaxBufferCount < maxBufferCount) {
144 BQ_LOGE("%s: async mode is invalid with buffer count override",
145 caller);
146 return BAD_VALUE;
147 }
148 }
149
150 // Free up any buffers that are in slots beyond the max buffer count
151 for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
152 assert(mSlots[s].mBufferState == BufferSlot::FREE);
153 if (mSlots[s].mGraphicBuffer != NULL) {
154 mCore->freeBufferLocked(s);
155 *returnFlags |= RELEASE_ALL_BUFFERS;
156 }
157 }
158
159 // Look for a free buffer to give to the client
160 *found = BufferQueueCore::INVALID_BUFFER_SLOT;
161 int dequeuedCount = 0;
162 int acquiredCount = 0;
163 for (int s = 0; s < maxBufferCount; ++s) {
164 switch (mSlots[s].mBufferState) {
165 case BufferSlot::DEQUEUED:
166 ++dequeuedCount;
167 break;
168 case BufferSlot::ACQUIRED:
169 ++acquiredCount;
170 break;
171 case BufferSlot::FREE:
172 // We return the oldest of the free buffers to avoid
173 // stalling the producer if possible, since the consumer
174 // may still have pending reads of in-flight buffers
175 if (*found == BufferQueueCore::INVALID_BUFFER_SLOT ||
176 mSlots[s].mFrameNumber < mSlots[*found].mFrameNumber) {
177 *found = s;
178 }
179 break;
180 default:
181 break;
182 }
183 }
184
185 // Producers are not allowed to dequeue more than one buffer if they
186 // did not set a buffer count
187 if (!mCore->mOverrideMaxBufferCount && dequeuedCount) {
188 BQ_LOGE("%s: can't dequeue multiple buffers without setting the "
189 "buffer count", caller);
190 return INVALID_OPERATION;
191 }
192
193 // See whether a buffer has been queued since the last
194 // setBufferCount so we know whether to perform the min undequeued
195 // buffers check below
196 if (mCore->mBufferHasBeenQueued) {
197 // Make sure the producer is not trying to dequeue more buffers
198 // than allowed
199 const int newUndequeuedCount =
200 maxBufferCount - (dequeuedCount + 1);
201 const int minUndequeuedCount =
202 mCore->getMinUndequeuedBufferCountLocked(async);
203 if (newUndequeuedCount < minUndequeuedCount) {
204 BQ_LOGE("%s: min undequeued buffer count (%d) exceeded "
205 "(dequeued=%d undequeued=%d)",
206 caller, minUndequeuedCount,
207 dequeuedCount, newUndequeuedCount);
208 return INVALID_OPERATION;
209 }
210 }
211
212 // If we disconnect and reconnect quickly, we can be in a state where
213 // our slots are empty but we have many buffers in the queue. This can
214 // cause us to run out of memory if we outrun the consumer. Wait here if
215 // it looks like we have too many buffers queued up.
216 bool tooManyBuffers = mCore->mQueue.size()
217 > static_cast<size_t>(maxBufferCount);
218 if (tooManyBuffers) {
219 BQ_LOGV("%s: queue size is %zu, waiting", caller,
220 mCore->mQueue.size());
221 }
222
223 // If no buffer is found, or if the queue has too many buffers
224 // outstanding, wait for a buffer to be acquired or released, or for the
225 // max buffer count to change.
226 tryAgain = (*found == BufferQueueCore::INVALID_BUFFER_SLOT) ||
227 tooManyBuffers;
228 if (tryAgain) {
229 // Return an error if we're in non-blocking mode (producer and
230 // consumer are controlled by the application).
231 // However, the consumer is allowed to briefly acquire an extra
232 // buffer (which could cause us to have to wait here), which is
233 // okay, since it is only used to implement an atomic acquire +
234 // release (e.g., in GLConsumer::updateTexImage())
235 if (mCore->mDequeueBufferCannotBlock &&
236 (acquiredCount <= mCore->mMaxAcquiredBufferCount)) {
237 return WOULD_BLOCK;
238 }
239 mCore->mDequeueCondition.wait(mCore->mMutex);
240 }
241 } // while (tryAgain)
242
243 return NO_ERROR;
244 }
245
dequeueBuffer(int * outSlot,sp<android::Fence> * outFence,bool async,uint32_t width,uint32_t height,uint32_t format,uint32_t usage)246 status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
247 sp<android::Fence> *outFence, bool async,
248 uint32_t width, uint32_t height, uint32_t format, uint32_t usage) {
249 ATRACE_CALL();
250 { // Autolock scope
251 Mutex::Autolock lock(mCore->mMutex);
252 mConsumerName = mCore->mConsumerName;
253 } // Autolock scope
254
255 BQ_LOGV("dequeueBuffer: async=%s w=%u h=%u format=%#x, usage=%#x",
256 async ? "true" : "false", width, height, format, usage);
257
258 if ((width && !height) || (!width && height)) {
259 BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height);
260 return BAD_VALUE;
261 }
262
263 status_t returnFlags = NO_ERROR;
264 EGLDisplay eglDisplay = EGL_NO_DISPLAY;
265 EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;
266 bool attachedByConsumer = false;
267
268 { // Autolock scope
269 Mutex::Autolock lock(mCore->mMutex);
270 mCore->waitWhileAllocatingLocked();
271
272 if (format == 0) {
273 format = mCore->mDefaultBufferFormat;
274 }
275
276 // Enable the usage bits the consumer requested
277 usage |= mCore->mConsumerUsageBits;
278
279 int found;
280 status_t status = waitForFreeSlotThenRelock("dequeueBuffer", async,
281 &found, &returnFlags);
282 if (status != NO_ERROR) {
283 return status;
284 }
285
286 // This should not happen
287 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
288 BQ_LOGE("dequeueBuffer: no available buffer slots");
289 return -EBUSY;
290 }
291
292 *outSlot = found;
293 ATRACE_BUFFER_INDEX(found);
294
295 attachedByConsumer = mSlots[found].mAttachedByConsumer;
296
297 const bool useDefaultSize = !width && !height;
298 if (useDefaultSize) {
299 width = mCore->mDefaultWidth;
300 height = mCore->mDefaultHeight;
301 }
302
303 mSlots[found].mBufferState = BufferSlot::DEQUEUED;
304
305 const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
306 if ((buffer == NULL) ||
307 (static_cast<uint32_t>(buffer->width) != width) ||
308 (static_cast<uint32_t>(buffer->height) != height) ||
309 (static_cast<uint32_t>(buffer->format) != format) ||
310 ((static_cast<uint32_t>(buffer->usage) & usage) != usage))
311 {
312 mSlots[found].mAcquireCalled = false;
313 mSlots[found].mGraphicBuffer = NULL;
314 mSlots[found].mRequestBufferCalled = false;
315 mSlots[found].mEglDisplay = EGL_NO_DISPLAY;
316 mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
317 mSlots[found].mFence = Fence::NO_FENCE;
318
319 returnFlags |= BUFFER_NEEDS_REALLOCATION;
320 }
321
322 if (CC_UNLIKELY(mSlots[found].mFence == NULL)) {
323 BQ_LOGE("dequeueBuffer: about to return a NULL fence - "
324 "slot=%d w=%d h=%d format=%u",
325 found, buffer->width, buffer->height, buffer->format);
326 }
327
328 eglDisplay = mSlots[found].mEglDisplay;
329 eglFence = mSlots[found].mEglFence;
330 *outFence = mSlots[found].mFence;
331 mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
332 mSlots[found].mFence = Fence::NO_FENCE;
333 } // Autolock scope
334
335 if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
336 status_t error;
337 BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
338 sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
339 width, height, format, usage, &error));
340 if (graphicBuffer == NULL) {
341 BQ_LOGE("dequeueBuffer: createGraphicBuffer failed");
342 return error;
343 }
344
345 { // Autolock scope
346 Mutex::Autolock lock(mCore->mMutex);
347
348 if (mCore->mIsAbandoned) {
349 BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
350 return NO_INIT;
351 }
352
353 mSlots[*outSlot].mFrameNumber = UINT32_MAX;
354 mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
355 } // Autolock scope
356 }
357
358 if (attachedByConsumer) {
359 returnFlags |= BUFFER_NEEDS_REALLOCATION;
360 }
361
362 if (eglFence != EGL_NO_SYNC_KHR) {
363 EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, 0,
364 1000000000);
365 // If something goes wrong, log the error, but return the buffer without
366 // synchronizing access to it. It's too late at this point to abort the
367 // dequeue operation.
368 if (result == EGL_FALSE) {
369 BQ_LOGE("dequeueBuffer: error %#x waiting for fence",
370 eglGetError());
371 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
372 BQ_LOGE("dequeueBuffer: timeout waiting for fence");
373 }
374 eglDestroySyncKHR(eglDisplay, eglFence);
375 }
376
377 BQ_LOGV("dequeueBuffer: returning slot=%d/%" PRIu64 " buf=%p flags=%#x",
378 *outSlot,
379 mSlots[*outSlot].mFrameNumber,
380 mSlots[*outSlot].mGraphicBuffer->handle, returnFlags);
381
382 return returnFlags;
383 }
384
detachBuffer(int slot)385 status_t BufferQueueProducer::detachBuffer(int slot) {
386 ATRACE_CALL();
387 ATRACE_BUFFER_INDEX(slot);
388 BQ_LOGV("detachBuffer(P): slot %d", slot);
389 Mutex::Autolock lock(mCore->mMutex);
390
391 if (mCore->mIsAbandoned) {
392 BQ_LOGE("detachBuffer(P): BufferQueue has been abandoned");
393 return NO_INIT;
394 }
395
396 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
397 BQ_LOGE("detachBuffer(P): slot index %d out of range [0, %d)",
398 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
399 return BAD_VALUE;
400 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
401 BQ_LOGE("detachBuffer(P): slot %d is not owned by the producer "
402 "(state = %d)", slot, mSlots[slot].mBufferState);
403 return BAD_VALUE;
404 } else if (!mSlots[slot].mRequestBufferCalled) {
405 BQ_LOGE("detachBuffer(P): buffer in slot %d has not been requested",
406 slot);
407 return BAD_VALUE;
408 }
409
410 mCore->freeBufferLocked(slot);
411 mCore->mDequeueCondition.broadcast();
412
413 return NO_ERROR;
414 }
415
detachNextBuffer(sp<GraphicBuffer> * outBuffer,sp<Fence> * outFence)416 status_t BufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
417 sp<Fence>* outFence) {
418 ATRACE_CALL();
419
420 if (outBuffer == NULL) {
421 BQ_LOGE("detachNextBuffer: outBuffer must not be NULL");
422 return BAD_VALUE;
423 } else if (outFence == NULL) {
424 BQ_LOGE("detachNextBuffer: outFence must not be NULL");
425 return BAD_VALUE;
426 }
427
428 Mutex::Autolock lock(mCore->mMutex);
429 mCore->waitWhileAllocatingLocked();
430
431 if (mCore->mIsAbandoned) {
432 BQ_LOGE("detachNextBuffer: BufferQueue has been abandoned");
433 return NO_INIT;
434 }
435
436 // Find the oldest valid slot
437 int found = BufferQueueCore::INVALID_BUFFER_SLOT;
438 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
439 if (mSlots[s].mBufferState == BufferSlot::FREE &&
440 mSlots[s].mGraphicBuffer != NULL) {
441 if (found == BufferQueueCore::INVALID_BUFFER_SLOT ||
442 mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) {
443 found = s;
444 }
445 }
446 }
447
448 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
449 return NO_MEMORY;
450 }
451
452 BQ_LOGV("detachNextBuffer detached slot %d", found);
453
454 *outBuffer = mSlots[found].mGraphicBuffer;
455 *outFence = mSlots[found].mFence;
456 mCore->freeBufferLocked(found);
457
458 return NO_ERROR;
459 }
460
attachBuffer(int * outSlot,const sp<android::GraphicBuffer> & buffer)461 status_t BufferQueueProducer::attachBuffer(int* outSlot,
462 const sp<android::GraphicBuffer>& buffer) {
463 ATRACE_CALL();
464
465 if (outSlot == NULL) {
466 BQ_LOGE("attachBuffer(P): outSlot must not be NULL");
467 return BAD_VALUE;
468 } else if (buffer == NULL) {
469 BQ_LOGE("attachBuffer(P): cannot attach NULL buffer");
470 return BAD_VALUE;
471 }
472
473 Mutex::Autolock lock(mCore->mMutex);
474 mCore->waitWhileAllocatingLocked();
475
476 status_t returnFlags = NO_ERROR;
477 int found;
478 // TODO: Should we provide an async flag to attachBuffer? It seems
479 // unlikely that buffers which we are attaching to a BufferQueue will
480 // be asynchronous (droppable), but it may not be impossible.
481 status_t status = waitForFreeSlotThenRelock("attachBuffer(P)", false,
482 &found, &returnFlags);
483 if (status != NO_ERROR) {
484 return status;
485 }
486
487 // This should not happen
488 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
489 BQ_LOGE("attachBuffer(P): no available buffer slots");
490 return -EBUSY;
491 }
492
493 *outSlot = found;
494 ATRACE_BUFFER_INDEX(*outSlot);
495 BQ_LOGV("attachBuffer(P): returning slot %d flags=%#x",
496 *outSlot, returnFlags);
497
498 mSlots[*outSlot].mGraphicBuffer = buffer;
499 mSlots[*outSlot].mBufferState = BufferSlot::DEQUEUED;
500 mSlots[*outSlot].mEglFence = EGL_NO_SYNC_KHR;
501 mSlots[*outSlot].mFence = Fence::NO_FENCE;
502 mSlots[*outSlot].mRequestBufferCalled = true;
503
504 return returnFlags;
505 }
506
queueBuffer(int slot,const QueueBufferInput & input,QueueBufferOutput * output)507 status_t BufferQueueProducer::queueBuffer(int slot,
508 const QueueBufferInput &input, QueueBufferOutput *output) {
509 ATRACE_CALL();
510 ATRACE_BUFFER_INDEX(slot);
511
512 int64_t timestamp;
513 bool isAutoTimestamp;
514 Rect crop;
515 int scalingMode;
516 uint32_t transform;
517 uint32_t stickyTransform;
518 bool async;
519 sp<Fence> fence;
520 input.deflate(×tamp, &isAutoTimestamp, &crop, &scalingMode, &transform,
521 &async, &fence, &stickyTransform);
522
523 if (fence == NULL) {
524 BQ_LOGE("queueBuffer: fence is NULL");
525 // Temporary workaround for b/17946343: soldier-on instead of returning an error. This
526 // prevents the client from dying, at the risk of visible corruption due to hwcomposer
527 // reading the buffer before the producer is done rendering it. Unless the buffer is the
528 // last frame of an animation, the corruption will be transient.
529 fence = Fence::NO_FENCE;
530 // return BAD_VALUE;
531 }
532
533 switch (scalingMode) {
534 case NATIVE_WINDOW_SCALING_MODE_FREEZE:
535 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
536 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
537 case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
538 break;
539 default:
540 BQ_LOGE("queueBuffer: unknown scaling mode %d", scalingMode);
541 return BAD_VALUE;
542 }
543
544 sp<IConsumerListener> listener;
545 { // Autolock scope
546 Mutex::Autolock lock(mCore->mMutex);
547
548 if (mCore->mIsAbandoned) {
549 BQ_LOGE("queueBuffer: BufferQueue has been abandoned");
550 return NO_INIT;
551 }
552
553 const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
554 if (async && mCore->mOverrideMaxBufferCount) {
555 // FIXME: Some drivers are manually setting the buffer count
556 // (which they shouldn't), so we do this extra test here to
557 // handle that case. This is TEMPORARY until we get this fixed.
558 if (mCore->mOverrideMaxBufferCount < maxBufferCount) {
559 BQ_LOGE("queueBuffer: async mode is invalid with "
560 "buffer count override");
561 return BAD_VALUE;
562 }
563 }
564
565 if (slot < 0 || slot >= maxBufferCount) {
566 BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)",
567 slot, maxBufferCount);
568 return BAD_VALUE;
569 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
570 BQ_LOGE("queueBuffer: slot %d is not owned by the producer "
571 "(state = %d)", slot, mSlots[slot].mBufferState);
572 return BAD_VALUE;
573 } else if (!mSlots[slot].mRequestBufferCalled) {
574 BQ_LOGE("queueBuffer: slot %d was queued without requesting "
575 "a buffer", slot);
576 return BAD_VALUE;
577 }
578
579 BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64
580 " crop=[%d,%d,%d,%d] transform=%#x scale=%s",
581 slot, mCore->mFrameCounter + 1, timestamp,
582 crop.left, crop.top, crop.right, crop.bottom,
583 transform, BufferItem::scalingModeName(scalingMode));
584
585 const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
586 Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
587 Rect croppedRect;
588 crop.intersect(bufferRect, &croppedRect);
589 if (croppedRect != crop) {
590 BQ_LOGE("queueBuffer: crop rect is not contained within the "
591 "buffer in slot %d", slot);
592 return BAD_VALUE;
593 }
594
595 mSlots[slot].mFence = fence;
596 mSlots[slot].mBufferState = BufferSlot::QUEUED;
597 ++mCore->mFrameCounter;
598 mSlots[slot].mFrameNumber = mCore->mFrameCounter;
599
600 BufferItem item;
601 item.mAcquireCalled = mSlots[slot].mAcquireCalled;
602 item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
603 item.mCrop = crop;
604 item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
605 item.mTransformToDisplayInverse =
606 bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
607 item.mScalingMode = scalingMode;
608 item.mTimestamp = timestamp;
609 item.mIsAutoTimestamp = isAutoTimestamp;
610 item.mFrameNumber = mCore->mFrameCounter;
611 item.mSlot = slot;
612 item.mFence = fence;
613 item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async;
614
615 mStickyTransform = stickyTransform;
616
617 if (mCore->mQueue.empty()) {
618 // When the queue is empty, we can ignore mDequeueBufferCannotBlock
619 // and simply queue this buffer
620 mCore->mQueue.push_back(item);
621 listener = mCore->mConsumerListener;
622 } else {
623 // When the queue is not empty, we need to look at the front buffer
624 // state to see if we need to replace it
625 BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
626 if (front->mIsDroppable) {
627 // If the front queued buffer is still being tracked, we first
628 // mark it as freed
629 if (mCore->stillTracking(front)) {
630 mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
631 // Reset the frame number of the freed buffer so that it is
632 // the first in line to be dequeued again
633 mSlots[front->mSlot].mFrameNumber = 0;
634 }
635 // Overwrite the droppable buffer with the incoming one
636 *front = item;
637 } else {
638 mCore->mQueue.push_back(item);
639 listener = mCore->mConsumerListener;
640 }
641 }
642
643 mCore->mBufferHasBeenQueued = true;
644 mCore->mDequeueCondition.broadcast();
645
646 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
647 mCore->mTransformHint, mCore->mQueue.size());
648
649 ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
650 } // Autolock scope
651
652 // Call back without lock held
653 if (listener != NULL) {
654 listener->onFrameAvailable();
655 }
656
657 return NO_ERROR;
658 }
659
cancelBuffer(int slot,const sp<Fence> & fence)660 void BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
661 ATRACE_CALL();
662 BQ_LOGV("cancelBuffer: slot %d", slot);
663 Mutex::Autolock lock(mCore->mMutex);
664
665 if (mCore->mIsAbandoned) {
666 BQ_LOGE("cancelBuffer: BufferQueue has been abandoned");
667 return;
668 }
669
670 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
671 BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)",
672 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
673 return;
674 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
675 BQ_LOGE("cancelBuffer: slot %d is not owned by the producer "
676 "(state = %d)", slot, mSlots[slot].mBufferState);
677 return;
678 } else if (fence == NULL) {
679 BQ_LOGE("cancelBuffer: fence is NULL");
680 return;
681 }
682
683 mSlots[slot].mBufferState = BufferSlot::FREE;
684 mSlots[slot].mFrameNumber = 0;
685 mSlots[slot].mFence = fence;
686 mCore->mDequeueCondition.broadcast();
687 }
688
query(int what,int * outValue)689 int BufferQueueProducer::query(int what, int *outValue) {
690 ATRACE_CALL();
691 Mutex::Autolock lock(mCore->mMutex);
692
693 if (outValue == NULL) {
694 BQ_LOGE("query: outValue was NULL");
695 return BAD_VALUE;
696 }
697
698 if (mCore->mIsAbandoned) {
699 BQ_LOGE("query: BufferQueue has been abandoned");
700 return NO_INIT;
701 }
702
703 int value;
704 switch (what) {
705 case NATIVE_WINDOW_WIDTH:
706 value = mCore->mDefaultWidth;
707 break;
708 case NATIVE_WINDOW_HEIGHT:
709 value = mCore->mDefaultHeight;
710 break;
711 case NATIVE_WINDOW_FORMAT:
712 value = mCore->mDefaultBufferFormat;
713 break;
714 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
715 value = mCore->getMinUndequeuedBufferCountLocked(false);
716 break;
717 case NATIVE_WINDOW_STICKY_TRANSFORM:
718 value = static_cast<int>(mStickyTransform);
719 break;
720 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
721 value = (mCore->mQueue.size() > 1);
722 break;
723 case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
724 value = mCore->mConsumerUsageBits;
725 break;
726 default:
727 return BAD_VALUE;
728 }
729
730 BQ_LOGV("query: %d? %d", what, value);
731 *outValue = value;
732 return NO_ERROR;
733 }
734
connect(const sp<IProducerListener> & listener,int api,bool producerControlledByApp,QueueBufferOutput * output)735 status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
736 int api, bool producerControlledByApp, QueueBufferOutput *output) {
737 ATRACE_CALL();
738 Mutex::Autolock lock(mCore->mMutex);
739 mConsumerName = mCore->mConsumerName;
740 BQ_LOGV("connect(P): api=%d producerControlledByApp=%s", api,
741 producerControlledByApp ? "true" : "false");
742
743 if (mCore->mIsAbandoned) {
744 BQ_LOGE("connect(P): BufferQueue has been abandoned");
745 return NO_INIT;
746 }
747
748 if (mCore->mConsumerListener == NULL) {
749 BQ_LOGE("connect(P): BufferQueue has no consumer");
750 return NO_INIT;
751 }
752
753 if (output == NULL) {
754 BQ_LOGE("connect(P): output was NULL");
755 return BAD_VALUE;
756 }
757
758 if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
759 BQ_LOGE("connect(P): already connected (cur=%d req=%d)",
760 mCore->mConnectedApi, api);
761 return BAD_VALUE;
762 }
763
764 int status = NO_ERROR;
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 mCore->mConnectedApi = api;
771 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
772 mCore->mTransformHint, mCore->mQueue.size());
773
774 // Set up a death notification so that we can disconnect
775 // automatically if the remote producer dies
776 if (listener != NULL &&
777 listener->asBinder()->remoteBinder() != NULL) {
778 status = listener->asBinder()->linkToDeath(
779 static_cast<IBinder::DeathRecipient*>(this));
780 if (status != NO_ERROR) {
781 BQ_LOGE("connect(P): linkToDeath failed: %s (%d)",
782 strerror(-status), status);
783 }
784 }
785 mCore->mConnectedProducerListener = listener;
786 break;
787 default:
788 BQ_LOGE("connect(P): unknown API %d", api);
789 status = BAD_VALUE;
790 break;
791 }
792
793 mCore->mBufferHasBeenQueued = false;
794 mCore->mDequeueBufferCannotBlock =
795 mCore->mConsumerControlledByApp && producerControlledByApp;
796
797 return status;
798 }
799
disconnect(int api)800 status_t BufferQueueProducer::disconnect(int api) {
801 ATRACE_CALL();
802 BQ_LOGV("disconnect(P): api %d", api);
803
804 int status = NO_ERROR;
805 sp<IConsumerListener> listener;
806 { // Autolock scope
807 Mutex::Autolock lock(mCore->mMutex);
808 mCore->waitWhileAllocatingLocked();
809
810 if (mCore->mIsAbandoned) {
811 // It's not really an error to disconnect after the surface has
812 // been abandoned; it should just be a no-op.
813 return NO_ERROR;
814 }
815
816 switch (api) {
817 case NATIVE_WINDOW_API_EGL:
818 case NATIVE_WINDOW_API_CPU:
819 case NATIVE_WINDOW_API_MEDIA:
820 case NATIVE_WINDOW_API_CAMERA:
821 if (mCore->mConnectedApi == api) {
822 mCore->freeAllBuffersLocked();
823
824 // Remove our death notification callback if we have one
825 if (mCore->mConnectedProducerListener != NULL) {
826 sp<IBinder> token =
827 mCore->mConnectedProducerListener->asBinder();
828 // This can fail if we're here because of the death
829 // notification, but we just ignore it
830 token->unlinkToDeath(
831 static_cast<IBinder::DeathRecipient*>(this));
832 }
833 mCore->mConnectedProducerListener = NULL;
834 mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
835 mCore->mSidebandStream.clear();
836 mCore->mDequeueCondition.broadcast();
837 listener = mCore->mConsumerListener;
838 } else {
839 BQ_LOGE("disconnect(P): connected to another API "
840 "(cur=%d req=%d)", mCore->mConnectedApi, api);
841 status = BAD_VALUE;
842 }
843 break;
844 default:
845 BQ_LOGE("disconnect(P): unknown API %d", api);
846 status = BAD_VALUE;
847 break;
848 }
849 } // Autolock scope
850
851 // Call back without lock held
852 if (listener != NULL) {
853 listener->onBuffersReleased();
854 }
855
856 return status;
857 }
858
setSidebandStream(const sp<NativeHandle> & stream)859 status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) {
860 sp<IConsumerListener> listener;
861 { // Autolock scope
862 Mutex::Autolock _l(mCore->mMutex);
863 mCore->mSidebandStream = stream;
864 listener = mCore->mConsumerListener;
865 } // Autolock scope
866
867 if (listener != NULL) {
868 listener->onSidebandStreamChanged();
869 }
870 return NO_ERROR;
871 }
872
allocateBuffers(bool async,uint32_t width,uint32_t height,uint32_t format,uint32_t usage)873 void BufferQueueProducer::allocateBuffers(bool async, uint32_t width,
874 uint32_t height, uint32_t format, uint32_t usage) {
875 ATRACE_CALL();
876 while (true) {
877 Vector<int> freeSlots;
878 size_t newBufferCount = 0;
879 uint32_t allocWidth = 0;
880 uint32_t allocHeight = 0;
881 uint32_t allocFormat = 0;
882 uint32_t allocUsage = 0;
883 { // Autolock scope
884 Mutex::Autolock lock(mCore->mMutex);
885 mCore->waitWhileAllocatingLocked();
886
887 int currentBufferCount = 0;
888 for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
889 if (mSlots[slot].mGraphicBuffer != NULL) {
890 ++currentBufferCount;
891 } else {
892 if (mSlots[slot].mBufferState != BufferSlot::FREE) {
893 BQ_LOGE("allocateBuffers: slot %d without buffer is not FREE",
894 slot);
895 continue;
896 }
897
898 freeSlots.push_back(slot);
899 }
900 }
901
902 int maxBufferCount = mCore->getMaxBufferCountLocked(async);
903 BQ_LOGV("allocateBuffers: allocating from %d buffers up to %d buffers",
904 currentBufferCount, maxBufferCount);
905 if (maxBufferCount <= currentBufferCount)
906 return;
907 newBufferCount = maxBufferCount - currentBufferCount;
908 if (freeSlots.size() < newBufferCount) {
909 BQ_LOGE("allocateBuffers: ran out of free slots");
910 return;
911 }
912 allocWidth = width > 0 ? width : mCore->mDefaultWidth;
913 allocHeight = height > 0 ? height : mCore->mDefaultHeight;
914 allocFormat = format != 0 ? format : mCore->mDefaultBufferFormat;
915 allocUsage = usage | mCore->mConsumerUsageBits;
916
917 mCore->mIsAllocating = true;
918 } // Autolock scope
919
920 Vector<sp<GraphicBuffer> > buffers;
921 for (size_t i = 0; i < newBufferCount; ++i) {
922 status_t result = NO_ERROR;
923 sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
924 allocWidth, allocHeight, allocFormat, allocUsage, &result));
925 if (result != NO_ERROR) {
926 BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format"
927 " %u, usage %u)", width, height, format, usage);
928 Mutex::Autolock lock(mCore->mMutex);
929 mCore->mIsAllocating = false;
930 mCore->mIsAllocatingCondition.broadcast();
931 return;
932 }
933 buffers.push_back(graphicBuffer);
934 }
935
936 { // Autolock scope
937 Mutex::Autolock lock(mCore->mMutex);
938 uint32_t checkWidth = width > 0 ? width : mCore->mDefaultWidth;
939 uint32_t checkHeight = height > 0 ? height : mCore->mDefaultHeight;
940 uint32_t checkFormat = format != 0 ? format : mCore->mDefaultBufferFormat;
941 uint32_t checkUsage = usage | mCore->mConsumerUsageBits;
942 if (checkWidth != allocWidth || checkHeight != allocHeight ||
943 checkFormat != allocFormat || checkUsage != allocUsage) {
944 // Something changed while we released the lock. Retry.
945 BQ_LOGV("allocateBuffers: size/format/usage changed while allocating. Retrying.");
946 mCore->mIsAllocating = false;
947 mCore->mIsAllocatingCondition.broadcast();
948 continue;
949 }
950
951 for (size_t i = 0; i < newBufferCount; ++i) {
952 int slot = freeSlots[i];
953 if (mSlots[slot].mBufferState != BufferSlot::FREE) {
954 // A consumer allocated the FREE slot with attachBuffer. Discard the buffer we
955 // allocated.
956 BQ_LOGV("allocateBuffers: slot %d was acquired while allocating. "
957 "Dropping allocated buffer.", slot);
958 continue;
959 }
960 mCore->freeBufferLocked(slot); // Clean up the slot first
961 mSlots[slot].mGraphicBuffer = buffers[i];
962 mSlots[slot].mFrameNumber = 0;
963 mSlots[slot].mFence = Fence::NO_FENCE;
964 BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d", slot);
965 }
966
967 mCore->mIsAllocating = false;
968 mCore->mIsAllocatingCondition.broadcast();
969 } // Autolock scope
970 }
971 }
972
binderDied(const wp<android::IBinder> &)973 void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
974 // If we're here, it means that a producer we were connected to died.
975 // We're guaranteed that we are still connected to it because we remove
976 // this callback upon disconnect. It's therefore safe to read mConnectedApi
977 // without synchronization here.
978 int api = mCore->mConnectedApi;
979 disconnect(api);
980 }
981
982 } // namespace android
983