blob: 2294fa8b37fb07d0c083a156653e768baab421b6 [file] [log] [blame]
Pawin Vongmasa36653902018-11-15 00:10:25 -08001/*
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
Pin-chih Linaa18ea52019-11-19 18:48:50 +080025#include <C2AllocatorBlob.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080026#include <C2AllocatorGralloc.h>
Pin-chih Linaa18ea52019-11-19 18:48:50 +080027#include <C2AllocatorIon.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080028#include <C2BufferPriv.h>
29#include <C2BlockInternal.h>
Pin-chih Linaa18ea52019-11-19 18:48:50 +080030#include <C2PlatformSupport.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080031#include <bufferpool/ClientManager.h>
32
33namespace {
34
Pin-chih Linaa18ea52019-11-19 18:48:50 +080035using android::C2AllocatorBlob;
Pawin Vongmasa36653902018-11-15 00:10:25 -080036using android::C2AllocatorGralloc;
37using android::C2AllocatorIon;
38using android::hardware::media::bufferpool::BufferPoolData;
Sungtak Leed3318082018-09-07 15:52:43 -070039using android::hardware::media::bufferpool::V2_0::ResultStatus;
40using android::hardware::media::bufferpool::V2_0::implementation::BufferPoolAllocation;
41using android::hardware::media::bufferpool::V2_0::implementation::BufferPoolAllocator;
42using android::hardware::media::bufferpool::V2_0::implementation::ClientManager;
43using android::hardware::media::bufferpool::V2_0::implementation::ConnectionId;
44using android::hardware::media::bufferpool::V2_0::implementation::INVALID_CONNECTIONID;
Pawin Vongmasa36653902018-11-15 00:10:25 -080045
46// This anonymous namespace contains the helper classes that allow our implementation to create
47// block/buffer objects.
48//
49// Inherit from the parent, share with the friend.
50class ReadViewBuddy : public C2ReadView {
51 using C2ReadView::C2ReadView;
52 friend class ::C2ConstLinearBlock;
53};
54
55class WriteViewBuddy : public C2WriteView {
56 using C2WriteView::C2WriteView;
57 friend class ::C2LinearBlock;
58};
59
60class ConstLinearBlockBuddy : public C2ConstLinearBlock {
61 using C2ConstLinearBlock::C2ConstLinearBlock;
62 friend class ::C2LinearBlock;
63};
64
65class LinearBlockBuddy : public C2LinearBlock {
66 using C2LinearBlock::C2LinearBlock;
67 friend class ::C2BasicLinearBlockPool;
68};
69
70class AcquirableReadViewBuddy : public C2Acquirable<C2ReadView> {
71 using C2Acquirable::C2Acquirable;
72 friend class ::C2ConstLinearBlock;
73};
74
75class AcquirableWriteViewBuddy : public C2Acquirable<C2WriteView> {
76 using C2Acquirable::C2Acquirable;
77 friend class ::C2LinearBlock;
78};
79
80class GraphicViewBuddy : public C2GraphicView {
81 using C2GraphicView::C2GraphicView;
82 friend class ::C2ConstGraphicBlock;
83 friend class ::C2GraphicBlock;
84};
85
86class AcquirableConstGraphicViewBuddy : public C2Acquirable<const C2GraphicView> {
87 using C2Acquirable::C2Acquirable;
88 friend class ::C2ConstGraphicBlock;
89};
90
91class AcquirableGraphicViewBuddy : public C2Acquirable<C2GraphicView> {
92 using C2Acquirable::C2Acquirable;
93 friend class ::C2GraphicBlock;
94};
95
96class ConstGraphicBlockBuddy : public C2ConstGraphicBlock {
97 using C2ConstGraphicBlock::C2ConstGraphicBlock;
98 friend class ::C2GraphicBlock;
99};
100
101class GraphicBlockBuddy : public C2GraphicBlock {
102 using C2GraphicBlock::C2GraphicBlock;
103 friend class ::C2BasicGraphicBlockPool;
104};
105
106class BufferDataBuddy : public C2BufferData {
107 using C2BufferData::C2BufferData;
108 friend class ::C2Buffer;
Lajos Molnar5019e352020-07-22 11:11:46 -0700109 friend class ::C2InfoBuffer;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800110};
111
112} // namespace
113
114/* ========================================== 1D BLOCK ========================================= */
115
116/**
117 * This class is the base class for all 1D block and view implementations.
118 *
119 * This is basically just a placeholder for the underlying 1D allocation and the range of the
120 * alloted portion to this block. There is also a placeholder for a blockpool data.
121 */
122class C2_HIDE _C2Block1DImpl : public _C2LinearRangeAspect {
123public:
124 _C2Block1DImpl(const std::shared_ptr<C2LinearAllocation> &alloc,
125 const std::shared_ptr<_C2BlockPoolData> &poolData = nullptr,
126 size_t offset = 0, size_t size = ~(size_t)0)
127 : _C2LinearRangeAspect(alloc.get(), offset, size),
128 mAllocation(alloc),
129 mPoolData(poolData) { }
130
131 _C2Block1DImpl(const _C2Block1DImpl &other, size_t offset = 0, size_t size = ~(size_t)0)
132 : _C2LinearRangeAspect(&other, offset, size),
133 mAllocation(other.mAllocation),
134 mPoolData(other.mPoolData) { }
135
136 /** returns pool data */
137 std::shared_ptr<_C2BlockPoolData> poolData() const {
138 return mPoolData;
139 }
140
141 /** returns native handle */
142 const C2Handle *handle() const {
143 return mAllocation ? mAllocation->handle() : nullptr;
144 }
145
146 /** returns the allocator's ID */
147 C2Allocator::id_t getAllocatorId() const {
148 // BAD_ID can only happen if this Impl class is initialized for a view - never for a block.
149 return mAllocation ? mAllocation->getAllocatorId() : C2Allocator::BAD_ID;
150 }
151
152 std::shared_ptr<C2LinearAllocation> getAllocation() const {
153 return mAllocation;
154 }
155
156private:
157 std::shared_ptr<C2LinearAllocation> mAllocation;
158 std::shared_ptr<_C2BlockPoolData> mPoolData;
159};
160
161/**
162 * This class contains the mapped data pointer, and the potential error.
163 *
164 * range is the mapped range of the underlying allocation (which is part of the allotted
165 * range).
166 */
167class C2_HIDE _C2MappedBlock1DImpl : public _C2Block1DImpl {
168public:
169 _C2MappedBlock1DImpl(const _C2Block1DImpl &block, uint8_t *data,
170 size_t offset = 0, size_t size = ~(size_t)0)
171 : _C2Block1DImpl(block, offset, size), mData(data), mError(C2_OK) { }
172
173 _C2MappedBlock1DImpl(c2_status_t error)
174 : _C2Block1DImpl(nullptr), mData(nullptr), mError(error) {
175 // CHECK(error != C2_OK);
176 }
177
178 const uint8_t *data() const {
179 return mData;
180 }
181
182 uint8_t *data() {
183 return mData;
184 }
185
186 c2_status_t error() const {
187 return mError;
188 }
189
190private:
191 uint8_t *mData;
192 c2_status_t mError;
193};
194
195/**
196 * Block implementation.
197 */
198class C2Block1D::Impl : public _C2Block1DImpl {
199 using _C2Block1DImpl::_C2Block1DImpl;
200};
201
202const C2Handle *C2Block1D::handle() const {
203 return mImpl->handle();
204};
205
206C2Allocator::id_t C2Block1D::getAllocatorId() const {
207 return mImpl->getAllocatorId();
208};
209
210C2Block1D::C2Block1D(std::shared_ptr<Impl> impl, const _C2LinearRangeAspect &range)
211 // always clamp subrange to parent (impl) range for safety
212 : _C2LinearRangeAspect(impl.get(), range.offset(), range.size()), mImpl(impl) {
213}
214
215/**
216 * Read view implementation.
217 *
218 * range of Impl is the mapped range of the underlying allocation (which is part of the allotted
219 * range). range of View is 0 to capacity() (not represented as an actual range). This maps to a
220 * subrange of Impl range starting at mImpl->offset() + _mOffset.
221 */
222class C2ReadView::Impl : public _C2MappedBlock1DImpl {
223 using _C2MappedBlock1DImpl::_C2MappedBlock1DImpl;
224};
225
226C2ReadView::C2ReadView(std::shared_ptr<Impl> impl, uint32_t offset, uint32_t size)
227 : _C2LinearCapacityAspect(C2LinearCapacity(impl->size()).range(offset, size).size()),
228 mImpl(impl),
229 mOffset(C2LinearCapacity(impl->size()).range(offset, size).offset()) { }
230
231C2ReadView::C2ReadView(c2_status_t error)
232 : _C2LinearCapacityAspect(0u), mImpl(std::make_shared<Impl>(error)), mOffset(0u) {
233 // CHECK(error != C2_OK);
234}
235
236const uint8_t *C2ReadView::data() const {
237 return mImpl->error() ? nullptr : mImpl->data() + mOffset;
238}
239
240c2_status_t C2ReadView::error() const {
241 return mImpl->error();
242}
243
244C2ReadView C2ReadView::subView(size_t offset, size_t size) const {
245 C2LinearRange subRange(*this, offset, size);
246 return C2ReadView(mImpl, mOffset + subRange.offset(), subRange.size());
247}
248
249/**
250 * Write view implementation.
251 */
252class C2WriteView::Impl : public _C2MappedBlock1DImpl {
253 using _C2MappedBlock1DImpl::_C2MappedBlock1DImpl;
254};
255
256C2WriteView::C2WriteView(std::shared_ptr<Impl> impl)
257// UGLY: _C2LinearRangeAspect requires a bona-fide object for capacity to prevent spoofing, so
258// this is what we have to do.
259// TODO: use childRange
260 : _C2EditableLinearRangeAspect(std::make_unique<C2LinearCapacity>(impl->size()).get()), mImpl(impl) { }
261
262C2WriteView::C2WriteView(c2_status_t error)
263 : _C2EditableLinearRangeAspect(nullptr), mImpl(std::make_shared<Impl>(error)) {}
264
265uint8_t *C2WriteView::base() { return mImpl->data(); }
266
267uint8_t *C2WriteView::data() { return mImpl->data() + offset(); }
268
269c2_status_t C2WriteView::error() const { return mImpl->error(); }
270
271/**
272 * Const linear block implementation.
273 */
274C2ConstLinearBlock::C2ConstLinearBlock(std::shared_ptr<Impl> impl, const _C2LinearRangeAspect &range, C2Fence fence)
275 : C2Block1D(impl, range), mFence(fence) { }
276
277C2Acquirable<C2ReadView> C2ConstLinearBlock::map() const {
278 void *base = nullptr;
279 uint32_t len = size();
280 c2_status_t error = mImpl->getAllocation()->map(
281 offset(), len, { C2MemoryUsage::CPU_READ, 0 }, nullptr, &base);
282 // TODO: wait on fence
283 if (error == C2_OK) {
284 std::shared_ptr<ReadViewBuddy::Impl> rvi = std::shared_ptr<ReadViewBuddy::Impl>(
285 new ReadViewBuddy::Impl(*mImpl, (uint8_t *)base, offset(), len),
286 [base, len](ReadViewBuddy::Impl *i) {
287 (void)i->getAllocation()->unmap(base, len, nullptr);
288 delete i;
289 });
290 return AcquirableReadViewBuddy(error, C2Fence(), ReadViewBuddy(rvi, 0, len));
291 } else {
292 return AcquirableReadViewBuddy(error, C2Fence(), ReadViewBuddy(error));
293 }
294}
295
296C2ConstLinearBlock C2ConstLinearBlock::subBlock(size_t offset_, size_t size_) const {
297 C2LinearRange subRange(*mImpl, offset_, size_);
298 return C2ConstLinearBlock(mImpl, subRange, mFence);
299}
300
301/**
302 * Linear block implementation.
303 */
304C2LinearBlock::C2LinearBlock(std::shared_ptr<Impl> impl, const _C2LinearRangeAspect &range)
305 : C2Block1D(impl, range) { }
306
307C2Acquirable<C2WriteView> C2LinearBlock::map() {
308 void *base = nullptr;
309 uint32_t len = size();
310 c2_status_t error = mImpl->getAllocation()->map(
311 offset(), len, { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE }, nullptr, &base);
312 // TODO: wait on fence
313 if (error == C2_OK) {
314 std::shared_ptr<WriteViewBuddy::Impl> rvi = std::shared_ptr<WriteViewBuddy::Impl>(
315 new WriteViewBuddy::Impl(*mImpl, (uint8_t *)base, 0, len),
316 [base, len](WriteViewBuddy::Impl *i) {
317 (void)i->getAllocation()->unmap(base, len, nullptr);
318 delete i;
319 });
320 return AcquirableWriteViewBuddy(error, C2Fence(), WriteViewBuddy(rvi));
321 } else {
322 return AcquirableWriteViewBuddy(error, C2Fence(), WriteViewBuddy(error));
323 }
324}
325
326C2ConstLinearBlock C2LinearBlock::share(size_t offset_, size_t size_, C2Fence fence) {
327 return ConstLinearBlockBuddy(mImpl, C2LinearRange(*this, offset_, size_), fence);
328}
329
330C2BasicLinearBlockPool::C2BasicLinearBlockPool(
331 const std::shared_ptr<C2Allocator> &allocator)
332 : mAllocator(allocator) { }
333
334c2_status_t C2BasicLinearBlockPool::fetchLinearBlock(
335 uint32_t capacity,
336 C2MemoryUsage usage,
337 std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
338 block->reset();
339
340 std::shared_ptr<C2LinearAllocation> alloc;
341 c2_status_t err = mAllocator->newLinearAllocation(capacity, usage, &alloc);
342 if (err != C2_OK) {
343 return err;
344 }
345
346 *block = _C2BlockFactory::CreateLinearBlock(alloc);
347
348 return C2_OK;
349}
350
351struct C2_HIDE C2PooledBlockPoolData : _C2BlockPoolData {
352
353 virtual type_t getType() const override {
354 return TYPE_BUFFERPOOL;
355 }
356
357 void getBufferPoolData(std::shared_ptr<BufferPoolData> *data) const {
358 *data = mData;
359 }
360
361 C2PooledBlockPoolData(const std::shared_ptr<BufferPoolData> &data) : mData(data) {}
362
363 virtual ~C2PooledBlockPoolData() override {}
364
365private:
366 std::shared_ptr<BufferPoolData> mData;
367};
368
369bool _C2BlockFactory::GetBufferPoolData(
370 const std::shared_ptr<const _C2BlockPoolData> &data,
371 std::shared_ptr<BufferPoolData> *bufferPoolData) {
372 if (data && data->getType() == _C2BlockPoolData::TYPE_BUFFERPOOL) {
373 const std::shared_ptr<const C2PooledBlockPoolData> poolData =
374 std::static_pointer_cast<const C2PooledBlockPoolData>(data);
375 poolData->getBufferPoolData(bufferPoolData);
376 return true;
377 }
378 return false;
379}
380
381std::shared_ptr<C2LinearBlock> _C2BlockFactory::CreateLinearBlock(
382 const std::shared_ptr<C2LinearAllocation> &alloc,
383 const std::shared_ptr<_C2BlockPoolData> &data, size_t offset, size_t size) {
384 std::shared_ptr<C2Block1D::Impl> impl =
385 std::make_shared<C2Block1D::Impl>(alloc, data, offset, size);
386 return std::shared_ptr<C2LinearBlock>(new C2LinearBlock(impl, *impl));
387}
388
389std::shared_ptr<_C2BlockPoolData> _C2BlockFactory::GetLinearBlockPoolData(
390 const C2Block1D &block) {
391 if (block.mImpl) {
392 return block.mImpl->poolData();
393 }
394 return nullptr;
395}
396
397std::shared_ptr<C2LinearBlock> _C2BlockFactory::CreateLinearBlock(
398 const C2Handle *handle) {
399 // TODO: get proper allocator? and mutex?
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800400 static std::unique_ptr<C2Allocator> sAllocator = []{
401 std::unique_ptr<C2Allocator> allocator;
402 if (android::GetPreferredLinearAllocatorId(android::GetCodec2PoolMask()) ==
403 android::C2PlatformAllocatorStore::BLOB) {
404 allocator = std::make_unique<C2AllocatorBlob>(android::C2PlatformAllocatorStore::BLOB);
405 } else {
406 allocator = std::make_unique<C2AllocatorIon>(android::C2PlatformAllocatorStore::ION);
407 }
408 return allocator;
409 }();
410
411 if (sAllocator == nullptr)
412 return nullptr;
413
414 bool isValidHandle = false;
415 if (sAllocator->getId() == android::C2PlatformAllocatorStore::BLOB) {
416 isValidHandle = C2AllocatorBlob::isValid(handle);
417 } else {
418 isValidHandle = C2AllocatorIon::isValid(handle);
419 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800420
421 std::shared_ptr<C2LinearAllocation> alloc;
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800422 if (isValidHandle) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800423 c2_status_t err = sAllocator->priorLinearAllocation(handle, &alloc);
424 if (err == C2_OK) {
425 std::shared_ptr<C2LinearBlock> block = _C2BlockFactory::CreateLinearBlock(alloc);
426 return block;
427 }
428 }
429 return nullptr;
430}
431
432std::shared_ptr<C2LinearBlock> _C2BlockFactory::CreateLinearBlock(
433 const C2Handle *cHandle, const std::shared_ptr<BufferPoolData> &data) {
434 // TODO: get proper allocator? and mutex?
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800435 static std::unique_ptr<C2Allocator> sAllocator = []{
436 std::unique_ptr<C2Allocator> allocator;
437 if (android::GetPreferredLinearAllocatorId(android::GetCodec2PoolMask()) ==
438 android::C2PlatformAllocatorStore::BLOB) {
439 allocator = std::make_unique<C2AllocatorBlob>(android::C2PlatformAllocatorStore::BLOB);
440 } else {
441 allocator = std::make_unique<C2AllocatorIon>(android::C2PlatformAllocatorStore::ION);
442 }
443 return allocator;
444 }();
445
446 if (sAllocator == nullptr)
447 return nullptr;
448
449 bool isValidHandle = false;
450 if (sAllocator->getId() == android::C2PlatformAllocatorStore::BLOB) {
451 isValidHandle = C2AllocatorBlob::isValid(cHandle);
452 } else {
453 isValidHandle = C2AllocatorIon::isValid(cHandle);
454 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800455
456 std::shared_ptr<C2LinearAllocation> alloc;
Pin-chih Linaa18ea52019-11-19 18:48:50 +0800457 if (isValidHandle) {
Sungtak Leedc5cb622019-07-25 14:22:36 -0700458 c2_status_t err = sAllocator->priorLinearAllocation(cHandle, &alloc);
459 const std::shared_ptr<C2PooledBlockPoolData> poolData =
460 std::make_shared<C2PooledBlockPoolData>(data);
461 if (err == C2_OK && poolData) {
462 // TODO: config params?
463 std::shared_ptr<C2LinearBlock> block =
464 _C2BlockFactory::CreateLinearBlock(alloc, poolData);
465 return block;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800466 }
467 }
468 return nullptr;
469};
470
471/**
472 * Wrapped C2Allocator which is injected to buffer pool on behalf of
473 * C2BlockPool.
474 */
475class _C2BufferPoolAllocator : public BufferPoolAllocator {
476public:
477 _C2BufferPoolAllocator(const std::shared_ptr<C2Allocator> &allocator)
478 : mAllocator(allocator) {}
479
480 ~_C2BufferPoolAllocator() override {}
481
482 ResultStatus allocate(const std::vector<uint8_t> &params,
483 std::shared_ptr<BufferPoolAllocation> *alloc,
484 size_t *allocSize) override;
485
486 bool compatible(const std::vector<uint8_t> &newParams,
487 const std::vector<uint8_t> &oldParams) override;
488
489 // Methods for codec2 component (C2BlockPool).
490 /**
491 * Transforms linear allocation parameters for C2Allocator to parameters
492 * for buffer pool.
493 *
494 * @param capacity size of linear allocation
495 * @param usage memory usage pattern for linear allocation
496 * @param params allocation parameters for buffer pool
497 */
498 void getLinearParams(uint32_t capacity, C2MemoryUsage usage,
499 std::vector<uint8_t> *params);
500
501 /**
502 * Transforms graphic allocation parameters for C2Allocator to parameters
503 * for buffer pool.
504 *
505 * @param width width of graphic allocation
506 * @param height height of graphic allocation
507 * @param format color format of graphic allocation
508 * @param params allocation parameter for buffer pool
509 */
510 void getGraphicParams(uint32_t width, uint32_t height,
511 uint32_t format, C2MemoryUsage usage,
512 std::vector<uint8_t> *params);
513
514 /**
515 * Transforms an existing native handle to an C2LinearAllcation.
516 * Wrapper to C2Allocator#priorLinearAllocation
517 */
518 c2_status_t priorLinearAllocation(
519 const C2Handle *handle,
520 std::shared_ptr<C2LinearAllocation> *c2Allocation);
521
522 /**
523 * Transforms an existing native handle to an C2GraphicAllcation.
524 * Wrapper to C2Allocator#priorGraphicAllocation
525 */
526 c2_status_t priorGraphicAllocation(
527 const C2Handle *handle,
528 std::shared_ptr<C2GraphicAllocation> *c2Allocation);
529
530private:
531 static constexpr int kMaxIntParams = 5; // large enough number;
532
533 enum AllocType : uint8_t {
534 ALLOC_NONE = 0,
535
536 ALLOC_LINEAR,
537 ALLOC_GRAPHIC,
538 };
539
540 union AllocParams {
541 struct {
542 AllocType allocType;
543 C2MemoryUsage usage;
544 uint32_t params[kMaxIntParams];
545 } data;
546 uint8_t array[0];
547
548 AllocParams() : data{ALLOC_NONE, {0, 0}, {0}} {}
549 AllocParams(C2MemoryUsage usage, uint32_t capacity)
550 : data{ALLOC_LINEAR, usage, {[0] = capacity}} {}
551 AllocParams(
552 C2MemoryUsage usage,
553 uint32_t width, uint32_t height, uint32_t format)
554 : data{ALLOC_GRAPHIC, usage, {width, height, format}} {}
555 };
556
557 const std::shared_ptr<C2Allocator> mAllocator;
558};
559
560struct LinearAllocationDtor {
561 LinearAllocationDtor(const std::shared_ptr<C2LinearAllocation> &alloc)
562 : mAllocation(alloc) {}
563
564 void operator()(BufferPoolAllocation *poolAlloc) { delete poolAlloc; }
565
566 const std::shared_ptr<C2LinearAllocation> mAllocation;
567};
568
569struct GraphicAllocationDtor {
570 GraphicAllocationDtor(const std::shared_ptr<C2GraphicAllocation> &alloc)
571 : mAllocation(alloc) {}
572
573 void operator()(BufferPoolAllocation *poolAlloc) { delete poolAlloc; }
574
575 const std::shared_ptr<C2GraphicAllocation> mAllocation;
576};
577
578ResultStatus _C2BufferPoolAllocator::allocate(
579 const std::vector<uint8_t> &params,
580 std::shared_ptr<BufferPoolAllocation> *alloc,
581 size_t *allocSize) {
582 AllocParams c2Params;
583 memcpy(&c2Params, params.data(), std::min(sizeof(AllocParams), params.size()));
584 c2_status_t status = C2_BAD_VALUE;
585 switch(c2Params.data.allocType) {
586 case ALLOC_NONE:
587 break;
588 case ALLOC_LINEAR: {
589 std::shared_ptr<C2LinearAllocation> c2Linear;
590 status = mAllocator->newLinearAllocation(
591 c2Params.data.params[0], c2Params.data.usage, &c2Linear);
592 if (status == C2_OK && c2Linear) {
593 BufferPoolAllocation *ptr = new BufferPoolAllocation(c2Linear->handle());
594 if (ptr) {
595 *alloc = std::shared_ptr<BufferPoolAllocation>(
596 ptr, LinearAllocationDtor(c2Linear));
597 if (*alloc) {
598 *allocSize = (size_t)c2Params.data.params[0];
599 return ResultStatus::OK;
600 }
601 delete ptr;
602 }
603 return ResultStatus::NO_MEMORY;
604 }
605 break;
606 }
607 case ALLOC_GRAPHIC: {
608 std::shared_ptr<C2GraphicAllocation> c2Graphic;
609 status = mAllocator->newGraphicAllocation(
610 c2Params.data.params[0],
611 c2Params.data.params[1],
612 c2Params.data.params[2],
613 c2Params.data.usage, &c2Graphic);
614 if (status == C2_OK && c2Graphic) {
615 BufferPoolAllocation *ptr = new BufferPoolAllocation(c2Graphic->handle());
616 if (ptr) {
617 *alloc = std::shared_ptr<BufferPoolAllocation>(
618 ptr, GraphicAllocationDtor(c2Graphic));
619 if (*alloc) {
620 *allocSize = c2Params.data.params[0] * c2Params.data.params[1];
621 return ResultStatus::OK;
622 }
623 delete ptr;
624 }
625 return ResultStatus::NO_MEMORY;
626 }
627 break;
628 }
629 default:
630 break;
631 }
632 return ResultStatus::CRITICAL_ERROR;
633}
634
635bool _C2BufferPoolAllocator::compatible(
636 const std::vector<uint8_t> &newParams,
637 const std::vector<uint8_t> &oldParams) {
638 AllocParams newAlloc;
639 AllocParams oldAlloc;
640 memcpy(&newAlloc, newParams.data(), std::min(sizeof(AllocParams), newParams.size()));
641 memcpy(&oldAlloc, oldParams.data(), std::min(sizeof(AllocParams), oldParams.size()));
642
643 // TODO: support not exact matching. e.g) newCapacity < oldCapacity
644 if (newAlloc.data.allocType == oldAlloc.data.allocType &&
645 newAlloc.data.usage.expected == oldAlloc.data.usage.expected) {
646 for (int i = 0; i < kMaxIntParams; ++i) {
647 if (newAlloc.data.params[i] != oldAlloc.data.params[i]) {
648 return false;
649 }
650 }
651 return true;
652 }
653 return false;
654}
655
656void _C2BufferPoolAllocator::getLinearParams(
657 uint32_t capacity, C2MemoryUsage usage, std::vector<uint8_t> *params) {
658 AllocParams c2Params(usage, capacity);
659 params->assign(c2Params.array, c2Params.array + sizeof(AllocParams));
660}
661
662void _C2BufferPoolAllocator::getGraphicParams(
663 uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
664 std::vector<uint8_t> *params) {
665 AllocParams c2Params(usage, width, height, format);
666 params->assign(c2Params.array, c2Params.array + sizeof(AllocParams));
667}
668
669c2_status_t _C2BufferPoolAllocator::priorLinearAllocation(
670 const C2Handle *handle,
671 std::shared_ptr<C2LinearAllocation> *c2Allocation) {
672 return mAllocator->priorLinearAllocation(handle, c2Allocation);
673}
674
675c2_status_t _C2BufferPoolAllocator::priorGraphicAllocation(
676 const C2Handle *handle,
677 std::shared_ptr<C2GraphicAllocation> *c2Allocation) {
678 return mAllocator->priorGraphicAllocation(handle, c2Allocation);
679}
680
681class C2PooledBlockPool::Impl {
682public:
683 Impl(const std::shared_ptr<C2Allocator> &allocator)
684 : mInit(C2_OK),
685 mBufferPoolManager(ClientManager::getInstance()),
686 mAllocator(std::make_shared<_C2BufferPoolAllocator>(allocator)) {
687 if (mAllocator && mBufferPoolManager) {
688 if (mBufferPoolManager->create(
689 mAllocator, &mConnectionId) == ResultStatus::OK) {
690 return;
691 }
692 }
693 mInit = C2_NO_INIT;
694 }
695
696 ~Impl() {
697 if (mInit == C2_OK) {
698 mBufferPoolManager->close(mConnectionId);
699 }
700 }
701
702 c2_status_t fetchLinearBlock(
703 uint32_t capacity, C2MemoryUsage usage,
704 std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
705 block->reset();
706 if (mInit != C2_OK) {
707 return mInit;
708 }
709 std::vector<uint8_t> params;
710 mAllocator->getLinearParams(capacity, usage, &params);
711 std::shared_ptr<BufferPoolData> bufferPoolData;
712 native_handle_t *cHandle = nullptr;
713 ResultStatus status = mBufferPoolManager->allocate(
714 mConnectionId, params, &cHandle, &bufferPoolData);
715 if (status == ResultStatus::OK) {
Sungtak Leedc5cb622019-07-25 14:22:36 -0700716 std::shared_ptr<C2LinearAllocation> alloc;
717 std::shared_ptr<C2PooledBlockPoolData> poolData =
718 std::make_shared<C2PooledBlockPoolData>(bufferPoolData);
719 c2_status_t err = mAllocator->priorLinearAllocation(cHandle, &alloc);
720 if (err == C2_OK && poolData && alloc) {
721 *block = _C2BlockFactory::CreateLinearBlock(alloc, poolData, 0, capacity);
722 if (*block) {
723 return C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800724 }
725 }
726 return C2_NO_MEMORY;
727 }
728 if (status == ResultStatus::NO_MEMORY) {
729 return C2_NO_MEMORY;
730 }
731 return C2_CORRUPTED;
732 }
733
734 c2_status_t fetchGraphicBlock(
735 uint32_t width, uint32_t height, uint32_t format,
736 C2MemoryUsage usage,
737 std::shared_ptr<C2GraphicBlock> *block) {
738 block->reset();
739 if (mInit != C2_OK) {
740 return mInit;
741 }
742 std::vector<uint8_t> params;
743 mAllocator->getGraphicParams(width, height, format, usage, &params);
744 std::shared_ptr<BufferPoolData> bufferPoolData;
745 native_handle_t *cHandle = nullptr;
746 ResultStatus status = mBufferPoolManager->allocate(
747 mConnectionId, params, &cHandle, &bufferPoolData);
748 if (status == ResultStatus::OK) {
Sungtak Leedc5cb622019-07-25 14:22:36 -0700749 std::shared_ptr<C2GraphicAllocation> alloc;
750 std::shared_ptr<C2PooledBlockPoolData> poolData =
751 std::make_shared<C2PooledBlockPoolData>(bufferPoolData);
752 c2_status_t err = mAllocator->priorGraphicAllocation(
753 cHandle, &alloc);
754 if (err == C2_OK && poolData && alloc) {
755 *block = _C2BlockFactory::CreateGraphicBlock(
756 alloc, poolData, C2Rect(width, height));
757 if (*block) {
758 return C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800759 }
760 }
761 return C2_NO_MEMORY;
762 }
763 if (status == ResultStatus::NO_MEMORY) {
764 return C2_NO_MEMORY;
765 }
766 return C2_CORRUPTED;
767 }
768
769 ConnectionId getConnectionId() {
770 return mInit != C2_OK ? INVALID_CONNECTIONID : mConnectionId;
771 }
772
773private:
774 c2_status_t mInit;
775 const android::sp<ClientManager> mBufferPoolManager;
776 ConnectionId mConnectionId; // locally
777 const std::shared_ptr<_C2BufferPoolAllocator> mAllocator;
778};
779
780C2PooledBlockPool::C2PooledBlockPool(
781 const std::shared_ptr<C2Allocator> &allocator, const local_id_t localId)
782 : mAllocator(allocator), mLocalId(localId), mImpl(new Impl(allocator)) {}
783
784C2PooledBlockPool::~C2PooledBlockPool() {
785}
786
787c2_status_t C2PooledBlockPool::fetchLinearBlock(
788 uint32_t capacity,
789 C2MemoryUsage usage,
790 std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
791 if (mImpl) {
792 return mImpl->fetchLinearBlock(capacity, usage, block);
793 }
794 return C2_CORRUPTED;
795}
796
797c2_status_t C2PooledBlockPool::fetchGraphicBlock(
798 uint32_t width,
799 uint32_t height,
800 uint32_t format,
801 C2MemoryUsage usage,
802 std::shared_ptr<C2GraphicBlock> *block) {
803 if (mImpl) {
804 return mImpl->fetchGraphicBlock(width, height, format, usage, block);
805 }
806 return C2_CORRUPTED;
807}
808
809int64_t C2PooledBlockPool::getConnectionId() {
810 if (mImpl) {
811 return mImpl->getConnectionId();
812 }
813 return 0;
814}
815
816/* ========================================== 2D BLOCK ========================================= */
817
818/**
819 * Implementation that is shared between all 2D blocks and views.
820 *
821 * For blocks' Impl's crop is always the allotted crop, even if it is a sub block.
822 *
823 * For views' Impl's crop is the mapped portion - which for now is always the
824 * allotted crop.
825 */
826class C2_HIDE _C2Block2DImpl : public _C2PlanarSectionAspect {
827public:
828 /**
829 * Impl's crop is always the or part of the allotted crop of the allocation.
830 */
831 _C2Block2DImpl(const std::shared_ptr<C2GraphicAllocation> &alloc,
832 const std::shared_ptr<_C2BlockPoolData> &poolData = nullptr,
833 const C2Rect &allottedCrop = C2Rect(~0u, ~0u))
834 : _C2PlanarSectionAspect(alloc.get(), allottedCrop),
835 mAllocation(alloc),
836 mPoolData(poolData) { }
837
838 virtual ~_C2Block2DImpl() = default;
839
840 /** returns pool data */
841 std::shared_ptr<_C2BlockPoolData> poolData() const {
842 return mPoolData;
843 }
844
845 /** returns native handle */
846 const C2Handle *handle() const {
847 return mAllocation ? mAllocation->handle() : nullptr;
848 }
849
850 /** returns the allocator's ID */
851 C2Allocator::id_t getAllocatorId() const {
852 // BAD_ID can only happen if this Impl class is initialized for a view - never for a block.
853 return mAllocation ? mAllocation->getAllocatorId() : C2Allocator::BAD_ID;
854 }
855
856 std::shared_ptr<C2GraphicAllocation> getAllocation() const {
857 return mAllocation;
858 }
859
860private:
861 std::shared_ptr<C2GraphicAllocation> mAllocation;
862 std::shared_ptr<_C2BlockPoolData> mPoolData;
863};
864
865class C2_HIDE _C2MappingBlock2DImpl
866 : public _C2Block2DImpl, public std::enable_shared_from_this<_C2MappingBlock2DImpl> {
867public:
868 using _C2Block2DImpl::_C2Block2DImpl;
869
870 virtual ~_C2MappingBlock2DImpl() override = default;
871
872 /**
873 * This class contains the mapped data pointer, and the potential error.
874 */
875 struct Mapped {
876 private:
877 friend class _C2MappingBlock2DImpl;
878
879 Mapped(const std::shared_ptr<_C2Block2DImpl> &impl, bool writable, C2Fence *fence __unused)
880 : mImpl(impl), mWritable(writable) {
881 memset(mData, 0, sizeof(mData));
882 const C2Rect crop = mImpl->crop();
883 // gralloc requires mapping the whole region of interest as we cannot
884 // map multiple regions
885 mError = mImpl->getAllocation()->map(
886 crop,
887 { C2MemoryUsage::CPU_READ, writable ? C2MemoryUsage::CPU_WRITE : 0 },
888 nullptr,
889 &mLayout,
890 mData);
891 if (mError != C2_OK) {
892 memset(&mLayout, 0, sizeof(mLayout));
893 memset(mData, 0, sizeof(mData));
894 memset(mOffsetData, 0, sizeof(mData));
895 } else {
896 // TODO: validate plane layout and
897 // adjust data pointers to the crop region's top left corner.
898 // fail if it is not on a subsampling boundary
899 for (size_t planeIx = 0; planeIx < mLayout.numPlanes; ++planeIx) {
900 const uint32_t colSampling = mLayout.planes[planeIx].colSampling;
901 const uint32_t rowSampling = mLayout.planes[planeIx].rowSampling;
902 if (crop.left % colSampling || crop.right() % colSampling
903 || crop.top % rowSampling || crop.bottom() % rowSampling) {
904 // cannot calculate data pointer
905 mImpl->getAllocation()->unmap(mData, crop, nullptr);
906 memset(&mLayout, 0, sizeof(mLayout));
907 memset(mData, 0, sizeof(mData));
908 memset(mOffsetData, 0, sizeof(mData));
909 mError = C2_BAD_VALUE;
910 return;
911 }
912 mOffsetData[planeIx] =
913 mData[planeIx] + (ssize_t)crop.left * mLayout.planes[planeIx].colInc
914 + (ssize_t)crop.top * mLayout.planes[planeIx].rowInc;
915 }
916 }
917 }
918
919 explicit Mapped(c2_status_t error)
920 : mImpl(nullptr), mWritable(false), mError(error) {
921 // CHECK(error != C2_OK);
922 memset(&mLayout, 0, sizeof(mLayout));
923 memset(mData, 0, sizeof(mData));
924 memset(mOffsetData, 0, sizeof(mData));
925 }
926
927 public:
928 ~Mapped() {
929 if (mData[0] != nullptr) {
930 mImpl->getAllocation()->unmap(mData, mImpl->crop(), nullptr);
931 }
932 }
933
934 /** returns mapping status */
935 c2_status_t error() const { return mError; }
936
937 /** returns data pointer */
938 uint8_t *const *data() const { return mOffsetData; }
939
940 /** returns the plane layout */
941 C2PlanarLayout layout() const { return mLayout; }
942
943 /** returns whether the mapping is writable */
944 bool writable() const { return mWritable; }
945
946 private:
947 const std::shared_ptr<_C2Block2DImpl> mImpl;
948 bool mWritable;
949 c2_status_t mError;
950 uint8_t *mData[C2PlanarLayout::MAX_NUM_PLANES];
951 uint8_t *mOffsetData[C2PlanarLayout::MAX_NUM_PLANES];
952 C2PlanarLayout mLayout;
953 };
954
955 /**
956 * Maps the allotted region.
957 *
958 * If already mapped and it is currently in use, returns the existing mapping.
959 * If fence is provided, an acquire fence is stored there.
960 */
961 std::shared_ptr<Mapped> map(bool writable, C2Fence *fence) {
962 std::lock_guard<std::mutex> lock(mMappedLock);
963 std::shared_ptr<Mapped> existing = mMapped.lock();
964 if (!existing) {
965 existing = std::shared_ptr<Mapped>(new Mapped(shared_from_this(), writable, fence));
966 mMapped = existing;
967 } else {
968 // if we mapped the region read-only, we cannot remap it read-write
969 if (writable && !existing->writable()) {
970 existing = std::shared_ptr<Mapped>(new Mapped(C2_CANNOT_DO));
971 }
972 if (fence != nullptr) {
973 *fence = C2Fence();
974 }
975 }
976 return existing;
977 }
978
979private:
980 std::weak_ptr<Mapped> mMapped;
981 std::mutex mMappedLock;
982};
983
984class C2_HIDE _C2MappedBlock2DImpl : public _C2Block2DImpl {
985public:
986 _C2MappedBlock2DImpl(const _C2Block2DImpl &impl,
987 std::shared_ptr<_C2MappingBlock2DImpl::Mapped> mapping)
988 : _C2Block2DImpl(impl), mMapping(mapping) {
989 }
990
991 virtual ~_C2MappedBlock2DImpl() override = default;
992
993 std::shared_ptr<_C2MappingBlock2DImpl::Mapped> mapping() const { return mMapping; }
994
995private:
996 std::shared_ptr<_C2MappingBlock2DImpl::Mapped> mMapping;
997};
998
999/**
1000 * Block implementation.
1001 */
1002class C2Block2D::Impl : public _C2MappingBlock2DImpl {
1003public:
1004 using _C2MappingBlock2DImpl::_C2MappingBlock2DImpl;
1005 virtual ~Impl() override = default;
1006};
1007
1008const C2Handle *C2Block2D::handle() const {
1009 return mImpl->handle();
1010}
1011
1012C2Allocator::id_t C2Block2D::getAllocatorId() const {
1013 return mImpl->getAllocatorId();
1014}
1015
1016C2Block2D::C2Block2D(std::shared_ptr<Impl> impl, const _C2PlanarSectionAspect &section)
1017 // always clamp subsection to parent (impl) crop for safety
1018 : _C2PlanarSectionAspect(impl.get(), section.crop()), mImpl(impl) {
1019}
1020
1021/**
1022 * Graphic view implementation.
1023 *
1024 * range of Impl is the mapped range of the underlying allocation. range of View is the current
1025 * crop.
1026 */
1027class C2GraphicView::Impl : public _C2MappedBlock2DImpl {
1028public:
1029 using _C2MappedBlock2DImpl::_C2MappedBlock2DImpl;
1030 virtual ~Impl() override = default;
1031};
1032
1033C2GraphicView::C2GraphicView(std::shared_ptr<Impl> impl, const _C2PlanarSectionAspect &section)
1034 : _C2EditablePlanarSectionAspect(impl.get(), section.crop()), mImpl(impl) {
1035}
1036
1037const uint8_t *const *C2GraphicView::data() const {
1038 return mImpl->mapping()->data();
1039}
1040
1041uint8_t *const *C2GraphicView::data() {
1042 return mImpl->mapping()->data();
1043}
1044
1045const C2PlanarLayout C2GraphicView::layout() const {
1046 return mImpl->mapping()->layout();
1047}
1048
1049const C2GraphicView C2GraphicView::subView(const C2Rect &rect) const {
1050 return C2GraphicView(mImpl, C2PlanarSection(*mImpl, rect));
1051}
1052
1053C2GraphicView C2GraphicView::subView(const C2Rect &rect) {
1054 return C2GraphicView(mImpl, C2PlanarSection(*mImpl, rect));
1055}
1056
1057c2_status_t C2GraphicView::error() const {
1058 return mImpl->mapping()->error();
1059}
1060
1061/**
1062 * Const graphic block implementation.
1063 */
1064C2ConstGraphicBlock::C2ConstGraphicBlock(
1065 std::shared_ptr<Impl> impl, const _C2PlanarSectionAspect &section, C2Fence fence)
1066 : C2Block2D(impl, section), mFence(fence) { }
1067
1068C2Acquirable<const C2GraphicView> C2ConstGraphicBlock::map() const {
1069 C2Fence fence;
1070 std::shared_ptr<_C2MappingBlock2DImpl::Mapped> mapping =
1071 mImpl->map(false /* writable */, &fence);
1072 std::shared_ptr<GraphicViewBuddy::Impl> gvi =
1073 std::shared_ptr<GraphicViewBuddy::Impl>(new GraphicViewBuddy::Impl(*mImpl, mapping));
1074 return AcquirableConstGraphicViewBuddy(
1075 mapping->error(), fence, GraphicViewBuddy(gvi, C2PlanarSection(*mImpl, crop())));
1076}
1077
1078C2ConstGraphicBlock C2ConstGraphicBlock::subBlock(const C2Rect &rect) const {
1079 return C2ConstGraphicBlock(mImpl, C2PlanarSection(*mImpl, crop().intersect(rect)), mFence);
1080}
1081
1082/**
1083 * Graphic block implementation.
1084 */
1085C2GraphicBlock::C2GraphicBlock(
1086 std::shared_ptr<Impl> impl, const _C2PlanarSectionAspect &section)
1087 : C2Block2D(impl, section) { }
1088
1089C2Acquirable<C2GraphicView> C2GraphicBlock::map() {
1090 C2Fence fence;
1091 std::shared_ptr<_C2MappingBlock2DImpl::Mapped> mapping =
1092 mImpl->map(true /* writable */, &fence);
1093 std::shared_ptr<GraphicViewBuddy::Impl> gvi =
1094 std::shared_ptr<GraphicViewBuddy::Impl>(new GraphicViewBuddy::Impl(*mImpl, mapping));
1095 return AcquirableGraphicViewBuddy(
1096 mapping->error(), fence, GraphicViewBuddy(gvi, C2PlanarSection(*mImpl, crop())));
1097}
1098
1099C2ConstGraphicBlock C2GraphicBlock::share(const C2Rect &crop, C2Fence fence) {
1100 return ConstGraphicBlockBuddy(mImpl, C2PlanarSection(*mImpl, crop), fence);
1101}
1102
1103/**
1104 * Basic block pool implementations.
1105 */
1106C2BasicGraphicBlockPool::C2BasicGraphicBlockPool(
1107 const std::shared_ptr<C2Allocator> &allocator)
1108 : mAllocator(allocator) {}
1109
1110c2_status_t C2BasicGraphicBlockPool::fetchGraphicBlock(
1111 uint32_t width,
1112 uint32_t height,
1113 uint32_t format,
1114 C2MemoryUsage usage,
1115 std::shared_ptr<C2GraphicBlock> *block /* nonnull */) {
1116 block->reset();
1117
1118 std::shared_ptr<C2GraphicAllocation> alloc;
1119 c2_status_t err = mAllocator->newGraphicAllocation(width, height, format, usage, &alloc);
1120 if (err != C2_OK) {
1121 return err;
1122 }
1123
1124 *block = _C2BlockFactory::CreateGraphicBlock(alloc);
1125
1126 return C2_OK;
1127}
1128
1129std::shared_ptr<C2GraphicBlock> _C2BlockFactory::CreateGraphicBlock(
1130 const std::shared_ptr<C2GraphicAllocation> &alloc,
1131 const std::shared_ptr<_C2BlockPoolData> &data, const C2Rect &allottedCrop) {
1132 std::shared_ptr<C2Block2D::Impl> impl =
1133 std::make_shared<C2Block2D::Impl>(alloc, data, allottedCrop);
1134 return std::shared_ptr<C2GraphicBlock>(new C2GraphicBlock(impl, *impl));
1135}
1136
1137std::shared_ptr<_C2BlockPoolData> _C2BlockFactory::GetGraphicBlockPoolData(
1138 const C2Block2D &block) {
1139 if (block.mImpl) {
1140 return block.mImpl->poolData();
1141 }
1142 return nullptr;
1143}
1144
1145std::shared_ptr<C2GraphicBlock> _C2BlockFactory::CreateGraphicBlock(
1146 const C2Handle *cHandle,
1147 const std::shared_ptr<BufferPoolData> &data) {
1148 // TODO: get proper allocator? and mutex?
1149 static std::unique_ptr<C2AllocatorGralloc> sAllocator = std::make_unique<C2AllocatorGralloc>(0);
1150
1151 std::shared_ptr<C2GraphicAllocation> alloc;
1152 if (C2AllocatorGralloc::isValid(cHandle)) {
Sungtak Leedc5cb622019-07-25 14:22:36 -07001153 c2_status_t err = sAllocator->priorGraphicAllocation(cHandle, &alloc);
1154 const std::shared_ptr<C2PooledBlockPoolData> poolData =
1155 std::make_shared<C2PooledBlockPoolData>(data);
1156 if (err == C2_OK && poolData) {
1157 // TODO: config setup?
1158 std::shared_ptr<C2GraphicBlock> block =
1159 _C2BlockFactory::CreateGraphicBlock(alloc, poolData);
1160 return block;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001161 }
1162 }
1163 return nullptr;
1164};
1165
1166
1167/* ========================================== BUFFER ========================================= */
1168
1169class C2BufferData::Impl {
1170public:
1171 explicit Impl(const std::vector<C2ConstLinearBlock> &blocks)
1172 : mType(blocks.size() == 1 ? LINEAR : LINEAR_CHUNKS),
1173 mLinearBlocks(blocks) {
1174 }
1175
1176 explicit Impl(const std::vector<C2ConstGraphicBlock> &blocks)
1177 : mType(blocks.size() == 1 ? GRAPHIC : GRAPHIC_CHUNKS),
1178 mGraphicBlocks(blocks) {
1179 }
1180
1181 type_t type() const { return mType; }
1182 const std::vector<C2ConstLinearBlock> &linearBlocks() const { return mLinearBlocks; }
1183 const std::vector<C2ConstGraphicBlock> &graphicBlocks() const { return mGraphicBlocks; }
1184
1185private:
1186 type_t mType;
1187 std::vector<C2ConstLinearBlock> mLinearBlocks;
1188 std::vector<C2ConstGraphicBlock> mGraphicBlocks;
Lajos Molnar5019e352020-07-22 11:11:46 -07001189 friend class C2InfoBuffer;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001190};
1191
1192C2BufferData::C2BufferData(const std::vector<C2ConstLinearBlock> &blocks) : mImpl(new Impl(blocks)) {}
1193C2BufferData::C2BufferData(const std::vector<C2ConstGraphicBlock> &blocks) : mImpl(new Impl(blocks)) {}
1194
1195C2BufferData::type_t C2BufferData::type() const { return mImpl->type(); }
1196
1197const std::vector<C2ConstLinearBlock> C2BufferData::linearBlocks() const {
1198 return mImpl->linearBlocks();
1199}
1200
1201const std::vector<C2ConstGraphicBlock> C2BufferData::graphicBlocks() const {
1202 return mImpl->graphicBlocks();
1203}
1204
Lajos Molnar5019e352020-07-22 11:11:46 -07001205C2InfoBuffer::C2InfoBuffer(
1206 C2Param::Index index, const std::vector<C2ConstLinearBlock> &blocks)
1207 : mIndex(index), mData(BufferDataBuddy(blocks)) {
1208}
1209
1210C2InfoBuffer::C2InfoBuffer(
1211 C2Param::Index index, const std::vector<C2ConstGraphicBlock> &blocks)
1212 : mIndex(index), mData(BufferDataBuddy(blocks)) {
1213}
1214
1215C2InfoBuffer::C2InfoBuffer(
1216 C2Param::Index index, const C2BufferData &data)
1217 : mIndex(index), mData(data) {
1218}
1219
1220// static
1221C2InfoBuffer C2InfoBuffer::CreateLinearBuffer(
1222 C2Param::CoreIndex index, const C2ConstLinearBlock &block) {
1223 return C2InfoBuffer(index.coreIndex() | C2Param::Index::KIND_INFO | C2Param::Index::DIR_GLOBAL,
1224 { block });
1225}
1226
1227// static
1228C2InfoBuffer C2InfoBuffer::CreateGraphicBuffer(
1229 C2Param::CoreIndex index, const C2ConstGraphicBlock &block) {
1230 return C2InfoBuffer(index.coreIndex() | C2Param::Index::KIND_INFO | C2Param::Index::DIR_GLOBAL,
1231 { block });
1232}
1233
Pawin Vongmasa36653902018-11-15 00:10:25 -08001234class C2Buffer::Impl {
1235public:
1236 Impl(C2Buffer *thiz, const std::vector<C2ConstLinearBlock> &blocks)
1237 : mThis(thiz), mData(blocks) {}
1238 Impl(C2Buffer *thiz, const std::vector<C2ConstGraphicBlock> &blocks)
1239 : mThis(thiz), mData(blocks) {}
1240
1241 ~Impl() {
1242 for (const auto &pair : mNotify) {
1243 pair.first(mThis, pair.second);
1244 }
1245 }
1246
1247 const C2BufferData &data() const { return mData; }
1248
1249 c2_status_t registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
1250 auto it = std::find_if(
1251 mNotify.begin(), mNotify.end(),
1252 [onDestroyNotify, arg] (const auto &pair) {
1253 return pair.first == onDestroyNotify && pair.second == arg;
1254 });
1255 if (it != mNotify.end()) {
1256 return C2_DUPLICATE;
1257 }
1258 mNotify.emplace_back(onDestroyNotify, arg);
1259 return C2_OK;
1260 }
1261
1262 c2_status_t unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
1263 auto it = std::find_if(
1264 mNotify.begin(), mNotify.end(),
1265 [onDestroyNotify, arg] (const auto &pair) {
1266 return pair.first == onDestroyNotify && pair.second == arg;
1267 });
1268 if (it == mNotify.end()) {
1269 return C2_NOT_FOUND;
1270 }
1271 mNotify.erase(it);
1272 return C2_OK;
1273 }
1274
1275 std::vector<std::shared_ptr<const C2Info>> info() const {
1276 std::vector<std::shared_ptr<const C2Info>> result(mInfos.size());
1277 std::transform(
1278 mInfos.begin(), mInfos.end(), result.begin(),
1279 [] (const auto &elem) { return elem.second; });
1280 return result;
1281 }
1282
1283 c2_status_t setInfo(const std::shared_ptr<C2Info> &info) {
1284 // To "update" you need to erase the existing one if any, and then insert.
1285 (void) mInfos.erase(info->coreIndex());
1286 (void) mInfos.insert({ info->coreIndex(), info });
1287 return C2_OK;
1288 }
1289
1290 bool hasInfo(C2Param::Type index) const {
1291 return mInfos.count(index.coreIndex()) > 0;
1292 }
1293
1294 std::shared_ptr<const C2Info> getInfo(C2Param::Type index) const {
1295 auto it = mInfos.find(index.coreIndex());
1296 if (it == mInfos.end()) {
1297 return nullptr;
1298 }
1299 return std::const_pointer_cast<const C2Info>(it->second);
1300 }
1301
1302 std::shared_ptr<C2Info> removeInfo(C2Param::Type index) {
1303 auto it = mInfos.find(index.coreIndex());
1304 if (it == mInfos.end()) {
1305 return nullptr;
1306 }
1307 std::shared_ptr<C2Info> ret = it->second;
1308 (void) mInfos.erase(it);
1309 return ret;
1310 }
1311
1312private:
1313 C2Buffer * const mThis;
1314 BufferDataBuddy mData;
1315 std::map<C2Param::CoreIndex, std::shared_ptr<C2Info>> mInfos;
1316 std::list<std::pair<OnDestroyNotify, void *>> mNotify;
1317};
1318
1319C2Buffer::C2Buffer(const std::vector<C2ConstLinearBlock> &blocks)
1320 : mImpl(new Impl(this, blocks)) {}
1321
1322C2Buffer::C2Buffer(const std::vector<C2ConstGraphicBlock> &blocks)
1323 : mImpl(new Impl(this, blocks)) {}
1324
1325const C2BufferData C2Buffer::data() const { return mImpl->data(); }
1326
1327c2_status_t C2Buffer::registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
1328 return mImpl->registerOnDestroyNotify(onDestroyNotify, arg);
1329}
1330
1331c2_status_t C2Buffer::unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
1332 return mImpl->unregisterOnDestroyNotify(onDestroyNotify, arg);
1333}
1334
1335const std::vector<std::shared_ptr<const C2Info>> C2Buffer::info() const {
1336 return mImpl->info();
1337}
1338
1339c2_status_t C2Buffer::setInfo(const std::shared_ptr<C2Info> &info) {
1340 return mImpl->setInfo(info);
1341}
1342
1343bool C2Buffer::hasInfo(C2Param::Type index) const {
1344 return mImpl->hasInfo(index);
1345}
1346
1347std::shared_ptr<const C2Info> C2Buffer::getInfo(C2Param::Type index) const {
1348 return mImpl->getInfo(index);
1349}
1350
1351std::shared_ptr<C2Info> C2Buffer::removeInfo(C2Param::Type index) {
1352 return mImpl->removeInfo(index);
1353}
1354
1355// static
1356std::shared_ptr<C2Buffer> C2Buffer::CreateLinearBuffer(const C2ConstLinearBlock &block) {
1357 return std::shared_ptr<C2Buffer>(new C2Buffer({ block }));
1358}
1359
1360// static
1361std::shared_ptr<C2Buffer> C2Buffer::CreateGraphicBuffer(const C2ConstGraphicBlock &block) {
1362 return std::shared_ptr<C2Buffer>(new C2Buffer({ block }));
1363}
1364