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