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 ANDROID_STAGEFRIGHT_C2BLOCK_INTERNAL_H_ 18 #define ANDROID_STAGEFRIGHT_C2BLOCK_INTERNAL_H_ 19 20 #include <android/hardware/graphics/bufferqueue/2.0/IGraphicBufferProducer.h> 21 22 #include <C2Buffer.h> 23 24 namespace android { 25 namespace hardware { 26 namespace media { 27 namespace bufferpool { 28 29 struct BufferPoolData; 30 31 } 32 } 33 } 34 } 35 36 /** 37 * Stores informations from C2BlockPool implementations which are required by C2Block. 38 */ 39 struct C2_HIDE _C2BlockPoolData { 40 enum type_t : int { 41 TYPE_BUFFERPOOL = 0, 42 TYPE_BUFFERQUEUE, 43 }; 44 45 virtual type_t getType() const = 0; 46 47 protected: 48 _C2BlockPoolData() = default; 49 50 virtual ~_C2BlockPoolData() = default; 51 }; 52 53 struct C2BufferQueueBlockPoolData; 54 55 class C2SurfaceSyncMemory; 56 57 /** 58 * Internal only interface for creating blocks by block pool/buffer passing implementations. 59 * 60 * \todo this must be hidden 61 */ 62 struct _C2BlockFactory { 63 /** 64 * Create a linear block from an allocation for an allotted range. 65 * 66 * \param alloc parent allocation 67 * \param data blockpool data 68 * \param offset allotted range offset 69 * \param size allotted size 70 * 71 * \return shared pointer to the linear block. nullptr if there was not enough memory to 72 * create this block. 73 */ 74 static 75 std::shared_ptr<C2LinearBlock> CreateLinearBlock( 76 const std::shared_ptr<C2LinearAllocation> &alloc, 77 const std::shared_ptr<_C2BlockPoolData> &data = nullptr, 78 size_t offset = 0, 79 size_t size = ~(size_t)0); 80 81 /** 82 * Create a graphic block from an allocation for an allotted section. 83 * 84 * \param alloc parent allocation 85 * \param data blockpool data 86 * \param crop allotted crop region 87 * 88 * \return shared pointer to the graphic block. nullptr if there was not enough memory to 89 * create this block. 90 */ 91 static 92 std::shared_ptr<C2GraphicBlock> CreateGraphicBlock( 93 const std::shared_ptr<C2GraphicAllocation> &alloc, 94 const std::shared_ptr<_C2BlockPoolData> &data = nullptr, 95 const C2Rect &allottedCrop = C2Rect(~0u, ~0u)); 96 97 /** 98 * Return a block pool data from 1D block. 99 * 100 * \param shared pointer to the 1D block which is already created. 101 */ 102 static 103 std::shared_ptr<_C2BlockPoolData> GetLinearBlockPoolData( 104 const C2Block1D& block); 105 106 /** 107 * Return a block pool data from 2D block. 108 * 109 * \param shared pointer to the 2D block which is already created. 110 */ 111 static 112 std::shared_ptr<_C2BlockPoolData> GetGraphicBlockPoolData( 113 const C2Block2D& block); 114 115 /** 116 * Create a linear block from the received native handle. 117 * 118 * \param handle native handle to a linear block 119 * 120 * \return shared pointer to the linear block. nullptr if there was not enough memory to 121 * create this block. 122 */ 123 static 124 std::shared_ptr<C2LinearBlock> CreateLinearBlock( 125 const C2Handle *handle); 126 127 /** 128 * Create a graphic block from the received native handle. 129 * 130 * \param handle native handle to a graphic block 131 * 132 * \return shared pointer to the graphic block. nullptr if there was not enough memory to 133 * create this block. 134 */ 135 static 136 std::shared_ptr<C2GraphicBlock> CreateGraphicBlock( 137 const C2Handle *handle); 138 139 /** 140 * Create a linear block from the received bufferpool data. 141 * 142 * \param data bufferpool data to a linear block 143 * 144 * \return shared pointer to the linear block. nullptr if there was not enough memory to 145 * create this block. 146 */ 147 static 148 std::shared_ptr<C2LinearBlock> CreateLinearBlock( 149 const C2Handle *handle, 150 const std::shared_ptr<android::hardware::media::bufferpool::BufferPoolData> &data); 151 152 /** 153 * Create a graphic block from the received bufferpool data. 154 * 155 * \param data bufferpool data to a graphic block 156 * 157 * \return shared pointer to the graphic block. nullptr if there was not enough memory to 158 * create this block. 159 */ 160 static 161 std::shared_ptr<C2GraphicBlock> CreateGraphicBlock( 162 const C2Handle *handle, 163 const std::shared_ptr<android::hardware::media::bufferpool::BufferPoolData> &data); 164 165 /** 166 * Get bufferpool data from the blockpool data. 167 * 168 * \param poolData blockpool data 169 * \param bufferPoolData pointer to bufferpool data where the bufferpool 170 * data is stored. 171 * 172 * \return {\code true} when there is valid bufferpool data, {\code false} otherwise. 173 */ 174 static 175 bool GetBufferPoolData( 176 const std::shared_ptr<const _C2BlockPoolData> &poolData, 177 std::shared_ptr<android::hardware::media::bufferpool::BufferPoolData> *bufferPoolData); 178 179 /* 180 * Life Cycle Management of BufferQueue-Based Blocks 181 * ================================================= 182 * 183 * A block that is created by a bufferqueue-based blockpool requires some 184 * special treatment when it is destroyed. In particular, if the block 185 * corresponds to a held (dequeued/attached) GraphicBuffer in a slot of a 186 * bufferqueue, its destruction should trigger a call to 187 * IGraphicBufferProducer::cancelBuffer(). On the other hand, if the 188 * GraphicBuffer is not held, i.e., if it has been queued or detached, 189 * cancelBuffer() should not be called upon the destruction of the block. 190 * 191 * _C2BlockPoolData created by a bufferqueue-based blockpool includes two 192 * main pieces of information: 193 * - "held" status: Whether cancelBuffer() should be called upon 194 * destruction of the block. 195 * - bufferqueue assignment: The quadruple (igbp, generation, bqId, 196 * bqSlot), where igbp is the IGraphicBufferProducer instance of the 197 * bufferqueue, generation is the latest generation number, of the 198 * bufferqueue, bqId is the globally unique id of the bufferqueue, and 199 * bqSlot is the slot in the bufferqueue. 200 * 201 * igbp is the instance of IGraphicBufferProducer on which cancelBuffer() 202 * will be called if "held" status is true when the block is destroyed. 203 * (bqSlot is an input to cancelBuffer().) However, only generation, bqId 204 * and bqSlot are retained when a block is transferred from one process to 205 * another. It is the responsibility of both the sending and receiving 206 * processes to maintain consistency of "held" status and igbp. Below are 207 * functions provided for this purpose: 208 * 209 * - GetBufferQueueData(): Returns generation, bqId and bqSlot. 210 * - HoldBlockFromBufferQueue(): Sets "held" status to true. 211 * - BeginTransferBlockToClient()/EndTransferBlockToClient(): 212 * Clear "held" status to false if transfer was successful, 213 * otherwise "held" status remains true. 214 * - BeginAttachBlockToBufferQueue()/EndAttachBlockToBufferQueue(): 215 * The will keep "held" status true if attach was eligible. 216 * Otherwise, "held" status is cleared to false. In that case, 217 * ownership of buffer should be transferred to bufferqueue. 218 * - DisplayBlockToBufferQueue() 219 * This will clear "held" status to false. 220 * 221 * All these functions operate on _C2BlockPoolData, which can be obtained by 222 * calling GetGraphicBlockPoolData(). 223 * 224 * Maintaining Consistency with IGraphicBufferProducer Operations 225 * ============================================================== 226 * 227 * dequeueBuffer() 228 * - This function is called by the blockpool. It should not be called 229 * manually. The blockpool will automatically generate the correct 230 * information for _C2BlockPoolData, with "held" status set to true. 231 * 232 * queueBuffer() 233 * - Before queueBuffer() is called, DisplayBlockToBufferQueue() should be 234 * called to test eligibility. If it's not eligible, do not call 235 * queueBuffer(). 236 * 237 * attachBuffer() - remote migration only. 238 * - Local migration on blockpool side will be done automatically by 239 * blockpool. 240 * - Before attachBuffer(), BeginAttachBlockToBufferQueue() should be called 241 * to test eligiblity. 242 * - After attachBuffer() is called, EndAttachBlockToBufferQueue() should 243 * be called. This will set "held" status to true. If it returned 244 * false, cancelBuffer() should be called. 245 * 246 * detachBuffer() - no-op. 247 */ 248 249 /** 250 * Get bufferqueue data from the blockpool data. 251 * 252 * Calling this function with \p generation set to nullptr will return 253 * whether the block comes from a bufferqueue-based blockpool, but will not 254 * fill in the values for \p generation, \p bqId or \p bqSlot. 255 * 256 * \param[in] poolData blockpool data. 257 * \param[out] generation Generation number attached to the buffer. 258 * \param[out] bqId Id of the bufferqueue owning the buffer (block). 259 * \param[out] bqSlot Slot number of the buffer. 260 * 261 * \return \c true when there is valid bufferqueue data; 262 * \c false otherwise. 263 */ 264 static 265 bool GetBufferQueueData( 266 const std::shared_ptr<const _C2BlockPoolData>& poolData, 267 uint32_t* generation = nullptr, 268 uint64_t* bqId = nullptr, 269 int32_t* bqSlot = nullptr); 270 271 /** 272 * Hold a block from the designated bufferqueue. This causes the destruction 273 * of the block to trigger a call to cancelBuffer(). 274 * 275 * This function assumes that \p poolData comes from a bufferqueue-based 276 * block. It does not check if that is the case. 277 * 278 * \param poolData blockpool data associated to the block. 279 * \param owner block owner from client bufferqueue manager. 280 * If this is expired, the block is not owned by client 281 * anymore. 282 * \param igbp \c IGraphicBufferProducer instance to be assigned to the 283 * block. This is not needed when the block is local. 284 * \param syncMem Memory block which will support synchronization 285 * between Framework and HAL. 286 * 287 * \return The previous held status. 288 */ 289 static 290 bool HoldBlockFromBufferQueue( 291 const std::shared_ptr<_C2BlockPoolData>& poolData, 292 const std::shared_ptr<int>& owner, 293 const ::android::sp<::android::hardware::graphics::bufferqueue:: 294 V2_0::IGraphicBufferProducer>& igbp = nullptr, 295 std::shared_ptr<C2SurfaceSyncMemory> syncMem = nullptr); 296 297 /** 298 * Prepare a block to be transferred to other process. This blocks 299 * bufferqueue migration from happening. The block should be in held. 300 * 301 * This function assumes that \p poolData comes from a bufferqueue-based 302 * block. It does not check if that is the case. 303 * 304 * \param poolData blockpool data associated to the block. 305 * 306 * \return true if transfer is eligible, false otherwise. 307 */ 308 static 309 bool BeginTransferBlockToClient( 310 const std::shared_ptr<_C2BlockPoolData>& poolData); 311 312 /** 313 * Called after transferring the specified block is finished. Make sure 314 * that BeginTransferBlockToClient() was called before this call. 315 * 316 * This will unblock bufferqueue migration. If transfer result was 317 * successful, this causes the destruction of the block not to trigger a 318 * call to cancelBuffer(). 319 * This function assumes that \p poolData comes from a bufferqueue-based 320 * block. It does not check if that is the case. 321 * 322 * \param poolData blockpool data associated to the block. 323 * 324 * \return true if transfer began before, false otherwise. 325 */ 326 static 327 bool EndTransferBlockToClient( 328 const std::shared_ptr<_C2BlockPoolData>& poolData, 329 bool transferred); 330 331 /** 332 * Prepare a block to be migrated to another bufferqueue. This blocks 333 * rendering until migration has been finished. The block should be in 334 * held. 335 * 336 * This function assumes that \p poolData comes from a bufferqueue-based 337 * block. It does not check if that is the case. 338 * 339 * \param poolData blockpool data associated to the block. 340 * 341 * \return true if migration is eligible, false otherwise. 342 */ 343 static 344 bool BeginAttachBlockToBufferQueue( 345 const std::shared_ptr<_C2BlockPoolData>& poolData); 346 347 /** 348 * Called after migration of the specified block is finished. Make sure 349 * that BeginAttachBlockToBufferQueue() was called before this call. 350 * 351 * This will unblock rendering. if redering is tried during migration, 352 * this returns false. In that case, cancelBuffer() should be called. 353 * This function assumes that \p poolData comes from a bufferqueue-based 354 * block. It does not check if that is the case. 355 * 356 * \param poolData blockpool data associated to the block. 357 * 358 * \return true if migration is eligible, false otherwise. 359 */ 360 static 361 bool EndAttachBlockToBufferQueue( 362 const std::shared_ptr<_C2BlockPoolData>& poolData, 363 const std::shared_ptr<int>& owner, 364 const ::android::sp<::android::hardware::graphics::bufferqueue:: 365 V2_0::IGraphicBufferProducer>& igbp, 366 std::shared_ptr<C2SurfaceSyncMemory>, 367 uint32_t generation, 368 uint64_t bqId, 369 int32_t bqSlot); 370 371 /** 372 * Indicates a block to be rendered very soon. 373 * 374 * This function assumes that \p poolData comes from a bufferqueue-based 375 * block. It does not check if that is the case. 376 * 377 * \param poolData blockpool data associated to the block. 378 * 379 * \return true if migration is eligible, false otherwise. 380 */ 381 static 382 bool DisplayBlockToBufferQueue( 383 const std::shared_ptr<_C2BlockPoolData>& poolData); 384 }; 385 386 #endif // ANDROID_STAGEFRIGHT_C2BLOCK_INTERNAL_H_ 387 388