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