blob: 8e2afd00127a2eb606d62bf60053cd4b64ce07e3 [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
Mark Salyzyn8f515ce2014-06-09 14:32:04 -070017#include <inttypes.h>
18
Dan Stoza3e96f192014-03-03 10:16:19 -080019#define LOG_TAG "BufferQueueConsumer"
20#define ATRACE_TAG ATRACE_TAG_GRAPHICS
21//#define LOG_NDEBUG 0
22
Dan Stoza289ade12014-02-28 11:17:17 -080023#include <gui/BufferItem.h>
24#include <gui/BufferQueueConsumer.h>
25#include <gui/BufferQueueCore.h>
26#include <gui/IConsumerListener.h>
Dan Stozad1c10362014-03-28 15:19:08 -070027#include <gui/IProducerListener.h>
Dan Stoza289ade12014-02-28 11:17:17 -080028
29namespace android {
30
31BufferQueueConsumer::BufferQueueConsumer(const sp<BufferQueueCore>& core) :
32 mCore(core),
33 mSlots(core->mSlots),
34 mConsumerName() {}
35
36BufferQueueConsumer::~BufferQueueConsumer() {}
37
38status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
Dan Stozaa4650a52015-05-12 12:56:16 -070039 nsecs_t expectedPresent, uint64_t maxFrameNumber) {
Dan Stoza289ade12014-02-28 11:17:17 -080040 ATRACE_CALL();
Dan Stoza289ade12014-02-28 11:17:17 -080041
Lajos Molnar5f920c12015-07-13 16:04:24 -070042 int numDroppedBuffers = 0;
43 sp<IProducerListener> listener;
44 {
45 Mutex::Autolock lock(mCore->mMutex);
46
47 // Check that the consumer doesn't currently have the maximum number of
48 // buffers acquired. We allow the max buffer count to be exceeded by one
49 // buffer so that the consumer can successfully set up the newly acquired
50 // buffer before releasing the old one.
51 int numAcquiredBuffers = 0;
52 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -070053 if (mSlots[s].mBufferState.isAcquired()) {
Lajos Molnar5f920c12015-07-13 16:04:24 -070054 ++numAcquiredBuffers;
55 }
Dan Stoza289ade12014-02-28 11:17:17 -080056 }
Lajos Molnar5f920c12015-07-13 16:04:24 -070057 if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) {
58 BQ_LOGE("acquireBuffer: max acquired buffer count reached: %d (max %d)",
59 numAcquiredBuffers, mCore->mMaxAcquiredBufferCount);
60 return INVALID_OPERATION;
61 }
Dan Stoza289ade12014-02-28 11:17:17 -080062
Pablo Ceballosccdfd602015-10-07 15:05:45 -070063 bool sharedBufferAvailable = mCore->mSingleBufferMode &&
64 mCore->mSingleBufferSlot !=
65 BufferQueueCore::INVALID_BUFFER_SLOT;
66
Lajos Molnar5f920c12015-07-13 16:04:24 -070067 // In asynchronous mode the list is guaranteed to be one buffer deep,
68 // while in synchronous mode we use the oldest buffer.
Pablo Ceballosccdfd602015-10-07 15:05:45 -070069 if (mCore->mQueue.empty() && !sharedBufferAvailable) {
Lajos Molnar5f920c12015-07-13 16:04:24 -070070 return NO_BUFFER_AVAILABLE;
71 }
Dan Stoza289ade12014-02-28 11:17:17 -080072
Lajos Molnar5f920c12015-07-13 16:04:24 -070073 BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
Dan Stoza289ade12014-02-28 11:17:17 -080074
Lajos Molnar5f920c12015-07-13 16:04:24 -070075 // If expectedPresent is specified, we may not want to return a buffer yet.
76 // If it's specified and there's more than one buffer queued, we may want
77 // to drop a buffer.
Pablo Ceballosccdfd602015-10-07 15:05:45 -070078 // Skip this if we're in single buffer mode and the queue is empty,
79 // since in that case we'll just return the shared buffer.
80 if (expectedPresent != 0 && !mCore->mQueue.empty()) {
Lajos Molnar5f920c12015-07-13 16:04:24 -070081 const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second
Dan Stoza289ade12014-02-28 11:17:17 -080082
Lajos Molnar5f920c12015-07-13 16:04:24 -070083 // The 'expectedPresent' argument indicates when the buffer is expected
84 // to be presented on-screen. If the buffer's desired present time is
85 // earlier (less) than expectedPresent -- meaning it will be displayed
86 // on time or possibly late if we show it as soon as possible -- we
87 // acquire and return it. If we don't want to display it until after the
88 // expectedPresent time, we return PRESENT_LATER without acquiring it.
89 //
90 // To be safe, we don't defer acquisition if expectedPresent is more
91 // than one second in the future beyond the desired present time
92 // (i.e., we'd be holding the buffer for a long time).
93 //
94 // NOTE: Code assumes monotonic time values from the system clock
95 // are positive.
Dan Stoza289ade12014-02-28 11:17:17 -080096
Lajos Molnar5f920c12015-07-13 16:04:24 -070097 // Start by checking to see if we can drop frames. We skip this check if
98 // the timestamps are being auto-generated by Surface. If the app isn't
99 // generating timestamps explicitly, it probably doesn't want frames to
100 // be discarded based on them.
101 while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) {
102 const BufferItem& bufferItem(mCore->mQueue[1]);
Dan Stozaa4650a52015-05-12 12:56:16 -0700103
Lajos Molnar5f920c12015-07-13 16:04:24 -0700104 // If dropping entry[0] would leave us with a buffer that the
105 // consumer is not yet ready for, don't drop it.
106 if (maxFrameNumber && bufferItem.mFrameNumber > maxFrameNumber) {
107 break;
108 }
109
110 // If entry[1] is timely, drop entry[0] (and repeat). We apply an
111 // additional criterion here: we only drop the earlier buffer if our
112 // desiredPresent falls within +/- 1 second of the expected present.
113 // Otherwise, bogus desiredPresent times (e.g., 0 or a small
114 // relative timestamp), which normally mean "ignore the timestamp
115 // and acquire immediately", would cause us to drop frames.
116 //
117 // We may want to add an additional criterion: don't drop the
118 // earlier buffer if entry[1]'s fence hasn't signaled yet.
119 nsecs_t desiredPresent = bufferItem.mTimestamp;
120 if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC ||
121 desiredPresent > expectedPresent) {
122 // This buffer is set to display in the near future, or
123 // desiredPresent is garbage. Either way we don't want to drop
124 // the previous buffer just to get this on the screen sooner.
125 BQ_LOGV("acquireBuffer: nodrop desire=%" PRId64 " expect=%"
126 PRId64 " (%" PRId64 ") now=%" PRId64,
127 desiredPresent, expectedPresent,
128 desiredPresent - expectedPresent,
129 systemTime(CLOCK_MONOTONIC));
130 break;
131 }
132
133 BQ_LOGV("acquireBuffer: drop desire=%" PRId64 " expect=%" PRId64
134 " size=%zu",
135 desiredPresent, expectedPresent, mCore->mQueue.size());
136 if (mCore->stillTracking(front)) {
137 // Front buffer is still in mSlots, so mark the slot as free
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700138 mSlots[front->mSlot].mBufferState.freeQueued();
139
140 // After leaving single buffer mode, the shared buffer will
141 // still be around. Mark it as no longer shared if this
142 // operation causes it to be free.
143 if (!mCore->mSingleBufferMode &&
144 mSlots[front->mSlot].mBufferState.isFree()) {
145 mSlots[front->mSlot].mBufferState.mShared = false;
146 }
147 // Don't put the shared buffer on the free list.
148 if (!mSlots[front->mSlot].mBufferState.isShared()) {
149 mCore->mFreeBuffers.push_back(front->mSlot);
150 }
Lajos Molnar5f920c12015-07-13 16:04:24 -0700151 listener = mCore->mConnectedProducerListener;
152 ++numDroppedBuffers;
153 }
154 mCore->mQueue.erase(front);
155 front = mCore->mQueue.begin();
Dan Stozaecc50402015-04-28 14:42:06 -0700156 }
157
Lajos Molnar5f920c12015-07-13 16:04:24 -0700158 // See if the front buffer is ready to be acquired
159 nsecs_t desiredPresent = front->mTimestamp;
160 bool bufferIsDue = desiredPresent <= expectedPresent ||
161 desiredPresent > expectedPresent + MAX_REASONABLE_NSEC;
162 bool consumerIsReady = maxFrameNumber > 0 ?
163 front->mFrameNumber <= maxFrameNumber : true;
164 if (!bufferIsDue || !consumerIsReady) {
165 BQ_LOGV("acquireBuffer: defer desire=%" PRId64 " expect=%" PRId64
166 " (%" PRId64 ") now=%" PRId64 " frame=%" PRIu64
167 " consumer=%" PRIu64,
Mark Salyzyn8f515ce2014-06-09 14:32:04 -0700168 desiredPresent, expectedPresent,
Dan Stoza289ade12014-02-28 11:17:17 -0800169 desiredPresent - expectedPresent,
Lajos Molnar5f920c12015-07-13 16:04:24 -0700170 systemTime(CLOCK_MONOTONIC),
171 front->mFrameNumber, maxFrameNumber);
172 return PRESENT_LATER;
Dan Stoza289ade12014-02-28 11:17:17 -0800173 }
174
Lajos Molnar5f920c12015-07-13 16:04:24 -0700175 BQ_LOGV("acquireBuffer: accept desire=%" PRId64 " expect=%" PRId64 " "
176 "(%" PRId64 ") now=%" PRId64, desiredPresent, expectedPresent,
Dan Stoza289ade12014-02-28 11:17:17 -0800177 desiredPresent - expectedPresent,
Lajos Molnar5f920c12015-07-13 16:04:24 -0700178 systemTime(CLOCK_MONOTONIC));
Dan Stoza289ade12014-02-28 11:17:17 -0800179 }
180
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700181 int slot = BufferQueueCore::INVALID_BUFFER_SLOT;
182
183 if (sharedBufferAvailable && mCore->mQueue.empty()) {
184 // make sure the buffer has finished allocating before acquiring it
185 mCore->waitWhileAllocatingLocked();
186
187 slot = mCore->mSingleBufferSlot;
188
189 // Recreate the BufferItem for the shared buffer from the data that
190 // was cached when it was last queued.
191 outBuffer->mGraphicBuffer = mSlots[slot].mGraphicBuffer;
192 outBuffer->mFence = Fence::NO_FENCE;
193 outBuffer->mCrop = mCore->mSingleBufferCache.crop;
194 outBuffer->mTransform = mCore->mSingleBufferCache.transform &
195 ~static_cast<uint32_t>(
196 NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
197 outBuffer->mScalingMode = mCore->mSingleBufferCache.scalingMode;
198 outBuffer->mDataSpace = mCore->mSingleBufferCache.dataspace;
199 outBuffer->mFrameNumber = mCore->mFrameCounter;
200 outBuffer->mSlot = slot;
201 outBuffer->mAcquireCalled = mSlots[slot].mAcquireCalled;
202 outBuffer->mTransformToDisplayInverse =
203 (mCore->mSingleBufferCache.transform &
204 NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) != 0;
205 outBuffer->mSurfaceDamage = Region::INVALID_REGION;
206 } else {
207 slot = front->mSlot;
208 *outBuffer = *front;
209 }
210
Lajos Molnar5f920c12015-07-13 16:04:24 -0700211 ATRACE_BUFFER_INDEX(slot);
212
213 BQ_LOGV("acquireBuffer: acquiring { slot=%d/%" PRIu64 " buffer=%p }",
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700214 slot, outBuffer->mFrameNumber, outBuffer->mGraphicBuffer->handle);
Lajos Molnar5f920c12015-07-13 16:04:24 -0700215 // If the front buffer is still being tracked, update its slot state
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700216 if (mCore->stillTracking(outBuffer)) {
Lajos Molnar5f920c12015-07-13 16:04:24 -0700217 mSlots[slot].mAcquireCalled = true;
218 mSlots[slot].mNeedsCleanupOnRelease = false;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700219 // Don't decrease the queue count if the BufferItem wasn't
220 // previously in the queue. This happens in single buffer mode when
221 // the queue is empty and the BufferItem is created above.
222 if (mCore->mQueue.empty()) {
223 mSlots[slot].mBufferState.acquireNotInQueue();
224 } else {
225 mSlots[slot].mBufferState.acquire();
226 }
Lajos Molnar5f920c12015-07-13 16:04:24 -0700227 mSlots[slot].mFence = Fence::NO_FENCE;
228 }
229
230 // If the buffer has previously been acquired by the consumer, set
231 // mGraphicBuffer to NULL to avoid unnecessarily remapping this buffer
232 // on the consumer side
233 if (outBuffer->mAcquireCalled) {
234 outBuffer->mGraphicBuffer = NULL;
235 }
236
237 mCore->mQueue.erase(front);
238
239 // We might have freed a slot while dropping old buffers, or the producer
240 // may be blocked waiting for the number of buffers in the queue to
241 // decrease.
242 mCore->mDequeueCondition.broadcast();
243
244 ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
245
246 mCore->validateConsistencyLocked();
Dan Stoza289ade12014-02-28 11:17:17 -0800247 }
248
Lajos Molnar5f920c12015-07-13 16:04:24 -0700249 if (listener != NULL) {
250 for (int i = 0; i < numDroppedBuffers; ++i) {
251 listener->onBufferReleased();
252 }
Dan Stoza289ade12014-02-28 11:17:17 -0800253 }
254
Dan Stoza289ade12014-02-28 11:17:17 -0800255 return NO_ERROR;
256}
257
Dan Stoza9f3053d2014-03-06 15:14:33 -0800258status_t BufferQueueConsumer::detachBuffer(int slot) {
259 ATRACE_CALL();
260 ATRACE_BUFFER_INDEX(slot);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700261 BQ_LOGV("detachBuffer: slot %d", slot);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800262 Mutex::Autolock lock(mCore->mMutex);
263
264 if (mCore->mIsAbandoned) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700265 BQ_LOGE("detachBuffer: BufferQueue has been abandoned");
Dan Stoza9f3053d2014-03-06 15:14:33 -0800266 return NO_INIT;
267 }
268
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700269 if (mCore->mSingleBufferMode) {
270 BQ_LOGE("detachBuffer: detachBuffer not allowed in single buffer"
271 "mode");
Dan Stoza9f3053d2014-03-06 15:14:33 -0800272 return BAD_VALUE;
273 }
274
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700275 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
276 BQ_LOGE("detachBuffer: slot index %d out of range [0, %d)",
277 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
278 return BAD_VALUE;
279 } else if (!mSlots[slot].mBufferState.isAcquired()) {
280 BQ_LOGE("detachBuffer: slot %d is not owned by the consumer "
281 "(state = %s)", slot, mSlots[slot].mBufferState.string());
282 return BAD_VALUE;
283 }
284
285 mSlots[slot].mBufferState.detachConsumer();
Dan Stoza9f3053d2014-03-06 15:14:33 -0800286 mCore->freeBufferLocked(slot);
287 mCore->mDequeueCondition.broadcast();
Dan Stoza0de7ea72015-04-23 13:20:51 -0700288 mCore->validateConsistencyLocked();
Dan Stoza9f3053d2014-03-06 15:14:33 -0800289
290 return NO_ERROR;
291}
292
293status_t BufferQueueConsumer::attachBuffer(int* outSlot,
294 const sp<android::GraphicBuffer>& buffer) {
295 ATRACE_CALL();
296
297 if (outSlot == NULL) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700298 BQ_LOGE("attachBuffer: outSlot must not be NULL");
Dan Stoza9f3053d2014-03-06 15:14:33 -0800299 return BAD_VALUE;
300 } else if (buffer == NULL) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700301 BQ_LOGE("attachBuffer: cannot attach NULL buffer");
Dan Stoza9f3053d2014-03-06 15:14:33 -0800302 return BAD_VALUE;
303 }
304
305 Mutex::Autolock lock(mCore->mMutex);
306
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700307 if (mCore->mSingleBufferMode) {
308 BQ_LOGE("attachBuffer: cannot attach a buffer in single buffer"
309 "mode");
310 return BAD_VALUE;
311 }
312
Dan Stoza0de7ea72015-04-23 13:20:51 -0700313 // Make sure we don't have too many acquired buffers
Dan Stoza9f3053d2014-03-06 15:14:33 -0800314 int numAcquiredBuffers = 0;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800315 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700316 if (mSlots[s].mBufferState.isAcquired()) {
Dan Stoza9f3053d2014-03-06 15:14:33 -0800317 ++numAcquiredBuffers;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800318 }
319 }
320
321 if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700322 BQ_LOGE("attachBuffer: max acquired buffer count reached: %d "
Dan Stoza9f3053d2014-03-06 15:14:33 -0800323 "(max %d)", numAcquiredBuffers,
324 mCore->mMaxAcquiredBufferCount);
325 return INVALID_OPERATION;
326 }
Dan Stoza0de7ea72015-04-23 13:20:51 -0700327
Dan Stoza812ed062015-06-02 15:45:22 -0700328 if (buffer->getGenerationNumber() != mCore->mGenerationNumber) {
329 BQ_LOGE("attachBuffer: generation number mismatch [buffer %u] "
330 "[queue %u]", buffer->getGenerationNumber(),
331 mCore->mGenerationNumber);
332 return BAD_VALUE;
333 }
334
Dan Stoza0de7ea72015-04-23 13:20:51 -0700335 // Find a free slot to put the buffer into
336 int found = BufferQueueCore::INVALID_BUFFER_SLOT;
337 if (!mCore->mFreeSlots.empty()) {
338 auto slot = mCore->mFreeSlots.begin();
339 found = *slot;
340 mCore->mFreeSlots.erase(slot);
341 } else if (!mCore->mFreeBuffers.empty()) {
342 found = mCore->mFreeBuffers.front();
343 mCore->mFreeBuffers.remove(found);
344 }
Dan Stoza9f3053d2014-03-06 15:14:33 -0800345 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700346 BQ_LOGE("attachBuffer: could not find free buffer slot");
Dan Stoza9f3053d2014-03-06 15:14:33 -0800347 return NO_MEMORY;
348 }
349
350 *outSlot = found;
351 ATRACE_BUFFER_INDEX(*outSlot);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700352 BQ_LOGV("attachBuffer: returning slot %d", *outSlot);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800353
354 mSlots[*outSlot].mGraphicBuffer = buffer;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700355 mSlots[*outSlot].mBufferState.attachConsumer();
Dan Stoza9f3053d2014-03-06 15:14:33 -0800356 mSlots[*outSlot].mAttachedByConsumer = true;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800357 mSlots[*outSlot].mNeedsCleanupOnRelease = false;
358 mSlots[*outSlot].mFence = Fence::NO_FENCE;
359 mSlots[*outSlot].mFrameNumber = 0;
360
Dan Stoza99b18b42014-03-28 15:34:33 -0700361 // mAcquireCalled tells BufferQueue that it doesn't need to send a valid
362 // GraphicBuffer pointer on the next acquireBuffer call, which decreases
363 // Binder traffic by not un/flattening the GraphicBuffer. However, it
364 // requires that the consumer maintain a cached copy of the slot <--> buffer
365 // mappings, which is why the consumer doesn't need the valid pointer on
366 // acquire.
367 //
368 // The StreamSplitter is one of the primary users of the attach/detach
369 // logic, and while it is running, all buffers it acquires are immediately
370 // detached, and all buffers it eventually releases are ones that were
371 // attached (as opposed to having been obtained from acquireBuffer), so it
372 // doesn't make sense to maintain the slot/buffer mappings, which would
373 // become invalid for every buffer during detach/attach. By setting this to
374 // false, the valid GraphicBuffer pointer will always be sent with acquire
375 // for attached buffers.
376 mSlots[*outSlot].mAcquireCalled = false;
377
Dan Stoza0de7ea72015-04-23 13:20:51 -0700378 mCore->validateConsistencyLocked();
379
Dan Stoza9f3053d2014-03-06 15:14:33 -0800380 return NO_ERROR;
381}
382
Dan Stoza289ade12014-02-28 11:17:17 -0800383status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
384 const sp<Fence>& releaseFence, EGLDisplay eglDisplay,
385 EGLSyncKHR eglFence) {
386 ATRACE_CALL();
387 ATRACE_BUFFER_INDEX(slot);
388
Dan Stoza9f3053d2014-03-06 15:14:33 -0800389 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS ||
390 releaseFence == NULL) {
Dan Stoza52937cd2015-05-01 16:42:55 -0700391 BQ_LOGE("releaseBuffer: slot %d out of range or fence %p NULL", slot,
392 releaseFence.get());
Dan Stoza289ade12014-02-28 11:17:17 -0800393 return BAD_VALUE;
394 }
395
Dan Stozad1c10362014-03-28 15:19:08 -0700396 sp<IProducerListener> listener;
397 { // Autolock scope
398 Mutex::Autolock lock(mCore->mMutex);
Dan Stoza289ade12014-02-28 11:17:17 -0800399
Dan Stozad1c10362014-03-28 15:19:08 -0700400 // If the frame number has changed because the buffer has been reallocated,
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700401 // we can ignore this releaseBuffer for the old buffer.
402 // Ignore this for the shared buffer where the frame number can easily
403 // get out of sync due to the buffer being queued and acquired at the
404 // same time.
405 if (frameNumber != mSlots[slot].mFrameNumber &&
406 !mSlots[slot].mBufferState.isShared()) {
Dan Stozad1c10362014-03-28 15:19:08 -0700407 return STALE_BUFFER_SLOT;
408 }
Dan Stoza289ade12014-02-28 11:17:17 -0800409
Dan Stozad1c10362014-03-28 15:19:08 -0700410
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700411 if (mSlots[slot].mBufferState.isAcquired()) {
Dan Stozad1c10362014-03-28 15:19:08 -0700412 mSlots[slot].mEglDisplay = eglDisplay;
413 mSlots[slot].mEglFence = eglFence;
414 mSlots[slot].mFence = releaseFence;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700415 mSlots[slot].mBufferState.release();
416
417 // After leaving single buffer mode, the shared buffer will
418 // still be around. Mark it as no longer shared if this
419 // operation causes it to be free.
420 if (!mCore->mSingleBufferMode &&
421 mSlots[slot].mBufferState.isFree()) {
422 mSlots[slot].mBufferState.mShared = false;
423 }
424 // Don't put the shared buffer on the free list.
425 if (!mSlots[slot].mBufferState.isShared()) {
426 mCore->mFreeBuffers.push_back(slot);
427 }
428
Dan Stozad1c10362014-03-28 15:19:08 -0700429 listener = mCore->mConnectedProducerListener;
430 BQ_LOGV("releaseBuffer: releasing slot %d", slot);
431 } else if (mSlots[slot].mNeedsCleanupOnRelease) {
432 BQ_LOGV("releaseBuffer: releasing a stale buffer slot %d "
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700433 "(state = %s)", slot, mSlots[slot].mBufferState.string());
Dan Stozad1c10362014-03-28 15:19:08 -0700434 mSlots[slot].mNeedsCleanupOnRelease = false;
435 return STALE_BUFFER_SLOT;
436 } else {
Dan Stoza52937cd2015-05-01 16:42:55 -0700437 BQ_LOGE("releaseBuffer: attempted to release buffer slot %d "
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700438 "but its state was %s", slot,
439 mSlots[slot].mBufferState.string());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800440 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800441 }
Dan Stoza289ade12014-02-28 11:17:17 -0800442
Dan Stozad1c10362014-03-28 15:19:08 -0700443 mCore->mDequeueCondition.broadcast();
Dan Stoza0de7ea72015-04-23 13:20:51 -0700444 mCore->validateConsistencyLocked();
Dan Stozad1c10362014-03-28 15:19:08 -0700445 } // Autolock scope
Dan Stoza289ade12014-02-28 11:17:17 -0800446
Dan Stozad1c10362014-03-28 15:19:08 -0700447 // Call back without lock held
448 if (listener != NULL) {
449 listener->onBufferReleased();
450 }
Dan Stoza289ade12014-02-28 11:17:17 -0800451
452 return NO_ERROR;
453}
454
455status_t BufferQueueConsumer::connect(
456 const sp<IConsumerListener>& consumerListener, bool controlledByApp) {
457 ATRACE_CALL();
458
459 if (consumerListener == NULL) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700460 BQ_LOGE("connect: consumerListener may not be NULL");
Dan Stoza289ade12014-02-28 11:17:17 -0800461 return BAD_VALUE;
462 }
463
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700464 BQ_LOGV("connect: controlledByApp=%s",
Dan Stoza289ade12014-02-28 11:17:17 -0800465 controlledByApp ? "true" : "false");
466
467 Mutex::Autolock lock(mCore->mMutex);
468
469 if (mCore->mIsAbandoned) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700470 BQ_LOGE("connect: BufferQueue has been abandoned");
Dan Stoza289ade12014-02-28 11:17:17 -0800471 return NO_INIT;
472 }
473
474 mCore->mConsumerListener = consumerListener;
475 mCore->mConsumerControlledByApp = controlledByApp;
476
477 return NO_ERROR;
478}
479
480status_t BufferQueueConsumer::disconnect() {
481 ATRACE_CALL();
482
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700483 BQ_LOGV("disconnect");
Dan Stoza289ade12014-02-28 11:17:17 -0800484
485 Mutex::Autolock lock(mCore->mMutex);
486
487 if (mCore->mConsumerListener == NULL) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700488 BQ_LOGE("disconnect: no consumer is connected");
Dan Stoza9f3053d2014-03-06 15:14:33 -0800489 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800490 }
491
492 mCore->mIsAbandoned = true;
493 mCore->mConsumerListener = NULL;
494 mCore->mQueue.clear();
495 mCore->freeAllBuffersLocked();
496 mCore->mDequeueCondition.broadcast();
497 return NO_ERROR;
498}
499
Dan Stozafebd4f42014-04-09 16:14:51 -0700500status_t BufferQueueConsumer::getReleasedBuffers(uint64_t *outSlotMask) {
Dan Stoza289ade12014-02-28 11:17:17 -0800501 ATRACE_CALL();
502
503 if (outSlotMask == NULL) {
504 BQ_LOGE("getReleasedBuffers: outSlotMask may not be NULL");
505 return BAD_VALUE;
506 }
507
508 Mutex::Autolock lock(mCore->mMutex);
509
510 if (mCore->mIsAbandoned) {
511 BQ_LOGE("getReleasedBuffers: BufferQueue has been abandoned");
512 return NO_INIT;
513 }
514
Dan Stozafebd4f42014-04-09 16:14:51 -0700515 uint64_t mask = 0;
Dan Stoza3e96f192014-03-03 10:16:19 -0800516 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
Dan Stoza289ade12014-02-28 11:17:17 -0800517 if (!mSlots[s].mAcquireCalled) {
Dan Stozafebd4f42014-04-09 16:14:51 -0700518 mask |= (1ULL << s);
Dan Stoza289ade12014-02-28 11:17:17 -0800519 }
520 }
521
522 // Remove from the mask queued buffers for which acquire has been called,
523 // since the consumer will not receive their buffer addresses and so must
524 // retain their cached information
525 BufferQueueCore::Fifo::iterator current(mCore->mQueue.begin());
526 while (current != mCore->mQueue.end()) {
527 if (current->mAcquireCalled) {
Dan Stozafebd4f42014-04-09 16:14:51 -0700528 mask &= ~(1ULL << current->mSlot);
Dan Stoza289ade12014-02-28 11:17:17 -0800529 }
530 ++current;
531 }
532
Dan Stozafebd4f42014-04-09 16:14:51 -0700533 BQ_LOGV("getReleasedBuffers: returning mask %#" PRIx64, mask);
Dan Stoza289ade12014-02-28 11:17:17 -0800534 *outSlotMask = mask;
535 return NO_ERROR;
536}
537
538status_t BufferQueueConsumer::setDefaultBufferSize(uint32_t width,
539 uint32_t height) {
540 ATRACE_CALL();
541
542 if (width == 0 || height == 0) {
543 BQ_LOGV("setDefaultBufferSize: dimensions cannot be 0 (width=%u "
544 "height=%u)", width, height);
545 return BAD_VALUE;
546 }
547
548 BQ_LOGV("setDefaultBufferSize: width=%u height=%u", width, height);
549
550 Mutex::Autolock lock(mCore->mMutex);
551 mCore->mDefaultWidth = width;
552 mCore->mDefaultHeight = height;
553 return NO_ERROR;
554}
555
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700556status_t BufferQueueConsumer::setMaxBufferCount(int bufferCount) {
Dan Stoza289ade12014-02-28 11:17:17 -0800557 ATRACE_CALL();
Dan Stoza289ade12014-02-28 11:17:17 -0800558
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700559 if (bufferCount < 1 || bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
560 BQ_LOGE("setMaxBufferCount: invalid count %d", bufferCount);
561 return BAD_VALUE;
562 }
Dan Stoza289ade12014-02-28 11:17:17 -0800563
564 Mutex::Autolock lock(mCore->mMutex);
565
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700566 if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
567 BQ_LOGE("setMaxBufferCount: producer is already connected");
Dan Stoza289ade12014-02-28 11:17:17 -0800568 return INVALID_OPERATION;
569 }
570
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700571 if (bufferCount < mCore->mMaxAcquiredBufferCount) {
572 BQ_LOGE("setMaxBufferCount: invalid buffer count (%d) less than"
573 "mMaxAcquiredBufferCount (%d)", bufferCount,
574 mCore->mMaxAcquiredBufferCount);
575 return BAD_VALUE;
576 }
577
578 mCore->mMaxBufferCount = bufferCount;
Dan Stoza289ade12014-02-28 11:17:17 -0800579 return NO_ERROR;
580}
581
582status_t BufferQueueConsumer::setMaxAcquiredBufferCount(
583 int maxAcquiredBuffers) {
584 ATRACE_CALL();
585
586 if (maxAcquiredBuffers < 1 ||
587 maxAcquiredBuffers > BufferQueueCore::MAX_MAX_ACQUIRED_BUFFERS) {
588 BQ_LOGE("setMaxAcquiredBufferCount: invalid count %d",
589 maxAcquiredBuffers);
590 return BAD_VALUE;
591 }
592
593 Mutex::Autolock lock(mCore->mMutex);
594
595 if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
596 BQ_LOGE("setMaxAcquiredBufferCount: producer is already connected");
597 return INVALID_OPERATION;
598 }
599
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700600 if ((maxAcquiredBuffers + mCore->mMaxDequeuedBufferCount +
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700601 (mCore->mAsyncMode || mCore->mDequeueBufferCannotBlock ? 1 : 0)) >
602 mCore->mMaxBufferCount) {
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700603 BQ_LOGE("setMaxAcquiredBufferCount: %d acquired buffers would exceed "
604 "the maxBufferCount (%d) (maxDequeued %d async %d)",
605 maxAcquiredBuffers, mCore->mMaxBufferCount,
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700606 mCore->mMaxDequeuedBufferCount, mCore->mAsyncMode ||
607 mCore->mDequeueBufferCannotBlock);
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700608 return BAD_VALUE;
609 }
610
Dan Stoza289ade12014-02-28 11:17:17 -0800611 BQ_LOGV("setMaxAcquiredBufferCount: %d", maxAcquiredBuffers);
612 mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers;
613 return NO_ERROR;
614}
615
616void BufferQueueConsumer::setConsumerName(const String8& name) {
617 ATRACE_CALL();
618 BQ_LOGV("setConsumerName: '%s'", name.string());
619 Mutex::Autolock lock(mCore->mMutex);
620 mCore->mConsumerName = name;
621 mConsumerName = name;
622}
623
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800624status_t BufferQueueConsumer::setDefaultBufferFormat(PixelFormat defaultFormat) {
Dan Stoza289ade12014-02-28 11:17:17 -0800625 ATRACE_CALL();
626 BQ_LOGV("setDefaultBufferFormat: %u", defaultFormat);
627 Mutex::Autolock lock(mCore->mMutex);
628 mCore->mDefaultBufferFormat = defaultFormat;
629 return NO_ERROR;
630}
631
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800632status_t BufferQueueConsumer::setDefaultBufferDataSpace(
633 android_dataspace defaultDataSpace) {
634 ATRACE_CALL();
635 BQ_LOGV("setDefaultBufferDataSpace: %u", defaultDataSpace);
636 Mutex::Autolock lock(mCore->mMutex);
637 mCore->mDefaultBufferDataSpace = defaultDataSpace;
638 return NO_ERROR;
639}
640
Dan Stoza289ade12014-02-28 11:17:17 -0800641status_t BufferQueueConsumer::setConsumerUsageBits(uint32_t usage) {
642 ATRACE_CALL();
643 BQ_LOGV("setConsumerUsageBits: %#x", usage);
644 Mutex::Autolock lock(mCore->mMutex);
645 mCore->mConsumerUsageBits = usage;
646 return NO_ERROR;
647}
648
649status_t BufferQueueConsumer::setTransformHint(uint32_t hint) {
650 ATRACE_CALL();
651 BQ_LOGV("setTransformHint: %#x", hint);
652 Mutex::Autolock lock(mCore->mMutex);
653 mCore->mTransformHint = hint;
654 return NO_ERROR;
655}
656
Jesse Hall399184a2014-03-03 15:42:54 -0800657sp<NativeHandle> BufferQueueConsumer::getSidebandStream() const {
658 return mCore->mSidebandStream;
659}
660
Dan Stoza289ade12014-02-28 11:17:17 -0800661void BufferQueueConsumer::dump(String8& result, const char* prefix) const {
662 mCore->dump(result, prefix);
663}
664
665} // namespace android