xref: /aosp_15_r20/frameworks/native/libs/gui/include/gui/BLASTBufferQueue.h (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ANDROID_GUI_BLAST_BUFFER_QUEUE_H
18 #define ANDROID_GUI_BLAST_BUFFER_QUEUE_H
19 
20 #include <optional>
21 #include <queue>
22 
23 #include <gui/BufferItem.h>
24 #include <gui/BufferItemConsumer.h>
25 #include <gui/IGraphicBufferConsumer.h>
26 #include <gui/IGraphicBufferProducer.h>
27 #include <gui/SurfaceComposerClient.h>
28 
29 #include <utils/Condition.h>
30 #include <utils/Mutex.h>
31 #include <utils/RefBase.h>
32 
33 #include <system/window.h>
34 
35 #include <com_android_graphics_libgui_flags.h>
36 
37 namespace android {
38 
39 class BLASTBufferQueue;
40 class BufferItemConsumer;
41 
42 class BLASTBufferItemConsumer : public BufferItemConsumer {
43 public:
44 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
BLASTBufferItemConsumer(const sp<IGraphicBufferProducer> & producer,const sp<IGraphicBufferConsumer> & consumer,uint64_t consumerUsage,int bufferCount,bool controlledByApp,wp<BLASTBufferQueue> bbq)45     BLASTBufferItemConsumer(const sp<IGraphicBufferProducer>& producer,
46                             const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage,
47                             int bufferCount, bool controlledByApp, wp<BLASTBufferQueue> bbq)
48           : BufferItemConsumer(producer, consumer, consumerUsage, bufferCount, controlledByApp),
49 #else
50     BLASTBufferItemConsumer(const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage,
51                             int bufferCount, bool controlledByApp, wp<BLASTBufferQueue> bbq)
52           : BufferItemConsumer(consumer, consumerUsage, bufferCount, controlledByApp),
53 #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
54             mBLASTBufferQueue(std::move(bbq)),
55             mCurrentlyConnected(false),
56             mPreviouslyConnected(false) {
57     }
58 
59     void onDisconnect() override EXCLUDES(mMutex);
60     void addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
61                                   FrameEventHistoryDelta* outDelta) override EXCLUDES(mMutex);
62     void updateFrameTimestamps(uint64_t frameNumber, uint64_t previousFrameNumber,
63                                nsecs_t refreshStartTime, const sp<Fence>& gpuCompositionDoneFence,
64                                const sp<Fence>& presentFence, const sp<Fence>& prevReleaseFence,
65                                CompositorTiming compositorTiming, nsecs_t latchTime,
66                                nsecs_t dequeueReadyTime) EXCLUDES(mMutex);
67     void getConnectionEvents(uint64_t frameNumber, bool* needsDisconnect) EXCLUDES(mMutex);
68 
69     void resizeFrameEventHistory(size_t newSize);
70 
71 protected:
72     void onSidebandStreamChanged() override EXCLUDES(mMutex);
73 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE)
74     void onSetFrameRate(float frameRate, int8_t compatibility,
75                         int8_t changeFrameRateStrategy) override;
76 #endif
77 
78 private:
79     const wp<BLASTBufferQueue> mBLASTBufferQueue;
80 
81     uint64_t mCurrentFrameNumber GUARDED_BY(mMutex) = 0;
82 
83     Mutex mMutex;
84     ConsumerFrameEventHistory mFrameEventHistory GUARDED_BY(mMutex);
85     std::queue<uint64_t> mDisconnectEvents GUARDED_BY(mMutex);
86     bool mCurrentlyConnected GUARDED_BY(mMutex);
87     bool mPreviouslyConnected GUARDED_BY(mMutex);
88 };
89 
90 class BLASTBufferQueue : public ConsumerBase::FrameAvailableListener {
91 public:
92     BLASTBufferQueue(const std::string& name, bool updateDestinationFrame = true);
93     BLASTBufferQueue(const std::string& name, const sp<SurfaceControl>& surface, int width,
94                      int height, int32_t format);
95 
getIGraphicBufferProducer()96     sp<IGraphicBufferProducer> getIGraphicBufferProducer() const {
97         return mProducer;
98     }
99     sp<Surface> getSurface(bool includeSurfaceControlHandle);
100     bool isSameSurfaceControl(const sp<SurfaceControl>& surfaceControl) const;
101 
102     void onFrameReplaced(const BufferItem& item) override;
103     void onFrameAvailable(const BufferItem& item) override;
104     void onFrameDequeued(const uint64_t) override;
105     void onFrameCancelled(const uint64_t) override;
106 
107     TransactionCompletedCallbackTakesContext makeTransactionCommittedCallbackThunk();
108     void transactionCommittedCallback(nsecs_t latchTime, const sp<Fence>& presentFence,
109                                       const std::vector<SurfaceControlStats>& stats);
110 
111     TransactionCompletedCallbackTakesContext makeTransactionCallbackThunk();
112     virtual void transactionCallback(nsecs_t latchTime, const sp<Fence>& presentFence,
113                                      const std::vector<SurfaceControlStats>& stats);
114 
115     ReleaseBufferCallback makeReleaseBufferCallbackThunk();
116     void releaseBufferCallback(const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
117                                std::optional<uint32_t> currentMaxAcquiredBufferCount);
118     void releaseBufferCallbackLocked(const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
119                                      std::optional<uint32_t> currentMaxAcquiredBufferCount,
120                                      bool fakeRelease) REQUIRES(mMutex);
121 
122     bool syncNextTransaction(std::function<void(SurfaceComposerClient::Transaction*)> callback,
123                              bool acquireSingleBuffer = true);
124     void stopContinuousSyncTransaction();
125     void clearSyncTransaction();
126 
127     void mergeWithNextTransaction(SurfaceComposerClient::Transaction* t, uint64_t frameNumber);
128     void applyPendingTransactions(uint64_t frameNumber);
129     SurfaceComposerClient::Transaction* gatherPendingTransactions(uint64_t frameNumber);
130 
131     void update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height, int32_t format);
132 
133     status_t setFrameRate(float frameRate, int8_t compatibility, bool shouldBeSeamless);
134     status_t setFrameTimelineInfo(uint64_t frameNumber, const FrameTimelineInfo& info);
135 
136     void setSidebandStream(const sp<NativeHandle>& stream);
137 
138     uint32_t getLastTransformHint() const;
139     uint64_t getLastAcquiredFrameNum();
140 
141     /**
142      * Set a callback to be invoked when we are hung. The string parameter
143      * indicates the reason for the hang.
144      */
145     void setTransactionHangCallback(std::function<void(const std::string&)> callback);
146     void setApplyToken(sp<IBinder>);
147     virtual ~BLASTBufferQueue();
148 
149     void onFirstRef() override;
150 
151 private:
152     friend class BLASTBufferQueueHelper;
153     friend class BBQBufferQueueProducer;
154 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
155     friend class BBQBufferQueueCore;
156 #endif
157 
158     // can't be copied
159     BLASTBufferQueue& operator = (const BLASTBufferQueue& rhs);
160     BLASTBufferQueue(const BLASTBufferQueue& rhs);
161     void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
162                            sp<IGraphicBufferConsumer>* outConsumer);
163 
164     void resizeFrameEventHistory(size_t newSize);
165 
166     status_t acquireNextBufferLocked(
167             const std::optional<SurfaceComposerClient::Transaction*> transaction) REQUIRES(mMutex);
168     Rect computeCrop(const BufferItem& item) REQUIRES(mMutex);
169     // Return true if we need to reject the buffer based on the scaling mode and the buffer size.
170     bool rejectBuffer(const BufferItem& item) REQUIRES(mMutex);
171     static PixelFormat convertBufferFormat(PixelFormat& format);
172     void mergePendingTransactions(SurfaceComposerClient::Transaction* t, uint64_t frameNumber)
173             REQUIRES(mMutex);
174 
175     void flushShadowQueue() REQUIRES(mMutex);
176     void acquireAndReleaseBuffer() REQUIRES(mMutex);
177     void releaseBuffer(const ReleaseCallbackId& callbackId, const sp<Fence>& releaseFence)
178             REQUIRES(mMutex);
179 
180     std::string mName;
181     // Represents the queued buffer count from buffer queue,
182     // pre-BLAST. This is mNumFrameAvailable (buffers that queued to blast) +
183     // mNumAcquired (buffers that queued to SF)  mPendingRelease.size() (buffers that are held by
184     // blast). This counter is read by android studio profiler.
185     std::string mQueuedBufferTrace;
186     sp<SurfaceControl> mSurfaceControl GUARDED_BY(mMutex);
187 
188     mutable std::mutex mMutex;
189     std::condition_variable mCallbackCV;
190 
191     // BufferQueue internally allows 1 more than
192     // the max to be acquired
193     int32_t mMaxAcquiredBuffers GUARDED_BY(mMutex) = 1;
194     int32_t mNumFrameAvailable GUARDED_BY(mMutex) = 0;
195     int32_t mNumAcquired GUARDED_BY(mMutex) = 0;
196 
197     // A value used to identify if a producer has been changed for the same SurfaceControl.
198     // This is needed to know when the frame number has been reset to make sure we don't
199     // latch stale buffers and that we don't wait on barriers from an old producer.
200     uint32_t mProducerId = 0;
201 
202     // Keep a reference to the submitted buffers so we can release when surfaceflinger drops the
203     // buffer or the buffer has been presented and a new buffer is ready to be presented.
204     std::unordered_map<ReleaseCallbackId, BufferItem, ReleaseBufferCallbackIdHash> mSubmitted
205             GUARDED_BY(mMutex);
206 
207     // Keep a queue of the released buffers instead of immediately releasing
208     // the buffers back to the buffer queue. This would be controlled by SF
209     // setting the max acquired buffer count.
210     struct ReleasedBuffer {
211         ReleaseCallbackId callbackId;
212         sp<Fence> releaseFence;
213         bool operator==(const ReleasedBuffer& rhs) const {
214             // Only compare Id so if we somehow got two callbacks
215             // with different fences we don't decrement mNumAcquired
216             // too far.
217             return rhs.callbackId == callbackId;
218         }
219     };
220     std::deque<ReleasedBuffer> mPendingRelease GUARDED_BY(mMutex);
221 
222     ui::Size mSize GUARDED_BY(mMutex);
223     ui::Size mRequestedSize GUARDED_BY(mMutex);
224     int32_t mFormat GUARDED_BY(mMutex);
225 
226     // Keep a copy of the current picture profile handle, so it can be moved to a new
227     // SurfaceControl when BBQ migrates via ::update.
228     std::optional<PictureProfileHandle> mPictureProfileHandle;
229 
230     struct BufferInfo {
231         bool hasBuffer = false;
232         uint32_t width;
233         uint32_t height;
234         uint32_t transform;
235         // This is used to check if we should update the blast layer size immediately or wait until
236         // we get the next buffer. This will support scenarios where the layer can change sizes
237         // and the buffer will scale to fit the new size.
238         uint32_t scalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
239         Rect crop;
240 
updateBufferInfo241         void update(bool hasBuffer, uint32_t width, uint32_t height, uint32_t transform,
242                     uint32_t scalingMode, const Rect& crop) {
243             this->hasBuffer = hasBuffer;
244             this->width = width;
245             this->height = height;
246             this->transform = transform;
247             this->scalingMode = scalingMode;
248             if (!crop.isEmpty()) {
249                 this->crop = crop;
250             } else {
251                 this->crop = Rect(width, height);
252             }
253         }
254     };
255 
256     // Last acquired buffer's info. This is used to calculate the correct scale when size change is
257     // requested. We need to use the old buffer's info to determine what scale we need to apply to
258     // ensure the correct size.
259     BufferInfo mLastBufferInfo GUARDED_BY(mMutex);
260     void setMatrix(SurfaceComposerClient::Transaction* t, const BufferInfo& bufferInfo)
261             REQUIRES(mMutex);
262 
263     uint32_t mTransformHint GUARDED_BY(mMutex);
264 
265     sp<IGraphicBufferConsumer> mConsumer;
266     sp<IGraphicBufferProducer> mProducer;
267     sp<BLASTBufferItemConsumer> mBufferItemConsumer;
268 
269     std::function<void(SurfaceComposerClient::Transaction*)> mTransactionReadyCallback
270             GUARDED_BY(mMutex);
271     SurfaceComposerClient::Transaction* mSyncTransaction GUARDED_BY(mMutex);
272     std::vector<std::tuple<uint64_t /* framenumber */, SurfaceComposerClient::Transaction>>
273             mPendingTransactions GUARDED_BY(mMutex);
274 
275     std::queue<std::pair<uint64_t, FrameTimelineInfo>> mPendingFrameTimelines GUARDED_BY(mMutex);
276 
277     // Tracks the last acquired frame number
278     uint64_t mLastAcquiredFrameNumber GUARDED_BY(mMutex) = 0;
279 
280     // Queues up transactions using this token in SurfaceFlinger. This prevents queued up
281     // transactions from other parts of the client from blocking this transaction.
282     sp<IBinder> mApplyToken GUARDED_BY(mMutex) = sp<BBinder>::make();
283 
284     // Guards access to mDequeueTimestamps since we cannot hold to mMutex in onFrameDequeued or
285     // we will deadlock.
286     std::mutex mTimestampMutex;
287     // Tracks buffer dequeue times by the client. This info is sent to SurfaceFlinger which uses
288     // it for debugging purposes.
289     std::unordered_map<uint64_t /* bufferId */, nsecs_t> mDequeueTimestamps
290             GUARDED_BY(mTimestampMutex);
291 
292     // Keep track of SurfaceControls that have submitted a transaction and BBQ is waiting on a
293     // callback for them.
294     std::queue<sp<SurfaceControl>> mSurfaceControlsWithPendingCallback GUARDED_BY(mMutex);
295 
296     uint32_t mCurrentMaxAcquiredBufferCount GUARDED_BY(mMutex);
297 
298     // Flag to determine if syncTransaction should only acquire a single buffer and then clear or
299     // continue to acquire buffers until explicitly cleared
300     bool mAcquireSingleBuffer GUARDED_BY(mMutex) = true;
301 
302     // True if BBQ will update the destination frame used to scale the buffer to the requested size.
303     // If false, the caller is responsible for updating the destination frame on the BBQ
304     // surfacecontol. This is useful if the caller wants to synchronize the buffer scale with
305     // additional scales in the hierarchy.
306     bool mUpdateDestinationFrame GUARDED_BY(mMutex) = true;
307 
308     // We send all transactions on our apply token over one-way binder calls to avoid blocking
309     // client threads. All of our transactions remain in order, since they are one-way binder calls
310     // from a single process, to a single interface. However once we give up a Transaction for sync
311     // we can start to have ordering issues. When we return from sync to normal frame production,
312     // we wait on the commit callback of sync frames ensuring ordering, however we don't want to
313     // wait on the commit callback for every normal frame (since even emitting them has a
314     // performance cost) this means we need a method to ensure frames are in order when switching
315     // from one-way application on our apply token, to application on some other apply token. We
316     // make use of setBufferHasBarrier to declare this ordering. This boolean simply tracks when we
317     // need to set this flag, notably only in the case where we are transitioning from a previous
318     // transaction applied by us (one way, may not yet have reached server) and an upcoming
319     // transaction that will be applied by some sync consumer.
320     bool mAppliedLastTransaction GUARDED_BY(mMutex) = false;
321     uint64_t mLastAppliedFrameNumber GUARDED_BY(mMutex) = 0;
322 
323     std::function<void(const std::string&)> mTransactionHangCallback;
324 
325     std::unordered_set<uint64_t> mSyncedFrameNumbers GUARDED_BY(mMutex);
326 
327 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
328     // BufferReleaseChannel is used to communicate buffer releases from SurfaceFlinger to the
329     // client.
330     std::unique_ptr<gui::BufferReleaseChannel::ConsumerEndpoint> mBufferReleaseConsumer;
331     std::shared_ptr<gui::BufferReleaseChannel::ProducerEndpoint> mBufferReleaseProducer;
332 
333     void updateBufferReleaseProducer() REQUIRES(mMutex);
334     void drainBufferReleaseConsumer();
335 
336     // BufferReleaseReader is used to do blocking but interruptible reads from the buffer
337     // release channel. To implement this, BufferReleaseReader owns an epoll file descriptor that
338     // is configured to wake up when either the BufferReleaseReader::ConsumerEndpoint or an eventfd
339     // becomes readable. Interrupts are necessary because a free buffer may become available for
340     // reasons other than a buffer release from the producer.
341     class BufferReleaseReader {
342     public:
343         explicit BufferReleaseReader(BLASTBufferQueue&);
344 
345         BufferReleaseReader(const BufferReleaseReader&) = delete;
346         BufferReleaseReader& operator=(const BufferReleaseReader&) = delete;
347 
348         // Block until we can read a buffer release message.
349         //
350         // Returns:
351         // * OK if a ReleaseCallbackId and Fence were successfully read.
352         // * WOULD_BLOCK if the blocking read was interrupted by interruptBlockingRead.
353         // * TIMED_OUT if the blocking read timed out.
354         // * UNKNOWN_ERROR if something went wrong.
355         status_t readBlocking(ReleaseCallbackId& outId, sp<Fence>& outReleaseFence,
356                               uint32_t& outMaxAcquiredBufferCount, nsecs_t timeout);
357 
358         void interruptBlockingRead();
359         void clearInterrupts();
360 
361     private:
362         BLASTBufferQueue& mBbq;
363 
364         android::base::unique_fd mEpollFd;
365         android::base::unique_fd mEventFd;
366     };
367 
368     std::optional<BufferReleaseReader> mBufferReleaseReader;
369 #endif
370 };
371 
372 } // namespace android
373 
374 #endif  // ANDROID_GUI_SURFACE_H
375