• 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 <gui/IGraphicBufferProducer.h>
21 #include <gui/BufferItemConsumer.h>
22 #include <gui/BufferItem.h>
23 #include <gui/SurfaceComposerClient.h>
24 
25 #include <utils/Condition.h>
26 #include <utils/Mutex.h>
27 #include <utils/RefBase.h>
28 
29 #include <system/window.h>
30 #include <thread>
31 #include <queue>
32 
33 namespace android {
34 
35 class BLASTBufferQueue;
36 class BufferItemConsumer;
37 
38 class BLASTBufferItemConsumer : public BufferItemConsumer {
39 public:
BLASTBufferItemConsumer(const sp<IGraphicBufferConsumer> & consumer,uint64_t consumerUsage,int bufferCount,bool controlledByApp,wp<BLASTBufferQueue> bbq)40     BLASTBufferItemConsumer(const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage,
41                             int bufferCount, bool controlledByApp, wp<BLASTBufferQueue> bbq)
42           : BufferItemConsumer(consumer, consumerUsage, bufferCount, controlledByApp),
43             mBLASTBufferQueue(std::move(bbq)),
44             mCurrentlyConnected(false),
45             mPreviouslyConnected(false) {}
46 
47     void onDisconnect() override EXCLUDES(mMutex);
48     void addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
49                                   FrameEventHistoryDelta* outDelta) override EXCLUDES(mMutex);
50     void updateFrameTimestamps(uint64_t frameNumber, nsecs_t refreshStartTime,
51                                const sp<Fence>& gpuCompositionDoneFence,
52                                const sp<Fence>& presentFence, const sp<Fence>& prevReleaseFence,
53                                CompositorTiming compositorTiming, nsecs_t latchTime,
54                                nsecs_t dequeueReadyTime) EXCLUDES(mMutex);
55     void getConnectionEvents(uint64_t frameNumber, bool* needsDisconnect) EXCLUDES(mMutex);
56 
57     void resizeFrameEventHistory(size_t newSize);
58 
59 protected:
60     void onSidebandStreamChanged() override EXCLUDES(mMutex);
61 
62 private:
63     const wp<BLASTBufferQueue> mBLASTBufferQueue;
64 
65     uint64_t mCurrentFrameNumber GUARDED_BY(mMutex) = 0;
66 
67     Mutex mMutex;
68     ConsumerFrameEventHistory mFrameEventHistory GUARDED_BY(mMutex);
69     std::queue<uint64_t> mDisconnectEvents GUARDED_BY(mMutex);
70     bool mCurrentlyConnected GUARDED_BY(mMutex);
71     bool mPreviouslyConnected GUARDED_BY(mMutex);
72 };
73 
74 class BLASTBufferQueue : public ConsumerBase::FrameAvailableListener {
75 public:
76     BLASTBufferQueue(const std::string& name, bool updateDestinationFrame = true);
77     BLASTBufferQueue(const std::string& name, const sp<SurfaceControl>& surface, int width,
78                      int height, int32_t format);
79 
getIGraphicBufferProducer()80     sp<IGraphicBufferProducer> getIGraphicBufferProducer() const {
81         return mProducer;
82     }
83     sp<Surface> getSurface(bool includeSurfaceControlHandle);
84     bool isSameSurfaceControl(const sp<SurfaceControl>& surfaceControl) const;
85 
86     void onFrameReplaced(const BufferItem& item) override;
87     void onFrameAvailable(const BufferItem& item) override;
88     void onFrameDequeued(const uint64_t) override;
89     void onFrameCancelled(const uint64_t) override;
90 
91     void transactionCommittedCallback(nsecs_t latchTime, const sp<Fence>& presentFence,
92                                       const std::vector<SurfaceControlStats>& stats);
93     virtual void transactionCallback(nsecs_t latchTime, const sp<Fence>& presentFence,
94                                      const std::vector<SurfaceControlStats>& stats);
95     void releaseBufferCallback(const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
96                                std::optional<uint32_t> currentMaxAcquiredBufferCount);
97     void releaseBufferCallbackLocked(const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
98                                      std::optional<uint32_t> currentMaxAcquiredBufferCount,
99                                      bool fakeRelease) REQUIRES(mMutex);
100     bool syncNextTransaction(std::function<void(SurfaceComposerClient::Transaction*)> callback,
101                              bool acquireSingleBuffer = true);
102     void stopContinuousSyncTransaction();
103     void clearSyncTransaction();
104 
105     void mergeWithNextTransaction(SurfaceComposerClient::Transaction* t, uint64_t frameNumber);
106     void applyPendingTransactions(uint64_t frameNumber);
107     SurfaceComposerClient::Transaction* gatherPendingTransactions(uint64_t frameNumber);
108 
109     void update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height, int32_t format);
110 
111     status_t setFrameRate(float frameRate, int8_t compatibility, bool shouldBeSeamless);
112     status_t setFrameTimelineInfo(uint64_t frameNumber, const FrameTimelineInfo& info);
113 
114     void setSidebandStream(const sp<NativeHandle>& stream);
115 
116     uint32_t getLastTransformHint() const;
117     uint64_t getLastAcquiredFrameNum();
118 
119     /**
120      * Set a callback to be invoked when we are hung. The string parameter
121      * indicates the reason for the hang.
122      */
123     void setTransactionHangCallback(std::function<void(const std::string&)> callback);
124 
125     virtual ~BLASTBufferQueue();
126 
127 private:
128     friend class BLASTBufferQueueHelper;
129     friend class BBQBufferQueueProducer;
130 
131     // can't be copied
132     BLASTBufferQueue& operator = (const BLASTBufferQueue& rhs);
133     BLASTBufferQueue(const BLASTBufferQueue& rhs);
134     void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
135                            sp<IGraphicBufferConsumer>* outConsumer);
136 
137     void resizeFrameEventHistory(size_t newSize);
138 
139     status_t acquireNextBufferLocked(
140             const std::optional<SurfaceComposerClient::Transaction*> transaction) REQUIRES(mMutex);
141     Rect computeCrop(const BufferItem& item) REQUIRES(mMutex);
142     // Return true if we need to reject the buffer based on the scaling mode and the buffer size.
143     bool rejectBuffer(const BufferItem& item) REQUIRES(mMutex);
144     static PixelFormat convertBufferFormat(PixelFormat& format);
145     void mergePendingTransactions(SurfaceComposerClient::Transaction* t, uint64_t frameNumber)
146             REQUIRES(mMutex);
147 
148     void flushShadowQueue() REQUIRES(mMutex);
149     void acquireAndReleaseBuffer() REQUIRES(mMutex);
150     void releaseBuffer(const ReleaseCallbackId& callbackId, const sp<Fence>& releaseFence)
151             REQUIRES(mMutex);
152 
153     std::string mName;
154     // Represents the queued buffer count from buffer queue,
155     // pre-BLAST. This is mNumFrameAvailable (buffers that queued to blast) +
156     // mNumAcquired (buffers that queued to SF)  mPendingRelease.size() (buffers that are held by
157     // blast). This counter is read by android studio profiler.
158     std::string mQueuedBufferTrace;
159     sp<SurfaceControl> mSurfaceControl GUARDED_BY(mMutex);
160 
161     mutable std::mutex mMutex;
162     std::condition_variable mCallbackCV;
163 
164     // BufferQueue internally allows 1 more than
165     // the max to be acquired
166     int32_t mMaxAcquiredBuffers = 1;
167 
168     int32_t mNumFrameAvailable GUARDED_BY(mMutex) = 0;
169     int32_t mNumAcquired GUARDED_BY(mMutex) = 0;
170 
171     // A value used to identify if a producer has been changed for the same SurfaceControl.
172     // This is needed to know when the frame number has been reset to make sure we don't
173     // latch stale buffers and that we don't wait on barriers from an old producer.
174     uint32_t mProducerId = 0;
175 
176     // Keep a reference to the submitted buffers so we can release when surfaceflinger drops the
177     // buffer or the buffer has been presented and a new buffer is ready to be presented.
178     std::unordered_map<ReleaseCallbackId, BufferItem, ReleaseBufferCallbackIdHash> mSubmitted
179             GUARDED_BY(mMutex);
180 
181     // Keep a queue of the released buffers instead of immediately releasing
182     // the buffers back to the buffer queue. This would be controlled by SF
183     // setting the max acquired buffer count.
184     struct ReleasedBuffer {
185         ReleaseCallbackId callbackId;
186         sp<Fence> releaseFence;
187         bool operator==(const ReleasedBuffer& rhs) const {
188             // Only compare Id so if we somehow got two callbacks
189             // with different fences we don't decrement mNumAcquired
190             // too far.
191             return rhs.callbackId == callbackId;
192         }
193     };
194     std::deque<ReleasedBuffer> mPendingRelease GUARDED_BY(mMutex);
195 
196     ui::Size mSize GUARDED_BY(mMutex);
197     ui::Size mRequestedSize GUARDED_BY(mMutex);
198     int32_t mFormat GUARDED_BY(mMutex);
199 
200     struct BufferInfo {
201         bool hasBuffer = false;
202         uint32_t width;
203         uint32_t height;
204         uint32_t transform;
205         // This is used to check if we should update the blast layer size immediately or wait until
206         // we get the next buffer. This will support scenarios where the layer can change sizes
207         // and the buffer will scale to fit the new size.
208         uint32_t scalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
209         Rect crop;
210 
updateBufferInfo211         void update(bool hasBuffer, uint32_t width, uint32_t height, uint32_t transform,
212                     uint32_t scalingMode, const Rect& crop) {
213             this->hasBuffer = hasBuffer;
214             this->width = width;
215             this->height = height;
216             this->transform = transform;
217             this->scalingMode = scalingMode;
218             if (!crop.isEmpty()) {
219                 this->crop = crop;
220             } else {
221                 this->crop = Rect(width, height);
222             }
223         }
224     };
225 
226     // Last acquired buffer's info. This is used to calculate the correct scale when size change is
227     // requested. We need to use the old buffer's info to determine what scale we need to apply to
228     // ensure the correct size.
229     BufferInfo mLastBufferInfo GUARDED_BY(mMutex);
230     void setMatrix(SurfaceComposerClient::Transaction* t, const BufferInfo& bufferInfo)
231             REQUIRES(mMutex);
232 
233     uint32_t mTransformHint GUARDED_BY(mMutex);
234 
235     sp<IGraphicBufferConsumer> mConsumer;
236     sp<IGraphicBufferProducer> mProducer;
237     sp<BLASTBufferItemConsumer> mBufferItemConsumer;
238 
239     std::function<void(SurfaceComposerClient::Transaction*)> mTransactionReadyCallback
240             GUARDED_BY(mMutex);
241     SurfaceComposerClient::Transaction* mSyncTransaction GUARDED_BY(mMutex);
242     std::vector<std::tuple<uint64_t /* framenumber */, SurfaceComposerClient::Transaction>>
243             mPendingTransactions GUARDED_BY(mMutex);
244 
245     std::queue<std::pair<uint64_t, FrameTimelineInfo>> mPendingFrameTimelines GUARDED_BY(mMutex);
246 
247     // Tracks the last acquired frame number
248     uint64_t mLastAcquiredFrameNumber GUARDED_BY(mMutex) = 0;
249 
250     // Queues up transactions using this token in SurfaceFlinger. This prevents queued up
251     // transactions from other parts of the client from blocking this transaction.
252     const sp<IBinder> mApplyToken GUARDED_BY(mMutex) = sp<BBinder>::make();
253 
254     // Guards access to mDequeueTimestamps since we cannot hold to mMutex in onFrameDequeued or
255     // we will deadlock.
256     std::mutex mTimestampMutex;
257     // Tracks buffer dequeue times by the client. This info is sent to SurfaceFlinger which uses
258     // it for debugging purposes.
259     std::unordered_map<uint64_t /* bufferId */, nsecs_t> mDequeueTimestamps
260             GUARDED_BY(mTimestampMutex);
261 
262     // Keep track of SurfaceControls that have submitted a transaction and BBQ is waiting on a
263     // callback for them.
264     std::queue<sp<SurfaceControl>> mSurfaceControlsWithPendingCallback GUARDED_BY(mMutex);
265 
266     uint32_t mCurrentMaxAcquiredBufferCount GUARDED_BY(mMutex);
267 
268     // Flag to determine if syncTransaction should only acquire a single buffer and then clear or
269     // continue to acquire buffers until explicitly cleared
270     bool mAcquireSingleBuffer GUARDED_BY(mMutex) = true;
271 
272     // True if BBQ will update the destination frame used to scale the buffer to the requested size.
273     // If false, the caller is responsible for updating the destination frame on the BBQ
274     // surfacecontol. This is useful if the caller wants to synchronize the buffer scale with
275     // additional scales in the hierarchy.
276     bool mUpdateDestinationFrame GUARDED_BY(mMutex) = true;
277 
278     // We send all transactions on our apply token over one-way binder calls to avoid blocking
279     // client threads. All of our transactions remain in order, since they are one-way binder calls
280     // from a single process, to a single interface. However once we give up a Transaction for sync
281     // we can start to have ordering issues. When we return from sync to normal frame production,
282     // we wait on the commit callback of sync frames ensuring ordering, however we don't want to
283     // wait on the commit callback for every normal frame (since even emitting them has a
284     // performance cost) this means we need a method to ensure frames are in order when switching
285     // from one-way application on our apply token, to application on some other apply token. We
286     // make use of setBufferHasBarrier to declare this ordering. This boolean simply tracks when we
287     // need to set this flag, notably only in the case where we are transitioning from a previous
288     // transaction applied by us (one way, may not yet have reached server) and an upcoming
289     // transaction that will be applied by some sync consumer.
290     bool mAppliedLastTransaction GUARDED_BY(mMutex) = false;
291     uint64_t mLastAppliedFrameNumber GUARDED_BY(mMutex) = 0;
292 
293     std::function<void(const std::string&)> mTransactionHangCallback;
294 
295     std::unordered_set<uint64_t> mSyncedFrameNumbers GUARDED_BY(mMutex);
296 };
297 
298 } // namespace android
299 
300 #endif  // ANDROID_GUI_SURFACE_H
301