1 /* 2 * Copyright (C) 2018 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 STAGEFRIGHT_CODEC2_BQ_BUFFER_PRIV_H_ 18 #define STAGEFRIGHT_CODEC2_BQ_BUFFER_PRIV_H_ 19 20 #include <android/hardware/graphics/bufferqueue/2.0/IGraphicBufferProducer.h> 21 22 #include <C2Buffer.h> 23 #include <C2BlockInternal.h> 24 25 #include <atomic> 26 #include <functional> 27 #include <mutex> 28 29 namespace android { 30 class GraphicBuffer; 31 } // namespace android 32 33 /** 34 * BufferQueue based BlockPool. 35 * 36 * This creates graphic blocks from BufferQueue. BufferQueue here is HIDL-ized IGBP. 37 * HIDL-ized IGBP enables vendor HAL to call IGBP interfaces via HIDL over process boundary. 38 * HIDL-ized IGBP is called as HGBP. HGBP had been used from multiple places in android, 39 * but now this is the only place HGBP is still used. 40 * 41 * Initially there is no HGBP configured, in the case graphic blocks are allocated 42 * from gralloc directly upon \fetchGraphicBlock() requests. 43 * 44 * HGBP can be configured as null as well, in the case graphic blocks are allocated 45 * from gralloc directly upon \fetchGraphicBlock() requests. 46 * 47 * If a specific HGBP is configured, the HGBP acts as an allocator for creating graphic blocks. 48 * 49 * 50 * HGBP/IGBP and the BlockPool 51 * 52 * GraphicBuffer(s) from BufferQueue(IGBP/IGBC) are based on slot id. 53 * A created GraphicBuffer occupies a slot(so the GraphicBuffer has a slot-id). 54 * A GraphicBuffer is produced and consumed and recyled based on the slot-id 55 * w.r.t. BufferQueue. 56 * 57 * HGBP::dequeueBuffer() returns a slot id where the slot has an available GraphicBuffer. 58 * If it is necessary, HGBP allocates a new GraphicBuffer to the slot and indicates 59 * that a new buffer is allocated as return flag. 60 * To retrieve the GraphicBuffer, HGBP::requestBuffer() along with the slot id 61 * is required. In order to save HGBP remote calls, the blockpool caches the 62 * allocated GraphicBuffer(s) along with the slot information. 63 * 64 * The blockpool provides C2GraphicBlock upon \fetchGraphicBlock(). 65 * The C2GraphicBlock has a native handle, which is extracted from a GraphicBuffer 66 * and then cloned for independent life-cycle with the GraphicBuffer. The GraphicBuffer 67 * is allocated by HGBP::dequeueBuffer() and retrieved by HGBP::requestBuffer() 68 * if there is a HGBP configured. 69 * 70 * 71 * Life-cycle of C2GraphicBlock 72 * 73 * The decoder HAL writes a decoded frame into C2GraphicBlock. Upon 74 * completion, the component sends the block to the client in the remote process 75 * (i.e. to MediaCodec). The remote process renders the frame into the output surface 76 * via IGBP::queueBuffer() (Note: this is not hidlized.). 77 * 78 * If the decoder HAL destroys the C2GraphicBlock without transferring to the 79 * client, the destroy request goes to the BlockPool. Then 80 * the BlockPool free the associated GraphicBuffer from a slot to 81 * HGBP in order to recycle via HGBP::cancelBuffer(). 82 * 83 * 84 * Clearing the Cache(GraphicBuffer) 85 * 86 * When the output surface is switched to a new surface, The GraphicBuffers from 87 * the old surface is either migrated or cleared. 88 * 89 * The GraphicBuffer(s) still in use are migrated to a new surface during 90 * configuration via HGBP::attachBuffer(). The GraphicBuffer(s) not in use are 91 * cleared from the cache inside the BlockPool. 92 * 93 * When the surface is switched to a null surface, all the 94 * GraphicBuffers in the cache are cleared. 95 * 96 * 97 * Workaround w.r.t. b/322731059 (Deferring cleaning the cache) 98 * 99 * Some vendor devices have issues with graphic buffer lifecycle management, 100 * where the graphic buffers get released even when the cloned native handles 101 * in the remote process are not closed yet. This issue led to rare crashes 102 * for those devices when the cache is cleared early. 103 * 104 * We workarounded the crash by deferring the cleaning of the cache. 105 * The workaround is not enabled by default, and can be enabled via a 106 * system property as shown below: 107 * 108 * 'debug.codec2.bqpool_dealloc_after_stop' = 1 109 * 110 * Configuring the debug flag will call \::setDeferDeallocationAfterStop() 111 * after the blockpool creation. This will enable the deferring. 112 * 113 * After enabling the deferring, clearing the GraphicBuffer is delayed until 114 * 1) \::clearDeferredBlocks() is called. 115 * Typically after HAL processes stop() request. 116 * 2) Or a new ::fetchGraphicBlock() is called. 117 * 118 * Since the deferring will delay the deallocation, the deferring will result 119 * in more memory consumption during the brief period. 120 */ 121 class C2BufferQueueBlockPool : public C2BlockPool { 122 public: 123 C2BufferQueueBlockPool(const std::shared_ptr<C2Allocator> &allocator, const local_id_t localId); 124 125 virtual ~C2BufferQueueBlockPool() override; 126 getAllocatorId()127 virtual C2Allocator::id_t getAllocatorId() const override { 128 return mAllocator->getId(); 129 }; 130 getLocalId()131 virtual local_id_t getLocalId() const override { 132 return mLocalId; 133 }; 134 135 virtual c2_status_t fetchGraphicBlock( 136 uint32_t width, 137 uint32_t height, 138 uint32_t format, 139 C2MemoryUsage usage, 140 std::shared_ptr<C2GraphicBlock> *block /* nonnull */) override; 141 142 virtual c2_status_t fetchGraphicBlock( 143 uint32_t width, 144 uint32_t height, 145 uint32_t format, 146 C2MemoryUsage usage, 147 std::shared_ptr<C2GraphicBlock> *block /* nonnull */, 148 C2Fence *fence /* nonnull */) override; 149 150 typedef std::function<void(uint64_t producer, int32_t slot, int64_t nsecs)> OnRenderCallback; 151 152 /** 153 * Sets render callback. 154 * 155 * \param renderCallbak callback to call for all dequeue buffer. 156 */ 157 virtual void setRenderCallback(const OnRenderCallback &renderCallback = OnRenderCallback()); 158 159 typedef ::android::hardware::graphics::bufferqueue::V2_0:: 160 IGraphicBufferProducer HGraphicBufferProducer; 161 /** 162 * Configures an IGBP in order to create blocks. A newly created block is 163 * dequeued from the configured IGBP. Unique Id of IGBP and the slot number of 164 * blocks are passed via native_handle. Managing IGBP is responsibility of caller. 165 * When IGBP is not configured, block will be created via allocator. 166 * Since zero is not used for Unique Id of IGBP, if IGBP is not configured or producer 167 * is configured as nullptr, unique id which is bundled in native_handle is zero. 168 * 169 * \param producer the IGBP, which will be used to fetch blocks 170 * This could be null, in the case this blockpool will 171 * allocate backed GraphicBuffer via allocator(gralloc). 172 */ 173 virtual void configureProducer(const android::sp<HGraphicBufferProducer> &producer); 174 175 /** 176 * Configures an IGBP in order to create blocks. A newly created block is 177 * dequeued from the configured IGBP. Unique Id of IGBP and the slot number of 178 * blocks are passed via native_handle. Managing IGBP is responsibility of caller. 179 * When IGBP is not configured, block will be created via allocator. 180 * Since zero is not used for Unique Id of IGBP, if IGBP is not configured or producer 181 * is configured as nullptr, unique id which is bundled in native_handle is zero. 182 * 183 * \param producer the IGBP, which will be used to fetch blocks 184 * This could be null, in the case this blockpool will 185 * allocate backed GraphicBuffer via allocator(gralloc). 186 * \param syncMemory Shared memory for synchronization of allocation & deallocation. 187 * \param bqId Id of IGBP 188 * \param generationId Generation Id for rendering output 189 * \param consumerUsage consumerUsage flagof the IGBP 190 */ 191 virtual void configureProducer( 192 const android::sp<HGraphicBufferProducer> &producer, 193 native_handle_t *syncMemory, 194 uint64_t bqId, 195 uint32_t generationId, 196 uint64_t consumerUsage); 197 198 virtual void getConsumerUsage(uint64_t *consumerUsage); 199 200 /** 201 * Invalidate the class. 202 * 203 * After the call, fetchGraphicBlock() will return C2_BAD_STATE. 204 */ 205 virtual void invalidate(); 206 207 /** 208 * Defer deallocation of cached blocks. 209 * 210 * Deallocation of cached blocks will be deferred until 211 * \clearDeferredBlocks() is called. Or a new block allocation is 212 * requested by \fetchGraphicBlock(). 213 */ 214 void setDeferDeallocationAfterStop(); 215 216 217 /** 218 * Clear deferred blocks. 219 * 220 * Deallocation of cached blocks can be deferred by 221 * \setDeferDeallocationAfterStop(). 222 * clear(deallocate) those deferred cached blocks explicitly. 223 * Use this interface, if the blockpool could be inactive indefinitely. 224 */ 225 void clearDeferredBlocks(); 226 227 private: 228 const std::shared_ptr<C2Allocator> mAllocator; 229 const local_id_t mLocalId; 230 231 class Impl; 232 std::shared_ptr<Impl> mImpl; 233 234 friend struct C2BufferQueueBlockPoolData; 235 }; 236 237 class C2SurfaceSyncMemory; 238 239 struct C2BufferQueueBlockPoolData : public _C2BlockPoolData { 240 public: 241 typedef ::android::hardware::graphics::bufferqueue::V2_0:: 242 IGraphicBufferProducer HGraphicBufferProducer; 243 244 // Create a remote BlockPoolData. 245 C2BufferQueueBlockPoolData( 246 uint32_t generation, uint64_t bqId, int32_t bqSlot, 247 const std::shared_ptr<int> &owner, 248 const android::sp<HGraphicBufferProducer>& producer); 249 250 // Create a local BlockPoolData. 251 C2BufferQueueBlockPoolData( 252 uint32_t generation, uint64_t bqId, int32_t bqSlot, 253 const std::shared_ptr<int> &owner, 254 const android::sp<HGraphicBufferProducer>& producer, 255 std::shared_ptr<C2SurfaceSyncMemory>); 256 257 virtual ~C2BufferQueueBlockPoolData() override; 258 259 virtual type_t getType() const override; 260 261 int migrate(const android::sp<HGraphicBufferProducer>& producer, 262 uint32_t toGeneration, uint64_t toUsage, uint64_t toBqId, 263 android::sp<android::GraphicBuffer>& graphicBuffer, uint32_t oldGeneration, 264 std::shared_ptr<C2SurfaceSyncMemory> syncMem); 265 private: 266 friend struct _C2BlockFactory; 267 268 // Methods delegated from _C2BlockFactory. 269 void getBufferQueueData(uint32_t* generation, uint64_t* bqId, int32_t* bqSlot) const; 270 bool holdBlockFromBufferQueue(const std::shared_ptr<int>& owner, 271 const android::sp<HGraphicBufferProducer>& igbp, 272 std::shared_ptr<C2SurfaceSyncMemory> syncMem); 273 bool beginTransferBlockToClient(); 274 bool endTransferBlockToClient(bool transfer); 275 bool beginAttachBlockToBufferQueue(); 276 bool endAttachBlockToBufferQueue(const std::shared_ptr<int>& owner, 277 const android::sp<HGraphicBufferProducer>& igbp, 278 std::shared_ptr<C2SurfaceSyncMemory> syncMem, 279 uint32_t generation, uint64_t bqId, int32_t bqSlot); 280 bool displayBlockToBufferQueue(); 281 282 const bool mLocal; 283 bool mHeld; 284 285 // Data of the corresponding buffer. 286 uint32_t mGeneration; 287 uint64_t mBqId; 288 int32_t mBqSlot; 289 290 // Data of the current IGBP, updated at migrate(). If the values are 291 // mismatched, then the corresponding buffer will not be cancelled back to 292 // IGBP at the destructor. 293 uint32_t mCurrentGeneration; 294 uint64_t mCurrentBqId; 295 296 bool mTransfer; // local transfer to remote 297 bool mAttach; // attach on remote 298 bool mDisplay; // display on remote; 299 std::weak_ptr<int> mOwner; 300 android::sp<HGraphicBufferProducer> mIgbp; 301 std::shared_ptr<C2SurfaceSyncMemory> mSyncMem; 302 mutable std::mutex mLock; 303 }; 304 305 #endif // STAGEFRIGHT_CODEC2_BUFFER_PRIV_H_ 306