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