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