1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker * Copyright (C) 2019 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker *
4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker *
8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker *
10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker */
16*38e8c45fSAndroid Build Coastguard Worker
17*38e8c45fSAndroid Build Coastguard Worker #undef LOG_TAG
18*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "BLASTBufferQueue"
19*38e8c45fSAndroid Build Coastguard Worker
20*38e8c45fSAndroid Build Coastguard Worker #define ATRACE_TAG ATRACE_TAG_GRAPHICS
21*38e8c45fSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
22*38e8c45fSAndroid Build Coastguard Worker
23*38e8c45fSAndroid Build Coastguard Worker #include <com_android_graphics_libgui_flags.h>
24*38e8c45fSAndroid Build Coastguard Worker #include <cutils/atomic.h>
25*38e8c45fSAndroid Build Coastguard Worker #include <ftl/fake_guard.h>
26*38e8c45fSAndroid Build Coastguard Worker #include <gui/BLASTBufferQueue.h>
27*38e8c45fSAndroid Build Coastguard Worker #include <gui/BufferItemConsumer.h>
28*38e8c45fSAndroid Build Coastguard Worker #include <gui/BufferQueueConsumer.h>
29*38e8c45fSAndroid Build Coastguard Worker #include <gui/BufferQueueCore.h>
30*38e8c45fSAndroid Build Coastguard Worker #include <gui/BufferQueueProducer.h>
31*38e8c45fSAndroid Build Coastguard Worker #include <sys/epoll.h>
32*38e8c45fSAndroid Build Coastguard Worker #include <sys/eventfd.h>
33*38e8c45fSAndroid Build Coastguard Worker
34*38e8c45fSAndroid Build Coastguard Worker #include <gui/FrameRateUtils.h>
35*38e8c45fSAndroid Build Coastguard Worker #include <gui/GLConsumer.h>
36*38e8c45fSAndroid Build Coastguard Worker #include <gui/IProducerListener.h>
37*38e8c45fSAndroid Build Coastguard Worker #include <gui/Surface.h>
38*38e8c45fSAndroid Build Coastguard Worker #include <gui/TraceUtils.h>
39*38e8c45fSAndroid Build Coastguard Worker #include <utils/Singleton.h>
40*38e8c45fSAndroid Build Coastguard Worker #include <utils/Trace.h>
41*38e8c45fSAndroid Build Coastguard Worker
42*38e8c45fSAndroid Build Coastguard Worker #include <private/gui/ComposerService.h>
43*38e8c45fSAndroid Build Coastguard Worker #include <private/gui/ComposerServiceAIDL.h>
44*38e8c45fSAndroid Build Coastguard Worker
45*38e8c45fSAndroid Build Coastguard Worker #include <android-base/thread_annotations.h>
46*38e8c45fSAndroid Build Coastguard Worker
47*38e8c45fSAndroid Build Coastguard Worker #include <com_android_graphics_libgui_flags.h>
48*38e8c45fSAndroid Build Coastguard Worker
49*38e8c45fSAndroid Build Coastguard Worker using namespace com::android::graphics::libgui;
50*38e8c45fSAndroid Build Coastguard Worker using namespace std::chrono_literals;
51*38e8c45fSAndroid Build Coastguard Worker
52*38e8c45fSAndroid Build Coastguard Worker namespace {
53*38e8c45fSAndroid Build Coastguard Worker
54*38e8c45fSAndroid Build Coastguard Worker #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
55*38e8c45fSAndroid Build Coastguard Worker template <class Mutex>
56*38e8c45fSAndroid Build Coastguard Worker class UnlockGuard {
57*38e8c45fSAndroid Build Coastguard Worker public:
UnlockGuard(Mutex & lock)58*38e8c45fSAndroid Build Coastguard Worker explicit UnlockGuard(Mutex& lock) : mLock{lock} { mLock.unlock(); }
59*38e8c45fSAndroid Build Coastguard Worker
~UnlockGuard()60*38e8c45fSAndroid Build Coastguard Worker ~UnlockGuard() { mLock.lock(); }
61*38e8c45fSAndroid Build Coastguard Worker
62*38e8c45fSAndroid Build Coastguard Worker UnlockGuard(const UnlockGuard&) = delete;
63*38e8c45fSAndroid Build Coastguard Worker UnlockGuard& operator=(const UnlockGuard&) = delete;
64*38e8c45fSAndroid Build Coastguard Worker
65*38e8c45fSAndroid Build Coastguard Worker private:
66*38e8c45fSAndroid Build Coastguard Worker Mutex& mLock;
67*38e8c45fSAndroid Build Coastguard Worker };
68*38e8c45fSAndroid Build Coastguard Worker #endif
69*38e8c45fSAndroid Build Coastguard Worker
boolToString(bool b)70*38e8c45fSAndroid Build Coastguard Worker inline const char* boolToString(bool b) {
71*38e8c45fSAndroid Build Coastguard Worker return b ? "true" : "false";
72*38e8c45fSAndroid Build Coastguard Worker }
73*38e8c45fSAndroid Build Coastguard Worker
74*38e8c45fSAndroid Build Coastguard Worker } // namespace
75*38e8c45fSAndroid Build Coastguard Worker
76*38e8c45fSAndroid Build Coastguard Worker namespace android {
77*38e8c45fSAndroid Build Coastguard Worker
78*38e8c45fSAndroid Build Coastguard Worker // Macros to include adapter info in log messages
79*38e8c45fSAndroid Build Coastguard Worker #define BQA_LOGD(x, ...) \
80*38e8c45fSAndroid Build Coastguard Worker ALOGD("[%s](f:%u,a:%u) " x, mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__)
81*38e8c45fSAndroid Build Coastguard Worker #define BQA_LOGV(x, ...) \
82*38e8c45fSAndroid Build Coastguard Worker ALOGV("[%s](f:%u,a:%u) " x, mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__)
83*38e8c45fSAndroid Build Coastguard Worker // enable logs for a single layer
84*38e8c45fSAndroid Build Coastguard Worker //#define BQA_LOGV(x, ...) \
85*38e8c45fSAndroid Build Coastguard Worker // ALOGV_IF((strstr(mName.c_str(), "SurfaceView") != nullptr), "[%s](f:%u,a:%u) " x, \
86*38e8c45fSAndroid Build Coastguard Worker // mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__)
87*38e8c45fSAndroid Build Coastguard Worker #define BQA_LOGE(x, ...) \
88*38e8c45fSAndroid Build Coastguard Worker ALOGE("[%s](f:%u,a:%u) " x, mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__)
89*38e8c45fSAndroid Build Coastguard Worker
90*38e8c45fSAndroid Build Coastguard Worker #define BBQ_TRACE(x, ...) \
91*38e8c45fSAndroid Build Coastguard Worker ATRACE_FORMAT("%s - %s(f:%u,a:%u)" x, __FUNCTION__, mName.c_str(), mNumFrameAvailable, \
92*38e8c45fSAndroid Build Coastguard Worker mNumAcquired, ##__VA_ARGS__)
93*38e8c45fSAndroid Build Coastguard Worker
94*38e8c45fSAndroid Build Coastguard Worker #define UNIQUE_LOCK_WITH_ASSERTION(mutex) \
95*38e8c45fSAndroid Build Coastguard Worker std::unique_lock _lock{mutex}; \
96*38e8c45fSAndroid Build Coastguard Worker base::ScopedLockAssertion assumeLocked(mutex);
97*38e8c45fSAndroid Build Coastguard Worker
onDisconnect()98*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferItemConsumer::onDisconnect() {
99*38e8c45fSAndroid Build Coastguard Worker Mutex::Autolock lock(mMutex);
100*38e8c45fSAndroid Build Coastguard Worker mPreviouslyConnected = mCurrentlyConnected;
101*38e8c45fSAndroid Build Coastguard Worker mCurrentlyConnected = false;
102*38e8c45fSAndroid Build Coastguard Worker if (mPreviouslyConnected) {
103*38e8c45fSAndroid Build Coastguard Worker mDisconnectEvents.push(mCurrentFrameNumber);
104*38e8c45fSAndroid Build Coastguard Worker }
105*38e8c45fSAndroid Build Coastguard Worker mFrameEventHistory.onDisconnect();
106*38e8c45fSAndroid Build Coastguard Worker }
107*38e8c45fSAndroid Build Coastguard Worker
addAndGetFrameTimestamps(const NewFrameEventsEntry * newTimestamps,FrameEventHistoryDelta * outDelta)108*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferItemConsumer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
109*38e8c45fSAndroid Build Coastguard Worker FrameEventHistoryDelta* outDelta) {
110*38e8c45fSAndroid Build Coastguard Worker Mutex::Autolock lock(mMutex);
111*38e8c45fSAndroid Build Coastguard Worker if (newTimestamps) {
112*38e8c45fSAndroid Build Coastguard Worker // BufferQueueProducer only adds a new timestamp on
113*38e8c45fSAndroid Build Coastguard Worker // queueBuffer
114*38e8c45fSAndroid Build Coastguard Worker mCurrentFrameNumber = newTimestamps->frameNumber;
115*38e8c45fSAndroid Build Coastguard Worker mFrameEventHistory.addQueue(*newTimestamps);
116*38e8c45fSAndroid Build Coastguard Worker }
117*38e8c45fSAndroid Build Coastguard Worker if (outDelta) {
118*38e8c45fSAndroid Build Coastguard Worker // frame event histories will be processed
119*38e8c45fSAndroid Build Coastguard Worker // only after the producer connects and requests
120*38e8c45fSAndroid Build Coastguard Worker // deltas for the first time. Forward this intent
121*38e8c45fSAndroid Build Coastguard Worker // to SF-side to turn event processing back on
122*38e8c45fSAndroid Build Coastguard Worker mPreviouslyConnected = mCurrentlyConnected;
123*38e8c45fSAndroid Build Coastguard Worker mCurrentlyConnected = true;
124*38e8c45fSAndroid Build Coastguard Worker mFrameEventHistory.getAndResetDelta(outDelta);
125*38e8c45fSAndroid Build Coastguard Worker }
126*38e8c45fSAndroid Build Coastguard Worker }
127*38e8c45fSAndroid Build Coastguard Worker
updateFrameTimestamps(uint64_t frameNumber,uint64_t previousFrameNumber,nsecs_t refreshStartTime,const sp<Fence> & glDoneFence,const sp<Fence> & presentFence,const sp<Fence> & prevReleaseFence,CompositorTiming compositorTiming,nsecs_t latchTime,nsecs_t dequeueReadyTime)128*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferItemConsumer::updateFrameTimestamps(
129*38e8c45fSAndroid Build Coastguard Worker uint64_t frameNumber, uint64_t previousFrameNumber, nsecs_t refreshStartTime,
130*38e8c45fSAndroid Build Coastguard Worker const sp<Fence>& glDoneFence, const sp<Fence>& presentFence,
131*38e8c45fSAndroid Build Coastguard Worker const sp<Fence>& prevReleaseFence, CompositorTiming compositorTiming, nsecs_t latchTime,
132*38e8c45fSAndroid Build Coastguard Worker nsecs_t dequeueReadyTime) {
133*38e8c45fSAndroid Build Coastguard Worker Mutex::Autolock lock(mMutex);
134*38e8c45fSAndroid Build Coastguard Worker
135*38e8c45fSAndroid Build Coastguard Worker // if the producer is not connected, don't bother updating,
136*38e8c45fSAndroid Build Coastguard Worker // the next producer that connects won't access this frame event
137*38e8c45fSAndroid Build Coastguard Worker if (!mCurrentlyConnected) return;
138*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<FenceTime> glDoneFenceTime = std::make_shared<FenceTime>(glDoneFence);
139*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<FenceTime> presentFenceTime = std::make_shared<FenceTime>(presentFence);
140*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<FenceTime> releaseFenceTime = std::make_shared<FenceTime>(prevReleaseFence);
141*38e8c45fSAndroid Build Coastguard Worker
142*38e8c45fSAndroid Build Coastguard Worker mFrameEventHistory.addLatch(frameNumber, latchTime);
143*38e8c45fSAndroid Build Coastguard Worker if (flags::frametimestamps_previousrelease()) {
144*38e8c45fSAndroid Build Coastguard Worker if (previousFrameNumber > 0) {
145*38e8c45fSAndroid Build Coastguard Worker mFrameEventHistory.addRelease(previousFrameNumber, dequeueReadyTime,
146*38e8c45fSAndroid Build Coastguard Worker std::move(releaseFenceTime));
147*38e8c45fSAndroid Build Coastguard Worker }
148*38e8c45fSAndroid Build Coastguard Worker } else {
149*38e8c45fSAndroid Build Coastguard Worker mFrameEventHistory.addRelease(frameNumber, dequeueReadyTime, std::move(releaseFenceTime));
150*38e8c45fSAndroid Build Coastguard Worker }
151*38e8c45fSAndroid Build Coastguard Worker
152*38e8c45fSAndroid Build Coastguard Worker mFrameEventHistory.addPreComposition(frameNumber, refreshStartTime);
153*38e8c45fSAndroid Build Coastguard Worker mFrameEventHistory.addPostComposition(frameNumber, glDoneFenceTime, presentFenceTime,
154*38e8c45fSAndroid Build Coastguard Worker compositorTiming);
155*38e8c45fSAndroid Build Coastguard Worker }
156*38e8c45fSAndroid Build Coastguard Worker
getConnectionEvents(uint64_t frameNumber,bool * needsDisconnect)157*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferItemConsumer::getConnectionEvents(uint64_t frameNumber, bool* needsDisconnect) {
158*38e8c45fSAndroid Build Coastguard Worker bool disconnect = false;
159*38e8c45fSAndroid Build Coastguard Worker Mutex::Autolock lock(mMutex);
160*38e8c45fSAndroid Build Coastguard Worker while (!mDisconnectEvents.empty() && mDisconnectEvents.front() <= frameNumber) {
161*38e8c45fSAndroid Build Coastguard Worker disconnect = true;
162*38e8c45fSAndroid Build Coastguard Worker mDisconnectEvents.pop();
163*38e8c45fSAndroid Build Coastguard Worker }
164*38e8c45fSAndroid Build Coastguard Worker if (needsDisconnect != nullptr) *needsDisconnect = disconnect;
165*38e8c45fSAndroid Build Coastguard Worker }
166*38e8c45fSAndroid Build Coastguard Worker
onSidebandStreamChanged()167*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferItemConsumer::onSidebandStreamChanged() {
168*38e8c45fSAndroid Build Coastguard Worker sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
169*38e8c45fSAndroid Build Coastguard Worker if (bbq != nullptr) {
170*38e8c45fSAndroid Build Coastguard Worker sp<NativeHandle> stream = getSidebandStream();
171*38e8c45fSAndroid Build Coastguard Worker bbq->setSidebandStream(stream);
172*38e8c45fSAndroid Build Coastguard Worker }
173*38e8c45fSAndroid Build Coastguard Worker }
174*38e8c45fSAndroid Build Coastguard Worker
175*38e8c45fSAndroid Build Coastguard Worker #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE)
onSetFrameRate(float frameRate,int8_t compatibility,int8_t changeFrameRateStrategy)176*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferItemConsumer::onSetFrameRate(float frameRate, int8_t compatibility,
177*38e8c45fSAndroid Build Coastguard Worker int8_t changeFrameRateStrategy) {
178*38e8c45fSAndroid Build Coastguard Worker sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
179*38e8c45fSAndroid Build Coastguard Worker if (bbq != nullptr) {
180*38e8c45fSAndroid Build Coastguard Worker bbq->setFrameRate(frameRate, compatibility, changeFrameRateStrategy);
181*38e8c45fSAndroid Build Coastguard Worker }
182*38e8c45fSAndroid Build Coastguard Worker }
183*38e8c45fSAndroid Build Coastguard Worker #endif
184*38e8c45fSAndroid Build Coastguard Worker
resizeFrameEventHistory(size_t newSize)185*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferItemConsumer::resizeFrameEventHistory(size_t newSize) {
186*38e8c45fSAndroid Build Coastguard Worker Mutex::Autolock lock(mMutex);
187*38e8c45fSAndroid Build Coastguard Worker mFrameEventHistory.resize(newSize);
188*38e8c45fSAndroid Build Coastguard Worker }
189*38e8c45fSAndroid Build Coastguard Worker
BLASTBufferQueue(const std::string & name,bool updateDestinationFrame)190*38e8c45fSAndroid Build Coastguard Worker BLASTBufferQueue::BLASTBufferQueue(const std::string& name, bool updateDestinationFrame)
191*38e8c45fSAndroid Build Coastguard Worker : mSurfaceControl(nullptr),
192*38e8c45fSAndroid Build Coastguard Worker mSize(1, 1),
193*38e8c45fSAndroid Build Coastguard Worker mRequestedSize(mSize),
194*38e8c45fSAndroid Build Coastguard Worker mFormat(PIXEL_FORMAT_RGBA_8888),
195*38e8c45fSAndroid Build Coastguard Worker mTransactionReadyCallback(nullptr),
196*38e8c45fSAndroid Build Coastguard Worker mSyncTransaction(nullptr),
197*38e8c45fSAndroid Build Coastguard Worker mUpdateDestinationFrame(updateDestinationFrame) {
198*38e8c45fSAndroid Build Coastguard Worker createBufferQueue(&mProducer, &mConsumer);
199*38e8c45fSAndroid Build Coastguard Worker #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
200*38e8c45fSAndroid Build Coastguard Worker mBufferItemConsumer = new BLASTBufferItemConsumer(mProducer, mConsumer,
201*38e8c45fSAndroid Build Coastguard Worker GraphicBuffer::USAGE_HW_COMPOSER |
202*38e8c45fSAndroid Build Coastguard Worker GraphicBuffer::USAGE_HW_TEXTURE,
203*38e8c45fSAndroid Build Coastguard Worker 1, false, this);
204*38e8c45fSAndroid Build Coastguard Worker #else
205*38e8c45fSAndroid Build Coastguard Worker mBufferItemConsumer = new BLASTBufferItemConsumer(mConsumer,
206*38e8c45fSAndroid Build Coastguard Worker GraphicBuffer::USAGE_HW_COMPOSER |
207*38e8c45fSAndroid Build Coastguard Worker GraphicBuffer::USAGE_HW_TEXTURE,
208*38e8c45fSAndroid Build Coastguard Worker 1, false, this);
209*38e8c45fSAndroid Build Coastguard Worker #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
210*38e8c45fSAndroid Build Coastguard Worker // since the adapter is in the client process, set dequeue timeout
211*38e8c45fSAndroid Build Coastguard Worker // explicitly so that dequeueBuffer will block
212*38e8c45fSAndroid Build Coastguard Worker mProducer->setDequeueTimeout(std::numeric_limits<int64_t>::max());
213*38e8c45fSAndroid Build Coastguard Worker
214*38e8c45fSAndroid Build Coastguard Worker static std::atomic<uint32_t> nextId = 0;
215*38e8c45fSAndroid Build Coastguard Worker mProducerId = nextId++;
216*38e8c45fSAndroid Build Coastguard Worker mName = name + "#" + std::to_string(mProducerId);
217*38e8c45fSAndroid Build Coastguard Worker auto consumerName = mName + "(BLAST Consumer)" + std::to_string(mProducerId);
218*38e8c45fSAndroid Build Coastguard Worker mQueuedBufferTrace = "QueuedBuffer - " + mName + "BLAST#" + std::to_string(mProducerId);
219*38e8c45fSAndroid Build Coastguard Worker mBufferItemConsumer->setName(String8(consumerName.c_str()));
220*38e8c45fSAndroid Build Coastguard Worker mBufferItemConsumer->setFrameAvailableListener(this);
221*38e8c45fSAndroid Build Coastguard Worker
222*38e8c45fSAndroid Build Coastguard Worker ComposerServiceAIDL::getComposerService()->getMaxAcquiredBufferCount(&mMaxAcquiredBuffers);
223*38e8c45fSAndroid Build Coastguard Worker mBufferItemConsumer->setMaxAcquiredBufferCount(mMaxAcquiredBuffers);
224*38e8c45fSAndroid Build Coastguard Worker mCurrentMaxAcquiredBufferCount = mMaxAcquiredBuffers;
225*38e8c45fSAndroid Build Coastguard Worker mNumAcquired = 0;
226*38e8c45fSAndroid Build Coastguard Worker mNumFrameAvailable = 0;
227*38e8c45fSAndroid Build Coastguard Worker
228*38e8c45fSAndroid Build Coastguard Worker TransactionCompletedListener::getInstance()->addQueueStallListener(
229*38e8c45fSAndroid Build Coastguard Worker [&](const std::string& reason) {
230*38e8c45fSAndroid Build Coastguard Worker std::function<void(const std::string&)> callbackCopy;
231*38e8c45fSAndroid Build Coastguard Worker {
232*38e8c45fSAndroid Build Coastguard Worker std::unique_lock _lock{mMutex};
233*38e8c45fSAndroid Build Coastguard Worker callbackCopy = mTransactionHangCallback;
234*38e8c45fSAndroid Build Coastguard Worker }
235*38e8c45fSAndroid Build Coastguard Worker if (callbackCopy) callbackCopy(reason);
236*38e8c45fSAndroid Build Coastguard Worker },
237*38e8c45fSAndroid Build Coastguard Worker this);
238*38e8c45fSAndroid Build Coastguard Worker
239*38e8c45fSAndroid Build Coastguard Worker #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
240*38e8c45fSAndroid Build Coastguard Worker gui::BufferReleaseChannel::open(mName, mBufferReleaseConsumer, mBufferReleaseProducer);
241*38e8c45fSAndroid Build Coastguard Worker mBufferReleaseReader.emplace(*this);
242*38e8c45fSAndroid Build Coastguard Worker #endif
243*38e8c45fSAndroid Build Coastguard Worker
244*38e8c45fSAndroid Build Coastguard Worker BQA_LOGV("BLASTBufferQueue created");
245*38e8c45fSAndroid Build Coastguard Worker }
246*38e8c45fSAndroid Build Coastguard Worker
BLASTBufferQueue(const std::string & name,const sp<SurfaceControl> & surface,int width,int height,int32_t format)247*38e8c45fSAndroid Build Coastguard Worker BLASTBufferQueue::BLASTBufferQueue(const std::string& name, const sp<SurfaceControl>& surface,
248*38e8c45fSAndroid Build Coastguard Worker int width, int height, int32_t format)
249*38e8c45fSAndroid Build Coastguard Worker : BLASTBufferQueue(name) {
250*38e8c45fSAndroid Build Coastguard Worker update(surface, width, height, format);
251*38e8c45fSAndroid Build Coastguard Worker }
252*38e8c45fSAndroid Build Coastguard Worker
~BLASTBufferQueue()253*38e8c45fSAndroid Build Coastguard Worker BLASTBufferQueue::~BLASTBufferQueue() {
254*38e8c45fSAndroid Build Coastguard Worker TransactionCompletedListener::getInstance()->removeQueueStallListener(this);
255*38e8c45fSAndroid Build Coastguard Worker if (mPendingTransactions.empty()) {
256*38e8c45fSAndroid Build Coastguard Worker return;
257*38e8c45fSAndroid Build Coastguard Worker }
258*38e8c45fSAndroid Build Coastguard Worker BQA_LOGE("Applying pending transactions on dtor %d",
259*38e8c45fSAndroid Build Coastguard Worker static_cast<uint32_t>(mPendingTransactions.size()));
260*38e8c45fSAndroid Build Coastguard Worker SurfaceComposerClient::Transaction t;
261*38e8c45fSAndroid Build Coastguard Worker mergePendingTransactions(&t, std::numeric_limits<uint64_t>::max() /* frameNumber */);
262*38e8c45fSAndroid Build Coastguard Worker // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction
263*38e8c45fSAndroid Build Coastguard Worker t.setApplyToken(mApplyToken).apply(false, true);
264*38e8c45fSAndroid Build Coastguard Worker
265*38e8c45fSAndroid Build Coastguard Worker if (mTransactionReadyCallback) {
266*38e8c45fSAndroid Build Coastguard Worker mTransactionReadyCallback(mSyncTransaction);
267*38e8c45fSAndroid Build Coastguard Worker }
268*38e8c45fSAndroid Build Coastguard Worker }
269*38e8c45fSAndroid Build Coastguard Worker
onFirstRef()270*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::onFirstRef() {
271*38e8c45fSAndroid Build Coastguard Worker // safe default, most producers are expected to override this
272*38e8c45fSAndroid Build Coastguard Worker mProducer->setMaxDequeuedBufferCount(2);
273*38e8c45fSAndroid Build Coastguard Worker }
274*38e8c45fSAndroid Build Coastguard Worker
update(const sp<SurfaceControl> & surface,uint32_t width,uint32_t height,int32_t format)275*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height,
276*38e8c45fSAndroid Build Coastguard Worker int32_t format) {
277*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(surface == nullptr, "BLASTBufferQueue: mSurfaceControl must not be NULL");
278*38e8c45fSAndroid Build Coastguard Worker
279*38e8c45fSAndroid Build Coastguard Worker std::lock_guard _lock{mMutex};
280*38e8c45fSAndroid Build Coastguard Worker if (mFormat != format) {
281*38e8c45fSAndroid Build Coastguard Worker mFormat = format;
282*38e8c45fSAndroid Build Coastguard Worker mBufferItemConsumer->setDefaultBufferFormat(convertBufferFormat(format));
283*38e8c45fSAndroid Build Coastguard Worker }
284*38e8c45fSAndroid Build Coastguard Worker
285*38e8c45fSAndroid Build Coastguard Worker const bool surfaceControlChanged = !SurfaceControl::isSameSurface(mSurfaceControl, surface);
286*38e8c45fSAndroid Build Coastguard Worker if (surfaceControlChanged && mSurfaceControl != nullptr) {
287*38e8c45fSAndroid Build Coastguard Worker BQA_LOGD("Updating SurfaceControl without recreating BBQ");
288*38e8c45fSAndroid Build Coastguard Worker }
289*38e8c45fSAndroid Build Coastguard Worker
290*38e8c45fSAndroid Build Coastguard Worker // Always update the native object even though they might have the same layer handle, so we can
291*38e8c45fSAndroid Build Coastguard Worker // get the updated transform hint from WM.
292*38e8c45fSAndroid Build Coastguard Worker mSurfaceControl = surface;
293*38e8c45fSAndroid Build Coastguard Worker SurfaceComposerClient::Transaction t;
294*38e8c45fSAndroid Build Coastguard Worker bool applyTransaction = false;
295*38e8c45fSAndroid Build Coastguard Worker if (surfaceControlChanged) {
296*38e8c45fSAndroid Build Coastguard Worker #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
297*38e8c45fSAndroid Build Coastguard Worker updateBufferReleaseProducer();
298*38e8c45fSAndroid Build Coastguard Worker #endif
299*38e8c45fSAndroid Build Coastguard Worker t.setFlags(mSurfaceControl, layer_state_t::eEnableBackpressure,
300*38e8c45fSAndroid Build Coastguard Worker layer_state_t::eEnableBackpressure);
301*38e8c45fSAndroid Build Coastguard Worker // Migrate the picture profile handle to the new surface control.
302*38e8c45fSAndroid Build Coastguard Worker if (com_android_graphics_libgui_flags_apply_picture_profiles() &&
303*38e8c45fSAndroid Build Coastguard Worker mPictureProfileHandle.has_value()) {
304*38e8c45fSAndroid Build Coastguard Worker t.setPictureProfileHandle(mSurfaceControl, *mPictureProfileHandle);
305*38e8c45fSAndroid Build Coastguard Worker }
306*38e8c45fSAndroid Build Coastguard Worker applyTransaction = true;
307*38e8c45fSAndroid Build Coastguard Worker }
308*38e8c45fSAndroid Build Coastguard Worker mTransformHint = mSurfaceControl->getTransformHint();
309*38e8c45fSAndroid Build Coastguard Worker mBufferItemConsumer->setTransformHint(mTransformHint);
310*38e8c45fSAndroid Build Coastguard Worker BQA_LOGV("update width=%d height=%d format=%d mTransformHint=%d", width, height, format,
311*38e8c45fSAndroid Build Coastguard Worker mTransformHint);
312*38e8c45fSAndroid Build Coastguard Worker
313*38e8c45fSAndroid Build Coastguard Worker ui::Size newSize(width, height);
314*38e8c45fSAndroid Build Coastguard Worker if (mRequestedSize != newSize) {
315*38e8c45fSAndroid Build Coastguard Worker mRequestedSize.set(newSize);
316*38e8c45fSAndroid Build Coastguard Worker mBufferItemConsumer->setDefaultBufferSize(mRequestedSize.width, mRequestedSize.height);
317*38e8c45fSAndroid Build Coastguard Worker if (mLastBufferInfo.scalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) {
318*38e8c45fSAndroid Build Coastguard Worker // If the buffer supports scaling, update the frame immediately since the client may
319*38e8c45fSAndroid Build Coastguard Worker // want to scale the existing buffer to the new size.
320*38e8c45fSAndroid Build Coastguard Worker mSize = mRequestedSize;
321*38e8c45fSAndroid Build Coastguard Worker if (mUpdateDestinationFrame) {
322*38e8c45fSAndroid Build Coastguard Worker t.setDestinationFrame(mSurfaceControl, Rect(newSize));
323*38e8c45fSAndroid Build Coastguard Worker applyTransaction = true;
324*38e8c45fSAndroid Build Coastguard Worker }
325*38e8c45fSAndroid Build Coastguard Worker }
326*38e8c45fSAndroid Build Coastguard Worker }
327*38e8c45fSAndroid Build Coastguard Worker if (applyTransaction) {
328*38e8c45fSAndroid Build Coastguard Worker // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction
329*38e8c45fSAndroid Build Coastguard Worker t.setApplyToken(mApplyToken).apply(false /* synchronous */, true /* oneWay */);
330*38e8c45fSAndroid Build Coastguard Worker }
331*38e8c45fSAndroid Build Coastguard Worker }
332*38e8c45fSAndroid Build Coastguard Worker
findMatchingStat(const std::vector<SurfaceControlStats> & stats,const sp<SurfaceControl> & sc)333*38e8c45fSAndroid Build Coastguard Worker static std::optional<SurfaceControlStats> findMatchingStat(
334*38e8c45fSAndroid Build Coastguard Worker const std::vector<SurfaceControlStats>& stats, const sp<SurfaceControl>& sc) {
335*38e8c45fSAndroid Build Coastguard Worker for (auto stat : stats) {
336*38e8c45fSAndroid Build Coastguard Worker if (SurfaceControl::isSameSurface(sc, stat.surfaceControl)) {
337*38e8c45fSAndroid Build Coastguard Worker return stat;
338*38e8c45fSAndroid Build Coastguard Worker }
339*38e8c45fSAndroid Build Coastguard Worker }
340*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
341*38e8c45fSAndroid Build Coastguard Worker }
342*38e8c45fSAndroid Build Coastguard Worker
makeTransactionCommittedCallbackThunk()343*38e8c45fSAndroid Build Coastguard Worker TransactionCompletedCallbackTakesContext BLASTBufferQueue::makeTransactionCommittedCallbackThunk() {
344*38e8c45fSAndroid Build Coastguard Worker return [bbq = sp<BLASTBufferQueue>::fromExisting(
345*38e8c45fSAndroid Build Coastguard Worker this)](void* /*context*/, nsecs_t latchTime, const sp<Fence>& presentFence,
346*38e8c45fSAndroid Build Coastguard Worker const std::vector<SurfaceControlStats>& stats) {
347*38e8c45fSAndroid Build Coastguard Worker bbq->transactionCommittedCallback(latchTime, presentFence, stats);
348*38e8c45fSAndroid Build Coastguard Worker };
349*38e8c45fSAndroid Build Coastguard Worker }
350*38e8c45fSAndroid Build Coastguard Worker
transactionCommittedCallback(nsecs_t,const sp<Fence> &,const std::vector<SurfaceControlStats> & stats)351*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::transactionCommittedCallback(nsecs_t /*latchTime*/,
352*38e8c45fSAndroid Build Coastguard Worker const sp<Fence>& /*presentFence*/,
353*38e8c45fSAndroid Build Coastguard Worker const std::vector<SurfaceControlStats>& stats) {
354*38e8c45fSAndroid Build Coastguard Worker {
355*38e8c45fSAndroid Build Coastguard Worker std::lock_guard _lock{mMutex};
356*38e8c45fSAndroid Build Coastguard Worker BBQ_TRACE();
357*38e8c45fSAndroid Build Coastguard Worker BQA_LOGV("transactionCommittedCallback");
358*38e8c45fSAndroid Build Coastguard Worker if (!mSurfaceControlsWithPendingCallback.empty()) {
359*38e8c45fSAndroid Build Coastguard Worker sp<SurfaceControl> pendingSC = mSurfaceControlsWithPendingCallback.front();
360*38e8c45fSAndroid Build Coastguard Worker std::optional<SurfaceControlStats> stat = findMatchingStat(stats, pendingSC);
361*38e8c45fSAndroid Build Coastguard Worker if (stat) {
362*38e8c45fSAndroid Build Coastguard Worker uint64_t currFrameNumber = stat->frameEventStats.frameNumber;
363*38e8c45fSAndroid Build Coastguard Worker
364*38e8c45fSAndroid Build Coastguard Worker // We need to check if we were waiting for a transaction callback in order to
365*38e8c45fSAndroid Build Coastguard Worker // process any pending buffers and unblock. It's possible to get transaction
366*38e8c45fSAndroid Build Coastguard Worker // callbacks for previous requests so we need to ensure that there are no pending
367*38e8c45fSAndroid Build Coastguard Worker // frame numbers that were in a sync. We remove the frame from mSyncedFrameNumbers
368*38e8c45fSAndroid Build Coastguard Worker // set and then check if it's empty. If there are no more pending syncs, we can
369*38e8c45fSAndroid Build Coastguard Worker // proceed with flushing the shadow queue.
370*38e8c45fSAndroid Build Coastguard Worker mSyncedFrameNumbers.erase(currFrameNumber);
371*38e8c45fSAndroid Build Coastguard Worker if (mSyncedFrameNumbers.empty()) {
372*38e8c45fSAndroid Build Coastguard Worker flushShadowQueue();
373*38e8c45fSAndroid Build Coastguard Worker }
374*38e8c45fSAndroid Build Coastguard Worker } else {
375*38e8c45fSAndroid Build Coastguard Worker BQA_LOGE("Failed to find matching SurfaceControl in transactionCommittedCallback");
376*38e8c45fSAndroid Build Coastguard Worker }
377*38e8c45fSAndroid Build Coastguard Worker } else {
378*38e8c45fSAndroid Build Coastguard Worker BQA_LOGE("No matching SurfaceControls found: mSurfaceControlsWithPendingCallback was "
379*38e8c45fSAndroid Build Coastguard Worker "empty.");
380*38e8c45fSAndroid Build Coastguard Worker }
381*38e8c45fSAndroid Build Coastguard Worker }
382*38e8c45fSAndroid Build Coastguard Worker }
383*38e8c45fSAndroid Build Coastguard Worker
makeTransactionCallbackThunk()384*38e8c45fSAndroid Build Coastguard Worker TransactionCompletedCallbackTakesContext BLASTBufferQueue::makeTransactionCallbackThunk() {
385*38e8c45fSAndroid Build Coastguard Worker return [bbq = sp<BLASTBufferQueue>::fromExisting(
386*38e8c45fSAndroid Build Coastguard Worker this)](void* /*context*/, nsecs_t latchTime, const sp<Fence>& presentFence,
387*38e8c45fSAndroid Build Coastguard Worker const std::vector<SurfaceControlStats>& stats) {
388*38e8c45fSAndroid Build Coastguard Worker bbq->transactionCallback(latchTime, presentFence, stats);
389*38e8c45fSAndroid Build Coastguard Worker };
390*38e8c45fSAndroid Build Coastguard Worker }
391*38e8c45fSAndroid Build Coastguard Worker
transactionCallback(nsecs_t,const sp<Fence> &,const std::vector<SurfaceControlStats> & stats)392*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence>& /*presentFence*/,
393*38e8c45fSAndroid Build Coastguard Worker const std::vector<SurfaceControlStats>& stats) {
394*38e8c45fSAndroid Build Coastguard Worker {
395*38e8c45fSAndroid Build Coastguard Worker std::lock_guard _lock{mMutex};
396*38e8c45fSAndroid Build Coastguard Worker BBQ_TRACE();
397*38e8c45fSAndroid Build Coastguard Worker BQA_LOGV("transactionCallback");
398*38e8c45fSAndroid Build Coastguard Worker
399*38e8c45fSAndroid Build Coastguard Worker if (!mSurfaceControlsWithPendingCallback.empty()) {
400*38e8c45fSAndroid Build Coastguard Worker sp<SurfaceControl> pendingSC = mSurfaceControlsWithPendingCallback.front();
401*38e8c45fSAndroid Build Coastguard Worker mSurfaceControlsWithPendingCallback.pop();
402*38e8c45fSAndroid Build Coastguard Worker std::optional<SurfaceControlStats> statsOptional = findMatchingStat(stats, pendingSC);
403*38e8c45fSAndroid Build Coastguard Worker if (statsOptional) {
404*38e8c45fSAndroid Build Coastguard Worker SurfaceControlStats stat = *statsOptional;
405*38e8c45fSAndroid Build Coastguard Worker if (stat.transformHint) {
406*38e8c45fSAndroid Build Coastguard Worker mTransformHint = *stat.transformHint;
407*38e8c45fSAndroid Build Coastguard Worker mBufferItemConsumer->setTransformHint(mTransformHint);
408*38e8c45fSAndroid Build Coastguard Worker BQA_LOGV("updated mTransformHint=%d", mTransformHint);
409*38e8c45fSAndroid Build Coastguard Worker }
410*38e8c45fSAndroid Build Coastguard Worker // Update frametime stamps if the frame was latched and presented, indicated by a
411*38e8c45fSAndroid Build Coastguard Worker // valid latch time.
412*38e8c45fSAndroid Build Coastguard Worker if (stat.latchTime > 0) {
413*38e8c45fSAndroid Build Coastguard Worker mBufferItemConsumer
414*38e8c45fSAndroid Build Coastguard Worker ->updateFrameTimestamps(stat.frameEventStats.frameNumber,
415*38e8c45fSAndroid Build Coastguard Worker stat.frameEventStats.previousFrameNumber,
416*38e8c45fSAndroid Build Coastguard Worker stat.frameEventStats.refreshStartTime,
417*38e8c45fSAndroid Build Coastguard Worker stat.frameEventStats.gpuCompositionDoneFence,
418*38e8c45fSAndroid Build Coastguard Worker stat.presentFence, stat.previousReleaseFence,
419*38e8c45fSAndroid Build Coastguard Worker stat.frameEventStats.compositorTiming,
420*38e8c45fSAndroid Build Coastguard Worker stat.latchTime,
421*38e8c45fSAndroid Build Coastguard Worker stat.frameEventStats.dequeueReadyTime);
422*38e8c45fSAndroid Build Coastguard Worker }
423*38e8c45fSAndroid Build Coastguard Worker auto currFrameNumber = stat.frameEventStats.frameNumber;
424*38e8c45fSAndroid Build Coastguard Worker std::vector<ReleaseCallbackId> staleReleases;
425*38e8c45fSAndroid Build Coastguard Worker for (const auto& [key, value]: mSubmitted) {
426*38e8c45fSAndroid Build Coastguard Worker if (currFrameNumber > key.framenumber) {
427*38e8c45fSAndroid Build Coastguard Worker staleReleases.push_back(key);
428*38e8c45fSAndroid Build Coastguard Worker }
429*38e8c45fSAndroid Build Coastguard Worker }
430*38e8c45fSAndroid Build Coastguard Worker for (const auto& staleRelease : staleReleases) {
431*38e8c45fSAndroid Build Coastguard Worker releaseBufferCallbackLocked(staleRelease,
432*38e8c45fSAndroid Build Coastguard Worker stat.previousReleaseFence
433*38e8c45fSAndroid Build Coastguard Worker ? stat.previousReleaseFence
434*38e8c45fSAndroid Build Coastguard Worker : Fence::NO_FENCE,
435*38e8c45fSAndroid Build Coastguard Worker stat.currentMaxAcquiredBufferCount,
436*38e8c45fSAndroid Build Coastguard Worker true /* fakeRelease */);
437*38e8c45fSAndroid Build Coastguard Worker }
438*38e8c45fSAndroid Build Coastguard Worker } else {
439*38e8c45fSAndroid Build Coastguard Worker BQA_LOGE("Failed to find matching SurfaceControl in transactionCallback");
440*38e8c45fSAndroid Build Coastguard Worker }
441*38e8c45fSAndroid Build Coastguard Worker } else {
442*38e8c45fSAndroid Build Coastguard Worker BQA_LOGE("No matching SurfaceControls found: mSurfaceControlsWithPendingCallback was "
443*38e8c45fSAndroid Build Coastguard Worker "empty.");
444*38e8c45fSAndroid Build Coastguard Worker }
445*38e8c45fSAndroid Build Coastguard Worker }
446*38e8c45fSAndroid Build Coastguard Worker }
447*38e8c45fSAndroid Build Coastguard Worker
flushShadowQueue()448*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::flushShadowQueue() {
449*38e8c45fSAndroid Build Coastguard Worker BQA_LOGV("flushShadowQueue");
450*38e8c45fSAndroid Build Coastguard Worker int numFramesToFlush = mNumFrameAvailable;
451*38e8c45fSAndroid Build Coastguard Worker while (numFramesToFlush > 0) {
452*38e8c45fSAndroid Build Coastguard Worker acquireNextBufferLocked(std::nullopt);
453*38e8c45fSAndroid Build Coastguard Worker numFramesToFlush--;
454*38e8c45fSAndroid Build Coastguard Worker }
455*38e8c45fSAndroid Build Coastguard Worker }
456*38e8c45fSAndroid Build Coastguard Worker
457*38e8c45fSAndroid Build Coastguard Worker // Unlike transactionCallbackThunk the release buffer callback does not extend the life of the
458*38e8c45fSAndroid Build Coastguard Worker // BBQ. This is because if the BBQ is destroyed, then the buffers will be released by the client.
459*38e8c45fSAndroid Build Coastguard Worker // So we pass in a weak pointer to the BBQ and if it still alive, then we release the buffer.
460*38e8c45fSAndroid Build Coastguard Worker // Otherwise, this is a no-op.
makeReleaseBufferCallbackThunk()461*38e8c45fSAndroid Build Coastguard Worker ReleaseBufferCallback BLASTBufferQueue::makeReleaseBufferCallbackThunk() {
462*38e8c45fSAndroid Build Coastguard Worker return [weakBbq = wp<BLASTBufferQueue>::fromExisting(
463*38e8c45fSAndroid Build Coastguard Worker this)](const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
464*38e8c45fSAndroid Build Coastguard Worker std::optional<uint32_t> currentMaxAcquiredBufferCount) {
465*38e8c45fSAndroid Build Coastguard Worker sp<BLASTBufferQueue> bbq = weakBbq.promote();
466*38e8c45fSAndroid Build Coastguard Worker if (!bbq) {
467*38e8c45fSAndroid Build Coastguard Worker ALOGV("releaseBufferCallbackThunk %s blastBufferQueue is dead", id.to_string().c_str());
468*38e8c45fSAndroid Build Coastguard Worker return;
469*38e8c45fSAndroid Build Coastguard Worker }
470*38e8c45fSAndroid Build Coastguard Worker bbq->releaseBufferCallback(id, releaseFence, currentMaxAcquiredBufferCount);
471*38e8c45fSAndroid Build Coastguard Worker #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
472*38e8c45fSAndroid Build Coastguard Worker bbq->drainBufferReleaseConsumer();
473*38e8c45fSAndroid Build Coastguard Worker #endif
474*38e8c45fSAndroid Build Coastguard Worker };
475*38e8c45fSAndroid Build Coastguard Worker }
476*38e8c45fSAndroid Build Coastguard Worker
releaseBufferCallback(const ReleaseCallbackId & id,const sp<Fence> & releaseFence,std::optional<uint32_t> currentMaxAcquiredBufferCount)477*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::releaseBufferCallback(
478*38e8c45fSAndroid Build Coastguard Worker const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
479*38e8c45fSAndroid Build Coastguard Worker std::optional<uint32_t> currentMaxAcquiredBufferCount) {
480*38e8c45fSAndroid Build Coastguard Worker std::lock_guard _lock{mMutex};
481*38e8c45fSAndroid Build Coastguard Worker BBQ_TRACE();
482*38e8c45fSAndroid Build Coastguard Worker releaseBufferCallbackLocked(id, releaseFence, currentMaxAcquiredBufferCount,
483*38e8c45fSAndroid Build Coastguard Worker false /* fakeRelease */);
484*38e8c45fSAndroid Build Coastguard Worker }
485*38e8c45fSAndroid Build Coastguard Worker
releaseBufferCallbackLocked(const ReleaseCallbackId & id,const sp<Fence> & releaseFence,std::optional<uint32_t> currentMaxAcquiredBufferCount,bool fakeRelease)486*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::releaseBufferCallbackLocked(
487*38e8c45fSAndroid Build Coastguard Worker const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
488*38e8c45fSAndroid Build Coastguard Worker std::optional<uint32_t> currentMaxAcquiredBufferCount, bool fakeRelease) {
489*38e8c45fSAndroid Build Coastguard Worker ATRACE_CALL();
490*38e8c45fSAndroid Build Coastguard Worker BQA_LOGV("releaseBufferCallback %s", id.to_string().c_str());
491*38e8c45fSAndroid Build Coastguard Worker
492*38e8c45fSAndroid Build Coastguard Worker // Calculate how many buffers we need to hold before we release them back
493*38e8c45fSAndroid Build Coastguard Worker // to the buffer queue. This will prevent higher latency when we are running
494*38e8c45fSAndroid Build Coastguard Worker // on a lower refresh rate than the max supported. We only do that for EGL
495*38e8c45fSAndroid Build Coastguard Worker // clients as others don't care about latency
496*38e8c45fSAndroid Build Coastguard Worker const auto it = mSubmitted.find(id);
497*38e8c45fSAndroid Build Coastguard Worker const bool isEGL = it != mSubmitted.end() && it->second.mApi == NATIVE_WINDOW_API_EGL;
498*38e8c45fSAndroid Build Coastguard Worker
499*38e8c45fSAndroid Build Coastguard Worker if (currentMaxAcquiredBufferCount) {
500*38e8c45fSAndroid Build Coastguard Worker mCurrentMaxAcquiredBufferCount = *currentMaxAcquiredBufferCount;
501*38e8c45fSAndroid Build Coastguard Worker }
502*38e8c45fSAndroid Build Coastguard Worker
503*38e8c45fSAndroid Build Coastguard Worker const uint32_t numPendingBuffersToHold =
504*38e8c45fSAndroid Build Coastguard Worker isEGL ? std::max(0, mMaxAcquiredBuffers - (int32_t)mCurrentMaxAcquiredBufferCount) : 0;
505*38e8c45fSAndroid Build Coastguard Worker
506*38e8c45fSAndroid Build Coastguard Worker auto rb = ReleasedBuffer{id, releaseFence};
507*38e8c45fSAndroid Build Coastguard Worker if (std::find(mPendingRelease.begin(), mPendingRelease.end(), rb) == mPendingRelease.end()) {
508*38e8c45fSAndroid Build Coastguard Worker mPendingRelease.emplace_back(rb);
509*38e8c45fSAndroid Build Coastguard Worker if (fakeRelease) {
510*38e8c45fSAndroid Build Coastguard Worker BQA_LOGE("Faking releaseBufferCallback from transactionCompleteCallback %" PRIu64,
511*38e8c45fSAndroid Build Coastguard Worker id.framenumber);
512*38e8c45fSAndroid Build Coastguard Worker BBQ_TRACE("FakeReleaseCallback");
513*38e8c45fSAndroid Build Coastguard Worker }
514*38e8c45fSAndroid Build Coastguard Worker }
515*38e8c45fSAndroid Build Coastguard Worker
516*38e8c45fSAndroid Build Coastguard Worker // Release all buffers that are beyond the ones that we need to hold
517*38e8c45fSAndroid Build Coastguard Worker while (mPendingRelease.size() > numPendingBuffersToHold) {
518*38e8c45fSAndroid Build Coastguard Worker const auto releasedBuffer = mPendingRelease.front();
519*38e8c45fSAndroid Build Coastguard Worker mPendingRelease.pop_front();
520*38e8c45fSAndroid Build Coastguard Worker releaseBuffer(releasedBuffer.callbackId, releasedBuffer.releaseFence);
521*38e8c45fSAndroid Build Coastguard Worker // Don't process the transactions here if mSyncedFrameNumbers is not empty. That means
522*38e8c45fSAndroid Build Coastguard Worker // are still transactions that have sync buffers in them that have not been applied or
523*38e8c45fSAndroid Build Coastguard Worker // dropped. Instead, let onFrameAvailable handle processing them since it will merge with
524*38e8c45fSAndroid Build Coastguard Worker // the syncTransaction.
525*38e8c45fSAndroid Build Coastguard Worker if (mSyncedFrameNumbers.empty()) {
526*38e8c45fSAndroid Build Coastguard Worker acquireNextBufferLocked(std::nullopt);
527*38e8c45fSAndroid Build Coastguard Worker }
528*38e8c45fSAndroid Build Coastguard Worker }
529*38e8c45fSAndroid Build Coastguard Worker
530*38e8c45fSAndroid Build Coastguard Worker ATRACE_INT("PendingRelease", mPendingRelease.size());
531*38e8c45fSAndroid Build Coastguard Worker ATRACE_INT(mQueuedBufferTrace.c_str(),
532*38e8c45fSAndroid Build Coastguard Worker mNumFrameAvailable + mNumAcquired - mPendingRelease.size());
533*38e8c45fSAndroid Build Coastguard Worker mCallbackCV.notify_all();
534*38e8c45fSAndroid Build Coastguard Worker }
535*38e8c45fSAndroid Build Coastguard Worker
releaseBuffer(const ReleaseCallbackId & callbackId,const sp<Fence> & releaseFence)536*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::releaseBuffer(const ReleaseCallbackId& callbackId,
537*38e8c45fSAndroid Build Coastguard Worker const sp<Fence>& releaseFence) {
538*38e8c45fSAndroid Build Coastguard Worker auto it = mSubmitted.find(callbackId);
539*38e8c45fSAndroid Build Coastguard Worker if (it == mSubmitted.end()) {
540*38e8c45fSAndroid Build Coastguard Worker return;
541*38e8c45fSAndroid Build Coastguard Worker }
542*38e8c45fSAndroid Build Coastguard Worker mNumAcquired--;
543*38e8c45fSAndroid Build Coastguard Worker BBQ_TRACE("frame=%" PRIu64, callbackId.framenumber);
544*38e8c45fSAndroid Build Coastguard Worker BQA_LOGV("released %s", callbackId.to_string().c_str());
545*38e8c45fSAndroid Build Coastguard Worker mBufferItemConsumer->releaseBuffer(it->second, releaseFence);
546*38e8c45fSAndroid Build Coastguard Worker mSubmitted.erase(it);
547*38e8c45fSAndroid Build Coastguard Worker // Remove the frame number from mSyncedFrameNumbers since we can get a release callback
548*38e8c45fSAndroid Build Coastguard Worker // without getting a transaction committed if the buffer was dropped.
549*38e8c45fSAndroid Build Coastguard Worker mSyncedFrameNumbers.erase(callbackId.framenumber);
550*38e8c45fSAndroid Build Coastguard Worker }
551*38e8c45fSAndroid Build Coastguard Worker
getBufferSize(const BufferItem & item)552*38e8c45fSAndroid Build Coastguard Worker static ui::Size getBufferSize(const BufferItem& item) {
553*38e8c45fSAndroid Build Coastguard Worker uint32_t bufWidth = item.mGraphicBuffer->getWidth();
554*38e8c45fSAndroid Build Coastguard Worker uint32_t bufHeight = item.mGraphicBuffer->getHeight();
555*38e8c45fSAndroid Build Coastguard Worker
556*38e8c45fSAndroid Build Coastguard Worker // Take the buffer's orientation into account
557*38e8c45fSAndroid Build Coastguard Worker if (item.mTransform & ui::Transform::ROT_90) {
558*38e8c45fSAndroid Build Coastguard Worker std::swap(bufWidth, bufHeight);
559*38e8c45fSAndroid Build Coastguard Worker }
560*38e8c45fSAndroid Build Coastguard Worker return ui::Size(bufWidth, bufHeight);
561*38e8c45fSAndroid Build Coastguard Worker }
562*38e8c45fSAndroid Build Coastguard Worker
acquireNextBufferLocked(const std::optional<SurfaceComposerClient::Transaction * > transaction)563*38e8c45fSAndroid Build Coastguard Worker status_t BLASTBufferQueue::acquireNextBufferLocked(
564*38e8c45fSAndroid Build Coastguard Worker const std::optional<SurfaceComposerClient::Transaction*> transaction) {
565*38e8c45fSAndroid Build Coastguard Worker // Check if we have frames available and we have not acquired the maximum number of buffers.
566*38e8c45fSAndroid Build Coastguard Worker // Even with this check, the consumer can fail to acquire an additional buffer if the consumer
567*38e8c45fSAndroid Build Coastguard Worker // has already acquired (mMaxAcquiredBuffers + 1) and the new buffer is not droppable. In this
568*38e8c45fSAndroid Build Coastguard Worker // case mBufferItemConsumer->acquireBuffer will return with NO_BUFFER_AVAILABLE.
569*38e8c45fSAndroid Build Coastguard Worker if (mNumFrameAvailable == 0) {
570*38e8c45fSAndroid Build Coastguard Worker BQA_LOGV("Can't acquire next buffer. No available frames");
571*38e8c45fSAndroid Build Coastguard Worker return BufferQueue::NO_BUFFER_AVAILABLE;
572*38e8c45fSAndroid Build Coastguard Worker }
573*38e8c45fSAndroid Build Coastguard Worker
574*38e8c45fSAndroid Build Coastguard Worker if (mNumAcquired >= (mMaxAcquiredBuffers + 2)) {
575*38e8c45fSAndroid Build Coastguard Worker BQA_LOGV("Can't acquire next buffer. Already acquired max frames %d max:%d + 2",
576*38e8c45fSAndroid Build Coastguard Worker mNumAcquired, mMaxAcquiredBuffers);
577*38e8c45fSAndroid Build Coastguard Worker return BufferQueue::NO_BUFFER_AVAILABLE;
578*38e8c45fSAndroid Build Coastguard Worker }
579*38e8c45fSAndroid Build Coastguard Worker
580*38e8c45fSAndroid Build Coastguard Worker if (mSurfaceControl == nullptr) {
581*38e8c45fSAndroid Build Coastguard Worker BQA_LOGE("ERROR : surface control is null");
582*38e8c45fSAndroid Build Coastguard Worker return NAME_NOT_FOUND;
583*38e8c45fSAndroid Build Coastguard Worker }
584*38e8c45fSAndroid Build Coastguard Worker
585*38e8c45fSAndroid Build Coastguard Worker SurfaceComposerClient::Transaction localTransaction;
586*38e8c45fSAndroid Build Coastguard Worker bool applyTransaction = true;
587*38e8c45fSAndroid Build Coastguard Worker SurfaceComposerClient::Transaction* t = &localTransaction;
588*38e8c45fSAndroid Build Coastguard Worker if (transaction) {
589*38e8c45fSAndroid Build Coastguard Worker t = *transaction;
590*38e8c45fSAndroid Build Coastguard Worker applyTransaction = false;
591*38e8c45fSAndroid Build Coastguard Worker }
592*38e8c45fSAndroid Build Coastguard Worker
593*38e8c45fSAndroid Build Coastguard Worker BufferItem bufferItem;
594*38e8c45fSAndroid Build Coastguard Worker
595*38e8c45fSAndroid Build Coastguard Worker status_t status =
596*38e8c45fSAndroid Build Coastguard Worker mBufferItemConsumer->acquireBuffer(&bufferItem, 0 /* expectedPresent */, false);
597*38e8c45fSAndroid Build Coastguard Worker if (status == BufferQueue::NO_BUFFER_AVAILABLE) {
598*38e8c45fSAndroid Build Coastguard Worker BQA_LOGV("Failed to acquire a buffer, err=NO_BUFFER_AVAILABLE");
599*38e8c45fSAndroid Build Coastguard Worker return status;
600*38e8c45fSAndroid Build Coastguard Worker } else if (status != OK) {
601*38e8c45fSAndroid Build Coastguard Worker BQA_LOGE("Failed to acquire a buffer, err=%s", statusToString(status).c_str());
602*38e8c45fSAndroid Build Coastguard Worker return status;
603*38e8c45fSAndroid Build Coastguard Worker }
604*38e8c45fSAndroid Build Coastguard Worker
605*38e8c45fSAndroid Build Coastguard Worker auto buffer = bufferItem.mGraphicBuffer;
606*38e8c45fSAndroid Build Coastguard Worker mNumFrameAvailable--;
607*38e8c45fSAndroid Build Coastguard Worker BBQ_TRACE("frame=%" PRIu64, bufferItem.mFrameNumber);
608*38e8c45fSAndroid Build Coastguard Worker
609*38e8c45fSAndroid Build Coastguard Worker if (buffer == nullptr) {
610*38e8c45fSAndroid Build Coastguard Worker mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE);
611*38e8c45fSAndroid Build Coastguard Worker BQA_LOGE("Buffer was empty");
612*38e8c45fSAndroid Build Coastguard Worker return BAD_VALUE;
613*38e8c45fSAndroid Build Coastguard Worker }
614*38e8c45fSAndroid Build Coastguard Worker
615*38e8c45fSAndroid Build Coastguard Worker if (rejectBuffer(bufferItem)) {
616*38e8c45fSAndroid Build Coastguard Worker BQA_LOGE("rejecting buffer:active_size=%dx%d, requested_size=%dx%d "
617*38e8c45fSAndroid Build Coastguard Worker "buffer{size=%dx%d transform=%d}",
618*38e8c45fSAndroid Build Coastguard Worker mSize.width, mSize.height, mRequestedSize.width, mRequestedSize.height,
619*38e8c45fSAndroid Build Coastguard Worker buffer->getWidth(), buffer->getHeight(), bufferItem.mTransform);
620*38e8c45fSAndroid Build Coastguard Worker mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE);
621*38e8c45fSAndroid Build Coastguard Worker return acquireNextBufferLocked(transaction);
622*38e8c45fSAndroid Build Coastguard Worker }
623*38e8c45fSAndroid Build Coastguard Worker
624*38e8c45fSAndroid Build Coastguard Worker mNumAcquired++;
625*38e8c45fSAndroid Build Coastguard Worker mLastAcquiredFrameNumber = bufferItem.mFrameNumber;
626*38e8c45fSAndroid Build Coastguard Worker ReleaseCallbackId releaseCallbackId(buffer->getId(), mLastAcquiredFrameNumber);
627*38e8c45fSAndroid Build Coastguard Worker mSubmitted[releaseCallbackId] = bufferItem;
628*38e8c45fSAndroid Build Coastguard Worker
629*38e8c45fSAndroid Build Coastguard Worker bool needsDisconnect = false;
630*38e8c45fSAndroid Build Coastguard Worker mBufferItemConsumer->getConnectionEvents(bufferItem.mFrameNumber, &needsDisconnect);
631*38e8c45fSAndroid Build Coastguard Worker
632*38e8c45fSAndroid Build Coastguard Worker // if producer disconnected before, notify SurfaceFlinger
633*38e8c45fSAndroid Build Coastguard Worker if (needsDisconnect) {
634*38e8c45fSAndroid Build Coastguard Worker t->notifyProducerDisconnect(mSurfaceControl);
635*38e8c45fSAndroid Build Coastguard Worker }
636*38e8c45fSAndroid Build Coastguard Worker
637*38e8c45fSAndroid Build Coastguard Worker // Only update mSize for destination bounds if the incoming buffer matches the requested size.
638*38e8c45fSAndroid Build Coastguard Worker // Otherwise, it could cause stretching since the destination bounds will update before the
639*38e8c45fSAndroid Build Coastguard Worker // buffer with the new size is acquired.
640*38e8c45fSAndroid Build Coastguard Worker if (mRequestedSize == getBufferSize(bufferItem) ||
641*38e8c45fSAndroid Build Coastguard Worker bufferItem.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) {
642*38e8c45fSAndroid Build Coastguard Worker mSize = mRequestedSize;
643*38e8c45fSAndroid Build Coastguard Worker }
644*38e8c45fSAndroid Build Coastguard Worker Rect crop = computeCrop(bufferItem);
645*38e8c45fSAndroid Build Coastguard Worker mLastBufferInfo.update(true /* hasBuffer */, bufferItem.mGraphicBuffer->getWidth(),
646*38e8c45fSAndroid Build Coastguard Worker bufferItem.mGraphicBuffer->getHeight(), bufferItem.mTransform,
647*38e8c45fSAndroid Build Coastguard Worker bufferItem.mScalingMode, crop);
648*38e8c45fSAndroid Build Coastguard Worker
649*38e8c45fSAndroid Build Coastguard Worker auto releaseBufferCallback = makeReleaseBufferCallbackThunk();
650*38e8c45fSAndroid Build Coastguard Worker sp<Fence> fence = bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE;
651*38e8c45fSAndroid Build Coastguard Worker
652*38e8c45fSAndroid Build Coastguard Worker nsecs_t dequeueTime = -1;
653*38e8c45fSAndroid Build Coastguard Worker {
654*38e8c45fSAndroid Build Coastguard Worker std::lock_guard _lock{mTimestampMutex};
655*38e8c45fSAndroid Build Coastguard Worker auto dequeueTimeIt = mDequeueTimestamps.find(buffer->getId());
656*38e8c45fSAndroid Build Coastguard Worker if (dequeueTimeIt != mDequeueTimestamps.end()) {
657*38e8c45fSAndroid Build Coastguard Worker dequeueTime = dequeueTimeIt->second;
658*38e8c45fSAndroid Build Coastguard Worker mDequeueTimestamps.erase(dequeueTimeIt);
659*38e8c45fSAndroid Build Coastguard Worker }
660*38e8c45fSAndroid Build Coastguard Worker }
661*38e8c45fSAndroid Build Coastguard Worker
662*38e8c45fSAndroid Build Coastguard Worker t->setBuffer(mSurfaceControl, buffer, fence, bufferItem.mFrameNumber, mProducerId,
663*38e8c45fSAndroid Build Coastguard Worker releaseBufferCallback, dequeueTime);
664*38e8c45fSAndroid Build Coastguard Worker t->setDataspace(mSurfaceControl, static_cast<ui::Dataspace>(bufferItem.mDataSpace));
665*38e8c45fSAndroid Build Coastguard Worker t->setHdrMetadata(mSurfaceControl, bufferItem.mHdrMetadata);
666*38e8c45fSAndroid Build Coastguard Worker t->setSurfaceDamageRegion(mSurfaceControl, bufferItem.mSurfaceDamage);
667*38e8c45fSAndroid Build Coastguard Worker t->addTransactionCompletedCallback(makeTransactionCallbackThunk(), nullptr);
668*38e8c45fSAndroid Build Coastguard Worker
669*38e8c45fSAndroid Build Coastguard Worker mSurfaceControlsWithPendingCallback.push(mSurfaceControl);
670*38e8c45fSAndroid Build Coastguard Worker
671*38e8c45fSAndroid Build Coastguard Worker if (mUpdateDestinationFrame) {
672*38e8c45fSAndroid Build Coastguard Worker t->setDestinationFrame(mSurfaceControl, Rect(mSize));
673*38e8c45fSAndroid Build Coastguard Worker } else {
674*38e8c45fSAndroid Build Coastguard Worker const bool ignoreDestinationFrame =
675*38e8c45fSAndroid Build Coastguard Worker bufferItem.mScalingMode == NATIVE_WINDOW_SCALING_MODE_FREEZE;
676*38e8c45fSAndroid Build Coastguard Worker t->setFlags(mSurfaceControl,
677*38e8c45fSAndroid Build Coastguard Worker ignoreDestinationFrame ? layer_state_t::eIgnoreDestinationFrame : 0,
678*38e8c45fSAndroid Build Coastguard Worker layer_state_t::eIgnoreDestinationFrame);
679*38e8c45fSAndroid Build Coastguard Worker }
680*38e8c45fSAndroid Build Coastguard Worker t->setBufferCrop(mSurfaceControl, crop);
681*38e8c45fSAndroid Build Coastguard Worker t->setTransform(mSurfaceControl, bufferItem.mTransform);
682*38e8c45fSAndroid Build Coastguard Worker t->setTransformToDisplayInverse(mSurfaceControl, bufferItem.mTransformToDisplayInverse);
683*38e8c45fSAndroid Build Coastguard Worker t->setAutoRefresh(mSurfaceControl, bufferItem.mAutoRefresh);
684*38e8c45fSAndroid Build Coastguard Worker if (!bufferItem.mIsAutoTimestamp) {
685*38e8c45fSAndroid Build Coastguard Worker t->setDesiredPresentTime(bufferItem.mTimestamp);
686*38e8c45fSAndroid Build Coastguard Worker }
687*38e8c45fSAndroid Build Coastguard Worker if (com_android_graphics_libgui_flags_apply_picture_profiles() &&
688*38e8c45fSAndroid Build Coastguard Worker bufferItem.mPictureProfileHandle.has_value()) {
689*38e8c45fSAndroid Build Coastguard Worker t->setPictureProfileHandle(mSurfaceControl, *bufferItem.mPictureProfileHandle);
690*38e8c45fSAndroid Build Coastguard Worker // The current picture profile must be maintained in case the BBQ gets its
691*38e8c45fSAndroid Build Coastguard Worker // SurfaceControl switched out.
692*38e8c45fSAndroid Build Coastguard Worker mPictureProfileHandle = bufferItem.mPictureProfileHandle;
693*38e8c45fSAndroid Build Coastguard Worker // Clear out the picture profile if the requestor has asked for it to be cleared
694*38e8c45fSAndroid Build Coastguard Worker if (mPictureProfileHandle == PictureProfileHandle::NONE) {
695*38e8c45fSAndroid Build Coastguard Worker mPictureProfileHandle = std::nullopt;
696*38e8c45fSAndroid Build Coastguard Worker }
697*38e8c45fSAndroid Build Coastguard Worker }
698*38e8c45fSAndroid Build Coastguard Worker
699*38e8c45fSAndroid Build Coastguard Worker // Drop stale frame timeline infos
700*38e8c45fSAndroid Build Coastguard Worker while (!mPendingFrameTimelines.empty() &&
701*38e8c45fSAndroid Build Coastguard Worker mPendingFrameTimelines.front().first < bufferItem.mFrameNumber) {
702*38e8c45fSAndroid Build Coastguard Worker ATRACE_FORMAT_INSTANT("dropping stale frameNumber: %" PRIu64 " vsyncId: %" PRId64,
703*38e8c45fSAndroid Build Coastguard Worker mPendingFrameTimelines.front().first,
704*38e8c45fSAndroid Build Coastguard Worker mPendingFrameTimelines.front().second.vsyncId);
705*38e8c45fSAndroid Build Coastguard Worker mPendingFrameTimelines.pop();
706*38e8c45fSAndroid Build Coastguard Worker }
707*38e8c45fSAndroid Build Coastguard Worker
708*38e8c45fSAndroid Build Coastguard Worker if (!mPendingFrameTimelines.empty() &&
709*38e8c45fSAndroid Build Coastguard Worker mPendingFrameTimelines.front().first == bufferItem.mFrameNumber) {
710*38e8c45fSAndroid Build Coastguard Worker ATRACE_FORMAT_INSTANT("Transaction::setFrameTimelineInfo frameNumber: %" PRIu64
711*38e8c45fSAndroid Build Coastguard Worker " vsyncId: %" PRId64,
712*38e8c45fSAndroid Build Coastguard Worker bufferItem.mFrameNumber,
713*38e8c45fSAndroid Build Coastguard Worker mPendingFrameTimelines.front().second.vsyncId);
714*38e8c45fSAndroid Build Coastguard Worker t->setFrameTimelineInfo(mPendingFrameTimelines.front().second);
715*38e8c45fSAndroid Build Coastguard Worker mPendingFrameTimelines.pop();
716*38e8c45fSAndroid Build Coastguard Worker }
717*38e8c45fSAndroid Build Coastguard Worker
718*38e8c45fSAndroid Build Coastguard Worker mergePendingTransactions(t, bufferItem.mFrameNumber);
719*38e8c45fSAndroid Build Coastguard Worker if (applyTransaction) {
720*38e8c45fSAndroid Build Coastguard Worker // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction
721*38e8c45fSAndroid Build Coastguard Worker t->setApplyToken(mApplyToken).apply(false, true);
722*38e8c45fSAndroid Build Coastguard Worker mAppliedLastTransaction = true;
723*38e8c45fSAndroid Build Coastguard Worker mLastAppliedFrameNumber = bufferItem.mFrameNumber;
724*38e8c45fSAndroid Build Coastguard Worker } else {
725*38e8c45fSAndroid Build Coastguard Worker t->setBufferHasBarrier(mSurfaceControl, mLastAppliedFrameNumber);
726*38e8c45fSAndroid Build Coastguard Worker mAppliedLastTransaction = false;
727*38e8c45fSAndroid Build Coastguard Worker }
728*38e8c45fSAndroid Build Coastguard Worker
729*38e8c45fSAndroid Build Coastguard Worker BQA_LOGV("acquireNextBufferLocked size=%dx%d mFrameNumber=%" PRIu64
730*38e8c45fSAndroid Build Coastguard Worker " applyTransaction=%s mTimestamp=%" PRId64 "%s mPendingTransactions.size=%d"
731*38e8c45fSAndroid Build Coastguard Worker " graphicBufferId=%" PRIu64 "%s transform=%d",
732*38e8c45fSAndroid Build Coastguard Worker mSize.width, mSize.height, bufferItem.mFrameNumber, boolToString(applyTransaction),
733*38e8c45fSAndroid Build Coastguard Worker bufferItem.mTimestamp, bufferItem.mIsAutoTimestamp ? "(auto)" : "",
734*38e8c45fSAndroid Build Coastguard Worker static_cast<uint32_t>(mPendingTransactions.size()), bufferItem.mGraphicBuffer->getId(),
735*38e8c45fSAndroid Build Coastguard Worker bufferItem.mAutoRefresh ? " mAutoRefresh" : "", bufferItem.mTransform);
736*38e8c45fSAndroid Build Coastguard Worker return OK;
737*38e8c45fSAndroid Build Coastguard Worker }
738*38e8c45fSAndroid Build Coastguard Worker
computeCrop(const BufferItem & item)739*38e8c45fSAndroid Build Coastguard Worker Rect BLASTBufferQueue::computeCrop(const BufferItem& item) {
740*38e8c45fSAndroid Build Coastguard Worker if (item.mScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
741*38e8c45fSAndroid Build Coastguard Worker return GLConsumer::scaleDownCrop(item.mCrop, mSize.width, mSize.height);
742*38e8c45fSAndroid Build Coastguard Worker }
743*38e8c45fSAndroid Build Coastguard Worker return item.mCrop;
744*38e8c45fSAndroid Build Coastguard Worker }
745*38e8c45fSAndroid Build Coastguard Worker
acquireAndReleaseBuffer()746*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::acquireAndReleaseBuffer() {
747*38e8c45fSAndroid Build Coastguard Worker BBQ_TRACE();
748*38e8c45fSAndroid Build Coastguard Worker BufferItem bufferItem;
749*38e8c45fSAndroid Build Coastguard Worker status_t status =
750*38e8c45fSAndroid Build Coastguard Worker mBufferItemConsumer->acquireBuffer(&bufferItem, 0 /* expectedPresent */, false);
751*38e8c45fSAndroid Build Coastguard Worker if (status != OK) {
752*38e8c45fSAndroid Build Coastguard Worker BQA_LOGE("Failed to acquire a buffer in acquireAndReleaseBuffer, err=%s",
753*38e8c45fSAndroid Build Coastguard Worker statusToString(status).c_str());
754*38e8c45fSAndroid Build Coastguard Worker return;
755*38e8c45fSAndroid Build Coastguard Worker }
756*38e8c45fSAndroid Build Coastguard Worker mNumFrameAvailable--;
757*38e8c45fSAndroid Build Coastguard Worker mBufferItemConsumer->releaseBuffer(bufferItem, bufferItem.mFence);
758*38e8c45fSAndroid Build Coastguard Worker }
759*38e8c45fSAndroid Build Coastguard Worker
onFrameAvailable(const BufferItem & item)760*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) {
761*38e8c45fSAndroid Build Coastguard Worker std::function<void(SurfaceComposerClient::Transaction*)> prevCallback = nullptr;
762*38e8c45fSAndroid Build Coastguard Worker SurfaceComposerClient::Transaction* prevTransaction = nullptr;
763*38e8c45fSAndroid Build Coastguard Worker
764*38e8c45fSAndroid Build Coastguard Worker {
765*38e8c45fSAndroid Build Coastguard Worker UNIQUE_LOCK_WITH_ASSERTION(mMutex);
766*38e8c45fSAndroid Build Coastguard Worker BBQ_TRACE();
767*38e8c45fSAndroid Build Coastguard Worker bool waitForTransactionCallback = !mSyncedFrameNumbers.empty();
768*38e8c45fSAndroid Build Coastguard Worker
769*38e8c45fSAndroid Build Coastguard Worker const bool syncTransactionSet = mTransactionReadyCallback != nullptr;
770*38e8c45fSAndroid Build Coastguard Worker BQA_LOGV("onFrameAvailable-start syncTransactionSet=%s", boolToString(syncTransactionSet));
771*38e8c45fSAndroid Build Coastguard Worker
772*38e8c45fSAndroid Build Coastguard Worker if (syncTransactionSet) {
773*38e8c45fSAndroid Build Coastguard Worker // If we are going to re-use the same mSyncTransaction, release the buffer that may
774*38e8c45fSAndroid Build Coastguard Worker // already be set in the Transaction. This is to allow us a free slot early to continue
775*38e8c45fSAndroid Build Coastguard Worker // processing a new buffer.
776*38e8c45fSAndroid Build Coastguard Worker if (!mAcquireSingleBuffer) {
777*38e8c45fSAndroid Build Coastguard Worker auto bufferData = mSyncTransaction->getAndClearBuffer(mSurfaceControl);
778*38e8c45fSAndroid Build Coastguard Worker if (bufferData) {
779*38e8c45fSAndroid Build Coastguard Worker BQA_LOGD("Releasing previous buffer when syncing: framenumber=%" PRIu64,
780*38e8c45fSAndroid Build Coastguard Worker bufferData->frameNumber);
781*38e8c45fSAndroid Build Coastguard Worker releaseBuffer(bufferData->generateReleaseCallbackId(),
782*38e8c45fSAndroid Build Coastguard Worker bufferData->acquireFence);
783*38e8c45fSAndroid Build Coastguard Worker }
784*38e8c45fSAndroid Build Coastguard Worker }
785*38e8c45fSAndroid Build Coastguard Worker
786*38e8c45fSAndroid Build Coastguard Worker if (waitForTransactionCallback) {
787*38e8c45fSAndroid Build Coastguard Worker // We are waiting on a previous sync's transaction callback so allow another sync
788*38e8c45fSAndroid Build Coastguard Worker // transaction to proceed.
789*38e8c45fSAndroid Build Coastguard Worker //
790*38e8c45fSAndroid Build Coastguard Worker // We need to first flush out the transactions that were in between the two syncs.
791*38e8c45fSAndroid Build Coastguard Worker // We do this by merging them into mSyncTransaction so any buffer merging will get
792*38e8c45fSAndroid Build Coastguard Worker // a release callback invoked.
793*38e8c45fSAndroid Build Coastguard Worker while (mNumFrameAvailable > 0) {
794*38e8c45fSAndroid Build Coastguard Worker // flush out the shadow queue
795*38e8c45fSAndroid Build Coastguard Worker acquireAndReleaseBuffer();
796*38e8c45fSAndroid Build Coastguard Worker }
797*38e8c45fSAndroid Build Coastguard Worker } else {
798*38e8c45fSAndroid Build Coastguard Worker // Make sure the frame available count is 0 before proceeding with a sync to ensure
799*38e8c45fSAndroid Build Coastguard Worker // the correct frame is used for the sync. The only way mNumFrameAvailable would be
800*38e8c45fSAndroid Build Coastguard Worker // greater than 0 is if we already ran out of buffers previously. This means we
801*38e8c45fSAndroid Build Coastguard Worker // need to flush the buffers before proceeding with the sync.
802*38e8c45fSAndroid Build Coastguard Worker while (mNumFrameAvailable > 0) {
803*38e8c45fSAndroid Build Coastguard Worker BQA_LOGD("waiting until no queued buffers");
804*38e8c45fSAndroid Build Coastguard Worker mCallbackCV.wait(_lock);
805*38e8c45fSAndroid Build Coastguard Worker }
806*38e8c45fSAndroid Build Coastguard Worker }
807*38e8c45fSAndroid Build Coastguard Worker }
808*38e8c45fSAndroid Build Coastguard Worker
809*38e8c45fSAndroid Build Coastguard Worker // add to shadow queue
810*38e8c45fSAndroid Build Coastguard Worker mNumFrameAvailable++;
811*38e8c45fSAndroid Build Coastguard Worker if (waitForTransactionCallback && mNumFrameAvailable >= 2) {
812*38e8c45fSAndroid Build Coastguard Worker acquireAndReleaseBuffer();
813*38e8c45fSAndroid Build Coastguard Worker }
814*38e8c45fSAndroid Build Coastguard Worker ATRACE_INT(mQueuedBufferTrace.c_str(),
815*38e8c45fSAndroid Build Coastguard Worker mNumFrameAvailable + mNumAcquired - mPendingRelease.size());
816*38e8c45fSAndroid Build Coastguard Worker
817*38e8c45fSAndroid Build Coastguard Worker BQA_LOGV("onFrameAvailable framenumber=%" PRIu64 " syncTransactionSet=%s",
818*38e8c45fSAndroid Build Coastguard Worker item.mFrameNumber, boolToString(syncTransactionSet));
819*38e8c45fSAndroid Build Coastguard Worker
820*38e8c45fSAndroid Build Coastguard Worker if (syncTransactionSet) {
821*38e8c45fSAndroid Build Coastguard Worker // Add to mSyncedFrameNumbers before waiting in case any buffers are released
822*38e8c45fSAndroid Build Coastguard Worker // while waiting for a free buffer. The release and commit callback will try to
823*38e8c45fSAndroid Build Coastguard Worker // acquire buffers if there are any available, but we don't want it to acquire
824*38e8c45fSAndroid Build Coastguard Worker // in the case where a sync transaction wants the buffer.
825*38e8c45fSAndroid Build Coastguard Worker mSyncedFrameNumbers.emplace(item.mFrameNumber);
826*38e8c45fSAndroid Build Coastguard Worker // If there's no available buffer and we're in a sync transaction, we need to wait
827*38e8c45fSAndroid Build Coastguard Worker // instead of returning since we guarantee a buffer will be acquired for the sync.
828*38e8c45fSAndroid Build Coastguard Worker while (acquireNextBufferLocked(mSyncTransaction) == BufferQueue::NO_BUFFER_AVAILABLE) {
829*38e8c45fSAndroid Build Coastguard Worker BQA_LOGD("waiting for available buffer");
830*38e8c45fSAndroid Build Coastguard Worker mCallbackCV.wait(_lock);
831*38e8c45fSAndroid Build Coastguard Worker }
832*38e8c45fSAndroid Build Coastguard Worker
833*38e8c45fSAndroid Build Coastguard Worker // Only need a commit callback when syncing to ensure the buffer that's synced has been
834*38e8c45fSAndroid Build Coastguard Worker // sent to SF
835*38e8c45fSAndroid Build Coastguard Worker mSyncTransaction
836*38e8c45fSAndroid Build Coastguard Worker ->addTransactionCommittedCallback(makeTransactionCommittedCallbackThunk(),
837*38e8c45fSAndroid Build Coastguard Worker nullptr);
838*38e8c45fSAndroid Build Coastguard Worker if (mAcquireSingleBuffer) {
839*38e8c45fSAndroid Build Coastguard Worker prevCallback = mTransactionReadyCallback;
840*38e8c45fSAndroid Build Coastguard Worker prevTransaction = mSyncTransaction;
841*38e8c45fSAndroid Build Coastguard Worker mTransactionReadyCallback = nullptr;
842*38e8c45fSAndroid Build Coastguard Worker mSyncTransaction = nullptr;
843*38e8c45fSAndroid Build Coastguard Worker }
844*38e8c45fSAndroid Build Coastguard Worker } else if (!waitForTransactionCallback) {
845*38e8c45fSAndroid Build Coastguard Worker acquireNextBufferLocked(std::nullopt);
846*38e8c45fSAndroid Build Coastguard Worker }
847*38e8c45fSAndroid Build Coastguard Worker }
848*38e8c45fSAndroid Build Coastguard Worker if (prevCallback) {
849*38e8c45fSAndroid Build Coastguard Worker prevCallback(prevTransaction);
850*38e8c45fSAndroid Build Coastguard Worker }
851*38e8c45fSAndroid Build Coastguard Worker }
852*38e8c45fSAndroid Build Coastguard Worker
onFrameReplaced(const BufferItem & item)853*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::onFrameReplaced(const BufferItem& item) {
854*38e8c45fSAndroid Build Coastguard Worker BQA_LOGV("onFrameReplaced framenumber=%" PRIu64, item.mFrameNumber);
855*38e8c45fSAndroid Build Coastguard Worker // Do nothing since we are not storing unacquired buffer items locally.
856*38e8c45fSAndroid Build Coastguard Worker }
857*38e8c45fSAndroid Build Coastguard Worker
onFrameDequeued(const uint64_t bufferId)858*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::onFrameDequeued(const uint64_t bufferId) {
859*38e8c45fSAndroid Build Coastguard Worker std::lock_guard _lock{mTimestampMutex};
860*38e8c45fSAndroid Build Coastguard Worker mDequeueTimestamps[bufferId] = systemTime();
861*38e8c45fSAndroid Build Coastguard Worker };
862*38e8c45fSAndroid Build Coastguard Worker
onFrameCancelled(const uint64_t bufferId)863*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::onFrameCancelled(const uint64_t bufferId) {
864*38e8c45fSAndroid Build Coastguard Worker std::lock_guard _lock{mTimestampMutex};
865*38e8c45fSAndroid Build Coastguard Worker mDequeueTimestamps.erase(bufferId);
866*38e8c45fSAndroid Build Coastguard Worker }
867*38e8c45fSAndroid Build Coastguard Worker
syncNextTransaction(std::function<void (SurfaceComposerClient::Transaction *)> callback,bool acquireSingleBuffer)868*38e8c45fSAndroid Build Coastguard Worker bool BLASTBufferQueue::syncNextTransaction(
869*38e8c45fSAndroid Build Coastguard Worker std::function<void(SurfaceComposerClient::Transaction*)> callback,
870*38e8c45fSAndroid Build Coastguard Worker bool acquireSingleBuffer) {
871*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(!callback,
872*38e8c45fSAndroid Build Coastguard Worker "BLASTBufferQueue: callback passed in to syncNextTransaction must not be "
873*38e8c45fSAndroid Build Coastguard Worker "NULL");
874*38e8c45fSAndroid Build Coastguard Worker
875*38e8c45fSAndroid Build Coastguard Worker std::lock_guard _lock{mMutex};
876*38e8c45fSAndroid Build Coastguard Worker BBQ_TRACE();
877*38e8c45fSAndroid Build Coastguard Worker if (mTransactionReadyCallback) {
878*38e8c45fSAndroid Build Coastguard Worker ALOGW("Attempting to overwrite transaction callback in syncNextTransaction");
879*38e8c45fSAndroid Build Coastguard Worker return false;
880*38e8c45fSAndroid Build Coastguard Worker }
881*38e8c45fSAndroid Build Coastguard Worker
882*38e8c45fSAndroid Build Coastguard Worker mTransactionReadyCallback = callback;
883*38e8c45fSAndroid Build Coastguard Worker mSyncTransaction = new SurfaceComposerClient::Transaction();
884*38e8c45fSAndroid Build Coastguard Worker mAcquireSingleBuffer = acquireSingleBuffer;
885*38e8c45fSAndroid Build Coastguard Worker return true;
886*38e8c45fSAndroid Build Coastguard Worker }
887*38e8c45fSAndroid Build Coastguard Worker
stopContinuousSyncTransaction()888*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::stopContinuousSyncTransaction() {
889*38e8c45fSAndroid Build Coastguard Worker std::function<void(SurfaceComposerClient::Transaction*)> prevCallback = nullptr;
890*38e8c45fSAndroid Build Coastguard Worker SurfaceComposerClient::Transaction* prevTransaction = nullptr;
891*38e8c45fSAndroid Build Coastguard Worker {
892*38e8c45fSAndroid Build Coastguard Worker std::lock_guard _lock{mMutex};
893*38e8c45fSAndroid Build Coastguard Worker if (mAcquireSingleBuffer || !mTransactionReadyCallback) {
894*38e8c45fSAndroid Build Coastguard Worker ALOGW("Attempting to stop continuous sync when none are active");
895*38e8c45fSAndroid Build Coastguard Worker return;
896*38e8c45fSAndroid Build Coastguard Worker }
897*38e8c45fSAndroid Build Coastguard Worker
898*38e8c45fSAndroid Build Coastguard Worker prevCallback = mTransactionReadyCallback;
899*38e8c45fSAndroid Build Coastguard Worker prevTransaction = mSyncTransaction;
900*38e8c45fSAndroid Build Coastguard Worker
901*38e8c45fSAndroid Build Coastguard Worker mTransactionReadyCallback = nullptr;
902*38e8c45fSAndroid Build Coastguard Worker mSyncTransaction = nullptr;
903*38e8c45fSAndroid Build Coastguard Worker mAcquireSingleBuffer = true;
904*38e8c45fSAndroid Build Coastguard Worker }
905*38e8c45fSAndroid Build Coastguard Worker
906*38e8c45fSAndroid Build Coastguard Worker if (prevCallback) {
907*38e8c45fSAndroid Build Coastguard Worker prevCallback(prevTransaction);
908*38e8c45fSAndroid Build Coastguard Worker }
909*38e8c45fSAndroid Build Coastguard Worker }
910*38e8c45fSAndroid Build Coastguard Worker
clearSyncTransaction()911*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::clearSyncTransaction() {
912*38e8c45fSAndroid Build Coastguard Worker std::lock_guard _lock{mMutex};
913*38e8c45fSAndroid Build Coastguard Worker if (!mAcquireSingleBuffer) {
914*38e8c45fSAndroid Build Coastguard Worker ALOGW("Attempting to clear sync transaction when none are active");
915*38e8c45fSAndroid Build Coastguard Worker return;
916*38e8c45fSAndroid Build Coastguard Worker }
917*38e8c45fSAndroid Build Coastguard Worker
918*38e8c45fSAndroid Build Coastguard Worker mTransactionReadyCallback = nullptr;
919*38e8c45fSAndroid Build Coastguard Worker mSyncTransaction = nullptr;
920*38e8c45fSAndroid Build Coastguard Worker }
921*38e8c45fSAndroid Build Coastguard Worker
rejectBuffer(const BufferItem & item)922*38e8c45fSAndroid Build Coastguard Worker bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) {
923*38e8c45fSAndroid Build Coastguard Worker if (item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) {
924*38e8c45fSAndroid Build Coastguard Worker // Only reject buffers if scaling mode is freeze.
925*38e8c45fSAndroid Build Coastguard Worker return false;
926*38e8c45fSAndroid Build Coastguard Worker }
927*38e8c45fSAndroid Build Coastguard Worker
928*38e8c45fSAndroid Build Coastguard Worker ui::Size bufferSize = getBufferSize(item);
929*38e8c45fSAndroid Build Coastguard Worker if (mRequestedSize != mSize && mRequestedSize == bufferSize) {
930*38e8c45fSAndroid Build Coastguard Worker return false;
931*38e8c45fSAndroid Build Coastguard Worker }
932*38e8c45fSAndroid Build Coastguard Worker
933*38e8c45fSAndroid Build Coastguard Worker // reject buffers if the buffer size doesn't match.
934*38e8c45fSAndroid Build Coastguard Worker return mSize != bufferSize;
935*38e8c45fSAndroid Build Coastguard Worker }
936*38e8c45fSAndroid Build Coastguard Worker
937*38e8c45fSAndroid Build Coastguard Worker class BBQSurface : public Surface {
938*38e8c45fSAndroid Build Coastguard Worker private:
939*38e8c45fSAndroid Build Coastguard Worker std::mutex mMutex;
940*38e8c45fSAndroid Build Coastguard Worker sp<BLASTBufferQueue> mBbq GUARDED_BY(mMutex);
941*38e8c45fSAndroid Build Coastguard Worker bool mDestroyed GUARDED_BY(mMutex) = false;
942*38e8c45fSAndroid Build Coastguard Worker
943*38e8c45fSAndroid Build Coastguard Worker public:
BBQSurface(const sp<IGraphicBufferProducer> & igbp,bool controlledByApp,const sp<IBinder> & scHandle,const sp<BLASTBufferQueue> & bbq)944*38e8c45fSAndroid Build Coastguard Worker BBQSurface(const sp<IGraphicBufferProducer>& igbp, bool controlledByApp,
945*38e8c45fSAndroid Build Coastguard Worker const sp<IBinder>& scHandle, const sp<BLASTBufferQueue>& bbq)
946*38e8c45fSAndroid Build Coastguard Worker : Surface(igbp, controlledByApp, scHandle), mBbq(bbq) {}
947*38e8c45fSAndroid Build Coastguard Worker
allocateBuffers()948*38e8c45fSAndroid Build Coastguard Worker void allocateBuffers() override {
949*38e8c45fSAndroid Build Coastguard Worker uint32_t reqWidth = mReqWidth ? mReqWidth : mUserWidth;
950*38e8c45fSAndroid Build Coastguard Worker uint32_t reqHeight = mReqHeight ? mReqHeight : mUserHeight;
951*38e8c45fSAndroid Build Coastguard Worker auto gbp = getIGraphicBufferProducer();
952*38e8c45fSAndroid Build Coastguard Worker std::thread ([reqWidth, reqHeight, gbp=getIGraphicBufferProducer(),
953*38e8c45fSAndroid Build Coastguard Worker reqFormat=mReqFormat, reqUsage=mReqUsage] () {
954*38e8c45fSAndroid Build Coastguard Worker gbp->allocateBuffers(reqWidth, reqHeight,
955*38e8c45fSAndroid Build Coastguard Worker reqFormat, reqUsage);
956*38e8c45fSAndroid Build Coastguard Worker
957*38e8c45fSAndroid Build Coastguard Worker }).detach();
958*38e8c45fSAndroid Build Coastguard Worker }
959*38e8c45fSAndroid Build Coastguard Worker
setFrameRate(float frameRate,int8_t compatibility,int8_t changeFrameRateStrategy)960*38e8c45fSAndroid Build Coastguard Worker status_t setFrameRate(float frameRate, int8_t compatibility,
961*38e8c45fSAndroid Build Coastguard Worker int8_t changeFrameRateStrategy) override {
962*38e8c45fSAndroid Build Coastguard Worker if (flags::bq_setframerate()) {
963*38e8c45fSAndroid Build Coastguard Worker return Surface::setFrameRate(frameRate, compatibility, changeFrameRateStrategy);
964*38e8c45fSAndroid Build Coastguard Worker }
965*38e8c45fSAndroid Build Coastguard Worker
966*38e8c45fSAndroid Build Coastguard Worker std::lock_guard _lock{mMutex};
967*38e8c45fSAndroid Build Coastguard Worker if (mDestroyed) {
968*38e8c45fSAndroid Build Coastguard Worker return DEAD_OBJECT;
969*38e8c45fSAndroid Build Coastguard Worker }
970*38e8c45fSAndroid Build Coastguard Worker if (!ValidateFrameRate(frameRate, compatibility, changeFrameRateStrategy,
971*38e8c45fSAndroid Build Coastguard Worker "BBQSurface::setFrameRate")) {
972*38e8c45fSAndroid Build Coastguard Worker return BAD_VALUE;
973*38e8c45fSAndroid Build Coastguard Worker }
974*38e8c45fSAndroid Build Coastguard Worker return mBbq->setFrameRate(frameRate, compatibility, changeFrameRateStrategy);
975*38e8c45fSAndroid Build Coastguard Worker }
976*38e8c45fSAndroid Build Coastguard Worker
setFrameTimelineInfo(uint64_t frameNumber,const FrameTimelineInfo & frameTimelineInfo)977*38e8c45fSAndroid Build Coastguard Worker status_t setFrameTimelineInfo(uint64_t frameNumber,
978*38e8c45fSAndroid Build Coastguard Worker const FrameTimelineInfo& frameTimelineInfo) override {
979*38e8c45fSAndroid Build Coastguard Worker std::lock_guard _lock{mMutex};
980*38e8c45fSAndroid Build Coastguard Worker if (mDestroyed) {
981*38e8c45fSAndroid Build Coastguard Worker return DEAD_OBJECT;
982*38e8c45fSAndroid Build Coastguard Worker }
983*38e8c45fSAndroid Build Coastguard Worker return mBbq->setFrameTimelineInfo(frameNumber, frameTimelineInfo);
984*38e8c45fSAndroid Build Coastguard Worker }
985*38e8c45fSAndroid Build Coastguard Worker
destroy()986*38e8c45fSAndroid Build Coastguard Worker void destroy() override {
987*38e8c45fSAndroid Build Coastguard Worker Surface::destroy();
988*38e8c45fSAndroid Build Coastguard Worker
989*38e8c45fSAndroid Build Coastguard Worker std::lock_guard _lock{mMutex};
990*38e8c45fSAndroid Build Coastguard Worker mDestroyed = true;
991*38e8c45fSAndroid Build Coastguard Worker mBbq = nullptr;
992*38e8c45fSAndroid Build Coastguard Worker }
993*38e8c45fSAndroid Build Coastguard Worker };
994*38e8c45fSAndroid Build Coastguard Worker
995*38e8c45fSAndroid Build Coastguard Worker // TODO: Can we coalesce this with frame updates? Need to confirm
996*38e8c45fSAndroid Build Coastguard Worker // no timing issues.
setFrameRate(float frameRate,int8_t compatibility,bool shouldBeSeamless)997*38e8c45fSAndroid Build Coastguard Worker status_t BLASTBufferQueue::setFrameRate(float frameRate, int8_t compatibility,
998*38e8c45fSAndroid Build Coastguard Worker bool shouldBeSeamless) {
999*38e8c45fSAndroid Build Coastguard Worker std::lock_guard _lock{mMutex};
1000*38e8c45fSAndroid Build Coastguard Worker SurfaceComposerClient::Transaction t;
1001*38e8c45fSAndroid Build Coastguard Worker
1002*38e8c45fSAndroid Build Coastguard Worker return t.setFrameRate(mSurfaceControl, frameRate, compatibility, shouldBeSeamless).apply();
1003*38e8c45fSAndroid Build Coastguard Worker }
1004*38e8c45fSAndroid Build Coastguard Worker
setFrameTimelineInfo(uint64_t frameNumber,const FrameTimelineInfo & frameTimelineInfo)1005*38e8c45fSAndroid Build Coastguard Worker status_t BLASTBufferQueue::setFrameTimelineInfo(uint64_t frameNumber,
1006*38e8c45fSAndroid Build Coastguard Worker const FrameTimelineInfo& frameTimelineInfo) {
1007*38e8c45fSAndroid Build Coastguard Worker ATRACE_FORMAT("%s(%s) frameNumber: %" PRIu64 " vsyncId: %" PRId64, __func__, mName.c_str(),
1008*38e8c45fSAndroid Build Coastguard Worker frameNumber, frameTimelineInfo.vsyncId);
1009*38e8c45fSAndroid Build Coastguard Worker std::lock_guard _lock{mMutex};
1010*38e8c45fSAndroid Build Coastguard Worker mPendingFrameTimelines.push({frameNumber, frameTimelineInfo});
1011*38e8c45fSAndroid Build Coastguard Worker return OK;
1012*38e8c45fSAndroid Build Coastguard Worker }
1013*38e8c45fSAndroid Build Coastguard Worker
setSidebandStream(const sp<NativeHandle> & stream)1014*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::setSidebandStream(const sp<NativeHandle>& stream) {
1015*38e8c45fSAndroid Build Coastguard Worker std::lock_guard _lock{mMutex};
1016*38e8c45fSAndroid Build Coastguard Worker SurfaceComposerClient::Transaction t;
1017*38e8c45fSAndroid Build Coastguard Worker
1018*38e8c45fSAndroid Build Coastguard Worker t.setSidebandStream(mSurfaceControl, stream).apply();
1019*38e8c45fSAndroid Build Coastguard Worker }
1020*38e8c45fSAndroid Build Coastguard Worker
getSurface(bool includeSurfaceControlHandle)1021*38e8c45fSAndroid Build Coastguard Worker sp<Surface> BLASTBufferQueue::getSurface(bool includeSurfaceControlHandle) {
1022*38e8c45fSAndroid Build Coastguard Worker std::lock_guard _lock{mMutex};
1023*38e8c45fSAndroid Build Coastguard Worker sp<IBinder> scHandle = nullptr;
1024*38e8c45fSAndroid Build Coastguard Worker if (includeSurfaceControlHandle && mSurfaceControl) {
1025*38e8c45fSAndroid Build Coastguard Worker scHandle = mSurfaceControl->getHandle();
1026*38e8c45fSAndroid Build Coastguard Worker }
1027*38e8c45fSAndroid Build Coastguard Worker return new BBQSurface(mProducer, true, scHandle, this);
1028*38e8c45fSAndroid Build Coastguard Worker }
1029*38e8c45fSAndroid Build Coastguard Worker
mergeWithNextTransaction(SurfaceComposerClient::Transaction * t,uint64_t frameNumber)1030*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::mergeWithNextTransaction(SurfaceComposerClient::Transaction* t,
1031*38e8c45fSAndroid Build Coastguard Worker uint64_t frameNumber) {
1032*38e8c45fSAndroid Build Coastguard Worker std::lock_guard _lock{mMutex};
1033*38e8c45fSAndroid Build Coastguard Worker if (mLastAcquiredFrameNumber >= frameNumber) {
1034*38e8c45fSAndroid Build Coastguard Worker // Apply the transaction since we have already acquired the desired frame.
1035*38e8c45fSAndroid Build Coastguard Worker t->apply();
1036*38e8c45fSAndroid Build Coastguard Worker } else {
1037*38e8c45fSAndroid Build Coastguard Worker mPendingTransactions.emplace_back(frameNumber, *t);
1038*38e8c45fSAndroid Build Coastguard Worker // Clear the transaction so it can't be applied elsewhere.
1039*38e8c45fSAndroid Build Coastguard Worker t->clear();
1040*38e8c45fSAndroid Build Coastguard Worker }
1041*38e8c45fSAndroid Build Coastguard Worker }
1042*38e8c45fSAndroid Build Coastguard Worker
applyPendingTransactions(uint64_t frameNumber)1043*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::applyPendingTransactions(uint64_t frameNumber) {
1044*38e8c45fSAndroid Build Coastguard Worker std::lock_guard _lock{mMutex};
1045*38e8c45fSAndroid Build Coastguard Worker
1046*38e8c45fSAndroid Build Coastguard Worker SurfaceComposerClient::Transaction t;
1047*38e8c45fSAndroid Build Coastguard Worker mergePendingTransactions(&t, frameNumber);
1048*38e8c45fSAndroid Build Coastguard Worker // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction
1049*38e8c45fSAndroid Build Coastguard Worker t.setApplyToken(mApplyToken).apply(false, true);
1050*38e8c45fSAndroid Build Coastguard Worker }
1051*38e8c45fSAndroid Build Coastguard Worker
mergePendingTransactions(SurfaceComposerClient::Transaction * t,uint64_t frameNumber)1052*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::mergePendingTransactions(SurfaceComposerClient::Transaction* t,
1053*38e8c45fSAndroid Build Coastguard Worker uint64_t frameNumber) {
1054*38e8c45fSAndroid Build Coastguard Worker auto mergeTransaction =
1055*38e8c45fSAndroid Build Coastguard Worker [&t, currentFrameNumber = frameNumber](
1056*38e8c45fSAndroid Build Coastguard Worker std::tuple<uint64_t, SurfaceComposerClient::Transaction> pendingTransaction) {
1057*38e8c45fSAndroid Build Coastguard Worker auto& [targetFrameNumber, transaction] = pendingTransaction;
1058*38e8c45fSAndroid Build Coastguard Worker if (currentFrameNumber < targetFrameNumber) {
1059*38e8c45fSAndroid Build Coastguard Worker return false;
1060*38e8c45fSAndroid Build Coastguard Worker }
1061*38e8c45fSAndroid Build Coastguard Worker t->merge(std::move(transaction));
1062*38e8c45fSAndroid Build Coastguard Worker return true;
1063*38e8c45fSAndroid Build Coastguard Worker };
1064*38e8c45fSAndroid Build Coastguard Worker
1065*38e8c45fSAndroid Build Coastguard Worker mPendingTransactions.erase(std::remove_if(mPendingTransactions.begin(),
1066*38e8c45fSAndroid Build Coastguard Worker mPendingTransactions.end(), mergeTransaction),
1067*38e8c45fSAndroid Build Coastguard Worker mPendingTransactions.end());
1068*38e8c45fSAndroid Build Coastguard Worker }
1069*38e8c45fSAndroid Build Coastguard Worker
gatherPendingTransactions(uint64_t frameNumber)1070*38e8c45fSAndroid Build Coastguard Worker SurfaceComposerClient::Transaction* BLASTBufferQueue::gatherPendingTransactions(
1071*38e8c45fSAndroid Build Coastguard Worker uint64_t frameNumber) {
1072*38e8c45fSAndroid Build Coastguard Worker std::lock_guard _lock{mMutex};
1073*38e8c45fSAndroid Build Coastguard Worker SurfaceComposerClient::Transaction* t = new SurfaceComposerClient::Transaction();
1074*38e8c45fSAndroid Build Coastguard Worker mergePendingTransactions(t, frameNumber);
1075*38e8c45fSAndroid Build Coastguard Worker return t;
1076*38e8c45fSAndroid Build Coastguard Worker }
1077*38e8c45fSAndroid Build Coastguard Worker
1078*38e8c45fSAndroid Build Coastguard Worker // Maintains a single worker thread per process that services a list of runnables.
1079*38e8c45fSAndroid Build Coastguard Worker class AsyncWorker : public Singleton<AsyncWorker> {
1080*38e8c45fSAndroid Build Coastguard Worker private:
1081*38e8c45fSAndroid Build Coastguard Worker std::thread mThread;
1082*38e8c45fSAndroid Build Coastguard Worker bool mDone = false;
1083*38e8c45fSAndroid Build Coastguard Worker std::deque<std::function<void()>> mRunnables;
1084*38e8c45fSAndroid Build Coastguard Worker std::mutex mMutex;
1085*38e8c45fSAndroid Build Coastguard Worker std::condition_variable mCv;
run()1086*38e8c45fSAndroid Build Coastguard Worker void run() {
1087*38e8c45fSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(mMutex);
1088*38e8c45fSAndroid Build Coastguard Worker while (!mDone) {
1089*38e8c45fSAndroid Build Coastguard Worker while (!mRunnables.empty()) {
1090*38e8c45fSAndroid Build Coastguard Worker std::deque<std::function<void()>> runnables = std::move(mRunnables);
1091*38e8c45fSAndroid Build Coastguard Worker mRunnables.clear();
1092*38e8c45fSAndroid Build Coastguard Worker lock.unlock();
1093*38e8c45fSAndroid Build Coastguard Worker // Run outside the lock since the runnable might trigger another
1094*38e8c45fSAndroid Build Coastguard Worker // post to the async worker.
1095*38e8c45fSAndroid Build Coastguard Worker execute(runnables);
1096*38e8c45fSAndroid Build Coastguard Worker lock.lock();
1097*38e8c45fSAndroid Build Coastguard Worker }
1098*38e8c45fSAndroid Build Coastguard Worker mCv.wait(lock);
1099*38e8c45fSAndroid Build Coastguard Worker }
1100*38e8c45fSAndroid Build Coastguard Worker }
1101*38e8c45fSAndroid Build Coastguard Worker
execute(std::deque<std::function<void ()>> & runnables)1102*38e8c45fSAndroid Build Coastguard Worker void execute(std::deque<std::function<void()>>& runnables) {
1103*38e8c45fSAndroid Build Coastguard Worker while (!runnables.empty()) {
1104*38e8c45fSAndroid Build Coastguard Worker std::function<void()> runnable = runnables.front();
1105*38e8c45fSAndroid Build Coastguard Worker runnables.pop_front();
1106*38e8c45fSAndroid Build Coastguard Worker runnable();
1107*38e8c45fSAndroid Build Coastguard Worker }
1108*38e8c45fSAndroid Build Coastguard Worker }
1109*38e8c45fSAndroid Build Coastguard Worker
1110*38e8c45fSAndroid Build Coastguard Worker public:
AsyncWorker()1111*38e8c45fSAndroid Build Coastguard Worker AsyncWorker() : Singleton<AsyncWorker>() { mThread = std::thread(&AsyncWorker::run, this); }
1112*38e8c45fSAndroid Build Coastguard Worker
~AsyncWorker()1113*38e8c45fSAndroid Build Coastguard Worker ~AsyncWorker() {
1114*38e8c45fSAndroid Build Coastguard Worker mDone = true;
1115*38e8c45fSAndroid Build Coastguard Worker mCv.notify_all();
1116*38e8c45fSAndroid Build Coastguard Worker if (mThread.joinable()) {
1117*38e8c45fSAndroid Build Coastguard Worker mThread.join();
1118*38e8c45fSAndroid Build Coastguard Worker }
1119*38e8c45fSAndroid Build Coastguard Worker }
1120*38e8c45fSAndroid Build Coastguard Worker
post(std::function<void ()> runnable)1121*38e8c45fSAndroid Build Coastguard Worker void post(std::function<void()> runnable) {
1122*38e8c45fSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(mMutex);
1123*38e8c45fSAndroid Build Coastguard Worker mRunnables.emplace_back(std::move(runnable));
1124*38e8c45fSAndroid Build Coastguard Worker mCv.notify_one();
1125*38e8c45fSAndroid Build Coastguard Worker }
1126*38e8c45fSAndroid Build Coastguard Worker };
1127*38e8c45fSAndroid Build Coastguard Worker ANDROID_SINGLETON_STATIC_INSTANCE(AsyncWorker);
1128*38e8c45fSAndroid Build Coastguard Worker
1129*38e8c45fSAndroid Build Coastguard Worker // Asynchronously calls ProducerListener functions so we can emulate one way binder calls.
1130*38e8c45fSAndroid Build Coastguard Worker class AsyncProducerListener : public BnProducerListener {
1131*38e8c45fSAndroid Build Coastguard Worker private:
1132*38e8c45fSAndroid Build Coastguard Worker const sp<IProducerListener> mListener;
1133*38e8c45fSAndroid Build Coastguard Worker
1134*38e8c45fSAndroid Build Coastguard Worker public:
AsyncProducerListener(const sp<IProducerListener> & listener)1135*38e8c45fSAndroid Build Coastguard Worker AsyncProducerListener(const sp<IProducerListener>& listener) : mListener(listener) {}
1136*38e8c45fSAndroid Build Coastguard Worker
onBufferReleased()1137*38e8c45fSAndroid Build Coastguard Worker void onBufferReleased() override {
1138*38e8c45fSAndroid Build Coastguard Worker AsyncWorker::getInstance().post([listener = mListener]() { listener->onBufferReleased(); });
1139*38e8c45fSAndroid Build Coastguard Worker }
1140*38e8c45fSAndroid Build Coastguard Worker
onBuffersDiscarded(const std::vector<int32_t> & slots)1141*38e8c45fSAndroid Build Coastguard Worker void onBuffersDiscarded(const std::vector<int32_t>& slots) override {
1142*38e8c45fSAndroid Build Coastguard Worker AsyncWorker::getInstance().post(
1143*38e8c45fSAndroid Build Coastguard Worker [listener = mListener, slots = slots]() { listener->onBuffersDiscarded(slots); });
1144*38e8c45fSAndroid Build Coastguard Worker }
1145*38e8c45fSAndroid Build Coastguard Worker
onBufferDetached(int slot)1146*38e8c45fSAndroid Build Coastguard Worker void onBufferDetached(int slot) override {
1147*38e8c45fSAndroid Build Coastguard Worker AsyncWorker::getInstance().post(
1148*38e8c45fSAndroid Build Coastguard Worker [listener = mListener, slot = slot]() { listener->onBufferDetached(slot); });
1149*38e8c45fSAndroid Build Coastguard Worker }
1150*38e8c45fSAndroid Build Coastguard Worker
1151*38e8c45fSAndroid Build Coastguard Worker #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_CONSUMER_ATTACH_CALLBACK)
onBufferAttached()1152*38e8c45fSAndroid Build Coastguard Worker void onBufferAttached() override {
1153*38e8c45fSAndroid Build Coastguard Worker AsyncWorker::getInstance().post([listener = mListener]() { listener->onBufferAttached(); });
1154*38e8c45fSAndroid Build Coastguard Worker }
1155*38e8c45fSAndroid Build Coastguard Worker #endif
1156*38e8c45fSAndroid Build Coastguard Worker };
1157*38e8c45fSAndroid Build Coastguard Worker
1158*38e8c45fSAndroid Build Coastguard Worker #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
1159*38e8c45fSAndroid Build Coastguard Worker class BBQBufferQueueCore : public BufferQueueCore {
1160*38e8c45fSAndroid Build Coastguard Worker public:
BBQBufferQueueCore(const wp<BLASTBufferQueue> & bbq)1161*38e8c45fSAndroid Build Coastguard Worker explicit BBQBufferQueueCore(const wp<BLASTBufferQueue>& bbq) : mBLASTBufferQueue{bbq} {}
1162*38e8c45fSAndroid Build Coastguard Worker
notifyBufferReleased() const1163*38e8c45fSAndroid Build Coastguard Worker void notifyBufferReleased() const override {
1164*38e8c45fSAndroid Build Coastguard Worker sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
1165*38e8c45fSAndroid Build Coastguard Worker if (!bbq) {
1166*38e8c45fSAndroid Build Coastguard Worker return;
1167*38e8c45fSAndroid Build Coastguard Worker }
1168*38e8c45fSAndroid Build Coastguard Worker bbq->mBufferReleaseReader->interruptBlockingRead();
1169*38e8c45fSAndroid Build Coastguard Worker }
1170*38e8c45fSAndroid Build Coastguard Worker
1171*38e8c45fSAndroid Build Coastguard Worker private:
1172*38e8c45fSAndroid Build Coastguard Worker wp<BLASTBufferQueue> mBLASTBufferQueue;
1173*38e8c45fSAndroid Build Coastguard Worker };
1174*38e8c45fSAndroid Build Coastguard Worker #endif
1175*38e8c45fSAndroid Build Coastguard Worker
1176*38e8c45fSAndroid Build Coastguard Worker // Extends the BufferQueueProducer to create a wrapper around the listener so the listener calls
1177*38e8c45fSAndroid Build Coastguard Worker // can be non-blocking when the producer is in the client process.
1178*38e8c45fSAndroid Build Coastguard Worker class BBQBufferQueueProducer : public BufferQueueProducer {
1179*38e8c45fSAndroid Build Coastguard Worker public:
BBQBufferQueueProducer(const sp<BufferQueueCore> & core,const wp<BLASTBufferQueue> & bbq)1180*38e8c45fSAndroid Build Coastguard Worker BBQBufferQueueProducer(const sp<BufferQueueCore>& core, const wp<BLASTBufferQueue>& bbq)
1181*38e8c45fSAndroid Build Coastguard Worker : BufferQueueProducer(core, false /* consumerIsSurfaceFlinger*/),
1182*38e8c45fSAndroid Build Coastguard Worker mBLASTBufferQueue(bbq) {}
1183*38e8c45fSAndroid Build Coastguard Worker
connect(const sp<IProducerListener> & listener,int api,bool producerControlledByApp,QueueBufferOutput * output)1184*38e8c45fSAndroid Build Coastguard Worker status_t connect(const sp<IProducerListener>& listener, int api, bool producerControlledByApp,
1185*38e8c45fSAndroid Build Coastguard Worker QueueBufferOutput* output) override {
1186*38e8c45fSAndroid Build Coastguard Worker if (!listener) {
1187*38e8c45fSAndroid Build Coastguard Worker return BufferQueueProducer::connect(listener, api, producerControlledByApp, output);
1188*38e8c45fSAndroid Build Coastguard Worker }
1189*38e8c45fSAndroid Build Coastguard Worker
1190*38e8c45fSAndroid Build Coastguard Worker return BufferQueueProducer::connect(new AsyncProducerListener(listener), api,
1191*38e8c45fSAndroid Build Coastguard Worker producerControlledByApp, output);
1192*38e8c45fSAndroid Build Coastguard Worker }
1193*38e8c45fSAndroid Build Coastguard Worker
1194*38e8c45fSAndroid Build Coastguard Worker // We want to resize the frame history when changing the size of the buffer queue
setMaxDequeuedBufferCount(int maxDequeuedBufferCount)1195*38e8c45fSAndroid Build Coastguard Worker status_t setMaxDequeuedBufferCount(int maxDequeuedBufferCount) override {
1196*38e8c45fSAndroid Build Coastguard Worker int maxBufferCount;
1197*38e8c45fSAndroid Build Coastguard Worker if (status_t status = BufferQueueProducer::setMaxDequeuedBufferCount(maxDequeuedBufferCount,
1198*38e8c45fSAndroid Build Coastguard Worker &maxBufferCount);
1199*38e8c45fSAndroid Build Coastguard Worker status != OK) {
1200*38e8c45fSAndroid Build Coastguard Worker return status;
1201*38e8c45fSAndroid Build Coastguard Worker }
1202*38e8c45fSAndroid Build Coastguard Worker
1203*38e8c45fSAndroid Build Coastguard Worker sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
1204*38e8c45fSAndroid Build Coastguard Worker if (!bbq) {
1205*38e8c45fSAndroid Build Coastguard Worker return OK;
1206*38e8c45fSAndroid Build Coastguard Worker }
1207*38e8c45fSAndroid Build Coastguard Worker
1208*38e8c45fSAndroid Build Coastguard Worker // if we can't determine the max buffer count, then just skip growing the history size
1209*38e8c45fSAndroid Build Coastguard Worker size_t newFrameHistorySize = maxBufferCount + 2; // +2 because triple buffer rendering
1210*38e8c45fSAndroid Build Coastguard Worker // optimize away resizing the frame history unless it will grow
1211*38e8c45fSAndroid Build Coastguard Worker if (newFrameHistorySize > FrameEventHistory::INITIAL_MAX_FRAME_HISTORY) {
1212*38e8c45fSAndroid Build Coastguard Worker ALOGV("increasing frame history size to %zu", newFrameHistorySize);
1213*38e8c45fSAndroid Build Coastguard Worker bbq->resizeFrameEventHistory(newFrameHistorySize);
1214*38e8c45fSAndroid Build Coastguard Worker }
1215*38e8c45fSAndroid Build Coastguard Worker
1216*38e8c45fSAndroid Build Coastguard Worker return OK;
1217*38e8c45fSAndroid Build Coastguard Worker }
1218*38e8c45fSAndroid Build Coastguard Worker
query(int what,int * value)1219*38e8c45fSAndroid Build Coastguard Worker int query(int what, int* value) override {
1220*38e8c45fSAndroid Build Coastguard Worker if (what == NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER) {
1221*38e8c45fSAndroid Build Coastguard Worker *value = 1;
1222*38e8c45fSAndroid Build Coastguard Worker return OK;
1223*38e8c45fSAndroid Build Coastguard Worker }
1224*38e8c45fSAndroid Build Coastguard Worker return BufferQueueProducer::query(what, value);
1225*38e8c45fSAndroid Build Coastguard Worker }
1226*38e8c45fSAndroid Build Coastguard Worker
1227*38e8c45fSAndroid Build Coastguard Worker #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
waitForBufferRelease(std::unique_lock<std::mutex> & bufferQueueLock,nsecs_t timeout) const1228*38e8c45fSAndroid Build Coastguard Worker status_t waitForBufferRelease(std::unique_lock<std::mutex>& bufferQueueLock,
1229*38e8c45fSAndroid Build Coastguard Worker nsecs_t timeout) const override {
1230*38e8c45fSAndroid Build Coastguard Worker sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
1231*38e8c45fSAndroid Build Coastguard Worker if (!bbq) {
1232*38e8c45fSAndroid Build Coastguard Worker return OK;
1233*38e8c45fSAndroid Build Coastguard Worker }
1234*38e8c45fSAndroid Build Coastguard Worker
1235*38e8c45fSAndroid Build Coastguard Worker // BufferQueue has already checked if we have a free buffer. If there's an unread interrupt,
1236*38e8c45fSAndroid Build Coastguard Worker // we want to ignore it. This must be done before unlocking the BufferQueue lock to ensure
1237*38e8c45fSAndroid Build Coastguard Worker // we don't miss an interrupt.
1238*38e8c45fSAndroid Build Coastguard Worker bbq->mBufferReleaseReader->clearInterrupts();
1239*38e8c45fSAndroid Build Coastguard Worker UnlockGuard unlockGuard{bufferQueueLock};
1240*38e8c45fSAndroid Build Coastguard Worker
1241*38e8c45fSAndroid Build Coastguard Worker ATRACE_FORMAT("waiting for free buffer");
1242*38e8c45fSAndroid Build Coastguard Worker ReleaseCallbackId id;
1243*38e8c45fSAndroid Build Coastguard Worker sp<Fence> fence;
1244*38e8c45fSAndroid Build Coastguard Worker uint32_t maxAcquiredBufferCount;
1245*38e8c45fSAndroid Build Coastguard Worker status_t status =
1246*38e8c45fSAndroid Build Coastguard Worker bbq->mBufferReleaseReader->readBlocking(id, fence, maxAcquiredBufferCount, timeout);
1247*38e8c45fSAndroid Build Coastguard Worker if (status == TIMED_OUT) {
1248*38e8c45fSAndroid Build Coastguard Worker return TIMED_OUT;
1249*38e8c45fSAndroid Build Coastguard Worker } else if (status != OK) {
1250*38e8c45fSAndroid Build Coastguard Worker // Waiting was interrupted or an error occurred. BufferQueueProducer will check if we
1251*38e8c45fSAndroid Build Coastguard Worker // have a free buffer and call this method again if not.
1252*38e8c45fSAndroid Build Coastguard Worker return OK;
1253*38e8c45fSAndroid Build Coastguard Worker }
1254*38e8c45fSAndroid Build Coastguard Worker
1255*38e8c45fSAndroid Build Coastguard Worker bbq->releaseBufferCallback(id, fence, maxAcquiredBufferCount);
1256*38e8c45fSAndroid Build Coastguard Worker return OK;
1257*38e8c45fSAndroid Build Coastguard Worker }
1258*38e8c45fSAndroid Build Coastguard Worker #endif
1259*38e8c45fSAndroid Build Coastguard Worker
1260*38e8c45fSAndroid Build Coastguard Worker private:
1261*38e8c45fSAndroid Build Coastguard Worker const wp<BLASTBufferQueue> mBLASTBufferQueue;
1262*38e8c45fSAndroid Build Coastguard Worker };
1263*38e8c45fSAndroid Build Coastguard Worker
1264*38e8c45fSAndroid Build Coastguard Worker // Similar to BufferQueue::createBufferQueue but creates an adapter specific bufferqueue producer.
1265*38e8c45fSAndroid Build Coastguard Worker // This BQP allows invoking client specified ProducerListeners and invoke them asynchronously,
1266*38e8c45fSAndroid Build Coastguard Worker // emulating one way binder call behavior. Without this, if the listener calls back into the queue,
1267*38e8c45fSAndroid Build Coastguard Worker // we can deadlock.
createBufferQueue(sp<IGraphicBufferProducer> * outProducer,sp<IGraphicBufferConsumer> * outConsumer)1268*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
1269*38e8c45fSAndroid Build Coastguard Worker sp<IGraphicBufferConsumer>* outConsumer) {
1270*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(outProducer == nullptr, "BLASTBufferQueue: outProducer must not be NULL");
1271*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(outConsumer == nullptr, "BLASTBufferQueue: outConsumer must not be NULL");
1272*38e8c45fSAndroid Build Coastguard Worker
1273*38e8c45fSAndroid Build Coastguard Worker #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
1274*38e8c45fSAndroid Build Coastguard Worker auto core = sp<BBQBufferQueueCore>::make(this);
1275*38e8c45fSAndroid Build Coastguard Worker #else
1276*38e8c45fSAndroid Build Coastguard Worker auto core = sp<BufferQueueCore>::make();
1277*38e8c45fSAndroid Build Coastguard Worker #endif
1278*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(core == nullptr, "BLASTBufferQueue: failed to create BufferQueueCore");
1279*38e8c45fSAndroid Build Coastguard Worker
1280*38e8c45fSAndroid Build Coastguard Worker auto producer = sp<BBQBufferQueueProducer>::make(core, this);
1281*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(producer == nullptr,
1282*38e8c45fSAndroid Build Coastguard Worker "BLASTBufferQueue: failed to create BBQBufferQueueProducer");
1283*38e8c45fSAndroid Build Coastguard Worker
1284*38e8c45fSAndroid Build Coastguard Worker auto consumer = sp<BufferQueueConsumer>::make(core);
1285*38e8c45fSAndroid Build Coastguard Worker consumer->setAllowExtraAcquire(true);
1286*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(consumer == nullptr,
1287*38e8c45fSAndroid Build Coastguard Worker "BLASTBufferQueue: failed to create BufferQueueConsumer");
1288*38e8c45fSAndroid Build Coastguard Worker
1289*38e8c45fSAndroid Build Coastguard Worker *outProducer = producer;
1290*38e8c45fSAndroid Build Coastguard Worker *outConsumer = consumer;
1291*38e8c45fSAndroid Build Coastguard Worker }
1292*38e8c45fSAndroid Build Coastguard Worker
resizeFrameEventHistory(size_t newSize)1293*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::resizeFrameEventHistory(size_t newSize) {
1294*38e8c45fSAndroid Build Coastguard Worker // This can be null during creation of the buffer queue, but resizing won't do anything at that
1295*38e8c45fSAndroid Build Coastguard Worker // point in time, so just ignore. This can go away once the class relationships and lifetimes of
1296*38e8c45fSAndroid Build Coastguard Worker // objects are cleaned up with a major refactor of BufferQueue as a whole.
1297*38e8c45fSAndroid Build Coastguard Worker if (mBufferItemConsumer != nullptr) {
1298*38e8c45fSAndroid Build Coastguard Worker std::unique_lock _lock{mMutex};
1299*38e8c45fSAndroid Build Coastguard Worker mBufferItemConsumer->resizeFrameEventHistory(newSize);
1300*38e8c45fSAndroid Build Coastguard Worker }
1301*38e8c45fSAndroid Build Coastguard Worker }
1302*38e8c45fSAndroid Build Coastguard Worker
convertBufferFormat(PixelFormat & format)1303*38e8c45fSAndroid Build Coastguard Worker PixelFormat BLASTBufferQueue::convertBufferFormat(PixelFormat& format) {
1304*38e8c45fSAndroid Build Coastguard Worker PixelFormat convertedFormat = format;
1305*38e8c45fSAndroid Build Coastguard Worker switch (format) {
1306*38e8c45fSAndroid Build Coastguard Worker case PIXEL_FORMAT_TRANSPARENT:
1307*38e8c45fSAndroid Build Coastguard Worker case PIXEL_FORMAT_TRANSLUCENT:
1308*38e8c45fSAndroid Build Coastguard Worker convertedFormat = PIXEL_FORMAT_RGBA_8888;
1309*38e8c45fSAndroid Build Coastguard Worker break;
1310*38e8c45fSAndroid Build Coastguard Worker case PIXEL_FORMAT_OPAQUE:
1311*38e8c45fSAndroid Build Coastguard Worker convertedFormat = PIXEL_FORMAT_RGBX_8888;
1312*38e8c45fSAndroid Build Coastguard Worker break;
1313*38e8c45fSAndroid Build Coastguard Worker }
1314*38e8c45fSAndroid Build Coastguard Worker return convertedFormat;
1315*38e8c45fSAndroid Build Coastguard Worker }
1316*38e8c45fSAndroid Build Coastguard Worker
getLastTransformHint() const1317*38e8c45fSAndroid Build Coastguard Worker uint32_t BLASTBufferQueue::getLastTransformHint() const {
1318*38e8c45fSAndroid Build Coastguard Worker std::lock_guard _lock{mMutex};
1319*38e8c45fSAndroid Build Coastguard Worker if (mSurfaceControl != nullptr) {
1320*38e8c45fSAndroid Build Coastguard Worker return mSurfaceControl->getTransformHint();
1321*38e8c45fSAndroid Build Coastguard Worker } else {
1322*38e8c45fSAndroid Build Coastguard Worker return 0;
1323*38e8c45fSAndroid Build Coastguard Worker }
1324*38e8c45fSAndroid Build Coastguard Worker }
1325*38e8c45fSAndroid Build Coastguard Worker
getLastAcquiredFrameNum()1326*38e8c45fSAndroid Build Coastguard Worker uint64_t BLASTBufferQueue::getLastAcquiredFrameNum() {
1327*38e8c45fSAndroid Build Coastguard Worker std::lock_guard _lock{mMutex};
1328*38e8c45fSAndroid Build Coastguard Worker return mLastAcquiredFrameNumber;
1329*38e8c45fSAndroid Build Coastguard Worker }
1330*38e8c45fSAndroid Build Coastguard Worker
isSameSurfaceControl(const sp<SurfaceControl> & surfaceControl) const1331*38e8c45fSAndroid Build Coastguard Worker bool BLASTBufferQueue::isSameSurfaceControl(const sp<SurfaceControl>& surfaceControl) const {
1332*38e8c45fSAndroid Build Coastguard Worker std::lock_guard _lock{mMutex};
1333*38e8c45fSAndroid Build Coastguard Worker return SurfaceControl::isSameSurface(mSurfaceControl, surfaceControl);
1334*38e8c45fSAndroid Build Coastguard Worker }
1335*38e8c45fSAndroid Build Coastguard Worker
setTransactionHangCallback(std::function<void (const std::string &)> callback)1336*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::setTransactionHangCallback(
1337*38e8c45fSAndroid Build Coastguard Worker std::function<void(const std::string&)> callback) {
1338*38e8c45fSAndroid Build Coastguard Worker std::lock_guard _lock{mMutex};
1339*38e8c45fSAndroid Build Coastguard Worker mTransactionHangCallback = std::move(callback);
1340*38e8c45fSAndroid Build Coastguard Worker }
1341*38e8c45fSAndroid Build Coastguard Worker
setApplyToken(sp<IBinder> applyToken)1342*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::setApplyToken(sp<IBinder> applyToken) {
1343*38e8c45fSAndroid Build Coastguard Worker std::lock_guard _lock{mMutex};
1344*38e8c45fSAndroid Build Coastguard Worker mApplyToken = std::move(applyToken);
1345*38e8c45fSAndroid Build Coastguard Worker }
1346*38e8c45fSAndroid Build Coastguard Worker
1347*38e8c45fSAndroid Build Coastguard Worker #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
1348*38e8c45fSAndroid Build Coastguard Worker
updateBufferReleaseProducer()1349*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::updateBufferReleaseProducer() {
1350*38e8c45fSAndroid Build Coastguard Worker // SELinux policy may prevent this process from sending the BufferReleaseChannel's file
1351*38e8c45fSAndroid Build Coastguard Worker // descriptor to SurfaceFlinger, causing the entire transaction to be dropped. We send this
1352*38e8c45fSAndroid Build Coastguard Worker // transaction independently of any other updates to ensure those updates aren't lost.
1353*38e8c45fSAndroid Build Coastguard Worker SurfaceComposerClient::Transaction t;
1354*38e8c45fSAndroid Build Coastguard Worker status_t status = t.setApplyToken(mApplyToken)
1355*38e8c45fSAndroid Build Coastguard Worker .setBufferReleaseChannel(mSurfaceControl, mBufferReleaseProducer)
1356*38e8c45fSAndroid Build Coastguard Worker .apply(false /* synchronous */, true /* oneWay */);
1357*38e8c45fSAndroid Build Coastguard Worker if (status != OK) {
1358*38e8c45fSAndroid Build Coastguard Worker ALOGW("[%s] %s - failed to set buffer release channel on %s", mName.c_str(),
1359*38e8c45fSAndroid Build Coastguard Worker statusToString(status).c_str(), mSurfaceControl->getName().c_str());
1360*38e8c45fSAndroid Build Coastguard Worker }
1361*38e8c45fSAndroid Build Coastguard Worker }
1362*38e8c45fSAndroid Build Coastguard Worker
drainBufferReleaseConsumer()1363*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::drainBufferReleaseConsumer() {
1364*38e8c45fSAndroid Build Coastguard Worker ATRACE_CALL();
1365*38e8c45fSAndroid Build Coastguard Worker while (true) {
1366*38e8c45fSAndroid Build Coastguard Worker ReleaseCallbackId id;
1367*38e8c45fSAndroid Build Coastguard Worker sp<Fence> fence;
1368*38e8c45fSAndroid Build Coastguard Worker uint32_t maxAcquiredBufferCount;
1369*38e8c45fSAndroid Build Coastguard Worker status_t status =
1370*38e8c45fSAndroid Build Coastguard Worker mBufferReleaseConsumer->readReleaseFence(id, fence, maxAcquiredBufferCount);
1371*38e8c45fSAndroid Build Coastguard Worker if (status != OK) {
1372*38e8c45fSAndroid Build Coastguard Worker return;
1373*38e8c45fSAndroid Build Coastguard Worker }
1374*38e8c45fSAndroid Build Coastguard Worker releaseBufferCallback(id, fence, maxAcquiredBufferCount);
1375*38e8c45fSAndroid Build Coastguard Worker }
1376*38e8c45fSAndroid Build Coastguard Worker }
1377*38e8c45fSAndroid Build Coastguard Worker
BufferReleaseReader(BLASTBufferQueue & bbq)1378*38e8c45fSAndroid Build Coastguard Worker BLASTBufferQueue::BufferReleaseReader::BufferReleaseReader(BLASTBufferQueue& bbq) : mBbq{bbq} {
1379*38e8c45fSAndroid Build Coastguard Worker mEpollFd = android::base::unique_fd{epoll_create1(EPOLL_CLOEXEC)};
1380*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(!mEpollFd.ok(),
1381*38e8c45fSAndroid Build Coastguard Worker "Failed to create buffer release epoll file descriptor. errno=%d "
1382*38e8c45fSAndroid Build Coastguard Worker "message='%s'",
1383*38e8c45fSAndroid Build Coastguard Worker errno, strerror(errno));
1384*38e8c45fSAndroid Build Coastguard Worker
1385*38e8c45fSAndroid Build Coastguard Worker epoll_event registerEndpointFd{};
1386*38e8c45fSAndroid Build Coastguard Worker registerEndpointFd.events = EPOLLIN;
1387*38e8c45fSAndroid Build Coastguard Worker registerEndpointFd.data.fd = mBbq.mBufferReleaseConsumer->getFd();
1388*38e8c45fSAndroid Build Coastguard Worker status_t status = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, mBbq.mBufferReleaseConsumer->getFd(),
1389*38e8c45fSAndroid Build Coastguard Worker ®isterEndpointFd);
1390*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(status == -1,
1391*38e8c45fSAndroid Build Coastguard Worker "Failed to register buffer release consumer file descriptor with epoll. "
1392*38e8c45fSAndroid Build Coastguard Worker "errno=%d message='%s'",
1393*38e8c45fSAndroid Build Coastguard Worker errno, strerror(errno));
1394*38e8c45fSAndroid Build Coastguard Worker
1395*38e8c45fSAndroid Build Coastguard Worker mEventFd = android::base::unique_fd(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
1396*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(!mEventFd.ok(),
1397*38e8c45fSAndroid Build Coastguard Worker "Failed to create buffer release event file descriptor. errno=%d "
1398*38e8c45fSAndroid Build Coastguard Worker "message='%s'",
1399*38e8c45fSAndroid Build Coastguard Worker errno, strerror(errno));
1400*38e8c45fSAndroid Build Coastguard Worker
1401*38e8c45fSAndroid Build Coastguard Worker epoll_event registerEventFd{};
1402*38e8c45fSAndroid Build Coastguard Worker registerEventFd.events = EPOLLIN;
1403*38e8c45fSAndroid Build Coastguard Worker registerEventFd.data.fd = mEventFd.get();
1404*38e8c45fSAndroid Build Coastguard Worker status = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, mEventFd.get(), ®isterEventFd);
1405*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(status == -1,
1406*38e8c45fSAndroid Build Coastguard Worker "Failed to register buffer release event file descriptor with epoll. "
1407*38e8c45fSAndroid Build Coastguard Worker "errno=%d message='%s'",
1408*38e8c45fSAndroid Build Coastguard Worker errno, strerror(errno));
1409*38e8c45fSAndroid Build Coastguard Worker }
1410*38e8c45fSAndroid Build Coastguard Worker
readBlocking(ReleaseCallbackId & outId,sp<Fence> & outFence,uint32_t & outMaxAcquiredBufferCount,nsecs_t timeout)1411*38e8c45fSAndroid Build Coastguard Worker status_t BLASTBufferQueue::BufferReleaseReader::readBlocking(ReleaseCallbackId& outId,
1412*38e8c45fSAndroid Build Coastguard Worker sp<Fence>& outFence,
1413*38e8c45fSAndroid Build Coastguard Worker uint32_t& outMaxAcquiredBufferCount,
1414*38e8c45fSAndroid Build Coastguard Worker nsecs_t timeout) {
1415*38e8c45fSAndroid Build Coastguard Worker // TODO(b/363290953) epoll_wait only has millisecond timeout precision. If timeout is less than
1416*38e8c45fSAndroid Build Coastguard Worker // 1ms, then we round timeout up to 1ms. Otherwise, we round timeout to the nearest
1417*38e8c45fSAndroid Build Coastguard Worker // millisecond. Once epoll_pwait2 can be used in libgui, we can specify timeout with nanosecond
1418*38e8c45fSAndroid Build Coastguard Worker // precision.
1419*38e8c45fSAndroid Build Coastguard Worker int timeoutMs = -1;
1420*38e8c45fSAndroid Build Coastguard Worker if (timeout == 0) {
1421*38e8c45fSAndroid Build Coastguard Worker timeoutMs = 0;
1422*38e8c45fSAndroid Build Coastguard Worker } else if (timeout > 0) {
1423*38e8c45fSAndroid Build Coastguard Worker const int nsPerMs = 1000000;
1424*38e8c45fSAndroid Build Coastguard Worker if (timeout < nsPerMs) {
1425*38e8c45fSAndroid Build Coastguard Worker timeoutMs = 1;
1426*38e8c45fSAndroid Build Coastguard Worker } else {
1427*38e8c45fSAndroid Build Coastguard Worker timeoutMs = static_cast<int>(
1428*38e8c45fSAndroid Build Coastguard Worker std::chrono::round<std::chrono::milliseconds>(std::chrono::nanoseconds{timeout})
1429*38e8c45fSAndroid Build Coastguard Worker .count());
1430*38e8c45fSAndroid Build Coastguard Worker }
1431*38e8c45fSAndroid Build Coastguard Worker }
1432*38e8c45fSAndroid Build Coastguard Worker
1433*38e8c45fSAndroid Build Coastguard Worker epoll_event event{};
1434*38e8c45fSAndroid Build Coastguard Worker int eventCount;
1435*38e8c45fSAndroid Build Coastguard Worker do {
1436*38e8c45fSAndroid Build Coastguard Worker eventCount = epoll_wait(mEpollFd.get(), &event, 1 /*maxevents*/, timeoutMs);
1437*38e8c45fSAndroid Build Coastguard Worker } while (eventCount == -1 && errno != EINTR);
1438*38e8c45fSAndroid Build Coastguard Worker
1439*38e8c45fSAndroid Build Coastguard Worker if (eventCount == -1) {
1440*38e8c45fSAndroid Build Coastguard Worker ALOGE("epoll_wait error while waiting for buffer release. errno=%d message='%s'", errno,
1441*38e8c45fSAndroid Build Coastguard Worker strerror(errno));
1442*38e8c45fSAndroid Build Coastguard Worker return UNKNOWN_ERROR;
1443*38e8c45fSAndroid Build Coastguard Worker }
1444*38e8c45fSAndroid Build Coastguard Worker
1445*38e8c45fSAndroid Build Coastguard Worker if (eventCount == 0) {
1446*38e8c45fSAndroid Build Coastguard Worker return TIMED_OUT;
1447*38e8c45fSAndroid Build Coastguard Worker }
1448*38e8c45fSAndroid Build Coastguard Worker
1449*38e8c45fSAndroid Build Coastguard Worker if (event.data.fd == mEventFd.get()) {
1450*38e8c45fSAndroid Build Coastguard Worker clearInterrupts();
1451*38e8c45fSAndroid Build Coastguard Worker return WOULD_BLOCK;
1452*38e8c45fSAndroid Build Coastguard Worker }
1453*38e8c45fSAndroid Build Coastguard Worker
1454*38e8c45fSAndroid Build Coastguard Worker return mBbq.mBufferReleaseConsumer->readReleaseFence(outId, outFence,
1455*38e8c45fSAndroid Build Coastguard Worker outMaxAcquiredBufferCount);
1456*38e8c45fSAndroid Build Coastguard Worker }
1457*38e8c45fSAndroid Build Coastguard Worker
interruptBlockingRead()1458*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::BufferReleaseReader::interruptBlockingRead() {
1459*38e8c45fSAndroid Build Coastguard Worker if (eventfd_write(mEventFd.get(), 1) == -1) {
1460*38e8c45fSAndroid Build Coastguard Worker ALOGE("failed to notify dequeue event. errno=%d message='%s'", errno, strerror(errno));
1461*38e8c45fSAndroid Build Coastguard Worker }
1462*38e8c45fSAndroid Build Coastguard Worker }
1463*38e8c45fSAndroid Build Coastguard Worker
clearInterrupts()1464*38e8c45fSAndroid Build Coastguard Worker void BLASTBufferQueue::BufferReleaseReader::clearInterrupts() {
1465*38e8c45fSAndroid Build Coastguard Worker eventfd_t value;
1466*38e8c45fSAndroid Build Coastguard Worker if (eventfd_read(mEventFd.get(), &value) == -1 && errno != EWOULDBLOCK) {
1467*38e8c45fSAndroid Build Coastguard Worker ALOGE("error while reading from eventfd. errno=%d message='%s'", errno, strerror(errno));
1468*38e8c45fSAndroid Build Coastguard Worker }
1469*38e8c45fSAndroid Build Coastguard Worker }
1470*38e8c45fSAndroid Build Coastguard Worker
1471*38e8c45fSAndroid Build Coastguard Worker #endif
1472*38e8c45fSAndroid Build Coastguard Worker
1473*38e8c45fSAndroid Build Coastguard Worker } // namespace android
1474