• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "C2Buffer"
19 #include <utils/Log.h>
20 
21 #include <list>
22 #include <map>
23 #include <mutex>
24 
25 #include <C2AllocatorBlob.h>
26 #include <C2AllocatorGralloc.h>
27 #include <C2AllocatorIon.h>
28 #include <C2BufferPriv.h>
29 #include <C2BlockInternal.h>
30 #include <C2PlatformSupport.h>
31 #include <bufferpool/ClientManager.h>
32 #include <bufferpool2/ClientManager.h>
33 
34 namespace {
35 
36 using android::C2AllocatorBlob;
37 using android::C2AllocatorGralloc;
38 using android::C2AllocatorIon;
39 
40 namespace bufferpool = android::hardware::media::bufferpool;
41 namespace bufferpool_impl = android::hardware::media::bufferpool::V2_0::implementation;
42 using android::hardware::media::bufferpool::V2_0::ResultStatus;
43 
44 namespace bufferpool2 = aidl::android::hardware::media::bufferpool2;
45 namespace bufferpool2_impl = aidl::android::hardware::media::bufferpool2::implementation;
46 using ResultStatus2 = aidl::android::hardware::media::bufferpool2::ResultStatus;
47 
48 // This anonymous namespace contains the helper classes that allow our implementation to create
49 // block/buffer objects.
50 //
51 // Inherit from the parent, share with the friend.
52 class ReadViewBuddy : public C2ReadView {
53     using C2ReadView::C2ReadView;
54     friend class ::C2ConstLinearBlock;
55 };
56 
57 class WriteViewBuddy : public C2WriteView {
58     using C2WriteView::C2WriteView;
59     friend class ::C2LinearBlock;
60 };
61 
62 class ConstLinearBlockBuddy : public C2ConstLinearBlock {
63     using C2ConstLinearBlock::C2ConstLinearBlock;
64     friend class ::C2LinearBlock;
65 };
66 
67 class LinearBlockBuddy : public C2LinearBlock {
68     using C2LinearBlock::C2LinearBlock;
69     friend class ::C2BasicLinearBlockPool;
70 };
71 
72 class AcquirableReadViewBuddy : public C2Acquirable<C2ReadView> {
73     using C2Acquirable::C2Acquirable;
74     friend class ::C2ConstLinearBlock;
75 };
76 
77 class AcquirableWriteViewBuddy : public C2Acquirable<C2WriteView> {
78     using C2Acquirable::C2Acquirable;
79     friend class ::C2LinearBlock;
80 };
81 
82 class GraphicViewBuddy : public C2GraphicView {
83     using C2GraphicView::C2GraphicView;
84     friend class ::C2ConstGraphicBlock;
85     friend class ::C2GraphicBlock;
86 };
87 
88 class AcquirableConstGraphicViewBuddy : public C2Acquirable<const C2GraphicView> {
89     using C2Acquirable::C2Acquirable;
90     friend class ::C2ConstGraphicBlock;
91 };
92 
93 class AcquirableGraphicViewBuddy : public C2Acquirable<C2GraphicView> {
94     using C2Acquirable::C2Acquirable;
95     friend class ::C2GraphicBlock;
96 };
97 
98 class ConstGraphicBlockBuddy : public C2ConstGraphicBlock {
99     using C2ConstGraphicBlock::C2ConstGraphicBlock;
100     friend class ::C2GraphicBlock;
101 };
102 
103 class GraphicBlockBuddy : public C2GraphicBlock {
104     using C2GraphicBlock::C2GraphicBlock;
105     friend class ::C2BasicGraphicBlockPool;
106 };
107 
108 class BufferDataBuddy : public C2BufferData {
109     using C2BufferData::C2BufferData;
110     friend class ::C2Buffer;
111     friend class ::C2InfoBuffer;
112 };
113 
114 }  // namespace
115 
116 /* ========================================== 1D BLOCK ========================================= */
117 
118 /**
119  * This class is the base class for all 1D block and view implementations.
120  *
121  * This is basically just a placeholder for the underlying 1D allocation and the range of the
122  * alloted portion to this block. There is also a placeholder for a blockpool data.
123  */
124 class C2_HIDE _C2Block1DImpl : public _C2LinearRangeAspect {
125 public:
_C2Block1DImpl(const std::shared_ptr<C2LinearAllocation> & alloc,const std::shared_ptr<_C2BlockPoolData> & poolData=nullptr,size_t offset=0,size_t size=~(size_t)0)126     _C2Block1DImpl(const std::shared_ptr<C2LinearAllocation> &alloc,
127             const std::shared_ptr<_C2BlockPoolData> &poolData = nullptr,
128             size_t offset = 0, size_t size = ~(size_t)0)
129         : _C2LinearRangeAspect(alloc.get(), offset, size),
130           mAllocation(alloc),
131           mPoolData(poolData) { }
132 
_C2Block1DImpl(const _C2Block1DImpl & other,size_t offset=0,size_t size=~(size_t)0)133     _C2Block1DImpl(const _C2Block1DImpl &other, size_t offset = 0, size_t size = ~(size_t)0)
134         : _C2LinearRangeAspect(&other, offset, size),
135           mAllocation(other.mAllocation),
136           mPoolData(other.mPoolData) { }
137 
138     /** returns pool data  */
poolData() const139     std::shared_ptr<_C2BlockPoolData> poolData() const {
140         return mPoolData;
141     }
142 
143     /** returns native handle */
handle() const144     const C2Handle *handle() const {
145         return mAllocation ? mAllocation->handle() : nullptr;
146     }
147 
148     /** returns the allocator's ID */
getAllocatorId() const149     C2Allocator::id_t getAllocatorId() const {
150         // BAD_ID can only happen if this Impl class is initialized for a view - never for a block.
151         return mAllocation ? mAllocation->getAllocatorId() : C2Allocator::BAD_ID;
152     }
153 
getAllocation() const154     std::shared_ptr<C2LinearAllocation> getAllocation() const {
155         return mAllocation;
156     }
157 
158 private:
159     std::shared_ptr<C2LinearAllocation> mAllocation;
160     std::shared_ptr<_C2BlockPoolData> mPoolData;
161 };
162 
163 /**
164  * This class contains the mapped data pointer, and the potential error.
165  *
166  * range is the mapped range of the underlying allocation (which is part of the allotted
167  * range).
168  */
169 class C2_HIDE _C2MappedBlock1DImpl : public _C2Block1DImpl {
170 public:
_C2MappedBlock1DImpl(const _C2Block1DImpl & block,uint8_t * data,size_t offset=0,size_t size=~(size_t)0)171     _C2MappedBlock1DImpl(const _C2Block1DImpl &block, uint8_t *data,
172                          size_t offset = 0, size_t size = ~(size_t)0)
173         : _C2Block1DImpl(block, offset, size), mData(data), mError(C2_OK) { }
174 
_C2MappedBlock1DImpl(c2_status_t error)175     _C2MappedBlock1DImpl(c2_status_t error)
176         : _C2Block1DImpl(nullptr), mData(nullptr), mError(error) {
177         // CHECK(error != C2_OK);
178     }
179 
data() const180     const uint8_t *data() const {
181         return mData;
182     }
183 
data()184     uint8_t *data() {
185         return mData;
186     }
187 
error() const188     c2_status_t error() const {
189         return mError;
190     }
191 
192 private:
193     uint8_t *mData;
194     c2_status_t mError;
195 };
196 
197 /**
198  * Block implementation.
199  */
200 class C2Block1D::Impl : public _C2Block1DImpl {
201     using _C2Block1DImpl::_C2Block1DImpl;
202 };
203 
handle() const204 const C2Handle *C2Block1D::handle() const {
205     return mImpl->handle();
206 };
207 
getAllocatorId() const208 C2Allocator::id_t C2Block1D::getAllocatorId() const {
209     return mImpl->getAllocatorId();
210 };
211 
C2Block1D(std::shared_ptr<Impl> impl,const _C2LinearRangeAspect & range)212 C2Block1D::C2Block1D(std::shared_ptr<Impl> impl, const _C2LinearRangeAspect &range)
213     // always clamp subrange to parent (impl) range for safety
214     : _C2LinearRangeAspect(impl.get(), range.offset(), range.size()), mImpl(impl) {
215 }
216 
217 /**
218  * Read view implementation.
219  *
220  * range of Impl is the mapped range of the underlying allocation (which is part of the allotted
221  * range). range of View is 0 to capacity() (not represented as an actual range). This maps to a
222  * subrange of Impl range starting at mImpl->offset() + _mOffset.
223  */
224 class C2ReadView::Impl : public _C2MappedBlock1DImpl {
225     using _C2MappedBlock1DImpl::_C2MappedBlock1DImpl;
226 };
227 
C2ReadView(std::shared_ptr<Impl> impl,uint32_t offset,uint32_t size)228 C2ReadView::C2ReadView(std::shared_ptr<Impl> impl, uint32_t offset, uint32_t size)
229     : _C2LinearCapacityAspect(C2LinearCapacity(impl->size()).range(offset, size).size()),
230       mImpl(impl),
231       mOffset(C2LinearCapacity(impl->size()).range(offset, size).offset()) { }
232 
C2ReadView(c2_status_t error)233 C2ReadView::C2ReadView(c2_status_t error)
234     : _C2LinearCapacityAspect(0u), mImpl(std::make_shared<Impl>(error)), mOffset(0u) {
235     // CHECK(error != C2_OK);
236 }
237 
data() const238 const uint8_t *C2ReadView::data() const {
239     return mImpl->error() ? nullptr : mImpl->data() + mOffset;
240 }
241 
error() const242 c2_status_t C2ReadView::error() const {
243     return mImpl->error();
244 }
245 
subView(size_t offset,size_t size) const246 C2ReadView C2ReadView::subView(size_t offset, size_t size) const {
247     C2LinearRange subRange(*this, offset, size);
248     return C2ReadView(mImpl, mOffset + subRange.offset(), subRange.size());
249 }
250 
251 /**
252  * Write view implementation.
253  */
254 class C2WriteView::Impl : public _C2MappedBlock1DImpl {
255     using _C2MappedBlock1DImpl::_C2MappedBlock1DImpl;
256 };
257 
C2WriteView(std::shared_ptr<Impl> impl)258 C2WriteView::C2WriteView(std::shared_ptr<Impl> impl)
259 // UGLY: _C2LinearRangeAspect requires a bona-fide object for capacity to prevent spoofing, so
260 // this is what we have to do.
261 // TODO: use childRange
262     : _C2EditableLinearRangeAspect(std::make_unique<C2LinearCapacity>(impl->size()).get()), mImpl(impl) { }
263 
C2WriteView(c2_status_t error)264 C2WriteView::C2WriteView(c2_status_t error)
265     : _C2EditableLinearRangeAspect(nullptr), mImpl(std::make_shared<Impl>(error)) {}
266 
base()267 uint8_t *C2WriteView::base() { return mImpl->data(); }
268 
data()269 uint8_t *C2WriteView::data() { return mImpl->data() + offset(); }
270 
error() const271 c2_status_t C2WriteView::error() const { return mImpl->error(); }
272 
273 /**
274  * Const linear block implementation.
275  */
C2ConstLinearBlock(std::shared_ptr<Impl> impl,const _C2LinearRangeAspect & range,C2Fence fence)276 C2ConstLinearBlock::C2ConstLinearBlock(std::shared_ptr<Impl> impl, const _C2LinearRangeAspect &range, C2Fence fence)
277     : C2Block1D(impl, range), mFence(fence) { }
278 
map() const279 C2Acquirable<C2ReadView> C2ConstLinearBlock::map() const {
280     void *base = nullptr;
281     uint32_t len = size();
282     c2_status_t error = mImpl->getAllocation()->map(
283             offset(), len, { C2MemoryUsage::CPU_READ, 0 }, nullptr, &base);
284     // TODO: wait on fence
285     if (error == C2_OK) {
286         std::shared_ptr<ReadViewBuddy::Impl> rvi = std::shared_ptr<ReadViewBuddy::Impl>(
287                 new ReadViewBuddy::Impl(*mImpl, (uint8_t *)base, offset(), len),
288                 [base, len](ReadViewBuddy::Impl *i) {
289                     (void)i->getAllocation()->unmap(base, len, nullptr);
290                     delete i;
291         });
292         return AcquirableReadViewBuddy(error, C2Fence(), ReadViewBuddy(rvi, 0, len));
293     } else {
294         return AcquirableReadViewBuddy(error, C2Fence(), ReadViewBuddy(error));
295     }
296 }
297 
subBlock(size_t offset_,size_t size_) const298 C2ConstLinearBlock C2ConstLinearBlock::subBlock(size_t offset_, size_t size_) const {
299     C2LinearRange subRange(*mImpl, offset_, size_);
300     return C2ConstLinearBlock(mImpl, subRange, mFence);
301 }
302 
303 /**
304  * Linear block implementation.
305  */
C2LinearBlock(std::shared_ptr<Impl> impl,const _C2LinearRangeAspect & range)306 C2LinearBlock::C2LinearBlock(std::shared_ptr<Impl> impl, const _C2LinearRangeAspect &range)
307     : C2Block1D(impl, range) { }
308 
map()309 C2Acquirable<C2WriteView> C2LinearBlock::map() {
310     void *base = nullptr;
311     uint32_t len = size();
312     c2_status_t error = mImpl->getAllocation()->map(
313             offset(), len, { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE }, nullptr, &base);
314     // TODO: wait on fence
315     if (error == C2_OK) {
316         std::shared_ptr<WriteViewBuddy::Impl> rvi = std::shared_ptr<WriteViewBuddy::Impl>(
317                 new WriteViewBuddy::Impl(*mImpl, (uint8_t *)base, 0, len),
318                 [base, len](WriteViewBuddy::Impl *i) {
319                     (void)i->getAllocation()->unmap(base, len, nullptr);
320                     delete i;
321         });
322         return AcquirableWriteViewBuddy(error, C2Fence(), WriteViewBuddy(rvi));
323     } else {
324         return AcquirableWriteViewBuddy(error, C2Fence(), WriteViewBuddy(error));
325     }
326 }
327 
share(size_t offset_,size_t size_,C2Fence fence)328 C2ConstLinearBlock C2LinearBlock::share(size_t offset_, size_t size_, C2Fence fence) {
329     return ConstLinearBlockBuddy(mImpl, C2LinearRange(*this, offset_, size_), fence);
330 }
331 
C2BasicLinearBlockPool(const std::shared_ptr<C2Allocator> & allocator)332 C2BasicLinearBlockPool::C2BasicLinearBlockPool(
333         const std::shared_ptr<C2Allocator> &allocator)
334   : mAllocator(allocator) { }
335 
fetchLinearBlock(uint32_t capacity,C2MemoryUsage usage,std::shared_ptr<C2LinearBlock> * block)336 c2_status_t C2BasicLinearBlockPool::fetchLinearBlock(
337         uint32_t capacity,
338         C2MemoryUsage usage,
339         std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
340     block->reset();
341 
342     std::shared_ptr<C2LinearAllocation> alloc;
343     c2_status_t err = mAllocator->newLinearAllocation(capacity, usage, &alloc);
344     if (err != C2_OK) {
345         return err;
346     }
347 
348     *block = _C2BlockFactory::CreateLinearBlock(alloc);
349 
350     return C2_OK;
351 }
352 
353 struct C2_HIDE C2PooledBlockPoolData : _C2BlockPoolData {
354 
getTypeC2PooledBlockPoolData355     virtual type_t getType() const override {
356         return TYPE_BUFFERPOOL;
357     }
358 
getBufferPoolDataC2PooledBlockPoolData359     void getBufferPoolData(std::shared_ptr<bufferpool::BufferPoolData> *data) const {
360         *data = mData;
361     }
362 
C2PooledBlockPoolDataC2PooledBlockPoolData363     C2PooledBlockPoolData(const std::shared_ptr<bufferpool::BufferPoolData> &data) : mData(data) {}
364 
~C2PooledBlockPoolDataC2PooledBlockPoolData365     virtual ~C2PooledBlockPoolData() override {}
366 
367 private:
368     std::shared_ptr<bufferpool::BufferPoolData> mData;
369 };
370 
GetBufferPoolData(const std::shared_ptr<const _C2BlockPoolData> & data,std::shared_ptr<bufferpool::BufferPoolData> * bufferPoolData)371 bool _C2BlockFactory::GetBufferPoolData(
372         const std::shared_ptr<const _C2BlockPoolData> &data,
373         std::shared_ptr<bufferpool::BufferPoolData> *bufferPoolData) {
374     if (data && data->getType() == _C2BlockPoolData::TYPE_BUFFERPOOL) {
375         const std::shared_ptr<const C2PooledBlockPoolData> poolData =
376                 std::static_pointer_cast<const C2PooledBlockPoolData>(data);
377         poolData->getBufferPoolData(bufferPoolData);
378         return true;
379     }
380     return false;
381 }
382 
383 struct C2_HIDE C2PooledBlockPoolData2 : _C2BlockPoolData { // AIDL BufferPool(bufferpool2)
384 
getTypeC2PooledBlockPoolData2385     type_t getType() const override {
386         return TYPE_BUFFERPOOL2;
387     }
388 
getBufferPoolDataC2PooledBlockPoolData2389     void getBufferPoolData(std::shared_ptr<bufferpool2::BufferPoolData> *data) const {
390         *data = mData;
391     }
392 
C2PooledBlockPoolData2C2PooledBlockPoolData2393     C2PooledBlockPoolData2(const std::shared_ptr<bufferpool2::BufferPoolData> &data)
394             : mData(data) {}
395 
~C2PooledBlockPoolData2C2PooledBlockPoolData2396     virtual ~C2PooledBlockPoolData2() override {}
397 
398 private:
399     std::shared_ptr<bufferpool2::BufferPoolData> mData;
400 };
401 
GetBufferPoolData(const std::shared_ptr<const _C2BlockPoolData> & data,std::shared_ptr<bufferpool2::BufferPoolData> * bufferPoolData)402 bool _C2BlockFactory::GetBufferPoolData(
403         const std::shared_ptr<const _C2BlockPoolData> &data,
404         std::shared_ptr<bufferpool2::BufferPoolData> *bufferPoolData) {
405     if (data && data->getType() == _C2BlockPoolData::TYPE_BUFFERPOOL2) {
406         const std::shared_ptr<const C2PooledBlockPoolData2> poolData =
407                 std::static_pointer_cast<const C2PooledBlockPoolData2>(data);
408         poolData->getBufferPoolData(bufferPoolData);
409         return true;
410     }
411     return false;
412 }
413 
CreateLinearBlock(const std::shared_ptr<C2LinearAllocation> & alloc,const std::shared_ptr<_C2BlockPoolData> & data,size_t offset,size_t size)414 std::shared_ptr<C2LinearBlock> _C2BlockFactory::CreateLinearBlock(
415         const std::shared_ptr<C2LinearAllocation> &alloc,
416         const std::shared_ptr<_C2BlockPoolData> &data, size_t offset, size_t size) {
417     std::shared_ptr<C2Block1D::Impl> impl =
418         std::make_shared<C2Block1D::Impl>(alloc, data, offset, size);
419     return std::shared_ptr<C2LinearBlock>(new C2LinearBlock(impl, *impl));
420 }
421 
GetLinearBlockPoolData(const C2Block1D & block)422 std::shared_ptr<_C2BlockPoolData> _C2BlockFactory::GetLinearBlockPoolData(
423         const C2Block1D &block) {
424     if (block.mImpl) {
425         return block.mImpl->poolData();
426     }
427     return nullptr;
428 }
429 
CreateLinearBlock(const C2Handle * handle)430 std::shared_ptr<C2LinearBlock> _C2BlockFactory::CreateLinearBlock(
431         const C2Handle *handle) {
432     // TODO: get proper allocator? and mutex?
433     static std::shared_ptr<C2Allocator> sAllocator = []{
434         std::shared_ptr<C2Allocator> allocator;
435         std::shared_ptr<C2AllocatorStore> allocatorStore = android::GetCodec2PlatformAllocatorStore();
436         allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
437 
438         return allocator;
439     }();
440 
441     if (sAllocator == nullptr)
442         return nullptr;
443 
444     bool isValidHandle = sAllocator->checkHandle(handle);
445 
446     std::shared_ptr<C2LinearAllocation> alloc;
447     if (isValidHandle) {
448         c2_status_t err = sAllocator->priorLinearAllocation(handle, &alloc);
449         if (err == C2_OK) {
450             std::shared_ptr<C2LinearBlock> block = _C2BlockFactory::CreateLinearBlock(alloc);
451             return block;
452         }
453     }
454     return nullptr;
455 }
456 
CreateLinearBlock(const C2Handle * cHandle,const std::shared_ptr<bufferpool::BufferPoolData> & data)457 std::shared_ptr<C2LinearBlock> _C2BlockFactory::CreateLinearBlock(
458         const C2Handle *cHandle, const std::shared_ptr<bufferpool::BufferPoolData> &data) {
459     // TODO: get proper allocator? and mutex?
460     static std::shared_ptr<C2Allocator> sAllocator = []{
461         std::shared_ptr<C2Allocator> allocator;
462         std::shared_ptr<C2AllocatorStore> allocatorStore = android::GetCodec2PlatformAllocatorStore();
463         allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
464 
465         return allocator;
466     }();
467 
468     if (sAllocator == nullptr)
469         return nullptr;
470 
471     bool isValidHandle = sAllocator->checkHandle(cHandle);
472 
473     std::shared_ptr<C2LinearAllocation> alloc;
474     if (isValidHandle) {
475         c2_status_t err = sAllocator->priorLinearAllocation(cHandle, &alloc);
476         const std::shared_ptr<C2PooledBlockPoolData> poolData =
477                 std::make_shared<C2PooledBlockPoolData>(data);
478         if (err == C2_OK && poolData) {
479             // TODO: config params?
480             std::shared_ptr<C2LinearBlock> block =
481                     _C2BlockFactory::CreateLinearBlock(alloc, poolData);
482             return block;
483         }
484     }
485     return nullptr;
486 };
487 
CreateLinearBlock(const C2Handle * cHandle,const std::shared_ptr<bufferpool2::BufferPoolData> & data)488 std::shared_ptr<C2LinearBlock> _C2BlockFactory::CreateLinearBlock(
489         const C2Handle *cHandle, const std::shared_ptr<bufferpool2::BufferPoolData> &data) {
490     // TODO: get proper allocator? and mutex?
491     static std::shared_ptr<C2Allocator> sAllocator = []{
492         std::shared_ptr<C2Allocator> allocator;
493         std::shared_ptr<C2AllocatorStore> allocatorStore =
494                 android::GetCodec2PlatformAllocatorStore();
495         allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
496 
497         return allocator;
498     }();
499 
500     if (sAllocator == nullptr)
501         return nullptr;
502 
503     bool isValidHandle = sAllocator->checkHandle(cHandle);
504 
505     std::shared_ptr<C2LinearAllocation> alloc;
506     if (isValidHandle) {
507         c2_status_t err = sAllocator->priorLinearAllocation(cHandle, &alloc);
508         const std::shared_ptr<C2PooledBlockPoolData2> poolData =
509                 std::make_shared<C2PooledBlockPoolData2>(data);
510         if (err == C2_OK && poolData) {
511             // TODO: config params?
512             std::shared_ptr<C2LinearBlock> block =
513                     _C2BlockFactory::CreateLinearBlock(alloc, poolData);
514             return block;
515         }
516     }
517     return nullptr;
518 };
519 
520 /**
521  * Wrapped C2Allocator which is injected to buffer pool on behalf of
522  * C2BlockPool.
523  */
524 class _C2BufferPoolAllocator : public bufferpool_impl::BufferPoolAllocator {
525 public:
_C2BufferPoolAllocator(const std::shared_ptr<C2Allocator> & allocator)526     _C2BufferPoolAllocator(const std::shared_ptr<C2Allocator> &allocator)
527         : mAllocator(allocator) {}
528 
~_C2BufferPoolAllocator()529     ~_C2BufferPoolAllocator() override {}
530 
531     ResultStatus allocate(const std::vector<uint8_t> &params,
532                           std::shared_ptr<bufferpool_impl::BufferPoolAllocation> *alloc,
533                           size_t *allocSize) override;
534 
535     bool compatible(const std::vector<uint8_t> &newParams,
536                     const std::vector<uint8_t> &oldParams) override;
537 
538     // Methods for codec2 component (C2BlockPool).
539     /**
540      * Transforms linear allocation parameters for C2Allocator to parameters
541      * for buffer pool.
542      *
543      * @param capacity      size of linear allocation
544      * @param usage         memory usage pattern for linear allocation
545      * @param params        allocation parameters for buffer pool
546      */
547     void getLinearParams(uint32_t capacity, C2MemoryUsage usage,
548                          std::vector<uint8_t> *params);
549 
550     /**
551      * Transforms graphic allocation parameters for C2Allocator to parameters
552      * for buffer pool.
553      *
554      * @param width         width of graphic allocation
555      * @param height        height of graphic allocation
556      * @param format        color format of graphic allocation
557      * @param params        allocation parameter for buffer pool
558      */
559     void getGraphicParams(uint32_t width, uint32_t height,
560                           uint32_t format, C2MemoryUsage usage,
561                           std::vector<uint8_t> *params);
562 
563     /**
564      * Transforms an existing native handle to a C2LinearAllocation.
565      * Wrapper to C2Allocator#priorLinearAllocation
566      */
567     c2_status_t priorLinearAllocation(
568             const C2Handle *handle,
569             std::shared_ptr<C2LinearAllocation> *c2Allocation);
570 
571     /**
572      * Transforms an existing native handle to a C2GraphicAllocation.
573      * Wrapper to C2Allocator#priorGraphicAllocation
574      */
575     c2_status_t priorGraphicAllocation(
576             const C2Handle *handle,
577             std::shared_ptr<C2GraphicAllocation> *c2Allocation);
578 
579 private:
580     static constexpr int kMaxIntParams = 5; // large enough number;
581 
582     enum AllocType : uint8_t {
583         ALLOC_NONE = 0,
584 
585         ALLOC_LINEAR,
586         ALLOC_GRAPHIC,
587     };
588 
589     union AllocParams {
590         struct {
591             AllocType allocType;
592             C2MemoryUsage usage;
593             uint32_t params[kMaxIntParams];
594         } data;
595         uint8_t array[0];
596 
AllocParams()597         AllocParams() : data{ALLOC_NONE, {0, 0}, {0}} {}
AllocParams(C2MemoryUsage usage,uint32_t capacity)598         AllocParams(C2MemoryUsage usage, uint32_t capacity)
599             : data{ALLOC_LINEAR, usage, {[0] = capacity}} {}
AllocParams(C2MemoryUsage usage,uint32_t width,uint32_t height,uint32_t format)600         AllocParams(
601                 C2MemoryUsage usage,
602                 uint32_t width, uint32_t height, uint32_t format)
603                 : data{ALLOC_GRAPHIC, usage, {width, height, format}} {}
604     };
605 
606     const std::shared_ptr<C2Allocator> mAllocator;
607 };
608 
609 struct LinearAllocationDtor {
LinearAllocationDtorLinearAllocationDtor610     LinearAllocationDtor(const std::shared_ptr<C2LinearAllocation> &alloc)
611         : mAllocation(alloc) {}
612 
operator ()LinearAllocationDtor613     void operator()(bufferpool_impl::BufferPoolAllocation *poolAlloc) { delete poolAlloc; }
614 
615     const std::shared_ptr<C2LinearAllocation> mAllocation;
616 };
617 
618 struct GraphicAllocationDtor {
GraphicAllocationDtorGraphicAllocationDtor619     GraphicAllocationDtor(const std::shared_ptr<C2GraphicAllocation> &alloc)
620         : mAllocation(alloc) {}
621 
operator ()GraphicAllocationDtor622     void operator()(bufferpool_impl::BufferPoolAllocation *poolAlloc) { delete poolAlloc; }
623 
624     const std::shared_ptr<C2GraphicAllocation> mAllocation;
625 };
626 
allocate(const std::vector<uint8_t> & params,std::shared_ptr<bufferpool_impl::BufferPoolAllocation> * alloc,size_t * allocSize)627 ResultStatus _C2BufferPoolAllocator::allocate(
628         const std::vector<uint8_t>  &params,
629         std::shared_ptr<bufferpool_impl::BufferPoolAllocation> *alloc,
630         size_t *allocSize) {
631     AllocParams c2Params;
632     memcpy(&c2Params, params.data(), std::min(sizeof(AllocParams), params.size()));
633     c2_status_t status = C2_BAD_VALUE;
634     switch(c2Params.data.allocType) {
635         case ALLOC_NONE:
636             break;
637         case ALLOC_LINEAR: {
638             std::shared_ptr<C2LinearAllocation> c2Linear;
639             status = mAllocator->newLinearAllocation(
640                     c2Params.data.params[0], c2Params.data.usage, &c2Linear);
641             if (status == C2_OK && c2Linear) {
642                 bufferpool_impl::BufferPoolAllocation *ptr =
643                         new bufferpool_impl::BufferPoolAllocation(c2Linear->handle());
644                 if (ptr) {
645                     *alloc = std::shared_ptr<bufferpool_impl::BufferPoolAllocation>(
646                             ptr, LinearAllocationDtor(c2Linear));
647                     if (*alloc) {
648                         *allocSize = (size_t)c2Params.data.params[0];
649                         return ResultStatus::OK;
650                     }
651                     delete ptr;
652                 }
653                 return ResultStatus::NO_MEMORY;
654             }
655             break;
656         }
657         case ALLOC_GRAPHIC: {
658             std::shared_ptr<C2GraphicAllocation> c2Graphic;
659             status = mAllocator->newGraphicAllocation(
660                     c2Params.data.params[0],
661                     c2Params.data.params[1],
662                     c2Params.data.params[2],
663                     c2Params.data.usage, &c2Graphic);
664             if (status == C2_OK && c2Graphic) {
665                 bufferpool_impl::BufferPoolAllocation *ptr =
666                         new bufferpool_impl::BufferPoolAllocation(c2Graphic->handle());
667                 if (ptr) {
668                     *alloc = std::shared_ptr<bufferpool_impl::BufferPoolAllocation>(
669                             ptr, GraphicAllocationDtor(c2Graphic));
670                     if (*alloc) {
671                         *allocSize = c2Params.data.params[0] * c2Params.data.params[1];
672                         return ResultStatus::OK;
673                     }
674                     delete ptr;
675                 }
676                 return ResultStatus::NO_MEMORY;
677             }
678             break;
679         }
680         default:
681             break;
682     }
683     return ResultStatus::CRITICAL_ERROR;
684 }
685 
compatible(const std::vector<uint8_t> & newParams,const std::vector<uint8_t> & oldParams)686 bool _C2BufferPoolAllocator::compatible(
687         const std::vector<uint8_t>  &newParams,
688         const std::vector<uint8_t>  &oldParams) {
689     AllocParams newAlloc;
690     AllocParams oldAlloc;
691     memcpy(&newAlloc, newParams.data(), std::min(sizeof(AllocParams), newParams.size()));
692     memcpy(&oldAlloc, oldParams.data(), std::min(sizeof(AllocParams), oldParams.size()));
693 
694     // TODO: support not exact matching. e.g.) newCapacity < oldCapacity
695     if (newAlloc.data.allocType == oldAlloc.data.allocType &&
696             newAlloc.data.usage.expected == oldAlloc.data.usage.expected) {
697         for (int i = 0; i < kMaxIntParams; ++i) {
698             if (newAlloc.data.params[i] != oldAlloc.data.params[i]) {
699                 return false;
700             }
701         }
702         return true;
703     }
704     return false;
705 }
706 
getLinearParams(uint32_t capacity,C2MemoryUsage usage,std::vector<uint8_t> * params)707 void _C2BufferPoolAllocator::getLinearParams(
708         uint32_t capacity, C2MemoryUsage usage, std::vector<uint8_t> *params) {
709     AllocParams c2Params(usage, capacity);
710     params->assign(c2Params.array, c2Params.array + sizeof(AllocParams));
711 }
712 
getGraphicParams(uint32_t width,uint32_t height,uint32_t format,C2MemoryUsage usage,std::vector<uint8_t> * params)713 void _C2BufferPoolAllocator::getGraphicParams(
714         uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
715         std::vector<uint8_t> *params) {
716     AllocParams c2Params(usage, width, height, format);
717     params->assign(c2Params.array, c2Params.array + sizeof(AllocParams));
718 }
719 
priorLinearAllocation(const C2Handle * handle,std::shared_ptr<C2LinearAllocation> * c2Allocation)720 c2_status_t _C2BufferPoolAllocator::priorLinearAllocation(
721         const C2Handle *handle,
722         std::shared_ptr<C2LinearAllocation> *c2Allocation) {
723     return mAllocator->priorLinearAllocation(handle, c2Allocation);
724 }
725 
priorGraphicAllocation(const C2Handle * handle,std::shared_ptr<C2GraphicAllocation> * c2Allocation)726 c2_status_t _C2BufferPoolAllocator::priorGraphicAllocation(
727         const C2Handle *handle,
728         std::shared_ptr<C2GraphicAllocation> *c2Allocation) {
729     return mAllocator->priorGraphicAllocation(handle, c2Allocation);
730 }
731 
732 class C2PooledBlockPool::Impl {
733 public:
Impl(const std::shared_ptr<C2Allocator> & allocator)734     Impl(const std::shared_ptr<C2Allocator> &allocator)
735             : mInit(C2_OK),
736               mBufferPoolManager(bufferpool_impl::ClientManager::getInstance()),
737               mAllocator(std::make_shared<_C2BufferPoolAllocator>(allocator)) {
738         if (mAllocator && mBufferPoolManager) {
739             if (mBufferPoolManager->create(
740                     mAllocator, &mConnectionId) == ResultStatus::OK) {
741                 return;
742             }
743         }
744         mInit = C2_NO_INIT;
745     }
746 
~Impl()747     ~Impl() {
748         if (mInit == C2_OK) {
749             mBufferPoolManager->close(mConnectionId);
750         }
751     }
752 
fetchLinearBlock(uint32_t capacity,C2MemoryUsage usage,std::shared_ptr<C2LinearBlock> * block)753     c2_status_t fetchLinearBlock(
754             uint32_t capacity, C2MemoryUsage usage,
755             std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
756         block->reset();
757         if (mInit != C2_OK) {
758             return mInit;
759         }
760         std::vector<uint8_t> params;
761         mAllocator->getLinearParams(capacity, usage, &params);
762         std::shared_ptr<bufferpool::BufferPoolData> bufferPoolData;
763         native_handle_t *cHandle = nullptr;
764         ResultStatus status = mBufferPoolManager->allocate(
765                 mConnectionId, params, &cHandle, &bufferPoolData);
766         if (status == ResultStatus::OK) {
767             std::shared_ptr<C2LinearAllocation> alloc;
768             std::shared_ptr<C2PooledBlockPoolData> poolData =
769                     std::make_shared<C2PooledBlockPoolData>(bufferPoolData);
770             c2_status_t err = mAllocator->priorLinearAllocation(cHandle, &alloc);
771             if (err == C2_OK && poolData && alloc) {
772                 *block = _C2BlockFactory::CreateLinearBlock(alloc, poolData, 0, capacity);
773                 if (*block) {
774                     return C2_OK;
775                 }
776             }
777             return C2_NO_MEMORY;
778         }
779         if (status == ResultStatus::NO_MEMORY) {
780             return C2_NO_MEMORY;
781         }
782         return C2_CORRUPTED;
783     }
784 
fetchGraphicBlock(uint32_t width,uint32_t height,uint32_t format,C2MemoryUsage usage,std::shared_ptr<C2GraphicBlock> * block)785     c2_status_t fetchGraphicBlock(
786             uint32_t width, uint32_t height, uint32_t format,
787             C2MemoryUsage usage,
788             std::shared_ptr<C2GraphicBlock> *block) {
789         block->reset();
790         if (mInit != C2_OK) {
791             return mInit;
792         }
793         std::vector<uint8_t> params;
794         mAllocator->getGraphicParams(width, height, format, usage, &params);
795         std::shared_ptr<bufferpool::BufferPoolData> bufferPoolData;
796         native_handle_t *cHandle = nullptr;
797         ResultStatus status = mBufferPoolManager->allocate(
798                 mConnectionId, params, &cHandle, &bufferPoolData);
799         if (status == ResultStatus::OK) {
800             std::shared_ptr<C2GraphicAllocation> alloc;
801             std::shared_ptr<C2PooledBlockPoolData> poolData =
802                 std::make_shared<C2PooledBlockPoolData>(bufferPoolData);
803             c2_status_t err = mAllocator->priorGraphicAllocation(
804                     cHandle, &alloc);
805             if (err == C2_OK && poolData && alloc) {
806                 *block = _C2BlockFactory::CreateGraphicBlock(
807                         alloc, poolData, C2Rect(width, height));
808                 if (*block) {
809                     return C2_OK;
810                 }
811             }
812             return C2_NO_MEMORY;
813         }
814         if (status == ResultStatus::NO_MEMORY) {
815             return C2_NO_MEMORY;
816         }
817         return C2_CORRUPTED;
818     }
819 
getConnectionId()820     bufferpool_impl::ConnectionId getConnectionId() {
821         return mInit != C2_OK ? bufferpool_impl::INVALID_CONNECTIONID : mConnectionId;
822     }
823 
824 private:
825     c2_status_t mInit;
826     const android::sp<bufferpool_impl::ClientManager> mBufferPoolManager;
827     bufferpool_impl::ConnectionId mConnectionId; // locally
828     const std::shared_ptr<_C2BufferPoolAllocator> mAllocator;
829 };
830 
831 /**
832  * Wrapped C2Allocator which is injected to AIDL buffer pool on behalf of
833  * C2BlockPool.
834  */
835 class _C2BufferPoolAllocator2 : public bufferpool2_impl::BufferPoolAllocator {
836 public:
_C2BufferPoolAllocator2(const std::shared_ptr<C2Allocator> & allocator)837     _C2BufferPoolAllocator2(const std::shared_ptr<C2Allocator> &allocator)
838         : mAllocator(allocator) {}
839 
~_C2BufferPoolAllocator2()840     ~_C2BufferPoolAllocator2() override {}
841 
842     bufferpool2_impl::BufferPoolStatus allocate(const std::vector<uint8_t> &params,
843                           std::shared_ptr<bufferpool2_impl::BufferPoolAllocation> *alloc,
844                           size_t *allocSize) override;
845 
846     bool compatible(const std::vector<uint8_t> &newParams,
847                     const std::vector<uint8_t> &oldParams) override;
848 
849     // Methods for codec2 component (C2BlockPool).
850     /**
851      * Transforms linear allocation parameters for C2Allocator to parameters
852      * for buffer pool.
853      *
854      * @param capacity      size of linear allocation
855      * @param usage         memory usage pattern for linear allocation
856      * @param params        allocation parameters for buffer pool
857      */
858     void getLinearParams(uint32_t capacity, C2MemoryUsage usage,
859                          std::vector<uint8_t> *params);
860 
861     /**
862      * Transforms graphic allocation parameters for C2Allocator to parameters
863      * for buffer pool.
864      *
865      * @param width         width of graphic allocation
866      * @param height        height of graphic allocation
867      * @param format        color format of graphic allocation
868      * @param params        allocation parameter for buffer pool
869      */
870     void getGraphicParams(uint32_t width, uint32_t height,
871                           uint32_t format, C2MemoryUsage usage,
872                           std::vector<uint8_t> *params);
873 
874     /**
875      * Transforms an existing native handle to a C2LinearAllocation.
876      * Wrapper to C2Allocator#priorLinearAllocation
877      */
878     c2_status_t priorLinearAllocation(
879             const C2Handle *handle,
880             std::shared_ptr<C2LinearAllocation> *c2Allocation);
881 
882     /**
883      * Transforms an existing native handle to a C2GraphicAllocation.
884      * Wrapper to C2Allocator#priorGraphicAllocation
885      */
886     c2_status_t priorGraphicAllocation(
887             const C2Handle *handle,
888             std::shared_ptr<C2GraphicAllocation> *c2Allocation);
889 
890 private:
891     static constexpr int kMaxIntParams = 5; // large enough number;
892 
893     enum AllocType : uint8_t {
894         ALLOC_NONE = 0,
895 
896         ALLOC_LINEAR,
897         ALLOC_GRAPHIC,
898     };
899 
900     union AllocParams {
901         struct {
902             AllocType allocType;
903             C2MemoryUsage usage;
904             uint32_t params[kMaxIntParams];
905         } data;
906         uint8_t array[0];
907 
AllocParams()908         AllocParams() : data{ALLOC_NONE, {0, 0}, {0}} {}
AllocParams(C2MemoryUsage usage,uint32_t capacity)909         AllocParams(C2MemoryUsage usage, uint32_t capacity)
910             : data{ALLOC_LINEAR, usage, {[0] = capacity}} {}
AllocParams(C2MemoryUsage usage,uint32_t width,uint32_t height,uint32_t format)911         AllocParams(
912                 C2MemoryUsage usage,
913                 uint32_t width, uint32_t height, uint32_t format)
914                 : data{ALLOC_GRAPHIC, usage, {width, height, format}} {}
915     };
916 
917     const std::shared_ptr<C2Allocator> mAllocator;
918 };
919 
920 struct LinearAllocationDtor2 {
LinearAllocationDtor2LinearAllocationDtor2921     LinearAllocationDtor2(const std::shared_ptr<C2LinearAllocation> &alloc)
922         : mAllocation(alloc) {}
923 
operator ()LinearAllocationDtor2924     void operator()(bufferpool2_impl::BufferPoolAllocation *poolAlloc) { delete poolAlloc; }
925 
926     const std::shared_ptr<C2LinearAllocation> mAllocation;
927 };
928 
929 struct GraphicAllocationDtor2 {
GraphicAllocationDtor2GraphicAllocationDtor2930     GraphicAllocationDtor2(const std::shared_ptr<C2GraphicAllocation> &alloc)
931         : mAllocation(alloc) {}
932 
operator ()GraphicAllocationDtor2933     void operator()(bufferpool2_impl::BufferPoolAllocation *poolAlloc) { delete poolAlloc; }
934 
935     const std::shared_ptr<C2GraphicAllocation> mAllocation;
936 };
937 
allocate(const std::vector<uint8_t> & params,std::shared_ptr<bufferpool2_impl::BufferPoolAllocation> * alloc,size_t * allocSize)938 bufferpool2_impl::BufferPoolStatus _C2BufferPoolAllocator2::allocate(
939         const std::vector<uint8_t>  &params,
940         std::shared_ptr<bufferpool2_impl::BufferPoolAllocation> *alloc,
941         size_t *allocSize) {
942     AllocParams c2Params;
943     memcpy(&c2Params, params.data(), std::min(sizeof(AllocParams), params.size()));
944     c2_status_t status = C2_BAD_VALUE;
945     switch(c2Params.data.allocType) {
946         case ALLOC_NONE:
947             break;
948         case ALLOC_LINEAR: {
949             std::shared_ptr<C2LinearAllocation> c2Linear;
950             status = mAllocator->newLinearAllocation(
951                     c2Params.data.params[0], c2Params.data.usage, &c2Linear);
952             if (status == C2_OK && c2Linear) {
953                 bufferpool2_impl::BufferPoolAllocation *ptr =
954                         new bufferpool2_impl::BufferPoolAllocation(c2Linear->handle());
955                 if (ptr) {
956                     *alloc = std::shared_ptr<bufferpool2_impl::BufferPoolAllocation>(
957                             ptr, LinearAllocationDtor2(c2Linear));
958                     if (*alloc) {
959                         *allocSize = (size_t)c2Params.data.params[0];
960                         return ResultStatus2::OK;
961                     }
962                     delete ptr;
963                 }
964                 return ResultStatus2::NO_MEMORY;
965             }
966             break;
967         }
968         case ALLOC_GRAPHIC: {
969             std::shared_ptr<C2GraphicAllocation> c2Graphic;
970             status = mAllocator->newGraphicAllocation(
971                     c2Params.data.params[0],
972                     c2Params.data.params[1],
973                     c2Params.data.params[2],
974                     c2Params.data.usage, &c2Graphic);
975             if (status == C2_OK && c2Graphic) {
976                 bufferpool2_impl::BufferPoolAllocation *ptr =
977                         new bufferpool2_impl::BufferPoolAllocation(c2Graphic->handle());
978                 if (ptr) {
979                     *alloc = std::shared_ptr<bufferpool2_impl::BufferPoolAllocation>(
980                             ptr, GraphicAllocationDtor2(c2Graphic));
981                     if (*alloc) {
982                         *allocSize = c2Params.data.params[0] * c2Params.data.params[1];
983                         return ResultStatus2::OK;
984                     }
985                     delete ptr;
986                 }
987                 return ResultStatus2::NO_MEMORY;
988             }
989             break;
990         }
991         default:
992             break;
993     }
994     return ResultStatus2::CRITICAL_ERROR;
995 }
996 
compatible(const std::vector<uint8_t> & newParams,const std::vector<uint8_t> & oldParams)997 bool _C2BufferPoolAllocator2::compatible(
998         const std::vector<uint8_t>  &newParams,
999         const std::vector<uint8_t>  &oldParams) {
1000     AllocParams newAlloc;
1001     AllocParams oldAlloc;
1002     memcpy(&newAlloc, newParams.data(), std::min(sizeof(AllocParams), newParams.size()));
1003     memcpy(&oldAlloc, oldParams.data(), std::min(sizeof(AllocParams), oldParams.size()));
1004 
1005     // TODO: support not exact matching. e.g.) newCapacity < oldCapacity
1006     if (newAlloc.data.allocType == oldAlloc.data.allocType &&
1007             newAlloc.data.usage.expected == oldAlloc.data.usage.expected) {
1008         for (int i = 0; i < kMaxIntParams; ++i) {
1009             if (newAlloc.data.params[i] != oldAlloc.data.params[i]) {
1010                 return false;
1011             }
1012         }
1013         return true;
1014     }
1015     return false;
1016 }
1017 
getLinearParams(uint32_t capacity,C2MemoryUsage usage,std::vector<uint8_t> * params)1018 void _C2BufferPoolAllocator2::getLinearParams(
1019         uint32_t capacity, C2MemoryUsage usage, std::vector<uint8_t> *params) {
1020     AllocParams c2Params(usage, capacity);
1021     params->assign(c2Params.array, c2Params.array + sizeof(AllocParams));
1022 }
1023 
getGraphicParams(uint32_t width,uint32_t height,uint32_t format,C2MemoryUsage usage,std::vector<uint8_t> * params)1024 void _C2BufferPoolAllocator2::getGraphicParams(
1025         uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
1026         std::vector<uint8_t> *params) {
1027     AllocParams c2Params(usage, width, height, format);
1028     params->assign(c2Params.array, c2Params.array + sizeof(AllocParams));
1029 }
1030 
priorLinearAllocation(const C2Handle * handle,std::shared_ptr<C2LinearAllocation> * c2Allocation)1031 c2_status_t _C2BufferPoolAllocator2::priorLinearAllocation(
1032         const C2Handle *handle,
1033         std::shared_ptr<C2LinearAllocation> *c2Allocation) {
1034     return mAllocator->priorLinearAllocation(handle, c2Allocation);
1035 }
1036 
priorGraphicAllocation(const C2Handle * handle,std::shared_ptr<C2GraphicAllocation> * c2Allocation)1037 c2_status_t _C2BufferPoolAllocator2::priorGraphicAllocation(
1038         const C2Handle *handle,
1039         std::shared_ptr<C2GraphicAllocation> *c2Allocation) {
1040     return mAllocator->priorGraphicAllocation(handle, c2Allocation);
1041 }
1042 
1043 class C2PooledBlockPool::Impl2 {
1044 public:
Impl2(const std::shared_ptr<C2Allocator> & allocator)1045     Impl2(const std::shared_ptr<C2Allocator> &allocator)
1046             : mInit(C2_OK),
1047               mBufferPoolManager(bufferpool2_impl::ClientManager::getInstance()),
1048               mAllocator(std::make_shared<_C2BufferPoolAllocator2>(allocator)) {
1049         if (mAllocator && mBufferPoolManager) {
1050             if (mBufferPoolManager->create(
1051                     mAllocator, &mConnectionId) == ResultStatus2::OK) {
1052                 return;
1053             }
1054         }
1055         mInit = C2_NO_INIT;
1056     }
1057 
~Impl2()1058     ~Impl2() {
1059         if (mInit == C2_OK) {
1060             mBufferPoolManager->close(mConnectionId);
1061         }
1062     }
1063 
fetchLinearBlock(uint32_t capacity,C2MemoryUsage usage,std::shared_ptr<C2LinearBlock> * block)1064     c2_status_t fetchLinearBlock(
1065             uint32_t capacity, C2MemoryUsage usage,
1066             std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
1067         block->reset();
1068         if (mInit != C2_OK) {
1069             return mInit;
1070         }
1071         std::vector<uint8_t> params;
1072         mAllocator->getLinearParams(capacity, usage, &params);
1073         std::shared_ptr<bufferpool2::BufferPoolData> bufferPoolData;
1074         native_handle_t *cHandle = nullptr;
1075         bufferpool2_impl::BufferPoolStatus status = mBufferPoolManager->allocate(
1076                 mConnectionId, params, &cHandle, &bufferPoolData);
1077         if (status == ResultStatus2::OK) {
1078             std::shared_ptr<C2LinearAllocation> alloc;
1079             std::shared_ptr<C2PooledBlockPoolData2> poolData =
1080                     std::make_shared<C2PooledBlockPoolData2>(bufferPoolData);
1081             c2_status_t err = mAllocator->priorLinearAllocation(cHandle, &alloc);
1082             if (err == C2_OK && poolData && alloc) {
1083                 *block = _C2BlockFactory::CreateLinearBlock(alloc, poolData, 0, capacity);
1084                 if (*block) {
1085                     return C2_OK;
1086                 }
1087             }
1088             return C2_NO_MEMORY;
1089         }
1090         if (status == ResultStatus2::NO_MEMORY) {
1091             return C2_NO_MEMORY;
1092         }
1093         return C2_CORRUPTED;
1094     }
1095 
fetchGraphicBlock(uint32_t width,uint32_t height,uint32_t format,C2MemoryUsage usage,std::shared_ptr<C2GraphicBlock> * block)1096     c2_status_t fetchGraphicBlock(
1097             uint32_t width, uint32_t height, uint32_t format,
1098             C2MemoryUsage usage,
1099             std::shared_ptr<C2GraphicBlock> *block) {
1100         block->reset();
1101         if (mInit != C2_OK) {
1102             return mInit;
1103         }
1104         std::vector<uint8_t> params;
1105         mAllocator->getGraphicParams(width, height, format, usage, &params);
1106         std::shared_ptr<bufferpool2::BufferPoolData> bufferPoolData;
1107         native_handle_t *cHandle = nullptr;
1108         bufferpool2_impl::BufferPoolStatus status = mBufferPoolManager->allocate(
1109                 mConnectionId, params, &cHandle, &bufferPoolData);
1110         if (status == ResultStatus2::OK) {
1111             std::shared_ptr<C2GraphicAllocation> alloc;
1112             std::shared_ptr<C2PooledBlockPoolData2> poolData =
1113                 std::make_shared<C2PooledBlockPoolData2>(bufferPoolData);
1114             c2_status_t err = mAllocator->priorGraphicAllocation(
1115                     cHandle, &alloc);
1116             if (err == C2_OK && poolData && alloc) {
1117                 *block = _C2BlockFactory::CreateGraphicBlock(
1118                         alloc, poolData, C2Rect(width, height));
1119                 if (*block) {
1120                     return C2_OK;
1121                 }
1122             }
1123             return C2_NO_MEMORY;
1124         }
1125         if (status == ResultStatus2::NO_MEMORY) {
1126             return C2_NO_MEMORY;
1127         }
1128         return C2_CORRUPTED;
1129     }
1130 
getConnectionId()1131     bufferpool2_impl::ConnectionId getConnectionId() {
1132         return mInit != C2_OK ? bufferpool2_impl::INVALID_CONNECTIONID : mConnectionId;
1133     }
1134 
1135 private:
1136     c2_status_t mInit;
1137     const std::shared_ptr<bufferpool2_impl::ClientManager> mBufferPoolManager;
1138     bufferpool2_impl::ConnectionId mConnectionId; // locally
1139     const std::shared_ptr<_C2BufferPoolAllocator2> mAllocator;
1140 };
1141 
C2PooledBlockPool(const std::shared_ptr<C2Allocator> & allocator,const local_id_t localId,BufferPoolVer ver)1142 C2PooledBlockPool::C2PooledBlockPool(
1143         const std::shared_ptr<C2Allocator> &allocator,
1144         const local_id_t localId,
1145         BufferPoolVer ver)
1146         : mAllocator(allocator), mLocalId(localId), mBufferPoolVer(ver) {
1147         if (mBufferPoolVer == VER_HIDL) {
1148             mImpl = std::make_unique<Impl>(allocator);
1149         }
1150         if (mBufferPoolVer == VER_AIDL2) {
1151             mImpl2 = std::make_unique<Impl2>(allocator);
1152         }
1153     }
1154 
~C2PooledBlockPool()1155 C2PooledBlockPool::~C2PooledBlockPool() {
1156 }
1157 
fetchLinearBlock(uint32_t capacity,C2MemoryUsage usage,std::shared_ptr<C2LinearBlock> * block)1158 c2_status_t C2PooledBlockPool::fetchLinearBlock(
1159         uint32_t capacity,
1160         C2MemoryUsage usage,
1161         std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
1162     if (mBufferPoolVer == VER_HIDL && mImpl) {
1163         return mImpl->fetchLinearBlock(capacity, usage, block);
1164     }
1165     if (mBufferPoolVer == VER_AIDL2 && mImpl2) {
1166         return mImpl2->fetchLinearBlock(capacity, usage, block);
1167     }
1168     return C2_CORRUPTED;
1169 }
1170 
fetchGraphicBlock(uint32_t width,uint32_t height,uint32_t format,C2MemoryUsage usage,std::shared_ptr<C2GraphicBlock> * block)1171 c2_status_t C2PooledBlockPool::fetchGraphicBlock(
1172         uint32_t width,
1173         uint32_t height,
1174         uint32_t format,
1175         C2MemoryUsage usage,
1176         std::shared_ptr<C2GraphicBlock> *block) {
1177     if (mBufferPoolVer == VER_HIDL && mImpl) {
1178         return mImpl->fetchGraphicBlock(width, height, format, usage, block);
1179     }
1180     if (mBufferPoolVer == VER_AIDL2 && mImpl2) {
1181         return mImpl2->fetchGraphicBlock(width, height, format, usage, block);
1182     }
1183     return C2_CORRUPTED;
1184 }
1185 
getConnectionId()1186 int64_t C2PooledBlockPool::getConnectionId() {
1187     if (mBufferPoolVer == VER_HIDL && mImpl) {
1188         return mImpl->getConnectionId();
1189     }
1190     if (mBufferPoolVer == VER_AIDL2 && mImpl2) {
1191         return mImpl2->getConnectionId();
1192     }
1193     return 0;
1194 }
1195 
1196 /* ========================================== 2D BLOCK ========================================= */
1197 
1198 /**
1199  * Implementation that is shared between all 2D blocks and views.
1200  *
1201  * For blocks' Impl's crop is always the allotted crop, even if it is a sub block.
1202  *
1203  * For views' Impl's crop is the mapped portion - which for now is always the
1204  * allotted crop.
1205  */
1206 class C2_HIDE _C2Block2DImpl : public _C2PlanarSectionAspect {
1207 public:
1208     /**
1209      * Impl's crop is always the or part of the allotted crop of the allocation.
1210      */
_C2Block2DImpl(const std::shared_ptr<C2GraphicAllocation> & alloc,const std::shared_ptr<_C2BlockPoolData> & poolData=nullptr,const C2Rect & allottedCrop=C2Rect (~0u,~0u))1211     _C2Block2DImpl(const std::shared_ptr<C2GraphicAllocation> &alloc,
1212             const std::shared_ptr<_C2BlockPoolData> &poolData = nullptr,
1213             const C2Rect &allottedCrop = C2Rect(~0u, ~0u))
1214         : _C2PlanarSectionAspect(alloc.get(), allottedCrop),
1215           mAllocation(alloc),
1216           mPoolData(poolData) { }
1217 
1218     virtual ~_C2Block2DImpl() = default;
1219 
1220     /** returns pool data  */
poolData() const1221     std::shared_ptr<_C2BlockPoolData> poolData() const {
1222         return mPoolData;
1223     }
1224 
1225     /** returns native handle */
handle() const1226     const C2Handle *handle() const {
1227         return mAllocation ? mAllocation->handle() : nullptr;
1228     }
1229 
1230     /** returns the allocator's ID */
getAllocatorId() const1231     C2Allocator::id_t getAllocatorId() const {
1232         // BAD_ID can only happen if this Impl class is initialized for a view - never for a block.
1233         return mAllocation ? mAllocation->getAllocatorId() : C2Allocator::BAD_ID;
1234     }
1235 
getAllocation() const1236     std::shared_ptr<C2GraphicAllocation> getAllocation() const {
1237         return mAllocation;
1238     }
1239 
1240 private:
1241     std::shared_ptr<C2GraphicAllocation> mAllocation;
1242     std::shared_ptr<_C2BlockPoolData> mPoolData;
1243 };
1244 
1245 class C2_HIDE _C2MappingBlock2DImpl
1246     : public _C2Block2DImpl, public std::enable_shared_from_this<_C2MappingBlock2DImpl> {
1247 public:
1248     using _C2Block2DImpl::_C2Block2DImpl;
1249 
1250     virtual ~_C2MappingBlock2DImpl() override = default;
1251 
1252     /**
1253      * This class contains the mapped data pointer, and the potential error.
1254      */
1255     struct Mapped {
1256     private:
1257         friend class _C2MappingBlock2DImpl;
1258 
Mapped_C2MappingBlock2DImpl::Mapped1259         Mapped(const std::shared_ptr<_C2Block2DImpl> &impl, bool writable, C2Fence *fence __unused)
1260             : mImpl(impl), mWritable(writable) {
1261             memset(mData, 0, sizeof(mData));
1262             const C2Rect crop = mImpl->crop();
1263             // gralloc requires mapping the whole region of interest as we cannot
1264             // map multiple regions
1265             mError = mImpl->getAllocation()->map(
1266                     crop,
1267                     { C2MemoryUsage::CPU_READ, writable ? C2MemoryUsage::CPU_WRITE : 0 },
1268                     nullptr,
1269                     &mLayout,
1270                     mData);
1271             if (mError != C2_OK) {
1272                 memset(&mLayout, 0, sizeof(mLayout));
1273                 memset(mData, 0, sizeof(mData));
1274                 memset(mOffsetData, 0, sizeof(mData));
1275             } else {
1276                 // TODO: validate plane layout and
1277                 // adjust data pointers to the crop region's top left corner.
1278                 // fail if it is not on a subsampling boundary
1279                 for (size_t planeIx = 0; planeIx < mLayout.numPlanes; ++planeIx) {
1280                     const uint32_t colSampling = mLayout.planes[planeIx].colSampling;
1281                     const uint32_t rowSampling = mLayout.planes[planeIx].rowSampling;
1282                     if (crop.left % colSampling || crop.right() % colSampling
1283                             || crop.top % rowSampling || crop.bottom() % rowSampling) {
1284                         // cannot calculate data pointer
1285                         mImpl->getAllocation()->unmap(mData, crop, nullptr);
1286                         memset(&mLayout, 0, sizeof(mLayout));
1287                         memset(mData, 0, sizeof(mData));
1288                         memset(mOffsetData, 0, sizeof(mData));
1289                         mError = C2_BAD_VALUE;
1290                         return;
1291                     }
1292                     mOffsetData[planeIx] =
1293                         mData[planeIx] + (ssize_t)crop.left * mLayout.planes[planeIx].colInc
1294                                 + (ssize_t)crop.top * mLayout.planes[planeIx].rowInc;
1295                 }
1296             }
1297         }
1298 
Mapped_C2MappingBlock2DImpl::Mapped1299         explicit Mapped(c2_status_t error)
1300             : mImpl(nullptr), mWritable(false), mError(error) {
1301             // CHECK(error != C2_OK);
1302             memset(&mLayout, 0, sizeof(mLayout));
1303             memset(mData, 0, sizeof(mData));
1304             memset(mOffsetData, 0, sizeof(mData));
1305         }
1306 
1307     public:
~Mapped_C2MappingBlock2DImpl::Mapped1308         ~Mapped() {
1309             if (mData[0] != nullptr) {
1310                 mImpl->getAllocation()->unmap(mData, mImpl->crop(), nullptr);
1311             }
1312         }
1313 
1314         /** returns mapping status */
error_C2MappingBlock2DImpl::Mapped1315         c2_status_t error() const { return mError; }
1316 
1317         /** returns data pointer */
data_C2MappingBlock2DImpl::Mapped1318         uint8_t *const *data() const { return mOffsetData; }
1319 
1320         /** returns the plane layout */
layout_C2MappingBlock2DImpl::Mapped1321         C2PlanarLayout layout() const { return mLayout; }
1322 
1323         /** returns whether the mapping is writable */
writable_C2MappingBlock2DImpl::Mapped1324         bool writable() const { return mWritable; }
1325 
1326     private:
1327         const std::shared_ptr<_C2Block2DImpl> mImpl;
1328         bool mWritable;
1329         c2_status_t mError;
1330         uint8_t *mData[C2PlanarLayout::MAX_NUM_PLANES];
1331         uint8_t *mOffsetData[C2PlanarLayout::MAX_NUM_PLANES];
1332         C2PlanarLayout mLayout;
1333     };
1334 
1335     /**
1336      * Maps the allotted region.
1337      *
1338      * If already mapped and it is currently in use, returns the existing mapping.
1339      * If fence is provided, an acquire fence is stored there.
1340      */
map(bool writable,C2Fence * fence)1341     std::shared_ptr<Mapped> map(bool writable, C2Fence *fence) {
1342         std::lock_guard<std::mutex> lock(mMappedLock);
1343         std::shared_ptr<Mapped> existing = mMapped.lock();
1344         if (!existing) {
1345             existing = std::shared_ptr<Mapped>(new Mapped(shared_from_this(), writable, fence));
1346             mMapped = existing;
1347         } else {
1348             // if we mapped the region read-only, we cannot remap it read-write
1349             if (writable && !existing->writable()) {
1350                 existing = std::shared_ptr<Mapped>(new Mapped(C2_CANNOT_DO));
1351             }
1352             if (fence != nullptr) {
1353                 *fence = C2Fence();
1354             }
1355         }
1356         return existing;
1357     }
1358 
1359 private:
1360     std::weak_ptr<Mapped> mMapped;
1361     std::mutex mMappedLock;
1362 };
1363 
1364 class C2_HIDE _C2MappedBlock2DImpl : public _C2Block2DImpl {
1365 public:
_C2MappedBlock2DImpl(const _C2Block2DImpl & impl,std::shared_ptr<_C2MappingBlock2DImpl::Mapped> mapping)1366     _C2MappedBlock2DImpl(const _C2Block2DImpl &impl,
1367                          std::shared_ptr<_C2MappingBlock2DImpl::Mapped> mapping)
1368         : _C2Block2DImpl(impl), mMapping(mapping) {
1369     }
1370 
1371     virtual ~_C2MappedBlock2DImpl() override = default;
1372 
mapping() const1373     std::shared_ptr<_C2MappingBlock2DImpl::Mapped> mapping() const { return mMapping; }
1374 
1375 private:
1376     std::shared_ptr<_C2MappingBlock2DImpl::Mapped> mMapping;
1377 };
1378 
1379 /**
1380  * Block implementation.
1381  */
1382 class C2Block2D::Impl : public _C2MappingBlock2DImpl {
1383 public:
1384     using _C2MappingBlock2DImpl::_C2MappingBlock2DImpl;
1385     virtual ~Impl() override = default;
1386 };
1387 
handle() const1388 const C2Handle *C2Block2D::handle() const {
1389     return mImpl->handle();
1390 }
1391 
getAllocatorId() const1392 C2Allocator::id_t C2Block2D::getAllocatorId() const {
1393     return mImpl->getAllocatorId();
1394 }
1395 
C2Block2D(std::shared_ptr<Impl> impl,const _C2PlanarSectionAspect & section)1396 C2Block2D::C2Block2D(std::shared_ptr<Impl> impl, const _C2PlanarSectionAspect &section)
1397     // always clamp subsection to parent (impl) crop for safety
1398     : _C2PlanarSectionAspect(impl.get(), section.crop()), mImpl(impl) {
1399 }
1400 
1401 /**
1402  * Graphic view implementation.
1403  *
1404  * range of Impl is the mapped range of the underlying allocation. range of View is the current
1405  * crop.
1406  */
1407 class C2GraphicView::Impl : public _C2MappedBlock2DImpl {
1408 public:
1409     using _C2MappedBlock2DImpl::_C2MappedBlock2DImpl;
1410     virtual ~Impl() override = default;
1411 };
1412 
C2GraphicView(std::shared_ptr<Impl> impl,const _C2PlanarSectionAspect & section)1413 C2GraphicView::C2GraphicView(std::shared_ptr<Impl> impl, const _C2PlanarSectionAspect &section)
1414     : _C2EditablePlanarSectionAspect(impl.get(), section.crop()), mImpl(impl) {
1415 }
1416 
data() const1417 const uint8_t *const *C2GraphicView::data() const {
1418     return mImpl->mapping()->data();
1419 }
1420 
data()1421 uint8_t *const *C2GraphicView::data() {
1422     return mImpl->mapping()->data();
1423 }
1424 
layout() const1425 const C2PlanarLayout C2GraphicView::layout() const {
1426     return mImpl->mapping()->layout();
1427 }
1428 
subView(const C2Rect & rect) const1429 const C2GraphicView C2GraphicView::subView(const C2Rect &rect) const {
1430     return C2GraphicView(mImpl, C2PlanarSection(*mImpl, rect));
1431 }
1432 
subView(const C2Rect & rect)1433 C2GraphicView C2GraphicView::subView(const C2Rect &rect) {
1434     return C2GraphicView(mImpl, C2PlanarSection(*mImpl, rect));
1435 }
1436 
error() const1437 c2_status_t C2GraphicView::error() const {
1438     return mImpl->mapping()->error();
1439 }
1440 
1441 /**
1442  * Const graphic block implementation.
1443  */
C2ConstGraphicBlock(std::shared_ptr<Impl> impl,const _C2PlanarSectionAspect & section,C2Fence fence)1444 C2ConstGraphicBlock::C2ConstGraphicBlock(
1445         std::shared_ptr<Impl> impl, const _C2PlanarSectionAspect &section, C2Fence fence)
1446     : C2Block2D(impl, section), mFence(fence) { }
1447 
map() const1448 C2Acquirable<const C2GraphicView> C2ConstGraphicBlock::map() const {
1449     C2Fence fence;
1450     std::shared_ptr<_C2MappingBlock2DImpl::Mapped> mapping =
1451         mImpl->map(false /* writable */, &fence);
1452     std::shared_ptr<GraphicViewBuddy::Impl> gvi =
1453         std::shared_ptr<GraphicViewBuddy::Impl>(new GraphicViewBuddy::Impl(*mImpl, mapping));
1454     return AcquirableConstGraphicViewBuddy(
1455             mapping->error(), fence, GraphicViewBuddy(gvi, C2PlanarSection(*mImpl, crop())));
1456 }
1457 
subBlock(const C2Rect & rect) const1458 C2ConstGraphicBlock C2ConstGraphicBlock::subBlock(const C2Rect &rect) const {
1459     return C2ConstGraphicBlock(mImpl, C2PlanarSection(*mImpl, crop().intersect(rect)), mFence);
1460 }
1461 
1462 /**
1463  * Graphic block implementation.
1464  */
C2GraphicBlock(std::shared_ptr<Impl> impl,const _C2PlanarSectionAspect & section)1465 C2GraphicBlock::C2GraphicBlock(
1466     std::shared_ptr<Impl> impl, const _C2PlanarSectionAspect &section)
1467     : C2Block2D(impl, section) { }
1468 
map()1469 C2Acquirable<C2GraphicView> C2GraphicBlock::map() {
1470     C2Fence fence;
1471     std::shared_ptr<_C2MappingBlock2DImpl::Mapped> mapping =
1472         mImpl->map(true /* writable */, &fence);
1473     std::shared_ptr<GraphicViewBuddy::Impl> gvi =
1474         std::shared_ptr<GraphicViewBuddy::Impl>(new GraphicViewBuddy::Impl(*mImpl, mapping));
1475     return AcquirableGraphicViewBuddy(
1476             mapping->error(), fence, GraphicViewBuddy(gvi, C2PlanarSection(*mImpl, crop())));
1477 }
1478 
share(const C2Rect & crop,C2Fence fence)1479 C2ConstGraphicBlock C2GraphicBlock::share(const C2Rect &crop, C2Fence fence) {
1480     return ConstGraphicBlockBuddy(mImpl, C2PlanarSection(*mImpl, crop), fence);
1481 }
1482 
1483 /**
1484  * Basic block pool implementations.
1485  */
C2BasicGraphicBlockPool(const std::shared_ptr<C2Allocator> & allocator)1486 C2BasicGraphicBlockPool::C2BasicGraphicBlockPool(
1487         const std::shared_ptr<C2Allocator> &allocator)
1488   : mAllocator(allocator) {}
1489 
fetchGraphicBlock(uint32_t width,uint32_t height,uint32_t format,C2MemoryUsage usage,std::shared_ptr<C2GraphicBlock> * block)1490 c2_status_t C2BasicGraphicBlockPool::fetchGraphicBlock(
1491         uint32_t width,
1492         uint32_t height,
1493         uint32_t format,
1494         C2MemoryUsage usage,
1495         std::shared_ptr<C2GraphicBlock> *block /* nonnull */) {
1496     block->reset();
1497 
1498     std::shared_ptr<C2GraphicAllocation> alloc;
1499     c2_status_t err = mAllocator->newGraphicAllocation(width, height, format, usage, &alloc);
1500     if (err != C2_OK) {
1501         return err;
1502     }
1503 
1504     *block = _C2BlockFactory::CreateGraphicBlock(alloc);
1505 
1506     return C2_OK;
1507 }
1508 
CreateGraphicBlock(const std::shared_ptr<C2GraphicAllocation> & alloc,const std::shared_ptr<_C2BlockPoolData> & data,const C2Rect & allottedCrop)1509 std::shared_ptr<C2GraphicBlock> _C2BlockFactory::CreateGraphicBlock(
1510         const std::shared_ptr<C2GraphicAllocation> &alloc,
1511         const std::shared_ptr<_C2BlockPoolData> &data, const C2Rect &allottedCrop) {
1512     std::shared_ptr<C2Block2D::Impl> impl =
1513         std::make_shared<C2Block2D::Impl>(alloc, data, allottedCrop);
1514     return std::shared_ptr<C2GraphicBlock>(new C2GraphicBlock(impl, *impl));
1515 }
1516 
GetGraphicBlockPoolData(const C2Block2D & block)1517 std::shared_ptr<_C2BlockPoolData> _C2BlockFactory::GetGraphicBlockPoolData(
1518         const C2Block2D &block) {
1519     if (block.mImpl) {
1520         return block.mImpl->poolData();
1521     }
1522     return nullptr;
1523 }
1524 
CreateGraphicBlock(const C2Handle * cHandle,const std::shared_ptr<bufferpool::BufferPoolData> & data)1525 std::shared_ptr<C2GraphicBlock> _C2BlockFactory::CreateGraphicBlock(
1526         const C2Handle *cHandle,
1527         const std::shared_ptr<bufferpool::BufferPoolData> &data) {
1528     // TODO: get proper allocator? and mutex?
1529     static std::unique_ptr<C2AllocatorGralloc> sAllocator = std::make_unique<C2AllocatorGralloc>(0);
1530 
1531     std::shared_ptr<C2GraphicAllocation> alloc;
1532     if (sAllocator->isValid(cHandle)) {
1533         c2_status_t err = sAllocator->priorGraphicAllocation(cHandle, &alloc);
1534         const std::shared_ptr<C2PooledBlockPoolData> poolData =
1535                 std::make_shared<C2PooledBlockPoolData>(data);
1536         if (err == C2_OK && poolData) {
1537             // TODO: config setup?
1538             std::shared_ptr<C2GraphicBlock> block =
1539                     _C2BlockFactory::CreateGraphicBlock(alloc, poolData);
1540             return block;
1541         }
1542     }
1543     return nullptr;
1544 };
1545 
CreateGraphicBlock(const C2Handle * cHandle,const std::shared_ptr<bufferpool2::BufferPoolData> & data)1546 std::shared_ptr<C2GraphicBlock> _C2BlockFactory::CreateGraphicBlock(
1547         const C2Handle *cHandle,
1548         const std::shared_ptr<bufferpool2::BufferPoolData> &data) {
1549     // TODO: get proper allocator? and mutex?
1550     static std::unique_ptr<C2AllocatorGralloc> sAllocator = std::make_unique<C2AllocatorGralloc>(0);
1551 
1552     std::shared_ptr<C2GraphicAllocation> alloc;
1553     if (sAllocator->isValid(cHandle)) {
1554         c2_status_t err = sAllocator->priorGraphicAllocation(cHandle, &alloc);
1555         const std::shared_ptr<C2PooledBlockPoolData2> poolData =
1556                 std::make_shared<C2PooledBlockPoolData2>(data);
1557         if (err == C2_OK && poolData) {
1558             // TODO: config setup?
1559             std::shared_ptr<C2GraphicBlock> block =
1560                     _C2BlockFactory::CreateGraphicBlock(alloc, poolData);
1561             return block;
1562         }
1563     }
1564     return nullptr;
1565 };
1566 
1567 /* ========================================== BUFFER ========================================= */
1568 
1569 class C2BufferData::Impl {
1570 public:
Impl(const std::vector<C2ConstLinearBlock> & blocks)1571     explicit Impl(const std::vector<C2ConstLinearBlock> &blocks)
1572         : mType(blocks.size() == 1 ? LINEAR : LINEAR_CHUNKS),
1573           mLinearBlocks(blocks) {
1574     }
1575 
Impl(const std::vector<C2ConstGraphicBlock> & blocks)1576     explicit Impl(const std::vector<C2ConstGraphicBlock> &blocks)
1577         : mType(blocks.size() == 1 ? GRAPHIC : GRAPHIC_CHUNKS),
1578           mGraphicBlocks(blocks) {
1579     }
1580 
type() const1581     type_t type() const { return mType; }
linearBlocks() const1582     const std::vector<C2ConstLinearBlock> &linearBlocks() const { return mLinearBlocks; }
graphicBlocks() const1583     const std::vector<C2ConstGraphicBlock> &graphicBlocks() const { return mGraphicBlocks; }
1584 
1585 private:
1586     type_t mType;
1587     std::vector<C2ConstLinearBlock> mLinearBlocks;
1588     std::vector<C2ConstGraphicBlock> mGraphicBlocks;
1589     friend class C2InfoBuffer;
1590 };
1591 
C2BufferData(const std::vector<C2ConstLinearBlock> & blocks)1592 C2BufferData::C2BufferData(const std::vector<C2ConstLinearBlock> &blocks) : mImpl(new Impl(blocks)) {}
C2BufferData(const std::vector<C2ConstGraphicBlock> & blocks)1593 C2BufferData::C2BufferData(const std::vector<C2ConstGraphicBlock> &blocks) : mImpl(new Impl(blocks)) {}
1594 
type() const1595 C2BufferData::type_t C2BufferData::type() const { return mImpl->type(); }
1596 
linearBlocks() const1597 const std::vector<C2ConstLinearBlock> C2BufferData::linearBlocks() const {
1598     return mImpl->linearBlocks();
1599 }
1600 
graphicBlocks() const1601 const std::vector<C2ConstGraphicBlock> C2BufferData::graphicBlocks() const {
1602     return mImpl->graphicBlocks();
1603 }
1604 
C2InfoBuffer(C2Param::Index index,const std::vector<C2ConstLinearBlock> & blocks)1605 C2InfoBuffer::C2InfoBuffer(
1606     C2Param::Index index, const std::vector<C2ConstLinearBlock> &blocks)
1607     : mIndex(index), mData(BufferDataBuddy(blocks)) {
1608 }
1609 
C2InfoBuffer(C2Param::Index index,const std::vector<C2ConstGraphicBlock> & blocks)1610 C2InfoBuffer::C2InfoBuffer(
1611     C2Param::Index index, const std::vector<C2ConstGraphicBlock> &blocks)
1612     : mIndex(index), mData(BufferDataBuddy(blocks)) {
1613 }
1614 
C2InfoBuffer(C2Param::Index index,const C2BufferData & data)1615 C2InfoBuffer::C2InfoBuffer(
1616     C2Param::Index index, const C2BufferData &data)
1617     : mIndex(index), mData(data) {
1618 }
1619 
1620 // static
CreateLinearBuffer(C2Param::CoreIndex index,const C2ConstLinearBlock & block)1621 C2InfoBuffer C2InfoBuffer::CreateLinearBuffer(
1622         C2Param::CoreIndex index, const C2ConstLinearBlock &block) {
1623     return C2InfoBuffer(index.coreIndex() | C2Param::Index::KIND_INFO | C2Param::Index::DIR_GLOBAL,
1624                         { block });
1625 }
1626 
1627 // static
CreateGraphicBuffer(C2Param::CoreIndex index,const C2ConstGraphicBlock & block)1628 C2InfoBuffer C2InfoBuffer::CreateGraphicBuffer(
1629         C2Param::CoreIndex index, const C2ConstGraphicBlock &block) {
1630     return C2InfoBuffer(index.coreIndex() | C2Param::Index::KIND_INFO | C2Param::Index::DIR_GLOBAL,
1631                         { block });
1632 }
1633 
1634 class C2Buffer::Impl {
1635 public:
Impl(C2Buffer * thiz,const std::vector<C2ConstLinearBlock> & blocks)1636     Impl(C2Buffer *thiz, const std::vector<C2ConstLinearBlock> &blocks)
1637         : mThis(thiz), mData(blocks) {}
Impl(C2Buffer * thiz,const std::vector<C2ConstGraphicBlock> & blocks)1638     Impl(C2Buffer *thiz, const std::vector<C2ConstGraphicBlock> &blocks)
1639         : mThis(thiz), mData(blocks) {}
1640 
~Impl()1641     ~Impl() {
1642         for (const auto &pair : mNotify) {
1643             pair.first(mThis, pair.second);
1644         }
1645     }
1646 
data() const1647     const C2BufferData &data() const { return mData; }
1648 
registerOnDestroyNotify(OnDestroyNotify onDestroyNotify,void * arg)1649     c2_status_t registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
1650         auto it = std::find_if(
1651                 mNotify.begin(), mNotify.end(),
1652                 [onDestroyNotify, arg] (const auto &pair) {
1653                     return pair.first == onDestroyNotify && pair.second == arg;
1654                 });
1655         if (it != mNotify.end()) {
1656             return C2_DUPLICATE;
1657         }
1658         mNotify.emplace_back(onDestroyNotify, arg);
1659         return C2_OK;
1660     }
1661 
unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify,void * arg)1662     c2_status_t unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
1663         auto it = std::find_if(
1664                 mNotify.begin(), mNotify.end(),
1665                 [onDestroyNotify, arg] (const auto &pair) {
1666                     return pair.first == onDestroyNotify && pair.second == arg;
1667                 });
1668         if (it == mNotify.end()) {
1669             return C2_NOT_FOUND;
1670         }
1671         mNotify.erase(it);
1672         return C2_OK;
1673     }
1674 
info() const1675     std::vector<std::shared_ptr<const C2Info>> info() const {
1676         std::vector<std::shared_ptr<const C2Info>> result(mInfos.size());
1677         std::transform(
1678                 mInfos.begin(), mInfos.end(), result.begin(),
1679                 [] (const auto &elem) { return elem.second; });
1680         return result;
1681     }
1682 
setInfo(const std::shared_ptr<C2Info> & info)1683     c2_status_t setInfo(const std::shared_ptr<C2Info> &info) {
1684         // To "update" you need to erase the existing one if any, and then insert.
1685         (void) mInfos.erase(info->coreIndex());
1686         (void) mInfos.insert({ info->coreIndex(), info });
1687         return C2_OK;
1688     }
1689 
hasInfo(C2Param::Type index) const1690     bool hasInfo(C2Param::Type index) const {
1691         return mInfos.count(index.coreIndex()) > 0;
1692     }
1693 
getInfo(C2Param::Type index) const1694     std::shared_ptr<const C2Info> getInfo(C2Param::Type index) const {
1695         auto it = mInfos.find(index.coreIndex());
1696         if (it == mInfos.end()) {
1697             return nullptr;
1698         }
1699         return std::const_pointer_cast<const C2Info>(it->second);
1700     }
1701 
removeInfo(C2Param::Type index)1702     std::shared_ptr<C2Info> removeInfo(C2Param::Type index) {
1703         auto it = mInfos.find(index.coreIndex());
1704         if (it == mInfos.end()) {
1705             return nullptr;
1706         }
1707         std::shared_ptr<C2Info> ret = it->second;
1708         (void) mInfos.erase(it);
1709         return ret;
1710     }
1711 
1712 private:
1713     C2Buffer * const mThis;
1714     BufferDataBuddy mData;
1715     std::map<C2Param::CoreIndex, std::shared_ptr<C2Info>> mInfos;
1716     std::list<std::pair<OnDestroyNotify, void *>> mNotify;
1717 };
1718 
C2Buffer(const std::vector<C2ConstLinearBlock> & blocks)1719 C2Buffer::C2Buffer(const std::vector<C2ConstLinearBlock> &blocks)
1720     : mImpl(new Impl(this, blocks)) {}
1721 
C2Buffer(const std::vector<C2ConstGraphicBlock> & blocks)1722 C2Buffer::C2Buffer(const std::vector<C2ConstGraphicBlock> &blocks)
1723     : mImpl(new Impl(this, blocks)) {}
1724 
data() const1725 const C2BufferData C2Buffer::data() const { return mImpl->data(); }
1726 
registerOnDestroyNotify(OnDestroyNotify onDestroyNotify,void * arg)1727 c2_status_t C2Buffer::registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
1728     return mImpl->registerOnDestroyNotify(onDestroyNotify, arg);
1729 }
1730 
unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify,void * arg)1731 c2_status_t C2Buffer::unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
1732     return mImpl->unregisterOnDestroyNotify(onDestroyNotify, arg);
1733 }
1734 
info() const1735 const std::vector<std::shared_ptr<const C2Info>> C2Buffer::info() const {
1736     return mImpl->info();
1737 }
1738 
setInfo(const std::shared_ptr<C2Info> & info)1739 c2_status_t C2Buffer::setInfo(const std::shared_ptr<C2Info> &info) {
1740     return mImpl->setInfo(info);
1741 }
1742 
hasInfo(C2Param::Type index) const1743 bool C2Buffer::hasInfo(C2Param::Type index) const {
1744     return mImpl->hasInfo(index);
1745 }
1746 
getInfo(C2Param::Type index) const1747 std::shared_ptr<const C2Info> C2Buffer::getInfo(C2Param::Type index) const {
1748     return mImpl->getInfo(index);
1749 }
1750 
removeInfo(C2Param::Type index)1751 std::shared_ptr<C2Info> C2Buffer::removeInfo(C2Param::Type index) {
1752     return mImpl->removeInfo(index);
1753 }
1754 
1755 // static
CreateLinearBuffer(const C2ConstLinearBlock & block)1756 std::shared_ptr<C2Buffer> C2Buffer::CreateLinearBuffer(const C2ConstLinearBlock &block) {
1757     return std::shared_ptr<C2Buffer>(new C2Buffer({ block }));
1758 }
1759 
1760 // static
CreateGraphicBuffer(const C2ConstGraphicBlock & block)1761 std::shared_ptr<C2Buffer> C2Buffer::CreateGraphicBuffer(const C2ConstGraphicBlock &block) {
1762     return std::shared_ptr<C2Buffer>(new C2Buffer({ block }));
1763 }
1764