blob: 9dd90bab5886130a9c07b74405978a25361428e9 [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;
Dan Stoza2443c792014-03-24 15:03:46 -0700435 mSlots[*outSlot].mRequestBufferCalled = true;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800436
437 return returnFlags;
438}
439
Dan Stoza289ade12014-02-28 11:17:17 -0800440status_t BufferQueueProducer::queueBuffer(int slot,
441 const QueueBufferInput &input, QueueBufferOutput *output) {
442 ATRACE_CALL();
443 ATRACE_BUFFER_INDEX(slot);
444
445 int64_t timestamp;
446 bool isAutoTimestamp;
447 Rect crop;
448 int scalingMode;
449 uint32_t transform;
450 bool async;
451 sp<Fence> fence;
452 input.deflate(&timestamp, &isAutoTimestamp, &crop, &scalingMode, &transform,
453 &async, &fence);
454
455 if (fence == NULL) {
456 BQ_LOGE("queueBuffer: fence is NULL");
457 return BAD_VALUE;
458 }
459
460 switch (scalingMode) {
461 case NATIVE_WINDOW_SCALING_MODE_FREEZE:
462 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
463 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
464 case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
465 break;
466 default:
467 BQ_LOGE("queueBuffer: unknown scaling mode %d", scalingMode);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800468 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800469 }
470
471 sp<IConsumerListener> listener;
472 { // Autolock scope
473 Mutex::Autolock lock(mCore->mMutex);
474
475 if (mCore->mIsAbandoned) {
476 BQ_LOGE("queueBuffer: BufferQueue has been abandoned");
477 return NO_INIT;
478 }
479
480 const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
481 if (async && mCore->mOverrideMaxBufferCount) {
482 // FIXME: Some drivers are manually setting the buffer count
483 // (which they shouldn't), so we do this extra test here to
484 // handle that case. This is TEMPORARY until we get this fixed.
485 if (mCore->mOverrideMaxBufferCount < maxBufferCount) {
486 BQ_LOGE("queueBuffer: async mode is invalid with "
487 "buffer count override");
488 return BAD_VALUE;
489 }
490 }
491
492 if (slot < 0 || slot >= maxBufferCount) {
493 BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)",
494 slot, maxBufferCount);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800495 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800496 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
497 BQ_LOGE("queueBuffer: slot %d is not owned by the producer "
498 "(state = %d)", slot, mSlots[slot].mBufferState);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800499 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800500 } else if (!mSlots[slot].mRequestBufferCalled) {
501 BQ_LOGE("queueBuffer: slot %d was queued without requesting "
502 "a buffer", slot);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800503 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800504 }
505
506 BQ_LOGV("queueBuffer: slot=%d/%llu time=%llu crop=[%d,%d,%d,%d] "
507 "transform=%#x scale=%s",
508 slot, mCore->mFrameCounter + 1, timestamp,
509 crop.left, crop.top, crop.right, crop.bottom,
510 transform, BufferItem::scalingModeName(scalingMode));
511
512 const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
513 Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
514 Rect croppedRect;
515 crop.intersect(bufferRect, &croppedRect);
516 if (croppedRect != crop) {
517 BQ_LOGE("queueBuffer: crop rect is not contained within the "
518 "buffer in slot %d", slot);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800519 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800520 }
521
522 mSlots[slot].mFence = fence;
523 mSlots[slot].mBufferState = BufferSlot::QUEUED;
524 ++mCore->mFrameCounter;
525 mSlots[slot].mFrameNumber = mCore->mFrameCounter;
526
527 BufferItem item;
528 item.mAcquireCalled = mSlots[slot].mAcquireCalled;
529 item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
530 item.mCrop = crop;
531 item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
532 item.mTransformToDisplayInverse =
533 bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
534 item.mScalingMode = scalingMode;
535 item.mTimestamp = timestamp;
536 item.mIsAutoTimestamp = isAutoTimestamp;
537 item.mFrameNumber = mCore->mFrameCounter;
538 item.mSlot = slot;
539 item.mFence = fence;
540 item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async;
541
542 if (mCore->mQueue.empty()) {
543 // When the queue is empty, we can ignore mDequeueBufferCannotBlock
544 // and simply queue this buffer
545 mCore->mQueue.push_back(item);
546 listener = mCore->mConsumerListener;
547 } else {
548 // When the queue is not empty, we need to look at the front buffer
549 // state to see if we need to replace it
550 BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
551 if (front->mIsDroppable) {
552 // If the front queued buffer is still being tracked, we first
553 // mark it as freed
554 if (mCore->stillTracking(front)) {
555 mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
556 // Reset the frame number of the freed buffer so that it is
557 // the first in line to be dequeued again
558 mSlots[front->mSlot].mFrameNumber = 0;
559 }
560 // Overwrite the droppable buffer with the incoming one
561 *front = item;
562 } else {
563 mCore->mQueue.push_back(item);
564 listener = mCore->mConsumerListener;
565 }
566 }
567
568 mCore->mBufferHasBeenQueued = true;
569 mCore->mDequeueCondition.broadcast();
570
571 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
572 mCore->mTransformHint, mCore->mQueue.size());
573
574 ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
575 } // Autolock scope
576
577 // Call back without lock held
578 if (listener != NULL) {
579 listener->onFrameAvailable();
580 }
581
582 return NO_ERROR;
583}
584
585void BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
586 ATRACE_CALL();
587 BQ_LOGV("cancelBuffer: slot %d", slot);
588 Mutex::Autolock lock(mCore->mMutex);
589
590 if (mCore->mIsAbandoned) {
591 BQ_LOGE("cancelBuffer: BufferQueue has been abandoned");
592 return;
593 }
594
Dan Stoza3e96f192014-03-03 10:16:19 -0800595 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
Dan Stoza289ade12014-02-28 11:17:17 -0800596 BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)",
Dan Stoza3e96f192014-03-03 10:16:19 -0800597 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
Dan Stoza289ade12014-02-28 11:17:17 -0800598 return;
599 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
600 BQ_LOGE("cancelBuffer: slot %d is not owned by the producer "
601 "(state = %d)", slot, mSlots[slot].mBufferState);
602 return;
603 } else if (fence == NULL) {
604 BQ_LOGE("cancelBuffer: fence is NULL");
605 return;
606 }
607
608 mSlots[slot].mBufferState = BufferSlot::FREE;
609 mSlots[slot].mFrameNumber = 0;
610 mSlots[slot].mFence = fence;
611 mCore->mDequeueCondition.broadcast();
612}
613
614int BufferQueueProducer::query(int what, int *outValue) {
615 ATRACE_CALL();
616 Mutex::Autolock lock(mCore->mMutex);
617
618 if (outValue == NULL) {
619 BQ_LOGE("query: outValue was NULL");
620 return BAD_VALUE;
621 }
622
623 if (mCore->mIsAbandoned) {
624 BQ_LOGE("query: BufferQueue has been abandoned");
625 return NO_INIT;
626 }
627
628 int value;
629 switch (what) {
630 case NATIVE_WINDOW_WIDTH:
631 value = mCore->mDefaultWidth;
632 break;
633 case NATIVE_WINDOW_HEIGHT:
634 value = mCore->mDefaultHeight;
635 break;
636 case NATIVE_WINDOW_FORMAT:
637 value = mCore->mDefaultBufferFormat;
638 break;
639 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
640 value = mCore->getMinUndequeuedBufferCountLocked(false);
641 break;
642 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
643 value = (mCore->mQueue.size() > 1);
644 break;
645 case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
646 value = mCore->mConsumerUsageBits;
647 break;
648 default:
649 return BAD_VALUE;
650 }
651
652 BQ_LOGV("query: %d? %d", what, value);
653 *outValue = value;
654 return NO_ERROR;
655}
656
657status_t BufferQueueProducer::connect(const sp<android::IBinder> &token,
658 int api, bool producerControlledByApp, QueueBufferOutput *output) {
659 ATRACE_CALL();
660 Mutex::Autolock lock(mCore->mMutex);
661 mConsumerName = mCore->mConsumerName;
662 BQ_LOGV("connect(P): api=%d producerControlledByApp=%s", api,
663 producerControlledByApp ? "true" : "false");
664
665 // If we disconnect and reconnect quickly, we can be in a state where our
666 // slots are empty but we have many buffers in the queue. This can cause us
667 // to run out of memory if we outrun the consumer. Wait here if it looks
668 // like we have too many buffers queued up.
669 while (true) {
670 if (mCore->mIsAbandoned) {
671 BQ_LOGE("connect(P): BufferQueue has been abandoned");
672 return NO_INIT;
673 }
674
675 if (mCore->mConsumerListener == NULL) {
676 BQ_LOGE("connect(P): BufferQueue has no consumer");
677 return NO_INIT;
678 }
679
680 if (output == NULL) {
681 BQ_LOGE("connect(P): output was NULL");
682 return BAD_VALUE;
683 }
684
685 if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
686 BQ_LOGE("connect(P): already connected (cur=%d req=%d)",
687 mCore->mConnectedApi, api);
688 return BAD_VALUE;
689 }
690
691 size_t maxBufferCount = mCore->getMaxBufferCountLocked(false);
692 if (mCore->mQueue.size() <= maxBufferCount) {
693 // The queue size seems small enough to proceed
694 // TODO: Make this bound tighter?
695 break;
696 }
697
698 BQ_LOGV("connect(P): queue size is %d, waiting", mCore->mQueue.size());
699 mCore->mDequeueCondition.wait(mCore->mMutex);
700 }
701
702 int status = NO_ERROR;
703 switch (api) {
704 case NATIVE_WINDOW_API_EGL:
705 case NATIVE_WINDOW_API_CPU:
706 case NATIVE_WINDOW_API_MEDIA:
707 case NATIVE_WINDOW_API_CAMERA:
708 mCore->mConnectedApi = api;
709 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
710 mCore->mTransformHint, mCore->mQueue.size());
711
712 // Set up a death notification so that we can disconnect
713 // automatically if the remote producer dies
714 if (token != NULL && token->remoteBinder() != NULL) {
715 status = token->linkToDeath(
716 static_cast<IBinder::DeathRecipient*>(this));
717 if (status == NO_ERROR) {
718 mCore->mConnectedProducerToken = token;
719 } else {
720 BQ_LOGE("connect(P): linkToDeath failed: %s (%d)",
721 strerror(-status), status);
722 }
723 }
724 break;
725 default:
726 BQ_LOGE("connect(P): unknown API %d", api);
727 status = BAD_VALUE;
728 break;
729 }
730
731 mCore->mBufferHasBeenQueued = false;
732 mCore->mDequeueBufferCannotBlock =
733 mCore->mConsumerControlledByApp && producerControlledByApp;
734
735 return status;
736}
737
738status_t BufferQueueProducer::disconnect(int api) {
739 ATRACE_CALL();
740 BQ_LOGV("disconnect(P): api %d", api);
741
742 int status = NO_ERROR;
743 sp<IConsumerListener> listener;
744 { // Autolock scope
745 Mutex::Autolock lock(mCore->mMutex);
746
747 if (mCore->mIsAbandoned) {
748 // It's not really an error to disconnect after the surface has
749 // been abandoned; it should just be a no-op.
750 return NO_ERROR;
751 }
752
753 switch (api) {
754 case NATIVE_WINDOW_API_EGL:
755 case NATIVE_WINDOW_API_CPU:
756 case NATIVE_WINDOW_API_MEDIA:
757 case NATIVE_WINDOW_API_CAMERA:
758 if (mCore->mConnectedApi == api) {
759 mCore->freeAllBuffersLocked();
760
761 // Remove our death notification callback if we have one
762 sp<IBinder> token = mCore->mConnectedProducerToken;
763 if (token != NULL) {
764 // This can fail if we're here because of the death
765 // notification, but we just ignore it
766 token->unlinkToDeath(
767 static_cast<IBinder::DeathRecipient*>(this));
768 }
769 mCore->mConnectedProducerToken = NULL;
770 mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
Jesse Hall399184a2014-03-03 15:42:54 -0800771 mCore->mSidebandStream.clear();
Dan Stoza289ade12014-02-28 11:17:17 -0800772 mCore->mDequeueCondition.broadcast();
773 listener = mCore->mConsumerListener;
774 } else {
775 BQ_LOGE("disconnect(P): connected to another API "
776 "(cur=%d req=%d)", mCore->mConnectedApi, api);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800777 status = BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800778 }
779 break;
780 default:
781 BQ_LOGE("disconnect(P): unknown API %d", api);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800782 status = BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800783 break;
784 }
785 } // Autolock scope
786
787 // Call back without lock held
788 if (listener != NULL) {
789 listener->onBuffersReleased();
790 }
791
792 return status;
793}
794
Jesse Hall399184a2014-03-03 15:42:54 -0800795status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) {
796 Mutex::Autolock _l(mCore->mMutex);
797 mCore->mSidebandStream = stream;
798 return NO_ERROR;
799}
800
Dan Stoza289ade12014-02-28 11:17:17 -0800801void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
802 // If we're here, it means that a producer we were connected to died.
803 // We're guaranteed that we are still connected to it because we remove
804 // this callback upon disconnect. It's therefore safe to read mConnectedApi
805 // without synchronization here.
806 int api = mCore->mConnectedApi;
807 disconnect(api);
808}
809
810} // namespace android