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