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  * TODO: add more ducumentation(graphic block life-cycle, waitable object and workaounds)
48  */
49 class C2BufferQueueBlockPool : public C2BlockPool {
50 public:
51     C2BufferQueueBlockPool(const std::shared_ptr<C2Allocator> &allocator, const local_id_t localId);
52 
53     virtual ~C2BufferQueueBlockPool() override;
54 
getAllocatorId()55     virtual C2Allocator::id_t getAllocatorId() const override {
56         return mAllocator->getId();
57     };
58 
getLocalId()59     virtual local_id_t getLocalId() const override {
60         return mLocalId;
61     };
62 
63     virtual c2_status_t fetchGraphicBlock(
64             uint32_t width,
65             uint32_t height,
66             uint32_t format,
67             C2MemoryUsage usage,
68             std::shared_ptr<C2GraphicBlock> *block /* nonnull */) override;
69 
70     virtual c2_status_t fetchGraphicBlock(
71             uint32_t width,
72             uint32_t height,
73             uint32_t format,
74             C2MemoryUsage usage,
75             std::shared_ptr<C2GraphicBlock> *block /* nonnull */,
76             C2Fence *fence /* nonnull */) override;
77 
78     typedef std::function<void(uint64_t producer, int32_t slot, int64_t nsecs)> OnRenderCallback;
79 
80     /**
81      * Sets render callback.
82      *
83      * \param renderCallbak callback to call for all dequeue buffer.
84      */
85     virtual void setRenderCallback(const OnRenderCallback &renderCallback = OnRenderCallback());
86 
87     typedef ::android::hardware::graphics::bufferqueue::V2_0::
88             IGraphicBufferProducer HGraphicBufferProducer;
89     /**
90      * Configures an IGBP in order to create blocks. A newly created block is
91      * dequeued from the configured IGBP. Unique Id of IGBP and the slot number of
92      * blocks are passed via native_handle. Managing IGBP is responsibility of caller.
93      * When IGBP is not configured, block will be created via allocator.
94      * Since zero is not used for Unique Id of IGBP, if IGBP is not configured or producer
95      * is configured as nullptr, unique id which is bundled in native_handle is zero.
96      *
97      * \param producer      the IGBP, which will be used to fetch blocks
98      *                      This could be null, in the case this blockpool will
99      *                      allocate backed GraphicBuffer via allocator(gralloc).
100      */
101     virtual void configureProducer(const android::sp<HGraphicBufferProducer> &producer);
102 
103     /**
104      * Configures an IGBP in order to create blocks. A newly created block is
105      * dequeued from the configured IGBP. Unique Id of IGBP and the slot number of
106      * blocks are passed via native_handle. Managing IGBP is responsibility of caller.
107      * When IGBP is not configured, block will be created via allocator.
108      * Since zero is not used for Unique Id of IGBP, if IGBP is not configured or producer
109      * is configured as nullptr, unique id which is bundled in native_handle is zero.
110      *
111      * \param producer      the IGBP, which will be used to fetch blocks
112      *                      This could be null, in the case this blockpool will
113      *                      allocate backed GraphicBuffer via allocator(gralloc).
114      * \param syncMemory    Shared memory for synchronization of allocation & deallocation.
115      * \param bqId          Id of IGBP
116      * \param generationId  Generation Id for rendering output
117      * \param consumerUsage consumerUsage flagof the IGBP
118      */
119     virtual void configureProducer(
120             const android::sp<HGraphicBufferProducer> &producer,
121             native_handle_t *syncMemory,
122             uint64_t bqId,
123             uint32_t generationId,
124             uint64_t consumerUsage);
125 
126     virtual void getConsumerUsage(uint64_t *consumerUsage);
127 
128     /**
129      * Invalidate the class.
130      *
131      * After the call, fetchGraphicBlock() will return C2_BAD_STATE.
132      */
133     virtual void invalidate();
134 
135     /**
136      * Defer deallocation of cached blocks.
137      *
138      * Deallocation of cached blocks will be deferred until
139      * \clearDeferredBlocks() is called. Or a new block allocation is
140      * requested by \fetchGraphicBlock().
141      */
142     void setDeferDeallocationAfterStop();
143 
144 
145     /**
146      * Clear deferred blocks.
147      *
148      * Deallocation of cached blocks can be deferred by
149      * \setDeferDeallocationAfterStop().
150      * clear(deallocate) those deferred cached blocks explicitly.
151      * Use this interface, if the blockpool could be inactive indefinitely.
152      */
153     void clearDeferredBlocks();
154 
155 private:
156     const std::shared_ptr<C2Allocator> mAllocator;
157     const local_id_t mLocalId;
158 
159     class Impl;
160     std::shared_ptr<Impl> mImpl;
161 
162     friend struct C2BufferQueueBlockPoolData;
163 };
164 
165 class C2SurfaceSyncMemory;
166 
167 struct C2BufferQueueBlockPoolData : public _C2BlockPoolData {
168 public:
169     typedef ::android::hardware::graphics::bufferqueue::V2_0::
170             IGraphicBufferProducer HGraphicBufferProducer;
171 
172     // Create a remote BlockPoolData.
173     C2BufferQueueBlockPoolData(
174             uint32_t generation, uint64_t bqId, int32_t bqSlot,
175             const std::shared_ptr<int> &owner,
176             const android::sp<HGraphicBufferProducer>& producer);
177 
178     // Create a local BlockPoolData.
179     C2BufferQueueBlockPoolData(
180             uint32_t generation, uint64_t bqId, int32_t bqSlot,
181             const std::shared_ptr<int> &owner,
182             const android::sp<HGraphicBufferProducer>& producer,
183             std::shared_ptr<C2SurfaceSyncMemory>);
184 
185     virtual ~C2BufferQueueBlockPoolData() override;
186 
187     virtual type_t getType() const override;
188 
189     int migrate(const android::sp<HGraphicBufferProducer>& producer,
190                 uint32_t toGeneration, uint64_t toUsage, uint64_t toBqId,
191                 android::sp<android::GraphicBuffer>& graphicBuffer, uint32_t oldGeneration,
192                 std::shared_ptr<C2SurfaceSyncMemory> syncMem);
193 private:
194     friend struct _C2BlockFactory;
195 
196     // Methods delegated from _C2BlockFactory.
197     void getBufferQueueData(uint32_t* generation, uint64_t* bqId, int32_t* bqSlot) const;
198     bool holdBlockFromBufferQueue(const std::shared_ptr<int>& owner,
199                                   const android::sp<HGraphicBufferProducer>& igbp,
200                                   std::shared_ptr<C2SurfaceSyncMemory> syncMem);
201     bool beginTransferBlockToClient();
202     bool endTransferBlockToClient(bool transfer);
203     bool beginAttachBlockToBufferQueue();
204     bool endAttachBlockToBufferQueue(const std::shared_ptr<int>& owner,
205                                      const android::sp<HGraphicBufferProducer>& igbp,
206                                      std::shared_ptr<C2SurfaceSyncMemory> syncMem,
207                                      uint32_t generation, uint64_t bqId, int32_t bqSlot);
208     bool displayBlockToBufferQueue();
209 
210     const bool mLocal;
211     bool mHeld;
212 
213     // Data of the corresponding buffer.
214     uint32_t mGeneration;
215     uint64_t mBqId;
216     int32_t mBqSlot;
217 
218     // Data of the current IGBP, updated at migrate(). If the values are
219     // mismatched, then the corresponding buffer will not be cancelled back to
220     // IGBP at the destructor.
221     uint32_t mCurrentGeneration;
222     uint64_t mCurrentBqId;
223 
224     bool mTransfer; // local transfer to remote
225     bool mAttach; // attach on remote
226     bool mDisplay; // display on remote;
227     std::weak_ptr<int> mOwner;
228     android::sp<HGraphicBufferProducer> mIgbp;
229     std::shared_ptr<C2SurfaceSyncMemory> mSyncMem;
230     mutable std::mutex mLock;
231 };
232 
233 #endif // STAGEFRIGHT_CODEC2_BUFFER_PRIV_H_
234