blob: c65eafa5416aad03a3b3f8980729438b477454ca [file] [log] [blame]
Robert Carr78c25dd2019-08-15 14:10:33 -07001/*
2 * Copyright (C) 2019 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
Valerie Haud3b90d22019-11-06 09:37:31 -080017#undef LOG_TAG
18#define LOG_TAG "BLASTBufferQueue"
19
Valerie Haua32c5522019-12-09 10:11:08 -080020#define ATRACE_TAG ATRACE_TAG_GRAPHICS
Vishnu Naire1a42322020-10-02 17:42:04 -070021//#define LOG_NDEBUG 0
Valerie Haua32c5522019-12-09 10:11:08 -080022
Jim Shargod30823a2024-07-27 02:49:39 +000023#include <com_android_graphics_libgui_flags.h>
liulijuneb489f62022-10-17 22:02:14 +080024#include <cutils/atomic.h>
Patrick Williams7c9fa272024-08-30 12:38:43 +000025#include <ftl/fake_guard.h>
Robert Carr78c25dd2019-08-15 14:10:33 -070026#include <gui/BLASTBufferQueue.h>
27#include <gui/BufferItemConsumer.h>
Vishnu Nair89496122020-12-14 17:14:53 -080028#include <gui/BufferQueueConsumer.h>
29#include <gui/BufferQueueCore.h>
30#include <gui/BufferQueueProducer.h>
Patrick Williams7c9fa272024-08-30 12:38:43 +000031#include <sys/epoll.h>
32#include <sys/eventfd.h>
Ady Abraham107788e2023-10-17 12:31:08 -070033
Alec Mouri3118f962024-09-13 22:34:11 +000034#include <gui/FenceMonitor.h>
Ady Abraham6cdd3fd2023-09-07 18:45:58 -070035#include <gui/FrameRateUtils.h>
Valerie Hau45e4b3b2019-12-03 10:49:17 -080036#include <gui/GLConsumer.h>
Vishnu Nair89496122020-12-14 17:14:53 -080037#include <gui/IProducerListener.h>
Robert Carr05086b22020-10-13 18:22:51 -070038#include <gui/Surface.h>
chaviw57ae4b22022-02-03 16:51:39 -060039#include <gui/TraceUtils.h>
Vishnu Nair89496122020-12-14 17:14:53 -080040#include <utils/Singleton.h>
Valerie Haua32c5522019-12-09 10:11:08 -080041#include <utils/Trace.h>
42
Ady Abraham0bde6b52021-05-18 13:57:02 -070043#include <private/gui/ComposerService.h>
Huihong Luo02186fb2022-02-23 14:21:54 -080044#include <private/gui/ComposerServiceAIDL.h>
Ady Abraham0bde6b52021-05-18 13:57:02 -070045
Chavi Weingartene0237bb2023-02-06 21:48:32 +000046#include <android-base/thread_annotations.h>
Robert Carr78c25dd2019-08-15 14:10:33 -070047
Alec Mouri21d94322023-10-17 19:51:39 +000048#include <com_android_graphics_libgui_flags.h>
49
Ady Abraham6cdd3fd2023-09-07 18:45:58 -070050using namespace com::android::graphics::libgui;
Robert Carr78c25dd2019-08-15 14:10:33 -070051using namespace std::chrono_literals;
52
Vishnu Nairdab94092020-09-29 16:09:04 -070053namespace {
chaviw3277faf2021-05-19 16:45:23 -050054inline const char* boolToString(bool b) {
Vishnu Nairdab94092020-09-29 16:09:04 -070055 return b ? "true" : "false";
56}
57} // namespace
58
Robert Carr78c25dd2019-08-15 14:10:33 -070059namespace android {
60
Vishnu Nairdab94092020-09-29 16:09:04 -070061// Macros to include adapter info in log messages
chaviwd7deef72021-10-06 11:53:40 -050062#define BQA_LOGD(x, ...) \
63 ALOGD("[%s](f:%u,a:%u) " x, mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__)
Vishnu Nairdab94092020-09-29 16:09:04 -070064#define BQA_LOGV(x, ...) \
65 ALOGV("[%s](f:%u,a:%u) " x, mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__)
Vishnu Nairc6f89ee2020-12-11 14:27:32 -080066// enable logs for a single layer
67//#define BQA_LOGV(x, ...) \
68// ALOGV_IF((strstr(mName.c_str(), "SurfaceView") != nullptr), "[%s](f:%u,a:%u) " x, \
69// mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__)
Vishnu Nairdab94092020-09-29 16:09:04 -070070#define BQA_LOGE(x, ...) \
71 ALOGE("[%s](f:%u,a:%u) " x, mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__)
72
chaviw57ae4b22022-02-03 16:51:39 -060073#define BBQ_TRACE(x, ...) \
74 ATRACE_FORMAT("%s - %s(f:%u,a:%u)" x, __FUNCTION__, mName.c_str(), mNumFrameAvailable, \
75 mNumAcquired, ##__VA_ARGS__)
76
Chavi Weingartene0237bb2023-02-06 21:48:32 +000077#define UNIQUE_LOCK_WITH_ASSERTION(mutex) \
78 std::unique_lock _lock{mutex}; \
79 base::ScopedLockAssertion assumeLocked(mutex);
80
Patrick Williams7c9fa272024-08-30 12:38:43 +000081#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
82static ReleaseBufferCallback EMPTY_RELEASE_CALLBACK =
83 [](const ReleaseCallbackId&, const sp<Fence>& /*releaseFence*/,
84 std::optional<uint32_t> /*currentMaxAcquiredBufferCount*/) {};
85#endif
86
Valerie Hau871d6352020-01-29 08:44:02 -080087void BLASTBufferItemConsumer::onDisconnect() {
Jiakai Zhangc33c63a2021-11-09 11:24:04 +000088 Mutex::Autolock lock(mMutex);
89 mPreviouslyConnected = mCurrentlyConnected;
90 mCurrentlyConnected = false;
91 if (mPreviouslyConnected) {
92 mDisconnectEvents.push(mCurrentFrameNumber);
Valerie Hau871d6352020-01-29 08:44:02 -080093 }
Jiakai Zhangc33c63a2021-11-09 11:24:04 +000094 mFrameEventHistory.onDisconnect();
Valerie Hau871d6352020-01-29 08:44:02 -080095}
96
97void BLASTBufferItemConsumer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
98 FrameEventHistoryDelta* outDelta) {
Hongguang Chen621ec582021-02-16 15:42:35 -080099 Mutex::Autolock lock(mMutex);
Valerie Hau871d6352020-01-29 08:44:02 -0800100 if (newTimestamps) {
101 // BufferQueueProducer only adds a new timestamp on
102 // queueBuffer
103 mCurrentFrameNumber = newTimestamps->frameNumber;
104 mFrameEventHistory.addQueue(*newTimestamps);
105 }
106 if (outDelta) {
107 // frame event histories will be processed
108 // only after the producer connects and requests
109 // deltas for the first time. Forward this intent
110 // to SF-side to turn event processing back on
111 mPreviouslyConnected = mCurrentlyConnected;
112 mCurrentlyConnected = true;
113 mFrameEventHistory.getAndResetDelta(outDelta);
114 }
115}
116
Alec Mouri21d94322023-10-17 19:51:39 +0000117void BLASTBufferItemConsumer::updateFrameTimestamps(
118 uint64_t frameNumber, uint64_t previousFrameNumber, nsecs_t refreshStartTime,
119 const sp<Fence>& glDoneFence, const sp<Fence>& presentFence,
120 const sp<Fence>& prevReleaseFence, CompositorTiming compositorTiming, nsecs_t latchTime,
121 nsecs_t dequeueReadyTime) {
Hongguang Chen621ec582021-02-16 15:42:35 -0800122 Mutex::Autolock lock(mMutex);
Valerie Hau871d6352020-01-29 08:44:02 -0800123
124 // if the producer is not connected, don't bother updating,
125 // the next producer that connects won't access this frame event
126 if (!mCurrentlyConnected) return;
127 std::shared_ptr<FenceTime> glDoneFenceTime = std::make_shared<FenceTime>(glDoneFence);
128 std::shared_ptr<FenceTime> presentFenceTime = std::make_shared<FenceTime>(presentFence);
129 std::shared_ptr<FenceTime> releaseFenceTime = std::make_shared<FenceTime>(prevReleaseFence);
130
131 mFrameEventHistory.addLatch(frameNumber, latchTime);
Alec Mouri21d94322023-10-17 19:51:39 +0000132 if (flags::frametimestamps_previousrelease()) {
133 if (previousFrameNumber > 0) {
134 mFrameEventHistory.addRelease(previousFrameNumber, dequeueReadyTime,
135 std::move(releaseFenceTime));
136 }
137 } else {
138 mFrameEventHistory.addRelease(frameNumber, dequeueReadyTime, std::move(releaseFenceTime));
139 }
140
Valerie Hau871d6352020-01-29 08:44:02 -0800141 mFrameEventHistory.addPreComposition(frameNumber, refreshStartTime);
142 mFrameEventHistory.addPostComposition(frameNumber, glDoneFenceTime, presentFenceTime,
143 compositorTiming);
144}
145
146void BLASTBufferItemConsumer::getConnectionEvents(uint64_t frameNumber, bool* needsDisconnect) {
147 bool disconnect = false;
Hongguang Chen621ec582021-02-16 15:42:35 -0800148 Mutex::Autolock lock(mMutex);
Valerie Hau871d6352020-01-29 08:44:02 -0800149 while (!mDisconnectEvents.empty() && mDisconnectEvents.front() <= frameNumber) {
150 disconnect = true;
151 mDisconnectEvents.pop();
152 }
153 if (needsDisconnect != nullptr) *needsDisconnect = disconnect;
154}
155
Hongguang Chen621ec582021-02-16 15:42:35 -0800156void BLASTBufferItemConsumer::onSidebandStreamChanged() {
Ady Abrahamdbca1352021-12-15 11:58:56 -0800157 sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
158 if (bbq != nullptr) {
Hongguang Chen621ec582021-02-16 15:42:35 -0800159 sp<NativeHandle> stream = getSidebandStream();
Ady Abrahamdbca1352021-12-15 11:58:56 -0800160 bbq->setSidebandStream(stream);
Hongguang Chen621ec582021-02-16 15:42:35 -0800161 }
162}
163
Ady Abraham107788e2023-10-17 12:31:08 -0700164#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE)
Ady Abraham6cdd3fd2023-09-07 18:45:58 -0700165void BLASTBufferItemConsumer::onSetFrameRate(float frameRate, int8_t compatibility,
166 int8_t changeFrameRateStrategy) {
167 sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
168 if (bbq != nullptr) {
169 bbq->setFrameRate(frameRate, compatibility, changeFrameRateStrategy);
170 }
171}
172#endif
173
Brian Lindahlc794b692023-01-31 15:42:47 -0700174void BLASTBufferItemConsumer::resizeFrameEventHistory(size_t newSize) {
175 Mutex::Autolock lock(mMutex);
176 mFrameEventHistory.resize(newSize);
177}
178
Vishnu Naird2aaab12022-02-10 14:49:09 -0800179BLASTBufferQueue::BLASTBufferQueue(const std::string& name, bool updateDestinationFrame)
Vishnu Nair1cb8e892021-12-06 16:45:48 -0800180 : mSurfaceControl(nullptr),
181 mSize(1, 1),
Vishnu Nairea0de002020-11-17 17:42:37 -0800182 mRequestedSize(mSize),
Vishnu Nair1cb8e892021-12-06 16:45:48 -0800183 mFormat(PIXEL_FORMAT_RGBA_8888),
Tianhao Yao4861b102022-02-03 20:18:35 +0000184 mTransactionReadyCallback(nullptr),
Vishnu Naird2aaab12022-02-10 14:49:09 -0800185 mSyncTransaction(nullptr),
186 mUpdateDestinationFrame(updateDestinationFrame) {
Vishnu Nair89496122020-12-14 17:14:53 -0800187 createBufferQueue(&mProducer, &mConsumer);
Jim Shargod30823a2024-07-27 02:49:39 +0000188#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
189 mBufferItemConsumer = new BLASTBufferItemConsumer(mProducer, mConsumer,
190 GraphicBuffer::USAGE_HW_COMPOSER |
191 GraphicBuffer::USAGE_HW_TEXTURE,
192 1, false, this);
193#else
Vishnu Nair1618c672021-02-05 13:08:26 -0800194 mBufferItemConsumer = new BLASTBufferItemConsumer(mConsumer,
195 GraphicBuffer::USAGE_HW_COMPOSER |
196 GraphicBuffer::USAGE_HW_TEXTURE,
Ady Abrahamdbca1352021-12-15 11:58:56 -0800197 1, false, this);
Jim Shargod30823a2024-07-27 02:49:39 +0000198#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
199 // since the adapter is in the client process, set dequeue timeout
200 // explicitly so that dequeueBuffer will block
201 mProducer->setDequeueTimeout(std::numeric_limits<int64_t>::max());
202
liulijuneb489f62022-10-17 22:02:14 +0800203 static std::atomic<uint32_t> nextId = 0;
204 mProducerId = nextId++;
205 mName = name + "#" + std::to_string(mProducerId);
206 auto consumerName = mName + "(BLAST Consumer)" + std::to_string(mProducerId);
207 mQueuedBufferTrace = "QueuedBuffer - " + mName + "BLAST#" + std::to_string(mProducerId);
Vishnu Nairdab94092020-09-29 16:09:04 -0700208 mBufferItemConsumer->setName(String8(consumerName.c_str()));
Robert Carr78c25dd2019-08-15 14:10:33 -0700209 mBufferItemConsumer->setFrameAvailableListener(this);
Robert Carr9f133d72020-04-01 15:51:46 -0700210
Huihong Luo02186fb2022-02-23 14:21:54 -0800211 ComposerServiceAIDL::getComposerService()->getMaxAcquiredBufferCount(&mMaxAcquiredBuffers);
Ady Abraham0bde6b52021-05-18 13:57:02 -0700212 mBufferItemConsumer->setMaxAcquiredBufferCount(mMaxAcquiredBuffers);
chaviw69058fb2021-09-27 09:37:30 -0500213 mCurrentMaxAcquiredBufferCount = mMaxAcquiredBuffers;
Valerie Haua32c5522019-12-09 10:11:08 -0800214 mNumAcquired = 0;
215 mNumFrameAvailable = 0;
Robert Carr4c1b6462021-12-21 10:30:50 -0800216
217 TransactionCompletedListener::getInstance()->addQueueStallListener(
Patrick Williamsf1e5df12022-10-17 21:37:42 +0000218 [&](const std::string& reason) {
219 std::function<void(const std::string&)> callbackCopy;
220 {
221 std::unique_lock _lock{mMutex};
222 callbackCopy = mTransactionHangCallback;
223 }
224 if (callbackCopy) callbackCopy(reason);
225 },
226 this);
Robert Carr4c1b6462021-12-21 10:30:50 -0800227
Patrick Williams7c9fa272024-08-30 12:38:43 +0000228#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
229 std::unique_ptr<gui::BufferReleaseChannel::ConsumerEndpoint> bufferReleaseConsumer;
230 gui::BufferReleaseChannel::open(mName, bufferReleaseConsumer, mBufferReleaseProducer);
231 mBufferReleaseReader = std::make_shared<BufferReleaseReader>(std::move(bufferReleaseConsumer));
232#endif
233
Vishnu Nair1e8bf102021-12-28 14:36:59 -0800234 BQA_LOGV("BLASTBufferQueue created");
Vishnu Nair1cb8e892021-12-06 16:45:48 -0800235}
236
237BLASTBufferQueue::BLASTBufferQueue(const std::string& name, const sp<SurfaceControl>& surface,
238 int width, int height, int32_t format)
239 : BLASTBufferQueue(name) {
240 update(surface, width, height, format);
Robert Carr78c25dd2019-08-15 14:10:33 -0700241}
242
Vishnu Nairc4a40c12020-12-23 09:14:32 -0800243BLASTBufferQueue::~BLASTBufferQueue() {
Robert Carr4c1b6462021-12-21 10:30:50 -0800244 TransactionCompletedListener::getInstance()->removeQueueStallListener(this);
Vishnu Nairc4a40c12020-12-23 09:14:32 -0800245 if (mPendingTransactions.empty()) {
246 return;
247 }
248 BQA_LOGE("Applying pending transactions on dtor %d",
249 static_cast<uint32_t>(mPendingTransactions.size()));
250 SurfaceComposerClient::Transaction t;
Vishnu Nair1e8bf102021-12-28 14:36:59 -0800251 mergePendingTransactions(&t, std::numeric_limits<uint64_t>::max() /* frameNumber */);
Robert Carr79dc06a2022-02-22 15:28:59 -0800252 // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction
253 t.setApplyToken(mApplyToken).apply(false, true);
chaviw3b4bdcf2022-03-17 09:27:03 -0500254
255 if (mTransactionReadyCallback) {
256 mTransactionReadyCallback(mSyncTransaction);
257 }
Vishnu Nairc4a40c12020-12-23 09:14:32 -0800258}
259
Patrick Williamsf5b42de2024-08-01 16:08:51 -0500260void BLASTBufferQueue::onFirstRef() {
261 // safe default, most producers are expected to override this
262 mProducer->setMaxDequeuedBufferCount(2);
Patrick Williams7c9fa272024-08-30 12:38:43 +0000263#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
264 mBufferReleaseThread.start(sp<BLASTBufferQueue>::fromExisting(this));
265#endif
Patrick Williamsf5b42de2024-08-01 16:08:51 -0500266}
267
chaviw565ee542021-01-14 10:21:23 -0800268void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height,
Vishnu Naird2aaab12022-02-10 14:49:09 -0800269 int32_t format) {
Vishnu Nair1e8bf102021-12-28 14:36:59 -0800270 LOG_ALWAYS_FATAL_IF(surface == nullptr, "BLASTBufferQueue: mSurfaceControl must not be NULL");
271
Chavi Weingartene0237bb2023-02-06 21:48:32 +0000272 std::lock_guard _lock{mMutex};
chaviw565ee542021-01-14 10:21:23 -0800273 if (mFormat != format) {
274 mFormat = format;
chaviw497e81c2021-02-04 17:09:47 -0800275 mBufferItemConsumer->setDefaultBufferFormat(convertBufferFormat(format));
chaviw565ee542021-01-14 10:21:23 -0800276 }
277
Vishnu Nair1e8bf102021-12-28 14:36:59 -0800278 const bool surfaceControlChanged = !SurfaceControl::isSameSurface(mSurfaceControl, surface);
Vishnu Nairab066512022-01-04 22:28:00 +0000279 if (surfaceControlChanged && mSurfaceControl != nullptr) {
280 BQA_LOGD("Updating SurfaceControl without recreating BBQ");
281 }
Vishnu Nairf6eddb62021-01-27 22:02:11 -0800282 bool applyTransaction = false;
Vishnu Nairf6eddb62021-01-27 22:02:11 -0800283
Vishnu Nair5fa91c22021-06-29 14:30:48 -0700284 // Always update the native object even though they might have the same layer handle, so we can
285 // get the updated transform hint from WM.
286 mSurfaceControl = surface;
Vishnu Naird2aaab12022-02-10 14:49:09 -0800287 SurfaceComposerClient::Transaction t;
Vishnu Nair1e8bf102021-12-28 14:36:59 -0800288 if (surfaceControlChanged) {
Vishnu Nair1e8bf102021-12-28 14:36:59 -0800289 t.setFlags(mSurfaceControl, layer_state_t::eEnableBackpressure,
290 layer_state_t::eEnableBackpressure);
Patrick Williams7c9fa272024-08-30 12:38:43 +0000291#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
292 t.setBufferReleaseChannel(mSurfaceControl, mBufferReleaseProducer);
293#endif
Vishnu Nair1e8bf102021-12-28 14:36:59 -0800294 applyTransaction = true;
Arthur Hungb6aa9a02021-06-09 14:23:01 +0800295 }
Vishnu Nair1e8bf102021-12-28 14:36:59 -0800296 mTransformHint = mSurfaceControl->getTransformHint();
297 mBufferItemConsumer->setTransformHint(mTransformHint);
Vishnu Naira4fbca52021-07-07 16:52:34 -0700298 BQA_LOGV("update width=%d height=%d format=%d mTransformHint=%d", width, height, format,
299 mTransformHint);
Arthur Hungb6aa9a02021-06-09 14:23:01 +0800300
Vishnu Nairea0de002020-11-17 17:42:37 -0800301 ui::Size newSize(width, height);
302 if (mRequestedSize != newSize) {
303 mRequestedSize.set(newSize);
304 mBufferItemConsumer->setDefaultBufferSize(mRequestedSize.width, mRequestedSize.height);
Chavi Weingartena5aedbd2021-04-09 13:37:33 +0000305 if (mLastBufferInfo.scalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) {
Vishnu Nair53c936c2020-12-03 11:46:37 -0800306 // If the buffer supports scaling, update the frame immediately since the client may
307 // want to scale the existing buffer to the new size.
308 mSize = mRequestedSize;
Vishnu Naird2aaab12022-02-10 14:49:09 -0800309 if (mUpdateDestinationFrame) {
310 t.setDestinationFrame(mSurfaceControl, Rect(newSize));
311 applyTransaction = true;
312 }
Vishnu Nair53c936c2020-12-03 11:46:37 -0800313 }
Robert Carrfc416512020-04-02 12:32:44 -0700314 }
Vishnu Nairf6eddb62021-01-27 22:02:11 -0800315 if (applyTransaction) {
Robert Carr79dc06a2022-02-22 15:28:59 -0800316 // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction
317 t.setApplyToken(mApplyToken).apply(false, true);
Vishnu Nairf6eddb62021-01-27 22:02:11 -0800318 }
Robert Carr78c25dd2019-08-15 14:10:33 -0700319}
320
chaviwd7deef72021-10-06 11:53:40 -0500321static std::optional<SurfaceControlStats> findMatchingStat(
322 const std::vector<SurfaceControlStats>& stats, const sp<SurfaceControl>& sc) {
323 for (auto stat : stats) {
324 if (SurfaceControl::isSameSurface(sc, stat.surfaceControl)) {
325 return stat;
326 }
327 }
328 return std::nullopt;
329}
330
Patrick Williams5312ec12024-08-23 16:11:10 -0500331TransactionCompletedCallbackTakesContext BLASTBufferQueue::makeTransactionCommittedCallbackThunk() {
332 return [bbq = sp<BLASTBufferQueue>::fromExisting(
333 this)](void* /*context*/, nsecs_t latchTime, const sp<Fence>& presentFence,
334 const std::vector<SurfaceControlStats>& stats) {
335 bbq->transactionCommittedCallback(latchTime, presentFence, stats);
336 };
chaviwd7deef72021-10-06 11:53:40 -0500337}
338
339void BLASTBufferQueue::transactionCommittedCallback(nsecs_t /*latchTime*/,
340 const sp<Fence>& /*presentFence*/,
341 const std::vector<SurfaceControlStats>& stats) {
342 {
Chavi Weingartene0237bb2023-02-06 21:48:32 +0000343 std::lock_guard _lock{mMutex};
chaviw57ae4b22022-02-03 16:51:39 -0600344 BBQ_TRACE();
chaviwd7deef72021-10-06 11:53:40 -0500345 BQA_LOGV("transactionCommittedCallback");
346 if (!mSurfaceControlsWithPendingCallback.empty()) {
347 sp<SurfaceControl> pendingSC = mSurfaceControlsWithPendingCallback.front();
348 std::optional<SurfaceControlStats> stat = findMatchingStat(stats, pendingSC);
349 if (stat) {
350 uint64_t currFrameNumber = stat->frameEventStats.frameNumber;
351
352 // We need to check if we were waiting for a transaction callback in order to
353 // process any pending buffers and unblock. It's possible to get transaction
chaviwc1cf4022022-06-03 13:32:33 -0500354 // callbacks for previous requests so we need to ensure that there are no pending
355 // frame numbers that were in a sync. We remove the frame from mSyncedFrameNumbers
356 // set and then check if it's empty. If there are no more pending syncs, we can
357 // proceed with flushing the shadow queue.
chaviwc1cf4022022-06-03 13:32:33 -0500358 mSyncedFrameNumbers.erase(currFrameNumber);
Chavi Weingartend48797b2023-08-04 13:11:39 +0000359 if (mSyncedFrameNumbers.empty()) {
chaviwd7deef72021-10-06 11:53:40 -0500360 flushShadowQueue();
361 }
362 } else {
chaviw768bfa02021-11-01 09:50:57 -0500363 BQA_LOGE("Failed to find matching SurfaceControl in transactionCommittedCallback");
chaviwd7deef72021-10-06 11:53:40 -0500364 }
365 } else {
366 BQA_LOGE("No matching SurfaceControls found: mSurfaceControlsWithPendingCallback was "
367 "empty.");
368 }
chaviwd7deef72021-10-06 11:53:40 -0500369 }
370}
371
Patrick Williams5312ec12024-08-23 16:11:10 -0500372TransactionCompletedCallbackTakesContext BLASTBufferQueue::makeTransactionCallbackThunk() {
373 return [bbq = sp<BLASTBufferQueue>::fromExisting(
374 this)](void* /*context*/, nsecs_t latchTime, const sp<Fence>& presentFence,
375 const std::vector<SurfaceControlStats>& stats) {
376 bbq->transactionCallback(latchTime, presentFence, stats);
377 };
Robert Carr78c25dd2019-08-15 14:10:33 -0700378}
379
380void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence>& /*presentFence*/,
381 const std::vector<SurfaceControlStats>& stats) {
chaviw71c2cc42020-10-23 16:42:02 -0700382 {
Chavi Weingartene0237bb2023-02-06 21:48:32 +0000383 std::lock_guard _lock{mMutex};
chaviw57ae4b22022-02-03 16:51:39 -0600384 BBQ_TRACE();
chaviw71c2cc42020-10-23 16:42:02 -0700385 BQA_LOGV("transactionCallback");
chaviw71c2cc42020-10-23 16:42:02 -0700386
chaviw42026162021-04-16 15:46:12 -0500387 if (!mSurfaceControlsWithPendingCallback.empty()) {
388 sp<SurfaceControl> pendingSC = mSurfaceControlsWithPendingCallback.front();
389 mSurfaceControlsWithPendingCallback.pop();
chaviwd7deef72021-10-06 11:53:40 -0500390 std::optional<SurfaceControlStats> statsOptional = findMatchingStat(stats, pendingSC);
391 if (statsOptional) {
392 SurfaceControlStats stat = *statsOptional;
Vishnu Nair71fcf912022-10-18 09:14:20 -0700393 if (stat.transformHint) {
394 mTransformHint = *stat.transformHint;
395 mBufferItemConsumer->setTransformHint(mTransformHint);
396 BQA_LOGV("updated mTransformHint=%d", mTransformHint);
397 }
Vishnu Nairde66dc72021-06-17 17:54:41 -0700398 // Update frametime stamps if the frame was latched and presented, indicated by a
399 // valid latch time.
400 if (stat.latchTime > 0) {
401 mBufferItemConsumer
402 ->updateFrameTimestamps(stat.frameEventStats.frameNumber,
Alec Mouri21d94322023-10-17 19:51:39 +0000403 stat.frameEventStats.previousFrameNumber,
Vishnu Nairde66dc72021-06-17 17:54:41 -0700404 stat.frameEventStats.refreshStartTime,
405 stat.frameEventStats.gpuCompositionDoneFence,
406 stat.presentFence, stat.previousReleaseFence,
407 stat.frameEventStats.compositorTiming,
408 stat.latchTime,
409 stat.frameEventStats.dequeueReadyTime);
410 }
Patrick Williams7c9fa272024-08-30 12:38:43 +0000411#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
Robert Carr405e2f62021-12-31 16:59:34 -0800412 auto currFrameNumber = stat.frameEventStats.frameNumber;
413 std::vector<ReleaseCallbackId> staleReleases;
414 for (const auto& [key, value]: mSubmitted) {
415 if (currFrameNumber > key.framenumber) {
416 staleReleases.push_back(key);
417 }
418 }
419 for (const auto& staleRelease : staleReleases) {
Robert Carr405e2f62021-12-31 16:59:34 -0800420 releaseBufferCallbackLocked(staleRelease,
Vishnu Nair28fe2e62022-11-01 14:29:10 -0700421 stat.previousReleaseFence
422 ? stat.previousReleaseFence
423 : Fence::NO_FENCE,
424 stat.currentMaxAcquiredBufferCount,
425 true /* fakeRelease */);
Robert Carr405e2f62021-12-31 16:59:34 -0800426 }
Patrick Williams7c9fa272024-08-30 12:38:43 +0000427#endif
chaviwd7deef72021-10-06 11:53:40 -0500428 } else {
chaviw768bfa02021-11-01 09:50:57 -0500429 BQA_LOGE("Failed to find matching SurfaceControl in transactionCallback");
chaviw42026162021-04-16 15:46:12 -0500430 }
431 } else {
432 BQA_LOGE("No matching SurfaceControls found: mSurfaceControlsWithPendingCallback was "
433 "empty.");
Valerie Haua32c5522019-12-09 10:11:08 -0800434 }
Robert Carr78c25dd2019-08-15 14:10:33 -0700435 }
Robert Carr78c25dd2019-08-15 14:10:33 -0700436}
437
Patrick Williams7c9fa272024-08-30 12:38:43 +0000438void BLASTBufferQueue::flushShadowQueue() {
439 BQA_LOGV("flushShadowQueue");
440 int numFramesToFlush = mNumFrameAvailable;
441 while (numFramesToFlush > 0) {
442 acquireNextBufferLocked(std::nullopt);
443 numFramesToFlush--;
444 }
445}
446
Vishnu Nair1506b182021-02-22 14:35:15 -0800447// Unlike transactionCallbackThunk the release buffer callback does not extend the life of the
448// BBQ. This is because if the BBQ is destroyed, then the buffers will be released by the client.
449// So we pass in a weak pointer to the BBQ and if it still alive, then we release the buffer.
450// Otherwise, this is a no-op.
Patrick Williams5312ec12024-08-23 16:11:10 -0500451ReleaseBufferCallback BLASTBufferQueue::makeReleaseBufferCallbackThunk() {
452 return [weakBbq = wp<BLASTBufferQueue>::fromExisting(
453 this)](const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
454 std::optional<uint32_t> currentMaxAcquiredBufferCount) {
455 sp<BLASTBufferQueue> bbq = weakBbq.promote();
456 if (!bbq) {
457 ALOGV("releaseBufferCallbackThunk %s blastBufferQueue is dead", id.to_string().c_str());
458 return;
459 }
460 bbq->releaseBufferCallback(id, releaseFence, currentMaxAcquiredBufferCount);
461 };
Vishnu Nair1506b182021-02-22 14:35:15 -0800462}
463
chaviw69058fb2021-09-27 09:37:30 -0500464void BLASTBufferQueue::releaseBufferCallback(
465 const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
466 std::optional<uint32_t> currentMaxAcquiredBufferCount) {
Chavi Weingartene0237bb2023-02-06 21:48:32 +0000467 std::lock_guard _lock{mMutex};
chaviw57ae4b22022-02-03 16:51:39 -0600468 BBQ_TRACE();
Vishnu Nair28fe2e62022-11-01 14:29:10 -0700469 releaseBufferCallbackLocked(id, releaseFence, currentMaxAcquiredBufferCount,
470 false /* fakeRelease */);
Robert Carr405e2f62021-12-31 16:59:34 -0800471}
472
Vishnu Nair28fe2e62022-11-01 14:29:10 -0700473void BLASTBufferQueue::releaseBufferCallbackLocked(
474 const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
475 std::optional<uint32_t> currentMaxAcquiredBufferCount, bool fakeRelease) {
Robert Carr405e2f62021-12-31 16:59:34 -0800476 ATRACE_CALL();
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -0700477 BQA_LOGV("releaseBufferCallback %s", id.to_string().c_str());
Vishnu Nair1506b182021-02-22 14:35:15 -0800478
Alec Mouri3118f962024-09-13 22:34:11 +0000479 if (CC_UNLIKELY(atrace_is_tag_enabled(ATRACE_TAG_GRAPHICS))) {
480 if (!mFenceMonitor) {
481 std::string monitorName = "release :";
482 monitorName.append(mName.c_str());
483 mFenceMonitor.emplace(monitorName.c_str());
484 }
485
486 mFenceMonitor->queueFence(releaseFence);
487 }
488
Ady Abraham899dcdb2021-06-15 16:56:21 -0700489 // Calculate how many buffers we need to hold before we release them back
490 // to the buffer queue. This will prevent higher latency when we are running
491 // on a lower refresh rate than the max supported. We only do that for EGL
492 // clients as others don't care about latency
Chavi Weingartene0237bb2023-02-06 21:48:32 +0000493 const auto it = mSubmitted.find(id);
494 const bool isEGL = it != mSubmitted.end() && it->second.mApi == NATIVE_WINDOW_API_EGL;
Ady Abraham899dcdb2021-06-15 16:56:21 -0700495
chaviw69058fb2021-09-27 09:37:30 -0500496 if (currentMaxAcquiredBufferCount) {
497 mCurrentMaxAcquiredBufferCount = *currentMaxAcquiredBufferCount;
498 }
499
liulijunf90df632022-11-14 14:24:48 +0800500 const uint32_t numPendingBuffersToHold =
501 isEGL ? std::max(0, mMaxAcquiredBuffers - (int32_t)mCurrentMaxAcquiredBufferCount) : 0;
Robert Carr405e2f62021-12-31 16:59:34 -0800502
503 auto rb = ReleasedBuffer{id, releaseFence};
504 if (std::find(mPendingRelease.begin(), mPendingRelease.end(), rb) == mPendingRelease.end()) {
505 mPendingRelease.emplace_back(rb);
Vishnu Nair28fe2e62022-11-01 14:29:10 -0700506 if (fakeRelease) {
507 BQA_LOGE("Faking releaseBufferCallback from transactionCompleteCallback %" PRIu64,
508 id.framenumber);
509 BBQ_TRACE("FakeReleaseCallback");
510 }
Robert Carr405e2f62021-12-31 16:59:34 -0800511 }
Ady Abraham899dcdb2021-06-15 16:56:21 -0700512
513 // Release all buffers that are beyond the ones that we need to hold
514 while (mPendingRelease.size() > numPendingBuffersToHold) {
chaviw0acd33a2021-11-02 11:55:37 -0500515 const auto releasedBuffer = mPendingRelease.front();
Ady Abraham899dcdb2021-06-15 16:56:21 -0700516 mPendingRelease.pop_front();
chaviw0acd33a2021-11-02 11:55:37 -0500517 releaseBuffer(releasedBuffer.callbackId, releasedBuffer.releaseFence);
chaviwc1cf4022022-06-03 13:32:33 -0500518 // Don't process the transactions here if mSyncedFrameNumbers is not empty. That means
519 // are still transactions that have sync buffers in them that have not been applied or
520 // dropped. Instead, let onFrameAvailable handle processing them since it will merge with
521 // the syncTransaction.
522 if (mSyncedFrameNumbers.empty()) {
chaviwd7deef72021-10-06 11:53:40 -0500523 acquireNextBufferLocked(std::nullopt);
524 }
Vishnu Nair1506b182021-02-22 14:35:15 -0800525 }
526
Ady Abraham899dcdb2021-06-15 16:56:21 -0700527 ATRACE_INT("PendingRelease", mPendingRelease.size());
Vishnu Nair2a52ca62021-06-24 13:08:53 -0700528 ATRACE_INT(mQueuedBufferTrace.c_str(),
529 mNumFrameAvailable + mNumAcquired - mPendingRelease.size());
Vishnu Nair1506b182021-02-22 14:35:15 -0800530 mCallbackCV.notify_all();
531}
532
chaviw0acd33a2021-11-02 11:55:37 -0500533void BLASTBufferQueue::releaseBuffer(const ReleaseCallbackId& callbackId,
534 const sp<Fence>& releaseFence) {
535 auto it = mSubmitted.find(callbackId);
536 if (it == mSubmitted.end()) {
Patrick Williams4b9507d2024-07-25 09:55:52 -0500537 BQA_LOGE("ERROR: releaseBufferCallback without corresponding submitted buffer %s",
538 callbackId.to_string().c_str());
chaviw0acd33a2021-11-02 11:55:37 -0500539 return;
540 }
541 mNumAcquired--;
chaviw57ae4b22022-02-03 16:51:39 -0600542 BBQ_TRACE("frame=%" PRIu64, callbackId.framenumber);
chaviw0acd33a2021-11-02 11:55:37 -0500543 BQA_LOGV("released %s", callbackId.to_string().c_str());
544 mBufferItemConsumer->releaseBuffer(it->second, releaseFence);
545 mSubmitted.erase(it);
chaviwc1cf4022022-06-03 13:32:33 -0500546 // Remove the frame number from mSyncedFrameNumbers since we can get a release callback
547 // without getting a transaction committed if the buffer was dropped.
548 mSyncedFrameNumbers.erase(callbackId.framenumber);
chaviw0acd33a2021-11-02 11:55:37 -0500549}
550
Chavi Weingarten70670e62023-02-22 17:36:40 +0000551static ui::Size getBufferSize(const BufferItem& item) {
552 uint32_t bufWidth = item.mGraphicBuffer->getWidth();
553 uint32_t bufHeight = item.mGraphicBuffer->getHeight();
554
555 // Take the buffer's orientation into account
556 if (item.mTransform & ui::Transform::ROT_90) {
557 std::swap(bufWidth, bufHeight);
558 }
559 return ui::Size(bufWidth, bufHeight);
560}
561
Chavi Weingarten3a8f19b2022-12-27 22:00:24 +0000562status_t BLASTBufferQueue::acquireNextBufferLocked(
chaviwd7deef72021-10-06 11:53:40 -0500563 const std::optional<SurfaceComposerClient::Transaction*> transaction) {
Vishnu Nairb4b484a2023-01-20 10:00:18 -0800564 // Check if we have frames available and we have not acquired the maximum number of buffers.
565 // Even with this check, the consumer can fail to acquire an additional buffer if the consumer
566 // has already acquired (mMaxAcquiredBuffers + 1) and the new buffer is not droppable. In this
567 // case mBufferItemConsumer->acquireBuffer will return with NO_BUFFER_AVAILABLE.
Chavi Weingarten3a8f19b2022-12-27 22:00:24 +0000568 if (mNumFrameAvailable == 0) {
Vishnu Nairb4b484a2023-01-20 10:00:18 -0800569 BQA_LOGV("Can't acquire next buffer. No available frames");
570 return BufferQueue::NO_BUFFER_AVAILABLE;
571 }
572
573 if (mNumAcquired >= (mMaxAcquiredBuffers + 2)) {
574 BQA_LOGV("Can't acquire next buffer. Already acquired max frames %d max:%d + 2",
575 mNumAcquired, mMaxAcquiredBuffers);
576 return BufferQueue::NO_BUFFER_AVAILABLE;
Valerie Haud3b90d22019-11-06 09:37:31 -0800577 }
578
Valerie Haua32c5522019-12-09 10:11:08 -0800579 if (mSurfaceControl == nullptr) {
Vishnu Nair670b3f72020-09-29 17:52:18 -0700580 BQA_LOGE("ERROR : surface control is null");
Chavi Weingarten3a8f19b2022-12-27 22:00:24 +0000581 return NAME_NOT_FOUND;
Valerie Haud3b90d22019-11-06 09:37:31 -0800582 }
583
Robert Carr78c25dd2019-08-15 14:10:33 -0700584 SurfaceComposerClient::Transaction localTransaction;
585 bool applyTransaction = true;
586 SurfaceComposerClient::Transaction* t = &localTransaction;
chaviwd7deef72021-10-06 11:53:40 -0500587 if (transaction) {
588 t = *transaction;
Robert Carr78c25dd2019-08-15 14:10:33 -0700589 applyTransaction = false;
590 }
591
Patrick Williams3ced5382024-08-21 15:39:32 -0500592 BufferItem bufferItem;
Valerie Haud3b90d22019-11-06 09:37:31 -0800593
Vishnu Nairc6f89ee2020-12-11 14:27:32 -0800594 status_t status =
595 mBufferItemConsumer->acquireBuffer(&bufferItem, 0 /* expectedPresent */, false);
Vishnu Nair8b30dd12021-01-25 14:16:54 -0800596 if (status == BufferQueue::NO_BUFFER_AVAILABLE) {
597 BQA_LOGV("Failed to acquire a buffer, err=NO_BUFFER_AVAILABLE");
Chavi Weingarten3a8f19b2022-12-27 22:00:24 +0000598 return status;
Vishnu Nair8b30dd12021-01-25 14:16:54 -0800599 } else if (status != OK) {
Vishnu Nairbf255772020-10-16 10:54:41 -0700600 BQA_LOGE("Failed to acquire a buffer, err=%s", statusToString(status).c_str());
Chavi Weingarten3a8f19b2022-12-27 22:00:24 +0000601 return status;
Robert Carr78c25dd2019-08-15 14:10:33 -0700602 }
chaviw57ae4b22022-02-03 16:51:39 -0600603
Valerie Haua32c5522019-12-09 10:11:08 -0800604 auto buffer = bufferItem.mGraphicBuffer;
605 mNumFrameAvailable--;
chaviw57ae4b22022-02-03 16:51:39 -0600606 BBQ_TRACE("frame=%" PRIu64, bufferItem.mFrameNumber);
Valerie Haua32c5522019-12-09 10:11:08 -0800607
608 if (buffer == nullptr) {
609 mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE);
Vishnu Nairbf255772020-10-16 10:54:41 -0700610 BQA_LOGE("Buffer was empty");
Chavi Weingarten3a8f19b2022-12-27 22:00:24 +0000611 return BAD_VALUE;
Valerie Haua32c5522019-12-09 10:11:08 -0800612 }
613
Vishnu Nair670b3f72020-09-29 17:52:18 -0700614 if (rejectBuffer(bufferItem)) {
Vishnu Naira4fbca52021-07-07 16:52:34 -0700615 BQA_LOGE("rejecting buffer:active_size=%dx%d, requested_size=%dx%d "
Vishnu Nairea0de002020-11-17 17:42:37 -0800616 "buffer{size=%dx%d transform=%d}",
617 mSize.width, mSize.height, mRequestedSize.width, mRequestedSize.height,
618 buffer->getWidth(), buffer->getHeight(), bufferItem.mTransform);
619 mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE);
Chavi Weingarten3a8f19b2022-12-27 22:00:24 +0000620 return acquireNextBufferLocked(transaction);
Vishnu Nair670b3f72020-09-29 17:52:18 -0700621 }
622
Valerie Haua32c5522019-12-09 10:11:08 -0800623 mNumAcquired++;
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -0700624 mLastAcquiredFrameNumber = bufferItem.mFrameNumber;
625 ReleaseCallbackId releaseCallbackId(buffer->getId(), mLastAcquiredFrameNumber);
626 mSubmitted[releaseCallbackId] = bufferItem;
Robert Carr78c25dd2019-08-15 14:10:33 -0700627
Valerie Hau871d6352020-01-29 08:44:02 -0800628 bool needsDisconnect = false;
629 mBufferItemConsumer->getConnectionEvents(bufferItem.mFrameNumber, &needsDisconnect);
630
631 // if producer disconnected before, notify SurfaceFlinger
632 if (needsDisconnect) {
633 t->notifyProducerDisconnect(mSurfaceControl);
634 }
635
Chavi Weingarten70670e62023-02-22 17:36:40 +0000636 // Only update mSize for destination bounds if the incoming buffer matches the requested size.
637 // Otherwise, it could cause stretching since the destination bounds will update before the
638 // buffer with the new size is acquired.
Vishnu Nair5b5f6932023-04-12 16:28:19 -0700639 if (mRequestedSize == getBufferSize(bufferItem) ||
640 bufferItem.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) {
Chavi Weingarten70670e62023-02-22 17:36:40 +0000641 mSize = mRequestedSize;
642 }
Vishnu Nair5cc9ac02021-04-19 13:23:38 -0700643 Rect crop = computeCrop(bufferItem);
Chavi Weingartena5aedbd2021-04-09 13:37:33 +0000644 mLastBufferInfo.update(true /* hasBuffer */, bufferItem.mGraphicBuffer->getWidth(),
645 bufferItem.mGraphicBuffer->getHeight(), bufferItem.mTransform,
Vishnu Nair5cc9ac02021-04-19 13:23:38 -0700646 bufferItem.mScalingMode, crop);
Vishnu Nair53c936c2020-12-03 11:46:37 -0800647
Patrick Williams7c9fa272024-08-30 12:38:43 +0000648#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
649 ReleaseBufferCallback releaseBufferCallback =
650 applyTransaction ? EMPTY_RELEASE_CALLBACK : makeReleaseBufferCallbackThunk();
651#else
Patrick Williams5312ec12024-08-23 16:11:10 -0500652 auto releaseBufferCallback = makeReleaseBufferCallbackThunk();
Patrick Williams7c9fa272024-08-30 12:38:43 +0000653#endif
chaviwba4320c2021-09-15 15:20:53 -0500654 sp<Fence> fence = bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE;
Nergi Rahardi39f510f2024-05-23 15:16:54 +0900655
656 nsecs_t dequeueTime = -1;
657 {
658 std::lock_guard _lock{mTimestampMutex};
659 auto dequeueTimeIt = mDequeueTimestamps.find(buffer->getId());
660 if (dequeueTimeIt != mDequeueTimestamps.end()) {
661 dequeueTime = dequeueTimeIt->second;
662 mDequeueTimestamps.erase(dequeueTimeIt);
663 }
664 }
665
liulijuneb489f62022-10-17 22:02:14 +0800666 t->setBuffer(mSurfaceControl, buffer, fence, bufferItem.mFrameNumber, mProducerId,
Nergi Rahardi39f510f2024-05-23 15:16:54 +0900667 releaseBufferCallback, dequeueTime);
John Reck137069e2020-12-10 22:07:37 -0500668 t->setDataspace(mSurfaceControl, static_cast<ui::Dataspace>(bufferItem.mDataSpace));
669 t->setHdrMetadata(mSurfaceControl, bufferItem.mHdrMetadata);
670 t->setSurfaceDamageRegion(mSurfaceControl, bufferItem.mSurfaceDamage);
Patrick Williams5312ec12024-08-23 16:11:10 -0500671 t->addTransactionCompletedCallback(makeTransactionCallbackThunk(), nullptr);
chaviwf2dace72021-11-17 17:36:50 -0600672
chaviw42026162021-04-16 15:46:12 -0500673 mSurfaceControlsWithPendingCallback.push(mSurfaceControl);
Robert Carr78c25dd2019-08-15 14:10:33 -0700674
Vishnu Naird2aaab12022-02-10 14:49:09 -0800675 if (mUpdateDestinationFrame) {
676 t->setDestinationFrame(mSurfaceControl, Rect(mSize));
677 } else {
678 const bool ignoreDestinationFrame =
679 bufferItem.mScalingMode == NATIVE_WINDOW_SCALING_MODE_FREEZE;
680 t->setFlags(mSurfaceControl,
681 ignoreDestinationFrame ? layer_state_t::eIgnoreDestinationFrame : 0,
682 layer_state_t::eIgnoreDestinationFrame);
Vishnu Nair084514a2021-07-30 16:07:42 -0700683 }
Vishnu Nair6bdec7d2021-05-10 15:01:13 -0700684 t->setBufferCrop(mSurfaceControl, crop);
Valerie Haua32c5522019-12-09 10:11:08 -0800685 t->setTransform(mSurfaceControl, bufferItem.mTransform);
Valerie Hau2882e982020-01-23 13:33:10 -0800686 t->setTransformToDisplayInverse(mSurfaceControl, bufferItem.mTransformToDisplayInverse);
Vishnu Naird2aaab12022-02-10 14:49:09 -0800687 t->setAutoRefresh(mSurfaceControl, bufferItem.mAutoRefresh);
Ady Abrahamf0c56492020-12-17 18:04:15 -0800688 if (!bufferItem.mIsAutoTimestamp) {
689 t->setDesiredPresentTime(bufferItem.mTimestamp);
690 }
Robert Carr78c25dd2019-08-15 14:10:33 -0700691
Ady Abrahamd6e409e2023-01-19 16:07:31 -0800692 // Drop stale frame timeline infos
693 while (!mPendingFrameTimelines.empty() &&
694 mPendingFrameTimelines.front().first < bufferItem.mFrameNumber) {
695 ATRACE_FORMAT_INSTANT("dropping stale frameNumber: %" PRIu64 " vsyncId: %" PRId64,
696 mPendingFrameTimelines.front().first,
697 mPendingFrameTimelines.front().second.vsyncId);
698 mPendingFrameTimelines.pop();
699 }
700
701 if (!mPendingFrameTimelines.empty() &&
702 mPendingFrameTimelines.front().first == bufferItem.mFrameNumber) {
703 ATRACE_FORMAT_INSTANT("Transaction::setFrameTimelineInfo frameNumber: %" PRIu64
704 " vsyncId: %" PRId64,
705 bufferItem.mFrameNumber,
706 mPendingFrameTimelines.front().second.vsyncId);
707 t->setFrameTimelineInfo(mPendingFrameTimelines.front().second);
708 mPendingFrameTimelines.pop();
Jorim Jaggia3fe67b2020-12-01 00:24:33 +0100709 }
710
chaviw6a195272021-09-03 16:14:25 -0500711 mergePendingTransactions(t, bufferItem.mFrameNumber);
Robert Carr78c25dd2019-08-15 14:10:33 -0700712 if (applyTransaction) {
Robert Carr79dc06a2022-02-22 15:28:59 -0800713 // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction
714 t->setApplyToken(mApplyToken).apply(false, true);
715 mAppliedLastTransaction = true;
716 mLastAppliedFrameNumber = bufferItem.mFrameNumber;
717 } else {
718 t->setBufferHasBarrier(mSurfaceControl, mLastAppliedFrameNumber);
719 mAppliedLastTransaction = false;
Robert Carr78c25dd2019-08-15 14:10:33 -0700720 }
Vishnu Nairdab94092020-09-29 16:09:04 -0700721
chaviwd7deef72021-10-06 11:53:40 -0500722 BQA_LOGV("acquireNextBufferLocked size=%dx%d mFrameNumber=%" PRIu64
Vishnu Nair1506b182021-02-22 14:35:15 -0800723 " applyTransaction=%s mTimestamp=%" PRId64 "%s mPendingTransactions.size=%d"
Vishnu Naira4fbca52021-07-07 16:52:34 -0700724 " graphicBufferId=%" PRIu64 "%s transform=%d",
chaviw3277faf2021-05-19 16:45:23 -0500725 mSize.width, mSize.height, bufferItem.mFrameNumber, boolToString(applyTransaction),
Vishnu Nair1506b182021-02-22 14:35:15 -0800726 bufferItem.mTimestamp, bufferItem.mIsAutoTimestamp ? "(auto)" : "",
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -0700727 static_cast<uint32_t>(mPendingTransactions.size()), bufferItem.mGraphicBuffer->getId(),
Vishnu Naira4fbca52021-07-07 16:52:34 -0700728 bufferItem.mAutoRefresh ? " mAutoRefresh" : "", bufferItem.mTransform);
Chavi Weingarten3a8f19b2022-12-27 22:00:24 +0000729 return OK;
Robert Carr78c25dd2019-08-15 14:10:33 -0700730}
731
Valerie Hau45e4b3b2019-12-03 10:49:17 -0800732Rect BLASTBufferQueue::computeCrop(const BufferItem& item) {
733 if (item.mScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
Vishnu Nairea0de002020-11-17 17:42:37 -0800734 return GLConsumer::scaleDownCrop(item.mCrop, mSize.width, mSize.height);
Valerie Hau45e4b3b2019-12-03 10:49:17 -0800735 }
736 return item.mCrop;
737}
738
chaviwd7deef72021-10-06 11:53:40 -0500739void BLASTBufferQueue::acquireAndReleaseBuffer() {
Chavi Weingartend00e0f72022-07-14 15:59:20 +0000740 BBQ_TRACE();
chaviwd7deef72021-10-06 11:53:40 -0500741 BufferItem bufferItem;
chaviw6ebdf5f2021-10-14 11:57:22 -0500742 status_t status =
743 mBufferItemConsumer->acquireBuffer(&bufferItem, 0 /* expectedPresent */, false);
744 if (status != OK) {
745 BQA_LOGE("Failed to acquire a buffer in acquireAndReleaseBuffer, err=%s",
746 statusToString(status).c_str());
747 return;
748 }
chaviwd7deef72021-10-06 11:53:40 -0500749 mNumFrameAvailable--;
chaviw6ebdf5f2021-10-14 11:57:22 -0500750 mBufferItemConsumer->releaseBuffer(bufferItem, bufferItem.mFence);
chaviwd7deef72021-10-06 11:53:40 -0500751}
752
Vishnu Nairaef1de92020-10-22 12:15:53 -0700753void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) {
Tianhao Yao4861b102022-02-03 20:18:35 +0000754 std::function<void(SurfaceComposerClient::Transaction*)> prevCallback = nullptr;
755 SurfaceComposerClient::Transaction* prevTransaction = nullptr;
chaviwc1cf4022022-06-03 13:32:33 -0500756
Tianhao Yao4861b102022-02-03 20:18:35 +0000757 {
Chavi Weingartene0237bb2023-02-06 21:48:32 +0000758 UNIQUE_LOCK_WITH_ASSERTION(mMutex);
Chavi Weingartend00e0f72022-07-14 15:59:20 +0000759 BBQ_TRACE();
Chavi Weingartene0237bb2023-02-06 21:48:32 +0000760 bool waitForTransactionCallback = !mSyncedFrameNumbers.empty();
Ady Abrahamd6e409e2023-01-19 16:07:31 -0800761
Tianhao Yao4861b102022-02-03 20:18:35 +0000762 const bool syncTransactionSet = mTransactionReadyCallback != nullptr;
763 BQA_LOGV("onFrameAvailable-start syncTransactionSet=%s", boolToString(syncTransactionSet));
Valerie Haud3b90d22019-11-06 09:37:31 -0800764
Tianhao Yao4861b102022-02-03 20:18:35 +0000765 if (syncTransactionSet) {
Tianhao Yao4861b102022-02-03 20:18:35 +0000766 // If we are going to re-use the same mSyncTransaction, release the buffer that may
767 // already be set in the Transaction. This is to allow us a free slot early to continue
768 // processing a new buffer.
769 if (!mAcquireSingleBuffer) {
770 auto bufferData = mSyncTransaction->getAndClearBuffer(mSurfaceControl);
771 if (bufferData) {
772 BQA_LOGD("Releasing previous buffer when syncing: framenumber=%" PRIu64,
773 bufferData->frameNumber);
774 releaseBuffer(bufferData->generateReleaseCallbackId(),
775 bufferData->acquireFence);
Tianhao Yao4861b102022-02-03 20:18:35 +0000776 }
777 }
chaviw0acd33a2021-11-02 11:55:37 -0500778
Chavi Weingarten3a8f19b2022-12-27 22:00:24 +0000779 if (waitForTransactionCallback) {
780 // We are waiting on a previous sync's transaction callback so allow another sync
781 // transaction to proceed.
782 //
783 // We need to first flush out the transactions that were in between the two syncs.
784 // We do this by merging them into mSyncTransaction so any buffer merging will get
785 // a release callback invoked.
786 while (mNumFrameAvailable > 0) {
787 // flush out the shadow queue
788 acquireAndReleaseBuffer();
789 }
Vishnu Nairb4b484a2023-01-20 10:00:18 -0800790 } else {
791 // Make sure the frame available count is 0 before proceeding with a sync to ensure
792 // the correct frame is used for the sync. The only way mNumFrameAvailable would be
793 // greater than 0 is if we already ran out of buffers previously. This means we
794 // need to flush the buffers before proceeding with the sync.
795 while (mNumFrameAvailable > 0) {
796 BQA_LOGD("waiting until no queued buffers");
797 mCallbackCV.wait(_lock);
798 }
chaviwd7deef72021-10-06 11:53:40 -0500799 }
800 }
801
Tianhao Yao4861b102022-02-03 20:18:35 +0000802 // add to shadow queue
803 mNumFrameAvailable++;
chaviwc1cf4022022-06-03 13:32:33 -0500804 if (waitForTransactionCallback && mNumFrameAvailable >= 2) {
Tianhao Yao4861b102022-02-03 20:18:35 +0000805 acquireAndReleaseBuffer();
806 }
807 ATRACE_INT(mQueuedBufferTrace.c_str(),
808 mNumFrameAvailable + mNumAcquired - mPendingRelease.size());
809
810 BQA_LOGV("onFrameAvailable framenumber=%" PRIu64 " syncTransactionSet=%s",
811 item.mFrameNumber, boolToString(syncTransactionSet));
812
813 if (syncTransactionSet) {
Vishnu Nairb4b484a2023-01-20 10:00:18 -0800814 // Add to mSyncedFrameNumbers before waiting in case any buffers are released
815 // while waiting for a free buffer. The release and commit callback will try to
816 // acquire buffers if there are any available, but we don't want it to acquire
817 // in the case where a sync transaction wants the buffer.
818 mSyncedFrameNumbers.emplace(item.mFrameNumber);
Chavi Weingarten3a8f19b2022-12-27 22:00:24 +0000819 // If there's no available buffer and we're in a sync transaction, we need to wait
820 // instead of returning since we guarantee a buffer will be acquired for the sync.
821 while (acquireNextBufferLocked(mSyncTransaction) == BufferQueue::NO_BUFFER_AVAILABLE) {
822 BQA_LOGD("waiting for available buffer");
823 mCallbackCV.wait(_lock);
824 }
Tianhao Yao4861b102022-02-03 20:18:35 +0000825
826 // Only need a commit callback when syncing to ensure the buffer that's synced has been
827 // sent to SF
Patrick Williams5312ec12024-08-23 16:11:10 -0500828 mSyncTransaction
829 ->addTransactionCommittedCallback(makeTransactionCommittedCallbackThunk(),
830 nullptr);
Tianhao Yao4861b102022-02-03 20:18:35 +0000831 if (mAcquireSingleBuffer) {
832 prevCallback = mTransactionReadyCallback;
833 prevTransaction = mSyncTransaction;
834 mTransactionReadyCallback = nullptr;
835 mSyncTransaction = nullptr;
836 }
chaviwc1cf4022022-06-03 13:32:33 -0500837 } else if (!waitForTransactionCallback) {
Tianhao Yao4861b102022-02-03 20:18:35 +0000838 acquireNextBufferLocked(std::nullopt);
Valerie Hau0188adf2020-02-13 08:29:20 -0800839 }
840 }
Tianhao Yao4861b102022-02-03 20:18:35 +0000841 if (prevCallback) {
842 prevCallback(prevTransaction);
chaviwd7deef72021-10-06 11:53:40 -0500843 }
Valerie Haud3b90d22019-11-06 09:37:31 -0800844}
845
Vishnu Nairaef1de92020-10-22 12:15:53 -0700846void BLASTBufferQueue::onFrameReplaced(const BufferItem& item) {
847 BQA_LOGV("onFrameReplaced framenumber=%" PRIu64, item.mFrameNumber);
848 // Do nothing since we are not storing unacquired buffer items locally.
849}
850
Vishnu Nairadf632b2021-01-07 14:05:08 -0800851void BLASTBufferQueue::onFrameDequeued(const uint64_t bufferId) {
Chavi Weingartene0237bb2023-02-06 21:48:32 +0000852 std::lock_guard _lock{mTimestampMutex};
Vishnu Nairadf632b2021-01-07 14:05:08 -0800853 mDequeueTimestamps[bufferId] = systemTime();
Patrick Williams4b9507d2024-07-25 09:55:52 -0500854};
Vishnu Nairadf632b2021-01-07 14:05:08 -0800855
856void BLASTBufferQueue::onFrameCancelled(const uint64_t bufferId) {
Patrick Williams3ced5382024-08-21 15:39:32 -0500857 std::lock_guard _lock{mTimestampMutex};
858 mDequeueTimestamps.erase(bufferId);
Patrick Williamsf5b42de2024-08-01 16:08:51 -0500859}
Vishnu Nairadf632b2021-01-07 14:05:08 -0800860
Chavi Weingartenc398c012023-04-12 17:26:02 +0000861bool BLASTBufferQueue::syncNextTransaction(
Tianhao Yao4861b102022-02-03 20:18:35 +0000862 std::function<void(SurfaceComposerClient::Transaction*)> callback,
863 bool acquireSingleBuffer) {
Chavi Weingartenc398c012023-04-12 17:26:02 +0000864 LOG_ALWAYS_FATAL_IF(!callback,
865 "BLASTBufferQueue: callback passed in to syncNextTransaction must not be "
866 "NULL");
chaviw3b4bdcf2022-03-17 09:27:03 -0500867
Chavi Weingartenc398c012023-04-12 17:26:02 +0000868 std::lock_guard _lock{mMutex};
869 BBQ_TRACE();
870 if (mTransactionReadyCallback) {
871 ALOGW("Attempting to overwrite transaction callback in syncNextTransaction");
872 return false;
Tianhao Yao4861b102022-02-03 20:18:35 +0000873 }
chaviw3b4bdcf2022-03-17 09:27:03 -0500874
Chavi Weingartenc398c012023-04-12 17:26:02 +0000875 mTransactionReadyCallback = callback;
876 mSyncTransaction = new SurfaceComposerClient::Transaction();
877 mAcquireSingleBuffer = acquireSingleBuffer;
878 return true;
Tianhao Yao4861b102022-02-03 20:18:35 +0000879}
880
881void BLASTBufferQueue::stopContinuousSyncTransaction() {
882 std::function<void(SurfaceComposerClient::Transaction*)> prevCallback = nullptr;
883 SurfaceComposerClient::Transaction* prevTransaction = nullptr;
884 {
885 std::lock_guard _lock{mMutex};
Chavi Weingartenc398c012023-04-12 17:26:02 +0000886 if (mAcquireSingleBuffer || !mTransactionReadyCallback) {
887 ALOGW("Attempting to stop continuous sync when none are active");
888 return;
Tianhao Yao4861b102022-02-03 20:18:35 +0000889 }
Chavi Weingartenc398c012023-04-12 17:26:02 +0000890
891 prevCallback = mTransactionReadyCallback;
892 prevTransaction = mSyncTransaction;
893
Tianhao Yao4861b102022-02-03 20:18:35 +0000894 mTransactionReadyCallback = nullptr;
895 mSyncTransaction = nullptr;
896 mAcquireSingleBuffer = true;
897 }
Chavi Weingartenc398c012023-04-12 17:26:02 +0000898
Tianhao Yao4861b102022-02-03 20:18:35 +0000899 if (prevCallback) {
900 prevCallback(prevTransaction);
901 }
Robert Carr78c25dd2019-08-15 14:10:33 -0700902}
903
Chavi Weingartenc398c012023-04-12 17:26:02 +0000904void BLASTBufferQueue::clearSyncTransaction() {
905 std::lock_guard _lock{mMutex};
906 if (!mAcquireSingleBuffer) {
907 ALOGW("Attempting to clear sync transaction when none are active");
908 return;
909 }
910
911 mTransactionReadyCallback = nullptr;
912 mSyncTransaction = nullptr;
913}
914
Vishnu Nairea0de002020-11-17 17:42:37 -0800915bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) {
Vishnu Nair670b3f72020-09-29 17:52:18 -0700916 if (item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) {
917 // Only reject buffers if scaling mode is freeze.
918 return false;
919 }
920
Chavi Weingarten70670e62023-02-22 17:36:40 +0000921 ui::Size bufferSize = getBufferSize(item);
Vishnu Nairea0de002020-11-17 17:42:37 -0800922 if (mRequestedSize != mSize && mRequestedSize == bufferSize) {
Vishnu Nairea0de002020-11-17 17:42:37 -0800923 return false;
924 }
Vishnu Naire1a42322020-10-02 17:42:04 -0700925
Vishnu Nair670b3f72020-09-29 17:52:18 -0700926 // reject buffers if the buffer size doesn't match.
Vishnu Nairea0de002020-11-17 17:42:37 -0800927 return mSize != bufferSize;
Vishnu Nair670b3f72020-09-29 17:52:18 -0700928}
Vishnu Nairbf255772020-10-16 10:54:41 -0700929
Robert Carr05086b22020-10-13 18:22:51 -0700930class BBQSurface : public Surface {
Robert Carr9c006e02020-10-14 13:41:57 -0700931private:
Vishnu Nair95b6d512021-08-30 15:31:08 -0700932 std::mutex mMutex;
Chavi Weingartene0237bb2023-02-06 21:48:32 +0000933 sp<BLASTBufferQueue> mBbq GUARDED_BY(mMutex);
934 bool mDestroyed GUARDED_BY(mMutex) = false;
Vishnu Nair95b6d512021-08-30 15:31:08 -0700935
Robert Carr05086b22020-10-13 18:22:51 -0700936public:
Vishnu Nair992496b2020-10-22 17:27:21 -0700937 BBQSurface(const sp<IGraphicBufferProducer>& igbp, bool controlledByApp,
938 const sp<IBinder>& scHandle, const sp<BLASTBufferQueue>& bbq)
939 : Surface(igbp, controlledByApp, scHandle), mBbq(bbq) {}
Robert Carr9c006e02020-10-14 13:41:57 -0700940
Robert Carr05086b22020-10-13 18:22:51 -0700941 void allocateBuffers() override {
942 uint32_t reqWidth = mReqWidth ? mReqWidth : mUserWidth;
943 uint32_t reqHeight = mReqHeight ? mReqHeight : mUserHeight;
944 auto gbp = getIGraphicBufferProducer();
945 std::thread ([reqWidth, reqHeight, gbp=getIGraphicBufferProducer(),
946 reqFormat=mReqFormat, reqUsage=mReqUsage] () {
947 gbp->allocateBuffers(reqWidth, reqHeight,
948 reqFormat, reqUsage);
949
950 }).detach();
951 }
Robert Carr9c006e02020-10-14 13:41:57 -0700952
Marin Shalamanovc5986772021-03-16 16:09:49 +0100953 status_t setFrameRate(float frameRate, int8_t compatibility,
954 int8_t changeFrameRateStrategy) override {
Ady Abraham6cdd3fd2023-09-07 18:45:58 -0700955 if (flags::bq_setframerate()) {
956 return Surface::setFrameRate(frameRate, compatibility, changeFrameRateStrategy);
957 }
958
Chavi Weingartene0237bb2023-02-06 21:48:32 +0000959 std::lock_guard _lock{mMutex};
Vishnu Nair95b6d512021-08-30 15:31:08 -0700960 if (mDestroyed) {
961 return DEAD_OBJECT;
962 }
Marin Shalamanovc5986772021-03-16 16:09:49 +0100963 if (!ValidateFrameRate(frameRate, compatibility, changeFrameRateStrategy,
964 "BBQSurface::setFrameRate")) {
Robert Carr9c006e02020-10-14 13:41:57 -0700965 return BAD_VALUE;
966 }
Marin Shalamanovc5986772021-03-16 16:09:49 +0100967 return mBbq->setFrameRate(frameRate, compatibility, changeFrameRateStrategy);
Robert Carr9c006e02020-10-14 13:41:57 -0700968 }
Robert Carr9b611b72020-10-19 12:00:23 -0700969
Ady Abrahamd6e409e2023-01-19 16:07:31 -0800970 status_t setFrameTimelineInfo(uint64_t frameNumber,
971 const FrameTimelineInfo& frameTimelineInfo) override {
Chavi Weingartene0237bb2023-02-06 21:48:32 +0000972 std::lock_guard _lock{mMutex};
Vishnu Nair95b6d512021-08-30 15:31:08 -0700973 if (mDestroyed) {
974 return DEAD_OBJECT;
975 }
Ady Abrahamd6e409e2023-01-19 16:07:31 -0800976 return mBbq->setFrameTimelineInfo(frameNumber, frameTimelineInfo);
Robert Carr9b611b72020-10-19 12:00:23 -0700977 }
Vishnu Nair95b6d512021-08-30 15:31:08 -0700978
979 void destroy() override {
980 Surface::destroy();
981
Chavi Weingartene0237bb2023-02-06 21:48:32 +0000982 std::lock_guard _lock{mMutex};
Vishnu Nair95b6d512021-08-30 15:31:08 -0700983 mDestroyed = true;
984 mBbq = nullptr;
985 }
Robert Carr05086b22020-10-13 18:22:51 -0700986};
987
Robert Carr9c006e02020-10-14 13:41:57 -0700988// TODO: Can we coalesce this with frame updates? Need to confirm
989// no timing issues.
Marin Shalamanov46084422020-10-13 12:33:42 +0200990status_t BLASTBufferQueue::setFrameRate(float frameRate, int8_t compatibility,
991 bool shouldBeSeamless) {
Chavi Weingartene0237bb2023-02-06 21:48:32 +0000992 std::lock_guard _lock{mMutex};
Robert Carr9c006e02020-10-14 13:41:57 -0700993 SurfaceComposerClient::Transaction t;
994
Marin Shalamanov46084422020-10-13 12:33:42 +0200995 return t.setFrameRate(mSurfaceControl, frameRate, compatibility, shouldBeSeamless).apply();
Robert Carr9c006e02020-10-14 13:41:57 -0700996}
997
Ady Abrahamd6e409e2023-01-19 16:07:31 -0800998status_t BLASTBufferQueue::setFrameTimelineInfo(uint64_t frameNumber,
999 const FrameTimelineInfo& frameTimelineInfo) {
1000 ATRACE_FORMAT("%s(%s) frameNumber: %" PRIu64 " vsyncId: %" PRId64, __func__, mName.c_str(),
1001 frameNumber, frameTimelineInfo.vsyncId);
Chavi Weingartene0237bb2023-02-06 21:48:32 +00001002 std::lock_guard _lock{mMutex};
Ady Abrahamd6e409e2023-01-19 16:07:31 -08001003 mPendingFrameTimelines.push({frameNumber, frameTimelineInfo});
Jorim Jaggia3fe67b2020-12-01 00:24:33 +01001004 return OK;
Robert Carr9b611b72020-10-19 12:00:23 -07001005}
1006
Hongguang Chen621ec582021-02-16 15:42:35 -08001007void BLASTBufferQueue::setSidebandStream(const sp<NativeHandle>& stream) {
Chavi Weingartene0237bb2023-02-06 21:48:32 +00001008 std::lock_guard _lock{mMutex};
Hongguang Chen621ec582021-02-16 15:42:35 -08001009 SurfaceComposerClient::Transaction t;
1010
1011 t.setSidebandStream(mSurfaceControl, stream).apply();
1012}
1013
Vishnu Nair992496b2020-10-22 17:27:21 -07001014sp<Surface> BLASTBufferQueue::getSurface(bool includeSurfaceControlHandle) {
Chavi Weingartene0237bb2023-02-06 21:48:32 +00001015 std::lock_guard _lock{mMutex};
Vishnu Nair992496b2020-10-22 17:27:21 -07001016 sp<IBinder> scHandle = nullptr;
1017 if (includeSurfaceControlHandle && mSurfaceControl) {
1018 scHandle = mSurfaceControl->getHandle();
1019 }
1020 return new BBQSurface(mProducer, true, scHandle, this);
Robert Carr05086b22020-10-13 18:22:51 -07001021}
1022
Vishnu Nairc4a40c12020-12-23 09:14:32 -08001023void BLASTBufferQueue::mergeWithNextTransaction(SurfaceComposerClient::Transaction* t,
1024 uint64_t frameNumber) {
1025 std::lock_guard _lock{mMutex};
1026 if (mLastAcquiredFrameNumber >= frameNumber) {
1027 // Apply the transaction since we have already acquired the desired frame.
1028 t->apply();
1029 } else {
chaviwaad6cf52021-03-23 17:27:20 -05001030 mPendingTransactions.emplace_back(frameNumber, *t);
1031 // Clear the transaction so it can't be applied elsewhere.
1032 t->clear();
Vishnu Nairc4a40c12020-12-23 09:14:32 -08001033 }
1034}
1035
chaviw6a195272021-09-03 16:14:25 -05001036void BLASTBufferQueue::applyPendingTransactions(uint64_t frameNumber) {
1037 std::lock_guard _lock{mMutex};
1038
1039 SurfaceComposerClient::Transaction t;
1040 mergePendingTransactions(&t, frameNumber);
Robert Carr79dc06a2022-02-22 15:28:59 -08001041 // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction
1042 t.setApplyToken(mApplyToken).apply(false, true);
chaviw6a195272021-09-03 16:14:25 -05001043}
1044
1045void BLASTBufferQueue::mergePendingTransactions(SurfaceComposerClient::Transaction* t,
1046 uint64_t frameNumber) {
1047 auto mergeTransaction =
1048 [&t, currentFrameNumber = frameNumber](
1049 std::tuple<uint64_t, SurfaceComposerClient::Transaction> pendingTransaction) {
1050 auto& [targetFrameNumber, transaction] = pendingTransaction;
1051 if (currentFrameNumber < targetFrameNumber) {
1052 return false;
1053 }
1054 t->merge(std::move(transaction));
1055 return true;
1056 };
1057
1058 mPendingTransactions.erase(std::remove_if(mPendingTransactions.begin(),
1059 mPendingTransactions.end(), mergeTransaction),
1060 mPendingTransactions.end());
1061}
1062
chaviwd84085a2022-02-08 11:07:04 -06001063SurfaceComposerClient::Transaction* BLASTBufferQueue::gatherPendingTransactions(
1064 uint64_t frameNumber) {
1065 std::lock_guard _lock{mMutex};
1066 SurfaceComposerClient::Transaction* t = new SurfaceComposerClient::Transaction();
1067 mergePendingTransactions(t, frameNumber);
1068 return t;
1069}
1070
Vishnu Nair89496122020-12-14 17:14:53 -08001071// Maintains a single worker thread per process that services a list of runnables.
1072class AsyncWorker : public Singleton<AsyncWorker> {
1073private:
1074 std::thread mThread;
1075 bool mDone = false;
1076 std::deque<std::function<void()>> mRunnables;
1077 std::mutex mMutex;
1078 std::condition_variable mCv;
1079 void run() {
1080 std::unique_lock<std::mutex> lock(mMutex);
1081 while (!mDone) {
Vishnu Nair89496122020-12-14 17:14:53 -08001082 while (!mRunnables.empty()) {
Vishnu Nair51e4dc82021-10-01 15:32:33 -07001083 std::deque<std::function<void()>> runnables = std::move(mRunnables);
1084 mRunnables.clear();
1085 lock.unlock();
1086 // Run outside the lock since the runnable might trigger another
1087 // post to the async worker.
1088 execute(runnables);
1089 lock.lock();
Vishnu Nair89496122020-12-14 17:14:53 -08001090 }
Wonsik Kim567533e2021-05-04 19:31:29 -07001091 mCv.wait(lock);
Vishnu Nair89496122020-12-14 17:14:53 -08001092 }
1093 }
1094
Vishnu Nair51e4dc82021-10-01 15:32:33 -07001095 void execute(std::deque<std::function<void()>>& runnables) {
1096 while (!runnables.empty()) {
1097 std::function<void()> runnable = runnables.front();
1098 runnables.pop_front();
1099 runnable();
1100 }
1101 }
1102
Vishnu Nair89496122020-12-14 17:14:53 -08001103public:
1104 AsyncWorker() : Singleton<AsyncWorker>() { mThread = std::thread(&AsyncWorker::run, this); }
1105
1106 ~AsyncWorker() {
1107 mDone = true;
1108 mCv.notify_all();
1109 if (mThread.joinable()) {
1110 mThread.join();
1111 }
1112 }
1113
1114 void post(std::function<void()> runnable) {
1115 std::unique_lock<std::mutex> lock(mMutex);
1116 mRunnables.emplace_back(std::move(runnable));
1117 mCv.notify_one();
1118 }
1119};
1120ANDROID_SINGLETON_STATIC_INSTANCE(AsyncWorker);
1121
1122// Asynchronously calls ProducerListener functions so we can emulate one way binder calls.
1123class AsyncProducerListener : public BnProducerListener {
1124private:
1125 const sp<IProducerListener> mListener;
1126
1127public:
1128 AsyncProducerListener(const sp<IProducerListener>& listener) : mListener(listener) {}
1129
1130 void onBufferReleased() override {
1131 AsyncWorker::getInstance().post([listener = mListener]() { listener->onBufferReleased(); });
1132 }
1133
1134 void onBuffersDiscarded(const std::vector<int32_t>& slots) override {
1135 AsyncWorker::getInstance().post(
1136 [listener = mListener, slots = slots]() { listener->onBuffersDiscarded(slots); });
1137 }
1138};
1139
1140// Extends the BufferQueueProducer to create a wrapper around the listener so the listener calls
1141// can be non-blocking when the producer is in the client process.
1142class BBQBufferQueueProducer : public BufferQueueProducer {
1143public:
Patrick Williamsca81c052024-08-15 12:38:34 -05001144 BBQBufferQueueProducer(const sp<BufferQueueCore>& core, const wp<BLASTBufferQueue>& bbq)
Brian Lindahlc794b692023-01-31 15:42:47 -07001145 : BufferQueueProducer(core, false /* consumerIsSurfaceFlinger*/),
Patrick Williamsca81c052024-08-15 12:38:34 -05001146 mBLASTBufferQueue(bbq) {}
Vishnu Nair89496122020-12-14 17:14:53 -08001147
1148 status_t connect(const sp<IProducerListener>& listener, int api, bool producerControlledByApp,
1149 QueueBufferOutput* output) override {
1150 if (!listener) {
1151 return BufferQueueProducer::connect(listener, api, producerControlledByApp, output);
1152 }
1153
1154 return BufferQueueProducer::connect(new AsyncProducerListener(listener), api,
1155 producerControlledByApp, output);
1156 }
Vishnu Nair17dde612020-12-28 11:39:59 -08001157
Brian Lindahlc794b692023-01-31 15:42:47 -07001158 // We want to resize the frame history when changing the size of the buffer queue
1159 status_t setMaxDequeuedBufferCount(int maxDequeuedBufferCount) override {
1160 int maxBufferCount;
Patrick Williamsf5b42de2024-08-01 16:08:51 -05001161 if (status_t status = BufferQueueProducer::setMaxDequeuedBufferCount(maxDequeuedBufferCount,
1162 &maxBufferCount);
1163 status != OK) {
1164 return status;
Brian Lindahlc794b692023-01-31 15:42:47 -07001165 }
Patrick Williamsf5b42de2024-08-01 16:08:51 -05001166
1167 sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
1168 if (!bbq) {
1169 return OK;
1170 }
1171
1172 // if we can't determine the max buffer count, then just skip growing the history size
1173 size_t newFrameHistorySize = maxBufferCount + 2; // +2 because triple buffer rendering
1174 // optimize away resizing the frame history unless it will grow
1175 if (newFrameHistorySize > FrameEventHistory::INITIAL_MAX_FRAME_HISTORY) {
1176 ALOGV("increasing frame history size to %zu", newFrameHistorySize);
1177 bbq->resizeFrameEventHistory(newFrameHistorySize);
1178 }
1179
Patrick Williamsf5b42de2024-08-01 16:08:51 -05001180 return OK;
Brian Lindahlc794b692023-01-31 15:42:47 -07001181 }
1182
Vishnu Nair17dde612020-12-28 11:39:59 -08001183 int query(int what, int* value) override {
1184 if (what == NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER) {
1185 *value = 1;
Patrick Williamsf5b42de2024-08-01 16:08:51 -05001186 return OK;
Vishnu Nair17dde612020-12-28 11:39:59 -08001187 }
1188 return BufferQueueProducer::query(what, value);
1189 }
Brian Lindahlc794b692023-01-31 15:42:47 -07001190
1191private:
1192 const wp<BLASTBufferQueue> mBLASTBufferQueue;
Vishnu Nair89496122020-12-14 17:14:53 -08001193};
1194
1195// Similar to BufferQueue::createBufferQueue but creates an adapter specific bufferqueue producer.
1196// This BQP allows invoking client specified ProducerListeners and invoke them asynchronously,
1197// emulating one way binder call behavior. Without this, if the listener calls back into the queue,
1198// we can deadlock.
1199void BLASTBufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
1200 sp<IGraphicBufferConsumer>* outConsumer) {
1201 LOG_ALWAYS_FATAL_IF(outProducer == nullptr, "BLASTBufferQueue: outProducer must not be NULL");
1202 LOG_ALWAYS_FATAL_IF(outConsumer == nullptr, "BLASTBufferQueue: outConsumer must not be NULL");
1203
1204 sp<BufferQueueCore> core(new BufferQueueCore());
1205 LOG_ALWAYS_FATAL_IF(core == nullptr, "BLASTBufferQueue: failed to create BufferQueueCore");
1206
Brian Lindahlc794b692023-01-31 15:42:47 -07001207 sp<IGraphicBufferProducer> producer(new BBQBufferQueueProducer(core, this));
Vishnu Nair89496122020-12-14 17:14:53 -08001208 LOG_ALWAYS_FATAL_IF(producer == nullptr,
1209 "BLASTBufferQueue: failed to create BBQBufferQueueProducer");
1210
Vishnu Nair8b30dd12021-01-25 14:16:54 -08001211 sp<BufferQueueConsumer> consumer(new BufferQueueConsumer(core));
1212 consumer->setAllowExtraAcquire(true);
Vishnu Nair89496122020-12-14 17:14:53 -08001213 LOG_ALWAYS_FATAL_IF(consumer == nullptr,
1214 "BLASTBufferQueue: failed to create BufferQueueConsumer");
1215
1216 *outProducer = producer;
1217 *outConsumer = consumer;
1218}
1219
Brian Lindahlc794b692023-01-31 15:42:47 -07001220void BLASTBufferQueue::resizeFrameEventHistory(size_t newSize) {
1221 // This can be null during creation of the buffer queue, but resizing won't do anything at that
1222 // point in time, so just ignore. This can go away once the class relationships and lifetimes of
1223 // objects are cleaned up with a major refactor of BufferQueue as a whole.
1224 if (mBufferItemConsumer != nullptr) {
1225 std::unique_lock _lock{mMutex};
1226 mBufferItemConsumer->resizeFrameEventHistory(newSize);
1227 }
1228}
1229
chaviw497e81c2021-02-04 17:09:47 -08001230PixelFormat BLASTBufferQueue::convertBufferFormat(PixelFormat& format) {
1231 PixelFormat convertedFormat = format;
1232 switch (format) {
1233 case PIXEL_FORMAT_TRANSPARENT:
1234 case PIXEL_FORMAT_TRANSLUCENT:
1235 convertedFormat = PIXEL_FORMAT_RGBA_8888;
1236 break;
1237 case PIXEL_FORMAT_OPAQUE:
1238 convertedFormat = PIXEL_FORMAT_RGBX_8888;
1239 break;
1240 }
1241 return convertedFormat;
1242}
1243
Robert Carr82d07c92021-05-10 11:36:43 -07001244uint32_t BLASTBufferQueue::getLastTransformHint() const {
Chavi Weingartene0237bb2023-02-06 21:48:32 +00001245 std::lock_guard _lock{mMutex};
Robert Carr82d07c92021-05-10 11:36:43 -07001246 if (mSurfaceControl != nullptr) {
1247 return mSurfaceControl->getTransformHint();
1248 } else {
1249 return 0;
1250 }
1251}
1252
chaviw0b020f82021-08-20 12:00:47 -05001253uint64_t BLASTBufferQueue::getLastAcquiredFrameNum() {
Chavi Weingartene0237bb2023-02-06 21:48:32 +00001254 std::lock_guard _lock{mMutex};
chaviw0b020f82021-08-20 12:00:47 -05001255 return mLastAcquiredFrameNumber;
1256}
1257
Vishnu Nair1e8bf102021-12-28 14:36:59 -08001258bool BLASTBufferQueue::isSameSurfaceControl(const sp<SurfaceControl>& surfaceControl) const {
Chavi Weingartene0237bb2023-02-06 21:48:32 +00001259 std::lock_guard _lock{mMutex};
Vishnu Nair1e8bf102021-12-28 14:36:59 -08001260 return SurfaceControl::isSameSurface(mSurfaceControl, surfaceControl);
1261}
1262
Patrick Williamsf1e5df12022-10-17 21:37:42 +00001263void BLASTBufferQueue::setTransactionHangCallback(
1264 std::function<void(const std::string&)> callback) {
Chavi Weingartene0237bb2023-02-06 21:48:32 +00001265 std::lock_guard _lock{mMutex};
Patrick Williams7c9fa272024-08-30 12:38:43 +00001266 mTransactionHangCallback = std::move(callback);
Robert Carr4c1b6462021-12-21 10:30:50 -08001267}
1268
Vishnu Nairaf15fab2024-07-30 08:59:26 -07001269void BLASTBufferQueue::setApplyToken(sp<IBinder> applyToken) {
1270 std::lock_guard _lock{mMutex};
1271 mApplyToken = std::move(applyToken);
1272}
1273
Patrick Williams7c9fa272024-08-30 12:38:43 +00001274#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
1275
1276BLASTBufferQueue::BufferReleaseReader::BufferReleaseReader(
1277 std::unique_ptr<gui::BufferReleaseChannel::ConsumerEndpoint> endpoint)
1278 : mEndpoint{std::move(endpoint)} {
1279 mEpollFd = android::base::unique_fd{epoll_create1(0)};
1280 LOG_ALWAYS_FATAL_IF(!mEpollFd.ok(),
1281 "Failed to create buffer release epoll file descriptor. errno=%d "
1282 "message='%s'",
1283 errno, strerror(errno));
1284
1285 epoll_event registerEndpointFd{};
1286 registerEndpointFd.events = EPOLLIN;
1287 registerEndpointFd.data.fd = mEndpoint->getFd();
1288 status_t status =
1289 epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, mEndpoint->getFd(), &registerEndpointFd);
1290 LOG_ALWAYS_FATAL_IF(status == -1,
1291 "Failed to register buffer release consumer file descriptor with epoll. "
1292 "errno=%d message='%s'",
1293 errno, strerror(errno));
1294
1295 mEventFd = android::base::unique_fd(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
1296 LOG_ALWAYS_FATAL_IF(!mEventFd.ok(),
1297 "Failed to create buffer release event file descriptor. errno=%d "
1298 "message='%s'",
1299 errno, strerror(errno));
1300
1301 epoll_event registerEventFd{};
1302 registerEventFd.events = EPOLLIN;
1303 registerEventFd.data.fd = mEventFd.get();
1304 status = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, mEventFd.get(), &registerEventFd);
1305 LOG_ALWAYS_FATAL_IF(status == -1,
1306 "Failed to register buffer release event file descriptor with epoll. "
1307 "errno=%d message='%s'",
1308 errno, strerror(errno));
1309}
1310
1311BLASTBufferQueue::BufferReleaseReader& BLASTBufferQueue::BufferReleaseReader::operator=(
1312 BufferReleaseReader&& other) {
1313 if (this != &other) {
1314 ftl::FakeGuard guard{mMutex};
1315 ftl::FakeGuard otherGuard{other.mMutex};
1316 mEndpoint = std::move(other.mEndpoint);
1317 mEpollFd = std::move(other.mEpollFd);
1318 mEventFd = std::move(other.mEventFd);
1319 }
1320 return *this;
1321}
1322
1323status_t BLASTBufferQueue::BufferReleaseReader::readBlocking(ReleaseCallbackId& outId,
1324 sp<Fence>& outFence,
1325 uint32_t& outMaxAcquiredBufferCount) {
1326 epoll_event event{};
1327 while (true) {
1328 int eventCount = epoll_wait(mEpollFd.get(), &event, 1 /* maxevents */, -1 /* timeout */);
1329 if (eventCount == 1) {
1330 break;
1331 }
1332 if (eventCount == -1 && errno != EINTR) {
1333 ALOGE("epoll_wait error while waiting for buffer release. errno=%d message='%s'", errno,
1334 strerror(errno));
1335 }
1336 }
1337
1338 if (event.data.fd == mEventFd.get()) {
1339 uint64_t value;
1340 if (read(mEventFd.get(), &value, sizeof(uint64_t)) == -1 && errno != EWOULDBLOCK) {
1341 ALOGE("error while reading from eventfd. errno=%d message='%s'", errno,
1342 strerror(errno));
1343 }
1344 return WOULD_BLOCK;
1345 }
1346
1347 std::lock_guard lock{mMutex};
1348 return mEndpoint->readReleaseFence(outId, outFence, outMaxAcquiredBufferCount);
1349}
1350
1351void BLASTBufferQueue::BufferReleaseReader::interruptBlockingRead() {
1352 uint64_t value = 1;
1353 if (write(mEventFd.get(), &value, sizeof(uint64_t)) == -1) {
1354 ALOGE("failed to notify dequeue event. errno=%d message='%s'", errno, strerror(errno));
1355 }
1356}
1357
1358void BLASTBufferQueue::BufferReleaseThread::start(const sp<BLASTBufferQueue>& bbq) {
1359 mRunning = std::make_shared<std::atomic_bool>(true);
1360 mReader = bbq->mBufferReleaseReader;
1361 std::thread([running = mRunning, reader = mReader, weakBbq = wp<BLASTBufferQueue>(bbq)]() {
1362 pthread_setname_np(pthread_self(), "BufferReleaseThread");
1363 while (*running) {
1364 ReleaseCallbackId id;
1365 sp<Fence> fence;
1366 uint32_t maxAcquiredBufferCount;
1367 if (status_t status = reader->readBlocking(id, fence, maxAcquiredBufferCount);
1368 status != OK) {
1369 continue;
1370 }
1371 sp<BLASTBufferQueue> bbq = weakBbq.promote();
1372 if (!bbq) {
1373 return;
1374 }
1375 bbq->releaseBufferCallback(id, fence, maxAcquiredBufferCount);
1376 }
1377 }).detach();
1378}
1379
1380BLASTBufferQueue::BufferReleaseThread::~BufferReleaseThread() {
1381 *mRunning = false;
1382 mReader->interruptBlockingRead();
1383}
1384
1385#endif
1386
Robert Carr78c25dd2019-08-15 14:10:33 -07001387} // namespace android