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