blob: 58e19f0754357d96031be1272b40389c0c02da37 [file] [log] [blame]
Dan Stoza289ade12014-02-28 11:17:17 -08001/*
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
Dan Stoza3e96f192014-03-03 10:16:19 -080017#define LOG_TAG "BufferQueueProducer"
18#define ATRACE_TAG ATRACE_TAG_GRAPHICS
19//#define LOG_NDEBUG 0
20
Dan Stoza289ade12014-02-28 11:17:17 -080021#define EGL_EGLEXT_PROTOTYPES
22
23#include <gui/BufferItem.h>
24#include <gui/BufferQueueCore.h>
25#include <gui/BufferQueueProducer.h>
26#include <gui/IConsumerListener.h>
27#include <gui/IGraphicBufferAlloc.h>
28
29#include <utils/Log.h>
30#include <utils/Trace.h>
31
32namespace android {
33
34BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core) :
35 mCore(core),
36 mSlots(core->mSlots),
37 mConsumerName() {}
38
39BufferQueueProducer::~BufferQueueProducer() {}
40
41status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
42 ATRACE_CALL();
43 BQ_LOGV("requestBuffer: slot %d", slot);
44 Mutex::Autolock lock(mCore->mMutex);
45
46 if (mCore->mIsAbandoned) {
47 BQ_LOGE("requestBuffer: BufferQueue has been abandoned");
48 return NO_INIT;
49 }
50
Dan Stoza3e96f192014-03-03 10:16:19 -080051 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
Dan Stoza289ade12014-02-28 11:17:17 -080052 BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)",
Dan Stoza3e96f192014-03-03 10:16:19 -080053 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
Dan Stoza289ade12014-02-28 11:17:17 -080054 return BAD_VALUE;
55 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
56 BQ_LOGE("requestBuffer: slot %d is not owned by the producer "
57 "(state = %d)", slot, mSlots[slot].mBufferState);
58 return BAD_VALUE;
59 }
60
61 mSlots[slot].mRequestBufferCalled = true;
62 *buf = mSlots[slot].mGraphicBuffer;
63 return NO_ERROR;
64}
65
66status_t BufferQueueProducer::setBufferCount(int bufferCount) {
67 ATRACE_CALL();
68 BQ_LOGV("setBufferCount: count = %d", bufferCount);
69
70 sp<IConsumerListener> listener;
71 { // Autolock scope
72 Mutex::Autolock lock(mCore->mMutex);
73
74 if (mCore->mIsAbandoned) {
75 BQ_LOGE("setBufferCount: BufferQueue has been abandoned");
76 return NO_INIT;
77 }
78
Dan Stoza3e96f192014-03-03 10:16:19 -080079 if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
Dan Stoza289ade12014-02-28 11:17:17 -080080 BQ_LOGE("setBufferCount: bufferCount %d too large (max %d)",
Dan Stoza3e96f192014-03-03 10:16:19 -080081 bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
Dan Stoza289ade12014-02-28 11:17:17 -080082 return BAD_VALUE;
83 }
84
85 // There must be no dequeued buffers when changing the buffer count.
Dan Stoza3e96f192014-03-03 10:16:19 -080086 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
Dan Stoza289ade12014-02-28 11:17:17 -080087 if (mSlots[s].mBufferState == BufferSlot::DEQUEUED) {
88 BQ_LOGE("setBufferCount: buffer owned by producer");
Dan Stoza9f3053d2014-03-06 15:14:33 -080089 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -080090 }
91 }
92
93 if (bufferCount == 0) {
94 mCore->mOverrideMaxBufferCount = 0;
95 mCore->mDequeueCondition.broadcast();
96 return NO_ERROR;
97 }
98
99 const int minBufferSlots = mCore->getMinMaxBufferCountLocked(false);
100 if (bufferCount < minBufferSlots) {
101 BQ_LOGE("setBufferCount: requested buffer count %d is less than "
102 "minimum %d", bufferCount, minBufferSlots);
103 return BAD_VALUE;
104 }
105
106 // Here we are guaranteed that the producer doesn't have any dequeued
107 // buffers and will release all of its buffer references. We don't
108 // clear the queue, however, so that currently queued buffers still
109 // get displayed.
110 mCore->freeAllBuffersLocked();
111 mCore->mOverrideMaxBufferCount = bufferCount;
112 mCore->mDequeueCondition.broadcast();
113 listener = mCore->mConsumerListener;
114 } // Autolock scope
115
116 // Call back without lock held
117 if (listener != NULL) {
118 listener->onBuffersReleased();
119 }
120
121 return NO_ERROR;
122}
123
Dan Stoza9f3053d2014-03-06 15:14:33 -0800124status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller,
125 bool async, int* found, status_t* returnFlags) const {
126 bool tryAgain = true;
127 while (tryAgain) {
128 if (mCore->mIsAbandoned) {
129 BQ_LOGE("%s: BufferQueue has been abandoned", caller);
130 return NO_INIT;
131 }
132
133 const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
134 if (async && mCore->mOverrideMaxBufferCount) {
135 // FIXME: Some drivers are manually setting the buffer count
136 // (which they shouldn't), so we do this extra test here to
137 // handle that case. This is TEMPORARY until we get this fixed.
138 if (mCore->mOverrideMaxBufferCount < maxBufferCount) {
139 BQ_LOGE("%s: async mode is invalid with buffer count override",
140 caller);
141 return BAD_VALUE;
142 }
143 }
144
145 // Free up any buffers that are in slots beyond the max buffer count
146 for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
147 assert(mSlots[s].mBufferState == BufferSlot::FREE);
148 if (mSlots[s].mGraphicBuffer != NULL) {
149 mCore->freeBufferLocked(s);
150 *returnFlags |= RELEASE_ALL_BUFFERS;
151 }
152 }
153
154 // Look for a free buffer to give to the client
155 *found = BufferQueueCore::INVALID_BUFFER_SLOT;
156 int dequeuedCount = 0;
157 int acquiredCount = 0;
158 for (int s = 0; s < maxBufferCount; ++s) {
159 switch (mSlots[s].mBufferState) {
160 case BufferSlot::DEQUEUED:
161 ++dequeuedCount;
162 break;
163 case BufferSlot::ACQUIRED:
164 ++acquiredCount;
165 break;
166 case BufferSlot::FREE:
167 // We return the oldest of the free buffers to avoid
168 // stalling the producer if possible, since the consumer
169 // may still have pending reads of in-flight buffers
170 if (*found == BufferQueueCore::INVALID_BUFFER_SLOT ||
171 mSlots[s].mFrameNumber < mSlots[*found].mFrameNumber) {
172 *found = s;
173 }
174 break;
175 default:
176 break;
177 }
178 }
179
180 // Producers are not allowed to dequeue more than one buffer if they
181 // did not set a buffer count
182 if (!mCore->mOverrideMaxBufferCount && dequeuedCount) {
183 BQ_LOGE("%s: can't dequeue multiple buffers without setting the "
184 "buffer count", caller);
185 return INVALID_OPERATION;
186 }
187
188 // See whether a buffer has been queued since the last
189 // setBufferCount so we know whether to perform the min undequeued
190 // buffers check below
191 if (mCore->mBufferHasBeenQueued) {
192 // Make sure the producer is not trying to dequeue more buffers
193 // than allowed
194 const int newUndequeuedCount =
195 maxBufferCount - (dequeuedCount + 1);
196 const int minUndequeuedCount =
197 mCore->getMinUndequeuedBufferCountLocked(async);
198 if (newUndequeuedCount < minUndequeuedCount) {
199 BQ_LOGE("%s: min undequeued buffer count (%d) exceeded "
200 "(dequeued=%d undequeued=%d)",
201 caller, minUndequeuedCount,
202 dequeuedCount, newUndequeuedCount);
203 return INVALID_OPERATION;
204 }
205 }
206
207 // If no buffer is found, wait for a buffer to be released or for
208 // the max buffer count to change
209 tryAgain = (*found == BufferQueueCore::INVALID_BUFFER_SLOT);
210 if (tryAgain) {
211 // Return an error if we're in non-blocking mode (producer and
212 // consumer are controlled by the application).
213 // However, the consumer is allowed to briefly acquire an extra
214 // buffer (which could cause us to have to wait here), which is
215 // okay, since it is only used to implement an atomic acquire +
216 // release (e.g., in GLConsumer::updateTexImage())
217 if (mCore->mDequeueBufferCannotBlock &&
218 (acquiredCount <= mCore->mMaxAcquiredBufferCount)) {
219 return WOULD_BLOCK;
220 }
221 mCore->mDequeueCondition.wait(mCore->mMutex);
222 }
223 } // while (tryAgain)
224
225 return NO_ERROR;
226}
227
Dan Stoza289ade12014-02-28 11:17:17 -0800228status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
229 sp<android::Fence> *outFence, bool async,
230 uint32_t width, uint32_t height, uint32_t format, uint32_t usage) {
231 ATRACE_CALL();
232 { // Autolock scope
233 Mutex::Autolock lock(mCore->mMutex);
234 mConsumerName = mCore->mConsumerName;
235 } // Autolock scope
236
237 BQ_LOGV("dequeueBuffer: async=%s w=%u h=%u format=%#x, usage=%#x",
238 async ? "true" : "false", width, height, format, usage);
239
240 if ((width && !height) || (!width && height)) {
241 BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height);
242 return BAD_VALUE;
243 }
244
245 status_t returnFlags = NO_ERROR;
246 EGLDisplay eglDisplay = EGL_NO_DISPLAY;
247 EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800248 bool attachedByConsumer = false;
Dan Stoza289ade12014-02-28 11:17:17 -0800249
250 { // Autolock scope
251 Mutex::Autolock lock(mCore->mMutex);
252
253 if (format == 0) {
254 format = mCore->mDefaultBufferFormat;
255 }
256
257 // Enable the usage bits the consumer requested
258 usage |= mCore->mConsumerUsageBits;
259
Dan Stoza9f3053d2014-03-06 15:14:33 -0800260 int found;
261 status_t status = waitForFreeSlotThenRelock("dequeueBuffer", async,
262 &found, &returnFlags);
263 if (status != NO_ERROR) {
264 return status;
265 }
Dan Stoza289ade12014-02-28 11:17:17 -0800266
267 // This should not happen
268 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
269 BQ_LOGE("dequeueBuffer: no available buffer slots");
270 return -EBUSY;
271 }
272
273 *outSlot = found;
274 ATRACE_BUFFER_INDEX(found);
275
Dan Stoza9f3053d2014-03-06 15:14:33 -0800276 attachedByConsumer = mSlots[found].mAttachedByConsumer;
277
Dan Stoza289ade12014-02-28 11:17:17 -0800278 const bool useDefaultSize = !width && !height;
279 if (useDefaultSize) {
280 width = mCore->mDefaultWidth;
281 height = mCore->mDefaultHeight;
282 }
283
284 mSlots[found].mBufferState = BufferSlot::DEQUEUED;
285
286 const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
287 if ((buffer == NULL) ||
288 (static_cast<uint32_t>(buffer->width) != width) ||
289 (static_cast<uint32_t>(buffer->height) != height) ||
290 (static_cast<uint32_t>(buffer->format) != format) ||
291 ((static_cast<uint32_t>(buffer->usage) & usage) != usage))
292 {
293 mSlots[found].mAcquireCalled = false;
294 mSlots[found].mGraphicBuffer = NULL;
295 mSlots[found].mRequestBufferCalled = false;
296 mSlots[found].mEglDisplay = EGL_NO_DISPLAY;
297 mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
298 mSlots[found].mFence = Fence::NO_FENCE;
299
300 returnFlags |= BUFFER_NEEDS_REALLOCATION;
301 }
302
303 if (CC_UNLIKELY(mSlots[found].mFence == NULL)) {
304 BQ_LOGE("dequeueBuffer: about to return a NULL fence - "
305 "slot=%d w=%d h=%d format=%u",
306 found, buffer->width, buffer->height, buffer->format);
307 }
308
309 eglDisplay = mSlots[found].mEglDisplay;
310 eglFence = mSlots[found].mEglFence;
311 *outFence = mSlots[found].mFence;
312 mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
313 mSlots[found].mFence = Fence::NO_FENCE;
314 } // Autolock scope
315
316 if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
317 status_t error;
318 sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
319 width, height, format, usage, &error));
320 if (graphicBuffer == NULL) {
321 BQ_LOGE("dequeueBuffer: createGraphicBuffer failed");
322 return error;
323 }
324
325 { // Autolock scope
326 Mutex::Autolock lock(mCore->mMutex);
327
328 if (mCore->mIsAbandoned) {
329 BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
330 return NO_INIT;
331 }
332
Dan Stoza9f3053d2014-03-06 15:14:33 -0800333 mSlots[*outSlot].mFrameNumber = UINT32_MAX;
Dan Stoza289ade12014-02-28 11:17:17 -0800334 mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
335 } // Autolock scope
336 }
337
Dan Stoza9f3053d2014-03-06 15:14:33 -0800338 if (attachedByConsumer) {
339 returnFlags |= BUFFER_NEEDS_REALLOCATION;
340 }
341
Dan Stoza289ade12014-02-28 11:17:17 -0800342 if (eglFence != EGL_NO_SYNC_KHR) {
343 EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, 0,
344 1000000000);
345 // If something goes wrong, log the error, but return the buffer without
346 // synchronizing access to it. It's too late at this point to abort the
347 // dequeue operation.
348 if (result == EGL_FALSE) {
349 BQ_LOGE("dequeueBuffer: error %#x waiting for fence",
350 eglGetError());
351 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
352 BQ_LOGE("dequeueBuffer: timeout waiting for fence");
353 }
354 eglDestroySyncKHR(eglDisplay, eglFence);
355 }
356
357 BQ_LOGV("dequeueBuffer: returning slot=%d/%llu buf=%p flags=%#x", *outSlot,
358 mSlots[*outSlot].mFrameNumber,
359 mSlots[*outSlot].mGraphicBuffer->handle, returnFlags);
360
361 return returnFlags;
362}
363
Dan Stoza9f3053d2014-03-06 15:14:33 -0800364status_t BufferQueueProducer::detachBuffer(int slot) {
365 ATRACE_CALL();
366 ATRACE_BUFFER_INDEX(slot);
367 BQ_LOGV("detachBuffer(P): slot %d", slot);
368 Mutex::Autolock lock(mCore->mMutex);
369
370 if (mCore->mIsAbandoned) {
371 BQ_LOGE("detachBuffer(P): BufferQueue has been abandoned");
372 return NO_INIT;
373 }
374
375 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
376 BQ_LOGE("detachBuffer(P): slot index %d out of range [0, %d)",
377 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
378 return BAD_VALUE;
379 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
380 BQ_LOGE("detachBuffer(P): slot %d is not owned by the producer "
381 "(state = %d)", slot, mSlots[slot].mBufferState);
382 return BAD_VALUE;
383 } else if (!mSlots[slot].mRequestBufferCalled) {
384 BQ_LOGE("detachBuffer(P): buffer in slot %d has not been requested",
385 slot);
386 return BAD_VALUE;
387 }
388
389 mCore->freeBufferLocked(slot);
390 mCore->mDequeueCondition.broadcast();
391
392 return NO_ERROR;
393}
394
395status_t BufferQueueProducer::attachBuffer(int* outSlot,
396 const sp<android::GraphicBuffer>& buffer) {
397 ATRACE_CALL();
398
399 if (outSlot == NULL) {
400 BQ_LOGE("attachBuffer(P): outSlot must not be NULL");
401 return BAD_VALUE;
402 } else if (buffer == NULL) {
403 BQ_LOGE("attachBuffer(P): cannot attach NULL buffer");
404 return BAD_VALUE;
405 }
406
407 Mutex::Autolock lock(mCore->mMutex);
408
409 status_t returnFlags = NO_ERROR;
410 int found;
411 // TODO: Should we provide an async flag to attachBuffer? It seems
412 // unlikely that buffers which we are attaching to a BufferQueue will
413 // be asynchronous (droppable), but it may not be impossible.
414 status_t status = waitForFreeSlotThenRelock("attachBuffer(P)", false,
415 &found, &returnFlags);
416 if (status != NO_ERROR) {
417 return status;
418 }
419
420 // This should not happen
421 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
422 BQ_LOGE("attachBuffer(P): no available buffer slots");
423 return -EBUSY;
424 }
425
426 *outSlot = found;
427 ATRACE_BUFFER_INDEX(*outSlot);
428 BQ_LOGV("attachBuffer(P): returning slot %d flags=%#x",
429 *outSlot, returnFlags);
430
431 mSlots[*outSlot].mGraphicBuffer = buffer;
432 mSlots[*outSlot].mBufferState = BufferSlot::DEQUEUED;
433 mSlots[*outSlot].mEglFence = EGL_NO_SYNC_KHR;
434 mSlots[*outSlot].mFence = Fence::NO_FENCE;
435
436 return returnFlags;
437}
438
Dan Stoza289ade12014-02-28 11:17:17 -0800439status_t BufferQueueProducer::queueBuffer(int slot,
440 const QueueBufferInput &input, QueueBufferOutput *output) {
441 ATRACE_CALL();
442 ATRACE_BUFFER_INDEX(slot);
443
444 int64_t timestamp;
445 bool isAutoTimestamp;
446 Rect crop;
447 int scalingMode;
448 uint32_t transform;
449 bool async;
450 sp<Fence> fence;
451 input.deflate(&timestamp, &isAutoTimestamp, &crop, &scalingMode, &transform,
452 &async, &fence);
453
454 if (fence == NULL) {
455 BQ_LOGE("queueBuffer: fence is NULL");
456 return BAD_VALUE;
457 }
458
459 switch (scalingMode) {
460 case NATIVE_WINDOW_SCALING_MODE_FREEZE:
461 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
462 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
463 case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
464 break;
465 default:
466 BQ_LOGE("queueBuffer: unknown scaling mode %d", scalingMode);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800467 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800468 }
469
470 sp<IConsumerListener> listener;
471 { // Autolock scope
472 Mutex::Autolock lock(mCore->mMutex);
473
474 if (mCore->mIsAbandoned) {
475 BQ_LOGE("queueBuffer: BufferQueue has been abandoned");
476 return NO_INIT;
477 }
478
479 const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
480 if (async && mCore->mOverrideMaxBufferCount) {
481 // FIXME: Some drivers are manually setting the buffer count
482 // (which they shouldn't), so we do this extra test here to
483 // handle that case. This is TEMPORARY until we get this fixed.
484 if (mCore->mOverrideMaxBufferCount < maxBufferCount) {
485 BQ_LOGE("queueBuffer: async mode is invalid with "
486 "buffer count override");
487 return BAD_VALUE;
488 }
489 }
490
491 if (slot < 0 || slot >= maxBufferCount) {
492 BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)",
493 slot, maxBufferCount);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800494 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800495 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
496 BQ_LOGE("queueBuffer: slot %d is not owned by the producer "
497 "(state = %d)", slot, mSlots[slot].mBufferState);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800498 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800499 } else if (!mSlots[slot].mRequestBufferCalled) {
500 BQ_LOGE("queueBuffer: slot %d was queued without requesting "
501 "a buffer", slot);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800502 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800503 }
504
505 BQ_LOGV("queueBuffer: slot=%d/%llu time=%llu crop=[%d,%d,%d,%d] "
506 "transform=%#x scale=%s",
507 slot, mCore->mFrameCounter + 1, timestamp,
508 crop.left, crop.top, crop.right, crop.bottom,
509 transform, BufferItem::scalingModeName(scalingMode));
510
511 const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
512 Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
513 Rect croppedRect;
514 crop.intersect(bufferRect, &croppedRect);
515 if (croppedRect != crop) {
516 BQ_LOGE("queueBuffer: crop rect is not contained within the "
517 "buffer in slot %d", slot);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800518 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800519 }
520
521 mSlots[slot].mFence = fence;
522 mSlots[slot].mBufferState = BufferSlot::QUEUED;
523 ++mCore->mFrameCounter;
524 mSlots[slot].mFrameNumber = mCore->mFrameCounter;
525
526 BufferItem item;
527 item.mAcquireCalled = mSlots[slot].mAcquireCalled;
528 item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
529 item.mCrop = crop;
530 item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
531 item.mTransformToDisplayInverse =
532 bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
533 item.mScalingMode = scalingMode;
534 item.mTimestamp = timestamp;
535 item.mIsAutoTimestamp = isAutoTimestamp;
536 item.mFrameNumber = mCore->mFrameCounter;
537 item.mSlot = slot;
538 item.mFence = fence;
539 item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async;
540
541 if (mCore->mQueue.empty()) {
542 // When the queue is empty, we can ignore mDequeueBufferCannotBlock
543 // and simply queue this buffer
544 mCore->mQueue.push_back(item);
545 listener = mCore->mConsumerListener;
546 } else {
547 // When the queue is not empty, we need to look at the front buffer
548 // state to see if we need to replace it
549 BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
550 if (front->mIsDroppable) {
551 // If the front queued buffer is still being tracked, we first
552 // mark it as freed
553 if (mCore->stillTracking(front)) {
554 mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
555 // Reset the frame number of the freed buffer so that it is
556 // the first in line to be dequeued again
557 mSlots[front->mSlot].mFrameNumber = 0;
558 }
559 // Overwrite the droppable buffer with the incoming one
560 *front = item;
561 } else {
562 mCore->mQueue.push_back(item);
563 listener = mCore->mConsumerListener;
564 }
565 }
566
567 mCore->mBufferHasBeenQueued = true;
568 mCore->mDequeueCondition.broadcast();
569
570 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
571 mCore->mTransformHint, mCore->mQueue.size());
572
573 ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
574 } // Autolock scope
575
576 // Call back without lock held
577 if (listener != NULL) {
578 listener->onFrameAvailable();
579 }
580
581 return NO_ERROR;
582}
583
584void BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
585 ATRACE_CALL();
586 BQ_LOGV("cancelBuffer: slot %d", slot);
587 Mutex::Autolock lock(mCore->mMutex);
588
589 if (mCore->mIsAbandoned) {
590 BQ_LOGE("cancelBuffer: BufferQueue has been abandoned");
591 return;
592 }
593
Dan Stoza3e96f192014-03-03 10:16:19 -0800594 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
Dan Stoza289ade12014-02-28 11:17:17 -0800595 BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)",
Dan Stoza3e96f192014-03-03 10:16:19 -0800596 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
Dan Stoza289ade12014-02-28 11:17:17 -0800597 return;
598 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
599 BQ_LOGE("cancelBuffer: slot %d is not owned by the producer "
600 "(state = %d)", slot, mSlots[slot].mBufferState);
601 return;
602 } else if (fence == NULL) {
603 BQ_LOGE("cancelBuffer: fence is NULL");
604 return;
605 }
606
607 mSlots[slot].mBufferState = BufferSlot::FREE;
608 mSlots[slot].mFrameNumber = 0;
609 mSlots[slot].mFence = fence;
610 mCore->mDequeueCondition.broadcast();
611}
612
613int BufferQueueProducer::query(int what, int *outValue) {
614 ATRACE_CALL();
615 Mutex::Autolock lock(mCore->mMutex);
616
617 if (outValue == NULL) {
618 BQ_LOGE("query: outValue was NULL");
619 return BAD_VALUE;
620 }
621
622 if (mCore->mIsAbandoned) {
623 BQ_LOGE("query: BufferQueue has been abandoned");
624 return NO_INIT;
625 }
626
627 int value;
628 switch (what) {
629 case NATIVE_WINDOW_WIDTH:
630 value = mCore->mDefaultWidth;
631 break;
632 case NATIVE_WINDOW_HEIGHT:
633 value = mCore->mDefaultHeight;
634 break;
635 case NATIVE_WINDOW_FORMAT:
636 value = mCore->mDefaultBufferFormat;
637 break;
638 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
639 value = mCore->getMinUndequeuedBufferCountLocked(false);
640 break;
641 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
642 value = (mCore->mQueue.size() > 1);
643 break;
644 case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
645 value = mCore->mConsumerUsageBits;
646 break;
647 default:
648 return BAD_VALUE;
649 }
650
651 BQ_LOGV("query: %d? %d", what, value);
652 *outValue = value;
653 return NO_ERROR;
654}
655
656status_t BufferQueueProducer::connect(const sp<android::IBinder> &token,
657 int api, bool producerControlledByApp, QueueBufferOutput *output) {
658 ATRACE_CALL();
659 Mutex::Autolock lock(mCore->mMutex);
660 mConsumerName = mCore->mConsumerName;
661 BQ_LOGV("connect(P): api=%d producerControlledByApp=%s", api,
662 producerControlledByApp ? "true" : "false");
663
664 // If we disconnect and reconnect quickly, we can be in a state where our
665 // slots are empty but we have many buffers in the queue. This can cause us
666 // to run out of memory if we outrun the consumer. Wait here if it looks
667 // like we have too many buffers queued up.
668 while (true) {
669 if (mCore->mIsAbandoned) {
670 BQ_LOGE("connect(P): BufferQueue has been abandoned");
671 return NO_INIT;
672 }
673
674 if (mCore->mConsumerListener == NULL) {
675 BQ_LOGE("connect(P): BufferQueue has no consumer");
676 return NO_INIT;
677 }
678
679 if (output == NULL) {
680 BQ_LOGE("connect(P): output was NULL");
681 return BAD_VALUE;
682 }
683
684 if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
685 BQ_LOGE("connect(P): already connected (cur=%d req=%d)",
686 mCore->mConnectedApi, api);
687 return BAD_VALUE;
688 }
689
690 size_t maxBufferCount = mCore->getMaxBufferCountLocked(false);
691 if (mCore->mQueue.size() <= maxBufferCount) {
692 // The queue size seems small enough to proceed
693 // TODO: Make this bound tighter?
694 break;
695 }
696
697 BQ_LOGV("connect(P): queue size is %d, waiting", mCore->mQueue.size());
698 mCore->mDequeueCondition.wait(mCore->mMutex);
699 }
700
701 int status = NO_ERROR;
702 switch (api) {
703 case NATIVE_WINDOW_API_EGL:
704 case NATIVE_WINDOW_API_CPU:
705 case NATIVE_WINDOW_API_MEDIA:
706 case NATIVE_WINDOW_API_CAMERA:
707 mCore->mConnectedApi = api;
708 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
709 mCore->mTransformHint, mCore->mQueue.size());
710
711 // Set up a death notification so that we can disconnect
712 // automatically if the remote producer dies
713 if (token != NULL && token->remoteBinder() != NULL) {
714 status = token->linkToDeath(
715 static_cast<IBinder::DeathRecipient*>(this));
716 if (status == NO_ERROR) {
717 mCore->mConnectedProducerToken = token;
718 } else {
719 BQ_LOGE("connect(P): linkToDeath failed: %s (%d)",
720 strerror(-status), status);
721 }
722 }
723 break;
724 default:
725 BQ_LOGE("connect(P): unknown API %d", api);
726 status = BAD_VALUE;
727 break;
728 }
729
730 mCore->mBufferHasBeenQueued = false;
731 mCore->mDequeueBufferCannotBlock =
732 mCore->mConsumerControlledByApp && producerControlledByApp;
733
734 return status;
735}
736
737status_t BufferQueueProducer::disconnect(int api) {
738 ATRACE_CALL();
739 BQ_LOGV("disconnect(P): api %d", api);
740
741 int status = NO_ERROR;
742 sp<IConsumerListener> listener;
743 { // Autolock scope
744 Mutex::Autolock lock(mCore->mMutex);
745
746 if (mCore->mIsAbandoned) {
747 // It's not really an error to disconnect after the surface has
748 // been abandoned; it should just be a no-op.
749 return NO_ERROR;
750 }
751
752 switch (api) {
753 case NATIVE_WINDOW_API_EGL:
754 case NATIVE_WINDOW_API_CPU:
755 case NATIVE_WINDOW_API_MEDIA:
756 case NATIVE_WINDOW_API_CAMERA:
757 if (mCore->mConnectedApi == api) {
758 mCore->freeAllBuffersLocked();
759
760 // Remove our death notification callback if we have one
761 sp<IBinder> token = mCore->mConnectedProducerToken;
762 if (token != NULL) {
763 // This can fail if we're here because of the death
764 // notification, but we just ignore it
765 token->unlinkToDeath(
766 static_cast<IBinder::DeathRecipient*>(this));
767 }
768 mCore->mConnectedProducerToken = NULL;
769 mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
770 mCore->mDequeueCondition.broadcast();
771 listener = mCore->mConsumerListener;
772 } else {
773 BQ_LOGE("disconnect(P): connected to another API "
774 "(cur=%d req=%d)", mCore->mConnectedApi, api);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800775 status = BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800776 }
777 break;
778 default:
779 BQ_LOGE("disconnect(P): unknown API %d", api);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800780 status = BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800781 break;
782 }
783 } // Autolock scope
784
785 // Call back without lock held
786 if (listener != NULL) {
787 listener->onBuffersReleased();
788 }
789
790 return status;
791}
792
793void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
794 // If we're here, it means that a producer we were connected to died.
795 // We're guaranteed that we are still connected to it because we remove
796 // this callback upon disconnect. It's therefore safe to read mConnectedApi
797 // without synchronization here.
798 int api = mCore->mConnectedApi;
799 disconnect(api);
800}
801
802} // namespace android