blob: bc23f494b2471802b19073c544f94e132c7a1d69 [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
Robert Carr97b9c862016-09-08 13:54:35 -070031#include <binder/IPCThreadState.h>
Dan Stoza289ade12014-02-28 11:17:17 -080032#include <gui/BufferItem.h>
33#include <gui/BufferQueueCore.h>
34#include <gui/BufferQueueProducer.h>
Ady Abraham107788e2023-10-17 12:31:08 -070035
Ady Abraham6cdd3fd2023-09-07 18:45:58 -070036#include <gui/FrameRateUtils.h>
John Reck1a61da52016-04-28 13:18:15 -070037#include <gui/GLConsumer.h>
Dan Stoza289ade12014-02-28 11:17:17 -080038#include <gui/IConsumerListener.h>
Dan Stozaf0eaf252014-03-21 13:05:51 -070039#include <gui/IProducerListener.h>
Vishnu Nair14a3c112023-04-21 14:49:47 -070040#include <gui/TraceUtils.h>
Jayant Chowdharyad9fe272019-03-07 22:36:06 -080041#include <private/gui/BufferQueueThreadState.h>
Dan Stoza289ade12014-02-28 11:17:17 -080042
43#include <utils/Log.h>
44#include <utils/Trace.h>
45
Mathias Agopian6a3c05b2017-04-27 20:06:55 -070046#include <system/window.h>
47
Mathias Agopianb96661f2024-09-17 11:45:38 -070048#include <com_android_graphics_libgui_flags.h>
49
Dan Stoza289ade12014-02-28 11:17:17 -080050namespace android {
Mathias Agopianb96661f2024-09-17 11:45:38 -070051using namespace com::android::graphics::libgui;
Dan Stoza289ade12014-02-28 11:17:17 -080052
Iris Chang430193f2019-12-04 16:25:46 +080053// Macros for include BufferQueueCore information in log messages
54#define BQ_LOGV(x, ...) \
Tomasz Wasilczykf2add402023-08-11 00:06:51 +000055 ALOGV("[%s](id:%" PRIx64 ",api:%d,p:%d,c:%" PRIu64 ") " x, mConsumerName.c_str(), \
Iris Chang430193f2019-12-04 16:25:46 +080056 mCore->mUniqueId, mCore->mConnectedApi, mCore->mConnectedPid, (mCore->mUniqueId) >> 32, \
57 ##__VA_ARGS__)
58#define BQ_LOGD(x, ...) \
Tomasz Wasilczykf2add402023-08-11 00:06:51 +000059 ALOGD("[%s](id:%" PRIx64 ",api:%d,p:%d,c:%" PRIu64 ") " x, mConsumerName.c_str(), \
Iris Chang430193f2019-12-04 16:25:46 +080060 mCore->mUniqueId, mCore->mConnectedApi, mCore->mConnectedPid, (mCore->mUniqueId) >> 32, \
61 ##__VA_ARGS__)
62#define BQ_LOGI(x, ...) \
Tomasz Wasilczykf2add402023-08-11 00:06:51 +000063 ALOGI("[%s](id:%" PRIx64 ",api:%d,p:%d,c:%" PRIu64 ") " x, mConsumerName.c_str(), \
Iris Chang430193f2019-12-04 16:25:46 +080064 mCore->mUniqueId, mCore->mConnectedApi, mCore->mConnectedPid, (mCore->mUniqueId) >> 32, \
65 ##__VA_ARGS__)
66#define BQ_LOGW(x, ...) \
Tomasz Wasilczykf2add402023-08-11 00:06:51 +000067 ALOGW("[%s](id:%" PRIx64 ",api:%d,p:%d,c:%" PRIu64 ") " x, mConsumerName.c_str(), \
Iris Chang430193f2019-12-04 16:25:46 +080068 mCore->mUniqueId, mCore->mConnectedApi, mCore->mConnectedPid, (mCore->mUniqueId) >> 32, \
69 ##__VA_ARGS__)
70#define BQ_LOGE(x, ...) \
Tomasz Wasilczykf2add402023-08-11 00:06:51 +000071 ALOGE("[%s](id:%" PRIx64 ",api:%d,p:%d,c:%" PRIu64 ") " x, mConsumerName.c_str(), \
Iris Chang430193f2019-12-04 16:25:46 +080072 mCore->mUniqueId, mCore->mConnectedApi, mCore->mConnectedPid, (mCore->mUniqueId) >> 32, \
73 ##__VA_ARGS__)
74
Craig Donner6ebc46a2016-10-21 15:23:44 -070075static constexpr uint32_t BQ_LAYER_COUNT = 1;
Chong Zhang62493092020-01-15 16:04:47 -080076ProducerListener::~ProducerListener() = default;
Craig Donner6ebc46a2016-10-21 15:23:44 -070077
Irvel468051e2016-06-13 16:44:44 -070078BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core,
79 bool consumerIsSurfaceFlinger) :
Dan Stoza289ade12014-02-28 11:17:17 -080080 mCore(core),
81 mSlots(core->mSlots),
Ruben Brunk1681d952014-06-27 15:51:55 -070082 mConsumerName(),
Eric Penner99a0afb2014-09-30 11:28:30 -070083 mStickyTransform(0),
Irvel468051e2016-06-13 16:44:44 -070084 mConsumerIsSurfaceFlinger(consumerIsSurfaceFlinger),
Dan Stoza8dc55392014-11-04 11:37:46 -080085 mLastQueueBufferFence(Fence::NO_FENCE),
Pablo Ceballosbd3577e2016-06-20 17:40:34 -070086 mLastQueuedTransform(0),
Dan Stoza8dc55392014-11-04 11:37:46 -080087 mCallbackMutex(),
88 mNextCallbackTicket(0),
89 mCurrentCallbackTicket(0),
Dan Stoza127fc632015-06-30 13:43:32 -070090 mCallbackCondition(),
Jorim Jaggi35b4e382019-03-28 00:44:03 +010091 mDequeueTimeout(-1),
92 mDequeueWaitingForAllocation(false) {}
Dan Stoza289ade12014-02-28 11:17:17 -080093
94BufferQueueProducer::~BufferQueueProducer() {}
95
96status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
97 ATRACE_CALL();
98 BQ_LOGV("requestBuffer: slot %d", slot);
Jorim Jaggi6ae55032019-04-02 02:27:44 +020099 std::lock_guard<std::mutex> lock(mCore->mMutex);
Dan Stoza289ade12014-02-28 11:17:17 -0800100
101 if (mCore->mIsAbandoned) {
102 BQ_LOGE("requestBuffer: BufferQueue has been abandoned");
103 return NO_INIT;
104 }
105
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700106 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
107 BQ_LOGE("requestBuffer: BufferQueue has no connected producer");
108 return NO_INIT;
109 }
110
Dan Stoza3e96f192014-03-03 10:16:19 -0800111 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
Dan Stoza289ade12014-02-28 11:17:17 -0800112 BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)",
Dan Stoza3e96f192014-03-03 10:16:19 -0800113 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
Dan Stoza289ade12014-02-28 11:17:17 -0800114 return BAD_VALUE;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700115 } else if (!mSlots[slot].mBufferState.isDequeued()) {
Dan Stoza289ade12014-02-28 11:17:17 -0800116 BQ_LOGE("requestBuffer: slot %d is not owned by the producer "
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700117 "(state = %s)", slot, mSlots[slot].mBufferState.string());
Dan Stoza289ade12014-02-28 11:17:17 -0800118 return BAD_VALUE;
119 }
120
121 mSlots[slot].mRequestBufferCalled = true;
122 *buf = mSlots[slot].mGraphicBuffer;
123 return NO_ERROR;
124}
125
Pablo Ceballosfa455352015-08-12 17:47:47 -0700126status_t BufferQueueProducer::setMaxDequeuedBufferCount(
127 int maxDequeuedBuffers) {
Brian Lindahlc794b692023-01-31 15:42:47 -0700128 int maxBufferCount;
129 return setMaxDequeuedBufferCount(maxDequeuedBuffers, &maxBufferCount);
130}
131
132status_t BufferQueueProducer::setMaxDequeuedBufferCount(int maxDequeuedBuffers,
133 int* maxBufferCount) {
Vishnu Nair14a3c112023-04-21 14:49:47 -0700134 ATRACE_FORMAT("%s(%d)", __func__, maxDequeuedBuffers);
Pablo Ceballosfa455352015-08-12 17:47:47 -0700135 BQ_LOGV("setMaxDequeuedBufferCount: maxDequeuedBuffers = %d",
136 maxDequeuedBuffers);
137
Pablo Ceballos981066c2016-02-18 12:54:37 -0800138 sp<IConsumerListener> listener;
Pablo Ceballosfa455352015-08-12 17:47:47 -0700139 { // Autolock scope
Jorim Jaggi6ae55032019-04-02 02:27:44 +0200140 std::unique_lock<std::mutex> lock(mCore->mMutex);
141 mCore->waitWhileAllocatingLocked(lock);
Pablo Ceballosfa455352015-08-12 17:47:47 -0700142
143 if (mCore->mIsAbandoned) {
144 BQ_LOGE("setMaxDequeuedBufferCount: BufferQueue has been "
145 "abandoned");
146 return NO_INIT;
147 }
148
Brian Lindahlc794b692023-01-31 15:42:47 -0700149 *maxBufferCount = mCore->getMaxBufferCountLocked();
150
Pablo Ceballos245cc5b2016-04-19 11:33:00 -0700151 if (maxDequeuedBuffers == mCore->mMaxDequeuedBufferCount) {
152 return NO_ERROR;
153 }
154
Pablo Ceballos72daab62015-12-07 16:38:43 -0800155 // The new maxDequeuedBuffer count should not be violated by the number
156 // of currently dequeued buffers
157 int dequeuedCount = 0;
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800158 for (int s : mCore->mActiveBuffers) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700159 if (mSlots[s].mBufferState.isDequeued()) {
Pablo Ceballos72daab62015-12-07 16:38:43 -0800160 dequeuedCount++;
Pablo Ceballosfa455352015-08-12 17:47:47 -0700161 }
162 }
Pablo Ceballos72daab62015-12-07 16:38:43 -0800163 if (dequeuedCount > maxDequeuedBuffers) {
164 BQ_LOGE("setMaxDequeuedBufferCount: the requested maxDequeuedBuffer"
165 "count (%d) exceeds the current dequeued buffer count (%d)",
166 maxDequeuedBuffers, dequeuedCount);
167 return BAD_VALUE;
168 }
Pablo Ceballosfa455352015-08-12 17:47:47 -0700169
Rajat Yadavd108d682021-08-31 18:58:23 +0800170 int minUndequedBufferCount = mCore->getMinUndequeuedBufferCountLocked();
171 int bufferCount = minUndequedBufferCount + maxDequeuedBuffers;
Pablo Ceballosfa455352015-08-12 17:47:47 -0700172
173 if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
174 BQ_LOGE("setMaxDequeuedBufferCount: bufferCount %d too large "
175 "(max %d)", bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
Rajat Yadavd108d682021-08-31 18:58:23 +0800176 bufferCount = BufferQueueDefs::NUM_BUFFER_SLOTS;
177 maxDequeuedBuffers = bufferCount - minUndequedBufferCount;
Pablo Ceballosfa455352015-08-12 17:47:47 -0700178 }
179
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700180 const int minBufferSlots = mCore->getMinMaxBufferCountLocked();
Pablo Ceballosfa455352015-08-12 17:47:47 -0700181 if (bufferCount < minBufferSlots) {
182 BQ_LOGE("setMaxDequeuedBufferCount: requested buffer count %d is "
183 "less than minimum %d", bufferCount, minBufferSlots);
184 return BAD_VALUE;
185 }
186
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700187 if (bufferCount > mCore->mMaxBufferCount) {
188 BQ_LOGE("setMaxDequeuedBufferCount: %d dequeued buffers would "
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700189 "exceed the maxBufferCount (%d) (maxAcquired %d async %d "
190 "mDequeuedBufferCannotBlock %d)", maxDequeuedBuffers,
191 mCore->mMaxBufferCount, mCore->mMaxAcquiredBufferCount,
192 mCore->mAsyncMode, mCore->mDequeueBufferCannotBlock);
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700193 return BAD_VALUE;
194 }
195
Pablo Ceballos72daab62015-12-07 16:38:43 -0800196 int delta = maxDequeuedBuffers - mCore->mMaxDequeuedBufferCount;
Pablo Ceballos981066c2016-02-18 12:54:37 -0800197 if (!mCore->adjustAvailableSlotsLocked(delta)) {
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800198 return BAD_VALUE;
199 }
Pablo Ceballosfa455352015-08-12 17:47:47 -0700200 mCore->mMaxDequeuedBufferCount = maxDequeuedBuffers;
Brian Lindahlc794b692023-01-31 15:42:47 -0700201 *maxBufferCount = mCore->getMaxBufferCountLocked();
Pablo Ceballos9e314332016-01-12 13:49:19 -0800202 VALIDATE_CONSISTENCY();
Pablo Ceballos72daab62015-12-07 16:38:43 -0800203 if (delta < 0) {
Pablo Ceballos981066c2016-02-18 12:54:37 -0800204 listener = mCore->mConsumerListener;
Pablo Ceballos72daab62015-12-07 16:38:43 -0800205 }
Patrick Williams078d7362024-08-27 10:20:39 -0500206#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
207 mCore->notifyBufferReleased();
208#else
Jorim Jaggi6ae55032019-04-02 02:27:44 +0200209 mCore->mDequeueCondition.notify_all();
Patrick Williams078d7362024-08-27 10:20:39 -0500210#endif
Pablo Ceballosfa455352015-08-12 17:47:47 -0700211 } // Autolock scope
212
213 // Call back without lock held
Yi Kong48a619f2018-06-05 16:34:59 -0700214 if (listener != nullptr) {
Pablo Ceballos981066c2016-02-18 12:54:37 -0800215 listener->onBuffersReleased();
Pablo Ceballosfa455352015-08-12 17:47:47 -0700216 }
217
218 return NO_ERROR;
219}
220
221status_t BufferQueueProducer::setAsyncMode(bool async) {
222 ATRACE_CALL();
223 BQ_LOGV("setAsyncMode: async = %d", async);
224
Pablo Ceballos981066c2016-02-18 12:54:37 -0800225 sp<IConsumerListener> listener;
Pablo Ceballosfa455352015-08-12 17:47:47 -0700226 { // Autolock scope
Jorim Jaggi6ae55032019-04-02 02:27:44 +0200227 std::unique_lock<std::mutex> lock(mCore->mMutex);
228 mCore->waitWhileAllocatingLocked(lock);
Pablo Ceballosfa455352015-08-12 17:47:47 -0700229
230 if (mCore->mIsAbandoned) {
231 BQ_LOGE("setAsyncMode: BufferQueue has been abandoned");
232 return NO_INIT;
233 }
234
Pablo Ceballos245cc5b2016-04-19 11:33:00 -0700235 if (async == mCore->mAsyncMode) {
236 return NO_ERROR;
237 }
238
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700239 if ((mCore->mMaxAcquiredBufferCount + mCore->mMaxDequeuedBufferCount +
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700240 (async || mCore->mDequeueBufferCannotBlock ? 1 : 0)) >
241 mCore->mMaxBufferCount) {
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700242 BQ_LOGE("setAsyncMode(%d): this call would cause the "
243 "maxBufferCount (%d) to be exceeded (maxAcquired %d "
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700244 "maxDequeued %d mDequeueBufferCannotBlock %d)", async,
245 mCore->mMaxBufferCount, mCore->mMaxAcquiredBufferCount,
246 mCore->mMaxDequeuedBufferCount,
247 mCore->mDequeueBufferCannotBlock);
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700248 return BAD_VALUE;
249 }
250
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800251 int delta = mCore->getMaxBufferCountLocked(async,
252 mCore->mDequeueBufferCannotBlock, mCore->mMaxBufferCount)
253 - mCore->getMaxBufferCountLocked();
254
Pablo Ceballos981066c2016-02-18 12:54:37 -0800255 if (!mCore->adjustAvailableSlotsLocked(delta)) {
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800256 BQ_LOGE("setAsyncMode: BufferQueue failed to adjust the number of "
257 "available slots. Delta = %d", delta);
258 return BAD_VALUE;
259 }
Pablo Ceballosfa455352015-08-12 17:47:47 -0700260 mCore->mAsyncMode = async;
Pablo Ceballos9e314332016-01-12 13:49:19 -0800261 VALIDATE_CONSISTENCY();
Patrick Williams078d7362024-08-27 10:20:39 -0500262#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
263 mCore->notifyBufferReleased();
264#else
Jorim Jaggi6ae55032019-04-02 02:27:44 +0200265 mCore->mDequeueCondition.notify_all();
Patrick Williams078d7362024-08-27 10:20:39 -0500266#endif
267
Pablo Ceballos245cc5b2016-04-19 11:33:00 -0700268 if (delta < 0) {
269 listener = mCore->mConsumerListener;
270 }
Pablo Ceballosfa455352015-08-12 17:47:47 -0700271 } // Autolock scope
272
273 // Call back without lock held
Yi Kong48a619f2018-06-05 16:34:59 -0700274 if (listener != nullptr) {
Pablo Ceballos981066c2016-02-18 12:54:37 -0800275 listener->onBuffersReleased();
Pablo Ceballosfa455352015-08-12 17:47:47 -0700276 }
277 return NO_ERROR;
278}
279
Dan Stoza5ecfb682016-01-04 17:01:02 -0800280int BufferQueueProducer::getFreeBufferLocked() const {
281 if (mCore->mFreeBuffers.empty()) {
282 return BufferQueueCore::INVALID_BUFFER_SLOT;
283 }
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800284 int slot = mCore->mFreeBuffers.front();
Dan Stoza5ecfb682016-01-04 17:01:02 -0800285 mCore->mFreeBuffers.pop_front();
286 return slot;
287}
288
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800289int BufferQueueProducer::getFreeSlotLocked() const {
Dan Stoza5ecfb682016-01-04 17:01:02 -0800290 if (mCore->mFreeSlots.empty()) {
291 return BufferQueueCore::INVALID_BUFFER_SLOT;
292 }
Pablo Ceballosdce5c552016-02-10 15:43:22 -0800293 int slot = *(mCore->mFreeSlots.begin());
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800294 mCore->mFreeSlots.erase(slot);
Pablo Ceballosdce5c552016-02-10 15:43:22 -0800295 return slot;
Dan Stoza5ecfb682016-01-04 17:01:02 -0800296}
297
298status_t BufferQueueProducer::waitForFreeSlotThenRelock(FreeSlotCaller caller,
Jorim Jaggi6ae55032019-04-02 02:27:44 +0200299 std::unique_lock<std::mutex>& lock, int* found) const {
Dan Stoza5ecfb682016-01-04 17:01:02 -0800300 auto callerString = (caller == FreeSlotCaller::Dequeue) ?
301 "dequeueBuffer" : "attachBuffer";
Dan Stoza9f3053d2014-03-06 15:14:33 -0800302 bool tryAgain = true;
303 while (tryAgain) {
304 if (mCore->mIsAbandoned) {
Dan Stoza5ecfb682016-01-04 17:01:02 -0800305 BQ_LOGE("%s: BufferQueue has been abandoned", callerString);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800306 return NO_INIT;
307 }
308
Dan Stoza9f3053d2014-03-06 15:14:33 -0800309 int dequeuedCount = 0;
310 int acquiredCount = 0;
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800311 for (int s : mCore->mActiveBuffers) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700312 if (mSlots[s].mBufferState.isDequeued()) {
313 ++dequeuedCount;
314 }
315 if (mSlots[s].mBufferState.isAcquired()) {
316 ++acquiredCount;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800317 }
318 }
319
Pablo Ceballose5b755a2015-08-13 16:18:19 -0700320 // Producers are not allowed to dequeue more than
321 // mMaxDequeuedBufferCount buffers.
322 // This check is only done if a buffer has already been queued
323 if (mCore->mBufferHasBeenQueued &&
324 dequeuedCount >= mCore->mMaxDequeuedBufferCount) {
Sungtak Leeaf141242019-04-24 16:36:44 -0700325 // Supress error logs when timeout is non-negative.
326 if (mDequeueTimeout < 0) {
327 BQ_LOGE("%s: attempting to exceed the max dequeued buffer "
328 "count (%d)", callerString,
329 mCore->mMaxDequeuedBufferCount);
330 }
Dan Stoza9f3053d2014-03-06 15:14:33 -0800331 return INVALID_OPERATION;
332 }
333
Dan Stoza0de7ea72015-04-23 13:20:51 -0700334 *found = BufferQueueCore::INVALID_BUFFER_SLOT;
335
Dan Stozaae3c3682014-04-18 15:43:35 -0700336 // If we disconnect and reconnect quickly, we can be in a state where
337 // our slots are empty but we have many buffers in the queue. This can
338 // cause us to run out of memory if we outrun the consumer. Wait here if
339 // it looks like we have too many buffers queued up.
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800340 const int maxBufferCount = mCore->getMaxBufferCountLocked();
Mark Salyzyn8f515ce2014-06-09 14:32:04 -0700341 bool tooManyBuffers = mCore->mQueue.size()
342 > static_cast<size_t>(maxBufferCount);
Dan Stozaae3c3682014-04-18 15:43:35 -0700343 if (tooManyBuffers) {
Dan Stoza5ecfb682016-01-04 17:01:02 -0800344 BQ_LOGV("%s: queue size is %zu, waiting", callerString,
Dan Stozaae3c3682014-04-18 15:43:35 -0700345 mCore->mQueue.size());
Dan Stoza0de7ea72015-04-23 13:20:51 -0700346 } else {
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700347 // If in shared buffer mode and a shared buffer exists, always
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700348 // return it.
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700349 if (mCore->mSharedBufferMode && mCore->mSharedBufferSlot !=
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700350 BufferQueueCore::INVALID_BUFFER_SLOT) {
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700351 *found = mCore->mSharedBufferSlot;
Dan Stoza5ecfb682016-01-04 17:01:02 -0800352 } else {
353 if (caller == FreeSlotCaller::Dequeue) {
354 // If we're calling this from dequeue, prefer free buffers
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800355 int slot = getFreeBufferLocked();
Dan Stoza5ecfb682016-01-04 17:01:02 -0800356 if (slot != BufferQueueCore::INVALID_BUFFER_SLOT) {
357 *found = slot;
358 } else if (mCore->mAllowAllocation) {
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800359 *found = getFreeSlotLocked();
Dan Stoza5ecfb682016-01-04 17:01:02 -0800360 }
361 } else {
362 // If we're calling this from attach, prefer free slots
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800363 int slot = getFreeSlotLocked();
Dan Stoza5ecfb682016-01-04 17:01:02 -0800364 if (slot != BufferQueueCore::INVALID_BUFFER_SLOT) {
365 *found = slot;
366 } else {
367 *found = getFreeBufferLocked();
368 }
Dan Stoza0de7ea72015-04-23 13:20:51 -0700369 }
370 }
Dan Stozaae3c3682014-04-18 15:43:35 -0700371 }
372
373 // If no buffer is found, or if the queue has too many buffers
374 // outstanding, wait for a buffer to be acquired or released, or for the
375 // max buffer count to change.
376 tryAgain = (*found == BufferQueueCore::INVALID_BUFFER_SLOT) ||
377 tooManyBuffers;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800378 if (tryAgain) {
379 // Return an error if we're in non-blocking mode (producer and
380 // consumer are controlled by the application).
381 // However, the consumer is allowed to briefly acquire an extra
382 // buffer (which could cause us to have to wait here), which is
383 // okay, since it is only used to implement an atomic acquire +
384 // release (e.g., in GLConsumer::updateTexImage())
Pablo Ceballosfa455352015-08-12 17:47:47 -0700385 if ((mCore->mDequeueBufferCannotBlock || mCore->mAsyncMode) &&
Dan Stoza9f3053d2014-03-06 15:14:33 -0800386 (acquiredCount <= mCore->mMaxAcquiredBufferCount)) {
387 return WOULD_BLOCK;
388 }
Patrick Williams078d7362024-08-27 10:20:39 -0500389#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
390 if (status_t status = waitForBufferRelease(lock, mDequeueTimeout);
391 status == TIMED_OUT) {
392 return TIMED_OUT;
393 }
394#else
Dan Stoza127fc632015-06-30 13:43:32 -0700395 if (mDequeueTimeout >= 0) {
Jorim Jaggi6ae55032019-04-02 02:27:44 +0200396 std::cv_status result = mCore->mDequeueCondition.wait_for(lock,
397 std::chrono::nanoseconds(mDequeueTimeout));
398 if (result == std::cv_status::timeout) {
399 return TIMED_OUT;
Dan Stoza127fc632015-06-30 13:43:32 -0700400 }
401 } else {
Jorim Jaggi6ae55032019-04-02 02:27:44 +0200402 mCore->mDequeueCondition.wait(lock);
Dan Stoza127fc632015-06-30 13:43:32 -0700403 }
Patrick Williams078d7362024-08-27 10:20:39 -0500404#endif
Dan Stoza9f3053d2014-03-06 15:14:33 -0800405 }
406 } // while (tryAgain)
407
408 return NO_ERROR;
409}
410
Patrick Williams078d7362024-08-27 10:20:39 -0500411#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
412status_t BufferQueueProducer::waitForBufferRelease(std::unique_lock<std::mutex>& lock,
413 nsecs_t timeout) const {
414 if (mDequeueTimeout >= 0) {
415 std::cv_status result =
416 mCore->mDequeueCondition.wait_for(lock, std::chrono::nanoseconds(timeout));
417 if (result == std::cv_status::timeout) {
418 return TIMED_OUT;
419 }
420 } else {
421 mCore->mDequeueCondition.wait(lock);
422 }
423 return OK;
424}
425#endif
426
Ian Elliottd11b0442017-07-18 11:05:49 -0600427status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* outFence,
428 uint32_t width, uint32_t height, PixelFormat format,
429 uint64_t usage, uint64_t* outBufferAge,
430 FrameEventHistoryDelta* outTimestamps) {
Dan Stoza289ade12014-02-28 11:17:17 -0800431 ATRACE_CALL();
432 { // Autolock scope
Jorim Jaggi6ae55032019-04-02 02:27:44 +0200433 std::lock_guard<std::mutex> lock(mCore->mMutex);
Dan Stoza289ade12014-02-28 11:17:17 -0800434 mConsumerName = mCore->mConsumerName;
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700435
436 if (mCore->mIsAbandoned) {
437 BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
438 return NO_INIT;
439 }
440
441 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
442 BQ_LOGE("dequeueBuffer: BufferQueue has no connected producer");
443 return NO_INIT;
444 }
Dan Stoza289ade12014-02-28 11:17:17 -0800445 } // Autolock scope
446
Mathias Agopiancb496ac2017-05-22 14:21:00 -0700447 BQ_LOGV("dequeueBuffer: w=%u h=%u format=%#x, usage=%#" PRIx64, width, height, format, usage);
Dan Stoza289ade12014-02-28 11:17:17 -0800448
449 if ((width && !height) || (!width && height)) {
450 BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height);
451 return BAD_VALUE;
452 }
453
454 status_t returnFlags = NO_ERROR;
Jim Shargo90842182024-11-14 00:49:27 +0000455#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
Dan Stoza289ade12014-02-28 11:17:17 -0800456 EGLDisplay eglDisplay = EGL_NO_DISPLAY;
457 EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;
Jim Shargo90842182024-11-14 00:49:27 +0000458#endif
Dan Stoza9f3053d2014-03-06 15:14:33 -0800459 bool attachedByConsumer = false;
Dan Stoza289ade12014-02-28 11:17:17 -0800460
Shuzhen Wang266f31a2023-07-24 22:45:44 +0000461 sp<IConsumerListener> listener;
462 bool callOnFrameDequeued = false;
463 uint64_t bufferId = 0; // Only used if callOnFrameDequeued == true
John Reckdb164ff2024-04-03 16:59:28 -0400464#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
465 std::vector<gui::AdditionalOptions> allocOptions;
466 uint32_t allocOptionsGenId = 0;
467#endif
468
Dan Stoza289ade12014-02-28 11:17:17 -0800469 { // Autolock scope
Jorim Jaggi6ae55032019-04-02 02:27:44 +0200470 std::unique_lock<std::mutex> lock(mCore->mMutex);
Dan Stoza289ade12014-02-28 11:17:17 -0800471
Jorim Jaggi35b4e382019-03-28 00:44:03 +0100472 // If we don't have a free buffer, but we are currently allocating, we wait until allocation
473 // is finished such that we don't allocate in parallel.
474 if (mCore->mFreeBuffers.empty() && mCore->mIsAllocating) {
475 mDequeueWaitingForAllocation = true;
476 mCore->waitWhileAllocatingLocked(lock);
477 mDequeueWaitingForAllocation = false;
478 mDequeueWaitingForAllocationCondition.notify_all();
479 }
Dan Stoza289ade12014-02-28 11:17:17 -0800480
481 if (format == 0) {
482 format = mCore->mDefaultBufferFormat;
483 }
484
485 // Enable the usage bits the consumer requested
486 usage |= mCore->mConsumerUsageBits;
487
Dan Stoza9de72932015-04-16 17:28:43 -0700488 const bool useDefaultSize = !width && !height;
489 if (useDefaultSize) {
490 width = mCore->mDefaultWidth;
491 height = mCore->mDefaultHeight;
Yiwei Zhang538cedc2019-06-24 19:35:03 -0700492 if (mCore->mAutoPrerotation &&
493 (mCore->mTransformHintInUse & NATIVE_WINDOW_TRANSFORM_ROT_90)) {
494 std::swap(width, height);
495 }
Dan Stoza9f3053d2014-03-06 15:14:33 -0800496 }
Dan Stoza289ade12014-02-28 11:17:17 -0800497
Pablo Ceballos981066c2016-02-18 12:54:37 -0800498 int found = BufferItem::INVALID_BUFFER_SLOT;
Dan Stoza9de72932015-04-16 17:28:43 -0700499 while (found == BufferItem::INVALID_BUFFER_SLOT) {
Jorim Jaggi6ae55032019-04-02 02:27:44 +0200500 status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Dequeue, lock, &found);
Dan Stoza9de72932015-04-16 17:28:43 -0700501 if (status != NO_ERROR) {
502 return status;
503 }
504
505 // This should not happen
506 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
507 BQ_LOGE("dequeueBuffer: no available buffer slots");
508 return -EBUSY;
509 }
510
511 const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
512
513 // If we are not allowed to allocate new buffers,
514 // waitForFreeSlotThenRelock must have returned a slot containing a
515 // buffer. If this buffer would require reallocation to meet the
516 // requested attributes, we free it and attempt to get another one.
517 if (!mCore->mAllowAllocation) {
Mathias Agopiancb496ac2017-05-22 14:21:00 -0700518 if (buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) {
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700519 if (mCore->mSharedBufferSlot == found) {
Mathias Agopiancb496ac2017-05-22 14:21:00 -0700520 BQ_LOGE("dequeueBuffer: cannot re-allocate a sharedbuffer");
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700521 return BAD_VALUE;
522 }
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800523 mCore->mFreeSlots.insert(found);
524 mCore->clearBufferSlotLocked(found);
Dan Stoza9de72932015-04-16 17:28:43 -0700525 found = BufferItem::INVALID_BUFFER_SLOT;
526 continue;
527 }
528 }
Dan Stoza289ade12014-02-28 11:17:17 -0800529 }
530
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800531 const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800532
John Reckdb164ff2024-04-03 16:59:28 -0400533 bool needsReallocation = buffer == nullptr ||
534 buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage);
535
536#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
537 needsReallocation |= mSlots[found].mAdditionalOptionsGenerationId !=
538 mCore->mAdditionalOptionsGenerationId;
539#endif
540
541 if (mCore->mSharedBufferSlot == found && needsReallocation) {
542 BQ_LOGE("dequeueBuffer: cannot re-allocate a shared buffer");
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800543 return BAD_VALUE;
544 }
545
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700546 if (mCore->mSharedBufferSlot != found) {
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800547 mCore->mActiveBuffers.insert(found);
548 }
Dan Stoza289ade12014-02-28 11:17:17 -0800549 *outSlot = found;
550 ATRACE_BUFFER_INDEX(found);
551
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800552 attachedByConsumer = mSlots[found].mNeedsReallocation;
553 mSlots[found].mNeedsReallocation = false;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800554
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700555 mSlots[found].mBufferState.dequeue();
556
John Reckdb164ff2024-04-03 16:59:28 -0400557 if (needsReallocation) {
Vishnu Nair14a3c112023-04-21 14:49:47 -0700558 if (CC_UNLIKELY(ATRACE_ENABLED())) {
559 if (buffer == nullptr) {
Tomasz Wasilczyk02fd95c2023-08-30 17:51:31 +0000560 ATRACE_FORMAT_INSTANT("%s buffer reallocation: null", mConsumerName.c_str());
Vishnu Nair14a3c112023-04-21 14:49:47 -0700561 } else {
562 ATRACE_FORMAT_INSTANT("%s buffer reallocation actual %dx%d format:%d "
563 "layerCount:%d "
564 "usage:%d requested: %dx%d format:%d layerCount:%d "
565 "usage:%d ",
Tomasz Wasilczyk02fd95c2023-08-30 17:51:31 +0000566 mConsumerName.c_str(), width, height, format,
Vishnu Nair14a3c112023-04-21 14:49:47 -0700567 BQ_LAYER_COUNT, usage, buffer->getWidth(),
568 buffer->getHeight(), buffer->getPixelFormat(),
569 buffer->getLayerCount(), buffer->getUsage());
570 }
571 }
Dan Stoza289ade12014-02-28 11:17:17 -0800572 mSlots[found].mAcquireCalled = false;
Yi Kong48a619f2018-06-05 16:34:59 -0700573 mSlots[found].mGraphicBuffer = nullptr;
Dan Stoza289ade12014-02-28 11:17:17 -0800574 mSlots[found].mRequestBufferCalled = false;
Jim Shargo90842182024-11-14 00:49:27 +0000575#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
Dan Stoza289ade12014-02-28 11:17:17 -0800576 mSlots[found].mEglDisplay = EGL_NO_DISPLAY;
577 mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
Jim Shargo90842182024-11-14 00:49:27 +0000578#endif
Dan Stoza289ade12014-02-28 11:17:17 -0800579 mSlots[found].mFence = Fence::NO_FENCE;
Dan Stoza4afd8b62015-02-25 16:49:08 -0800580 mCore->mBufferAge = 0;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700581 mCore->mIsAllocating = true;
John Reckdb164ff2024-04-03 16:59:28 -0400582#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
583 allocOptions = mCore->mAdditionalOptions;
584 allocOptionsGenId = mCore->mAdditionalOptionsGenerationId;
585#endif
Dan Stoza289ade12014-02-28 11:17:17 -0800586
587 returnFlags |= BUFFER_NEEDS_REALLOCATION;
Dan Stoza4afd8b62015-02-25 16:49:08 -0800588 } else {
589 // We add 1 because that will be the frame number when this buffer
590 // is queued
Mathias Agopiancb496ac2017-05-22 14:21:00 -0700591 mCore->mBufferAge = mCore->mFrameCounter + 1 - mSlots[found].mFrameNumber;
Dan Stoza289ade12014-02-28 11:17:17 -0800592 }
593
Dan Stoza800b41a2015-04-28 14:20:04 -0700594 BQ_LOGV("dequeueBuffer: setting buffer age to %" PRIu64,
595 mCore->mBufferAge);
Dan Stoza4afd8b62015-02-25 16:49:08 -0800596
Yi Kong48a619f2018-06-05 16:34:59 -0700597 if (CC_UNLIKELY(mSlots[found].mFence == nullptr)) {
Dan Stoza289ade12014-02-28 11:17:17 -0800598 BQ_LOGE("dequeueBuffer: about to return a NULL fence - "
599 "slot=%d w=%d h=%d format=%u",
600 found, buffer->width, buffer->height, buffer->format);
601 }
602
Jim Shargo90842182024-11-14 00:49:27 +0000603#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
Dan Stoza289ade12014-02-28 11:17:17 -0800604 eglDisplay = mSlots[found].mEglDisplay;
605 eglFence = mSlots[found].mEglFence;
Jim Shargo90842182024-11-14 00:49:27 +0000606#endif
Pablo Ceballos28c65ad2016-06-01 15:03:21 -0700607 // Don't return a fence in shared buffer mode, except for the first
608 // frame.
609 *outFence = (mCore->mSharedBufferMode &&
610 mCore->mSharedBufferSlot == found) ?
611 Fence::NO_FENCE : mSlots[found].mFence;
Jim Shargo90842182024-11-14 00:49:27 +0000612#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
Dan Stoza289ade12014-02-28 11:17:17 -0800613 mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
Jim Shargo90842182024-11-14 00:49:27 +0000614#endif
Dan Stoza289ade12014-02-28 11:17:17 -0800615 mSlots[found].mFence = Fence::NO_FENCE;
Pablo Ceballos28c65ad2016-06-01 15:03:21 -0700616
617 // If shared buffer mode has just been enabled, cache the slot of the
618 // first buffer that is dequeued and mark it as the shared buffer.
619 if (mCore->mSharedBufferMode && mCore->mSharedBufferSlot ==
620 BufferQueueCore::INVALID_BUFFER_SLOT) {
621 mCore->mSharedBufferSlot = found;
622 mSlots[found].mBufferState.mShared = true;
623 }
Adithya Srinivasana820af92019-11-01 13:55:17 -0700624
625 if (!(returnFlags & BUFFER_NEEDS_REALLOCATION)) {
Shuzhen Wang266f31a2023-07-24 22:45:44 +0000626 callOnFrameDequeued = true;
627 bufferId = mSlots[*outSlot].mGraphicBuffer->getId();
Adithya Srinivasana820af92019-11-01 13:55:17 -0700628 }
Shuzhen Wang266f31a2023-07-24 22:45:44 +0000629
630 listener = mCore->mConsumerListener;
Dan Stoza289ade12014-02-28 11:17:17 -0800631 } // Autolock scope
632
633 if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
Dan Stoza29a3e902014-06-20 13:13:57 -0700634 BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
John Reckdb164ff2024-04-03 16:59:28 -0400635
636#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
637 std::vector<GraphicBufferAllocator::AdditionalOptions> tempOptions;
638 tempOptions.reserve(allocOptions.size());
639 for (const auto& it : allocOptions) {
640 tempOptions.emplace_back(it.name.c_str(), it.value);
641 }
642 const GraphicBufferAllocator::AllocationRequest allocRequest = {
643 .importBuffer = true,
644 .width = width,
645 .height = height,
646 .format = format,
647 .layerCount = BQ_LAYER_COUNT,
648 .usage = usage,
649 .requestorName = {mConsumerName.c_str(), mConsumerName.size()},
650 .extras = std::move(tempOptions),
651 };
652 sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(allocRequest);
653#else
Tomasz Wasilczykf2add402023-08-11 00:06:51 +0000654 sp<GraphicBuffer> graphicBuffer =
655 new GraphicBuffer(width, height, format, BQ_LAYER_COUNT, usage,
656 {mConsumerName.c_str(), mConsumerName.size()});
John Reckdb164ff2024-04-03 16:59:28 -0400657#endif
Mathias Agopian0556d792017-03-22 15:49:32 -0700658
659 status_t error = graphicBuffer->initCheck();
660
Dan Stoza289ade12014-02-28 11:17:17 -0800661 { // Autolock scope
Jorim Jaggi6ae55032019-04-02 02:27:44 +0200662 std::lock_guard<std::mutex> lock(mCore->mMutex);
Dan Stoza289ade12014-02-28 11:17:17 -0800663
Chia-I Wufeec3b12017-05-25 09:34:56 -0700664 if (error == NO_ERROR && !mCore->mIsAbandoned) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700665 graphicBuffer->setGenerationNumber(mCore->mGenerationNumber);
666 mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
John Reckdb164ff2024-04-03 16:59:28 -0400667#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
668 mSlots[*outSlot].mAdditionalOptionsGenerationId = allocOptionsGenId;
669#endif
Shuzhen Wang266f31a2023-07-24 22:45:44 +0000670 callOnFrameDequeued = true;
671 bufferId = mSlots[*outSlot].mGraphicBuffer->getId();
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700672 }
673
674 mCore->mIsAllocating = false;
Jorim Jaggi6ae55032019-04-02 02:27:44 +0200675 mCore->mIsAllocatingCondition.notify_all();
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700676
Chia-I Wufeec3b12017-05-25 09:34:56 -0700677 if (error != NO_ERROR) {
Pablo Ceballos0a068092016-06-29 15:08:33 -0700678 mCore->mFreeSlots.insert(*outSlot);
679 mCore->clearBufferSlotLocked(*outSlot);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700680 BQ_LOGE("dequeueBuffer: createGraphicBuffer failed");
681 return error;
682 }
683
Dan Stoza289ade12014-02-28 11:17:17 -0800684 if (mCore->mIsAbandoned) {
Pablo Ceballos0a068092016-06-29 15:08:33 -0700685 mCore->mFreeSlots.insert(*outSlot);
686 mCore->clearBufferSlotLocked(*outSlot);
Dan Stoza289ade12014-02-28 11:17:17 -0800687 BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
688 return NO_INIT;
689 }
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800690
Pablo Ceballos9e314332016-01-12 13:49:19 -0800691 VALIDATE_CONSISTENCY();
Dan Stoza289ade12014-02-28 11:17:17 -0800692 } // Autolock scope
693 }
694
Shuzhen Wang266f31a2023-07-24 22:45:44 +0000695 if (listener != nullptr && callOnFrameDequeued) {
696 listener->onFrameDequeued(bufferId);
697 }
698
Dan Stoza9f3053d2014-03-06 15:14:33 -0800699 if (attachedByConsumer) {
700 returnFlags |= BUFFER_NEEDS_REALLOCATION;
701 }
702
Jim Shargo90842182024-11-14 00:49:27 +0000703#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
Dan Stoza289ade12014-02-28 11:17:17 -0800704 if (eglFence != EGL_NO_SYNC_KHR) {
705 EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, 0,
706 1000000000);
707 // If something goes wrong, log the error, but return the buffer without
708 // synchronizing access to it. It's too late at this point to abort the
709 // dequeue operation.
710 if (result == EGL_FALSE) {
711 BQ_LOGE("dequeueBuffer: error %#x waiting for fence",
712 eglGetError());
713 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
714 BQ_LOGE("dequeueBuffer: timeout waiting for fence");
715 }
716 eglDestroySyncKHR(eglDisplay, eglFence);
717 }
Jim Shargo90842182024-11-14 00:49:27 +0000718#endif
Dan Stoza289ade12014-02-28 11:17:17 -0800719
Mark Salyzyn8f515ce2014-06-09 14:32:04 -0700720 BQ_LOGV("dequeueBuffer: returning slot=%d/%" PRIu64 " buf=%p flags=%#x",
721 *outSlot,
Dan Stoza289ade12014-02-28 11:17:17 -0800722 mSlots[*outSlot].mFrameNumber,
tangcheng5614ca02022-04-07 14:26:05 +0800723 mSlots[*outSlot].mGraphicBuffer != nullptr ?
724 mSlots[*outSlot].mGraphicBuffer->handle : nullptr, returnFlags);
Dan Stoza289ade12014-02-28 11:17:17 -0800725
Ian Elliottd11b0442017-07-18 11:05:49 -0600726 if (outBufferAge) {
727 *outBufferAge = mCore->mBufferAge;
728 }
Brian Anderson7c3ba8a2016-07-25 12:48:08 -0700729 addAndGetFrameTimestamps(nullptr, outTimestamps);
730
Dan Stoza289ade12014-02-28 11:17:17 -0800731 return returnFlags;
732}
733
Dan Stoza9f3053d2014-03-06 15:14:33 -0800734status_t BufferQueueProducer::detachBuffer(int slot) {
735 ATRACE_CALL();
736 ATRACE_BUFFER_INDEX(slot);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700737 BQ_LOGV("detachBuffer: slot %d", slot);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800738
Eino-Ville Talvala93dd0512016-06-10 14:21:02 -0700739 sp<IConsumerListener> listener;
Shuzhen Wang266f31a2023-07-24 22:45:44 +0000740 bool callOnFrameDetached = false;
741 uint64_t bufferId = 0; // Only used if callOnFrameDetached is true
Eino-Ville Talvala93dd0512016-06-10 14:21:02 -0700742 {
Jorim Jaggi6ae55032019-04-02 02:27:44 +0200743 std::lock_guard<std::mutex> lock(mCore->mMutex);
Eino-Ville Talvala93dd0512016-06-10 14:21:02 -0700744
745 if (mCore->mIsAbandoned) {
746 BQ_LOGE("detachBuffer: BufferQueue has been abandoned");
747 return NO_INIT;
748 }
749
750 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
751 BQ_LOGE("detachBuffer: BufferQueue has no connected producer");
752 return NO_INIT;
753 }
754
755 if (mCore->mSharedBufferMode || mCore->mSharedBufferSlot == slot) {
756 BQ_LOGE("detachBuffer: cannot detach a buffer in shared buffer mode");
757 return BAD_VALUE;
758 }
759
760 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
761 BQ_LOGE("detachBuffer: slot index %d out of range [0, %d)",
762 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
763 return BAD_VALUE;
764 } else if (!mSlots[slot].mBufferState.isDequeued()) {
Darwin Huang29936fa2021-09-08 18:29:18 +0000765 // TODO(http://b/140581935): This message is BQ_LOGW because it
766 // often logs when no actionable errors are present. Return to
767 // using BQ_LOGE after ensuring this only logs during errors.
768 BQ_LOGW("detachBuffer: slot %d is not owned by the producer "
Eino-Ville Talvala93dd0512016-06-10 14:21:02 -0700769 "(state = %s)", slot, mSlots[slot].mBufferState.string());
770 return BAD_VALUE;
771 } else if (!mSlots[slot].mRequestBufferCalled) {
772 BQ_LOGE("detachBuffer: buffer in slot %d has not been requested",
773 slot);
774 return BAD_VALUE;
775 }
776
Adithya Srinivasan2e434382019-10-09 11:43:01 -0700777 listener = mCore->mConsumerListener;
Robert Carrfc069ba2020-04-20 13:26:31 -0700778 auto gb = mSlots[slot].mGraphicBuffer;
Shuzhen Wang266f31a2023-07-24 22:45:44 +0000779 if (gb != nullptr) {
780 callOnFrameDetached = true;
781 bufferId = gb->getId();
Adithya Srinivasan2e434382019-10-09 11:43:01 -0700782 }
Eino-Ville Talvala93dd0512016-06-10 14:21:02 -0700783 mSlots[slot].mBufferState.detachProducer();
784 mCore->mActiveBuffers.erase(slot);
785 mCore->mFreeSlots.insert(slot);
786 mCore->clearBufferSlotLocked(slot);
Patrick Williams078d7362024-08-27 10:20:39 -0500787#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
788 mCore->notifyBufferReleased();
789#else
Jorim Jaggi6ae55032019-04-02 02:27:44 +0200790 mCore->mDequeueCondition.notify_all();
Patrick Williams078d7362024-08-27 10:20:39 -0500791#endif
Eino-Ville Talvala93dd0512016-06-10 14:21:02 -0700792 VALIDATE_CONSISTENCY();
Dan Stoza9f3053d2014-03-06 15:14:33 -0800793 }
794
Shuzhen Wang266f31a2023-07-24 22:45:44 +0000795 if (listener != nullptr && callOnFrameDetached) {
796 listener->onFrameDetached(bufferId);
797 }
798
Yi Kong48a619f2018-06-05 16:34:59 -0700799 if (listener != nullptr) {
Eino-Ville Talvala93dd0512016-06-10 14:21:02 -0700800 listener->onBuffersReleased();
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700801 }
Pablo Ceballos981066c2016-02-18 12:54:37 -0800802
Dan Stoza9f3053d2014-03-06 15:14:33 -0800803 return NO_ERROR;
804}
805
Dan Stozad9822a32014-03-28 15:25:31 -0700806status_t BufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
807 sp<Fence>* outFence) {
808 ATRACE_CALL();
809
Yi Kong48a619f2018-06-05 16:34:59 -0700810 if (outBuffer == nullptr) {
Dan Stozad9822a32014-03-28 15:25:31 -0700811 BQ_LOGE("detachNextBuffer: outBuffer must not be NULL");
812 return BAD_VALUE;
Yi Kong48a619f2018-06-05 16:34:59 -0700813 } else if (outFence == nullptr) {
Dan Stozad9822a32014-03-28 15:25:31 -0700814 BQ_LOGE("detachNextBuffer: outFence must not be NULL");
815 return BAD_VALUE;
816 }
817
Eino-Ville Talvala2672dec2017-06-13 16:39:11 -0700818 sp<IConsumerListener> listener;
819 {
Jorim Jaggi6ae55032019-04-02 02:27:44 +0200820 std::unique_lock<std::mutex> lock(mCore->mMutex);
Dan Stozad9822a32014-03-28 15:25:31 -0700821
Eino-Ville Talvala2672dec2017-06-13 16:39:11 -0700822 if (mCore->mIsAbandoned) {
823 BQ_LOGE("detachNextBuffer: BufferQueue has been abandoned");
824 return NO_INIT;
825 }
826
827 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
828 BQ_LOGE("detachNextBuffer: BufferQueue has no connected producer");
829 return NO_INIT;
830 }
831
832 if (mCore->mSharedBufferMode) {
833 BQ_LOGE("detachNextBuffer: cannot detach a buffer in shared buffer "
834 "mode");
835 return BAD_VALUE;
836 }
837
Jorim Jaggi6ae55032019-04-02 02:27:44 +0200838 mCore->waitWhileAllocatingLocked(lock);
Eino-Ville Talvala2672dec2017-06-13 16:39:11 -0700839
840 if (mCore->mFreeBuffers.empty()) {
841 return NO_MEMORY;
842 }
843
844 int found = mCore->mFreeBuffers.front();
845 mCore->mFreeBuffers.remove(found);
846 mCore->mFreeSlots.insert(found);
847
848 BQ_LOGV("detachNextBuffer detached slot %d", found);
849
850 *outBuffer = mSlots[found].mGraphicBuffer;
851 *outFence = mSlots[found].mFence;
852 mCore->clearBufferSlotLocked(found);
853 VALIDATE_CONSISTENCY();
854 listener = mCore->mConsumerListener;
Dan Stozad9822a32014-03-28 15:25:31 -0700855 }
856
Yi Kong48a619f2018-06-05 16:34:59 -0700857 if (listener != nullptr) {
Eino-Ville Talvala2672dec2017-06-13 16:39:11 -0700858 listener->onBuffersReleased();
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700859 }
Pablo Ceballos981066c2016-02-18 12:54:37 -0800860
Dan Stozad9822a32014-03-28 15:25:31 -0700861 return NO_ERROR;
862}
863
Dan Stoza9f3053d2014-03-06 15:14:33 -0800864status_t BufferQueueProducer::attachBuffer(int* outSlot,
865 const sp<android::GraphicBuffer>& buffer) {
866 ATRACE_CALL();
867
Yi Kong48a619f2018-06-05 16:34:59 -0700868 if (outSlot == nullptr) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700869 BQ_LOGE("attachBuffer: outSlot must not be NULL");
Dan Stoza9f3053d2014-03-06 15:14:33 -0800870 return BAD_VALUE;
Yi Kong48a619f2018-06-05 16:34:59 -0700871 } else if (buffer == nullptr) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700872 BQ_LOGE("attachBuffer: cannot attach NULL buffer");
Dan Stoza9f3053d2014-03-06 15:14:33 -0800873 return BAD_VALUE;
874 }
875
Jorim Jaggi6ae55032019-04-02 02:27:44 +0200876 std::unique_lock<std::mutex> lock(mCore->mMutex);
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700877
878 if (mCore->mIsAbandoned) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700879 BQ_LOGE("attachBuffer: BufferQueue has been abandoned");
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700880 return NO_INIT;
881 }
882
883 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700884 BQ_LOGE("attachBuffer: BufferQueue has no connected producer");
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700885 return NO_INIT;
886 }
Dan Stoza9f3053d2014-03-06 15:14:33 -0800887
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700888 if (mCore->mSharedBufferMode) {
889 BQ_LOGE("attachBuffer: cannot attach a buffer in shared buffer mode");
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700890 return BAD_VALUE;
891 }
892
Dan Stoza812ed062015-06-02 15:45:22 -0700893 if (buffer->getGenerationNumber() != mCore->mGenerationNumber) {
894 BQ_LOGE("attachBuffer: generation number mismatch [buffer %u] "
895 "[queue %u]", buffer->getGenerationNumber(),
896 mCore->mGenerationNumber);
897 return BAD_VALUE;
898 }
899
Jorim Jaggi6ae55032019-04-02 02:27:44 +0200900 mCore->waitWhileAllocatingLocked(lock);
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700901
Dan Stoza9f3053d2014-03-06 15:14:33 -0800902 status_t returnFlags = NO_ERROR;
903 int found;
Jorim Jaggi6ae55032019-04-02 02:27:44 +0200904 status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Attach, lock, &found);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800905 if (status != NO_ERROR) {
906 return status;
907 }
908
909 // This should not happen
910 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700911 BQ_LOGE("attachBuffer: no available buffer slots");
Dan Stoza9f3053d2014-03-06 15:14:33 -0800912 return -EBUSY;
913 }
914
915 *outSlot = found;
916 ATRACE_BUFFER_INDEX(*outSlot);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700917 BQ_LOGV("attachBuffer: returning slot %d flags=%#x",
Dan Stoza9f3053d2014-03-06 15:14:33 -0800918 *outSlot, returnFlags);
919
920 mSlots[*outSlot].mGraphicBuffer = buffer;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700921 mSlots[*outSlot].mBufferState.attachProducer();
Jim Shargo90842182024-11-14 00:49:27 +0000922#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
Dan Stoza9f3053d2014-03-06 15:14:33 -0800923 mSlots[*outSlot].mEglFence = EGL_NO_SYNC_KHR;
Jim Shargo90842182024-11-14 00:49:27 +0000924#endif
Dan Stoza9f3053d2014-03-06 15:14:33 -0800925 mSlots[*outSlot].mFence = Fence::NO_FENCE;
Dan Stoza2443c792014-03-24 15:03:46 -0700926 mSlots[*outSlot].mRequestBufferCalled = true;
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800927 mSlots[*outSlot].mAcquireCalled = false;
Jammy Yu69958b82017-02-22 16:41:38 -0800928 mSlots[*outSlot].mNeedsReallocation = false;
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800929 mCore->mActiveBuffers.insert(found);
Pablo Ceballos9e314332016-01-12 13:49:19 -0800930 VALIDATE_CONSISTENCY();
Dan Stoza0de7ea72015-04-23 13:20:51 -0700931
Dan Stoza9f3053d2014-03-06 15:14:33 -0800932 return returnFlags;
933}
934
Dan Stoza289ade12014-02-28 11:17:17 -0800935status_t BufferQueueProducer::queueBuffer(int slot,
936 const QueueBufferInput &input, QueueBufferOutput *output) {
937 ATRACE_CALL();
938 ATRACE_BUFFER_INDEX(slot);
939
Brian Andersond6927fb2016-07-23 23:37:30 -0700940 int64_t requestedPresentTimestamp;
Dan Stoza289ade12014-02-28 11:17:17 -0800941 bool isAutoTimestamp;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800942 android_dataspace dataSpace;
Pablo Ceballos60d69222015-08-07 14:47:20 -0700943 Rect crop(Rect::EMPTY_RECT);
Dan Stoza289ade12014-02-28 11:17:17 -0800944 int scalingMode;
945 uint32_t transform;
Ruben Brunk1681d952014-06-27 15:51:55 -0700946 uint32_t stickyTransform;
Brian Andersond6927fb2016-07-23 23:37:30 -0700947 sp<Fence> acquireFence;
Brian Anderson7c3ba8a2016-07-25 12:48:08 -0700948 bool getFrameTimestamps = false;
Brian Andersond6927fb2016-07-23 23:37:30 -0700949 input.deflate(&requestedPresentTimestamp, &isAutoTimestamp, &dataSpace,
Brian Anderson7c3ba8a2016-07-25 12:48:08 -0700950 &crop, &scalingMode, &transform, &acquireFence, &stickyTransform,
951 &getFrameTimestamps);
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700952 const Region& surfaceDamage = input.getSurfaceDamage();
Courtney Goeltzenleuchter9bad0d72017-12-19 12:34:34 -0700953 const HdrMetadata& hdrMetadata = input.getHdrMetadata();
Brian Lindahl628cff42024-10-30 11:50:28 -0600954 const std::optional<PictureProfileHandle>& pictureProfileHandle =
955 input.getPictureProfileHandle();
Dan Stoza289ade12014-02-28 11:17:17 -0800956
Yi Kong48a619f2018-06-05 16:34:59 -0700957 if (acquireFence == nullptr) {
Dan Stoza289ade12014-02-28 11:17:17 -0800958 BQ_LOGE("queueBuffer: fence is NULL");
Jesse Hallde288fe2014-11-04 08:30:48 -0800959 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800960 }
961
Brian Anderson3d4039d2016-09-23 16:31:30 -0700962 auto acquireFenceTime = std::make_shared<FenceTime>(acquireFence);
963
Dan Stoza289ade12014-02-28 11:17:17 -0800964 switch (scalingMode) {
965 case NATIVE_WINDOW_SCALING_MODE_FREEZE:
966 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
967 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
968 case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
969 break;
970 default:
971 BQ_LOGE("queueBuffer: unknown scaling mode %d", scalingMode);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800972 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800973 }
974
Dan Stoza8dc55392014-11-04 11:37:46 -0800975 sp<IConsumerListener> frameAvailableListener;
976 sp<IConsumerListener> frameReplacedListener;
977 int callbackTicket = 0;
Brian Andersond6927fb2016-07-23 23:37:30 -0700978 uint64_t currentFrameNumber = 0;
Dan Stoza8dc55392014-11-04 11:37:46 -0800979 BufferItem item;
John Reckd2c4a4a2024-02-07 10:31:09 -0500980 int connectedApi;
Mathias Agopianb96661f2024-09-17 11:45:38 -0700981 bool enableEglCpuThrottling = true;
John Reckd2c4a4a2024-02-07 10:31:09 -0500982 sp<Fence> lastQueuedFence;
983
Dan Stoza289ade12014-02-28 11:17:17 -0800984 { // Autolock scope
Jorim Jaggi6ae55032019-04-02 02:27:44 +0200985 std::lock_guard<std::mutex> lock(mCore->mMutex);
Dan Stoza289ade12014-02-28 11:17:17 -0800986
987 if (mCore->mIsAbandoned) {
988 BQ_LOGE("queueBuffer: BufferQueue has been abandoned");
989 return NO_INIT;
990 }
991
Pablo Ceballos583b1b32015-09-03 18:23:52 -0700992 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
993 BQ_LOGE("queueBuffer: BufferQueue has no connected producer");
994 return NO_INIT;
995 }
996
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800997 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
Dan Stoza289ade12014-02-28 11:17:17 -0800998 BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)",
Pablo Ceballos23b4abe2016-01-08 12:15:22 -0800999 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
Dan Stoza9f3053d2014-03-06 15:14:33 -08001000 return BAD_VALUE;
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001001 } else if (!mSlots[slot].mBufferState.isDequeued()) {
Dan Stoza289ade12014-02-28 11:17:17 -08001002 BQ_LOGE("queueBuffer: slot %d is not owned by the producer "
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001003 "(state = %s)", slot, mSlots[slot].mBufferState.string());
Dan Stoza9f3053d2014-03-06 15:14:33 -08001004 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -08001005 } else if (!mSlots[slot].mRequestBufferCalled) {
1006 BQ_LOGE("queueBuffer: slot %d was queued without requesting "
1007 "a buffer", slot);
Dan Stoza9f3053d2014-03-06 15:14:33 -08001008 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -08001009 }
1010
Pablo Ceballos3559fbf2016-03-17 15:50:23 -07001011 // If shared buffer mode has just been enabled, cache the slot of the
Pablo Ceballos295a9fc2016-03-14 16:02:19 -07001012 // first buffer that is queued and mark it as the shared buffer.
Pablo Ceballos3559fbf2016-03-17 15:50:23 -07001013 if (mCore->mSharedBufferMode && mCore->mSharedBufferSlot ==
Pablo Ceballos295a9fc2016-03-14 16:02:19 -07001014 BufferQueueCore::INVALID_BUFFER_SLOT) {
Pablo Ceballos3559fbf2016-03-17 15:50:23 -07001015 mCore->mSharedBufferSlot = slot;
Pablo Ceballos295a9fc2016-03-14 16:02:19 -07001016 mSlots[slot].mBufferState.mShared = true;
1017 }
1018
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -08001019 BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64 " dataSpace=%d"
Courtney Goeltzenleuchter9bad0d72017-12-19 12:34:34 -07001020 " validHdrMetadataTypes=0x%x crop=[%d,%d,%d,%d] transform=%#x scale=%s",
1021 slot, mCore->mFrameCounter + 1, requestedPresentTimestamp, dataSpace,
1022 hdrMetadata.validTypes, crop.left, crop.top, crop.right, crop.bottom,
Brian Andersond6927fb2016-07-23 23:37:30 -07001023 transform,
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001024 BufferItem::scalingModeName(static_cast<uint32_t>(scalingMode)));
Dan Stoza289ade12014-02-28 11:17:17 -08001025
1026 const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
1027 Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
Pablo Ceballos60d69222015-08-07 14:47:20 -07001028 Rect croppedRect(Rect::EMPTY_RECT);
Dan Stoza289ade12014-02-28 11:17:17 -08001029 crop.intersect(bufferRect, &croppedRect);
1030 if (croppedRect != crop) {
1031 BQ_LOGE("queueBuffer: crop rect is not contained within the "
1032 "buffer in slot %d", slot);
Dan Stoza9f3053d2014-03-06 15:14:33 -08001033 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -08001034 }
1035
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -08001036 // Override UNKNOWN dataspace with consumer default
1037 if (dataSpace == HAL_DATASPACE_UNKNOWN) {
1038 dataSpace = mCore->mDefaultBufferDataSpace;
1039 }
1040
Brian Andersond6927fb2016-07-23 23:37:30 -07001041 mSlots[slot].mFence = acquireFence;
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001042 mSlots[slot].mBufferState.queue();
1043
Brian Andersond6927fb2016-07-23 23:37:30 -07001044 // Increment the frame counter and store a local version of it
1045 // for use outside the lock on mCore->mMutex.
Dan Stoza289ade12014-02-28 11:17:17 -08001046 ++mCore->mFrameCounter;
Brian Andersond6927fb2016-07-23 23:37:30 -07001047 currentFrameNumber = mCore->mFrameCounter;
1048 mSlots[slot].mFrameNumber = currentFrameNumber;
Dan Stoza289ade12014-02-28 11:17:17 -08001049
Dan Stoza289ade12014-02-28 11:17:17 -08001050 item.mAcquireCalled = mSlots[slot].mAcquireCalled;
1051 item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
1052 item.mCrop = crop;
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001053 item.mTransform = transform &
1054 ~static_cast<uint32_t>(NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
Dan Stoza289ade12014-02-28 11:17:17 -08001055 item.mTransformToDisplayInverse =
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001056 (transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) != 0;
1057 item.mScalingMode = static_cast<uint32_t>(scalingMode);
Brian Andersond6927fb2016-07-23 23:37:30 -07001058 item.mTimestamp = requestedPresentTimestamp;
Dan Stoza289ade12014-02-28 11:17:17 -08001059 item.mIsAutoTimestamp = isAutoTimestamp;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -08001060 item.mDataSpace = dataSpace;
Courtney Goeltzenleuchter9bad0d72017-12-19 12:34:34 -07001061 item.mHdrMetadata = hdrMetadata;
Brian Lindahl628cff42024-10-30 11:50:28 -06001062 item.mPictureProfileHandle = pictureProfileHandle;
Brian Andersond6927fb2016-07-23 23:37:30 -07001063 item.mFrameNumber = currentFrameNumber;
Dan Stoza289ade12014-02-28 11:17:17 -08001064 item.mSlot = slot;
Brian Andersond6927fb2016-07-23 23:37:30 -07001065 item.mFence = acquireFence;
Brian Anderson3d4039d2016-09-23 16:31:30 -07001066 item.mFenceTime = acquireFenceTime;
Pablo Ceballos567dbbb2015-08-26 18:59:08 -07001067 item.mIsDroppable = mCore->mAsyncMode ||
Sungtak Lee45e9e0b2019-05-28 13:38:23 -07001068 (mConsumerIsSurfaceFlinger && mCore->mQueueBufferCanDrop) ||
Sungtak Lee3249fb62019-03-02 16:40:47 -08001069 (mCore->mLegacyBufferDrop && mCore->mQueueBufferCanDrop) ||
Pablo Ceballos3559fbf2016-03-17 15:50:23 -07001070 (mCore->mSharedBufferMode && mCore->mSharedBufferSlot == slot);
Dan Stoza5065a552015-03-17 16:23:42 -07001071 item.mSurfaceDamage = surfaceDamage;
Pablo Ceballos06312182015-10-07 16:32:12 -07001072 item.mQueuedBuffer = true;
Pablo Ceballos3559fbf2016-03-17 15:50:23 -07001073 item.mAutoRefresh = mCore->mSharedBufferMode && mCore->mAutoRefresh;
Chia-I Wu5c6e4632018-01-11 08:54:38 -08001074 item.mApi = mCore->mConnectedApi;
Dan Stoza289ade12014-02-28 11:17:17 -08001075
Ruben Brunk1681d952014-06-27 15:51:55 -07001076 mStickyTransform = stickyTransform;
1077
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001078 // Cache the shared buffer data so that the BufferItem can be recreated.
Pablo Ceballos3559fbf2016-03-17 15:50:23 -07001079 if (mCore->mSharedBufferMode) {
1080 mCore->mSharedBufferCache.crop = crop;
1081 mCore->mSharedBufferCache.transform = transform;
1082 mCore->mSharedBufferCache.scalingMode = static_cast<uint32_t>(
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001083 scalingMode);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -07001084 mCore->mSharedBufferCache.dataspace = dataSpace;
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001085 }
1086
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001087 output->bufferReplaced = false;
Dan Stoza289ade12014-02-28 11:17:17 -08001088 if (mCore->mQueue.empty()) {
1089 // When the queue is empty, we can ignore mDequeueBufferCannotBlock
1090 // and simply queue this buffer
1091 mCore->mQueue.push_back(item);
Dan Stoza8dc55392014-11-04 11:37:46 -08001092 frameAvailableListener = mCore->mConsumerListener;
Dan Stoza289ade12014-02-28 11:17:17 -08001093 } else {
Pablo Ceballos4d85da42016-04-19 20:11:56 -07001094 // When the queue is not empty, we need to look at the last buffer
1095 // in the queue to see if we need to replace it
1096 const BufferItem& last = mCore->mQueue.itemAt(
1097 mCore->mQueue.size() - 1);
1098 if (last.mIsDroppable) {
Pablo Ceballos23b4abe2016-01-08 12:15:22 -08001099
Pablo Ceballos4d85da42016-04-19 20:11:56 -07001100 if (!last.mIsStale) {
1101 mSlots[last.mSlot].mBufferState.freeQueued();
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001102
Pablo Ceballos3559fbf2016-03-17 15:50:23 -07001103 // After leaving shared buffer mode, the shared buffer will
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001104 // still be around. Mark it as no longer shared if this
1105 // operation causes it to be free.
Pablo Ceballos3559fbf2016-03-17 15:50:23 -07001106 if (!mCore->mSharedBufferMode &&
Pablo Ceballos4d85da42016-04-19 20:11:56 -07001107 mSlots[last.mSlot].mBufferState.isFree()) {
1108 mSlots[last.mSlot].mBufferState.mShared = false;
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001109 }
1110 // Don't put the shared buffer on the free list.
Pablo Ceballos4d85da42016-04-19 20:11:56 -07001111 if (!mSlots[last.mSlot].mBufferState.isShared()) {
1112 mCore->mActiveBuffers.erase(last.mSlot);
1113 mCore->mFreeBuffers.push_back(last.mSlot);
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001114 output->bufferReplaced = true;
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001115 }
Dan Stoza289ade12014-02-28 11:17:17 -08001116 }
Pablo Ceballos23b4abe2016-01-08 12:15:22 -08001117
Steven Thomas862e7532019-07-10 19:21:03 -07001118 // Make sure to merge the damage rect from the frame we're about
1119 // to drop into the new frame's damage rect.
1120 if (last.mSurfaceDamage.bounds() == Rect::INVALID_RECT ||
1121 item.mSurfaceDamage.bounds() == Rect::INVALID_RECT) {
1122 item.mSurfaceDamage = Region::INVALID_REGION;
1123 } else {
1124 item.mSurfaceDamage |= last.mSurfaceDamage;
1125 }
1126
Dan Stoza289ade12014-02-28 11:17:17 -08001127 // Overwrite the droppable buffer with the incoming one
Pablo Ceballos4d85da42016-04-19 20:11:56 -07001128 mCore->mQueue.editItemAt(mCore->mQueue.size() - 1) = item;
Dan Stoza8dc55392014-11-04 11:37:46 -08001129 frameReplacedListener = mCore->mConsumerListener;
Dan Stoza289ade12014-02-28 11:17:17 -08001130 } else {
1131 mCore->mQueue.push_back(item);
Dan Stoza8dc55392014-11-04 11:37:46 -08001132 frameAvailableListener = mCore->mConsumerListener;
Dan Stoza289ade12014-02-28 11:17:17 -08001133 }
1134 }
1135
1136 mCore->mBufferHasBeenQueued = true;
Patrick Williams078d7362024-08-27 10:20:39 -05001137#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
1138 mCore->notifyBufferReleased();
1139#else
Jorim Jaggi6ae55032019-04-02 02:27:44 +02001140 mCore->mDequeueCondition.notify_all();
Patrick Williams078d7362024-08-27 10:20:39 -05001141#endif
Dan Stoza50101d02016-04-07 16:53:23 -07001142 mCore->mLastQueuedSlot = slot;
Dan Stoza289ade12014-02-28 11:17:17 -08001143
Brian Anderson7c3ba8a2016-07-25 12:48:08 -07001144 output->width = mCore->mDefaultWidth;
1145 output->height = mCore->mDefaultHeight;
Yiwei Zhang538cedc2019-06-24 19:35:03 -07001146 output->transformHint = mCore->mTransformHintInUse = mCore->mTransformHint;
Brian Anderson7c3ba8a2016-07-25 12:48:08 -07001147 output->numPendingBuffers = static_cast<uint32_t>(mCore->mQueue.size());
1148 output->nextFrameNumber = mCore->mFrameCounter + 1;
Dan Stoza289ade12014-02-28 11:17:17 -08001149
Tomasz Wasilczykf2add402023-08-11 00:06:51 +00001150 ATRACE_INT(mCore->mConsumerName.c_str(), static_cast<int32_t>(mCore->mQueue.size()));
Chong Zhang62493092020-01-15 16:04:47 -08001151#ifndef NO_BINDER
Dan Stozae77c7662016-05-13 11:37:28 -07001152 mCore->mOccupancyTracker.registerOccupancyChange(mCore->mQueue.size());
Chong Zhang62493092020-01-15 16:04:47 -08001153#endif
Dan Stoza8dc55392014-11-04 11:37:46 -08001154 // Take a ticket for the callback functions
1155 callbackTicket = mNextCallbackTicket++;
Dan Stoza0de7ea72015-04-23 13:20:51 -07001156
Pablo Ceballos9e314332016-01-12 13:49:19 -08001157 VALIDATE_CONSISTENCY();
John Reckd2c4a4a2024-02-07 10:31:09 -05001158
1159 connectedApi = mCore->mConnectedApi;
Mathias Agopianb96661f2024-09-17 11:45:38 -07001160 if (flags::bq_producer_throttles_only_async_mode()) {
1161 enableEglCpuThrottling = mCore->mAsyncMode || mCore->mDequeueBufferCannotBlock;
1162 }
John Reckd2c4a4a2024-02-07 10:31:09 -05001163 lastQueuedFence = std::move(mLastQueueBufferFence);
1164
1165 mLastQueueBufferFence = std::move(acquireFence);
1166 mLastQueuedCrop = item.mCrop;
1167 mLastQueuedTransform = item.mTransform;
Dan Stoza289ade12014-02-28 11:17:17 -08001168 } // Autolock scope
1169
Irvel468051e2016-06-13 16:44:44 -07001170 // It is okay not to clear the GraphicBuffer when the consumer is SurfaceFlinger because
1171 // it is guaranteed that the BufferQueue is inside SurfaceFlinger's process and
1172 // there will be no Binder call
1173 if (!mConsumerIsSurfaceFlinger) {
1174 item.mGraphicBuffer.clear();
1175 }
1176
JihCheng Chiu544c5222019-04-02 20:50:58 +08001177 // Update and get FrameEventHistory.
1178 nsecs_t postedTime = systemTime(SYSTEM_TIME_MONOTONIC);
1179 NewFrameEventsEntry newFrameEventsEntry = {
1180 currentFrameNumber,
1181 postedTime,
1182 requestedPresentTimestamp,
1183 std::move(acquireFenceTime)
1184 };
1185 addAndGetFrameTimestamps(&newFrameEventsEntry,
1186 getFrameTimestamps ? &output->frameTimestamps : nullptr);
1187
Dan Stoza8dc55392014-11-04 11:37:46 -08001188 // Call back without the main BufferQueue lock held, but with the callback
1189 // lock held so we can ensure that callbacks occur in order
Mathias Agopian4f6ce7c2017-04-03 17:14:31 -07001190
Mathias Agopian4f6ce7c2017-04-03 17:14:31 -07001191 { // scope for the lock
Jorim Jaggi6ae55032019-04-02 02:27:44 +02001192 std::unique_lock<std::mutex> lock(mCallbackMutex);
Dan Stoza8dc55392014-11-04 11:37:46 -08001193 while (callbackTicket != mCurrentCallbackTicket) {
Jorim Jaggi6ae55032019-04-02 02:27:44 +02001194 mCallbackCondition.wait(lock);
Dan Stoza8dc55392014-11-04 11:37:46 -08001195 }
1196
Yi Kong48a619f2018-06-05 16:34:59 -07001197 if (frameAvailableListener != nullptr) {
Dan Stoza8dc55392014-11-04 11:37:46 -08001198 frameAvailableListener->onFrameAvailable(item);
Yi Kong48a619f2018-06-05 16:34:59 -07001199 } else if (frameReplacedListener != nullptr) {
Dan Stoza8dc55392014-11-04 11:37:46 -08001200 frameReplacedListener->onFrameReplaced(item);
1201 }
1202
1203 ++mCurrentCallbackTicket;
Jorim Jaggi6ae55032019-04-02 02:27:44 +02001204 mCallbackCondition.notify_all();
Dan Stoza289ade12014-02-28 11:17:17 -08001205 }
1206
Yiwei Zhangcb7dd002019-04-16 11:03:01 -07001207 // Wait without lock held
Mathias Agopianb96661f2024-09-17 11:45:38 -07001208 if (connectedApi == NATIVE_WINDOW_API_EGL && enableEglCpuThrottling) {
Yiwei Zhangcb7dd002019-04-16 11:03:01 -07001209 // Waiting here allows for two full buffers to be queued but not a
1210 // third. In the event that frames take varying time, this makes a
1211 // small trade-off in favor of latency rather than throughput.
1212 lastQueuedFence->waitForever("Throttling EGL Production");
1213 }
1214
Dan Stoza289ade12014-02-28 11:17:17 -08001215 return NO_ERROR;
1216}
1217
Pablo Ceballos583b1b32015-09-03 18:23:52 -07001218status_t BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
Dan Stoza289ade12014-02-28 11:17:17 -08001219 ATRACE_CALL();
1220 BQ_LOGV("cancelBuffer: slot %d", slot);
Dan Stoza289ade12014-02-28 11:17:17 -08001221
Shuzhen Wang266f31a2023-07-24 22:45:44 +00001222 sp<IConsumerListener> listener;
1223 bool callOnFrameCancelled = false;
1224 uint64_t bufferId = 0; // Only used if callOnFrameCancelled == true
1225 {
1226 std::lock_guard<std::mutex> lock(mCore->mMutex);
1227
1228 if (mCore->mIsAbandoned) {
1229 BQ_LOGE("cancelBuffer: BufferQueue has been abandoned");
1230 return NO_INIT;
1231 }
1232
1233 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
1234 BQ_LOGE("cancelBuffer: BufferQueue has no connected producer");
1235 return NO_INIT;
1236 }
1237
1238 if (mCore->mSharedBufferMode) {
1239 BQ_LOGE("cancelBuffer: cannot cancel a buffer in shared buffer mode");
1240 return BAD_VALUE;
1241 }
1242
1243 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
1244 BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)", slot,
1245 BufferQueueDefs::NUM_BUFFER_SLOTS);
1246 return BAD_VALUE;
1247 } else if (!mSlots[slot].mBufferState.isDequeued()) {
1248 BQ_LOGE("cancelBuffer: slot %d is not owned by the producer "
1249 "(state = %s)",
1250 slot, mSlots[slot].mBufferState.string());
1251 return BAD_VALUE;
1252 } else if (fence == nullptr) {
1253 BQ_LOGE("cancelBuffer: fence is NULL");
1254 return BAD_VALUE;
1255 }
1256
1257 mSlots[slot].mBufferState.cancel();
1258
1259 // After leaving shared buffer mode, the shared buffer will still be around.
1260 // Mark it as no longer shared if this operation causes it to be free.
1261 if (!mCore->mSharedBufferMode && mSlots[slot].mBufferState.isFree()) {
1262 mSlots[slot].mBufferState.mShared = false;
1263 }
1264
1265 // Don't put the shared buffer on the free list.
1266 if (!mSlots[slot].mBufferState.isShared()) {
1267 mCore->mActiveBuffers.erase(slot);
1268 mCore->mFreeBuffers.push_back(slot);
1269 }
1270
1271 auto gb = mSlots[slot].mGraphicBuffer;
1272 if (gb != nullptr) {
1273 callOnFrameCancelled = true;
1274 bufferId = gb->getId();
1275 }
1276 mSlots[slot].mFence = fence;
Patrick Williams078d7362024-08-27 10:20:39 -05001277#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
1278 mCore->notifyBufferReleased();
1279#else
Shuzhen Wang266f31a2023-07-24 22:45:44 +00001280 mCore->mDequeueCondition.notify_all();
Patrick Williams078d7362024-08-27 10:20:39 -05001281#endif
Shuzhen Wang266f31a2023-07-24 22:45:44 +00001282 listener = mCore->mConsumerListener;
1283 VALIDATE_CONSISTENCY();
Pablo Ceballos583b1b32015-09-03 18:23:52 -07001284 }
1285
Shuzhen Wang266f31a2023-07-24 22:45:44 +00001286 if (listener != nullptr && callOnFrameCancelled) {
1287 listener->onFrameCancelled(bufferId);
Dan Stoza289ade12014-02-28 11:17:17 -08001288 }
1289
Pablo Ceballos583b1b32015-09-03 18:23:52 -07001290 return NO_ERROR;
Dan Stoza289ade12014-02-28 11:17:17 -08001291}
1292
1293int BufferQueueProducer::query(int what, int *outValue) {
1294 ATRACE_CALL();
Jorim Jaggi6ae55032019-04-02 02:27:44 +02001295 std::lock_guard<std::mutex> lock(mCore->mMutex);
Dan Stoza289ade12014-02-28 11:17:17 -08001296
Yi Kong48a619f2018-06-05 16:34:59 -07001297 if (outValue == nullptr) {
Dan Stoza289ade12014-02-28 11:17:17 -08001298 BQ_LOGE("query: outValue was NULL");
1299 return BAD_VALUE;
1300 }
1301
1302 if (mCore->mIsAbandoned) {
1303 BQ_LOGE("query: BufferQueue has been abandoned");
1304 return NO_INIT;
1305 }
1306
1307 int value;
1308 switch (what) {
1309 case NATIVE_WINDOW_WIDTH:
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001310 value = static_cast<int32_t>(mCore->mDefaultWidth);
Dan Stoza289ade12014-02-28 11:17:17 -08001311 break;
1312 case NATIVE_WINDOW_HEIGHT:
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001313 value = static_cast<int32_t>(mCore->mDefaultHeight);
Dan Stoza289ade12014-02-28 11:17:17 -08001314 break;
1315 case NATIVE_WINDOW_FORMAT:
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001316 value = static_cast<int32_t>(mCore->mDefaultBufferFormat);
Dan Stoza289ade12014-02-28 11:17:17 -08001317 break;
Craig Donner6ebc46a2016-10-21 15:23:44 -07001318 case NATIVE_WINDOW_LAYER_COUNT:
1319 // All BufferQueue buffers have a single layer.
1320 value = BQ_LAYER_COUNT;
1321 break;
Dan Stoza289ade12014-02-28 11:17:17 -08001322 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
Pablo Ceballos567dbbb2015-08-26 18:59:08 -07001323 value = mCore->getMinUndequeuedBufferCountLocked();
Dan Stoza289ade12014-02-28 11:17:17 -08001324 break;
Ruben Brunk1681d952014-06-27 15:51:55 -07001325 case NATIVE_WINDOW_STICKY_TRANSFORM:
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001326 value = static_cast<int32_t>(mStickyTransform);
Ruben Brunk1681d952014-06-27 15:51:55 -07001327 break;
Dan Stoza289ade12014-02-28 11:17:17 -08001328 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
1329 value = (mCore->mQueue.size() > 1);
1330 break;
1331 case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
Chia-I Wue2786ea2017-08-07 10:36:08 -07001332 // deprecated; higher 32 bits are truncated
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001333 value = static_cast<int32_t>(mCore->mConsumerUsageBits);
Dan Stoza289ade12014-02-28 11:17:17 -08001334 break;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -08001335 case NATIVE_WINDOW_DEFAULT_DATASPACE:
1336 value = static_cast<int32_t>(mCore->mDefaultBufferDataSpace);
1337 break;
Dan Stoza4afd8b62015-02-25 16:49:08 -08001338 case NATIVE_WINDOW_BUFFER_AGE:
1339 if (mCore->mBufferAge > INT32_MAX) {
1340 value = 0;
1341 } else {
1342 value = static_cast<int32_t>(mCore->mBufferAge);
1343 }
1344 break;
Jiwen 'Steve' Cai20419132017-04-21 18:49:53 -07001345 case NATIVE_WINDOW_CONSUMER_IS_PROTECTED:
1346 value = static_cast<int32_t>(mCore->mConsumerIsProtected);
1347 break;
Dan Stoza289ade12014-02-28 11:17:17 -08001348 default:
1349 return BAD_VALUE;
1350 }
1351
1352 BQ_LOGV("query: %d? %d", what, value);
1353 *outValue = value;
1354 return NO_ERROR;
1355}
1356
Dan Stozaf0eaf252014-03-21 13:05:51 -07001357status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
Dan Stoza289ade12014-02-28 11:17:17 -08001358 int api, bool producerControlledByApp, QueueBufferOutput *output) {
1359 ATRACE_CALL();
Jorim Jaggi6ae55032019-04-02 02:27:44 +02001360 std::lock_guard<std::mutex> lock(mCore->mMutex);
Pablo Ceballos981066c2016-02-18 12:54:37 -08001361 mConsumerName = mCore->mConsumerName;
1362 BQ_LOGV("connect: api=%d producerControlledByApp=%s", api,
1363 producerControlledByApp ? "true" : "false");
1364
1365 if (mCore->mIsAbandoned) {
1366 BQ_LOGE("connect: BufferQueue has been abandoned");
1367 return NO_INIT;
1368 }
1369
Yi Kong48a619f2018-06-05 16:34:59 -07001370 if (mCore->mConsumerListener == nullptr) {
Pablo Ceballos981066c2016-02-18 12:54:37 -08001371 BQ_LOGE("connect: BufferQueue has no consumer");
1372 return NO_INIT;
1373 }
1374
Yi Kong48a619f2018-06-05 16:34:59 -07001375 if (output == nullptr) {
Pablo Ceballos981066c2016-02-18 12:54:37 -08001376 BQ_LOGE("connect: output was NULL");
1377 return BAD_VALUE;
1378 }
1379
1380 if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
1381 BQ_LOGE("connect: already connected (cur=%d req=%d)",
1382 mCore->mConnectedApi, api);
1383 return BAD_VALUE;
1384 }
1385
1386 int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode,
1387 mDequeueTimeout < 0 ?
1388 mCore->mConsumerControlledByApp && producerControlledByApp : false,
1389 mCore->mMaxBufferCount) -
1390 mCore->getMaxBufferCountLocked();
1391 if (!mCore->adjustAvailableSlotsLocked(delta)) {
1392 BQ_LOGE("connect: BufferQueue failed to adjust the number of available "
1393 "slots. Delta = %d", delta);
1394 return BAD_VALUE;
1395 }
1396
Dan Stoza289ade12014-02-28 11:17:17 -08001397 int status = NO_ERROR;
Pablo Ceballos981066c2016-02-18 12:54:37 -08001398 switch (api) {
1399 case NATIVE_WINDOW_API_EGL:
1400 case NATIVE_WINDOW_API_CPU:
1401 case NATIVE_WINDOW_API_MEDIA:
1402 case NATIVE_WINDOW_API_CAMERA:
1403 mCore->mConnectedApi = api;
Brian Anderson7c3ba8a2016-07-25 12:48:08 -07001404
1405 output->width = mCore->mDefaultWidth;
1406 output->height = mCore->mDefaultHeight;
Yiwei Zhang538cedc2019-06-24 19:35:03 -07001407 output->transformHint = mCore->mTransformHintInUse = mCore->mTransformHint;
Brian Anderson7c3ba8a2016-07-25 12:48:08 -07001408 output->numPendingBuffers =
1409 static_cast<uint32_t>(mCore->mQueue.size());
1410 output->nextFrameNumber = mCore->mFrameCounter + 1;
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001411 output->bufferReplaced = false;
silence_dogoode9d092a2019-06-19 16:14:53 -07001412 output->maxBufferCount = mCore->mMaxBufferCount;
Dan Stoza289ade12014-02-28 11:17:17 -08001413
Yi Kong48a619f2018-06-05 16:34:59 -07001414 if (listener != nullptr) {
Matthew Bouyack3b8e6b22016-10-03 16:24:26 -07001415 // Set up a death notification so that we can disconnect
1416 // automatically if the remote producer dies
Chong Zhang62493092020-01-15 16:04:47 -08001417#ifndef NO_BINDER
Yi Kong48a619f2018-06-05 16:34:59 -07001418 if (IInterface::asBinder(listener)->remoteBinder() != nullptr) {
Matthew Bouyack3b8e6b22016-10-03 16:24:26 -07001419 status = IInterface::asBinder(listener)->linkToDeath(
1420 static_cast<IBinder::DeathRecipient*>(this));
1421 if (status != NO_ERROR) {
1422 BQ_LOGE("connect: linkToDeath failed: %s (%d)",
1423 strerror(-status), status);
1424 }
1425 mCore->mLinkedToDeath = listener;
1426 }
Chong Zhang62493092020-01-15 16:04:47 -08001427#endif
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001428 mCore->mConnectedProducerListener = listener;
1429 mCore->mBufferReleasedCbEnabled = listener->needsReleaseNotify();
Sungtak Leecd217472024-07-19 17:17:40 +00001430#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_CONSUMER_ATTACH_CALLBACK)
1431 mCore->mBufferAttachedCbEnabled = listener->needsAttachNotify();
1432#endif
Pablo Ceballos981066c2016-02-18 12:54:37 -08001433 }
Pablo Ceballos981066c2016-02-18 12:54:37 -08001434 break;
1435 default:
1436 BQ_LOGE("connect: unknown API %d", api);
1437 status = BAD_VALUE;
1438 break;
Dan Stoza289ade12014-02-28 11:17:17 -08001439 }
Jayant Chowdharyad9fe272019-03-07 22:36:06 -08001440 mCore->mConnectedPid = BufferQueueThreadState::getCallingPid();
Pablo Ceballos981066c2016-02-18 12:54:37 -08001441 mCore->mBufferHasBeenQueued = false;
1442 mCore->mDequeueBufferCannotBlock = false;
Sungtak Lee3249fb62019-03-02 16:40:47 -08001443 mCore->mQueueBufferCanDrop = false;
1444 mCore->mLegacyBufferDrop = true;
1445 if (mCore->mConsumerControlledByApp && producerControlledByApp) {
1446 mCore->mDequeueBufferCannotBlock = mDequeueTimeout < 0;
1447 mCore->mQueueBufferCanDrop = mDequeueTimeout <= 0;
Dan Stoza127fc632015-06-30 13:43:32 -07001448 }
Dan Stoza289ade12014-02-28 11:17:17 -08001449
Pablo Ceballos981066c2016-02-18 12:54:37 -08001450 mCore->mAllowAllocation = true;
John Reckdb164ff2024-04-03 16:59:28 -04001451#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
1452 mCore->mAdditionalOptions.clear();
1453#endif
Pablo Ceballos981066c2016-02-18 12:54:37 -08001454 VALIDATE_CONSISTENCY();
Dan Stoza289ade12014-02-28 11:17:17 -08001455 return status;
1456}
1457
Robert Carr97b9c862016-09-08 13:54:35 -07001458status_t BufferQueueProducer::disconnect(int api, DisconnectMode mode) {
Dan Stoza289ade12014-02-28 11:17:17 -08001459 ATRACE_CALL();
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001460 BQ_LOGV("disconnect: api %d", api);
Dan Stoza289ade12014-02-28 11:17:17 -08001461
1462 int status = NO_ERROR;
1463 sp<IConsumerListener> listener;
1464 { // Autolock scope
Jorim Jaggi6ae55032019-04-02 02:27:44 +02001465 std::unique_lock<std::mutex> lock(mCore->mMutex);
Robert Carr97b9c862016-09-08 13:54:35 -07001466
1467 if (mode == DisconnectMode::AllLocal) {
Jayant Chowdharyad9fe272019-03-07 22:36:06 -08001468 if (BufferQueueThreadState::getCallingPid() != mCore->mConnectedPid) {
Robert Carr97b9c862016-09-08 13:54:35 -07001469 return NO_ERROR;
1470 }
1471 api = BufferQueueCore::CURRENTLY_CONNECTED_API;
1472 }
1473
Jorim Jaggi6ae55032019-04-02 02:27:44 +02001474 mCore->waitWhileAllocatingLocked(lock);
Dan Stoza289ade12014-02-28 11:17:17 -08001475
1476 if (mCore->mIsAbandoned) {
1477 // It's not really an error to disconnect after the surface has
1478 // been abandoned; it should just be a no-op.
1479 return NO_ERROR;
1480 }
1481
Chong Zhang1b3a9ac2016-02-29 16:47:47 -08001482 if (api == BufferQueueCore::CURRENTLY_CONNECTED_API) {
Chong Zhang5ac51482017-02-16 15:52:33 -08001483 if (mCore->mConnectedApi == NATIVE_WINDOW_API_MEDIA) {
1484 ALOGD("About to force-disconnect API_MEDIA, mode=%d", mode);
1485 }
Chong Zhang1b3a9ac2016-02-29 16:47:47 -08001486 api = mCore->mConnectedApi;
Chong Zhang26bb2b12016-03-08 12:08:33 -08001487 // If we're asked to disconnect the currently connected api but
1488 // nobody is connected, it's not really an error.
1489 if (api == BufferQueueCore::NO_CONNECTED_API) {
1490 return NO_ERROR;
1491 }
Chong Zhang1b3a9ac2016-02-29 16:47:47 -08001492 }
1493
Dan Stoza289ade12014-02-28 11:17:17 -08001494 switch (api) {
1495 case NATIVE_WINDOW_API_EGL:
1496 case NATIVE_WINDOW_API_CPU:
1497 case NATIVE_WINDOW_API_MEDIA:
1498 case NATIVE_WINDOW_API_CAMERA:
1499 if (mCore->mConnectedApi == api) {
1500 mCore->freeAllBuffersLocked();
1501
Chong Zhang62493092020-01-15 16:04:47 -08001502#ifndef NO_BINDER
Dan Stoza289ade12014-02-28 11:17:17 -08001503 // Remove our death notification callback if we have one
Yi Kong48a619f2018-06-05 16:34:59 -07001504 if (mCore->mLinkedToDeath != nullptr) {
Dan Stozaf0eaf252014-03-21 13:05:51 -07001505 sp<IBinder> token =
Matthew Bouyack3b8e6b22016-10-03 16:24:26 -07001506 IInterface::asBinder(mCore->mLinkedToDeath);
Dan Stoza289ade12014-02-28 11:17:17 -08001507 // This can fail if we're here because of the death
1508 // notification, but we just ignore it
1509 token->unlinkToDeath(
1510 static_cast<IBinder::DeathRecipient*>(this));
1511 }
Chong Zhang62493092020-01-15 16:04:47 -08001512#endif
Pablo Ceballos3559fbf2016-03-17 15:50:23 -07001513 mCore->mSharedBufferSlot =
Pablo Ceballos23b4abe2016-01-08 12:15:22 -08001514 BufferQueueCore::INVALID_BUFFER_SLOT;
Yi Kong48a619f2018-06-05 16:34:59 -07001515 mCore->mLinkedToDeath = nullptr;
1516 mCore->mConnectedProducerListener = nullptr;
Dan Stoza289ade12014-02-28 11:17:17 -08001517 mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
Robert Carr97b9c862016-09-08 13:54:35 -07001518 mCore->mConnectedPid = -1;
Jesse Hall399184a2014-03-03 15:42:54 -08001519 mCore->mSidebandStream.clear();
Patrick Williams078d7362024-08-27 10:20:39 -05001520#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
1521 mCore->notifyBufferReleased();
1522#else
Jorim Jaggi6ae55032019-04-02 02:27:44 +02001523 mCore->mDequeueCondition.notify_all();
Patrick Williams078d7362024-08-27 10:20:39 -05001524#endif
Yiwei Zhang538cedc2019-06-24 19:35:03 -07001525 mCore->mAutoPrerotation = false;
John Reckdb164ff2024-04-03 16:59:28 -04001526#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
1527 mCore->mAdditionalOptions.clear();
1528#endif
Dan Stoza289ade12014-02-28 11:17:17 -08001529 listener = mCore->mConsumerListener;
Wonsik Kim3e198b22017-04-07 15:43:16 -07001530 } else if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
1531 BQ_LOGE("disconnect: not connected (req=%d)", api);
1532 status = NO_INIT;
1533 } else {
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001534 BQ_LOGE("disconnect: still connected to another API "
Dan Stoza289ade12014-02-28 11:17:17 -08001535 "(cur=%d req=%d)", mCore->mConnectedApi, api);
Dan Stoza9f3053d2014-03-06 15:14:33 -08001536 status = BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -08001537 }
1538 break;
1539 default:
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001540 BQ_LOGE("disconnect: unknown API %d", api);
Dan Stoza9f3053d2014-03-06 15:14:33 -08001541 status = BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -08001542 break;
1543 }
1544 } // Autolock scope
1545
1546 // Call back without lock held
Yi Kong48a619f2018-06-05 16:34:59 -07001547 if (listener != nullptr) {
Dan Stoza289ade12014-02-28 11:17:17 -08001548 listener->onBuffersReleased();
Brian Anderson5ea5e592016-12-01 16:54:33 -08001549 listener->onDisconnect();
Dan Stoza289ade12014-02-28 11:17:17 -08001550 }
1551
1552 return status;
1553}
1554
Jesse Hall399184a2014-03-03 15:42:54 -08001555status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) {
Wonsik Kimafe30812014-03-31 23:16:08 +09001556 sp<IConsumerListener> listener;
1557 { // Autolock scope
Jorim Jaggi6ae55032019-04-02 02:27:44 +02001558 std::lock_guard<std::mutex> _l(mCore->mMutex);
Wonsik Kimafe30812014-03-31 23:16:08 +09001559 mCore->mSidebandStream = stream;
1560 listener = mCore->mConsumerListener;
1561 } // Autolock scope
1562
Yi Kong48a619f2018-06-05 16:34:59 -07001563 if (listener != nullptr) {
Wonsik Kimafe30812014-03-31 23:16:08 +09001564 listener->onSidebandStreamChanged();
1565 }
Jesse Hall399184a2014-03-03 15:42:54 -08001566 return NO_ERROR;
1567}
1568
Pablo Ceballos567dbbb2015-08-26 18:59:08 -07001569void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height,
Mathias Agopiancb496ac2017-05-22 14:21:00 -07001570 PixelFormat format, uint64_t usage) {
Antoine Labour78014f32014-07-15 21:17:03 -07001571 ATRACE_CALL();
Yiwei Zhang538cedc2019-06-24 19:35:03 -07001572
1573 const bool useDefaultSize = !width && !height;
Antoine Labour78014f32014-07-15 21:17:03 -07001574 while (true) {
Antoine Labour78014f32014-07-15 21:17:03 -07001575 uint32_t allocWidth = 0;
1576 uint32_t allocHeight = 0;
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001577 PixelFormat allocFormat = PIXEL_FORMAT_UNKNOWN;
Mathias Agopiancb496ac2017-05-22 14:21:00 -07001578 uint64_t allocUsage = 0;
Chia-I Wu1dbf0e32018-02-07 14:40:08 -08001579 std::string allocName;
John Reckdb164ff2024-04-03 16:59:28 -04001580#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
1581 std::vector<gui::AdditionalOptions> allocOptions;
1582 uint32_t allocOptionsGenId = 0;
1583#endif
Antoine Labour78014f32014-07-15 21:17:03 -07001584 { // Autolock scope
Jorim Jaggi6ae55032019-04-02 02:27:44 +02001585 std::unique_lock<std::mutex> lock(mCore->mMutex);
1586 mCore->waitWhileAllocatingLocked(lock);
Dan Stoza29a3e902014-06-20 13:13:57 -07001587
Dan Stoza9de72932015-04-16 17:28:43 -07001588 if (!mCore->mAllowAllocation) {
1589 BQ_LOGE("allocateBuffers: allocation is not allowed for this "
1590 "BufferQueue");
1591 return;
1592 }
1593
Jorim Jaggi0a3e7842018-07-17 13:48:33 +02001594 // Only allocate one buffer at a time to reduce risks of overlapping an allocation from
1595 // both allocateBuffers and dequeueBuffer.
Shuangxi Xiang045a30e2024-10-14 09:38:32 +00001596 if (mCore->mFreeSlots.empty()) {
1597 BQ_LOGV("allocateBuffers: a slot was occupied while "
1598 "allocating. Dropping allocated buffer.");
Antoine Labour78014f32014-07-15 21:17:03 -07001599 return;
1600 }
Pablo Ceballos23b4abe2016-01-08 12:15:22 -08001601
Antoine Labour78014f32014-07-15 21:17:03 -07001602 allocWidth = width > 0 ? width : mCore->mDefaultWidth;
1603 allocHeight = height > 0 ? height : mCore->mDefaultHeight;
Yiwei Zhang538cedc2019-06-24 19:35:03 -07001604 if (useDefaultSize && mCore->mAutoPrerotation &&
1605 (mCore->mTransformHintInUse & NATIVE_WINDOW_TRANSFORM_ROT_90)) {
1606 std::swap(allocWidth, allocHeight);
1607 }
1608
Antoine Labour78014f32014-07-15 21:17:03 -07001609 allocFormat = format != 0 ? format : mCore->mDefaultBufferFormat;
1610 allocUsage = usage | mCore->mConsumerUsageBits;
Tomasz Wasilczykf2add402023-08-11 00:06:51 +00001611 allocName.assign(mCore->mConsumerName.c_str(), mCore->mConsumerName.size());
Antoine Labour78014f32014-07-15 21:17:03 -07001612
John Reckdb164ff2024-04-03 16:59:28 -04001613#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
1614 allocOptions = mCore->mAdditionalOptions;
1615 allocOptionsGenId = mCore->mAdditionalOptionsGenerationId;
1616#endif
1617
Antoine Labour78014f32014-07-15 21:17:03 -07001618 mCore->mIsAllocating = true;
John Reckdb164ff2024-04-03 16:59:28 -04001619
Antoine Labour78014f32014-07-15 21:17:03 -07001620 } // Autolock scope
1621
John Reckdb164ff2024-04-03 16:59:28 -04001622#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
1623 std::vector<GraphicBufferAllocator::AdditionalOptions> tempOptions;
1624 tempOptions.reserve(allocOptions.size());
1625 for (const auto& it : allocOptions) {
1626 tempOptions.emplace_back(it.name.c_str(), it.value);
1627 }
1628 const GraphicBufferAllocator::AllocationRequest allocRequest = {
1629 .importBuffer = true,
1630 .width = allocWidth,
1631 .height = allocHeight,
1632 .format = allocFormat,
1633 .layerCount = BQ_LAYER_COUNT,
1634 .usage = allocUsage,
1635 .requestorName = allocName,
1636 .extras = std::move(tempOptions),
1637 };
1638#endif
1639
John Reckdb164ff2024-04-03 16:59:28 -04001640#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
Shuangxi Xiang045a30e2024-10-14 09:38:32 +00001641 sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(allocRequest);
John Reckdb164ff2024-04-03 16:59:28 -04001642#else
Shuangxi Xiang045a30e2024-10-14 09:38:32 +00001643 sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
1644 allocWidth, allocHeight, allocFormat, BQ_LAYER_COUNT,
1645 allocUsage, allocName);
John Reckdb164ff2024-04-03 16:59:28 -04001646#endif
Mathias Agopian0556d792017-03-22 15:49:32 -07001647
Shuangxi Xiang045a30e2024-10-14 09:38:32 +00001648 status_t result = graphicBuffer->initCheck();
Mathias Agopian0556d792017-03-22 15:49:32 -07001649
Shuangxi Xiang045a30e2024-10-14 09:38:32 +00001650 if (result != NO_ERROR) {
1651 BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format"
1652 " %u, usage %#" PRIx64 ")", width, height, format, usage);
1653 std::lock_guard<std::mutex> lock(mCore->mMutex);
1654 mCore->mIsAllocating = false;
1655 mCore->mIsAllocatingCondition.notify_all();
1656 return;
Antoine Labour78014f32014-07-15 21:17:03 -07001657 }
1658
1659 { // Autolock scope
Jorim Jaggi6ae55032019-04-02 02:27:44 +02001660 std::unique_lock<std::mutex> lock(mCore->mMutex);
Antoine Labour78014f32014-07-15 21:17:03 -07001661 uint32_t checkWidth = width > 0 ? width : mCore->mDefaultWidth;
1662 uint32_t checkHeight = height > 0 ? height : mCore->mDefaultHeight;
Yiwei Zhang538cedc2019-06-24 19:35:03 -07001663 if (useDefaultSize && mCore->mAutoPrerotation &&
1664 (mCore->mTransformHintInUse & NATIVE_WINDOW_TRANSFORM_ROT_90)) {
1665 std::swap(checkWidth, checkHeight);
1666 }
1667
Dan Stoza3be1c6b2014-11-18 10:24:03 -08001668 PixelFormat checkFormat = format != 0 ?
1669 format : mCore->mDefaultBufferFormat;
Mathias Agopiancb496ac2017-05-22 14:21:00 -07001670 uint64_t checkUsage = usage | mCore->mConsumerUsageBits;
John Reckdb164ff2024-04-03 16:59:28 -04001671 bool allocOptionsChanged = false;
1672#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
1673 allocOptionsChanged = allocOptionsGenId != mCore->mAdditionalOptionsGenerationId;
1674#endif
Antoine Labour78014f32014-07-15 21:17:03 -07001675 if (checkWidth != allocWidth || checkHeight != allocHeight ||
John Reckdb164ff2024-04-03 16:59:28 -04001676 checkFormat != allocFormat || checkUsage != allocUsage || allocOptionsChanged) {
Antoine Labour78014f32014-07-15 21:17:03 -07001677 // Something changed while we released the lock. Retry.
1678 BQ_LOGV("allocateBuffers: size/format/usage changed while allocating. Retrying.");
1679 mCore->mIsAllocating = false;
Jorim Jaggi6ae55032019-04-02 02:27:44 +02001680 mCore->mIsAllocatingCondition.notify_all();
Dan Stoza29a3e902014-06-20 13:13:57 -07001681 continue;
1682 }
1683
Shuangxi Xiang045a30e2024-10-14 09:38:32 +00001684 if (mCore->mFreeSlots.empty()) {
1685 BQ_LOGV("allocateBuffers: a slot was occupied while "
1686 "allocating. Dropping allocated buffer.");
1687 } else {
Pablo Ceballos23b4abe2016-01-08 12:15:22 -08001688 auto slot = mCore->mFreeSlots.begin();
1689 mCore->clearBufferSlotLocked(*slot); // Clean up the slot first
Shuangxi Xiang045a30e2024-10-14 09:38:32 +00001690 mSlots[*slot].mGraphicBuffer = graphicBuffer;
Pablo Ceballos23b4abe2016-01-08 12:15:22 -08001691 mSlots[*slot].mFence = Fence::NO_FENCE;
John Reckdb164ff2024-04-03 16:59:28 -04001692#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
1693 mSlots[*slot].mAdditionalOptionsGenerationId = allocOptionsGenId;
1694#endif
Dan Stoza0de7ea72015-04-23 13:20:51 -07001695
1696 // freeBufferLocked puts this slot on the free slots list. Since
1697 // we then attached a buffer, move the slot to free buffer list.
Pablo Ceballos23b4abe2016-01-08 12:15:22 -08001698 mCore->mFreeBuffers.push_front(*slot);
Dan Stoza0de7ea72015-04-23 13:20:51 -07001699
Pablo Ceballos23b4abe2016-01-08 12:15:22 -08001700 BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d",
1701 *slot);
Christopher Ferris87e94cd2016-04-26 11:29:08 -07001702
1703 // Make sure the erase is done after all uses of the slot
1704 // iterator since it will be invalid after this point.
1705 mCore->mFreeSlots.erase(slot);
Antoine Labour78014f32014-07-15 21:17:03 -07001706 }
Dan Stoza29a3e902014-06-20 13:13:57 -07001707
Antoine Labour78014f32014-07-15 21:17:03 -07001708 mCore->mIsAllocating = false;
Jorim Jaggi6ae55032019-04-02 02:27:44 +02001709 mCore->mIsAllocatingCondition.notify_all();
Pablo Ceballos9e314332016-01-12 13:49:19 -08001710 VALIDATE_CONSISTENCY();
Jorim Jaggi35b4e382019-03-28 00:44:03 +01001711
1712 // If dequeue is waiting for to allocate a buffer, release the lock until it's not
1713 // waiting anymore so it can use the buffer we just allocated.
1714 while (mDequeueWaitingForAllocation) {
1715 mDequeueWaitingForAllocationCondition.wait(lock);
1716 }
Antoine Labour78014f32014-07-15 21:17:03 -07001717 } // Autolock scope
Dan Stoza29a3e902014-06-20 13:13:57 -07001718 }
1719}
1720
Dan Stoza9de72932015-04-16 17:28:43 -07001721status_t BufferQueueProducer::allowAllocation(bool allow) {
1722 ATRACE_CALL();
1723 BQ_LOGV("allowAllocation: %s", allow ? "true" : "false");
1724
Jorim Jaggi6ae55032019-04-02 02:27:44 +02001725 std::lock_guard<std::mutex> lock(mCore->mMutex);
Dan Stoza9de72932015-04-16 17:28:43 -07001726 mCore->mAllowAllocation = allow;
1727 return NO_ERROR;
1728}
1729
Dan Stoza812ed062015-06-02 15:45:22 -07001730status_t BufferQueueProducer::setGenerationNumber(uint32_t generationNumber) {
1731 ATRACE_CALL();
1732 BQ_LOGV("setGenerationNumber: %u", generationNumber);
1733
Jorim Jaggi6ae55032019-04-02 02:27:44 +02001734 std::lock_guard<std::mutex> lock(mCore->mMutex);
Dan Stoza812ed062015-06-02 15:45:22 -07001735 mCore->mGenerationNumber = generationNumber;
1736 return NO_ERROR;
1737}
1738
Dan Stozac6f30bd2015-06-08 09:32:50 -07001739String8 BufferQueueProducer::getConsumerName() const {
1740 ATRACE_CALL();
Jorim Jaggi6ae55032019-04-02 02:27:44 +02001741 std::lock_guard<std::mutex> lock(mCore->mMutex);
Tomasz Wasilczykf2add402023-08-11 00:06:51 +00001742 BQ_LOGV("getConsumerName: %s", mConsumerName.c_str());
Dan Stozac6f30bd2015-06-08 09:32:50 -07001743 return mConsumerName;
1744}
1745
Pablo Ceballos3559fbf2016-03-17 15:50:23 -07001746status_t BufferQueueProducer::setSharedBufferMode(bool sharedBufferMode) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001747 ATRACE_CALL();
Pablo Ceballos3559fbf2016-03-17 15:50:23 -07001748 BQ_LOGV("setSharedBufferMode: %d", sharedBufferMode);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001749
Jorim Jaggi6ae55032019-04-02 02:27:44 +02001750 std::lock_guard<std::mutex> lock(mCore->mMutex);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -07001751 if (!sharedBufferMode) {
1752 mCore->mSharedBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT;
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001753 }
Pablo Ceballos3559fbf2016-03-17 15:50:23 -07001754 mCore->mSharedBufferMode = sharedBufferMode;
Dan Stoza127fc632015-06-30 13:43:32 -07001755 return NO_ERROR;
1756}
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001757
Pablo Ceballosff95aab2016-01-13 17:09:58 -08001758status_t BufferQueueProducer::setAutoRefresh(bool autoRefresh) {
1759 ATRACE_CALL();
1760 BQ_LOGV("setAutoRefresh: %d", autoRefresh);
1761
Jorim Jaggi6ae55032019-04-02 02:27:44 +02001762 std::lock_guard<std::mutex> lock(mCore->mMutex);
Pablo Ceballosff95aab2016-01-13 17:09:58 -08001763
1764 mCore->mAutoRefresh = autoRefresh;
1765 return NO_ERROR;
1766}
1767
Dan Stoza127fc632015-06-30 13:43:32 -07001768status_t BufferQueueProducer::setDequeueTimeout(nsecs_t timeout) {
1769 ATRACE_CALL();
1770 BQ_LOGV("setDequeueTimeout: %" PRId64, timeout);
1771
Jorim Jaggi6ae55032019-04-02 02:27:44 +02001772 std::lock_guard<std::mutex> lock(mCore->mMutex);
Sungtak Lee42a94c62019-05-24 14:27:14 -07001773 bool dequeueBufferCannotBlock =
1774 timeout >= 0 ? false : mCore->mDequeueBufferCannotBlock;
1775 int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode, dequeueBufferCannotBlock,
Pablo Ceballos981066c2016-02-18 12:54:37 -08001776 mCore->mMaxBufferCount) - mCore->getMaxBufferCountLocked();
1777 if (!mCore->adjustAvailableSlotsLocked(delta)) {
1778 BQ_LOGE("setDequeueTimeout: BufferQueue failed to adjust the number of "
1779 "available slots. Delta = %d", delta);
1780 return BAD_VALUE;
Pablo Ceballos23b4abe2016-01-08 12:15:22 -08001781 }
1782
Pablo Ceballos981066c2016-02-18 12:54:37 -08001783 mDequeueTimeout = timeout;
Sungtak Lee42a94c62019-05-24 14:27:14 -07001784 mCore->mDequeueBufferCannotBlock = dequeueBufferCannotBlock;
1785 if (timeout > 0) {
1786 mCore->mQueueBufferCanDrop = false;
Sungtak Lee3249fb62019-03-02 16:40:47 -08001787 }
Pablo Ceballos9e314332016-01-12 13:49:19 -08001788
Pablo Ceballos981066c2016-02-18 12:54:37 -08001789 VALIDATE_CONSISTENCY();
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001790 return NO_ERROR;
1791}
1792
Sungtak Lee3249fb62019-03-02 16:40:47 -08001793status_t BufferQueueProducer::setLegacyBufferDrop(bool drop) {
1794 ATRACE_CALL();
1795 BQ_LOGV("setLegacyBufferDrop: drop = %d", drop);
1796
1797 std::lock_guard<std::mutex> lock(mCore->mMutex);
1798 mCore->mLegacyBufferDrop = drop;
1799 return NO_ERROR;
1800}
1801
Dan Stoza50101d02016-04-07 16:53:23 -07001802status_t BufferQueueProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
John Reck1a61da52016-04-28 13:18:15 -07001803 sp<Fence>* outFence, float outTransformMatrix[16]) {
Dan Stoza50101d02016-04-07 16:53:23 -07001804 ATRACE_CALL();
Dan Stoza50101d02016-04-07 16:53:23 -07001805
Jorim Jaggi6ae55032019-04-02 02:27:44 +02001806 std::lock_guard<std::mutex> lock(mCore->mMutex);
John Reckd2c4a4a2024-02-07 10:31:09 -05001807 BQ_LOGV("getLastQueuedBuffer, slot=%d", mCore->mLastQueuedSlot);
1808
Dan Stoza50101d02016-04-07 16:53:23 -07001809 if (mCore->mLastQueuedSlot == BufferItem::INVALID_BUFFER_SLOT) {
1810 *outBuffer = nullptr;
1811 *outFence = Fence::NO_FENCE;
1812 return NO_ERROR;
1813 }
1814
1815 *outBuffer = mSlots[mCore->mLastQueuedSlot].mGraphicBuffer;
1816 *outFence = mLastQueueBufferFence;
1817
John Reck1a61da52016-04-28 13:18:15 -07001818 // Currently only SurfaceFlinger internally ever changes
1819 // GLConsumer's filtering mode, so we just use 'true' here as
1820 // this is slightly specialized for the current client of this API,
1821 // which does want filtering.
1822 GLConsumer::computeTransformMatrix(outTransformMatrix,
1823 mSlots[mCore->mLastQueuedSlot].mGraphicBuffer, mLastQueuedCrop,
1824 mLastQueuedTransform, true /* filter */);
1825
Dan Stoza50101d02016-04-07 16:53:23 -07001826 return NO_ERROR;
1827}
1828
John Reckf0f13e82021-05-18 00:42:56 -04001829status_t BufferQueueProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence,
1830 Rect* outRect, uint32_t* outTransform) {
1831 ATRACE_CALL();
John Reckf0f13e82021-05-18 00:42:56 -04001832
1833 std::lock_guard<std::mutex> lock(mCore->mMutex);
John Reckd2c4a4a2024-02-07 10:31:09 -05001834 BQ_LOGV("getLastQueuedBuffer, slot=%d", mCore->mLastQueuedSlot);
1835 if (mCore->mLastQueuedSlot == BufferItem::INVALID_BUFFER_SLOT ||
1836 mSlots[mCore->mLastQueuedSlot].mBufferState.isDequeued()) {
John Reckf0f13e82021-05-18 00:42:56 -04001837 *outBuffer = nullptr;
1838 *outFence = Fence::NO_FENCE;
1839 return NO_ERROR;
1840 }
1841
1842 *outBuffer = mSlots[mCore->mLastQueuedSlot].mGraphicBuffer;
1843 *outFence = mLastQueueBufferFence;
1844 *outRect = mLastQueuedCrop;
1845 *outTransform = mLastQueuedTransform;
1846
1847 return NO_ERROR;
1848}
1849
Brian Anderson3890c392016-07-25 12:48:08 -07001850void BufferQueueProducer::getFrameTimestamps(FrameEventHistoryDelta* outDelta) {
1851 addAndGetFrameTimestamps(nullptr, outDelta);
Brian Andersond6927fb2016-07-23 23:37:30 -07001852}
Pablo Ceballosce796e72016-02-04 19:10:51 -08001853
Brian Anderson3890c392016-07-25 12:48:08 -07001854void BufferQueueProducer::addAndGetFrameTimestamps(
Brian Andersond6927fb2016-07-23 23:37:30 -07001855 const NewFrameEventsEntry* newTimestamps,
Brian Anderson3890c392016-07-25 12:48:08 -07001856 FrameEventHistoryDelta* outDelta) {
1857 if (newTimestamps == nullptr && outDelta == nullptr) {
1858 return;
Brian Andersond6927fb2016-07-23 23:37:30 -07001859 }
1860
1861 ATRACE_CALL();
1862 BQ_LOGV("addAndGetFrameTimestamps");
1863 sp<IConsumerListener> listener;
Pablo Ceballosce796e72016-02-04 19:10:51 -08001864 {
Jorim Jaggi6ae55032019-04-02 02:27:44 +02001865 std::lock_guard<std::mutex> lock(mCore->mMutex);
Pablo Ceballosce796e72016-02-04 19:10:51 -08001866 listener = mCore->mConsumerListener;
1867 }
Yi Kong48a619f2018-06-05 16:34:59 -07001868 if (listener != nullptr) {
Brian Anderson3890c392016-07-25 12:48:08 -07001869 listener->addAndGetFrameTimestamps(newTimestamps, outDelta);
Pablo Ceballosce796e72016-02-04 19:10:51 -08001870 }
Pablo Ceballosce796e72016-02-04 19:10:51 -08001871}
1872
Dan Stoza289ade12014-02-28 11:17:17 -08001873void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
1874 // If we're here, it means that a producer we were connected to died.
1875 // We're guaranteed that we are still connected to it because we remove
1876 // this callback upon disconnect. It's therefore safe to read mConnectedApi
1877 // without synchronization here.
1878 int api = mCore->mConnectedApi;
1879 disconnect(api);
1880}
1881
Pablo Ceballos8e3e92b2016-06-27 17:56:53 -07001882status_t BufferQueueProducer::getUniqueId(uint64_t* outId) const {
1883 BQ_LOGV("getUniqueId");
1884
1885 *outId = mCore->mUniqueId;
1886 return NO_ERROR;
1887}
1888
Chia-I Wue2786ea2017-08-07 10:36:08 -07001889status_t BufferQueueProducer::getConsumerUsage(uint64_t* outUsage) const {
1890 BQ_LOGV("getConsumerUsage");
1891
Jorim Jaggi6ae55032019-04-02 02:27:44 +02001892 std::lock_guard<std::mutex> lock(mCore->mMutex);
Chia-I Wue2786ea2017-08-07 10:36:08 -07001893 *outUsage = mCore->mConsumerUsageBits;
1894 return NO_ERROR;
1895}
1896
Yiwei Zhang538cedc2019-06-24 19:35:03 -07001897status_t BufferQueueProducer::setAutoPrerotation(bool autoPrerotation) {
1898 ATRACE_CALL();
1899 BQ_LOGV("setAutoPrerotation: %d", autoPrerotation);
1900
1901 std::lock_guard<std::mutex> lock(mCore->mMutex);
1902
1903 mCore->mAutoPrerotation = autoPrerotation;
1904 return NO_ERROR;
1905}
1906
Ady Abraham107788e2023-10-17 12:31:08 -07001907#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE)
Ady Abraham6cdd3fd2023-09-07 18:45:58 -07001908status_t BufferQueueProducer::setFrameRate(float frameRate, int8_t compatibility,
1909 int8_t changeFrameRateStrategy) {
1910 ATRACE_CALL();
1911 BQ_LOGV("setFrameRate: %.2f", frameRate);
1912
1913 if (!ValidateFrameRate(frameRate, compatibility, changeFrameRateStrategy,
1914 "BufferQueueProducer::setFrameRate")) {
1915 return BAD_VALUE;
1916 }
1917
1918 sp<IConsumerListener> listener;
1919 {
1920 std::lock_guard<std::mutex> lock(mCore->mMutex);
1921 listener = mCore->mConsumerListener;
1922 }
1923 if (listener != nullptr) {
1924 listener->onSetFrameRate(frameRate, compatibility, changeFrameRateStrategy);
1925 }
1926 return NO_ERROR;
1927}
1928#endif
1929
John Reckdb164ff2024-04-03 16:59:28 -04001930#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
1931status_t BufferQueueProducer::setAdditionalOptions(
1932 const std::vector<gui::AdditionalOptions>& options) {
1933 ATRACE_CALL();
1934 BQ_LOGV("setAdditionalOptions, size = %zu", options.size());
1935
1936 if (!GraphicBufferAllocator::get().supportsAdditionalOptions()) {
1937 return INVALID_OPERATION;
1938 }
1939
1940 std::lock_guard<std::mutex> lock(mCore->mMutex);
1941
1942 if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
1943 BQ_LOGE("setAdditionalOptions: BufferQueue not connected, cannot set additional options");
1944 return NO_INIT;
1945 }
1946
1947 if (mCore->mAdditionalOptions != options) {
1948 mCore->mAdditionalOptions = options;
1949 mCore->mAdditionalOptionsGenerationId++;
1950 }
1951 return NO_ERROR;
1952}
1953#endif
1954
Dan Stoza289ade12014-02-28 11:17:17 -08001955} // namespace android