blob: 30b6c334a303a9f87fc368735fc41ed5eae74e99 [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
Pablo Ceballos9e314332016-01-12 13:49:19 -080023#if DEBUG_ONLY_CODE
24#define VALIDATE_CONSISTENCY() do { mCore->validateConsistencyLocked(); } while (0)
25#else
26#define VALIDATE_CONSISTENCY()
27#endif
28
Dan Stoza289ade12014-02-28 11:17:17 -080029#define EGL_EGLEXT_PROTOTYPES
30
31#include <gui/BufferItem.h>
32#include <gui/BufferQueueCore.h>
33#include <gui/BufferQueueProducer.h>
John Reck1a61da52016-04-28 13:18:15 -070034#include <gui/GLConsumer.h>
Dan Stoza289ade12014-02-28 11:17:17 -080035#include <gui/IConsumerListener.h>
36#include <gui/IGraphicBufferAlloc.h>
Dan Stozaf0eaf252014-03-21 13:05:51 -070037#include <gui/IProducerListener.h>
Dan Stoza289ade12014-02-28 11:17:17 -080038
39#include <utils/Log.h>
40#include <utils/Trace.h>
41
42namespace android {
43
Irvel468051e2016-06-13 16:44:44 -070044BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core,
45 bool consumerIsSurfaceFlinger) :
Dan Stoza289ade12014-02-28 11:17:17 -080046 mCore(core),
47 mSlots(core->mSlots),
Ruben Brunk1681d952014-06-27 15:51:55 -070048 mConsumerName(),
Eric Penner99a0afb2014-09-30 11:28:30 -070049 mStickyTransform(0),
Irvel468051e2016-06-13 16:44:44 -070050 mConsumerIsSurfaceFlinger(consumerIsSurfaceFlinger),
Dan Stoza8dc55392014-11-04 11:37:46 -080051 mLastQueueBufferFence(Fence::NO_FENCE),
Pablo Ceballosbd3577e2016-06-20 17:40:34 -070052 mLastQueuedTransform(0),
Dan Stoza8dc55392014-11-04 11:37:46 -080053 mCallbackMutex(),
54 mNextCallbackTicket(0),
55 mCurrentCallbackTicket(0),
Dan Stoza127fc632015-06-30 13:43:32 -070056 mCallbackCondition(),
57 mDequeueTimeout(-1) {}
Dan Stoza289ade12014-02-28 11:17:17 -080058
59BufferQueueProducer::~BufferQueueProducer() {}
60
61status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
62 ATRACE_CALL();
63 BQ_LOGV("requestBuffer: slot %d", slot);
64 Mutex::Autolock lock(mCore->mMutex);
65
66 if (mCore->mIsAbandoned) {
67 BQ_LOGE("requestBuffer: BufferQueue has been abandoned");
68 return NO_INIT;
69 }
70
Pablo Ceballos583b1b32015-09-03 18:23:52 -070071 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
72 BQ_LOGE("requestBuffer: BufferQueue has no connected producer");
73 return NO_INIT;
74 }
75
Dan Stoza3e96f192014-03-03 10:16:19 -080076 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
Dan Stoza289ade12014-02-28 11:17:17 -080077 BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)",
Dan Stoza3e96f192014-03-03 10:16:19 -080078 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
Dan Stoza289ade12014-02-28 11:17:17 -080079 return BAD_VALUE;
Pablo Ceballosccdfd602015-10-07 15:05:45 -070080 } else if (!mSlots[slot].mBufferState.isDequeued()) {
Dan Stoza289ade12014-02-28 11:17:17 -080081 BQ_LOGE("requestBuffer: slot %d is not owned by the producer "
Pablo Ceballosccdfd602015-10-07 15:05:45 -070082 "(state = %s)", slot, mSlots[slot].mBufferState.string());
Dan Stoza289ade12014-02-28 11:17:17 -080083 return BAD_VALUE;
84 }
85
86 mSlots[slot].mRequestBufferCalled = true;
87 *buf = mSlots[slot].mGraphicBuffer;
88 return NO_ERROR;
89}
90
Pablo Ceballosfa455352015-08-12 17:47:47 -070091status_t BufferQueueProducer::setMaxDequeuedBufferCount(
92 int maxDequeuedBuffers) {
93 ATRACE_CALL();
94 BQ_LOGV("setMaxDequeuedBufferCount: maxDequeuedBuffers = %d",
95 maxDequeuedBuffers);
96
Pablo Ceballos981066c2016-02-18 12:54:37 -080097 sp<IConsumerListener> listener;
Pablo Ceballosfa455352015-08-12 17:47:47 -070098 { // Autolock scope
99 Mutex::Autolock lock(mCore->mMutex);
100 mCore->waitWhileAllocatingLocked();
101
102 if (mCore->mIsAbandoned) {
103 BQ_LOGE("setMaxDequeuedBufferCount: BufferQueue has been "
104 "abandoned");
105 return NO_INIT;
106 }
107
Pablo Ceballos245cc5b2016-04-19 11:33:00 -0700108 if (maxDequeuedBuffers == mCore->mMaxDequeuedBufferCount) {
109 return NO_ERROR;
110 }
111
Pablo Ceballos72daab62015-12-07 16:38:43 -0800112 // The new maxDequeuedBuffer count should not be violated by the number
113 // of currently dequeued buffers
114 int dequeuedCount = 0;
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800115 for (int s : mCore->mActiveBuffers) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700116 if (mSlots[s].mBufferState.isDequeued()) {
Pablo Ceballos72daab62015-12-07 16:38:43 -0800117 dequeuedCount++;
Pablo Ceballosfa455352015-08-12 17:47:47 -0700118 }
119 }
Pablo Ceballos72daab62015-12-07 16:38:43 -0800120 if (dequeuedCount > maxDequeuedBuffers) {
121 BQ_LOGE("setMaxDequeuedBufferCount: the requested maxDequeuedBuffer"
122 "count (%d) exceeds the current dequeued buffer count (%d)",
123 maxDequeuedBuffers, dequeuedCount);
124 return BAD_VALUE;
125 }
Pablo Ceballosfa455352015-08-12 17:47:47 -0700126
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700127 int bufferCount = mCore->getMinUndequeuedBufferCountLocked();
Pablo Ceballosfa455352015-08-12 17:47:47 -0700128 bufferCount += maxDequeuedBuffers;
129
130 if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
131 BQ_LOGE("setMaxDequeuedBufferCount: bufferCount %d too large "
132 "(max %d)", bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
133 return BAD_VALUE;
134 }
135
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700136 const int minBufferSlots = mCore->getMinMaxBufferCountLocked();
Pablo Ceballosfa455352015-08-12 17:47:47 -0700137 if (bufferCount < minBufferSlots) {
138 BQ_LOGE("setMaxDequeuedBufferCount: requested buffer count %d is "
139 "less than minimum %d", bufferCount, minBufferSlots);
140 return BAD_VALUE;
141 }
142
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700143 if (bufferCount > mCore->mMaxBufferCount) {
144 BQ_LOGE("setMaxDequeuedBufferCount: %d dequeued buffers would "
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700145 "exceed the maxBufferCount (%d) (maxAcquired %d async %d "
146 "mDequeuedBufferCannotBlock %d)", maxDequeuedBuffers,
147 mCore->mMaxBufferCount, mCore->mMaxAcquiredBufferCount,
148 mCore->mAsyncMode, mCore->mDequeueBufferCannotBlock);
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700149 return BAD_VALUE;
150 }
151
Pablo Ceballos72daab62015-12-07 16:38:43 -0800152 int delta = maxDequeuedBuffers - mCore->mMaxDequeuedBufferCount;
Pablo Ceballos981066c2016-02-18 12:54:37 -0800153 if (!mCore->adjustAvailableSlotsLocked(delta)) {
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800154 return BAD_VALUE;
155 }
Pablo Ceballosfa455352015-08-12 17:47:47 -0700156 mCore->mMaxDequeuedBufferCount = maxDequeuedBuffers;
Pablo Ceballos9e314332016-01-12 13:49:19 -0800157 VALIDATE_CONSISTENCY();
Pablo Ceballos72daab62015-12-07 16:38:43 -0800158 if (delta < 0) {
Pablo Ceballos981066c2016-02-18 12:54:37 -0800159 listener = mCore->mConsumerListener;
Pablo Ceballos72daab62015-12-07 16:38:43 -0800160 }
Pablo Ceballosfa455352015-08-12 17:47:47 -0700161 mCore->mDequeueCondition.broadcast();
Pablo Ceballosfa455352015-08-12 17:47:47 -0700162 } // Autolock scope
163
164 // Call back without lock held
Pablo Ceballos981066c2016-02-18 12:54:37 -0800165 if (listener != NULL) {
166 listener->onBuffersReleased();
Pablo Ceballosfa455352015-08-12 17:47:47 -0700167 }
168
169 return NO_ERROR;
170}
171
172status_t BufferQueueProducer::setAsyncMode(bool async) {
173 ATRACE_CALL();
174 BQ_LOGV("setAsyncMode: async = %d", async);
175
Pablo Ceballos981066c2016-02-18 12:54:37 -0800176 sp<IConsumerListener> listener;
Pablo Ceballosfa455352015-08-12 17:47:47 -0700177 { // Autolock scope
178 Mutex::Autolock lock(mCore->mMutex);
179 mCore->waitWhileAllocatingLocked();
180
181 if (mCore->mIsAbandoned) {
182 BQ_LOGE("setAsyncMode: BufferQueue has been abandoned");
183 return NO_INIT;
184 }
185
Pablo Ceballos245cc5b2016-04-19 11:33:00 -0700186 if (async == mCore->mAsyncMode) {
187 return NO_ERROR;
188 }
189
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700190 if ((mCore->mMaxAcquiredBufferCount + mCore->mMaxDequeuedBufferCount +
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700191 (async || mCore->mDequeueBufferCannotBlock ? 1 : 0)) >
192 mCore->mMaxBufferCount) {
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700193 BQ_LOGE("setAsyncMode(%d): this call would cause the "
194 "maxBufferCount (%d) to be exceeded (maxAcquired %d "
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700195 "maxDequeued %d mDequeueBufferCannotBlock %d)", async,
196 mCore->mMaxBufferCount, mCore->mMaxAcquiredBufferCount,
197 mCore->mMaxDequeuedBufferCount,
198 mCore->mDequeueBufferCannotBlock);
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700199 return BAD_VALUE;
200 }
201
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800202 int delta = mCore->getMaxBufferCountLocked(async,
203 mCore->mDequeueBufferCannotBlock, mCore->mMaxBufferCount)
204 - mCore->getMaxBufferCountLocked();
205
Pablo Ceballos981066c2016-02-18 12:54:37 -0800206 if (!mCore->adjustAvailableSlotsLocked(delta)) {
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800207 BQ_LOGE("setAsyncMode: BufferQueue failed to adjust the number of "
208 "available slots. Delta = %d", delta);
209 return BAD_VALUE;
210 }
Pablo Ceballosfa455352015-08-12 17:47:47 -0700211 mCore->mAsyncMode = async;
Pablo Ceballos9e314332016-01-12 13:49:19 -0800212 VALIDATE_CONSISTENCY();
Pablo Ceballosfa455352015-08-12 17:47:47 -0700213 mCore->mDequeueCondition.broadcast();
Pablo Ceballos245cc5b2016-04-19 11:33:00 -0700214 if (delta < 0) {
215 listener = mCore->mConsumerListener;
216 }
Pablo Ceballosfa455352015-08-12 17:47:47 -0700217 } // Autolock scope
218
219 // Call back without lock held
Pablo Ceballos981066c2016-02-18 12:54:37 -0800220 if (listener != NULL) {
221 listener->onBuffersReleased();
Pablo Ceballosfa455352015-08-12 17:47:47 -0700222 }
223 return NO_ERROR;
224}
225
Dan Stoza5ecfb682016-01-04 17:01:02 -0800226int BufferQueueProducer::getFreeBufferLocked() const {
227 if (mCore->mFreeBuffers.empty()) {
228 return BufferQueueCore::INVALID_BUFFER_SLOT;
229 }
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800230 int slot = mCore->mFreeBuffers.front();
Dan Stoza5ecfb682016-01-04 17:01:02 -0800231 mCore->mFreeBuffers.pop_front();
232 return slot;
233}
234
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800235int BufferQueueProducer::getFreeSlotLocked() const {
Dan Stoza5ecfb682016-01-04 17:01:02 -0800236 if (mCore->mFreeSlots.empty()) {
237 return BufferQueueCore::INVALID_BUFFER_SLOT;
238 }
Pablo Ceballosdce5c552016-02-10 15:43:22 -0800239 int slot = *(mCore->mFreeSlots.begin());
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800240 mCore->mFreeSlots.erase(slot);
Pablo Ceballosdce5c552016-02-10 15:43:22 -0800241 return slot;
Dan Stoza5ecfb682016-01-04 17:01:02 -0800242}
243
244status_t BufferQueueProducer::waitForFreeSlotThenRelock(FreeSlotCaller caller,
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800245 int* found) const {
Dan Stoza5ecfb682016-01-04 17:01:02 -0800246 auto callerString = (caller == FreeSlotCaller::Dequeue) ?
247 "dequeueBuffer" : "attachBuffer";
Dan Stoza9f3053d2014-03-06 15:14:33 -0800248 bool tryAgain = true;
249 while (tryAgain) {
250 if (mCore->mIsAbandoned) {
Dan Stoza5ecfb682016-01-04 17:01:02 -0800251 BQ_LOGE("%s: BufferQueue has been abandoned", callerString);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800252 return NO_INIT;
253 }
254
Dan Stoza9f3053d2014-03-06 15:14:33 -0800255 int dequeuedCount = 0;
256 int acquiredCount = 0;
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800257 for (int s : mCore->mActiveBuffers) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700258 if (mSlots[s].mBufferState.isDequeued()) {
259 ++dequeuedCount;
260 }
261 if (mSlots[s].mBufferState.isAcquired()) {
262 ++acquiredCount;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800263 }
264 }
265
Pablo Ceballose5b755a2015-08-13 16:18:19 -0700266 // Producers are not allowed to dequeue more than
267 // mMaxDequeuedBufferCount buffers.
268 // This check is only done if a buffer has already been queued
269 if (mCore->mBufferHasBeenQueued &&
270 dequeuedCount >= mCore->mMaxDequeuedBufferCount) {
271 BQ_LOGE("%s: attempting to exceed the max dequeued buffer count "
Dan Stoza5ecfb682016-01-04 17:01:02 -0800272 "(%d)", callerString, mCore->mMaxDequeuedBufferCount);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800273 return INVALID_OPERATION;
274 }
275
Dan Stoza0de7ea72015-04-23 13:20:51 -0700276 *found = BufferQueueCore::INVALID_BUFFER_SLOT;
277
Dan Stozaae3c3682014-04-18 15:43:35 -0700278 // If we disconnect and reconnect quickly, we can be in a state where
279 // our slots are empty but we have many buffers in the queue. This can
280 // cause us to run out of memory if we outrun the consumer. Wait here if
281 // it looks like we have too many buffers queued up.
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800282 const int maxBufferCount = mCore->getMaxBufferCountLocked();
Mark Salyzyn8f515ce2014-06-09 14:32:04 -0700283 bool tooManyBuffers = mCore->mQueue.size()
284 > static_cast<size_t>(maxBufferCount);
Dan Stozaae3c3682014-04-18 15:43:35 -0700285 if (tooManyBuffers) {
Dan Stoza5ecfb682016-01-04 17:01:02 -0800286 BQ_LOGV("%s: queue size is %zu, waiting", callerString,
Dan Stozaae3c3682014-04-18 15:43:35 -0700287 mCore->mQueue.size());
Dan Stoza0de7ea72015-04-23 13:20:51 -0700288 } else {
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700289 // If in shared buffer mode and a shared buffer exists, always
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700290 // return it.
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700291 if (mCore->mSharedBufferMode && mCore->mSharedBufferSlot !=
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700292 BufferQueueCore::INVALID_BUFFER_SLOT) {
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700293 *found = mCore->mSharedBufferSlot;
Dan Stoza5ecfb682016-01-04 17:01:02 -0800294 } else {
295 if (caller == FreeSlotCaller::Dequeue) {
296 // If we're calling this from dequeue, prefer free buffers
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800297 int slot = getFreeBufferLocked();
Dan Stoza5ecfb682016-01-04 17:01:02 -0800298 if (slot != BufferQueueCore::INVALID_BUFFER_SLOT) {
299 *found = slot;
300 } else if (mCore->mAllowAllocation) {
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800301 *found = getFreeSlotLocked();
Dan Stoza5ecfb682016-01-04 17:01:02 -0800302 }
303 } else {
304 // If we're calling this from attach, prefer free slots
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800305 int slot = getFreeSlotLocked();
Dan Stoza5ecfb682016-01-04 17:01:02 -0800306 if (slot != BufferQueueCore::INVALID_BUFFER_SLOT) {
307 *found = slot;
308 } else {
309 *found = getFreeBufferLocked();
310 }
Dan Stoza0de7ea72015-04-23 13:20:51 -0700311 }
312 }
Dan Stozaae3c3682014-04-18 15:43:35 -0700313 }
314
315 // If no buffer is found, or if the queue has too many buffers
316 // outstanding, wait for a buffer to be acquired or released, or for the
317 // max buffer count to change.
318 tryAgain = (*found == BufferQueueCore::INVALID_BUFFER_SLOT) ||
319 tooManyBuffers;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800320 if (tryAgain) {
321 // Return an error if we're in non-blocking mode (producer and
322 // consumer are controlled by the application).
323 // However, the consumer is allowed to briefly acquire an extra
324 // buffer (which could cause us to have to wait here), which is
325 // okay, since it is only used to implement an atomic acquire +
326 // release (e.g., in GLConsumer::updateTexImage())
Pablo Ceballosfa455352015-08-12 17:47:47 -0700327 if ((mCore->mDequeueBufferCannotBlock || mCore->mAsyncMode) &&
Dan Stoza9f3053d2014-03-06 15:14:33 -0800328 (acquiredCount <= mCore->mMaxAcquiredBufferCount)) {
329 return WOULD_BLOCK;
330 }
Dan Stoza127fc632015-06-30 13:43:32 -0700331 if (mDequeueTimeout >= 0) {
332 status_t result = mCore->mDequeueCondition.waitRelative(
333 mCore->mMutex, mDequeueTimeout);
334 if (result == TIMED_OUT) {
335 return result;
336 }
337 } else {
338 mCore->mDequeueCondition.wait(mCore->mMutex);
339 }
Dan Stoza9f3053d2014-03-06 15:14:33 -0800340 }
341 } // while (tryAgain)
342
343 return NO_ERROR;
344}
345
Dan Stoza289ade12014-02-28 11:17:17 -0800346status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700347 sp<android::Fence> *outFence, uint32_t width, uint32_t height,
348 PixelFormat format, uint32_t usage) {
Dan Stoza289ade12014-02-28 11:17:17 -0800349 ATRACE_CALL();
350 { // Autolock scope
351 Mutex::Autolock lock(mCore->mMutex);
352 mConsumerName = mCore->mConsumerName;
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700353
354 if (mCore->mIsAbandoned) {
355 BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
356 return NO_INIT;
357 }
358
359 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
360 BQ_LOGE("dequeueBuffer: BufferQueue has no connected producer");
361 return NO_INIT;
362 }
Dan Stoza289ade12014-02-28 11:17:17 -0800363 } // Autolock scope
364
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700365 BQ_LOGV("dequeueBuffer: w=%u h=%u format=%#x, usage=%#x", width, height,
366 format, usage);
Dan Stoza289ade12014-02-28 11:17:17 -0800367
368 if ((width && !height) || (!width && height)) {
369 BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height);
370 return BAD_VALUE;
371 }
372
373 status_t returnFlags = NO_ERROR;
374 EGLDisplay eglDisplay = EGL_NO_DISPLAY;
375 EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800376 bool attachedByConsumer = false;
Dan Stoza289ade12014-02-28 11:17:17 -0800377
378 { // Autolock scope
379 Mutex::Autolock lock(mCore->mMutex);
Antoine Labour78014f32014-07-15 21:17:03 -0700380 mCore->waitWhileAllocatingLocked();
Dan Stoza289ade12014-02-28 11:17:17 -0800381
382 if (format == 0) {
383 format = mCore->mDefaultBufferFormat;
384 }
385
386 // Enable the usage bits the consumer requested
387 usage |= mCore->mConsumerUsageBits;
388
Dan Stoza9de72932015-04-16 17:28:43 -0700389 const bool useDefaultSize = !width && !height;
390 if (useDefaultSize) {
391 width = mCore->mDefaultWidth;
392 height = mCore->mDefaultHeight;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800393 }
Dan Stoza289ade12014-02-28 11:17:17 -0800394
Pablo Ceballos981066c2016-02-18 12:54:37 -0800395 int found = BufferItem::INVALID_BUFFER_SLOT;
Dan Stoza9de72932015-04-16 17:28:43 -0700396 while (found == BufferItem::INVALID_BUFFER_SLOT) {
Dan Stoza5ecfb682016-01-04 17:01:02 -0800397 status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Dequeue,
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800398 &found);
Dan Stoza9de72932015-04-16 17:28:43 -0700399 if (status != NO_ERROR) {
400 return status;
401 }
402
403 // This should not happen
404 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
405 BQ_LOGE("dequeueBuffer: no available buffer slots");
406 return -EBUSY;
407 }
408
409 const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
410
411 // If we are not allowed to allocate new buffers,
412 // waitForFreeSlotThenRelock must have returned a slot containing a
413 // buffer. If this buffer would require reallocation to meet the
414 // requested attributes, we free it and attempt to get another one.
415 if (!mCore->mAllowAllocation) {
416 if (buffer->needsReallocation(width, height, format, usage)) {
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700417 if (mCore->mSharedBufferSlot == found) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700418 BQ_LOGE("dequeueBuffer: cannot re-allocate a shared"
419 "buffer");
420 return BAD_VALUE;
421 }
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800422 mCore->mFreeSlots.insert(found);
423 mCore->clearBufferSlotLocked(found);
Dan Stoza9de72932015-04-16 17:28:43 -0700424 found = BufferItem::INVALID_BUFFER_SLOT;
425 continue;
426 }
427 }
Dan Stoza289ade12014-02-28 11:17:17 -0800428 }
429
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800430 const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700431 if (mCore->mSharedBufferSlot == found &&
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800432 buffer->needsReallocation(width, height, format, usage)) {
433 BQ_LOGE("dequeueBuffer: cannot re-allocate a shared"
434 "buffer");
435
436 return BAD_VALUE;
437 }
438
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700439 if (mCore->mSharedBufferSlot != found) {
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800440 mCore->mActiveBuffers.insert(found);
441 }
Dan Stoza289ade12014-02-28 11:17:17 -0800442 *outSlot = found;
443 ATRACE_BUFFER_INDEX(found);
444
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800445 attachedByConsumer = mSlots[found].mNeedsReallocation;
446 mSlots[found].mNeedsReallocation = false;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800447
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700448 mSlots[found].mBufferState.dequeue();
449
Dan Stoza289ade12014-02-28 11:17:17 -0800450 if ((buffer == NULL) ||
Dan Stoza9de72932015-04-16 17:28:43 -0700451 buffer->needsReallocation(width, height, format, usage))
Dan Stoza289ade12014-02-28 11:17:17 -0800452 {
453 mSlots[found].mAcquireCalled = false;
454 mSlots[found].mGraphicBuffer = NULL;
455 mSlots[found].mRequestBufferCalled = false;
456 mSlots[found].mEglDisplay = EGL_NO_DISPLAY;
457 mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
458 mSlots[found].mFence = Fence::NO_FENCE;
Dan Stoza4afd8b62015-02-25 16:49:08 -0800459 mCore->mBufferAge = 0;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700460 mCore->mIsAllocating = true;
Dan Stoza289ade12014-02-28 11:17:17 -0800461
462 returnFlags |= BUFFER_NEEDS_REALLOCATION;
Dan Stoza4afd8b62015-02-25 16:49:08 -0800463 } else {
464 // We add 1 because that will be the frame number when this buffer
465 // is queued
466 mCore->mBufferAge =
467 mCore->mFrameCounter + 1 - mSlots[found].mFrameNumber;
Dan Stoza289ade12014-02-28 11:17:17 -0800468 }
469
Dan Stoza800b41a2015-04-28 14:20:04 -0700470 BQ_LOGV("dequeueBuffer: setting buffer age to %" PRIu64,
471 mCore->mBufferAge);
Dan Stoza4afd8b62015-02-25 16:49:08 -0800472
Dan Stoza289ade12014-02-28 11:17:17 -0800473 if (CC_UNLIKELY(mSlots[found].mFence == NULL)) {
474 BQ_LOGE("dequeueBuffer: about to return a NULL fence - "
475 "slot=%d w=%d h=%d format=%u",
476 found, buffer->width, buffer->height, buffer->format);
477 }
478
479 eglDisplay = mSlots[found].mEglDisplay;
480 eglFence = mSlots[found].mEglFence;
Pablo Ceballos28c65ad2016-06-01 15:03:21 -0700481 // Don't return a fence in shared buffer mode, except for the first
482 // frame.
483 *outFence = (mCore->mSharedBufferMode &&
484 mCore->mSharedBufferSlot == found) ?
485 Fence::NO_FENCE : mSlots[found].mFence;
Dan Stoza289ade12014-02-28 11:17:17 -0800486 mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
487 mSlots[found].mFence = Fence::NO_FENCE;
Pablo Ceballos28c65ad2016-06-01 15:03:21 -0700488
489 // If shared buffer mode has just been enabled, cache the slot of the
490 // first buffer that is dequeued and mark it as the shared buffer.
491 if (mCore->mSharedBufferMode && mCore->mSharedBufferSlot ==
492 BufferQueueCore::INVALID_BUFFER_SLOT) {
493 mCore->mSharedBufferSlot = found;
494 mSlots[found].mBufferState.mShared = true;
495 }
Dan Stoza289ade12014-02-28 11:17:17 -0800496 } // Autolock scope
497
498 if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
499 status_t error;
Dan Stoza29a3e902014-06-20 13:13:57 -0700500 BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
Dan Stoza289ade12014-02-28 11:17:17 -0800501 sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
Dan Stoza024e9312016-08-24 12:17:29 -0700502 width, height, format, usage,
503 {mConsumerName.string(), mConsumerName.size()}, &error));
Dan Stoza289ade12014-02-28 11:17:17 -0800504 { // Autolock scope
505 Mutex::Autolock lock(mCore->mMutex);
506
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700507 if (graphicBuffer != NULL && !mCore->mIsAbandoned) {
508 graphicBuffer->setGenerationNumber(mCore->mGenerationNumber);
509 mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
510 }
511
512 mCore->mIsAllocating = false;
513 mCore->mIsAllocatingCondition.broadcast();
514
515 if (graphicBuffer == NULL) {
Pablo Ceballos0a068092016-06-29 15:08:33 -0700516 mCore->mFreeSlots.insert(*outSlot);
517 mCore->clearBufferSlotLocked(*outSlot);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700518 BQ_LOGE("dequeueBuffer: createGraphicBuffer failed");
519 return error;
520 }
521
Dan Stoza289ade12014-02-28 11:17:17 -0800522 if (mCore->mIsAbandoned) {
Pablo Ceballos0a068092016-06-29 15:08:33 -0700523 mCore->mFreeSlots.insert(*outSlot);
524 mCore->clearBufferSlotLocked(*outSlot);
Dan Stoza289ade12014-02-28 11:17:17 -0800525 BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
526 return NO_INIT;
527 }
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800528
Pablo Ceballos9e314332016-01-12 13:49:19 -0800529 VALIDATE_CONSISTENCY();
Dan Stoza289ade12014-02-28 11:17:17 -0800530 } // Autolock scope
531 }
532
Dan Stoza9f3053d2014-03-06 15:14:33 -0800533 if (attachedByConsumer) {
534 returnFlags |= BUFFER_NEEDS_REALLOCATION;
535 }
536
Dan Stoza289ade12014-02-28 11:17:17 -0800537 if (eglFence != EGL_NO_SYNC_KHR) {
538 EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, 0,
539 1000000000);
540 // If something goes wrong, log the error, but return the buffer without
541 // synchronizing access to it. It's too late at this point to abort the
542 // dequeue operation.
543 if (result == EGL_FALSE) {
544 BQ_LOGE("dequeueBuffer: error %#x waiting for fence",
545 eglGetError());
546 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
547 BQ_LOGE("dequeueBuffer: timeout waiting for fence");
548 }
549 eglDestroySyncKHR(eglDisplay, eglFence);
550 }
551
Mark Salyzyn8f515ce2014-06-09 14:32:04 -0700552 BQ_LOGV("dequeueBuffer: returning slot=%d/%" PRIu64 " buf=%p flags=%#x",
553 *outSlot,
Dan Stoza289ade12014-02-28 11:17:17 -0800554 mSlots[*outSlot].mFrameNumber,
555 mSlots[*outSlot].mGraphicBuffer->handle, returnFlags);
556
557 return returnFlags;
558}
559
Dan Stoza9f3053d2014-03-06 15:14:33 -0800560status_t BufferQueueProducer::detachBuffer(int slot) {
561 ATRACE_CALL();
562 ATRACE_BUFFER_INDEX(slot);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700563 BQ_LOGV("detachBuffer: slot %d", slot);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800564
Eino-Ville Talvala93dd0512016-06-10 14:21:02 -0700565 sp<IConsumerListener> listener;
566 {
567 Mutex::Autolock lock(mCore->mMutex);
568
569 if (mCore->mIsAbandoned) {
570 BQ_LOGE("detachBuffer: BufferQueue has been abandoned");
571 return NO_INIT;
572 }
573
574 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
575 BQ_LOGE("detachBuffer: BufferQueue has no connected producer");
576 return NO_INIT;
577 }
578
579 if (mCore->mSharedBufferMode || mCore->mSharedBufferSlot == slot) {
580 BQ_LOGE("detachBuffer: cannot detach a buffer in shared buffer mode");
581 return BAD_VALUE;
582 }
583
584 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
585 BQ_LOGE("detachBuffer: slot index %d out of range [0, %d)",
586 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
587 return BAD_VALUE;
588 } else if (!mSlots[slot].mBufferState.isDequeued()) {
589 BQ_LOGE("detachBuffer: slot %d is not owned by the producer "
590 "(state = %s)", slot, mSlots[slot].mBufferState.string());
591 return BAD_VALUE;
592 } else if (!mSlots[slot].mRequestBufferCalled) {
593 BQ_LOGE("detachBuffer: buffer in slot %d has not been requested",
594 slot);
595 return BAD_VALUE;
596 }
597
598 mSlots[slot].mBufferState.detachProducer();
599 mCore->mActiveBuffers.erase(slot);
600 mCore->mFreeSlots.insert(slot);
601 mCore->clearBufferSlotLocked(slot);
602 mCore->mDequeueCondition.broadcast();
603 VALIDATE_CONSISTENCY();
604 listener = mCore->mConsumerListener;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800605 }
606
Eino-Ville Talvala93dd0512016-06-10 14:21:02 -0700607 if (listener != NULL) {
608 listener->onBuffersReleased();
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700609 }
Pablo Ceballos981066c2016-02-18 12:54:37 -0800610
Dan Stoza9f3053d2014-03-06 15:14:33 -0800611 return NO_ERROR;
612}
613
Dan Stozad9822a32014-03-28 15:25:31 -0700614status_t BufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
615 sp<Fence>* outFence) {
616 ATRACE_CALL();
617
618 if (outBuffer == NULL) {
619 BQ_LOGE("detachNextBuffer: outBuffer must not be NULL");
620 return BAD_VALUE;
621 } else if (outFence == NULL) {
622 BQ_LOGE("detachNextBuffer: outFence must not be NULL");
623 return BAD_VALUE;
624 }
625
Pablo Ceballos981066c2016-02-18 12:54:37 -0800626 Mutex::Autolock lock(mCore->mMutex);
Dan Stozad9822a32014-03-28 15:25:31 -0700627
Pablo Ceballos981066c2016-02-18 12:54:37 -0800628 if (mCore->mIsAbandoned) {
629 BQ_LOGE("detachNextBuffer: BufferQueue has been abandoned");
630 return NO_INIT;
Dan Stozad9822a32014-03-28 15:25:31 -0700631 }
632
Pablo Ceballos981066c2016-02-18 12:54:37 -0800633 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
634 BQ_LOGE("detachNextBuffer: BufferQueue has no connected producer");
635 return NO_INIT;
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700636 }
Pablo Ceballos981066c2016-02-18 12:54:37 -0800637
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700638 if (mCore->mSharedBufferMode) {
639 BQ_LOGE("detachNextBuffer: cannot detach a buffer in shared buffer "
640 "mode");
Pablo Ceballos981066c2016-02-18 12:54:37 -0800641 return BAD_VALUE;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700642 }
643
Pablo Ceballos981066c2016-02-18 12:54:37 -0800644 mCore->waitWhileAllocatingLocked();
645
646 if (mCore->mFreeBuffers.empty()) {
647 return NO_MEMORY;
648 }
649
650 int found = mCore->mFreeBuffers.front();
651 mCore->mFreeBuffers.remove(found);
652 mCore->mFreeSlots.insert(found);
653
654 BQ_LOGV("detachNextBuffer detached slot %d", found);
655
656 *outBuffer = mSlots[found].mGraphicBuffer;
657 *outFence = mSlots[found].mFence;
658 mCore->clearBufferSlotLocked(found);
659 VALIDATE_CONSISTENCY();
660
Dan Stozad9822a32014-03-28 15:25:31 -0700661 return NO_ERROR;
662}
663
Dan Stoza9f3053d2014-03-06 15:14:33 -0800664status_t BufferQueueProducer::attachBuffer(int* outSlot,
665 const sp<android::GraphicBuffer>& buffer) {
666 ATRACE_CALL();
667
668 if (outSlot == NULL) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700669 BQ_LOGE("attachBuffer: outSlot must not be NULL");
Dan Stoza9f3053d2014-03-06 15:14:33 -0800670 return BAD_VALUE;
671 } else if (buffer == NULL) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700672 BQ_LOGE("attachBuffer: cannot attach NULL buffer");
Dan Stoza9f3053d2014-03-06 15:14:33 -0800673 return BAD_VALUE;
674 }
675
676 Mutex::Autolock lock(mCore->mMutex);
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700677
678 if (mCore->mIsAbandoned) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700679 BQ_LOGE("attachBuffer: BufferQueue has been abandoned");
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700680 return NO_INIT;
681 }
682
683 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700684 BQ_LOGE("attachBuffer: BufferQueue has no connected producer");
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700685 return NO_INIT;
686 }
Dan Stoza9f3053d2014-03-06 15:14:33 -0800687
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700688 if (mCore->mSharedBufferMode) {
689 BQ_LOGE("attachBuffer: cannot attach a buffer in shared buffer mode");
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700690 return BAD_VALUE;
691 }
692
Dan Stoza812ed062015-06-02 15:45:22 -0700693 if (buffer->getGenerationNumber() != mCore->mGenerationNumber) {
694 BQ_LOGE("attachBuffer: generation number mismatch [buffer %u] "
695 "[queue %u]", buffer->getGenerationNumber(),
696 mCore->mGenerationNumber);
697 return BAD_VALUE;
698 }
699
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700700 mCore->waitWhileAllocatingLocked();
701
Dan Stoza9f3053d2014-03-06 15:14:33 -0800702 status_t returnFlags = NO_ERROR;
703 int found;
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800704 status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Attach, &found);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800705 if (status != NO_ERROR) {
706 return status;
707 }
708
709 // This should not happen
710 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700711 BQ_LOGE("attachBuffer: no available buffer slots");
Dan Stoza9f3053d2014-03-06 15:14:33 -0800712 return -EBUSY;
713 }
714
715 *outSlot = found;
716 ATRACE_BUFFER_INDEX(*outSlot);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700717 BQ_LOGV("attachBuffer: returning slot %d flags=%#x",
Dan Stoza9f3053d2014-03-06 15:14:33 -0800718 *outSlot, returnFlags);
719
720 mSlots[*outSlot].mGraphicBuffer = buffer;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700721 mSlots[*outSlot].mBufferState.attachProducer();
Dan Stoza9f3053d2014-03-06 15:14:33 -0800722 mSlots[*outSlot].mEglFence = EGL_NO_SYNC_KHR;
723 mSlots[*outSlot].mFence = Fence::NO_FENCE;
Dan Stoza2443c792014-03-24 15:03:46 -0700724 mSlots[*outSlot].mRequestBufferCalled = true;
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800725 mSlots[*outSlot].mAcquireCalled = false;
726 mCore->mActiveBuffers.insert(found);
Pablo Ceballos9e314332016-01-12 13:49:19 -0800727 VALIDATE_CONSISTENCY();
Dan Stoza0de7ea72015-04-23 13:20:51 -0700728
Dan Stoza9f3053d2014-03-06 15:14:33 -0800729 return returnFlags;
730}
731
Dan Stoza289ade12014-02-28 11:17:17 -0800732status_t BufferQueueProducer::queueBuffer(int slot,
733 const QueueBufferInput &input, QueueBufferOutput *output) {
734 ATRACE_CALL();
735 ATRACE_BUFFER_INDEX(slot);
736
737 int64_t timestamp;
738 bool isAutoTimestamp;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800739 android_dataspace dataSpace;
Pablo Ceballos60d69222015-08-07 14:47:20 -0700740 Rect crop(Rect::EMPTY_RECT);
Dan Stoza289ade12014-02-28 11:17:17 -0800741 int scalingMode;
742 uint32_t transform;
Ruben Brunk1681d952014-06-27 15:51:55 -0700743 uint32_t stickyTransform;
Dan Stoza289ade12014-02-28 11:17:17 -0800744 sp<Fence> fence;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800745 input.deflate(&timestamp, &isAutoTimestamp, &dataSpace, &crop, &scalingMode,
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700746 &transform, &fence, &stickyTransform);
Dan Stoza5065a552015-03-17 16:23:42 -0700747 Region surfaceDamage = input.getSurfaceDamage();
Dan Stoza289ade12014-02-28 11:17:17 -0800748
749 if (fence == NULL) {
750 BQ_LOGE("queueBuffer: fence is NULL");
Jesse Hallde288fe2014-11-04 08:30:48 -0800751 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800752 }
753
754 switch (scalingMode) {
755 case NATIVE_WINDOW_SCALING_MODE_FREEZE:
756 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
757 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
758 case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
759 break;
760 default:
761 BQ_LOGE("queueBuffer: unknown scaling mode %d", scalingMode);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800762 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800763 }
764
Dan Stoza8dc55392014-11-04 11:37:46 -0800765 sp<IConsumerListener> frameAvailableListener;
766 sp<IConsumerListener> frameReplacedListener;
767 int callbackTicket = 0;
768 BufferItem item;
Dan Stoza289ade12014-02-28 11:17:17 -0800769 { // Autolock scope
770 Mutex::Autolock lock(mCore->mMutex);
771
772 if (mCore->mIsAbandoned) {
773 BQ_LOGE("queueBuffer: BufferQueue has been abandoned");
774 return NO_INIT;
775 }
776
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700777 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
778 BQ_LOGE("queueBuffer: BufferQueue has no connected producer");
779 return NO_INIT;
780 }
781
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800782 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
Dan Stoza289ade12014-02-28 11:17:17 -0800783 BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)",
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800784 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800785 return BAD_VALUE;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700786 } else if (!mSlots[slot].mBufferState.isDequeued()) {
Dan Stoza289ade12014-02-28 11:17:17 -0800787 BQ_LOGE("queueBuffer: slot %d is not owned by the producer "
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700788 "(state = %s)", slot, mSlots[slot].mBufferState.string());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800789 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800790 } else if (!mSlots[slot].mRequestBufferCalled) {
791 BQ_LOGE("queueBuffer: slot %d was queued without requesting "
792 "a buffer", slot);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800793 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800794 }
795
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700796 // If shared buffer mode has just been enabled, cache the slot of the
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700797 // first buffer that is queued and mark it as the shared buffer.
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700798 if (mCore->mSharedBufferMode && mCore->mSharedBufferSlot ==
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700799 BufferQueueCore::INVALID_BUFFER_SLOT) {
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700800 mCore->mSharedBufferSlot = slot;
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700801 mSlots[slot].mBufferState.mShared = true;
802 }
803
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800804 BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64 " dataSpace=%d"
Mark Salyzyn8f515ce2014-06-09 14:32:04 -0700805 " crop=[%d,%d,%d,%d] transform=%#x scale=%s",
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800806 slot, mCore->mFrameCounter + 1, timestamp, dataSpace,
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800807 crop.left, crop.top, crop.right, crop.bottom, transform,
808 BufferItem::scalingModeName(static_cast<uint32_t>(scalingMode)));
Dan Stoza289ade12014-02-28 11:17:17 -0800809
810 const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
811 Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
Pablo Ceballos60d69222015-08-07 14:47:20 -0700812 Rect croppedRect(Rect::EMPTY_RECT);
Dan Stoza289ade12014-02-28 11:17:17 -0800813 crop.intersect(bufferRect, &croppedRect);
814 if (croppedRect != crop) {
815 BQ_LOGE("queueBuffer: crop rect is not contained within the "
816 "buffer in slot %d", slot);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800817 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800818 }
819
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800820 // Override UNKNOWN dataspace with consumer default
821 if (dataSpace == HAL_DATASPACE_UNKNOWN) {
822 dataSpace = mCore->mDefaultBufferDataSpace;
823 }
824
Dan Stoza289ade12014-02-28 11:17:17 -0800825 mSlots[slot].mFence = fence;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700826 mSlots[slot].mBufferState.queue();
827
Dan Stoza289ade12014-02-28 11:17:17 -0800828 ++mCore->mFrameCounter;
829 mSlots[slot].mFrameNumber = mCore->mFrameCounter;
830
Dan Stoza289ade12014-02-28 11:17:17 -0800831 item.mAcquireCalled = mSlots[slot].mAcquireCalled;
832 item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
833 item.mCrop = crop;
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800834 item.mTransform = transform &
835 ~static_cast<uint32_t>(NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
Dan Stoza289ade12014-02-28 11:17:17 -0800836 item.mTransformToDisplayInverse =
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800837 (transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) != 0;
838 item.mScalingMode = static_cast<uint32_t>(scalingMode);
Dan Stoza289ade12014-02-28 11:17:17 -0800839 item.mTimestamp = timestamp;
840 item.mIsAutoTimestamp = isAutoTimestamp;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800841 item.mDataSpace = dataSpace;
Dan Stoza289ade12014-02-28 11:17:17 -0800842 item.mFrameNumber = mCore->mFrameCounter;
843 item.mSlot = slot;
844 item.mFence = fence;
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700845 item.mIsDroppable = mCore->mAsyncMode ||
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700846 mCore->mDequeueBufferCannotBlock ||
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700847 (mCore->mSharedBufferMode && mCore->mSharedBufferSlot == slot);
Dan Stoza5065a552015-03-17 16:23:42 -0700848 item.mSurfaceDamage = surfaceDamage;
Pablo Ceballos06312182015-10-07 16:32:12 -0700849 item.mQueuedBuffer = true;
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700850 item.mAutoRefresh = mCore->mSharedBufferMode && mCore->mAutoRefresh;
Dan Stoza289ade12014-02-28 11:17:17 -0800851
Ruben Brunk1681d952014-06-27 15:51:55 -0700852 mStickyTransform = stickyTransform;
853
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700854 // Cache the shared buffer data so that the BufferItem can be recreated.
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700855 if (mCore->mSharedBufferMode) {
856 mCore->mSharedBufferCache.crop = crop;
857 mCore->mSharedBufferCache.transform = transform;
858 mCore->mSharedBufferCache.scalingMode = static_cast<uint32_t>(
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700859 scalingMode);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700860 mCore->mSharedBufferCache.dataspace = dataSpace;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700861 }
862
Dan Stoza289ade12014-02-28 11:17:17 -0800863 if (mCore->mQueue.empty()) {
864 // When the queue is empty, we can ignore mDequeueBufferCannotBlock
865 // and simply queue this buffer
866 mCore->mQueue.push_back(item);
Dan Stoza8dc55392014-11-04 11:37:46 -0800867 frameAvailableListener = mCore->mConsumerListener;
Dan Stoza289ade12014-02-28 11:17:17 -0800868 } else {
Pablo Ceballos4d85da42016-04-19 20:11:56 -0700869 // When the queue is not empty, we need to look at the last buffer
870 // in the queue to see if we need to replace it
871 const BufferItem& last = mCore->mQueue.itemAt(
872 mCore->mQueue.size() - 1);
873 if (last.mIsDroppable) {
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800874
Pablo Ceballos4d85da42016-04-19 20:11:56 -0700875 if (!last.mIsStale) {
876 mSlots[last.mSlot].mBufferState.freeQueued();
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700877
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700878 // After leaving shared buffer mode, the shared buffer will
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700879 // still be around. Mark it as no longer shared if this
880 // operation causes it to be free.
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700881 if (!mCore->mSharedBufferMode &&
Pablo Ceballos4d85da42016-04-19 20:11:56 -0700882 mSlots[last.mSlot].mBufferState.isFree()) {
883 mSlots[last.mSlot].mBufferState.mShared = false;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700884 }
885 // Don't put the shared buffer on the free list.
Pablo Ceballos4d85da42016-04-19 20:11:56 -0700886 if (!mSlots[last.mSlot].mBufferState.isShared()) {
887 mCore->mActiveBuffers.erase(last.mSlot);
888 mCore->mFreeBuffers.push_back(last.mSlot);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700889 }
Dan Stoza289ade12014-02-28 11:17:17 -0800890 }
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800891
Dan Stoza289ade12014-02-28 11:17:17 -0800892 // Overwrite the droppable buffer with the incoming one
Pablo Ceballos4d85da42016-04-19 20:11:56 -0700893 mCore->mQueue.editItemAt(mCore->mQueue.size() - 1) = item;
Dan Stoza8dc55392014-11-04 11:37:46 -0800894 frameReplacedListener = mCore->mConsumerListener;
Dan Stoza289ade12014-02-28 11:17:17 -0800895 } else {
896 mCore->mQueue.push_back(item);
Dan Stoza8dc55392014-11-04 11:37:46 -0800897 frameAvailableListener = mCore->mConsumerListener;
Dan Stoza289ade12014-02-28 11:17:17 -0800898 }
899 }
900
901 mCore->mBufferHasBeenQueued = true;
902 mCore->mDequeueCondition.broadcast();
Dan Stoza50101d02016-04-07 16:53:23 -0700903 mCore->mLastQueuedSlot = slot;
Dan Stoza289ade12014-02-28 11:17:17 -0800904
905 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
Dan Stoza3be1c6b2014-11-18 10:24:03 -0800906 mCore->mTransformHint,
Pablo Ceballosbc8c1922016-07-01 14:15:41 -0700907 static_cast<uint32_t>(mCore->mQueue.size()),
908 mCore->mFrameCounter + 1);
Dan Stoza289ade12014-02-28 11:17:17 -0800909
910 ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
Dan Stozae77c7662016-05-13 11:37:28 -0700911 mCore->mOccupancyTracker.registerOccupancyChange(mCore->mQueue.size());
Dan Stoza8dc55392014-11-04 11:37:46 -0800912
913 // Take a ticket for the callback functions
914 callbackTicket = mNextCallbackTicket++;
Dan Stoza0de7ea72015-04-23 13:20:51 -0700915
Pablo Ceballos9e314332016-01-12 13:49:19 -0800916 VALIDATE_CONSISTENCY();
Dan Stoza289ade12014-02-28 11:17:17 -0800917 } // Autolock scope
918
Irvel468051e2016-06-13 16:44:44 -0700919 // It is okay not to clear the GraphicBuffer when the consumer is SurfaceFlinger because
920 // it is guaranteed that the BufferQueue is inside SurfaceFlinger's process and
921 // there will be no Binder call
922 if (!mConsumerIsSurfaceFlinger) {
923 item.mGraphicBuffer.clear();
924 }
925
926 // Don't send the slot number through the callback since the consumer shouldn't need it
Dan Stoza8dc55392014-11-04 11:37:46 -0800927 item.mSlot = BufferItem::INVALID_BUFFER_SLOT;
928
929 // Call back without the main BufferQueue lock held, but with the callback
930 // lock held so we can ensure that callbacks occur in order
931 {
932 Mutex::Autolock lock(mCallbackMutex);
933 while (callbackTicket != mCurrentCallbackTicket) {
934 mCallbackCondition.wait(mCallbackMutex);
935 }
936
937 if (frameAvailableListener != NULL) {
938 frameAvailableListener->onFrameAvailable(item);
939 } else if (frameReplacedListener != NULL) {
940 frameReplacedListener->onFrameReplaced(item);
941 }
942
943 ++mCurrentCallbackTicket;
944 mCallbackCondition.broadcast();
Dan Stoza289ade12014-02-28 11:17:17 -0800945 }
946
Christian Poetzsch82fbb122015-12-07 13:36:22 +0000947 // Wait without lock held
948 if (mCore->mConnectedApi == NATIVE_WINDOW_API_EGL) {
949 // Waiting here allows for two full buffers to be queued but not a
950 // third. In the event that frames take varying time, this makes a
951 // small trade-off in favor of latency rather than throughput.
952 mLastQueueBufferFence->waitForever("Throttling EGL Production");
Christian Poetzsch82fbb122015-12-07 13:36:22 +0000953 }
Dan Stoza50101d02016-04-07 16:53:23 -0700954 mLastQueueBufferFence = fence;
John Reck1a61da52016-04-28 13:18:15 -0700955 mLastQueuedCrop = item.mCrop;
956 mLastQueuedTransform = item.mTransform;
Christian Poetzsch82fbb122015-12-07 13:36:22 +0000957
Dan Stoza289ade12014-02-28 11:17:17 -0800958 return NO_ERROR;
959}
960
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700961status_t BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
Dan Stoza289ade12014-02-28 11:17:17 -0800962 ATRACE_CALL();
963 BQ_LOGV("cancelBuffer: slot %d", slot);
964 Mutex::Autolock lock(mCore->mMutex);
965
966 if (mCore->mIsAbandoned) {
967 BQ_LOGE("cancelBuffer: BufferQueue has been abandoned");
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700968 return NO_INIT;
969 }
970
971 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
972 BQ_LOGE("cancelBuffer: BufferQueue has no connected producer");
973 return NO_INIT;
Dan Stoza289ade12014-02-28 11:17:17 -0800974 }
975
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700976 if (mCore->mSharedBufferMode) {
977 BQ_LOGE("cancelBuffer: cannot cancel a buffer in shared buffer mode");
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700978 return BAD_VALUE;
979 }
980
Dan Stoza3e96f192014-03-03 10:16:19 -0800981 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
Dan Stoza289ade12014-02-28 11:17:17 -0800982 BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)",
Dan Stoza3e96f192014-03-03 10:16:19 -0800983 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700984 return BAD_VALUE;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700985 } else if (!mSlots[slot].mBufferState.isDequeued()) {
Dan Stoza289ade12014-02-28 11:17:17 -0800986 BQ_LOGE("cancelBuffer: slot %d is not owned by the producer "
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700987 "(state = %s)", slot, mSlots[slot].mBufferState.string());
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700988 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800989 } else if (fence == NULL) {
990 BQ_LOGE("cancelBuffer: fence is NULL");
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700991 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800992 }
993
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700994 mSlots[slot].mBufferState.cancel();
995
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700996 // After leaving shared buffer mode, the shared buffer will still be around.
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700997 // Mark it as no longer shared if this operation causes it to be free.
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700998 if (!mCore->mSharedBufferMode && mSlots[slot].mBufferState.isFree()) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700999 mSlots[slot].mBufferState.mShared = false;
1000 }
1001
1002 // Don't put the shared buffer on the free list.
1003 if (!mSlots[slot].mBufferState.isShared()) {
Pablo Ceballos23b4abe2016-01-08 12:15:22 -08001004 mCore->mActiveBuffers.erase(slot);
1005 mCore->mFreeBuffers.push_back(slot);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001006 }
Pablo Ceballos23b4abe2016-01-08 12:15:22 -08001007
Dan Stoza289ade12014-02-28 11:17:17 -08001008 mSlots[slot].mFence = fence;
1009 mCore->mDequeueCondition.broadcast();
Pablo Ceballos9e314332016-01-12 13:49:19 -08001010 VALIDATE_CONSISTENCY();
Pablo Ceballos583b1b32015-09-03 18:23:52 -07001011
1012 return NO_ERROR;
Dan Stoza289ade12014-02-28 11:17:17 -08001013}
1014
1015int BufferQueueProducer::query(int what, int *outValue) {
1016 ATRACE_CALL();
1017 Mutex::Autolock lock(mCore->mMutex);
1018
1019 if (outValue == NULL) {
1020 BQ_LOGE("query: outValue was NULL");
1021 return BAD_VALUE;
1022 }
1023
1024 if (mCore->mIsAbandoned) {
1025 BQ_LOGE("query: BufferQueue has been abandoned");
1026 return NO_INIT;
1027 }
1028
1029 int value;
1030 switch (what) {
1031 case NATIVE_WINDOW_WIDTH:
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001032 value = static_cast<int32_t>(mCore->mDefaultWidth);
Dan Stoza289ade12014-02-28 11:17:17 -08001033 break;
1034 case NATIVE_WINDOW_HEIGHT:
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001035 value = static_cast<int32_t>(mCore->mDefaultHeight);
Dan Stoza289ade12014-02-28 11:17:17 -08001036 break;
1037 case NATIVE_WINDOW_FORMAT:
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001038 value = static_cast<int32_t>(mCore->mDefaultBufferFormat);
Dan Stoza289ade12014-02-28 11:17:17 -08001039 break;
1040 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
Pablo Ceballos567dbbb2015-08-26 18:59:08 -07001041 value = mCore->getMinUndequeuedBufferCountLocked();
Dan Stoza289ade12014-02-28 11:17:17 -08001042 break;
Ruben Brunk1681d952014-06-27 15:51:55 -07001043 case NATIVE_WINDOW_STICKY_TRANSFORM:
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001044 value = static_cast<int32_t>(mStickyTransform);
Ruben Brunk1681d952014-06-27 15:51:55 -07001045 break;
Dan Stoza289ade12014-02-28 11:17:17 -08001046 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
1047 value = (mCore->mQueue.size() > 1);
1048 break;
1049 case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001050 value = static_cast<int32_t>(mCore->mConsumerUsageBits);
Dan Stoza289ade12014-02-28 11:17:17 -08001051 break;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -08001052 case NATIVE_WINDOW_DEFAULT_DATASPACE:
1053 value = static_cast<int32_t>(mCore->mDefaultBufferDataSpace);
1054 break;
Dan Stoza4afd8b62015-02-25 16:49:08 -08001055 case NATIVE_WINDOW_BUFFER_AGE:
1056 if (mCore->mBufferAge > INT32_MAX) {
1057 value = 0;
1058 } else {
1059 value = static_cast<int32_t>(mCore->mBufferAge);
1060 }
1061 break;
Dan Stoza289ade12014-02-28 11:17:17 -08001062 default:
1063 return BAD_VALUE;
1064 }
1065
1066 BQ_LOGV("query: %d? %d", what, value);
1067 *outValue = value;
1068 return NO_ERROR;
1069}
1070
Dan Stozaf0eaf252014-03-21 13:05:51 -07001071status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
Dan Stoza289ade12014-02-28 11:17:17 -08001072 int api, bool producerControlledByApp, QueueBufferOutput *output) {
1073 ATRACE_CALL();
Pablo Ceballos981066c2016-02-18 12:54:37 -08001074 Mutex::Autolock lock(mCore->mMutex);
1075 mConsumerName = mCore->mConsumerName;
1076 BQ_LOGV("connect: api=%d producerControlledByApp=%s", api,
1077 producerControlledByApp ? "true" : "false");
1078
1079 if (mCore->mIsAbandoned) {
1080 BQ_LOGE("connect: BufferQueue has been abandoned");
1081 return NO_INIT;
1082 }
1083
1084 if (mCore->mConsumerListener == NULL) {
1085 BQ_LOGE("connect: BufferQueue has no consumer");
1086 return NO_INIT;
1087 }
1088
1089 if (output == NULL) {
1090 BQ_LOGE("connect: output was NULL");
1091 return BAD_VALUE;
1092 }
1093
1094 if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
1095 BQ_LOGE("connect: already connected (cur=%d req=%d)",
1096 mCore->mConnectedApi, api);
1097 return BAD_VALUE;
1098 }
1099
1100 int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode,
1101 mDequeueTimeout < 0 ?
1102 mCore->mConsumerControlledByApp && producerControlledByApp : false,
1103 mCore->mMaxBufferCount) -
1104 mCore->getMaxBufferCountLocked();
1105 if (!mCore->adjustAvailableSlotsLocked(delta)) {
1106 BQ_LOGE("connect: BufferQueue failed to adjust the number of available "
1107 "slots. Delta = %d", delta);
1108 return BAD_VALUE;
1109 }
1110
Dan Stoza289ade12014-02-28 11:17:17 -08001111 int status = NO_ERROR;
Pablo Ceballos981066c2016-02-18 12:54:37 -08001112 switch (api) {
1113 case NATIVE_WINDOW_API_EGL:
1114 case NATIVE_WINDOW_API_CPU:
1115 case NATIVE_WINDOW_API_MEDIA:
1116 case NATIVE_WINDOW_API_CAMERA:
1117 mCore->mConnectedApi = api;
1118 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
1119 mCore->mTransformHint,
Pablo Ceballosbc8c1922016-07-01 14:15:41 -07001120 static_cast<uint32_t>(mCore->mQueue.size()),
1121 mCore->mFrameCounter + 1);
Dan Stoza289ade12014-02-28 11:17:17 -08001122
Pablo Ceballos981066c2016-02-18 12:54:37 -08001123 // Set up a death notification so that we can disconnect
1124 // automatically if the remote producer dies
1125 if (listener != NULL &&
1126 IInterface::asBinder(listener)->remoteBinder() != NULL) {
1127 status = IInterface::asBinder(listener)->linkToDeath(
1128 static_cast<IBinder::DeathRecipient*>(this));
1129 if (status != NO_ERROR) {
1130 BQ_LOGE("connect: linkToDeath failed: %s (%d)",
1131 strerror(-status), status);
Dan Stoza289ade12014-02-28 11:17:17 -08001132 }
Pablo Ceballos981066c2016-02-18 12:54:37 -08001133 }
1134 mCore->mConnectedProducerListener = listener;
1135 break;
1136 default:
1137 BQ_LOGE("connect: unknown API %d", api);
1138 status = BAD_VALUE;
1139 break;
Dan Stoza289ade12014-02-28 11:17:17 -08001140 }
1141
Pablo Ceballos981066c2016-02-18 12:54:37 -08001142 mCore->mBufferHasBeenQueued = false;
1143 mCore->mDequeueBufferCannotBlock = false;
1144 if (mDequeueTimeout < 0) {
1145 mCore->mDequeueBufferCannotBlock =
1146 mCore->mConsumerControlledByApp && producerControlledByApp;
Dan Stoza127fc632015-06-30 13:43:32 -07001147 }
Dan Stoza289ade12014-02-28 11:17:17 -08001148
Pablo Ceballos981066c2016-02-18 12:54:37 -08001149 mCore->mAllowAllocation = true;
1150 VALIDATE_CONSISTENCY();
Dan Stoza289ade12014-02-28 11:17:17 -08001151 return status;
1152}
1153
1154status_t BufferQueueProducer::disconnect(int api) {
1155 ATRACE_CALL();
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001156 BQ_LOGV("disconnect: api %d", api);
Dan Stoza289ade12014-02-28 11:17:17 -08001157
1158 int status = NO_ERROR;
1159 sp<IConsumerListener> listener;
1160 { // Autolock scope
1161 Mutex::Autolock lock(mCore->mMutex);
Antoine Labour78014f32014-07-15 21:17:03 -07001162 mCore->waitWhileAllocatingLocked();
Dan Stoza289ade12014-02-28 11:17:17 -08001163
1164 if (mCore->mIsAbandoned) {
1165 // It's not really an error to disconnect after the surface has
1166 // been abandoned; it should just be a no-op.
1167 return NO_ERROR;
1168 }
1169
Chong Zhang1b3a9ac2016-02-29 16:47:47 -08001170 if (api == BufferQueueCore::CURRENTLY_CONNECTED_API) {
1171 api = mCore->mConnectedApi;
Chong Zhang26bb2b12016-03-08 12:08:33 -08001172 // If we're asked to disconnect the currently connected api but
1173 // nobody is connected, it's not really an error.
1174 if (api == BufferQueueCore::NO_CONNECTED_API) {
1175 return NO_ERROR;
1176 }
Chong Zhang1b3a9ac2016-02-29 16:47:47 -08001177 }
1178
Dan Stoza289ade12014-02-28 11:17:17 -08001179 switch (api) {
1180 case NATIVE_WINDOW_API_EGL:
1181 case NATIVE_WINDOW_API_CPU:
1182 case NATIVE_WINDOW_API_MEDIA:
1183 case NATIVE_WINDOW_API_CAMERA:
1184 if (mCore->mConnectedApi == api) {
1185 mCore->freeAllBuffersLocked();
1186
1187 // Remove our death notification callback if we have one
Dan Stozaf0eaf252014-03-21 13:05:51 -07001188 if (mCore->mConnectedProducerListener != NULL) {
1189 sp<IBinder> token =
Marco Nelissen097ca272014-11-14 08:01:01 -08001190 IInterface::asBinder(mCore->mConnectedProducerListener);
Dan Stoza289ade12014-02-28 11:17:17 -08001191 // This can fail if we're here because of the death
1192 // notification, but we just ignore it
1193 token->unlinkToDeath(
1194 static_cast<IBinder::DeathRecipient*>(this));
1195 }
Pablo Ceballos3559fbf2016-03-17 15:50:23 -07001196 mCore->mSharedBufferSlot =
Pablo Ceballos23b4abe2016-01-08 12:15:22 -08001197 BufferQueueCore::INVALID_BUFFER_SLOT;
Dan Stozaf0eaf252014-03-21 13:05:51 -07001198 mCore->mConnectedProducerListener = NULL;
Dan Stoza289ade12014-02-28 11:17:17 -08001199 mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
Jesse Hall399184a2014-03-03 15:42:54 -08001200 mCore->mSidebandStream.clear();
Dan Stoza289ade12014-02-28 11:17:17 -08001201 mCore->mDequeueCondition.broadcast();
1202 listener = mCore->mConsumerListener;
Amith Dsouza4f21a4c2015-06-30 22:54:16 -07001203 } else if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001204 BQ_LOGE("disconnect: still connected to another API "
Dan Stoza289ade12014-02-28 11:17:17 -08001205 "(cur=%d req=%d)", mCore->mConnectedApi, api);
Dan Stoza9f3053d2014-03-06 15:14:33 -08001206 status = BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -08001207 }
1208 break;
1209 default:
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001210 BQ_LOGE("disconnect: unknown API %d", api);
Dan Stoza9f3053d2014-03-06 15:14:33 -08001211 status = BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -08001212 break;
1213 }
1214 } // Autolock scope
1215
1216 // Call back without lock held
1217 if (listener != NULL) {
1218 listener->onBuffersReleased();
1219 }
1220
1221 return status;
1222}
1223
Jesse Hall399184a2014-03-03 15:42:54 -08001224status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) {
Wonsik Kimafe30812014-03-31 23:16:08 +09001225 sp<IConsumerListener> listener;
1226 { // Autolock scope
1227 Mutex::Autolock _l(mCore->mMutex);
1228 mCore->mSidebandStream = stream;
1229 listener = mCore->mConsumerListener;
1230 } // Autolock scope
1231
1232 if (listener != NULL) {
1233 listener->onSidebandStreamChanged();
1234 }
Jesse Hall399184a2014-03-03 15:42:54 -08001235 return NO_ERROR;
1236}
1237
Pablo Ceballos567dbbb2015-08-26 18:59:08 -07001238void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height,
1239 PixelFormat format, uint32_t usage) {
Antoine Labour78014f32014-07-15 21:17:03 -07001240 ATRACE_CALL();
1241 while (true) {
Antoine Labour78014f32014-07-15 21:17:03 -07001242 size_t newBufferCount = 0;
1243 uint32_t allocWidth = 0;
1244 uint32_t allocHeight = 0;
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001245 PixelFormat allocFormat = PIXEL_FORMAT_UNKNOWN;
Antoine Labour78014f32014-07-15 21:17:03 -07001246 uint32_t allocUsage = 0;
1247 { // Autolock scope
1248 Mutex::Autolock lock(mCore->mMutex);
1249 mCore->waitWhileAllocatingLocked();
Dan Stoza29a3e902014-06-20 13:13:57 -07001250
Dan Stoza9de72932015-04-16 17:28:43 -07001251 if (!mCore->mAllowAllocation) {
1252 BQ_LOGE("allocateBuffers: allocation is not allowed for this "
1253 "BufferQueue");
1254 return;
1255 }
1256
Pablo Ceballos23b4abe2016-01-08 12:15:22 -08001257 newBufferCount = mCore->mFreeSlots.size();
1258 if (newBufferCount == 0) {
Antoine Labour78014f32014-07-15 21:17:03 -07001259 return;
1260 }
Pablo Ceballos23b4abe2016-01-08 12:15:22 -08001261
Antoine Labour78014f32014-07-15 21:17:03 -07001262 allocWidth = width > 0 ? width : mCore->mDefaultWidth;
1263 allocHeight = height > 0 ? height : mCore->mDefaultHeight;
1264 allocFormat = format != 0 ? format : mCore->mDefaultBufferFormat;
1265 allocUsage = usage | mCore->mConsumerUsageBits;
1266
1267 mCore->mIsAllocating = true;
1268 } // Autolock scope
1269
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001270 Vector<sp<GraphicBuffer>> buffers;
Antoine Labour78014f32014-07-15 21:17:03 -07001271 for (size_t i = 0; i < newBufferCount; ++i) {
1272 status_t result = NO_ERROR;
1273 sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
Dan Stoza024e9312016-08-24 12:17:29 -07001274 allocWidth, allocHeight, allocFormat, allocUsage,
1275 {mConsumerName.string(), mConsumerName.size()}, &result));
Antoine Labour78014f32014-07-15 21:17:03 -07001276 if (result != NO_ERROR) {
1277 BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format"
1278 " %u, usage %u)", width, height, format, usage);
1279 Mutex::Autolock lock(mCore->mMutex);
1280 mCore->mIsAllocating = false;
1281 mCore->mIsAllocatingCondition.broadcast();
1282 return;
1283 }
1284 buffers.push_back(graphicBuffer);
1285 }
1286
1287 { // Autolock scope
1288 Mutex::Autolock lock(mCore->mMutex);
1289 uint32_t checkWidth = width > 0 ? width : mCore->mDefaultWidth;
1290 uint32_t checkHeight = height > 0 ? height : mCore->mDefaultHeight;
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001291 PixelFormat checkFormat = format != 0 ?
1292 format : mCore->mDefaultBufferFormat;
Antoine Labour78014f32014-07-15 21:17:03 -07001293 uint32_t checkUsage = usage | mCore->mConsumerUsageBits;
1294 if (checkWidth != allocWidth || checkHeight != allocHeight ||
1295 checkFormat != allocFormat || checkUsage != allocUsage) {
1296 // Something changed while we released the lock. Retry.
1297 BQ_LOGV("allocateBuffers: size/format/usage changed while allocating. Retrying.");
1298 mCore->mIsAllocating = false;
1299 mCore->mIsAllocatingCondition.broadcast();
Dan Stoza29a3e902014-06-20 13:13:57 -07001300 continue;
1301 }
1302
Antoine Labour78014f32014-07-15 21:17:03 -07001303 for (size_t i = 0; i < newBufferCount; ++i) {
Pablo Ceballos23b4abe2016-01-08 12:15:22 -08001304 if (mCore->mFreeSlots.empty()) {
1305 BQ_LOGV("allocateBuffers: a slot was occupied while "
1306 "allocating. Dropping allocated buffer.");
Antoine Labour78014f32014-07-15 21:17:03 -07001307 continue;
1308 }
Pablo Ceballos23b4abe2016-01-08 12:15:22 -08001309 auto slot = mCore->mFreeSlots.begin();
1310 mCore->clearBufferSlotLocked(*slot); // Clean up the slot first
1311 mSlots[*slot].mGraphicBuffer = buffers[i];
1312 mSlots[*slot].mFence = Fence::NO_FENCE;
Dan Stoza0de7ea72015-04-23 13:20:51 -07001313
1314 // freeBufferLocked puts this slot on the free slots list. Since
1315 // we then attached a buffer, move the slot to free buffer list.
Pablo Ceballos23b4abe2016-01-08 12:15:22 -08001316 mCore->mFreeBuffers.push_front(*slot);
Dan Stoza0de7ea72015-04-23 13:20:51 -07001317
Pablo Ceballos23b4abe2016-01-08 12:15:22 -08001318 BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d",
1319 *slot);
Christopher Ferris87e94cd2016-04-26 11:29:08 -07001320
1321 // Make sure the erase is done after all uses of the slot
1322 // iterator since it will be invalid after this point.
1323 mCore->mFreeSlots.erase(slot);
Antoine Labour78014f32014-07-15 21:17:03 -07001324 }
Dan Stoza29a3e902014-06-20 13:13:57 -07001325
Antoine Labour78014f32014-07-15 21:17:03 -07001326 mCore->mIsAllocating = false;
1327 mCore->mIsAllocatingCondition.broadcast();
Pablo Ceballos9e314332016-01-12 13:49:19 -08001328 VALIDATE_CONSISTENCY();
Antoine Labour78014f32014-07-15 21:17:03 -07001329 } // Autolock scope
Dan Stoza29a3e902014-06-20 13:13:57 -07001330 }
1331}
1332
Dan Stoza9de72932015-04-16 17:28:43 -07001333status_t BufferQueueProducer::allowAllocation(bool allow) {
1334 ATRACE_CALL();
1335 BQ_LOGV("allowAllocation: %s", allow ? "true" : "false");
1336
1337 Mutex::Autolock lock(mCore->mMutex);
1338 mCore->mAllowAllocation = allow;
1339 return NO_ERROR;
1340}
1341
Dan Stoza812ed062015-06-02 15:45:22 -07001342status_t BufferQueueProducer::setGenerationNumber(uint32_t generationNumber) {
1343 ATRACE_CALL();
1344 BQ_LOGV("setGenerationNumber: %u", generationNumber);
1345
1346 Mutex::Autolock lock(mCore->mMutex);
1347 mCore->mGenerationNumber = generationNumber;
1348 return NO_ERROR;
1349}
1350
Dan Stozac6f30bd2015-06-08 09:32:50 -07001351String8 BufferQueueProducer::getConsumerName() const {
1352 ATRACE_CALL();
1353 BQ_LOGV("getConsumerName: %s", mConsumerName.string());
1354 return mConsumerName;
1355}
1356
Pablo Ceballos3559fbf2016-03-17 15:50:23 -07001357status_t BufferQueueProducer::setSharedBufferMode(bool sharedBufferMode) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001358 ATRACE_CALL();
Pablo Ceballos3559fbf2016-03-17 15:50:23 -07001359 BQ_LOGV("setSharedBufferMode: %d", sharedBufferMode);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001360
1361 Mutex::Autolock lock(mCore->mMutex);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -07001362 if (!sharedBufferMode) {
1363 mCore->mSharedBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT;
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001364 }
Pablo Ceballos3559fbf2016-03-17 15:50:23 -07001365 mCore->mSharedBufferMode = sharedBufferMode;
Dan Stoza127fc632015-06-30 13:43:32 -07001366 return NO_ERROR;
1367}
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001368
Pablo Ceballosff95aab2016-01-13 17:09:58 -08001369status_t BufferQueueProducer::setAutoRefresh(bool autoRefresh) {
1370 ATRACE_CALL();
1371 BQ_LOGV("setAutoRefresh: %d", autoRefresh);
1372
1373 Mutex::Autolock lock(mCore->mMutex);
1374
1375 mCore->mAutoRefresh = autoRefresh;
1376 return NO_ERROR;
1377}
1378
Dan Stoza127fc632015-06-30 13:43:32 -07001379status_t BufferQueueProducer::setDequeueTimeout(nsecs_t timeout) {
1380 ATRACE_CALL();
1381 BQ_LOGV("setDequeueTimeout: %" PRId64, timeout);
1382
Pablo Ceballos981066c2016-02-18 12:54:37 -08001383 Mutex::Autolock lock(mCore->mMutex);
1384 int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode, false,
1385 mCore->mMaxBufferCount) - mCore->getMaxBufferCountLocked();
1386 if (!mCore->adjustAvailableSlotsLocked(delta)) {
1387 BQ_LOGE("setDequeueTimeout: BufferQueue failed to adjust the number of "
1388 "available slots. Delta = %d", delta);
1389 return BAD_VALUE;
Pablo Ceballos23b4abe2016-01-08 12:15:22 -08001390 }
1391
Pablo Ceballos981066c2016-02-18 12:54:37 -08001392 mDequeueTimeout = timeout;
1393 mCore->mDequeueBufferCannotBlock = false;
Pablo Ceballos9e314332016-01-12 13:49:19 -08001394
Pablo Ceballos981066c2016-02-18 12:54:37 -08001395 VALIDATE_CONSISTENCY();
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001396 return NO_ERROR;
1397}
1398
Dan Stoza50101d02016-04-07 16:53:23 -07001399status_t BufferQueueProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
John Reck1a61da52016-04-28 13:18:15 -07001400 sp<Fence>* outFence, float outTransformMatrix[16]) {
Dan Stoza50101d02016-04-07 16:53:23 -07001401 ATRACE_CALL();
1402 BQ_LOGV("getLastQueuedBuffer");
1403
1404 Mutex::Autolock lock(mCore->mMutex);
1405 if (mCore->mLastQueuedSlot == BufferItem::INVALID_BUFFER_SLOT) {
1406 *outBuffer = nullptr;
1407 *outFence = Fence::NO_FENCE;
1408 return NO_ERROR;
1409 }
1410
1411 *outBuffer = mSlots[mCore->mLastQueuedSlot].mGraphicBuffer;
1412 *outFence = mLastQueueBufferFence;
1413
John Reck1a61da52016-04-28 13:18:15 -07001414 // Currently only SurfaceFlinger internally ever changes
1415 // GLConsumer's filtering mode, so we just use 'true' here as
1416 // this is slightly specialized for the current client of this API,
1417 // which does want filtering.
1418 GLConsumer::computeTransformMatrix(outTransformMatrix,
1419 mSlots[mCore->mLastQueuedSlot].mGraphicBuffer, mLastQueuedCrop,
1420 mLastQueuedTransform, true /* filter */);
1421
Dan Stoza50101d02016-04-07 16:53:23 -07001422 return NO_ERROR;
1423}
1424
Pablo Ceballosce796e72016-02-04 19:10:51 -08001425bool BufferQueueProducer::getFrameTimestamps(uint64_t frameNumber,
1426 FrameTimestamps* outTimestamps) const {
1427 ATRACE_CALL();
1428 BQ_LOGV("getFrameTimestamps, %" PRIu64, frameNumber);
1429 sp<IConsumerListener> listener;
1430
1431 {
1432 Mutex::Autolock lock(mCore->mMutex);
1433 listener = mCore->mConsumerListener;
1434 }
1435 if (listener != NULL) {
1436 return listener->getFrameTimestamps(frameNumber, outTimestamps);
1437 }
1438 return false;
1439}
1440
Dan Stoza289ade12014-02-28 11:17:17 -08001441void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
1442 // If we're here, it means that a producer we were connected to died.
1443 // We're guaranteed that we are still connected to it because we remove
1444 // this callback upon disconnect. It's therefore safe to read mConnectedApi
1445 // without synchronization here.
1446 int api = mCore->mConnectedApi;
1447 disconnect(api);
1448}
1449
Pablo Ceballos8e3e92b2016-06-27 17:56:53 -07001450status_t BufferQueueProducer::getUniqueId(uint64_t* outId) const {
1451 BQ_LOGV("getUniqueId");
1452
1453 *outId = mCore->mUniqueId;
1454 return NO_ERROR;
1455}
1456
Dan Stoza289ade12014-02-28 11:17:17 -08001457} // namespace android