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> ¶ms,
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> ¶ms,
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, ¶ms);
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, ¶ms);
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> ¶ms,
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> ¶ms,
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, ¶ms);
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, ¶ms);
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 §ion)
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 §ion)
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 §ion, 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 §ion)
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