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