blob: deec3305b884a40c7968db2baf2d0d8253c37dbb [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),
46 mCallbackCondition() {}
Dan Stoza289ade12014-02-28 11:17:17 -080047
48BufferQueueProducer::~BufferQueueProducer() {}
49
50status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
51 ATRACE_CALL();
52 BQ_LOGV("requestBuffer: slot %d", slot);
53 Mutex::Autolock lock(mCore->mMutex);
54
55 if (mCore->mIsAbandoned) {
56 BQ_LOGE("requestBuffer: BufferQueue has been abandoned");
57 return NO_INIT;
58 }
59
Pablo Ceballos583b1b32015-09-03 18:23:52 -070060 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
61 BQ_LOGE("requestBuffer: BufferQueue has no connected producer");
62 return NO_INIT;
63 }
64
Dan Stoza3e96f192014-03-03 10:16:19 -080065 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
Dan Stoza289ade12014-02-28 11:17:17 -080066 BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)",
Dan Stoza3e96f192014-03-03 10:16:19 -080067 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
Dan Stoza289ade12014-02-28 11:17:17 -080068 return BAD_VALUE;
69 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
70 BQ_LOGE("requestBuffer: slot %d is not owned by the producer "
71 "(state = %d)", slot, mSlots[slot].mBufferState);
72 return BAD_VALUE;
73 }
74
75 mSlots[slot].mRequestBufferCalled = true;
76 *buf = mSlots[slot].mGraphicBuffer;
77 return NO_ERROR;
78}
79
Pablo Ceballosfa455352015-08-12 17:47:47 -070080status_t BufferQueueProducer::setMaxDequeuedBufferCount(
81 int maxDequeuedBuffers) {
82 ATRACE_CALL();
83 BQ_LOGV("setMaxDequeuedBufferCount: maxDequeuedBuffers = %d",
84 maxDequeuedBuffers);
85
86 sp<IConsumerListener> listener;
87 { // Autolock scope
88 Mutex::Autolock lock(mCore->mMutex);
89 mCore->waitWhileAllocatingLocked();
90
91 if (mCore->mIsAbandoned) {
92 BQ_LOGE("setMaxDequeuedBufferCount: BufferQueue has been "
93 "abandoned");
94 return NO_INIT;
95 }
96
97 // There must be no dequeued buffers when changing the buffer count.
98 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
99 if (mSlots[s].mBufferState == BufferSlot::DEQUEUED) {
100 BQ_LOGE("setMaxDequeuedBufferCount: buffer owned by producer");
101 return BAD_VALUE;
102 }
103 }
104
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700105 int bufferCount = mCore->getMinUndequeuedBufferCountLocked();
Pablo Ceballosfa455352015-08-12 17:47:47 -0700106 bufferCount += maxDequeuedBuffers;
107
108 if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
109 BQ_LOGE("setMaxDequeuedBufferCount: bufferCount %d too large "
110 "(max %d)", bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
111 return BAD_VALUE;
112 }
113
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700114 const int minBufferSlots = mCore->getMinMaxBufferCountLocked();
Pablo Ceballosfa455352015-08-12 17:47:47 -0700115 if (bufferCount < minBufferSlots) {
116 BQ_LOGE("setMaxDequeuedBufferCount: requested buffer count %d is "
117 "less than minimum %d", bufferCount, minBufferSlots);
118 return BAD_VALUE;
119 }
120
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700121 if (bufferCount > mCore->mMaxBufferCount) {
122 BQ_LOGE("setMaxDequeuedBufferCount: %d dequeued buffers would "
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700123 "exceed the maxBufferCount (%d) (maxAcquired %d async %d "
124 "mDequeuedBufferCannotBlock %d)", maxDequeuedBuffers,
125 mCore->mMaxBufferCount, mCore->mMaxAcquiredBufferCount,
126 mCore->mAsyncMode, mCore->mDequeueBufferCannotBlock);
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700127 return BAD_VALUE;
128 }
129
Pablo Ceballosfa455352015-08-12 17:47:47 -0700130 // Here we are guaranteed that the producer doesn't have any dequeued
131 // buffers and will release all of its buffer references. We don't
132 // clear the queue, however, so that currently queued buffers still
133 // get displayed.
134 mCore->freeAllBuffersLocked();
135 mCore->mMaxDequeuedBufferCount = maxDequeuedBuffers;
Pablo Ceballosfa455352015-08-12 17:47:47 -0700136 mCore->mDequeueCondition.broadcast();
137 listener = mCore->mConsumerListener;
138 } // Autolock scope
139
140 // Call back without lock held
141 if (listener != NULL) {
142 listener->onBuffersReleased();
143 }
144
145 return NO_ERROR;
146}
147
148status_t BufferQueueProducer::setAsyncMode(bool async) {
149 ATRACE_CALL();
150 BQ_LOGV("setAsyncMode: async = %d", async);
151
152 sp<IConsumerListener> listener;
153 { // Autolock scope
154 Mutex::Autolock lock(mCore->mMutex);
155 mCore->waitWhileAllocatingLocked();
156
157 if (mCore->mIsAbandoned) {
158 BQ_LOGE("setAsyncMode: BufferQueue has been abandoned");
159 return NO_INIT;
160 }
161
162 // There must be no dequeued buffers when changing the async mode.
163 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
164 if (mSlots[s].mBufferState == BufferSlot::DEQUEUED) {
165 BQ_LOGE("setAsyncMode: buffer owned by producer");
166 return BAD_VALUE;
167 }
168 }
169
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700170 if ((mCore->mMaxAcquiredBufferCount + mCore->mMaxDequeuedBufferCount +
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700171 (async || mCore->mDequeueBufferCannotBlock ? 1 : 0)) >
172 mCore->mMaxBufferCount) {
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700173 BQ_LOGE("setAsyncMode(%d): this call would cause the "
174 "maxBufferCount (%d) to be exceeded (maxAcquired %d "
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700175 "maxDequeued %d mDequeueBufferCannotBlock %d)", async,
176 mCore->mMaxBufferCount, mCore->mMaxAcquiredBufferCount,
177 mCore->mMaxDequeuedBufferCount,
178 mCore->mDequeueBufferCannotBlock);
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700179 return BAD_VALUE;
180 }
181
Pablo Ceballosfa455352015-08-12 17:47:47 -0700182 mCore->mAsyncMode = async;
183 mCore->mDequeueCondition.broadcast();
184 listener = mCore->mConsumerListener;
185 } // Autolock scope
186
187 // Call back without lock held
188 if (listener != NULL) {
189 listener->onBuffersReleased();
190 }
191 return NO_ERROR;
192}
193
Dan Stoza9f3053d2014-03-06 15:14:33 -0800194status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller,
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700195 int* found, status_t* returnFlags) const {
Dan Stoza9f3053d2014-03-06 15:14:33 -0800196 bool tryAgain = true;
197 while (tryAgain) {
198 if (mCore->mIsAbandoned) {
199 BQ_LOGE("%s: BufferQueue has been abandoned", caller);
200 return NO_INIT;
201 }
202
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700203 const int maxBufferCount = mCore->getMaxBufferCountLocked();
Dan Stoza9f3053d2014-03-06 15:14:33 -0800204
205 // Free up any buffers that are in slots beyond the max buffer count
206 for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
207 assert(mSlots[s].mBufferState == BufferSlot::FREE);
208 if (mSlots[s].mGraphicBuffer != NULL) {
209 mCore->freeBufferLocked(s);
210 *returnFlags |= RELEASE_ALL_BUFFERS;
211 }
212 }
213
Dan Stoza9f3053d2014-03-06 15:14:33 -0800214 int dequeuedCount = 0;
215 int acquiredCount = 0;
216 for (int s = 0; s < maxBufferCount; ++s) {
217 switch (mSlots[s].mBufferState) {
218 case BufferSlot::DEQUEUED:
219 ++dequeuedCount;
220 break;
221 case BufferSlot::ACQUIRED:
222 ++acquiredCount;
223 break;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800224 default:
225 break;
226 }
227 }
228
Pablo Ceballose5b755a2015-08-13 16:18:19 -0700229 // Producers are not allowed to dequeue more than
230 // mMaxDequeuedBufferCount buffers.
231 // This check is only done if a buffer has already been queued
232 if (mCore->mBufferHasBeenQueued &&
233 dequeuedCount >= mCore->mMaxDequeuedBufferCount) {
234 BQ_LOGE("%s: attempting to exceed the max dequeued buffer count "
235 "(%d)", caller, mCore->mMaxDequeuedBufferCount);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800236 return INVALID_OPERATION;
237 }
238
Dan Stoza0de7ea72015-04-23 13:20:51 -0700239 *found = BufferQueueCore::INVALID_BUFFER_SLOT;
240
Dan Stozaae3c3682014-04-18 15:43:35 -0700241 // If we disconnect and reconnect quickly, we can be in a state where
242 // our slots are empty but we have many buffers in the queue. This can
243 // cause us to run out of memory if we outrun the consumer. Wait here if
244 // it looks like we have too many buffers queued up.
Mark Salyzyn8f515ce2014-06-09 14:32:04 -0700245 bool tooManyBuffers = mCore->mQueue.size()
246 > static_cast<size_t>(maxBufferCount);
Dan Stozaae3c3682014-04-18 15:43:35 -0700247 if (tooManyBuffers) {
Mark Salyzyn8f515ce2014-06-09 14:32:04 -0700248 BQ_LOGV("%s: queue size is %zu, waiting", caller,
Dan Stozaae3c3682014-04-18 15:43:35 -0700249 mCore->mQueue.size());
Dan Stoza0de7ea72015-04-23 13:20:51 -0700250 } else {
251 if (!mCore->mFreeBuffers.empty()) {
252 auto slot = mCore->mFreeBuffers.begin();
253 *found = *slot;
254 mCore->mFreeBuffers.erase(slot);
Dan Stoza9de72932015-04-16 17:28:43 -0700255 } else if (mCore->mAllowAllocation && !mCore->mFreeSlots.empty()) {
Dan Stoza0de7ea72015-04-23 13:20:51 -0700256 auto slot = mCore->mFreeSlots.begin();
257 // Only return free slots up to the max buffer count
258 if (*slot < maxBufferCount) {
259 *found = *slot;
260 mCore->mFreeSlots.erase(slot);
261 }
262 }
Dan Stozaae3c3682014-04-18 15:43:35 -0700263 }
264
265 // If no buffer is found, or if the queue has too many buffers
266 // outstanding, wait for a buffer to be acquired or released, or for the
267 // max buffer count to change.
268 tryAgain = (*found == BufferQueueCore::INVALID_BUFFER_SLOT) ||
269 tooManyBuffers;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800270 if (tryAgain) {
271 // Return an error if we're in non-blocking mode (producer and
272 // consumer are controlled by the application).
273 // However, the consumer is allowed to briefly acquire an extra
274 // buffer (which could cause us to have to wait here), which is
275 // okay, since it is only used to implement an atomic acquire +
276 // release (e.g., in GLConsumer::updateTexImage())
Pablo Ceballosfa455352015-08-12 17:47:47 -0700277 if ((mCore->mDequeueBufferCannotBlock || mCore->mAsyncMode) &&
Dan Stoza9f3053d2014-03-06 15:14:33 -0800278 (acquiredCount <= mCore->mMaxAcquiredBufferCount)) {
279 return WOULD_BLOCK;
280 }
281 mCore->mDequeueCondition.wait(mCore->mMutex);
282 }
283 } // while (tryAgain)
284
285 return NO_ERROR;
286}
287
Dan Stoza289ade12014-02-28 11:17:17 -0800288status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700289 sp<android::Fence> *outFence, uint32_t width, uint32_t height,
290 PixelFormat format, uint32_t usage) {
Dan Stoza289ade12014-02-28 11:17:17 -0800291 ATRACE_CALL();
292 { // Autolock scope
293 Mutex::Autolock lock(mCore->mMutex);
294 mConsumerName = mCore->mConsumerName;
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700295
296 if (mCore->mIsAbandoned) {
297 BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
298 return NO_INIT;
299 }
300
301 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
302 BQ_LOGE("dequeueBuffer: BufferQueue has no connected producer");
303 return NO_INIT;
304 }
Dan Stoza289ade12014-02-28 11:17:17 -0800305 } // Autolock scope
306
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700307 BQ_LOGV("dequeueBuffer: w=%u h=%u format=%#x, usage=%#x", width, height,
308 format, usage);
Dan Stoza289ade12014-02-28 11:17:17 -0800309
310 if ((width && !height) || (!width && height)) {
311 BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height);
312 return BAD_VALUE;
313 }
314
315 status_t returnFlags = NO_ERROR;
316 EGLDisplay eglDisplay = EGL_NO_DISPLAY;
317 EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800318 bool attachedByConsumer = false;
Dan Stoza289ade12014-02-28 11:17:17 -0800319
320 { // Autolock scope
321 Mutex::Autolock lock(mCore->mMutex);
Antoine Labour78014f32014-07-15 21:17:03 -0700322 mCore->waitWhileAllocatingLocked();
Dan Stoza289ade12014-02-28 11:17:17 -0800323
324 if (format == 0) {
325 format = mCore->mDefaultBufferFormat;
326 }
327
328 // Enable the usage bits the consumer requested
329 usage |= mCore->mConsumerUsageBits;
330
Dan Stoza9de72932015-04-16 17:28:43 -0700331 const bool useDefaultSize = !width && !height;
332 if (useDefaultSize) {
333 width = mCore->mDefaultWidth;
334 height = mCore->mDefaultHeight;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800335 }
Dan Stoza289ade12014-02-28 11:17:17 -0800336
Dan Stoza9de72932015-04-16 17:28:43 -0700337 int found = BufferItem::INVALID_BUFFER_SLOT;
338 while (found == BufferItem::INVALID_BUFFER_SLOT) {
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700339 status_t status = waitForFreeSlotThenRelock("dequeueBuffer", &found,
340 &returnFlags);
Dan Stoza9de72932015-04-16 17:28:43 -0700341 if (status != NO_ERROR) {
342 return status;
343 }
344
345 // This should not happen
346 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
347 BQ_LOGE("dequeueBuffer: no available buffer slots");
348 return -EBUSY;
349 }
350
351 const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
352
353 // If we are not allowed to allocate new buffers,
354 // waitForFreeSlotThenRelock must have returned a slot containing a
355 // buffer. If this buffer would require reallocation to meet the
356 // requested attributes, we free it and attempt to get another one.
357 if (!mCore->mAllowAllocation) {
358 if (buffer->needsReallocation(width, height, format, usage)) {
359 mCore->freeBufferLocked(found);
360 found = BufferItem::INVALID_BUFFER_SLOT;
361 continue;
362 }
363 }
Dan Stoza289ade12014-02-28 11:17:17 -0800364 }
365
366 *outSlot = found;
367 ATRACE_BUFFER_INDEX(found);
368
Dan Stoza9f3053d2014-03-06 15:14:33 -0800369 attachedByConsumer = mSlots[found].mAttachedByConsumer;
370
Dan Stoza289ade12014-02-28 11:17:17 -0800371 mSlots[found].mBufferState = BufferSlot::DEQUEUED;
372
373 const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
374 if ((buffer == NULL) ||
Dan Stoza9de72932015-04-16 17:28:43 -0700375 buffer->needsReallocation(width, height, format, usage))
Dan Stoza289ade12014-02-28 11:17:17 -0800376 {
377 mSlots[found].mAcquireCalled = false;
378 mSlots[found].mGraphicBuffer = NULL;
379 mSlots[found].mRequestBufferCalled = false;
380 mSlots[found].mEglDisplay = EGL_NO_DISPLAY;
381 mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
382 mSlots[found].mFence = Fence::NO_FENCE;
Dan Stoza4afd8b62015-02-25 16:49:08 -0800383 mCore->mBufferAge = 0;
Dan Stoza289ade12014-02-28 11:17:17 -0800384
385 returnFlags |= BUFFER_NEEDS_REALLOCATION;
Dan Stoza4afd8b62015-02-25 16:49:08 -0800386 } else {
387 // We add 1 because that will be the frame number when this buffer
388 // is queued
389 mCore->mBufferAge =
390 mCore->mFrameCounter + 1 - mSlots[found].mFrameNumber;
Dan Stoza289ade12014-02-28 11:17:17 -0800391 }
392
Dan Stoza800b41a2015-04-28 14:20:04 -0700393 BQ_LOGV("dequeueBuffer: setting buffer age to %" PRIu64,
394 mCore->mBufferAge);
Dan Stoza4afd8b62015-02-25 16:49:08 -0800395
Dan Stoza289ade12014-02-28 11:17:17 -0800396 if (CC_UNLIKELY(mSlots[found].mFence == NULL)) {
397 BQ_LOGE("dequeueBuffer: about to return a NULL fence - "
398 "slot=%d w=%d h=%d format=%u",
399 found, buffer->width, buffer->height, buffer->format);
400 }
401
402 eglDisplay = mSlots[found].mEglDisplay;
403 eglFence = mSlots[found].mEglFence;
404 *outFence = mSlots[found].mFence;
405 mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
406 mSlots[found].mFence = Fence::NO_FENCE;
Dan Stoza0de7ea72015-04-23 13:20:51 -0700407
408 mCore->validateConsistencyLocked();
Dan Stoza289ade12014-02-28 11:17:17 -0800409 } // Autolock scope
410
411 if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
412 status_t error;
Dan Stoza29a3e902014-06-20 13:13:57 -0700413 BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
Dan Stoza289ade12014-02-28 11:17:17 -0800414 sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800415 width, height, format, usage, &error));
Dan Stoza289ade12014-02-28 11:17:17 -0800416 if (graphicBuffer == NULL) {
417 BQ_LOGE("dequeueBuffer: createGraphicBuffer failed");
418 return error;
419 }
420
421 { // Autolock scope
422 Mutex::Autolock lock(mCore->mMutex);
423
424 if (mCore->mIsAbandoned) {
425 BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
426 return NO_INIT;
427 }
428
Dan Stoza812ed062015-06-02 15:45:22 -0700429 graphicBuffer->setGenerationNumber(mCore->mGenerationNumber);
Dan Stoza289ade12014-02-28 11:17:17 -0800430 mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
431 } // Autolock scope
432 }
433
Dan Stoza9f3053d2014-03-06 15:14:33 -0800434 if (attachedByConsumer) {
435 returnFlags |= BUFFER_NEEDS_REALLOCATION;
436 }
437
Dan Stoza289ade12014-02-28 11:17:17 -0800438 if (eglFence != EGL_NO_SYNC_KHR) {
439 EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, 0,
440 1000000000);
441 // If something goes wrong, log the error, but return the buffer without
442 // synchronizing access to it. It's too late at this point to abort the
443 // dequeue operation.
444 if (result == EGL_FALSE) {
445 BQ_LOGE("dequeueBuffer: error %#x waiting for fence",
446 eglGetError());
447 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
448 BQ_LOGE("dequeueBuffer: timeout waiting for fence");
449 }
450 eglDestroySyncKHR(eglDisplay, eglFence);
451 }
452
Mark Salyzyn8f515ce2014-06-09 14:32:04 -0700453 BQ_LOGV("dequeueBuffer: returning slot=%d/%" PRIu64 " buf=%p flags=%#x",
454 *outSlot,
Dan Stoza289ade12014-02-28 11:17:17 -0800455 mSlots[*outSlot].mFrameNumber,
456 mSlots[*outSlot].mGraphicBuffer->handle, returnFlags);
457
458 return returnFlags;
459}
460
Dan Stoza9f3053d2014-03-06 15:14:33 -0800461status_t BufferQueueProducer::detachBuffer(int slot) {
462 ATRACE_CALL();
463 ATRACE_BUFFER_INDEX(slot);
464 BQ_LOGV("detachBuffer(P): slot %d", slot);
465 Mutex::Autolock lock(mCore->mMutex);
466
467 if (mCore->mIsAbandoned) {
468 BQ_LOGE("detachBuffer(P): BufferQueue has been abandoned");
469 return NO_INIT;
470 }
471
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700472 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
473 BQ_LOGE("detachBuffer(P): BufferQueue has no connected producer");
474 return NO_INIT;
475 }
476
Dan Stoza9f3053d2014-03-06 15:14:33 -0800477 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
478 BQ_LOGE("detachBuffer(P): slot index %d out of range [0, %d)",
479 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
480 return BAD_VALUE;
481 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
482 BQ_LOGE("detachBuffer(P): slot %d is not owned by the producer "
483 "(state = %d)", slot, mSlots[slot].mBufferState);
484 return BAD_VALUE;
485 } else if (!mSlots[slot].mRequestBufferCalled) {
486 BQ_LOGE("detachBuffer(P): buffer in slot %d has not been requested",
487 slot);
488 return BAD_VALUE;
489 }
490
491 mCore->freeBufferLocked(slot);
492 mCore->mDequeueCondition.broadcast();
Dan Stoza0de7ea72015-04-23 13:20:51 -0700493 mCore->validateConsistencyLocked();
Dan Stoza9f3053d2014-03-06 15:14:33 -0800494
495 return NO_ERROR;
496}
497
Dan Stozad9822a32014-03-28 15:25:31 -0700498status_t BufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
499 sp<Fence>* outFence) {
500 ATRACE_CALL();
501
502 if (outBuffer == NULL) {
503 BQ_LOGE("detachNextBuffer: outBuffer must not be NULL");
504 return BAD_VALUE;
505 } else if (outFence == NULL) {
506 BQ_LOGE("detachNextBuffer: outFence must not be NULL");
507 return BAD_VALUE;
508 }
509
510 Mutex::Autolock lock(mCore->mMutex);
511
512 if (mCore->mIsAbandoned) {
513 BQ_LOGE("detachNextBuffer: BufferQueue has been abandoned");
514 return NO_INIT;
515 }
516
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700517 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
518 BQ_LOGE("detachNextBuffer: BufferQueue has no connected producer");
519 return NO_INIT;
520 }
521
522 mCore->waitWhileAllocatingLocked();
523
Dan Stoza0de7ea72015-04-23 13:20:51 -0700524 if (mCore->mFreeBuffers.empty()) {
Dan Stoza1fc9cc22015-04-22 18:57:39 +0000525 return NO_MEMORY;
526 }
Dan Stoza8dddc992015-04-16 15:39:18 -0700527
Dan Stoza0de7ea72015-04-23 13:20:51 -0700528 int found = mCore->mFreeBuffers.front();
529 mCore->mFreeBuffers.remove(found);
530
Dan Stozad9822a32014-03-28 15:25:31 -0700531 BQ_LOGV("detachNextBuffer detached slot %d", found);
532
533 *outBuffer = mSlots[found].mGraphicBuffer;
534 *outFence = mSlots[found].mFence;
535 mCore->freeBufferLocked(found);
Dan Stoza0de7ea72015-04-23 13:20:51 -0700536 mCore->validateConsistencyLocked();
Dan Stozad9822a32014-03-28 15:25:31 -0700537
538 return NO_ERROR;
539}
540
Dan Stoza9f3053d2014-03-06 15:14:33 -0800541status_t BufferQueueProducer::attachBuffer(int* outSlot,
542 const sp<android::GraphicBuffer>& buffer) {
543 ATRACE_CALL();
544
545 if (outSlot == NULL) {
546 BQ_LOGE("attachBuffer(P): outSlot must not be NULL");
547 return BAD_VALUE;
548 } else if (buffer == NULL) {
549 BQ_LOGE("attachBuffer(P): cannot attach NULL buffer");
550 return BAD_VALUE;
551 }
552
553 Mutex::Autolock lock(mCore->mMutex);
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700554
555 if (mCore->mIsAbandoned) {
556 BQ_LOGE("attachBuffer(P): BufferQueue has been abandoned");
557 return NO_INIT;
558 }
559
560 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
561 BQ_LOGE("attachBuffer(P): BufferQueue has no connected producer");
562 return NO_INIT;
563 }
Dan Stoza9f3053d2014-03-06 15:14:33 -0800564
Dan Stoza812ed062015-06-02 15:45:22 -0700565 if (buffer->getGenerationNumber() != mCore->mGenerationNumber) {
566 BQ_LOGE("attachBuffer: generation number mismatch [buffer %u] "
567 "[queue %u]", buffer->getGenerationNumber(),
568 mCore->mGenerationNumber);
569 return BAD_VALUE;
570 }
571
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700572 mCore->waitWhileAllocatingLocked();
573
Dan Stoza9f3053d2014-03-06 15:14:33 -0800574 status_t returnFlags = NO_ERROR;
575 int found;
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700576 status_t status = waitForFreeSlotThenRelock("attachBuffer(P)", &found,
577 &returnFlags);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800578 if (status != NO_ERROR) {
579 return status;
580 }
581
582 // This should not happen
583 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
584 BQ_LOGE("attachBuffer(P): no available buffer slots");
585 return -EBUSY;
586 }
587
588 *outSlot = found;
589 ATRACE_BUFFER_INDEX(*outSlot);
590 BQ_LOGV("attachBuffer(P): returning slot %d flags=%#x",
591 *outSlot, returnFlags);
592
593 mSlots[*outSlot].mGraphicBuffer = buffer;
594 mSlots[*outSlot].mBufferState = BufferSlot::DEQUEUED;
595 mSlots[*outSlot].mEglFence = EGL_NO_SYNC_KHR;
596 mSlots[*outSlot].mFence = Fence::NO_FENCE;
Dan Stoza2443c792014-03-24 15:03:46 -0700597 mSlots[*outSlot].mRequestBufferCalled = true;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800598
Dan Stoza0de7ea72015-04-23 13:20:51 -0700599 mCore->validateConsistencyLocked();
600
Dan Stoza9f3053d2014-03-06 15:14:33 -0800601 return returnFlags;
602}
603
Dan Stoza289ade12014-02-28 11:17:17 -0800604status_t BufferQueueProducer::queueBuffer(int slot,
605 const QueueBufferInput &input, QueueBufferOutput *output) {
606 ATRACE_CALL();
607 ATRACE_BUFFER_INDEX(slot);
608
609 int64_t timestamp;
610 bool isAutoTimestamp;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800611 android_dataspace dataSpace;
Pablo Ceballos60d69222015-08-07 14:47:20 -0700612 Rect crop(Rect::EMPTY_RECT);
Dan Stoza289ade12014-02-28 11:17:17 -0800613 int scalingMode;
614 uint32_t transform;
Ruben Brunk1681d952014-06-27 15:51:55 -0700615 uint32_t stickyTransform;
Dan Stoza289ade12014-02-28 11:17:17 -0800616 sp<Fence> fence;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800617 input.deflate(&timestamp, &isAutoTimestamp, &dataSpace, &crop, &scalingMode,
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700618 &transform, &fence, &stickyTransform);
Dan Stoza5065a552015-03-17 16:23:42 -0700619 Region surfaceDamage = input.getSurfaceDamage();
Dan Stoza289ade12014-02-28 11:17:17 -0800620
621 if (fence == NULL) {
622 BQ_LOGE("queueBuffer: fence is NULL");
Jesse Hallde288fe2014-11-04 08:30:48 -0800623 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800624 }
625
626 switch (scalingMode) {
627 case NATIVE_WINDOW_SCALING_MODE_FREEZE:
628 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
629 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
630 case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
631 break;
632 default:
633 BQ_LOGE("queueBuffer: unknown scaling mode %d", scalingMode);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800634 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800635 }
636
Dan Stoza8dc55392014-11-04 11:37:46 -0800637 sp<IConsumerListener> frameAvailableListener;
638 sp<IConsumerListener> frameReplacedListener;
639 int callbackTicket = 0;
640 BufferItem item;
Dan Stoza289ade12014-02-28 11:17:17 -0800641 { // Autolock scope
642 Mutex::Autolock lock(mCore->mMutex);
643
644 if (mCore->mIsAbandoned) {
645 BQ_LOGE("queueBuffer: BufferQueue has been abandoned");
646 return NO_INIT;
647 }
648
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700649 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
650 BQ_LOGE("queueBuffer: BufferQueue has no connected producer");
651 return NO_INIT;
652 }
653
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700654 const int maxBufferCount = mCore->getMaxBufferCountLocked();
Dan Stoza289ade12014-02-28 11:17:17 -0800655
656 if (slot < 0 || slot >= maxBufferCount) {
657 BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)",
658 slot, maxBufferCount);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800659 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800660 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
661 BQ_LOGE("queueBuffer: slot %d is not owned by the producer "
662 "(state = %d)", slot, mSlots[slot].mBufferState);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800663 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800664 } else if (!mSlots[slot].mRequestBufferCalled) {
665 BQ_LOGE("queueBuffer: slot %d was queued without requesting "
666 "a buffer", slot);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800667 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800668 }
669
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800670 BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64 " dataSpace=%d"
Mark Salyzyn8f515ce2014-06-09 14:32:04 -0700671 " crop=[%d,%d,%d,%d] transform=%#x scale=%s",
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800672 slot, mCore->mFrameCounter + 1, timestamp, dataSpace,
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800673 crop.left, crop.top, crop.right, crop.bottom, transform,
674 BufferItem::scalingModeName(static_cast<uint32_t>(scalingMode)));
Dan Stoza289ade12014-02-28 11:17:17 -0800675
676 const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
677 Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
Pablo Ceballos60d69222015-08-07 14:47:20 -0700678 Rect croppedRect(Rect::EMPTY_RECT);
Dan Stoza289ade12014-02-28 11:17:17 -0800679 crop.intersect(bufferRect, &croppedRect);
680 if (croppedRect != crop) {
681 BQ_LOGE("queueBuffer: crop rect is not contained within the "
682 "buffer in slot %d", slot);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800683 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800684 }
685
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800686 // Override UNKNOWN dataspace with consumer default
687 if (dataSpace == HAL_DATASPACE_UNKNOWN) {
688 dataSpace = mCore->mDefaultBufferDataSpace;
689 }
690
Dan Stoza289ade12014-02-28 11:17:17 -0800691 mSlots[slot].mFence = fence;
692 mSlots[slot].mBufferState = BufferSlot::QUEUED;
693 ++mCore->mFrameCounter;
694 mSlots[slot].mFrameNumber = mCore->mFrameCounter;
695
Dan Stoza289ade12014-02-28 11:17:17 -0800696 item.mAcquireCalled = mSlots[slot].mAcquireCalled;
697 item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
698 item.mCrop = crop;
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800699 item.mTransform = transform &
700 ~static_cast<uint32_t>(NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
Dan Stoza289ade12014-02-28 11:17:17 -0800701 item.mTransformToDisplayInverse =
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800702 (transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) != 0;
703 item.mScalingMode = static_cast<uint32_t>(scalingMode);
Dan Stoza289ade12014-02-28 11:17:17 -0800704 item.mTimestamp = timestamp;
705 item.mIsAutoTimestamp = isAutoTimestamp;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800706 item.mDataSpace = dataSpace;
Dan Stoza289ade12014-02-28 11:17:17 -0800707 item.mFrameNumber = mCore->mFrameCounter;
708 item.mSlot = slot;
709 item.mFence = fence;
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700710 item.mIsDroppable = mCore->mAsyncMode ||
711 mCore->mDequeueBufferCannotBlock;
Dan Stoza5065a552015-03-17 16:23:42 -0700712 item.mSurfaceDamage = surfaceDamage;
Dan Stoza289ade12014-02-28 11:17:17 -0800713
Ruben Brunk1681d952014-06-27 15:51:55 -0700714 mStickyTransform = stickyTransform;
715
Dan Stoza289ade12014-02-28 11:17:17 -0800716 if (mCore->mQueue.empty()) {
717 // When the queue is empty, we can ignore mDequeueBufferCannotBlock
718 // and simply queue this buffer
719 mCore->mQueue.push_back(item);
Dan Stoza8dc55392014-11-04 11:37:46 -0800720 frameAvailableListener = mCore->mConsumerListener;
Dan Stoza289ade12014-02-28 11:17:17 -0800721 } else {
722 // When the queue is not empty, we need to look at the front buffer
723 // state to see if we need to replace it
724 BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
725 if (front->mIsDroppable) {
726 // If the front queued buffer is still being tracked, we first
727 // mark it as freed
728 if (mCore->stillTracking(front)) {
729 mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
Dan Stoza0de7ea72015-04-23 13:20:51 -0700730 mCore->mFreeBuffers.push_front(front->mSlot);
Dan Stoza289ade12014-02-28 11:17:17 -0800731 }
732 // Overwrite the droppable buffer with the incoming one
733 *front = item;
Dan Stoza8dc55392014-11-04 11:37:46 -0800734 frameReplacedListener = mCore->mConsumerListener;
Dan Stoza289ade12014-02-28 11:17:17 -0800735 } else {
736 mCore->mQueue.push_back(item);
Dan Stoza8dc55392014-11-04 11:37:46 -0800737 frameAvailableListener = mCore->mConsumerListener;
Dan Stoza289ade12014-02-28 11:17:17 -0800738 }
739 }
740
741 mCore->mBufferHasBeenQueued = true;
742 mCore->mDequeueCondition.broadcast();
743
744 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800745 mCore->mTransformHint,
746 static_cast<uint32_t>(mCore->mQueue.size()));
Dan Stoza289ade12014-02-28 11:17:17 -0800747
748 ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
Dan Stoza8dc55392014-11-04 11:37:46 -0800749
750 // Take a ticket for the callback functions
751 callbackTicket = mNextCallbackTicket++;
Dan Stoza0de7ea72015-04-23 13:20:51 -0700752
753 mCore->validateConsistencyLocked();
Dan Stoza289ade12014-02-28 11:17:17 -0800754 } // Autolock scope
755
Eric Penner99a0afb2014-09-30 11:28:30 -0700756 // Wait without lock held
757 if (mCore->mConnectedApi == NATIVE_WINDOW_API_EGL) {
758 // Waiting here allows for two full buffers to be queued but not a
759 // third. In the event that frames take varying time, this makes a
760 // small trade-off in favor of latency rather than throughput.
761 mLastQueueBufferFence->waitForever("Throttling EGL Production");
762 mLastQueueBufferFence = fence;
763 }
764
Dan Stoza8dc55392014-11-04 11:37:46 -0800765 // Don't send the GraphicBuffer through the callback, and don't send
766 // the slot number, since the consumer shouldn't need it
767 item.mGraphicBuffer.clear();
768 item.mSlot = BufferItem::INVALID_BUFFER_SLOT;
769
770 // Call back without the main BufferQueue lock held, but with the callback
771 // lock held so we can ensure that callbacks occur in order
772 {
773 Mutex::Autolock lock(mCallbackMutex);
774 while (callbackTicket != mCurrentCallbackTicket) {
775 mCallbackCondition.wait(mCallbackMutex);
776 }
777
778 if (frameAvailableListener != NULL) {
779 frameAvailableListener->onFrameAvailable(item);
780 } else if (frameReplacedListener != NULL) {
781 frameReplacedListener->onFrameReplaced(item);
782 }
783
784 ++mCurrentCallbackTicket;
785 mCallbackCondition.broadcast();
Dan Stoza289ade12014-02-28 11:17:17 -0800786 }
787
788 return NO_ERROR;
789}
790
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700791status_t BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
Dan Stoza289ade12014-02-28 11:17:17 -0800792 ATRACE_CALL();
793 BQ_LOGV("cancelBuffer: slot %d", slot);
794 Mutex::Autolock lock(mCore->mMutex);
795
796 if (mCore->mIsAbandoned) {
797 BQ_LOGE("cancelBuffer: BufferQueue has been abandoned");
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700798 return NO_INIT;
799 }
800
801 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
802 BQ_LOGE("cancelBuffer: BufferQueue has no connected producer");
803 return NO_INIT;
Dan Stoza289ade12014-02-28 11:17:17 -0800804 }
805
Dan Stoza3e96f192014-03-03 10:16:19 -0800806 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
Dan Stoza289ade12014-02-28 11:17:17 -0800807 BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)",
Dan Stoza3e96f192014-03-03 10:16:19 -0800808 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700809 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800810 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
811 BQ_LOGE("cancelBuffer: slot %d is not owned by the producer "
812 "(state = %d)", slot, mSlots[slot].mBufferState);
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700813 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800814 } else if (fence == NULL) {
815 BQ_LOGE("cancelBuffer: fence is NULL");
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700816 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800817 }
818
Dan Stoza0de7ea72015-04-23 13:20:51 -0700819 mCore->mFreeBuffers.push_front(slot);
Dan Stoza289ade12014-02-28 11:17:17 -0800820 mSlots[slot].mBufferState = BufferSlot::FREE;
Dan Stoza289ade12014-02-28 11:17:17 -0800821 mSlots[slot].mFence = fence;
822 mCore->mDequeueCondition.broadcast();
Dan Stoza0de7ea72015-04-23 13:20:51 -0700823 mCore->validateConsistencyLocked();
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700824
825 return NO_ERROR;
Dan Stoza289ade12014-02-28 11:17:17 -0800826}
827
828int BufferQueueProducer::query(int what, int *outValue) {
829 ATRACE_CALL();
830 Mutex::Autolock lock(mCore->mMutex);
831
832 if (outValue == NULL) {
833 BQ_LOGE("query: outValue was NULL");
834 return BAD_VALUE;
835 }
836
837 if (mCore->mIsAbandoned) {
838 BQ_LOGE("query: BufferQueue has been abandoned");
839 return NO_INIT;
840 }
841
842 int value;
843 switch (what) {
844 case NATIVE_WINDOW_WIDTH:
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800845 value = static_cast<int32_t>(mCore->mDefaultWidth);
Dan Stoza289ade12014-02-28 11:17:17 -0800846 break;
847 case NATIVE_WINDOW_HEIGHT:
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800848 value = static_cast<int32_t>(mCore->mDefaultHeight);
Dan Stoza289ade12014-02-28 11:17:17 -0800849 break;
850 case NATIVE_WINDOW_FORMAT:
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800851 value = static_cast<int32_t>(mCore->mDefaultBufferFormat);
Dan Stoza289ade12014-02-28 11:17:17 -0800852 break;
853 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700854 value = mCore->getMinUndequeuedBufferCountLocked();
Dan Stoza289ade12014-02-28 11:17:17 -0800855 break;
Ruben Brunk1681d952014-06-27 15:51:55 -0700856 case NATIVE_WINDOW_STICKY_TRANSFORM:
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800857 value = static_cast<int32_t>(mStickyTransform);
Ruben Brunk1681d952014-06-27 15:51:55 -0700858 break;
Dan Stoza289ade12014-02-28 11:17:17 -0800859 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
860 value = (mCore->mQueue.size() > 1);
861 break;
862 case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800863 value = static_cast<int32_t>(mCore->mConsumerUsageBits);
Dan Stoza289ade12014-02-28 11:17:17 -0800864 break;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800865 case NATIVE_WINDOW_DEFAULT_DATASPACE:
866 value = static_cast<int32_t>(mCore->mDefaultBufferDataSpace);
867 break;
Dan Stoza4afd8b62015-02-25 16:49:08 -0800868 case NATIVE_WINDOW_BUFFER_AGE:
869 if (mCore->mBufferAge > INT32_MAX) {
870 value = 0;
871 } else {
872 value = static_cast<int32_t>(mCore->mBufferAge);
873 }
874 break;
Dan Stoza289ade12014-02-28 11:17:17 -0800875 default:
876 return BAD_VALUE;
877 }
878
879 BQ_LOGV("query: %d? %d", what, value);
880 *outValue = value;
881 return NO_ERROR;
882}
883
Dan Stozaf0eaf252014-03-21 13:05:51 -0700884status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
Dan Stoza289ade12014-02-28 11:17:17 -0800885 int api, bool producerControlledByApp, QueueBufferOutput *output) {
886 ATRACE_CALL();
887 Mutex::Autolock lock(mCore->mMutex);
888 mConsumerName = mCore->mConsumerName;
889 BQ_LOGV("connect(P): api=%d producerControlledByApp=%s", api,
890 producerControlledByApp ? "true" : "false");
891
Dan Stozaae3c3682014-04-18 15:43:35 -0700892 if (mCore->mIsAbandoned) {
893 BQ_LOGE("connect(P): BufferQueue has been abandoned");
894 return NO_INIT;
895 }
Dan Stoza289ade12014-02-28 11:17:17 -0800896
Dan Stozaae3c3682014-04-18 15:43:35 -0700897 if (mCore->mConsumerListener == NULL) {
898 BQ_LOGE("connect(P): BufferQueue has no consumer");
899 return NO_INIT;
900 }
Dan Stoza289ade12014-02-28 11:17:17 -0800901
Dan Stozaae3c3682014-04-18 15:43:35 -0700902 if (output == NULL) {
903 BQ_LOGE("connect(P): output was NULL");
904 return BAD_VALUE;
905 }
Dan Stoza289ade12014-02-28 11:17:17 -0800906
Dan Stozaae3c3682014-04-18 15:43:35 -0700907 if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
908 BQ_LOGE("connect(P): already connected (cur=%d req=%d)",
909 mCore->mConnectedApi, api);
910 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800911 }
912
913 int status = NO_ERROR;
914 switch (api) {
915 case NATIVE_WINDOW_API_EGL:
916 case NATIVE_WINDOW_API_CPU:
917 case NATIVE_WINDOW_API_MEDIA:
918 case NATIVE_WINDOW_API_CAMERA:
919 mCore->mConnectedApi = api;
920 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800921 mCore->mTransformHint,
922 static_cast<uint32_t>(mCore->mQueue.size()));
Dan Stoza289ade12014-02-28 11:17:17 -0800923
924 // Set up a death notification so that we can disconnect
925 // automatically if the remote producer dies
Dan Stozaf0eaf252014-03-21 13:05:51 -0700926 if (listener != NULL &&
Marco Nelissen097ca272014-11-14 08:01:01 -0800927 IInterface::asBinder(listener)->remoteBinder() != NULL) {
928 status = IInterface::asBinder(listener)->linkToDeath(
Dan Stoza289ade12014-02-28 11:17:17 -0800929 static_cast<IBinder::DeathRecipient*>(this));
Dan Stozaf0eaf252014-03-21 13:05:51 -0700930 if (status != NO_ERROR) {
Dan Stoza289ade12014-02-28 11:17:17 -0800931 BQ_LOGE("connect(P): linkToDeath failed: %s (%d)",
932 strerror(-status), status);
933 }
934 }
Dan Stozaf0eaf252014-03-21 13:05:51 -0700935 mCore->mConnectedProducerListener = listener;
Dan Stoza289ade12014-02-28 11:17:17 -0800936 break;
937 default:
938 BQ_LOGE("connect(P): unknown API %d", api);
939 status = BAD_VALUE;
940 break;
941 }
942
943 mCore->mBufferHasBeenQueued = false;
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700944 mCore->mDequeueBufferCannotBlock = mCore->mConsumerControlledByApp &&
945 producerControlledByApp;
Dan Stoza2b83cc92015-05-12 14:55:15 -0700946 mCore->mAllowAllocation = true;
Dan Stoza289ade12014-02-28 11:17:17 -0800947
948 return status;
949}
950
951status_t BufferQueueProducer::disconnect(int api) {
952 ATRACE_CALL();
953 BQ_LOGV("disconnect(P): api %d", api);
954
955 int status = NO_ERROR;
956 sp<IConsumerListener> listener;
957 { // Autolock scope
958 Mutex::Autolock lock(mCore->mMutex);
Antoine Labour78014f32014-07-15 21:17:03 -0700959 mCore->waitWhileAllocatingLocked();
Dan Stoza289ade12014-02-28 11:17:17 -0800960
961 if (mCore->mIsAbandoned) {
962 // It's not really an error to disconnect after the surface has
963 // been abandoned; it should just be a no-op.
964 return NO_ERROR;
965 }
966
967 switch (api) {
968 case NATIVE_WINDOW_API_EGL:
969 case NATIVE_WINDOW_API_CPU:
970 case NATIVE_WINDOW_API_MEDIA:
971 case NATIVE_WINDOW_API_CAMERA:
972 if (mCore->mConnectedApi == api) {
973 mCore->freeAllBuffersLocked();
974
975 // Remove our death notification callback if we have one
Dan Stozaf0eaf252014-03-21 13:05:51 -0700976 if (mCore->mConnectedProducerListener != NULL) {
977 sp<IBinder> token =
Marco Nelissen097ca272014-11-14 08:01:01 -0800978 IInterface::asBinder(mCore->mConnectedProducerListener);
Dan Stoza289ade12014-02-28 11:17:17 -0800979 // This can fail if we're here because of the death
980 // notification, but we just ignore it
981 token->unlinkToDeath(
982 static_cast<IBinder::DeathRecipient*>(this));
983 }
Dan Stozaf0eaf252014-03-21 13:05:51 -0700984 mCore->mConnectedProducerListener = NULL;
Dan Stoza289ade12014-02-28 11:17:17 -0800985 mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
Jesse Hall399184a2014-03-03 15:42:54 -0800986 mCore->mSidebandStream.clear();
Dan Stoza289ade12014-02-28 11:17:17 -0800987 mCore->mDequeueCondition.broadcast();
988 listener = mCore->mConsumerListener;
Amith Dsouza4f21a4c2015-06-30 22:54:16 -0700989 } else if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
990 BQ_LOGE("disconnect(P): still connected to another API "
Dan Stoza289ade12014-02-28 11:17:17 -0800991 "(cur=%d req=%d)", mCore->mConnectedApi, api);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800992 status = BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800993 }
994 break;
995 default:
996 BQ_LOGE("disconnect(P): unknown API %d", api);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800997 status = BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800998 break;
999 }
1000 } // Autolock scope
1001
1002 // Call back without lock held
1003 if (listener != NULL) {
1004 listener->onBuffersReleased();
1005 }
1006
1007 return status;
1008}
1009
Jesse Hall399184a2014-03-03 15:42:54 -08001010status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) {
Wonsik Kimafe30812014-03-31 23:16:08 +09001011 sp<IConsumerListener> listener;
1012 { // Autolock scope
1013 Mutex::Autolock _l(mCore->mMutex);
1014 mCore->mSidebandStream = stream;
1015 listener = mCore->mConsumerListener;
1016 } // Autolock scope
1017
1018 if (listener != NULL) {
1019 listener->onSidebandStreamChanged();
1020 }
Jesse Hall399184a2014-03-03 15:42:54 -08001021 return NO_ERROR;
1022}
1023
Pablo Ceballos567dbbb2015-08-26 18:59:08 -07001024void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height,
1025 PixelFormat format, uint32_t usage) {
Antoine Labour78014f32014-07-15 21:17:03 -07001026 ATRACE_CALL();
1027 while (true) {
1028 Vector<int> freeSlots;
1029 size_t newBufferCount = 0;
1030 uint32_t allocWidth = 0;
1031 uint32_t allocHeight = 0;
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001032 PixelFormat allocFormat = PIXEL_FORMAT_UNKNOWN;
Antoine Labour78014f32014-07-15 21:17:03 -07001033 uint32_t allocUsage = 0;
1034 { // Autolock scope
1035 Mutex::Autolock lock(mCore->mMutex);
1036 mCore->waitWhileAllocatingLocked();
Dan Stoza29a3e902014-06-20 13:13:57 -07001037
Dan Stoza9de72932015-04-16 17:28:43 -07001038 if (!mCore->mAllowAllocation) {
1039 BQ_LOGE("allocateBuffers: allocation is not allowed for this "
1040 "BufferQueue");
1041 return;
1042 }
1043
Antoine Labour78014f32014-07-15 21:17:03 -07001044 int currentBufferCount = 0;
1045 for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
1046 if (mSlots[slot].mGraphicBuffer != NULL) {
1047 ++currentBufferCount;
1048 } else {
1049 if (mSlots[slot].mBufferState != BufferSlot::FREE) {
1050 BQ_LOGE("allocateBuffers: slot %d without buffer is not FREE",
1051 slot);
1052 continue;
1053 }
Dan Stoza29a3e902014-06-20 13:13:57 -07001054
Antoine Labour11f14872014-07-25 18:14:42 -07001055 freeSlots.push_back(slot);
Antoine Labour78014f32014-07-15 21:17:03 -07001056 }
1057 }
1058
Pablo Ceballos567dbbb2015-08-26 18:59:08 -07001059 int maxBufferCount = mCore->getMaxBufferCountLocked();
Antoine Labour78014f32014-07-15 21:17:03 -07001060 BQ_LOGV("allocateBuffers: allocating from %d buffers up to %d buffers",
1061 currentBufferCount, maxBufferCount);
1062 if (maxBufferCount <= currentBufferCount)
1063 return;
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001064 newBufferCount =
1065 static_cast<size_t>(maxBufferCount - currentBufferCount);
Antoine Labour78014f32014-07-15 21:17:03 -07001066 if (freeSlots.size() < newBufferCount) {
1067 BQ_LOGE("allocateBuffers: ran out of free slots");
1068 return;
1069 }
1070 allocWidth = width > 0 ? width : mCore->mDefaultWidth;
1071 allocHeight = height > 0 ? height : mCore->mDefaultHeight;
1072 allocFormat = format != 0 ? format : mCore->mDefaultBufferFormat;
1073 allocUsage = usage | mCore->mConsumerUsageBits;
1074
1075 mCore->mIsAllocating = true;
1076 } // Autolock scope
1077
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001078 Vector<sp<GraphicBuffer>> buffers;
Antoine Labour78014f32014-07-15 21:17:03 -07001079 for (size_t i = 0; i < newBufferCount; ++i) {
1080 status_t result = NO_ERROR;
1081 sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
1082 allocWidth, allocHeight, allocFormat, allocUsage, &result));
1083 if (result != NO_ERROR) {
1084 BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format"
1085 " %u, usage %u)", width, height, format, usage);
1086 Mutex::Autolock lock(mCore->mMutex);
1087 mCore->mIsAllocating = false;
1088 mCore->mIsAllocatingCondition.broadcast();
1089 return;
1090 }
1091 buffers.push_back(graphicBuffer);
1092 }
1093
1094 { // Autolock scope
1095 Mutex::Autolock lock(mCore->mMutex);
1096 uint32_t checkWidth = width > 0 ? width : mCore->mDefaultWidth;
1097 uint32_t checkHeight = height > 0 ? height : mCore->mDefaultHeight;
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001098 PixelFormat checkFormat = format != 0 ?
1099 format : mCore->mDefaultBufferFormat;
Antoine Labour78014f32014-07-15 21:17:03 -07001100 uint32_t checkUsage = usage | mCore->mConsumerUsageBits;
1101 if (checkWidth != allocWidth || checkHeight != allocHeight ||
1102 checkFormat != allocFormat || checkUsage != allocUsage) {
1103 // Something changed while we released the lock. Retry.
1104 BQ_LOGV("allocateBuffers: size/format/usage changed while allocating. Retrying.");
1105 mCore->mIsAllocating = false;
1106 mCore->mIsAllocatingCondition.broadcast();
Dan Stoza29a3e902014-06-20 13:13:57 -07001107 continue;
1108 }
1109
Antoine Labour78014f32014-07-15 21:17:03 -07001110 for (size_t i = 0; i < newBufferCount; ++i) {
1111 int slot = freeSlots[i];
1112 if (mSlots[slot].mBufferState != BufferSlot::FREE) {
1113 // A consumer allocated the FREE slot with attachBuffer. Discard the buffer we
1114 // allocated.
1115 BQ_LOGV("allocateBuffers: slot %d was acquired while allocating. "
1116 "Dropping allocated buffer.", slot);
1117 continue;
1118 }
1119 mCore->freeBufferLocked(slot); // Clean up the slot first
1120 mSlots[slot].mGraphicBuffer = buffers[i];
Antoine Labour78014f32014-07-15 21:17:03 -07001121 mSlots[slot].mFence = Fence::NO_FENCE;
Dan Stoza0de7ea72015-04-23 13:20:51 -07001122
1123 // freeBufferLocked puts this slot on the free slots list. Since
1124 // we then attached a buffer, move the slot to free buffer list.
1125 mCore->mFreeSlots.erase(slot);
1126 mCore->mFreeBuffers.push_front(slot);
1127
Antoine Labour78014f32014-07-15 21:17:03 -07001128 BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d", slot);
1129 }
Dan Stoza29a3e902014-06-20 13:13:57 -07001130
Antoine Labour78014f32014-07-15 21:17:03 -07001131 mCore->mIsAllocating = false;
1132 mCore->mIsAllocatingCondition.broadcast();
Dan Stoza0de7ea72015-04-23 13:20:51 -07001133 mCore->validateConsistencyLocked();
Antoine Labour78014f32014-07-15 21:17:03 -07001134 } // Autolock scope
Dan Stoza29a3e902014-06-20 13:13:57 -07001135 }
1136}
1137
Dan Stoza9de72932015-04-16 17:28:43 -07001138status_t BufferQueueProducer::allowAllocation(bool allow) {
1139 ATRACE_CALL();
1140 BQ_LOGV("allowAllocation: %s", allow ? "true" : "false");
1141
1142 Mutex::Autolock lock(mCore->mMutex);
1143 mCore->mAllowAllocation = allow;
1144 return NO_ERROR;
1145}
1146
Dan Stoza812ed062015-06-02 15:45:22 -07001147status_t BufferQueueProducer::setGenerationNumber(uint32_t generationNumber) {
1148 ATRACE_CALL();
1149 BQ_LOGV("setGenerationNumber: %u", generationNumber);
1150
1151 Mutex::Autolock lock(mCore->mMutex);
1152 mCore->mGenerationNumber = generationNumber;
1153 return NO_ERROR;
1154}
1155
Dan Stozac6f30bd2015-06-08 09:32:50 -07001156String8 BufferQueueProducer::getConsumerName() const {
1157 ATRACE_CALL();
1158 BQ_LOGV("getConsumerName: %s", mConsumerName.string());
1159 return mConsumerName;
1160}
1161
Dan Stoza289ade12014-02-28 11:17:17 -08001162void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
1163 // If we're here, it means that a producer we were connected to died.
1164 // We're guaranteed that we are still connected to it because we remove
1165 // this callback upon disconnect. It's therefore safe to read mConnectedApi
1166 // without synchronization here.
1167 int api = mCore->mConnectedApi;
1168 disconnect(api);
1169}
1170
1171} // namespace android