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