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