blob: c48f23728c1621ee76fef65384763596e79ac3ef [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 "BufferQueueProducer"
20#define ATRACE_TAG ATRACE_TAG_GRAPHICS
21//#define LOG_NDEBUG 0
22
Dan Stoza289ade12014-02-28 11:17:17 -080023#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>
Dan Stozaf0eaf252014-03-21 13:05:51 -070030#include <gui/IProducerListener.h>
Dan Stoza289ade12014-02-28 11:17:17 -080031
32#include <utils/Log.h>
33#include <utils/Trace.h>
34
35namespace android {
36
37BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core) :
38 mCore(core),
39 mSlots(core->mSlots),
Ruben Brunk1681d952014-06-27 15:51:55 -070040 mConsumerName(),
Eric Penner99a0afb2014-09-30 11:28:30 -070041 mStickyTransform(0),
Dan Stoza8dc55392014-11-04 11:37:46 -080042 mLastQueueBufferFence(Fence::NO_FENCE),
43 mCallbackMutex(),
44 mNextCallbackTicket(0),
45 mCurrentCallbackTicket(0),
Dan Stoza127fc632015-06-30 13:43:32 -070046 mCallbackCondition(),
47 mDequeueTimeout(-1) {}
Dan Stoza289ade12014-02-28 11:17:17 -080048
49BufferQueueProducer::~BufferQueueProducer() {}
50
51status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
52 ATRACE_CALL();
53 BQ_LOGV("requestBuffer: slot %d", slot);
54 Mutex::Autolock lock(mCore->mMutex);
55
56 if (mCore->mIsAbandoned) {
57 BQ_LOGE("requestBuffer: BufferQueue has been abandoned");
58 return NO_INIT;
59 }
60
Pablo Ceballos583b1b32015-09-03 18:23:52 -070061 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
62 BQ_LOGE("requestBuffer: BufferQueue has no connected producer");
63 return NO_INIT;
64 }
65
Dan Stoza3e96f192014-03-03 10:16:19 -080066 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
Dan Stoza289ade12014-02-28 11:17:17 -080067 BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)",
Dan Stoza3e96f192014-03-03 10:16:19 -080068 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
Dan Stoza289ade12014-02-28 11:17:17 -080069 return BAD_VALUE;
Pablo Ceballosccdfd602015-10-07 15:05:45 -070070 } else if (!mSlots[slot].mBufferState.isDequeued()) {
Dan Stoza289ade12014-02-28 11:17:17 -080071 BQ_LOGE("requestBuffer: slot %d is not owned by the producer "
Pablo Ceballosccdfd602015-10-07 15:05:45 -070072 "(state = %s)", slot, mSlots[slot].mBufferState.string());
Dan Stoza289ade12014-02-28 11:17:17 -080073 return BAD_VALUE;
74 }
75
76 mSlots[slot].mRequestBufferCalled = true;
77 *buf = mSlots[slot].mGraphicBuffer;
78 return NO_ERROR;
79}
80
Pablo Ceballosfa455352015-08-12 17:47:47 -070081status_t BufferQueueProducer::setMaxDequeuedBufferCount(
82 int maxDequeuedBuffers) {
83 ATRACE_CALL();
84 BQ_LOGV("setMaxDequeuedBufferCount: maxDequeuedBuffers = %d",
85 maxDequeuedBuffers);
86
87 sp<IConsumerListener> listener;
88 { // Autolock scope
89 Mutex::Autolock lock(mCore->mMutex);
90 mCore->waitWhileAllocatingLocked();
91
92 if (mCore->mIsAbandoned) {
93 BQ_LOGE("setMaxDequeuedBufferCount: BufferQueue has been "
94 "abandoned");
95 return NO_INIT;
96 }
97
98 // There must be no dequeued buffers when changing the buffer count.
99 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700100 if (mSlots[s].mBufferState.isDequeued()) {
Pablo Ceballosfa455352015-08-12 17:47:47 -0700101 BQ_LOGE("setMaxDequeuedBufferCount: buffer owned by producer");
102 return BAD_VALUE;
103 }
104 }
105
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700106 int bufferCount = mCore->getMinUndequeuedBufferCountLocked();
Pablo Ceballosfa455352015-08-12 17:47:47 -0700107 bufferCount += maxDequeuedBuffers;
108
109 if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
110 BQ_LOGE("setMaxDequeuedBufferCount: bufferCount %d too large "
111 "(max %d)", bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
112 return BAD_VALUE;
113 }
114
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700115 const int minBufferSlots = mCore->getMinMaxBufferCountLocked();
Pablo Ceballosfa455352015-08-12 17:47:47 -0700116 if (bufferCount < minBufferSlots) {
117 BQ_LOGE("setMaxDequeuedBufferCount: requested buffer count %d is "
118 "less than minimum %d", bufferCount, minBufferSlots);
119 return BAD_VALUE;
120 }
121
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700122 if (bufferCount > mCore->mMaxBufferCount) {
123 BQ_LOGE("setMaxDequeuedBufferCount: %d dequeued buffers would "
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700124 "exceed the maxBufferCount (%d) (maxAcquired %d async %d "
125 "mDequeuedBufferCannotBlock %d)", maxDequeuedBuffers,
126 mCore->mMaxBufferCount, mCore->mMaxAcquiredBufferCount,
127 mCore->mAsyncMode, mCore->mDequeueBufferCannotBlock);
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700128 return BAD_VALUE;
129 }
130
Pablo Ceballosfa455352015-08-12 17:47:47 -0700131 // Here we are guaranteed that the producer doesn't have any dequeued
132 // buffers and will release all of its buffer references. We don't
133 // clear the queue, however, so that currently queued buffers still
134 // get displayed.
135 mCore->freeAllBuffersLocked();
136 mCore->mMaxDequeuedBufferCount = maxDequeuedBuffers;
Pablo Ceballosfa455352015-08-12 17:47:47 -0700137 mCore->mDequeueCondition.broadcast();
138 listener = mCore->mConsumerListener;
139 } // Autolock scope
140
141 // Call back without lock held
142 if (listener != NULL) {
143 listener->onBuffersReleased();
144 }
145
146 return NO_ERROR;
147}
148
149status_t BufferQueueProducer::setAsyncMode(bool async) {
150 ATRACE_CALL();
151 BQ_LOGV("setAsyncMode: async = %d", async);
152
153 sp<IConsumerListener> listener;
154 { // Autolock scope
155 Mutex::Autolock lock(mCore->mMutex);
156 mCore->waitWhileAllocatingLocked();
157
158 if (mCore->mIsAbandoned) {
159 BQ_LOGE("setAsyncMode: BufferQueue has been abandoned");
160 return NO_INIT;
161 }
162
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700163 if ((mCore->mMaxAcquiredBufferCount + mCore->mMaxDequeuedBufferCount +
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700164 (async || mCore->mDequeueBufferCannotBlock ? 1 : 0)) >
165 mCore->mMaxBufferCount) {
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700166 BQ_LOGE("setAsyncMode(%d): this call would cause the "
167 "maxBufferCount (%d) to be exceeded (maxAcquired %d "
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700168 "maxDequeued %d mDequeueBufferCannotBlock %d)", async,
169 mCore->mMaxBufferCount, mCore->mMaxAcquiredBufferCount,
170 mCore->mMaxDequeuedBufferCount,
171 mCore->mDequeueBufferCannotBlock);
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700172 return BAD_VALUE;
173 }
174
Pablo Ceballosfa455352015-08-12 17:47:47 -0700175 mCore->mAsyncMode = async;
176 mCore->mDequeueCondition.broadcast();
177 listener = mCore->mConsumerListener;
178 } // Autolock scope
179
180 // Call back without lock held
181 if (listener != NULL) {
182 listener->onBuffersReleased();
183 }
184 return NO_ERROR;
185}
186
Dan Stoza9f3053d2014-03-06 15:14:33 -0800187status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller,
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700188 int* found, status_t* returnFlags) const {
Dan Stoza9f3053d2014-03-06 15:14:33 -0800189 bool tryAgain = true;
190 while (tryAgain) {
191 if (mCore->mIsAbandoned) {
192 BQ_LOGE("%s: BufferQueue has been abandoned", caller);
193 return NO_INIT;
194 }
195
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700196 const int maxBufferCount = mCore->getMaxBufferCountLocked();
Dan Stoza9f3053d2014-03-06 15:14:33 -0800197
198 // Free up any buffers that are in slots beyond the max buffer count
199 for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700200 assert(mSlots[s].mBufferState.isFree());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800201 if (mSlots[s].mGraphicBuffer != NULL) {
202 mCore->freeBufferLocked(s);
203 *returnFlags |= RELEASE_ALL_BUFFERS;
204 }
205 }
206
Dan Stoza9f3053d2014-03-06 15:14:33 -0800207 int dequeuedCount = 0;
208 int acquiredCount = 0;
209 for (int s = 0; s < maxBufferCount; ++s) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700210 if (mSlots[s].mBufferState.isDequeued()) {
211 ++dequeuedCount;
212 }
213 if (mSlots[s].mBufferState.isAcquired()) {
214 ++acquiredCount;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800215 }
216 }
217
Pablo Ceballose5b755a2015-08-13 16:18:19 -0700218 // Producers are not allowed to dequeue more than
219 // mMaxDequeuedBufferCount buffers.
220 // This check is only done if a buffer has already been queued
221 if (mCore->mBufferHasBeenQueued &&
222 dequeuedCount >= mCore->mMaxDequeuedBufferCount) {
223 BQ_LOGE("%s: attempting to exceed the max dequeued buffer count "
224 "(%d)", caller, mCore->mMaxDequeuedBufferCount);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800225 return INVALID_OPERATION;
226 }
227
Dan Stoza0de7ea72015-04-23 13:20:51 -0700228 *found = BufferQueueCore::INVALID_BUFFER_SLOT;
229
Dan Stozaae3c3682014-04-18 15:43:35 -0700230 // If we disconnect and reconnect quickly, we can be in a state where
231 // our slots are empty but we have many buffers in the queue. This can
232 // cause us to run out of memory if we outrun the consumer. Wait here if
233 // it looks like we have too many buffers queued up.
Mark Salyzyn8f515ce2014-06-09 14:32:04 -0700234 bool tooManyBuffers = mCore->mQueue.size()
235 > static_cast<size_t>(maxBufferCount);
Dan Stozaae3c3682014-04-18 15:43:35 -0700236 if (tooManyBuffers) {
Mark Salyzyn8f515ce2014-06-09 14:32:04 -0700237 BQ_LOGV("%s: queue size is %zu, waiting", caller,
Dan Stozaae3c3682014-04-18 15:43:35 -0700238 mCore->mQueue.size());
Dan Stoza0de7ea72015-04-23 13:20:51 -0700239 } else {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700240 // If in single buffer mode and a shared buffer exists, always
241 // return it.
242 if (mCore->mSingleBufferMode && mCore->mSingleBufferSlot !=
243 BufferQueueCore::INVALID_BUFFER_SLOT) {
244 *found = mCore->mSingleBufferSlot;
245 } else if (!mCore->mFreeBuffers.empty()) {
Dan Stoza0de7ea72015-04-23 13:20:51 -0700246 auto slot = mCore->mFreeBuffers.begin();
247 *found = *slot;
248 mCore->mFreeBuffers.erase(slot);
Dan Stoza9de72932015-04-16 17:28:43 -0700249 } else if (mCore->mAllowAllocation && !mCore->mFreeSlots.empty()) {
Dan Stoza0de7ea72015-04-23 13:20:51 -0700250 auto slot = mCore->mFreeSlots.begin();
251 // Only return free slots up to the max buffer count
252 if (*slot < maxBufferCount) {
253 *found = *slot;
254 mCore->mFreeSlots.erase(slot);
255 }
256 }
Dan Stozaae3c3682014-04-18 15:43:35 -0700257 }
258
259 // If no buffer is found, or if the queue has too many buffers
260 // outstanding, wait for a buffer to be acquired or released, or for the
261 // max buffer count to change.
262 tryAgain = (*found == BufferQueueCore::INVALID_BUFFER_SLOT) ||
263 tooManyBuffers;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800264 if (tryAgain) {
265 // Return an error if we're in non-blocking mode (producer and
266 // consumer are controlled by the application).
267 // However, the consumer is allowed to briefly acquire an extra
268 // buffer (which could cause us to have to wait here), which is
269 // okay, since it is only used to implement an atomic acquire +
270 // release (e.g., in GLConsumer::updateTexImage())
Pablo Ceballosfa455352015-08-12 17:47:47 -0700271 if ((mCore->mDequeueBufferCannotBlock || mCore->mAsyncMode) &&
Dan Stoza9f3053d2014-03-06 15:14:33 -0800272 (acquiredCount <= mCore->mMaxAcquiredBufferCount)) {
273 return WOULD_BLOCK;
274 }
Dan Stoza127fc632015-06-30 13:43:32 -0700275 if (mDequeueTimeout >= 0) {
276 status_t result = mCore->mDequeueCondition.waitRelative(
277 mCore->mMutex, mDequeueTimeout);
278 if (result == TIMED_OUT) {
279 return result;
280 }
281 } else {
282 mCore->mDequeueCondition.wait(mCore->mMutex);
283 }
Dan Stoza9f3053d2014-03-06 15:14:33 -0800284 }
285 } // while (tryAgain)
286
287 return NO_ERROR;
288}
289
Dan Stoza289ade12014-02-28 11:17:17 -0800290status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700291 sp<android::Fence> *outFence, uint32_t width, uint32_t height,
292 PixelFormat format, uint32_t usage) {
Dan Stoza289ade12014-02-28 11:17:17 -0800293 ATRACE_CALL();
294 { // Autolock scope
295 Mutex::Autolock lock(mCore->mMutex);
296 mConsumerName = mCore->mConsumerName;
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700297
298 if (mCore->mIsAbandoned) {
299 BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
300 return NO_INIT;
301 }
302
303 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
304 BQ_LOGE("dequeueBuffer: BufferQueue has no connected producer");
305 return NO_INIT;
306 }
Dan Stoza289ade12014-02-28 11:17:17 -0800307 } // Autolock scope
308
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700309 BQ_LOGV("dequeueBuffer: w=%u h=%u format=%#x, usage=%#x", width, height,
310 format, usage);
Dan Stoza289ade12014-02-28 11:17:17 -0800311
312 if ((width && !height) || (!width && height)) {
313 BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height);
314 return BAD_VALUE;
315 }
316
317 status_t returnFlags = NO_ERROR;
318 EGLDisplay eglDisplay = EGL_NO_DISPLAY;
319 EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800320 bool attachedByConsumer = false;
Dan Stoza289ade12014-02-28 11:17:17 -0800321
322 { // Autolock scope
323 Mutex::Autolock lock(mCore->mMutex);
Antoine Labour78014f32014-07-15 21:17:03 -0700324 mCore->waitWhileAllocatingLocked();
Dan Stoza289ade12014-02-28 11:17:17 -0800325
326 if (format == 0) {
327 format = mCore->mDefaultBufferFormat;
328 }
329
330 // Enable the usage bits the consumer requested
331 usage |= mCore->mConsumerUsageBits;
332
Dan Stoza9de72932015-04-16 17:28:43 -0700333 const bool useDefaultSize = !width && !height;
334 if (useDefaultSize) {
335 width = mCore->mDefaultWidth;
336 height = mCore->mDefaultHeight;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800337 }
Dan Stoza289ade12014-02-28 11:17:17 -0800338
Dan Stoza9de72932015-04-16 17:28:43 -0700339 int found = BufferItem::INVALID_BUFFER_SLOT;
340 while (found == BufferItem::INVALID_BUFFER_SLOT) {
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700341 status_t status = waitForFreeSlotThenRelock("dequeueBuffer", &found,
342 &returnFlags);
Dan Stoza9de72932015-04-16 17:28:43 -0700343 if (status != NO_ERROR) {
344 return status;
345 }
346
347 // This should not happen
348 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
349 BQ_LOGE("dequeueBuffer: no available buffer slots");
350 return -EBUSY;
351 }
352
353 const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
354
355 // If we are not allowed to allocate new buffers,
356 // waitForFreeSlotThenRelock must have returned a slot containing a
357 // buffer. If this buffer would require reallocation to meet the
358 // requested attributes, we free it and attempt to get another one.
359 if (!mCore->mAllowAllocation) {
360 if (buffer->needsReallocation(width, height, format, usage)) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700361 if (mCore->mSingleBufferMode &&
362 mCore->mSingleBufferSlot == found) {
363 BQ_LOGE("dequeueBuffer: cannot re-allocate a shared"
364 "buffer");
365 return BAD_VALUE;
366 }
367
Dan Stoza9de72932015-04-16 17:28:43 -0700368 mCore->freeBufferLocked(found);
369 found = BufferItem::INVALID_BUFFER_SLOT;
370 continue;
371 }
372 }
Dan Stoza289ade12014-02-28 11:17:17 -0800373 }
374
375 *outSlot = found;
376 ATRACE_BUFFER_INDEX(found);
377
Dan Stoza9f3053d2014-03-06 15:14:33 -0800378 attachedByConsumer = mSlots[found].mAttachedByConsumer;
379
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700380 mSlots[found].mBufferState.dequeue();
381
382 // If single buffer mode has just been enabled, cache the slot of the
383 // first buffer that is dequeued and mark it as the shared buffer.
384 if (mCore->mSingleBufferMode && mCore->mSingleBufferSlot ==
385 BufferQueueCore::INVALID_BUFFER_SLOT) {
386 mCore->mSingleBufferSlot = found;
387 mSlots[found].mBufferState.mShared = true;
388 }
Dan Stoza289ade12014-02-28 11:17:17 -0800389
390 const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
391 if ((buffer == NULL) ||
Dan Stoza9de72932015-04-16 17:28:43 -0700392 buffer->needsReallocation(width, height, format, usage))
Dan Stoza289ade12014-02-28 11:17:17 -0800393 {
394 mSlots[found].mAcquireCalled = false;
395 mSlots[found].mGraphicBuffer = NULL;
396 mSlots[found].mRequestBufferCalled = false;
397 mSlots[found].mEglDisplay = EGL_NO_DISPLAY;
398 mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
399 mSlots[found].mFence = Fence::NO_FENCE;
Dan Stoza4afd8b62015-02-25 16:49:08 -0800400 mCore->mBufferAge = 0;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700401 mCore->mIsAllocating = true;
Dan Stoza289ade12014-02-28 11:17:17 -0800402
403 returnFlags |= BUFFER_NEEDS_REALLOCATION;
Dan Stoza4afd8b62015-02-25 16:49:08 -0800404 } else {
405 // We add 1 because that will be the frame number when this buffer
406 // is queued
407 mCore->mBufferAge =
408 mCore->mFrameCounter + 1 - mSlots[found].mFrameNumber;
Dan Stoza289ade12014-02-28 11:17:17 -0800409 }
410
Dan Stoza800b41a2015-04-28 14:20:04 -0700411 BQ_LOGV("dequeueBuffer: setting buffer age to %" PRIu64,
412 mCore->mBufferAge);
Dan Stoza4afd8b62015-02-25 16:49:08 -0800413
Dan Stoza289ade12014-02-28 11:17:17 -0800414 if (CC_UNLIKELY(mSlots[found].mFence == NULL)) {
415 BQ_LOGE("dequeueBuffer: about to return a NULL fence - "
416 "slot=%d w=%d h=%d format=%u",
417 found, buffer->width, buffer->height, buffer->format);
418 }
419
420 eglDisplay = mSlots[found].mEglDisplay;
421 eglFence = mSlots[found].mEglFence;
422 *outFence = mSlots[found].mFence;
423 mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
424 mSlots[found].mFence = Fence::NO_FENCE;
Dan Stoza0de7ea72015-04-23 13:20:51 -0700425
426 mCore->validateConsistencyLocked();
Dan Stoza289ade12014-02-28 11:17:17 -0800427 } // Autolock scope
428
429 if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
430 status_t error;
Dan Stoza29a3e902014-06-20 13:13:57 -0700431 BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
Dan Stoza289ade12014-02-28 11:17:17 -0800432 sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800433 width, height, format, usage, &error));
Dan Stoza289ade12014-02-28 11:17:17 -0800434 { // Autolock scope
435 Mutex::Autolock lock(mCore->mMutex);
436
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700437 if (graphicBuffer != NULL && !mCore->mIsAbandoned) {
438 graphicBuffer->setGenerationNumber(mCore->mGenerationNumber);
439 mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
440 }
441
442 mCore->mIsAllocating = false;
443 mCore->mIsAllocatingCondition.broadcast();
444
445 if (graphicBuffer == NULL) {
446 BQ_LOGE("dequeueBuffer: createGraphicBuffer failed");
447 return error;
448 }
449
Dan Stoza289ade12014-02-28 11:17:17 -0800450 if (mCore->mIsAbandoned) {
451 BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
452 return NO_INIT;
453 }
Dan Stoza289ade12014-02-28 11:17:17 -0800454 } // Autolock scope
455 }
456
Dan Stoza9f3053d2014-03-06 15:14:33 -0800457 if (attachedByConsumer) {
458 returnFlags |= BUFFER_NEEDS_REALLOCATION;
459 }
460
Dan Stoza289ade12014-02-28 11:17:17 -0800461 if (eglFence != EGL_NO_SYNC_KHR) {
462 EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, 0,
463 1000000000);
464 // If something goes wrong, log the error, but return the buffer without
465 // synchronizing access to it. It's too late at this point to abort the
466 // dequeue operation.
467 if (result == EGL_FALSE) {
468 BQ_LOGE("dequeueBuffer: error %#x waiting for fence",
469 eglGetError());
470 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
471 BQ_LOGE("dequeueBuffer: timeout waiting for fence");
472 }
473 eglDestroySyncKHR(eglDisplay, eglFence);
474 }
475
Mark Salyzyn8f515ce2014-06-09 14:32:04 -0700476 BQ_LOGV("dequeueBuffer: returning slot=%d/%" PRIu64 " buf=%p flags=%#x",
477 *outSlot,
Dan Stoza289ade12014-02-28 11:17:17 -0800478 mSlots[*outSlot].mFrameNumber,
479 mSlots[*outSlot].mGraphicBuffer->handle, returnFlags);
480
481 return returnFlags;
482}
483
Dan Stoza9f3053d2014-03-06 15:14:33 -0800484status_t BufferQueueProducer::detachBuffer(int slot) {
485 ATRACE_CALL();
486 ATRACE_BUFFER_INDEX(slot);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700487 BQ_LOGV("detachBuffer: slot %d", slot);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800488 Mutex::Autolock lock(mCore->mMutex);
489
490 if (mCore->mIsAbandoned) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700491 BQ_LOGE("detachBuffer: BufferQueue has been abandoned");
Dan Stoza9f3053d2014-03-06 15:14:33 -0800492 return NO_INIT;
493 }
494
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700495 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700496 BQ_LOGE("detachBuffer: BufferQueue has no connected producer");
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700497 return NO_INIT;
498 }
499
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700500 if (mCore->mSingleBufferMode) {
501 BQ_LOGE("detachBuffer: cannot detach a buffer in single buffer"
502 "mode");
503 return BAD_VALUE;
504 }
505
Dan Stoza9f3053d2014-03-06 15:14:33 -0800506 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700507 BQ_LOGE("detachBuffer: slot index %d out of range [0, %d)",
Dan Stoza9f3053d2014-03-06 15:14:33 -0800508 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
509 return BAD_VALUE;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700510 } else if (!mSlots[slot].mBufferState.isDequeued()) {
511 BQ_LOGE("detachBuffer: slot %d is not owned by the producer "
512 "(state = %s)", slot, mSlots[slot].mBufferState.string());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800513 return BAD_VALUE;
514 } else if (!mSlots[slot].mRequestBufferCalled) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700515 BQ_LOGE("detachBuffer: buffer in slot %d has not been requested",
Dan Stoza9f3053d2014-03-06 15:14:33 -0800516 slot);
517 return BAD_VALUE;
518 }
519
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700520 mSlots[slot].mBufferState.detachProducer();
Dan Stoza9f3053d2014-03-06 15:14:33 -0800521 mCore->freeBufferLocked(slot);
522 mCore->mDequeueCondition.broadcast();
Dan Stoza0de7ea72015-04-23 13:20:51 -0700523 mCore->validateConsistencyLocked();
Dan Stoza9f3053d2014-03-06 15:14:33 -0800524
525 return NO_ERROR;
526}
527
Dan Stozad9822a32014-03-28 15:25:31 -0700528status_t BufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
529 sp<Fence>* outFence) {
530 ATRACE_CALL();
531
532 if (outBuffer == NULL) {
533 BQ_LOGE("detachNextBuffer: outBuffer must not be NULL");
534 return BAD_VALUE;
535 } else if (outFence == NULL) {
536 BQ_LOGE("detachNextBuffer: outFence must not be NULL");
537 return BAD_VALUE;
538 }
539
540 Mutex::Autolock lock(mCore->mMutex);
541
542 if (mCore->mIsAbandoned) {
543 BQ_LOGE("detachNextBuffer: BufferQueue has been abandoned");
544 return NO_INIT;
545 }
546
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700547 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
548 BQ_LOGE("detachNextBuffer: BufferQueue has no connected producer");
549 return NO_INIT;
550 }
551
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700552 if (mCore->mSingleBufferMode) {
553 BQ_LOGE("detachNextBuffer: cannot detach a buffer in single buffer"
554 "mode");
555 return BAD_VALUE;
556 }
557
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700558 mCore->waitWhileAllocatingLocked();
559
Dan Stoza0de7ea72015-04-23 13:20:51 -0700560 if (mCore->mFreeBuffers.empty()) {
Dan Stoza1fc9cc22015-04-22 18:57:39 +0000561 return NO_MEMORY;
562 }
Dan Stoza8dddc992015-04-16 15:39:18 -0700563
Dan Stoza0de7ea72015-04-23 13:20:51 -0700564 int found = mCore->mFreeBuffers.front();
565 mCore->mFreeBuffers.remove(found);
566
Dan Stozad9822a32014-03-28 15:25:31 -0700567 BQ_LOGV("detachNextBuffer detached slot %d", found);
568
569 *outBuffer = mSlots[found].mGraphicBuffer;
570 *outFence = mSlots[found].mFence;
571 mCore->freeBufferLocked(found);
Dan Stoza0de7ea72015-04-23 13:20:51 -0700572 mCore->validateConsistencyLocked();
Dan Stozad9822a32014-03-28 15:25:31 -0700573
574 return NO_ERROR;
575}
576
Dan Stoza9f3053d2014-03-06 15:14:33 -0800577status_t BufferQueueProducer::attachBuffer(int* outSlot,
578 const sp<android::GraphicBuffer>& buffer) {
579 ATRACE_CALL();
580
581 if (outSlot == NULL) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700582 BQ_LOGE("attachBuffer: outSlot must not be NULL");
Dan Stoza9f3053d2014-03-06 15:14:33 -0800583 return BAD_VALUE;
584 } else if (buffer == NULL) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700585 BQ_LOGE("attachBuffer: cannot attach NULL buffer");
Dan Stoza9f3053d2014-03-06 15:14:33 -0800586 return BAD_VALUE;
587 }
588
589 Mutex::Autolock lock(mCore->mMutex);
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700590
591 if (mCore->mIsAbandoned) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700592 BQ_LOGE("attachBuffer: BufferQueue has been abandoned");
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700593 return NO_INIT;
594 }
595
596 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700597 BQ_LOGE("attachBuffer: BufferQueue has no connected producer");
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700598 return NO_INIT;
599 }
Dan Stoza9f3053d2014-03-06 15:14:33 -0800600
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700601 if (mCore->mSingleBufferMode) {
602 BQ_LOGE("attachBuffer: cannot atach a buffer in single buffer mode");
603 return BAD_VALUE;
604 }
605
Dan Stoza812ed062015-06-02 15:45:22 -0700606 if (buffer->getGenerationNumber() != mCore->mGenerationNumber) {
607 BQ_LOGE("attachBuffer: generation number mismatch [buffer %u] "
608 "[queue %u]", buffer->getGenerationNumber(),
609 mCore->mGenerationNumber);
610 return BAD_VALUE;
611 }
612
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700613 mCore->waitWhileAllocatingLocked();
614
Dan Stoza9f3053d2014-03-06 15:14:33 -0800615 status_t returnFlags = NO_ERROR;
616 int found;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700617 status_t status = waitForFreeSlotThenRelock("attachBuffer", &found,
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700618 &returnFlags);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800619 if (status != NO_ERROR) {
620 return status;
621 }
622
623 // This should not happen
624 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700625 BQ_LOGE("attachBuffer: no available buffer slots");
Dan Stoza9f3053d2014-03-06 15:14:33 -0800626 return -EBUSY;
627 }
628
629 *outSlot = found;
630 ATRACE_BUFFER_INDEX(*outSlot);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700631 BQ_LOGV("attachBuffer: returning slot %d flags=%#x",
Dan Stoza9f3053d2014-03-06 15:14:33 -0800632 *outSlot, returnFlags);
633
634 mSlots[*outSlot].mGraphicBuffer = buffer;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700635 mSlots[*outSlot].mBufferState.attachProducer();
Dan Stoza9f3053d2014-03-06 15:14:33 -0800636 mSlots[*outSlot].mEglFence = EGL_NO_SYNC_KHR;
637 mSlots[*outSlot].mFence = Fence::NO_FENCE;
Dan Stoza2443c792014-03-24 15:03:46 -0700638 mSlots[*outSlot].mRequestBufferCalled = true;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800639
Dan Stoza0de7ea72015-04-23 13:20:51 -0700640 mCore->validateConsistencyLocked();
641
Dan Stoza9f3053d2014-03-06 15:14:33 -0800642 return returnFlags;
643}
644
Dan Stoza289ade12014-02-28 11:17:17 -0800645status_t BufferQueueProducer::queueBuffer(int slot,
646 const QueueBufferInput &input, QueueBufferOutput *output) {
647 ATRACE_CALL();
648 ATRACE_BUFFER_INDEX(slot);
649
650 int64_t timestamp;
651 bool isAutoTimestamp;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800652 android_dataspace dataSpace;
Pablo Ceballos60d69222015-08-07 14:47:20 -0700653 Rect crop(Rect::EMPTY_RECT);
Dan Stoza289ade12014-02-28 11:17:17 -0800654 int scalingMode;
655 uint32_t transform;
Ruben Brunk1681d952014-06-27 15:51:55 -0700656 uint32_t stickyTransform;
Dan Stoza289ade12014-02-28 11:17:17 -0800657 sp<Fence> fence;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800658 input.deflate(&timestamp, &isAutoTimestamp, &dataSpace, &crop, &scalingMode,
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700659 &transform, &fence, &stickyTransform);
Dan Stoza5065a552015-03-17 16:23:42 -0700660 Region surfaceDamage = input.getSurfaceDamage();
Dan Stoza289ade12014-02-28 11:17:17 -0800661
662 if (fence == NULL) {
663 BQ_LOGE("queueBuffer: fence is NULL");
Jesse Hallde288fe2014-11-04 08:30:48 -0800664 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800665 }
666
667 switch (scalingMode) {
668 case NATIVE_WINDOW_SCALING_MODE_FREEZE:
669 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
670 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
671 case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
672 break;
673 default:
674 BQ_LOGE("queueBuffer: unknown scaling mode %d", scalingMode);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800675 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800676 }
677
Dan Stoza8dc55392014-11-04 11:37:46 -0800678 sp<IConsumerListener> frameAvailableListener;
679 sp<IConsumerListener> frameReplacedListener;
680 int callbackTicket = 0;
681 BufferItem item;
Dan Stoza289ade12014-02-28 11:17:17 -0800682 { // Autolock scope
683 Mutex::Autolock lock(mCore->mMutex);
684
685 if (mCore->mIsAbandoned) {
686 BQ_LOGE("queueBuffer: BufferQueue has been abandoned");
687 return NO_INIT;
688 }
689
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700690 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
691 BQ_LOGE("queueBuffer: BufferQueue has no connected producer");
692 return NO_INIT;
693 }
694
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700695 const int maxBufferCount = mCore->getMaxBufferCountLocked();
Dan Stoza289ade12014-02-28 11:17:17 -0800696
697 if (slot < 0 || slot >= maxBufferCount) {
698 BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)",
699 slot, maxBufferCount);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800700 return BAD_VALUE;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700701 } else if (!mSlots[slot].mBufferState.isDequeued()) {
Dan Stoza289ade12014-02-28 11:17:17 -0800702 BQ_LOGE("queueBuffer: slot %d is not owned by the producer "
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700703 "(state = %s)", slot, mSlots[slot].mBufferState.string());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800704 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800705 } else if (!mSlots[slot].mRequestBufferCalled) {
706 BQ_LOGE("queueBuffer: slot %d was queued without requesting "
707 "a buffer", slot);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800708 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800709 }
710
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800711 BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64 " dataSpace=%d"
Mark Salyzyn8f515ce2014-06-09 14:32:04 -0700712 " crop=[%d,%d,%d,%d] transform=%#x scale=%s",
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800713 slot, mCore->mFrameCounter + 1, timestamp, dataSpace,
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800714 crop.left, crop.top, crop.right, crop.bottom, transform,
715 BufferItem::scalingModeName(static_cast<uint32_t>(scalingMode)));
Dan Stoza289ade12014-02-28 11:17:17 -0800716
717 const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
718 Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
Pablo Ceballos60d69222015-08-07 14:47:20 -0700719 Rect croppedRect(Rect::EMPTY_RECT);
Dan Stoza289ade12014-02-28 11:17:17 -0800720 crop.intersect(bufferRect, &croppedRect);
721 if (croppedRect != crop) {
722 BQ_LOGE("queueBuffer: crop rect is not contained within the "
723 "buffer in slot %d", slot);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800724 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800725 }
726
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800727 // Override UNKNOWN dataspace with consumer default
728 if (dataSpace == HAL_DATASPACE_UNKNOWN) {
729 dataSpace = mCore->mDefaultBufferDataSpace;
730 }
731
Dan Stoza289ade12014-02-28 11:17:17 -0800732 mSlots[slot].mFence = fence;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700733 mSlots[slot].mBufferState.queue();
734
Dan Stoza289ade12014-02-28 11:17:17 -0800735 ++mCore->mFrameCounter;
736 mSlots[slot].mFrameNumber = mCore->mFrameCounter;
737
Dan Stoza289ade12014-02-28 11:17:17 -0800738 item.mAcquireCalled = mSlots[slot].mAcquireCalled;
739 item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
740 item.mCrop = crop;
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800741 item.mTransform = transform &
742 ~static_cast<uint32_t>(NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
Dan Stoza289ade12014-02-28 11:17:17 -0800743 item.mTransformToDisplayInverse =
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800744 (transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) != 0;
745 item.mScalingMode = static_cast<uint32_t>(scalingMode);
Dan Stoza289ade12014-02-28 11:17:17 -0800746 item.mTimestamp = timestamp;
747 item.mIsAutoTimestamp = isAutoTimestamp;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800748 item.mDataSpace = dataSpace;
Dan Stoza289ade12014-02-28 11:17:17 -0800749 item.mFrameNumber = mCore->mFrameCounter;
750 item.mSlot = slot;
751 item.mFence = fence;
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700752 item.mIsDroppable = mCore->mAsyncMode ||
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700753 mCore->mDequeueBufferCannotBlock ||
754 (mCore->mSingleBufferMode && mCore->mSingleBufferSlot == slot);
Dan Stoza5065a552015-03-17 16:23:42 -0700755 item.mSurfaceDamage = surfaceDamage;
Pablo Ceballos06312182015-10-07 16:32:12 -0700756 item.mSingleBufferMode = mCore->mSingleBufferMode;
757 item.mQueuedBuffer = true;
Dan Stoza289ade12014-02-28 11:17:17 -0800758
Ruben Brunk1681d952014-06-27 15:51:55 -0700759 mStickyTransform = stickyTransform;
760
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700761 // Cache the shared buffer data so that the BufferItem can be recreated.
762 if (mCore->mSingleBufferMode) {
763 mCore->mSingleBufferCache.crop = crop;
764 mCore->mSingleBufferCache.transform = transform;
765 mCore->mSingleBufferCache.scalingMode = static_cast<uint32_t>(
766 scalingMode);
767 mCore->mSingleBufferCache.dataspace = dataSpace;
768 }
769
Dan Stoza289ade12014-02-28 11:17:17 -0800770 if (mCore->mQueue.empty()) {
771 // When the queue is empty, we can ignore mDequeueBufferCannotBlock
772 // and simply queue this buffer
773 mCore->mQueue.push_back(item);
Dan Stoza8dc55392014-11-04 11:37:46 -0800774 frameAvailableListener = mCore->mConsumerListener;
Dan Stoza289ade12014-02-28 11:17:17 -0800775 } else {
776 // When the queue is not empty, we need to look at the front buffer
777 // state to see if we need to replace it
778 BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
779 if (front->mIsDroppable) {
780 // If the front queued buffer is still being tracked, we first
781 // mark it as freed
782 if (mCore->stillTracking(front)) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700783 mSlots[front->mSlot].mBufferState.freeQueued();
784
785 // After leaving single buffer mode, the shared buffer will
786 // still be around. Mark it as no longer shared if this
787 // operation causes it to be free.
788 if (!mCore->mSingleBufferMode &&
789 mSlots[front->mSlot].mBufferState.isFree()) {
790 mSlots[front->mSlot].mBufferState.mShared = false;
791 }
792 // Don't put the shared buffer on the free list.
793 if (!mSlots[front->mSlot].mBufferState.isShared()) {
794 mCore->mFreeBuffers.push_front(front->mSlot);
795 }
Dan Stoza289ade12014-02-28 11:17:17 -0800796 }
797 // Overwrite the droppable buffer with the incoming one
798 *front = item;
Dan Stoza8dc55392014-11-04 11:37:46 -0800799 frameReplacedListener = mCore->mConsumerListener;
Dan Stoza289ade12014-02-28 11:17:17 -0800800 } else {
801 mCore->mQueue.push_back(item);
Dan Stoza8dc55392014-11-04 11:37:46 -0800802 frameAvailableListener = mCore->mConsumerListener;
Dan Stoza289ade12014-02-28 11:17:17 -0800803 }
804 }
805
806 mCore->mBufferHasBeenQueued = true;
807 mCore->mDequeueCondition.broadcast();
808
809 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800810 mCore->mTransformHint,
811 static_cast<uint32_t>(mCore->mQueue.size()));
Dan Stoza289ade12014-02-28 11:17:17 -0800812
813 ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
Dan Stoza8dc55392014-11-04 11:37:46 -0800814
815 // Take a ticket for the callback functions
816 callbackTicket = mNextCallbackTicket++;
Dan Stoza0de7ea72015-04-23 13:20:51 -0700817
818 mCore->validateConsistencyLocked();
Dan Stoza289ade12014-02-28 11:17:17 -0800819 } // Autolock scope
820
Dan Stoza8dc55392014-11-04 11:37:46 -0800821 // Don't send the GraphicBuffer through the callback, and don't send
822 // the slot number, since the consumer shouldn't need it
823 item.mGraphicBuffer.clear();
824 item.mSlot = BufferItem::INVALID_BUFFER_SLOT;
825
826 // Call back without the main BufferQueue lock held, but with the callback
827 // lock held so we can ensure that callbacks occur in order
828 {
829 Mutex::Autolock lock(mCallbackMutex);
830 while (callbackTicket != mCurrentCallbackTicket) {
831 mCallbackCondition.wait(mCallbackMutex);
832 }
833
834 if (frameAvailableListener != NULL) {
835 frameAvailableListener->onFrameAvailable(item);
836 } else if (frameReplacedListener != NULL) {
837 frameReplacedListener->onFrameReplaced(item);
838 }
839
840 ++mCurrentCallbackTicket;
841 mCallbackCondition.broadcast();
Dan Stoza289ade12014-02-28 11:17:17 -0800842 }
843
Christian Poetzsch82fbb122015-12-07 13:36:22 +0000844 // Wait without lock held
845 if (mCore->mConnectedApi == NATIVE_WINDOW_API_EGL) {
846 // Waiting here allows for two full buffers to be queued but not a
847 // third. In the event that frames take varying time, this makes a
848 // small trade-off in favor of latency rather than throughput.
849 mLastQueueBufferFence->waitForever("Throttling EGL Production");
850 mLastQueueBufferFence = fence;
851 }
852
Dan Stoza289ade12014-02-28 11:17:17 -0800853 return NO_ERROR;
854}
855
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700856status_t BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
Dan Stoza289ade12014-02-28 11:17:17 -0800857 ATRACE_CALL();
858 BQ_LOGV("cancelBuffer: slot %d", slot);
859 Mutex::Autolock lock(mCore->mMutex);
860
861 if (mCore->mIsAbandoned) {
862 BQ_LOGE("cancelBuffer: BufferQueue has been abandoned");
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700863 return NO_INIT;
864 }
865
866 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
867 BQ_LOGE("cancelBuffer: BufferQueue has no connected producer");
868 return NO_INIT;
Dan Stoza289ade12014-02-28 11:17:17 -0800869 }
870
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700871 if (mCore->mSingleBufferMode) {
872 BQ_LOGE("cancelBuffer: cannot cancel a buffer in single buffer mode");
873 return BAD_VALUE;
874 }
875
Dan Stoza3e96f192014-03-03 10:16:19 -0800876 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
Dan Stoza289ade12014-02-28 11:17:17 -0800877 BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)",
Dan Stoza3e96f192014-03-03 10:16:19 -0800878 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700879 return BAD_VALUE;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700880 } else if (!mSlots[slot].mBufferState.isDequeued()) {
Dan Stoza289ade12014-02-28 11:17:17 -0800881 BQ_LOGE("cancelBuffer: slot %d is not owned by the producer "
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700882 "(state = %s)", slot, mSlots[slot].mBufferState.string());
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700883 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800884 } else if (fence == NULL) {
885 BQ_LOGE("cancelBuffer: fence is NULL");
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700886 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800887 }
888
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700889 mSlots[slot].mBufferState.cancel();
890
891 // After leaving single buffer mode, the shared buffer will still be around.
892 // Mark it as no longer shared if this operation causes it to be free.
893 if (!mCore->mSingleBufferMode && mSlots[slot].mBufferState.isFree()) {
894 mSlots[slot].mBufferState.mShared = false;
895 }
896
897 // Don't put the shared buffer on the free list.
898 if (!mSlots[slot].mBufferState.isShared()) {
899 mCore->mFreeBuffers.push_front(slot);
900 }
Dan Stoza289ade12014-02-28 11:17:17 -0800901 mSlots[slot].mFence = fence;
902 mCore->mDequeueCondition.broadcast();
Dan Stoza0de7ea72015-04-23 13:20:51 -0700903 mCore->validateConsistencyLocked();
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700904
905 return NO_ERROR;
Dan Stoza289ade12014-02-28 11:17:17 -0800906}
907
908int BufferQueueProducer::query(int what, int *outValue) {
909 ATRACE_CALL();
910 Mutex::Autolock lock(mCore->mMutex);
911
912 if (outValue == NULL) {
913 BQ_LOGE("query: outValue was NULL");
914 return BAD_VALUE;
915 }
916
917 if (mCore->mIsAbandoned) {
918 BQ_LOGE("query: BufferQueue has been abandoned");
919 return NO_INIT;
920 }
921
922 int value;
923 switch (what) {
924 case NATIVE_WINDOW_WIDTH:
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800925 value = static_cast<int32_t>(mCore->mDefaultWidth);
Dan Stoza289ade12014-02-28 11:17:17 -0800926 break;
927 case NATIVE_WINDOW_HEIGHT:
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800928 value = static_cast<int32_t>(mCore->mDefaultHeight);
Dan Stoza289ade12014-02-28 11:17:17 -0800929 break;
930 case NATIVE_WINDOW_FORMAT:
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800931 value = static_cast<int32_t>(mCore->mDefaultBufferFormat);
Dan Stoza289ade12014-02-28 11:17:17 -0800932 break;
933 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700934 value = mCore->getMinUndequeuedBufferCountLocked();
Dan Stoza289ade12014-02-28 11:17:17 -0800935 break;
Ruben Brunk1681d952014-06-27 15:51:55 -0700936 case NATIVE_WINDOW_STICKY_TRANSFORM:
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800937 value = static_cast<int32_t>(mStickyTransform);
Ruben Brunk1681d952014-06-27 15:51:55 -0700938 break;
Dan Stoza289ade12014-02-28 11:17:17 -0800939 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
940 value = (mCore->mQueue.size() > 1);
941 break;
942 case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800943 value = static_cast<int32_t>(mCore->mConsumerUsageBits);
Dan Stoza289ade12014-02-28 11:17:17 -0800944 break;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800945 case NATIVE_WINDOW_DEFAULT_DATASPACE:
946 value = static_cast<int32_t>(mCore->mDefaultBufferDataSpace);
947 break;
Dan Stoza4afd8b62015-02-25 16:49:08 -0800948 case NATIVE_WINDOW_BUFFER_AGE:
949 if (mCore->mBufferAge > INT32_MAX) {
950 value = 0;
951 } else {
952 value = static_cast<int32_t>(mCore->mBufferAge);
953 }
954 break;
Dan Stoza289ade12014-02-28 11:17:17 -0800955 default:
956 return BAD_VALUE;
957 }
958
959 BQ_LOGV("query: %d? %d", what, value);
960 *outValue = value;
961 return NO_ERROR;
962}
963
Dan Stozaf0eaf252014-03-21 13:05:51 -0700964status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
Dan Stoza289ade12014-02-28 11:17:17 -0800965 int api, bool producerControlledByApp, QueueBufferOutput *output) {
966 ATRACE_CALL();
967 Mutex::Autolock lock(mCore->mMutex);
968 mConsumerName = mCore->mConsumerName;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700969 BQ_LOGV("connect: api=%d producerControlledByApp=%s", api,
Dan Stoza289ade12014-02-28 11:17:17 -0800970 producerControlledByApp ? "true" : "false");
971
Dan Stozaae3c3682014-04-18 15:43:35 -0700972 if (mCore->mIsAbandoned) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700973 BQ_LOGE("connect: BufferQueue has been abandoned");
Dan Stozaae3c3682014-04-18 15:43:35 -0700974 return NO_INIT;
975 }
Dan Stoza289ade12014-02-28 11:17:17 -0800976
Dan Stozaae3c3682014-04-18 15:43:35 -0700977 if (mCore->mConsumerListener == NULL) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700978 BQ_LOGE("connect: BufferQueue has no consumer");
Dan Stozaae3c3682014-04-18 15:43:35 -0700979 return NO_INIT;
980 }
Dan Stoza289ade12014-02-28 11:17:17 -0800981
Dan Stozaae3c3682014-04-18 15:43:35 -0700982 if (output == NULL) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700983 BQ_LOGE("connect: output was NULL");
Dan Stozaae3c3682014-04-18 15:43:35 -0700984 return BAD_VALUE;
985 }
Dan Stoza289ade12014-02-28 11:17:17 -0800986
Dan Stozaae3c3682014-04-18 15:43:35 -0700987 if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700988 BQ_LOGE("connect: already connected (cur=%d req=%d)",
Dan Stozaae3c3682014-04-18 15:43:35 -0700989 mCore->mConnectedApi, api);
990 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800991 }
992
993 int status = NO_ERROR;
994 switch (api) {
995 case NATIVE_WINDOW_API_EGL:
996 case NATIVE_WINDOW_API_CPU:
997 case NATIVE_WINDOW_API_MEDIA:
998 case NATIVE_WINDOW_API_CAMERA:
999 mCore->mConnectedApi = api;
1000 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001001 mCore->mTransformHint,
1002 static_cast<uint32_t>(mCore->mQueue.size()));
Dan Stoza289ade12014-02-28 11:17:17 -08001003
1004 // Set up a death notification so that we can disconnect
1005 // automatically if the remote producer dies
Dan Stozaf0eaf252014-03-21 13:05:51 -07001006 if (listener != NULL &&
Marco Nelissen097ca272014-11-14 08:01:01 -08001007 IInterface::asBinder(listener)->remoteBinder() != NULL) {
1008 status = IInterface::asBinder(listener)->linkToDeath(
Dan Stoza289ade12014-02-28 11:17:17 -08001009 static_cast<IBinder::DeathRecipient*>(this));
Dan Stozaf0eaf252014-03-21 13:05:51 -07001010 if (status != NO_ERROR) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001011 BQ_LOGE("connect: linkToDeath failed: %s (%d)",
Dan Stoza289ade12014-02-28 11:17:17 -08001012 strerror(-status), status);
1013 }
1014 }
Dan Stozaf0eaf252014-03-21 13:05:51 -07001015 mCore->mConnectedProducerListener = listener;
Dan Stoza289ade12014-02-28 11:17:17 -08001016 break;
1017 default:
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001018 BQ_LOGE("connect: unknown API %d", api);
Dan Stoza289ade12014-02-28 11:17:17 -08001019 status = BAD_VALUE;
1020 break;
1021 }
1022
1023 mCore->mBufferHasBeenQueued = false;
Dan Stoza127fc632015-06-30 13:43:32 -07001024 mCore->mDequeueBufferCannotBlock = false;
1025 if (mDequeueTimeout < 0) {
1026 mCore->mDequeueBufferCannotBlock =
1027 mCore->mConsumerControlledByApp && producerControlledByApp;
1028 }
Dan Stoza2b83cc92015-05-12 14:55:15 -07001029 mCore->mAllowAllocation = true;
Dan Stoza289ade12014-02-28 11:17:17 -08001030
1031 return status;
1032}
1033
1034status_t BufferQueueProducer::disconnect(int api) {
1035 ATRACE_CALL();
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001036 BQ_LOGV("disconnect: api %d", api);
Dan Stoza289ade12014-02-28 11:17:17 -08001037
1038 int status = NO_ERROR;
1039 sp<IConsumerListener> listener;
1040 { // Autolock scope
1041 Mutex::Autolock lock(mCore->mMutex);
Antoine Labour78014f32014-07-15 21:17:03 -07001042 mCore->waitWhileAllocatingLocked();
Dan Stoza289ade12014-02-28 11:17:17 -08001043
1044 if (mCore->mIsAbandoned) {
1045 // It's not really an error to disconnect after the surface has
1046 // been abandoned; it should just be a no-op.
1047 return NO_ERROR;
1048 }
1049
1050 switch (api) {
1051 case NATIVE_WINDOW_API_EGL:
1052 case NATIVE_WINDOW_API_CPU:
1053 case NATIVE_WINDOW_API_MEDIA:
1054 case NATIVE_WINDOW_API_CAMERA:
1055 if (mCore->mConnectedApi == api) {
1056 mCore->freeAllBuffersLocked();
1057
1058 // Remove our death notification callback if we have one
Dan Stozaf0eaf252014-03-21 13:05:51 -07001059 if (mCore->mConnectedProducerListener != NULL) {
1060 sp<IBinder> token =
Marco Nelissen097ca272014-11-14 08:01:01 -08001061 IInterface::asBinder(mCore->mConnectedProducerListener);
Dan Stoza289ade12014-02-28 11:17:17 -08001062 // This can fail if we're here because of the death
1063 // notification, but we just ignore it
1064 token->unlinkToDeath(
1065 static_cast<IBinder::DeathRecipient*>(this));
1066 }
Dan Stozaf0eaf252014-03-21 13:05:51 -07001067 mCore->mConnectedProducerListener = NULL;
Dan Stoza289ade12014-02-28 11:17:17 -08001068 mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
Jesse Hall399184a2014-03-03 15:42:54 -08001069 mCore->mSidebandStream.clear();
Dan Stoza289ade12014-02-28 11:17:17 -08001070 mCore->mDequeueCondition.broadcast();
1071 listener = mCore->mConsumerListener;
Amith Dsouza4f21a4c2015-06-30 22:54:16 -07001072 } else if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001073 BQ_LOGE("disconnect: still connected to another API "
Dan Stoza289ade12014-02-28 11:17:17 -08001074 "(cur=%d req=%d)", mCore->mConnectedApi, api);
Dan Stoza9f3053d2014-03-06 15:14:33 -08001075 status = BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -08001076 }
1077 break;
1078 default:
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001079 BQ_LOGE("disconnect: unknown API %d", api);
Dan Stoza9f3053d2014-03-06 15:14:33 -08001080 status = BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -08001081 break;
1082 }
1083 } // Autolock scope
1084
1085 // Call back without lock held
1086 if (listener != NULL) {
1087 listener->onBuffersReleased();
1088 }
1089
1090 return status;
1091}
1092
Jesse Hall399184a2014-03-03 15:42:54 -08001093status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) {
Wonsik Kimafe30812014-03-31 23:16:08 +09001094 sp<IConsumerListener> listener;
1095 { // Autolock scope
1096 Mutex::Autolock _l(mCore->mMutex);
1097 mCore->mSidebandStream = stream;
1098 listener = mCore->mConsumerListener;
1099 } // Autolock scope
1100
1101 if (listener != NULL) {
1102 listener->onSidebandStreamChanged();
1103 }
Jesse Hall399184a2014-03-03 15:42:54 -08001104 return NO_ERROR;
1105}
1106
Pablo Ceballos567dbbb2015-08-26 18:59:08 -07001107void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height,
1108 PixelFormat format, uint32_t usage) {
Antoine Labour78014f32014-07-15 21:17:03 -07001109 ATRACE_CALL();
1110 while (true) {
1111 Vector<int> freeSlots;
1112 size_t newBufferCount = 0;
1113 uint32_t allocWidth = 0;
1114 uint32_t allocHeight = 0;
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001115 PixelFormat allocFormat = PIXEL_FORMAT_UNKNOWN;
Antoine Labour78014f32014-07-15 21:17:03 -07001116 uint32_t allocUsage = 0;
1117 { // Autolock scope
1118 Mutex::Autolock lock(mCore->mMutex);
1119 mCore->waitWhileAllocatingLocked();
Dan Stoza29a3e902014-06-20 13:13:57 -07001120
Dan Stoza9de72932015-04-16 17:28:43 -07001121 if (!mCore->mAllowAllocation) {
1122 BQ_LOGE("allocateBuffers: allocation is not allowed for this "
1123 "BufferQueue");
1124 return;
1125 }
1126
Antoine Labour78014f32014-07-15 21:17:03 -07001127 int currentBufferCount = 0;
1128 for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
1129 if (mSlots[slot].mGraphicBuffer != NULL) {
1130 ++currentBufferCount;
1131 } else {
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001132 if (!mSlots[slot].mBufferState.isFree()) {
Antoine Labour78014f32014-07-15 21:17:03 -07001133 BQ_LOGE("allocateBuffers: slot %d without buffer is not FREE",
1134 slot);
1135 continue;
1136 }
Dan Stoza29a3e902014-06-20 13:13:57 -07001137
Antoine Labour11f14872014-07-25 18:14:42 -07001138 freeSlots.push_back(slot);
Antoine Labour78014f32014-07-15 21:17:03 -07001139 }
1140 }
1141
Pablo Ceballos567dbbb2015-08-26 18:59:08 -07001142 int maxBufferCount = mCore->getMaxBufferCountLocked();
Antoine Labour78014f32014-07-15 21:17:03 -07001143 BQ_LOGV("allocateBuffers: allocating from %d buffers up to %d buffers",
1144 currentBufferCount, maxBufferCount);
1145 if (maxBufferCount <= currentBufferCount)
1146 return;
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001147 newBufferCount =
1148 static_cast<size_t>(maxBufferCount - currentBufferCount);
Antoine Labour78014f32014-07-15 21:17:03 -07001149 if (freeSlots.size() < newBufferCount) {
1150 BQ_LOGE("allocateBuffers: ran out of free slots");
1151 return;
1152 }
1153 allocWidth = width > 0 ? width : mCore->mDefaultWidth;
1154 allocHeight = height > 0 ? height : mCore->mDefaultHeight;
1155 allocFormat = format != 0 ? format : mCore->mDefaultBufferFormat;
1156 allocUsage = usage | mCore->mConsumerUsageBits;
1157
1158 mCore->mIsAllocating = true;
1159 } // Autolock scope
1160
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001161 Vector<sp<GraphicBuffer>> buffers;
Antoine Labour78014f32014-07-15 21:17:03 -07001162 for (size_t i = 0; i < newBufferCount; ++i) {
1163 status_t result = NO_ERROR;
1164 sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
1165 allocWidth, allocHeight, allocFormat, allocUsage, &result));
1166 if (result != NO_ERROR) {
1167 BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format"
1168 " %u, usage %u)", width, height, format, usage);
1169 Mutex::Autolock lock(mCore->mMutex);
1170 mCore->mIsAllocating = false;
1171 mCore->mIsAllocatingCondition.broadcast();
1172 return;
1173 }
1174 buffers.push_back(graphicBuffer);
1175 }
1176
1177 { // Autolock scope
1178 Mutex::Autolock lock(mCore->mMutex);
1179 uint32_t checkWidth = width > 0 ? width : mCore->mDefaultWidth;
1180 uint32_t checkHeight = height > 0 ? height : mCore->mDefaultHeight;
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001181 PixelFormat checkFormat = format != 0 ?
1182 format : mCore->mDefaultBufferFormat;
Antoine Labour78014f32014-07-15 21:17:03 -07001183 uint32_t checkUsage = usage | mCore->mConsumerUsageBits;
1184 if (checkWidth != allocWidth || checkHeight != allocHeight ||
1185 checkFormat != allocFormat || checkUsage != allocUsage) {
1186 // Something changed while we released the lock. Retry.
1187 BQ_LOGV("allocateBuffers: size/format/usage changed while allocating. Retrying.");
1188 mCore->mIsAllocating = false;
1189 mCore->mIsAllocatingCondition.broadcast();
Dan Stoza29a3e902014-06-20 13:13:57 -07001190 continue;
1191 }
1192
Antoine Labour78014f32014-07-15 21:17:03 -07001193 for (size_t i = 0; i < newBufferCount; ++i) {
1194 int slot = freeSlots[i];
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001195 if (!mSlots[slot].mBufferState.isFree()) {
Antoine Labour78014f32014-07-15 21:17:03 -07001196 // A consumer allocated the FREE slot with attachBuffer. Discard the buffer we
1197 // allocated.
1198 BQ_LOGV("allocateBuffers: slot %d was acquired while allocating. "
1199 "Dropping allocated buffer.", slot);
1200 continue;
1201 }
1202 mCore->freeBufferLocked(slot); // Clean up the slot first
1203 mSlots[slot].mGraphicBuffer = buffers[i];
Antoine Labour78014f32014-07-15 21:17:03 -07001204 mSlots[slot].mFence = Fence::NO_FENCE;
Dan Stoza0de7ea72015-04-23 13:20:51 -07001205
1206 // freeBufferLocked puts this slot on the free slots list. Since
1207 // we then attached a buffer, move the slot to free buffer list.
1208 mCore->mFreeSlots.erase(slot);
1209 mCore->mFreeBuffers.push_front(slot);
1210
Antoine Labour78014f32014-07-15 21:17:03 -07001211 BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d", slot);
1212 }
Dan Stoza29a3e902014-06-20 13:13:57 -07001213
Antoine Labour78014f32014-07-15 21:17:03 -07001214 mCore->mIsAllocating = false;
1215 mCore->mIsAllocatingCondition.broadcast();
Dan Stoza0de7ea72015-04-23 13:20:51 -07001216 mCore->validateConsistencyLocked();
Antoine Labour78014f32014-07-15 21:17:03 -07001217 } // Autolock scope
Dan Stoza29a3e902014-06-20 13:13:57 -07001218 }
1219}
1220
Dan Stoza9de72932015-04-16 17:28:43 -07001221status_t BufferQueueProducer::allowAllocation(bool allow) {
1222 ATRACE_CALL();
1223 BQ_LOGV("allowAllocation: %s", allow ? "true" : "false");
1224
1225 Mutex::Autolock lock(mCore->mMutex);
1226 mCore->mAllowAllocation = allow;
1227 return NO_ERROR;
1228}
1229
Dan Stoza812ed062015-06-02 15:45:22 -07001230status_t BufferQueueProducer::setGenerationNumber(uint32_t generationNumber) {
1231 ATRACE_CALL();
1232 BQ_LOGV("setGenerationNumber: %u", generationNumber);
1233
1234 Mutex::Autolock lock(mCore->mMutex);
1235 mCore->mGenerationNumber = generationNumber;
1236 return NO_ERROR;
1237}
1238
Dan Stozac6f30bd2015-06-08 09:32:50 -07001239String8 BufferQueueProducer::getConsumerName() const {
1240 ATRACE_CALL();
1241 BQ_LOGV("getConsumerName: %s", mConsumerName.string());
1242 return mConsumerName;
1243}
1244
Dan Stoza7dde5992015-05-22 09:51:44 -07001245uint64_t BufferQueueProducer::getNextFrameNumber() const {
1246 ATRACE_CALL();
1247
1248 Mutex::Autolock lock(mCore->mMutex);
1249 uint64_t nextFrameNumber = mCore->mFrameCounter + 1;
1250 return nextFrameNumber;
1251}
1252
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001253status_t BufferQueueProducer::setSingleBufferMode(bool singleBufferMode) {
1254 ATRACE_CALL();
1255 BQ_LOGV("setSingleBufferMode: %d", singleBufferMode);
1256
1257 Mutex::Autolock lock(mCore->mMutex);
1258 if (!singleBufferMode) {
1259 mCore->mSingleBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT;
1260 }
1261 mCore->mSingleBufferMode = singleBufferMode;
Dan Stoza127fc632015-06-30 13:43:32 -07001262 return NO_ERROR;
1263}
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001264
Dan Stoza127fc632015-06-30 13:43:32 -07001265status_t BufferQueueProducer::setDequeueTimeout(nsecs_t timeout) {
1266 ATRACE_CALL();
1267 BQ_LOGV("setDequeueTimeout: %" PRId64, timeout);
1268
1269 Mutex::Autolock lock(mCore->mMutex);
1270 mDequeueTimeout = timeout;
1271 mCore->mDequeueBufferCannotBlock = false;
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001272 return NO_ERROR;
1273}
1274
Dan Stoza289ade12014-02-28 11:17:17 -08001275void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
1276 // If we're here, it means that a producer we were connected to died.
1277 // We're guaranteed that we are still connected to it because we remove
1278 // this callback upon disconnect. It's therefore safe to read mConnectedApi
1279 // without synchronization here.
1280 int api = mCore->mConnectedApi;
1281 disconnect(api);
1282}
1283
1284} // namespace android