• 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;
48     void addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
49                                   FrameEventHistoryDelta* outDelta) override REQUIRES(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) REQUIRES(mMutex);
55     void getConnectionEvents(uint64_t frameNumber, bool* needsDisconnect);
56 
57 protected:
58     void onSidebandStreamChanged() override REQUIRES(mMutex);
59 
60 private:
61     const wp<BLASTBufferQueue> mBLASTBufferQueue;
62 
63     uint64_t mCurrentFrameNumber = 0;
64 
65     Mutex mMutex;
66     ConsumerFrameEventHistory mFrameEventHistory GUARDED_BY(mMutex);
67     std::queue<uint64_t> mDisconnectEvents GUARDED_BY(mMutex);
68     bool mCurrentlyConnected GUARDED_BY(mMutex);
69     bool mPreviouslyConnected GUARDED_BY(mMutex);
70 };
71 
72 class BLASTBufferQueue
73     : public ConsumerBase::FrameAvailableListener, public BufferItemConsumer::BufferFreedListener
74 {
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 
onBufferFreed(const wp<GraphicBuffer> &)86     void onBufferFreed(const wp<GraphicBuffer>&/* graphicBuffer*/) override { /* TODO */ }
87     void onFrameReplaced(const BufferItem& item) override;
88     void onFrameAvailable(const BufferItem& item) override;
89     void onFrameDequeued(const uint64_t) override;
90     void onFrameCancelled(const uint64_t) override;
91 
92     void transactionCommittedCallback(nsecs_t latchTime, const sp<Fence>& presentFence,
93                                       const std::vector<SurfaceControlStats>& stats);
94     virtual void transactionCallback(nsecs_t latchTime, const sp<Fence>& presentFence,
95                                      const std::vector<SurfaceControlStats>& stats);
96     void releaseBufferCallback(const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
97                                std::optional<uint32_t> currentMaxAcquiredBufferCount);
98     void releaseBufferCallbackLocked(const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
99                                      std::optional<uint32_t> currentMaxAcquiredBufferCount,
100                                      bool fakeRelease);
101     void syncNextTransaction(std::function<void(SurfaceComposerClient::Transaction*)> callback,
102                              bool acquireSingleBuffer = true);
103     void stopContinuousSyncTransaction();
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     void abandon();
119 
120     /**
121      * Set a callback to be invoked when we are hung. The boolean parameter
122      * indicates whether the hang is due to an unfired fence.
123      * TODO: The boolean is always true atm, unfired fence is
124      * the only case we detect.
125      */
126     void setTransactionHangCallback(std::function<void(bool)> callback);
127 
128     virtual ~BLASTBufferQueue();
129 
130 private:
131     friend class BLASTBufferQueueHelper;
132 
133     // can't be copied
134     BLASTBufferQueue& operator = (const BLASTBufferQueue& rhs);
135     BLASTBufferQueue(const BLASTBufferQueue& rhs);
136     void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
137                            sp<IGraphicBufferConsumer>* outConsumer);
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;
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     // Keep a reference to the submitted buffers so we can release when surfaceflinger drops the
172     // buffer or the buffer has been presented and a new buffer is ready to be presented.
173     std::unordered_map<ReleaseCallbackId, BufferItem, ReleaseBufferCallbackIdHash> mSubmitted
174             GUARDED_BY(mMutex);
175 
176     // Keep a queue of the released buffers instead of immediately releasing
177     // the buffers back to the buffer queue. This would be controlled by SF
178     // setting the max acquired buffer count.
179     struct ReleasedBuffer {
180         ReleaseCallbackId callbackId;
181         sp<Fence> releaseFence;
182         bool operator==(const ReleasedBuffer& rhs) const {
183             // Only compare Id so if we somehow got two callbacks
184             // with different fences we don't decrement mNumAcquired
185             // too far.
186             return rhs.callbackId == callbackId;
187         }
188     };
189     std::deque<ReleasedBuffer> mPendingRelease GUARDED_BY(mMutex);
190 
191     ui::Size mSize GUARDED_BY(mMutex);
192     ui::Size mRequestedSize GUARDED_BY(mMutex);
193     int32_t mFormat GUARDED_BY(mMutex);
194 
195     struct BufferInfo {
196         bool hasBuffer = false;
197         uint32_t width;
198         uint32_t height;
199         uint32_t transform;
200         // This is used to check if we should update the blast layer size immediately or wait until
201         // we get the next buffer. This will support scenarios where the layer can change sizes
202         // and the buffer will scale to fit the new size.
203         uint32_t scalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
204         Rect crop;
205 
updateBufferInfo206         void update(bool hasBuffer, uint32_t width, uint32_t height, uint32_t transform,
207                     uint32_t scalingMode, const Rect& crop) {
208             this->hasBuffer = hasBuffer;
209             this->width = width;
210             this->height = height;
211             this->transform = transform;
212             this->scalingMode = scalingMode;
213             if (!crop.isEmpty()) {
214                 this->crop = crop;
215             } else {
216                 this->crop = Rect(width, height);
217             }
218         }
219     };
220 
221     // Last acquired buffer's info. This is used to calculate the correct scale when size change is
222     // requested. We need to use the old buffer's info to determine what scale we need to apply to
223     // ensure the correct size.
224     BufferInfo mLastBufferInfo GUARDED_BY(mMutex);
225     void setMatrix(SurfaceComposerClient::Transaction* t, const BufferInfo& bufferInfo)
226             REQUIRES(mMutex);
227 
228     uint32_t mTransformHint GUARDED_BY(mMutex);
229 
230     sp<IGraphicBufferConsumer> mConsumer;
231     sp<IGraphicBufferProducer> mProducer;
232     sp<BLASTBufferItemConsumer> mBufferItemConsumer;
233 
234     std::function<void(SurfaceComposerClient::Transaction*)> mTransactionReadyCallback
235             GUARDED_BY(mMutex);
236     SurfaceComposerClient::Transaction* mSyncTransaction GUARDED_BY(mMutex);
237     std::vector<std::tuple<uint64_t /* framenumber */, SurfaceComposerClient::Transaction>>
238             mPendingTransactions GUARDED_BY(mMutex);
239 
240     std::queue<std::pair<uint64_t, FrameTimelineInfo>> mPendingFrameTimelines GUARDED_BY(mMutex);
241 
242     // Tracks the last acquired frame number
243     uint64_t mLastAcquiredFrameNumber GUARDED_BY(mMutex) = 0;
244 
245     // Queues up transactions using this token in SurfaceFlinger. This prevents queued up
246     // transactions from other parts of the client from blocking this transaction.
247     const sp<IBinder> mApplyToken GUARDED_BY(mMutex) = new BBinder();
248 
249     // Guards access to mDequeueTimestamps since we cannot hold to mMutex in onFrameDequeued or
250     // we will deadlock.
251     std::mutex mTimestampMutex;
252     // Tracks buffer dequeue times by the client. This info is sent to SurfaceFlinger which uses
253     // it for debugging purposes.
254     std::unordered_map<uint64_t /* bufferId */, nsecs_t> mDequeueTimestamps
255             GUARDED_BY(mTimestampMutex);
256 
257     // Keep track of SurfaceControls that have submitted a transaction and BBQ is waiting on a
258     // callback for them.
259     std::queue<sp<SurfaceControl>> mSurfaceControlsWithPendingCallback GUARDED_BY(mMutex);
260 
261     uint32_t mCurrentMaxAcquiredBufferCount;
262 
263     // Flag to determine if syncTransaction should only acquire a single buffer and then clear or
264     // continue to acquire buffers until explicitly cleared
265     bool mAcquireSingleBuffer GUARDED_BY(mMutex) = true;
266 
267     // True if BBQ will update the destination frame used to scale the buffer to the requested size.
268     // If false, the caller is responsible for updating the destination frame on the BBQ
269     // surfacecontol. This is useful if the caller wants to synchronize the buffer scale with
270     // additional scales in the hierarchy.
271     bool mUpdateDestinationFrame GUARDED_BY(mMutex) = true;
272 
273     // We send all transactions on our apply token over one-way binder calls to avoid blocking
274     // client threads. All of our transactions remain in order, since they are one-way binder calls
275     // from a single process, to a single interface. However once we give up a Transaction for sync
276     // we can start to have ordering issues. When we return from sync to normal frame production,
277     // we wait on the commit callback of sync frames ensuring ordering, however we don't want to
278     // wait on the commit callback for every normal frame (since even emitting them has a
279     // performance cost) this means we need a method to ensure frames are in order when switching
280     // from one-way application on our apply token, to application on some other apply token. We
281     // make use of setBufferHasBarrier to declare this ordering. This boolean simply tracks when we
282     // need to set this flag, notably only in the case where we are transitioning from a previous
283     // transaction applied by us (one way, may not yet have reached server) and an upcoming
284     // transaction that will be applied by some sync consumer.
285     bool mAppliedLastTransaction = false;
286     uint64_t mLastAppliedFrameNumber = 0;
287 
288     std::function<void(bool)> mTransactionHangCallback;
289 
290     std::unordered_set<uint64_t> mSyncedFrameNumbers GUARDED_BY(mMutex);
291 };
292 
293 } // namespace android
294 
295 #endif  // ANDROID_GUI_SURFACE_H
296