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 #ifndef C2BUFFER_H_ 18 #define C2BUFFER_H_ 19 20 #include <C2.h> 21 #include <C2BufferBase.h> 22 #include <C2Param.h> // for C2Info 23 24 #include <memory> 25 #include <vector> 26 27 #ifdef __ANDROID__ 28 #include <android-C2Buffer.h> 29 #else 30 31 typedef void* C2Handle; 32 33 #endif 34 35 /// \defgroup buffer Buffers 36 /// @{ 37 38 /// \defgroup buffer_sync Synchronization 39 /// @{ 40 41 /** 42 * Synchronization is accomplished using event and fence objects. 43 * 44 * These are cross-process extensions of promise/future infrastructure. 45 * Events are analogous to std::promise<void>, whereas fences are to std::shared_future<void>. 46 * 47 * Fences and events are shareable/copyable. 48 * 49 * Fences are used in two scenarios, and all copied instances refer to the same event. 50 * \todo do events need to be copyable or should they be unique? 51 * 52 * acquire sync fence object: signaled when it is safe for the component or client to access 53 * (the contents of) an object. 54 * 55 * release sync fence object: \todo 56 * 57 * Fences can be backed by hardware. Hardware fences are guaranteed to signal NO MATTER WHAT within 58 * a short (platform specific) amount of time; this guarantee is usually less than 15 msecs. 59 */ 60 61 /** 62 * Fence object used by components and the framework. 63 * 64 * Implements the waiting for an event, analogous to a 'future'. 65 * 66 * To be implemented by vendors if using HW fences. 67 */ 68 class C2Fence { 69 public: 70 /** 71 * Waits for a fence to be signaled with a timeout. 72 * 73 * \todo a mechanism to cancel a wait - for now the only way to do this is to abandon the 74 * event, but fences are shared so canceling a wait will cancel all waits. 75 * 76 * \param timeoutNs the maximum time to wait in nsecs 77 * 78 * \retval C2_OK the fence has been signaled 79 * \retval C2_TIMED_OUT the fence has not been signaled within the timeout 80 * \retval C2_BAD_STATE the fence has been abandoned without being signaled (it will never 81 * be signaled) 82 * \retval C2_REFUSED no permission to wait for the fence (unexpected - system) 83 * \retval C2_CORRUPTED some unknown error prevented waiting for the fence (unexpected) 84 */ 85 c2_status_t wait(c2_nsecs_t timeoutNs); 86 87 /** 88 * Used to check if this fence is valid (if there is a chance for it to be signaled.) 89 * A fence becomes invalid if the controling event is destroyed without it signaling the fence. 90 * 91 * \return whether this fence is valid 92 */ 93 bool valid() const; 94 95 /** 96 * Used to check if this fence has been signaled (is ready). 97 * 98 * \return whether this fence has been signaled 99 */ 100 bool ready() const; 101 102 /** 103 * Returns a file descriptor that can be used to wait for this fence in a select system call. 104 * \note The returned file descriptor, if valid, must be closed by the caller. 105 * 106 * This can be used in e.g. poll() system calls. This file becomes readable (POLLIN) when the 107 * fence is signaled, and bad (POLLERR) if the fence is abandoned. 108 * 109 * \return a file descriptor representing this fence (with ownership), or -1 if the fence 110 * has already been signaled (\todo or abandoned). 111 * 112 * \todo this must be compatible with fences used by gralloc 113 */ 114 int fd() const; 115 116 /** 117 * Returns whether this fence is a hardware-backed fence. 118 * \return whether this is a hardware fence 119 */ 120 bool isHW() const; 121 122 /** 123 * Null-fence. A fence that has fired. 124 */ C2Fence()125 constexpr C2Fence() : mImpl(nullptr) { } 126 127 private: 128 class Impl; 129 std::shared_ptr<Impl> mImpl; 130 C2Fence(std::shared_ptr<Impl> impl); 131 friend struct _C2FenceFactory; 132 }; 133 134 /** 135 * Event object used by components and the framework. 136 * 137 * Implements the signaling of an event, analogous to a 'promise'. 138 * 139 * Hardware backed events do not go through this object, and must be exposed directly as fences 140 * by vendors. 141 */ 142 class C2Event { 143 public: 144 /** 145 * Returns a fence for this event. 146 */ 147 C2Fence fence() const; 148 149 /** 150 * Signals (all) associated fence(s). 151 * This has no effect no effect if the event was already signaled or abandoned. 152 * 153 * \retval C2_OK the fence(s) were successfully signaled 154 * \retval C2_BAD_STATE the fence(s) have already been abandoned or merged (caller error) 155 * \retval C2_DUPLICATE the fence(s) have already been signaled (caller error) 156 * \retval C2_REFUSED no permission to signal the fence (unexpected - system) 157 * \retval C2_CORRUPTED some unknown error prevented signaling the fence(s) (unexpected) 158 */ 159 c2_status_t fire(); 160 161 /** 162 * Trigger this event from the merging of the supplied fences. This means that it will be 163 * abandoned if any of these fences have been abandoned, and it will be fired if all of these 164 * fences have been signaled. 165 * 166 * \retval C2_OK the merging was successfully done 167 * \retval C2_NO_MEMORY not enough memory to perform the merging 168 * \retval C2_DUPLICATE the fence have already been merged (caller error) 169 * \retval C2_BAD_STATE the fence have already been signaled or abandoned (caller error) 170 * \retval C2_REFUSED no permission to merge the fence (unexpected - system) 171 * \retval C2_CORRUPTED some unknown error prevented merging the fence(s) (unexpected) 172 */ 173 c2_status_t merge(std::vector<C2Fence> fences); 174 175 /** 176 * Abandons the event and any associated fence(s). 177 * \note Call this to explicitly abandon an event before it is destructed to avoid a warning. 178 * 179 * This has no effect no effect if the event was already signaled or abandoned. 180 * 181 * \retval C2_OK the fence(s) were successfully signaled 182 * \retval C2_BAD_STATE the fence(s) have already been signaled or merged (caller error) 183 * \retval C2_DUPLICATE the fence(s) have already been abandoned (caller error) 184 * \retval C2_REFUSED no permission to abandon the fence (unexpected - system) 185 * \retval C2_CORRUPTED some unknown error prevented signaling the fence(s) (unexpected) 186 */ 187 c2_status_t abandon(); 188 189 private: 190 class Impl; 191 std::shared_ptr<Impl> mImpl; 192 }; 193 194 /// \addtogroup buf_internal Internal 195 /// @{ 196 197 /** 198 * Interface for objects that encapsulate an updatable status value. 199 */ 200 struct _C2InnateStatus { status_C2InnateStatus201 inline c2_status_t status() const { return mStatus; } 202 203 protected: _C2InnateStatus_C2InnateStatus204 _C2InnateStatus(c2_status_t status) : mStatus(status) { } 205 206 c2_status_t mStatus; // this status is updatable by the object 207 }; 208 209 /// @} 210 211 /** 212 * This is a utility template for objects protected by an acquire fence, so that errors during 213 * acquiring the object are propagated to the object itself. 214 */ 215 template<typename T> 216 class C2Acquirable : public C2Fence { 217 public: 218 /** 219 * Acquires the object protected by an acquire fence. Any errors during the mapping will be 220 * passed to the object. 221 * 222 * \return acquired object potentially invalidated if waiting for the fence failed. 223 */ get()224 T get() { 225 // TODO: 226 // wait(); 227 return mT; 228 } 229 230 protected: C2Acquirable(c2_status_t error,C2Fence fence,T t)231 C2Acquirable(c2_status_t error, C2Fence fence, T t) : C2Fence(fence), mInitialError(error), mT(t) { } 232 233 private: 234 c2_status_t mInitialError; 235 T mT; // TODO: move instead of copy 236 }; 237 238 /// @} 239 240 /// \defgroup linear Linear Data Blocks 241 /// @{ 242 243 /************************************************************************************************** 244 LINEAR ASPECTS, BLOCKS AND VIEWS 245 **************************************************************************************************/ 246 247 /** 248 * Basic segment math support. 249 */ 250 struct C2Segment { 251 uint32_t offset; 252 uint32_t size; 253 C2SegmentC2Segment254 inline constexpr C2Segment(uint32_t offset_, uint32_t size_) 255 : offset(offset_), 256 size(size_) { 257 } 258 isEmptyC2Segment259 inline constexpr bool isEmpty() const { 260 return size == 0; 261 } 262 isValidC2Segment263 inline constexpr bool isValid() const { 264 return offset <= ~size; 265 } 266 267 inline constexpr operator bool() const { 268 return isValid() && !isEmpty(); 269 } 270 271 inline constexpr bool operator!() const { 272 return !bool(*this); 273 } 274 275 C2_ALLOW_OVERFLOW containsC2Segment276 inline constexpr bool contains(const C2Segment &other) const { 277 if (!isValid() || !other.isValid()) { 278 return false; 279 } else { 280 return offset <= other.offset 281 && offset + size >= other.offset + other.size; 282 } 283 } 284 285 inline constexpr bool operator==(const C2Segment &other) const { 286 if (!isValid()) { 287 return !other.isValid(); 288 } else { 289 return offset == other.offset && size == other.size; 290 } 291 } 292 293 inline constexpr bool operator!=(const C2Segment &other) const { 294 return !operator==(other); 295 } 296 297 inline constexpr bool operator>=(const C2Segment &other) const { 298 return contains(other); 299 } 300 301 inline constexpr bool operator>(const C2Segment &other) const { 302 return contains(other) && !operator==(other); 303 } 304 305 inline constexpr bool operator<=(const C2Segment &other) const { 306 return other.contains(*this); 307 } 308 309 inline constexpr bool operator<(const C2Segment &other) const { 310 return other.contains(*this) && !operator==(other); 311 } 312 313 C2_ALLOW_OVERFLOW endC2Segment314 inline constexpr uint32_t end() const { 315 return offset + size; 316 } 317 318 C2_ALLOW_OVERFLOW intersectC2Segment319 inline constexpr C2Segment intersect(const C2Segment &other) const { 320 return C2Segment(c2_max(offset, other.offset), 321 c2_min(end(), other.end()) - c2_max(offset, other.offset)); 322 } 323 324 /** clamps end to offset if it overflows */ normalizeC2Segment325 inline constexpr C2Segment normalize() const { 326 return C2Segment(offset, c2_max(offset, end()) - offset); 327 } 328 329 /** clamps end to max if it overflows */ saturateC2Segment330 inline constexpr C2Segment saturate() const { 331 return C2Segment(offset, c2_min(size, ~offset)); 332 } 333 334 }; 335 336 /** 337 * Common aspect for all objects that have a linear capacity. 338 */ 339 class _C2LinearCapacityAspect { 340 /// \name Linear capacity interface 341 /// @{ 342 public: capacity()343 inline constexpr uint32_t capacity() const { return mCapacity; } 344 C2Segment()345 inline constexpr operator C2Segment() const { 346 return C2Segment(0, mCapacity); 347 } 348 349 protected: 350 351 #if UINTPTR_MAX == 0xffffffff 352 static_assert(sizeof(size_t) == sizeof(uint32_t), "size_t is too big"); 353 #else 354 static_assert(sizeof(size_t) > sizeof(uint32_t), "size_t is too small"); 355 // explicitly disable construction from size_t 356 inline explicit _C2LinearCapacityAspect(size_t capacity) = delete; 357 #endif 358 _C2LinearCapacityAspect(uint32_t capacity)359 inline explicit constexpr _C2LinearCapacityAspect(uint32_t capacity) 360 : mCapacity(capacity) { } 361 _C2LinearCapacityAspect(const _C2LinearCapacityAspect * parent)362 inline explicit constexpr _C2LinearCapacityAspect(const _C2LinearCapacityAspect *parent) 363 : mCapacity(parent == nullptr ? 0 : parent->capacity()) { } 364 365 private: 366 uint32_t mCapacity; 367 /// @} 368 }; 369 370 /** 371 * Aspect for objects that have a linear range inside a linear capacity. 372 * 373 * This class is copiable. 374 */ 375 class _C2LinearRangeAspect : public _C2LinearCapacityAspect { 376 /// \name Linear range interface 377 /// @{ 378 public: offset()379 inline constexpr uint32_t offset() const { return mOffset; } endOffset()380 inline constexpr uint32_t endOffset() const { return mOffset + mSize; } size()381 inline constexpr uint32_t size() const { return mSize; } 382 C2Segment()383 inline constexpr operator C2Segment() const { 384 return C2Segment(mOffset, mSize); 385 } 386 387 private: 388 // subrange of capacity [0, capacity] & [size, size + offset] _C2LinearRangeAspect(uint32_t capacity_,size_t offset,size_t size)389 inline constexpr _C2LinearRangeAspect(uint32_t capacity_, size_t offset, size_t size) 390 : _C2LinearCapacityAspect(capacity_), 391 mOffset(c2_min(offset, capacity())), 392 mSize(c2_min(size, capacity() - mOffset)) { 393 } 394 395 protected: 396 // copy constructor (no error check) _C2LinearRangeAspect(const _C2LinearRangeAspect & other)397 inline constexpr _C2LinearRangeAspect(const _C2LinearRangeAspect &other) 398 : _C2LinearCapacityAspect(other.capacity()), 399 mOffset(other.offset()), 400 mSize(other.size()) { 401 } 402 403 // parent capacity range [0, capacity] _C2LinearRangeAspect(const _C2LinearCapacityAspect * parent)404 inline constexpr explicit _C2LinearRangeAspect(const _C2LinearCapacityAspect *parent) 405 : _C2LinearCapacityAspect(parent), 406 mOffset(0), 407 mSize(capacity()) { 408 } 409 410 // subrange of parent capacity [0, capacity] & [size, size + offset] _C2LinearRangeAspect(const _C2LinearCapacityAspect * parent,size_t offset,size_t size)411 inline constexpr _C2LinearRangeAspect(const _C2LinearCapacityAspect *parent, size_t offset, size_t size) 412 : _C2LinearCapacityAspect(parent), 413 mOffset(c2_min(offset, capacity())), 414 mSize(c2_min(size, capacity() - mOffset)) { 415 } 416 417 // subsection of the parent's and [offset, offset + size] ranges _C2LinearRangeAspect(const _C2LinearRangeAspect * parent,size_t offset,size_t size)418 inline constexpr _C2LinearRangeAspect(const _C2LinearRangeAspect *parent, size_t offset, size_t size) 419 : _C2LinearCapacityAspect(parent), 420 mOffset(c2_min(c2_max(offset, parent == nullptr ? 0 : parent->offset()), capacity())), 421 mSize(std::min(c2_min(size, parent == nullptr ? 0 : parent->size()), capacity() - mOffset)) { 422 } 423 424 public: childRange(size_t offset,size_t size)425 inline constexpr _C2LinearRangeAspect childRange(size_t offset, size_t size) const { 426 return _C2LinearRangeAspect( 427 mSize, 428 c2_min(c2_max(offset, mOffset), capacity()) - mOffset, 429 c2_min(c2_min(size, mSize), capacity() - c2_min(c2_max(offset, mOffset), capacity()))); 430 } 431 432 friend class _C2EditableLinearRangeAspect; 433 // invariants 0 <= mOffset <= mOffset + mSize <= capacity() 434 uint32_t mOffset; 435 uint32_t mSize; 436 /// @} 437 }; 438 439 /** 440 * Utility class for safe range calculations using size_t-s. 441 */ 442 class C2LinearRange : public _C2LinearRangeAspect { 443 public: C2LinearRange(const _C2LinearCapacityAspect & parent,size_t offset,size_t size)444 inline constexpr C2LinearRange(const _C2LinearCapacityAspect &parent, size_t offset, size_t size) 445 : _C2LinearRangeAspect(&parent, offset, size) { } 446 C2LinearRange(const _C2LinearRangeAspect & parent,size_t offset,size_t size)447 inline constexpr C2LinearRange(const _C2LinearRangeAspect &parent, size_t offset, size_t size) 448 : _C2LinearRangeAspect(&parent, offset, size) { } 449 intersect(size_t offset,size_t size)450 inline constexpr C2LinearRange intersect(size_t offset, size_t size) const { 451 return C2LinearRange(*this, offset, size); 452 } 453 }; 454 455 /** 456 * Utility class for simple and safe capacity and range construction. 457 */ 458 class C2LinearCapacity : public _C2LinearCapacityAspect { 459 public: C2LinearCapacity(size_t capacity)460 inline constexpr explicit C2LinearCapacity(size_t capacity) 461 : _C2LinearCapacityAspect(c2_min(capacity, std::numeric_limits<uint32_t>::max())) { } 462 range(size_t offset,size_t size)463 inline constexpr C2LinearRange range(size_t offset, size_t size) const { 464 return C2LinearRange(*this, offset, size); 465 } 466 }; 467 468 /** 469 * Aspect for objects that have an editable linear range. 470 * 471 * This class is copiable. 472 */ 473 class _C2EditableLinearRangeAspect : public _C2LinearRangeAspect { 474 using _C2LinearRangeAspect::_C2LinearRangeAspect; 475 476 public: 477 /// \name Editable linear range interface 478 /// @{ 479 480 /** 481 * Sets the offset to |offset|, while trying to keep the end of the buffer unchanged (e.g. 482 * size will grow if offset is decreased, and may shrink if offset is increased.) Returns 483 * true if successful, which is equivalent to if 0 <= |offset| <= capacity(). 484 * 485 * Note: setting offset and size will yield different result depending on the order of the 486 * operations. Always set offset first to ensure proper size. 487 */ setOffset(uint32_t offset)488 inline bool setOffset(uint32_t offset) { 489 if (offset > capacity()) { 490 return false; 491 } 492 493 if (offset > mOffset + mSize) { 494 mSize = 0; 495 } else { 496 mSize = mOffset + mSize - offset; 497 } 498 mOffset = offset; 499 return true; 500 } 501 502 /** 503 * Sets the size to |size|. Returns true if successful, which is equivalent to 504 * if 0 <= |size| <= capacity() - offset(). 505 * 506 * Note: setting offset and size will yield different result depending on the order of the 507 * operations. Always set offset first to ensure proper size. 508 */ setSize(uint32_t size)509 inline bool setSize(uint32_t size) { 510 if (size > capacity() - mOffset) { 511 return false; 512 } else { 513 mSize = size; 514 return true; 515 } 516 } 517 518 /** 519 * Sets the offset to |offset| with best effort. Same as setOffset() except that offset will 520 * be clamped to the buffer capacity. 521 * 522 * Note: setting offset and size (even using best effort) will yield different result depending 523 * on the order of the operations. Always set offset first to ensure proper size. 524 */ setOffset_be(uint32_t offset)525 inline void setOffset_be(uint32_t offset) { 526 (void)setOffset(c2_min(offset, capacity())); 527 } 528 529 /** 530 * Sets the size to |size| with best effort. Same as setSize() except that the selected region 531 * will be clamped to the buffer capacity (e.g. size is clamped to [0, capacity() - offset()]). 532 * 533 * Note: setting offset and size (even using best effort) will yield different result depending 534 * on the order of the operations. Always set offset first to ensure proper size. 535 */ setSize_be(uint32_t size)536 inline void setSize_be(uint32_t size) { 537 mSize = c2_min(size, capacity() - mOffset); 538 } 539 /// @} 540 }; 541 542 /************************************************************************************************** 543 ALLOCATIONS 544 **************************************************************************************************/ 545 546 /// \ingroup allocator Allocation and memory placement 547 /// @{ 548 549 class C2LinearAllocation; 550 class C2GraphicAllocation; 551 552 /** 553 * Allocators are used by the framework to allocate memory (allocations) for buffers. They can 554 * support either 1D or 2D allocations. 555 * 556 * \note In theory they could support both, but in practice, we will use only one or the other. 557 * 558 * Never constructed on stack. 559 * 560 * Allocators are provided by vendors. 561 */ 562 class C2Allocator { 563 public: 564 /** 565 * Allocator ID type. 566 */ 567 typedef uint32_t id_t; 568 enum : id_t { 569 BAD_ID = 0xBADD, // invalid allocator ID 570 }; 571 572 /** 573 * Allocation types. This is a bitmask and is used in C2Allocator::Info 574 * to list the supported allocation types of an allocator. 575 */ 576 enum type_t : uint32_t { 577 LINEAR = 1 << 0, // 578 GRAPHIC = 1 << 1, 579 }; 580 581 /** 582 * Information about an allocator. 583 * 584 * Allocators don't have a query API so all queriable information is stored here. 585 */ 586 struct Traits { 587 C2String name; ///< allocator name 588 id_t id; ///< allocator ID 589 type_t supportedTypes; ///< supported allocation types 590 C2MemoryUsage minimumUsage; ///< usage that is minimally required for allocations 591 C2MemoryUsage maximumUsage; ///< usage that is maximally allowed for allocations 592 }; 593 594 /** 595 * Returns the unique name of this allocator. 596 * 597 * This method MUST be "non-blocking" and return within 1ms. 598 * 599 * \return the name of this allocator. 600 * \retval an empty string if there was not enough memory to allocate the actual name. 601 */ 602 virtual C2String getName() const = 0; 603 604 /** 605 * Returns a unique ID for this allocator. This ID is used to get this allocator from the 606 * allocator store, and to identify this allocator across all processes. 607 * 608 * This method MUST be "non-blocking" and return within 1ms. 609 * 610 * \return a unique ID for this allocator. 611 */ 612 virtual id_t getId() const = 0; 613 614 /** 615 * Returns the allocator traits. 616 * 617 * This method MUST be "non-blocking" and return within 1ms. 618 * 619 * Allocators don't have a full-fledged query API, only this method. 620 * 621 * \return allocator information 622 */ 623 virtual std::shared_ptr<const Traits> getTraits() const = 0; 624 625 /** 626 * Allocates a 1D allocation of given |capacity| and |usage|. If successful, the allocation is 627 * stored in |allocation|. Otherwise, |allocation| is set to 'nullptr'. 628 * 629 * \param capacity the size of requested allocation (the allocation could be slightly 630 * larger, e.g. to account for any system-required alignment) 631 * \param usage the memory usage info for the requested allocation. \note that the 632 * returned allocation may be later used/mapped with different usage. 633 * The allocator should layout the buffer to be optimized for this usage, 634 * but must support any usage. One exception: protected buffers can 635 * only be used in a protected scenario. 636 * \param allocation pointer to where the allocation shall be stored on success. nullptr 637 * will be stored here on failure 638 * 639 * \retval C2_OK the allocation was successful 640 * \retval C2_NO_MEMORY not enough memory to complete the allocation 641 * \retval C2_TIMED_OUT the allocation timed out 642 * \retval C2_REFUSED no permission to complete the allocation 643 * \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error) 644 * \retval C2_OMITTED this allocator does not support 1D allocations 645 * \retval C2_CORRUPTED some unknown, unrecoverable error occurred during allocation 646 * (unexpected) 647 */ newLinearAllocation(uint32_t capacity __unused,C2MemoryUsage usage __unused,std::shared_ptr<C2LinearAllocation> * allocation)648 virtual c2_status_t newLinearAllocation( 649 uint32_t capacity __unused, C2MemoryUsage usage __unused, 650 std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) { 651 *allocation = nullptr; 652 return C2_OMITTED; 653 } 654 655 /** 656 * (Re)creates a 1D allocation from a native |handle|. If successful, the allocation is stored 657 * in |allocation|. Otherwise, |allocation| is set to 'nullptr'. 658 * 659 * \param handle the handle for the existing allocation. On success, the allocation will 660 * take ownership of |handle|. 661 * \param allocation pointer to where the allocation shall be stored on success. nullptr 662 * will be stored here on failure 663 * 664 * \retval C2_OK the allocation was recreated successfully 665 * \retval C2_NO_MEMORY not enough memory to recreate the allocation 666 * \retval C2_TIMED_OUT the recreation timed out (unexpected) 667 * \retval C2_REFUSED no permission to recreate the allocation 668 * \retval C2_BAD_VALUE invalid handle (caller error) 669 * \retval C2_OMITTED this allocator does not support 1D allocations 670 * \retval C2_CORRUPTED some unknown, unrecoverable error occurred during allocation 671 * (unexpected) 672 */ priorLinearAllocation(const C2Handle * handle __unused,std::shared_ptr<C2LinearAllocation> * allocation)673 virtual c2_status_t priorLinearAllocation( 674 const C2Handle *handle __unused, 675 std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) { 676 *allocation = nullptr; 677 return C2_OMITTED; 678 } 679 680 /** 681 * Allocates a 2D allocation of given |width|, |height|, |format| and |usage|. If successful, 682 * the allocation is stored in |allocation|. Otherwise, |allocation| is set to 'nullptr'. 683 * 684 * \param width the width of requested allocation (the allocation could be slightly 685 * larger, e.g. to account for any system-required alignment) 686 * \param height the height of requested allocation (the allocation could be slightly 687 * larger, e.g. to account for any system-required alignment) 688 * \param format the pixel format of requested allocation. This could be a vendor 689 * specific format. 690 * \param usage the memory usage info for the requested allocation. \note that the 691 * returned allocation may be later used/mapped with different usage. 692 * The allocator should layout the buffer to be optimized for this usage, 693 * but must support any usage. One exception: protected buffers can 694 * only be used in a protected scenario. 695 * \param allocation pointer to where the allocation shall be stored on success. nullptr 696 * will be stored here on failure 697 * 698 * \retval C2_OK the allocation was successful 699 * \retval C2_NO_MEMORY not enough memory to complete the allocation 700 * \retval C2_TIMED_OUT the allocation timed out 701 * \retval C2_REFUSED no permission to complete the allocation 702 * \retval C2_BAD_VALUE width, height, format or usage are not supported (invalid) (caller error) 703 * \retval C2_OMITTED this allocator does not support 2D allocations 704 * \retval C2_CORRUPTED some unknown, unrecoverable error occurred during allocation 705 * (unexpected) 706 */ newGraphicAllocation(uint32_t width __unused,uint32_t height __unused,uint32_t format __unused,C2MemoryUsage usage __unused,std::shared_ptr<C2GraphicAllocation> * allocation)707 virtual c2_status_t newGraphicAllocation( 708 uint32_t width __unused, uint32_t height __unused, uint32_t format __unused, 709 C2MemoryUsage usage __unused, 710 std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) { 711 *allocation = nullptr; 712 return C2_OMITTED; 713 } 714 715 /** 716 * (Re)creates a 2D allocation from a native handle. If successful, the allocation is stored 717 * in |allocation|. Otherwise, |allocation| is set to 'nullptr'. 718 * 719 * \param handle the handle for the existing allocation. On success, the allocation will 720 * take ownership of |handle|. 721 * \param allocation pointer to where the allocation shall be stored on success. nullptr 722 * will be stored here on failure 723 * 724 * \retval C2_OK the allocation was recreated successfully 725 * \retval C2_NO_MEMORY not enough memory to recreate the allocation 726 * \retval C2_TIMED_OUT the recreation timed out (unexpected) 727 * \retval C2_REFUSED no permission to recreate the allocation 728 * \retval C2_BAD_VALUE invalid handle (caller error) 729 * \retval C2_OMITTED this allocator does not support 2D allocations 730 * \retval C2_CORRUPTED some unknown, unrecoverable error occurred during recreation 731 * (unexpected) 732 */ priorGraphicAllocation(const C2Handle * handle __unused,std::shared_ptr<C2GraphicAllocation> * allocation)733 virtual c2_status_t priorGraphicAllocation( 734 const C2Handle *handle __unused, 735 std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) { 736 *allocation = nullptr; 737 return C2_OMITTED; 738 } 739 740 virtual ~C2Allocator() = default; 741 742 /** 743 * Returns a true if the handle looks valid for this allocator. 744 * 745 * It does not actually validate that the handle represents a valid allocation (by this 746 * allocator), only that the handle could have been returned by this allocator. As such, 747 * multiple allocators may return true for looksValid for the same handle. 748 * 749 * This method MUST be "non-blocking", MUST not access kernel and/or device drivers, and 750 * return within 1us. 751 * 752 * \param handle the handle for an existing allocation (possibly from another 753 * allocator) 754 */ 755 virtual bool checkHandle(const C2Handle *const handle) const = 0; 756 757 protected: 758 C2Allocator() = default; 759 }; 760 761 /** 762 * \ingroup linear allocator 763 * 1D allocation interface. 764 */ 765 class C2LinearAllocation : public _C2LinearCapacityAspect { 766 public: 767 /** 768 * Maps a portion of an allocation starting from |offset| with |size| into local process memory. 769 * Stores the starting address into |addr|, or NULL if the operation was unsuccessful. 770 * |fence| will contain an acquire sync fence object. If it is already 771 * safe to access the buffer contents, then it will contain an empty (already fired) fence. 772 * 773 * \param offset starting position of the portion to be mapped (this does not have to 774 * be page aligned) 775 * \param size size of the portion to be mapped (this does not have to be page 776 * aligned) 777 * \param usage the desired usage. \todo this must be kSoftwareRead and/or 778 * kSoftwareWrite. 779 * \param fence a pointer to a fence object if an async mapping is requested. If 780 * not-null, and acquire fence will be stored here on success, or empty 781 * fence on failure. If null, the mapping will be synchronous. 782 * \param addr a pointer to where the starting address of the mapped portion will be 783 * stored. On failure, nullptr will be stored here. 784 * 785 * \todo Only one portion can be mapped at the same time - this is true for gralloc, but there 786 * is no need for this for 1D buffers. 787 * \todo Do we need to support sync operation as we could just wait for the fence? 788 * 789 * \retval C2_OK the operation was successful 790 * \retval C2_REFUSED no permission to map the portion 791 * \retval C2_TIMED_OUT the operation timed out 792 * \retval C2_DUPLICATE if the allocation is already mapped. 793 * \retval C2_NO_MEMORY not enough memory to complete the operation 794 * \retval C2_BAD_VALUE the parameters (offset/size) are invalid or outside the allocation, or 795 * the usage flags are invalid (caller error) 796 * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected) 797 */ 798 virtual c2_status_t map( 799 size_t offset, size_t size, C2MemoryUsage usage, C2Fence *fence /* nullable */, 800 void **addr /* nonnull */) = 0; 801 802 /** 803 * Unmaps a portion of an allocation at |addr| with |size|. These must be parameters previously 804 * passed to and returned by |map|; otherwise, this operation is a no-op. 805 * 806 * \param addr starting address of the mapped region 807 * \param size size of the mapped region 808 * \param fence a pointer to a fence object if an async unmapping is requested. If 809 * not-null, a release fence will be stored here on success, or empty fence 810 * on failure. This fence signals when the original allocation contains 811 * all changes that happened to the mapped region. If null, the unmapping 812 * will be synchronous. 813 * 814 * \retval C2_OK the operation was successful 815 * \retval C2_TIMED_OUT the operation timed out 816 * \retval C2_NOT_FOUND if the allocation was not mapped previously. 817 * \retval C2_BAD_VALUE the parameters (addr/size) do not correspond to previously mapped 818 * regions (caller error) 819 * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected) 820 * \retval C2_REFUSED no permission to unmap the portion (unexpected - system) 821 */ 822 virtual c2_status_t unmap(void *addr, size_t size, C2Fence *fence /* nullable */) = 0; 823 824 /** 825 * Returns the allocator ID for this allocation. This is useful to put the handle into context. 826 */ 827 virtual C2Allocator::id_t getAllocatorId() const = 0; 828 829 /** 830 * Returns a pointer to the allocation handle. 831 */ 832 virtual const C2Handle *handle() const = 0; 833 834 /** 835 * Returns true if this is the same allocation as |other|. 836 */ 837 virtual bool equals(const std::shared_ptr<C2LinearAllocation> &other) const = 0; 838 839 protected: 840 // \todo should we limit allocation directly? C2LinearAllocation(size_t capacity)841 C2LinearAllocation(size_t capacity) : _C2LinearCapacityAspect(c2_min(capacity, UINT32_MAX)) {} 842 virtual ~C2LinearAllocation() = default; 843 }; 844 845 class C2CircularBlock; 846 class C2LinearBlock; 847 class C2GraphicBlock; 848 849 /** 850 * Block pools are used by components to obtain output buffers in an efficient way. They can 851 * support either linear (1D), circular (1D) or graphic (2D) blocks. 852 * 853 * Block pools decouple the recycling of memory/allocations from the components. They are meant to 854 * be an opaque service (there are no public APIs other than obtaining blocks) provided by the 855 * platform. Block pools are also meant to decouple allocations from memory used by buffers. This 856 * is accomplished by allowing pools to allot multiple memory 'blocks' on a single allocation. As 857 * their name suggest, block pools maintain a pool of memory blocks. When a component asks for 858 * a memory block, pools will try to return a free memory block already in the pool. If no such 859 * block exists, they will allocate memory using the backing allocator and allot a block on that 860 * allocation. When blocks are no longer used in the system, they are recycled back to the block 861 * pool and are available as free blocks. 862 * 863 * Never constructed on stack. 864 */ 865 class C2BlockPool { 866 public: 867 /** 868 * Block pool ID type. 869 */ 870 typedef uint64_t local_id_t; 871 872 enum : local_id_t { 873 BASIC_LINEAR = 0, ///< ID of basic (unoptimized) block pool for fetching 1D blocks 874 BASIC_GRAPHIC = 1, ///< ID of basic (unoptimized) block pool for fetching 2D blocks 875 PLATFORM_START = 0x10, 876 }; 877 878 /** 879 * Returns the ID for this block pool. This ID is used to get this block pool from the platform. 880 * It is only valid in the current process. 881 * 882 * This method MUST be "non-blocking" and return within 1ms. 883 * 884 * \return a local ID for this block pool. 885 */ 886 virtual local_id_t getLocalId() const = 0; 887 888 /** 889 * Returns the ID of the backing allocator of this block pool. 890 * 891 * This method MUST be "non-blocking" and return within 1ms. 892 * 893 * \return the ID of the backing allocator of this block pool. 894 */ 895 virtual C2Allocator::id_t getAllocatorId() const = 0; 896 897 /** 898 * Obtains a linear writeable block of given |capacity| and |usage|. If successful, the 899 * block is stored in |block|. Otherwise, |block| is set to 'nullptr'. 900 * 901 * \note The returned buffer may have a larger capacity than requested. In this case the 902 * larger (returned) capacity may be fully used. 903 * 904 * \note There is no guarantee on the alignedness of the returned block. The only guarantee is 905 * that its capacity is equal to or larger than the requested capacity. 906 * 907 * \param capacity the size of requested block. 908 * \param usage the memory usage info for the requested block. Returned blocks will be 909 * optimized for this usage, but may be used with any usage. One exception: 910 * protected blocks/buffers can only be used in a protected scenario. 911 * \param block pointer to where the obtained block shall be stored on success. nullptr will 912 * be stored here on failure 913 * 914 * \retval C2_OK the operation was successful 915 * \retval C2_NO_MEMORY not enough memory to complete any required allocation 916 * \retval C2_TIMED_OUT the operation timed out 917 * \retval C2_BLOCKING the operation is blocked 918 * \retval C2_REFUSED no permission to complete any required allocation 919 * \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error) 920 * \retval C2_OMITTED this pool does not support linear blocks 921 * \retval C2_CORRUPTED some unknown, unrecoverable error occurred during operation 922 * (unexpected) 923 */ fetchLinearBlock(uint32_t capacity __unused,C2MemoryUsage usage __unused,std::shared_ptr<C2LinearBlock> * block)924 virtual c2_status_t fetchLinearBlock( 925 uint32_t capacity __unused, C2MemoryUsage usage __unused, 926 std::shared_ptr<C2LinearBlock> *block /* nonnull */) { 927 *block = nullptr; 928 return C2_OMITTED; 929 } 930 931 /** 932 * Obtains a circular writeable block of given |capacity| and |usage|. If successful, the 933 * block is stored in |block|. Otherwise, |block| is set to 'nullptr'. 934 * 935 * \note The returned buffer may have a larger capacity than requested. In this case the 936 * larger (returned) capacity may be fully used. 937 * 938 * \note There is no guarantee on the alignedness of the returned block. The only guarantee is 939 * that its capacity is equal to or larger than the requested capacity. 940 * 941 * \param capacity the size of requested circular block. (note: the size of the obtained 942 * block could be slightly larger, e.g. to accommodate any system-required 943 * alignment) 944 * \param usage the memory usage info for the requested block. Returned blocks will be 945 * optimized for this usage, but may be used with any usage. One exception: 946 * protected blocks/buffers can only be used in a protected scenario. 947 * \param block pointer to where the obtained block shall be stored on success. nullptr 948 * will be stored here on failure 949 * 950 * \retval C2_OK the operation was successful 951 * \retval C2_NO_MEMORY not enough memory to complete any required allocation 952 * \retval C2_TIMED_OUT the operation timed out 953 * \retval C2_BLOCKING the operation is blocked 954 * \retval C2_REFUSED no permission to complete any required allocation 955 * \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error) 956 * \retval C2_OMITTED this pool does not support circular blocks 957 * \retval C2_CORRUPTED some unknown, unrecoverable error occurred during operation 958 * (unexpected) 959 */ fetchCircularBlock(uint32_t capacity __unused,C2MemoryUsage usage __unused,std::shared_ptr<C2CircularBlock> * block)960 virtual c2_status_t fetchCircularBlock( 961 uint32_t capacity __unused, C2MemoryUsage usage __unused, 962 std::shared_ptr<C2CircularBlock> *block /* nonnull */) { 963 *block = nullptr; 964 return C2_OMITTED; 965 } 966 967 /** 968 * Obtains a 2D graphic block of given |width|, |height|, |format| and |usage|. If successful, 969 * the block is stored in |block|. Otherwise, |block| is set to 'nullptr'. 970 * 971 * \note The returned buffer may have a larger capacity (width and height) than requested. In 972 * this case the larger (returned) capacity may be fully used. 973 * 974 * \note There is no guarantee on the alignedness of the returned block. The only guarantee is 975 * that its capacity is equal to or larger than the requested capacity (width and height). 976 * 977 * \param width the width of requested block (the obtained block could be slightly larger, e.g. 978 * to accommodate any system-required alignment) 979 * \param height the height of requested block (the obtained block could be slightly larger, 980 * e.g. to accommodate any system-required alignment) 981 * \param format the pixel format of requested block. This could be a vendor specific format. 982 * \param usage the memory usage info for the requested block. Returned blocks will be 983 * optimized for this usage, but may be used with any usage. One exception: 984 * protected blocks/buffers can only be used in a protected scenario. 985 * \param block pointer to where the obtained block shall be stored on success. nullptr 986 * will be stored here on failure 987 * 988 * \retval C2_OK the operation was successful 989 * \retval C2_NO_MEMORY not enough memory to complete any required allocation 990 * \retval C2_TIMED_OUT the operation timed out 991 * \retval C2_BLOCKING the operation is blocked 992 * \retval C2_REFUSED no permission to complete any required allocation 993 * \retval C2_BAD_VALUE width, height, format or usage are not supported (invalid) (caller 994 * error) 995 * \retval C2_OMITTED this pool does not support 2D blocks 996 * \retval C2_CORRUPTED some unknown, unrecoverable error occurred during operation 997 * (unexpected) 998 */ fetchGraphicBlock(uint32_t width __unused,uint32_t height __unused,uint32_t format __unused,C2MemoryUsage usage __unused,std::shared_ptr<C2GraphicBlock> * block)999 virtual c2_status_t fetchGraphicBlock( 1000 uint32_t width __unused, uint32_t height __unused, uint32_t format __unused, 1001 C2MemoryUsage usage __unused, 1002 std::shared_ptr<C2GraphicBlock> *block /* nonnull */) { 1003 *block = nullptr; 1004 return C2_OMITTED; 1005 } 1006 1007 virtual ~C2BlockPool() = default; 1008 1009 /** 1010 * Blocking fetch for linear block. Obtains a linear writable block of given |capacity| 1011 * and |usage|. If a block can be successfully obtained, the block is stored in |block|, 1012 * |fence| is set to a null-fence and C2_OK is returned. 1013 * 1014 * If a block cannot be temporarily obtained, |block| is set to nullptr, a waitable fence 1015 * is stored into |fence| and C2_BLOCKING is returned. 1016 * 1017 * Otherwise, |block| is set to nullptr and |fence| is set to a null-fence. The waitable 1018 * fence is signalled when the temporary restriction on fetch is lifted. 1019 * e.g. more memory is available to fetch because some meomory or prior blocks were released. 1020 * 1021 * \note The returned buffer may have a larger capacity than requested. In this case the 1022 * larger (returned) capacity may be fully used. 1023 * 1024 * \note There is no guarantee on the alignedness of the returned block. The only guarantee is 1025 * that its capacity is equal to or larger than the requested capacity. 1026 * 1027 * \param capacity the size of requested block. 1028 * \param usage the memory usage info for the requested block. Returned blocks will be 1029 * optimized for this usage, but may be used with any usage. One exception: 1030 * protected blocks/buffers can only be used in a protected scenario. 1031 * \param block pointer to where the obtained block shall be stored on success. nullptr will 1032 * be stored here on failure 1033 * \param fence pointer to where the fence shall be stored on C2_BLOCKING error. 1034 * 1035 * \retval C2_OK the operation was successful 1036 * \retval C2_NO_MEMORY not enough memory to complete any required allocation 1037 * \retval C2_TIMED_OUT the operation timed out 1038 * \retval C2_BLOCKING the operation is blocked 1039 * \retval C2_REFUSED no permission to complete any required allocation 1040 * \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error) 1041 * \retval C2_OMITTED this pool does not support linear blocks nor fence. 1042 * \retval C2_CORRUPTED some unknown, unrecoverable error occurred during operation 1043 * (unexpected) 1044 */ fetchLinearBlock(uint32_t capacity __unused,C2MemoryUsage usage __unused,std::shared_ptr<C2LinearBlock> * block,C2Fence * fence)1045 virtual c2_status_t fetchLinearBlock( 1046 uint32_t capacity __unused, C2MemoryUsage usage __unused, 1047 std::shared_ptr<C2LinearBlock> *block /* nonnull */, 1048 C2Fence *fence /* nonnull */) { 1049 *block = nullptr; 1050 (void) fence; 1051 return C2_OMITTED; 1052 } 1053 1054 /** 1055 * Blocking fetch for 2D graphic block. Obtains a 2D graphic writable block of given |capacity| 1056 * and |usage|. If a block can be successfully obtained, the block is stored in |block|, 1057 * |fence| is set to a null-fence and C2_OK is returned. 1058 * 1059 * If a block cannot be temporarily obtained, |block| is set to nullptr, a waitable fence 1060 * is stored into |fence| and C2_BLOCKING is returned. 1061 * 1062 * Otherwise, |block| is set to nullptr and |fence| is set to a null-fence. The waitable 1063 * fence is signalled when the temporary restriction on fetch is lifted. 1064 * e.g. more memory is available to fetch because some meomory or prior blocks were released. 1065 * 1066 * \note The returned buffer may have a larger capacity (width and height) than requested. In 1067 * this case the larger (returned) capacity may be fully used. 1068 * 1069 * \note There is no guarantee on the alignedness of the returned block. The only guarantee is 1070 * that its capacity is equal to or larger than the requested capacity (width and height). 1071 * 1072 * \param width the width of requested block (the obtained block could be slightly larger, e.g. 1073 * to accommodate any system-required alignment) 1074 * \param height the height of requested block (the obtained block could be slightly larger, 1075 * e.g. to accommodate any system-required alignment) 1076 * \param format the pixel format of requested block. This could be a vendor specific format. 1077 * \param usage the memory usage info for the requested block. Returned blocks will be 1078 * optimized for this usage, but may be used with any usage. One exception: 1079 * protected blocks/buffers can only be used in a protected scenario. 1080 * \param block pointer to where the obtained block shall be stored on success. nullptr 1081 * will be stored here on failure 1082 * \param fence pointer to where the fence shall be stored on C2_BLOCKING error. 1083 * 1084 * \retval C2_OK the operation was successful 1085 * \retval C2_NO_MEMORY not enough memory to complete any required allocation 1086 * \retval C2_TIMED_OUT the operation timed out 1087 * \retval C2_BLOCKING the operation is blocked 1088 * \retval C2_REFUSED no permission to complete any required allocation 1089 * \retval C2_BAD_VALUE width, height, format or usage are not supported (invalid) (caller 1090 * error) 1091 * \retval C2_OMITTED this pool does not support 2D blocks 1092 * \retval C2_CORRUPTED some unknown, unrecoverable error occurred during operation 1093 * (unexpected) 1094 */ fetchGraphicBlock(uint32_t width __unused,uint32_t height __unused,uint32_t format __unused,C2MemoryUsage usage __unused,std::shared_ptr<C2GraphicBlock> * block,C2Fence * fence)1095 virtual c2_status_t fetchGraphicBlock( 1096 uint32_t width __unused, uint32_t height __unused, uint32_t format __unused, 1097 C2MemoryUsage usage __unused, 1098 std::shared_ptr<C2GraphicBlock> *block /* nonnull */, 1099 C2Fence *fence /* nonnull */) { 1100 *block = nullptr; 1101 (void) fence; 1102 return C2_OMITTED; 1103 } 1104 protected: 1105 C2BlockPool() = default; 1106 }; 1107 1108 /// @} 1109 1110 // ================================================================================================ 1111 // BLOCKS 1112 // ================================================================================================ 1113 1114 /** 1115 * Blocks are sections of allocations. They can be either 1D or 2D. 1116 */ 1117 1118 class C2LinearAllocation; 1119 1120 /** 1121 * A 1D block. 1122 * 1123 * \note capacity() is not meaningful for users of blocks; instead size() is the capacity of the 1124 * usable portion. Use and offset() and size() if accessing the block directly through its handle 1125 * to represent the allotted range of the underlying allocation to this block. 1126 */ 1127 class C2Block1D : public _C2LinearRangeAspect { 1128 public: 1129 /** 1130 * Returns the underlying handle for this allocation. 1131 * 1132 * \note that the block and its block pool has shared ownership of the handle 1133 * and if all references to the block are released, the underlying block 1134 * allocation may get reused even if a client keeps a clone of this handle. 1135 */ 1136 const C2Handle *handle() const; 1137 1138 /** 1139 * Returns the allocator's ID that created the underlying allocation for this block. This 1140 * provides the context for understanding the handle. 1141 */ 1142 C2Allocator::id_t getAllocatorId() const; 1143 1144 protected: 1145 class Impl; 1146 /** construct a block. */ 1147 C2Block1D(std::shared_ptr<Impl> impl, const _C2LinearRangeAspect &range); 1148 1149 friend struct _C2BlockFactory; 1150 std::shared_ptr<Impl> mImpl; 1151 }; 1152 1153 /** 1154 * Read view provides read-only access for a linear memory segment. 1155 * 1156 * This class is copiable. 1157 */ 1158 class C2ReadView : public _C2LinearCapacityAspect { 1159 public: 1160 /** 1161 * \return pointer to the start of the block or nullptr on error. 1162 * This pointer is only valid during the lifetime of this view or until it is released. 1163 */ 1164 const uint8_t *data() const; 1165 1166 /** 1167 * Returns a portion of this view. 1168 * 1169 * \param offset the start offset of the portion. \note This is clamped to the capacity of this 1170 * view. 1171 * \param size the size of the portion. \note This is clamped to the remaining data from offset. 1172 * 1173 * \return a read view containing a portion of this view 1174 */ 1175 C2ReadView subView(size_t offset, size_t size) const; 1176 1177 /** 1178 * \return error during the creation/mapping of this view. 1179 */ 1180 c2_status_t error() const; 1181 1182 /** 1183 * Releases this view. This sets error to C2_NO_INIT. 1184 */ 1185 //void release(); 1186 1187 protected: 1188 class Impl; 1189 C2ReadView(std::shared_ptr<Impl> impl, uint32_t offset, uint32_t size); 1190 explicit C2ReadView(c2_status_t error); 1191 1192 private: 1193 friend struct _C2BlockFactory; 1194 std::shared_ptr<Impl> mImpl; 1195 uint32_t mOffset; /**< offset into the linear block backing this read view */ 1196 }; 1197 1198 /** 1199 * Write view provides read/write access for a linear memory segment. 1200 * 1201 * This class is copiable. \todo movable only? 1202 */ 1203 class C2WriteView : public _C2EditableLinearRangeAspect { 1204 public: 1205 /** 1206 * Start of the block. 1207 * 1208 * \return pointer to the start of the block or nullptr on error. 1209 * This pointer is only valid during the lifetime of this view or until it is released. 1210 */ 1211 uint8_t *base(); 1212 1213 /** 1214 * \return pointer to the block at the current offset or nullptr on error. 1215 * This pointer is only valid during the lifetime of this view or until it is released. 1216 */ 1217 uint8_t *data(); 1218 1219 /** 1220 * \return error during the creation/mapping of this view. 1221 */ 1222 c2_status_t error() const; 1223 1224 /** 1225 * Releases this view. This sets error to C2_NO_INIT. 1226 */ 1227 //void release(); 1228 1229 protected: 1230 class Impl; 1231 C2WriteView(std::shared_ptr<Impl> impl); 1232 explicit C2WriteView(c2_status_t error); 1233 1234 private: 1235 friend struct _C2BlockFactory; 1236 std::shared_ptr<Impl> mImpl; 1237 }; 1238 1239 /** 1240 * A constant (read-only) linear block (portion of an allocation) with an acquire fence. 1241 * Blocks are unmapped when created, and can be mapped into a read view on demand. 1242 * 1243 * This class is copiable and contains a reference to the allocation that it is based on. 1244 */ 1245 class C2ConstLinearBlock : public C2Block1D { 1246 public: 1247 /** 1248 * Maps this block into memory and returns a read view for it. 1249 * 1250 * \return a read view for this block. 1251 */ 1252 C2Acquirable<C2ReadView> map() const; 1253 1254 /** 1255 * Returns a portion of this block. 1256 * 1257 * \param offset the start offset of the portion. \note This is clamped to the capacity of this 1258 * block. 1259 * \param size the size of the portion. \note This is clamped to the remaining data from offset. 1260 * 1261 * \return a constant linear block containing a portion of this block 1262 */ 1263 C2ConstLinearBlock subBlock(size_t offset, size_t size) const; 1264 1265 /** 1266 * Returns the acquire fence for this block. 1267 * 1268 * \return a fence that must be waited on before reading the block. 1269 */ fence()1270 C2Fence fence() const { return mFence; } 1271 1272 protected: 1273 C2ConstLinearBlock(std::shared_ptr<Impl> impl, const _C2LinearRangeAspect &range, C2Fence mFence); 1274 1275 private: 1276 friend struct _C2BlockFactory; 1277 C2Fence mFence; 1278 }; 1279 1280 /** 1281 * Linear block is a writeable 1D block. Once written, it can be shared in whole or in parts with 1282 * consumers/readers as read-only const linear block(s). 1283 */ 1284 class C2LinearBlock : public C2Block1D { 1285 public: 1286 /** 1287 * Maps this block into memory and returns a write view for it. 1288 * 1289 * \return a write view for this block. 1290 */ 1291 C2Acquirable<C2WriteView> map(); 1292 1293 /** 1294 * Creates a read-only const linear block for a portion of this block; optionally protected 1295 * by an acquire fence. There are two ways to use this: 1296 * 1297 * 1) share ready block after writing data into the block. In this case no fence shall be 1298 * supplied, and the block shall not be modified after calling this method. 1299 * 2) share block metadata before actually (finishing) writing the data into the block. In 1300 * this case a fence must be supplied that will be triggered when the data is written. 1301 * The block shall be modified only until firing the event for the fence. 1302 */ 1303 C2ConstLinearBlock share(size_t offset, size_t size, C2Fence fence); 1304 1305 protected: 1306 C2LinearBlock(std::shared_ptr<Impl> impl, const _C2LinearRangeAspect &range); 1307 1308 friend struct _C2BlockFactory; 1309 }; 1310 1311 /// @} 1312 1313 /************************************************************************************************** 1314 CIRCULAR BLOCKS AND VIEWS 1315 **************************************************************************************************/ 1316 1317 /// \defgroup circular Circular buffer support 1318 /// @{ 1319 1320 /** 1321 * Circular blocks can be used to share data between a writer and a reader (and/or other consumers)- 1322 * in a memory-efficient way by reusing a section of memory. Circular blocks are a bit more complex 1323 * than single reader/single writer schemes to facilitate block-based consuming of data. 1324 * 1325 * They can operate in two modes: 1326 * 1327 * 1) one writer that creates blocks to be consumed (this model can be used by components) 1328 * 1329 * 2) one writer that writes continuously, and one reader that can creates blocks to be consumed 1330 * by further recipients (this model is used by the framework, and cannot be used by components.) 1331 * 1332 * Circular blocks have four segments with running pointers: 1333 * - reserved: data reserved and available for the writer 1334 * - committed: data committed by the writer and available to the reader (if present) 1335 * - used: data used by consumers (if present) 1336 * - available: unused data available to be reserved 1337 */ 1338 class C2CircularBlock : public C2Block1D { 1339 // TODO: add methods 1340 1341 private: 1342 size_t mReserved __unused; // end of reserved section 1343 size_t mCommitted __unused; // end of committed section 1344 size_t mUsed __unused; // end of used section 1345 size_t mFree __unused; // end of free section 1346 }; 1347 1348 class _C2CircularBlockSegment : public _C2LinearCapacityAspect { 1349 public: 1350 /** 1351 * Returns the available size for this segment. 1352 * 1353 * \return currently available size for this segment 1354 */ 1355 size_t available() const; 1356 1357 /** 1358 * Reserve some space for this segment from its current start. 1359 * 1360 * \param size desired space in bytes 1361 * \param fence a pointer to an acquire fence. If non-null, the reservation is asynchronous and 1362 * a fence will be stored here that will be signaled when the reservation is 1363 * complete. If null, the reservation is synchronous. 1364 * 1365 * \retval C2_OK the space was successfully reserved 1366 * \retval C2_NO_MEMORY the space requested cannot be reserved 1367 * \retval C2_TIMED_OUT the reservation timed out \todo when? 1368 * \retval C2_CORRUPTED some unknown error prevented reserving space. (unexpected) 1369 */ 1370 c2_status_t reserve(size_t size, C2Fence *fence /* nullable */); 1371 1372 /** 1373 * Abandons a portion of this segment. This will move to the beginning of this segment. 1374 * 1375 * \note This methods is only allowed if this segment is producing blocks. 1376 * 1377 * \param size number of bytes to abandon 1378 * 1379 * \retval C2_OK the data was successfully abandoned 1380 * \retval C2_TIMED_OUT the operation timed out (unexpected) 1381 * \retval C2_CORRUPTED some unknown error prevented abandoning the data (unexpected) 1382 */ 1383 c2_status_t abandon(size_t size); 1384 1385 /** 1386 * Share a portion as block(s) with consumers (these are moved to the used section). 1387 * 1388 * \note This methods is only allowed if this segment is producing blocks. 1389 * \note Share does not move the beginning of the segment. (\todo add abandon/offset?) 1390 * 1391 * \param size number of bytes to share 1392 * \param fence fence to be used for the section 1393 * \param blocks vector where the blocks of the section are appended to 1394 * 1395 * \retval C2_OK the portion was successfully shared 1396 * \retval C2_NO_MEMORY not enough memory to share the portion 1397 * \retval C2_TIMED_OUT the operation timed out (unexpected) 1398 * \retval C2_CORRUPTED some unknown error prevented sharing the data (unexpected) 1399 */ 1400 c2_status_t share(size_t size, C2Fence fence, std::vector<C2ConstLinearBlock> &blocks); 1401 1402 /** 1403 * Returns the beginning offset of this segment from the start of this circular block. 1404 * 1405 * @return beginning offset 1406 */ 1407 size_t begin(); 1408 1409 /** 1410 * Returns the end offset of this segment from the start of this circular block. 1411 * 1412 * @return end offset 1413 */ 1414 size_t end(); 1415 }; 1416 1417 /** 1418 * A circular write-view is a dynamic mapped view for a segment of a circular block. Care must be 1419 * taken when using this view so that only the section owned by the segment is modified. 1420 */ 1421 class C2CircularWriteView : public _C2LinearCapacityAspect { 1422 public: 1423 /** 1424 * Start of the circular block. 1425 * \note the segment does not own this pointer. 1426 * 1427 * \return pointer to the start of the circular block or nullptr on error. 1428 */ 1429 uint8_t *base(); 1430 1431 /** 1432 * \return error during the creation/mapping of this view. 1433 */ 1434 c2_status_t error() const; 1435 }; 1436 1437 /** 1438 * The writer of a circular buffer. 1439 * 1440 * Can commit data to a reader (not supported for components) OR share data blocks directly with a 1441 * consumer. 1442 * 1443 * If a component supports outputting data into circular buffers, it must allocate a circular 1444 * block and use a circular writer. 1445 */ 1446 class C2CircularWriter : public _C2CircularBlockSegment { 1447 public: 1448 /** 1449 * Commits a portion of this segment to the next segment. This moves the beginning of the 1450 * segment. 1451 * 1452 * \param size number of bytes to commit to the next segment 1453 * \param fence fence used for the commit (the fence must signal before the data is committed) 1454 */ 1455 c2_status_t commit(size_t size, C2Fence fence); 1456 1457 /** 1458 * Maps this block into memory and returns a write view for it. 1459 * 1460 * \return a write view for this block. 1461 */ 1462 C2Acquirable<C2CircularWriteView> map(); 1463 }; 1464 1465 /// @} 1466 1467 /// \defgroup graphic Graphic Data Blocks 1468 /// @{ 1469 1470 /** 1471 * C2Rect: rectangle type with non-negative coordinates. 1472 * 1473 * \note This struct has public fields without getters/setters. All methods are inline. 1474 */ 1475 struct C2Rect { 1476 // public: 1477 uint32_t width; 1478 uint32_t height; 1479 uint32_t left; 1480 uint32_t top; 1481 C2RectC2Rect1482 constexpr inline C2Rect() 1483 : C2Rect(0, 0, 0, 0) { } 1484 C2RectC2Rect1485 constexpr inline C2Rect(uint32_t width_, uint32_t height_) 1486 : C2Rect(width_, height_, 0, 0) { } 1487 atC2Rect1488 constexpr C2Rect inline at(uint32_t left_, uint32_t top_) const { 1489 return C2Rect(width, height, left_, top_); 1490 } 1491 1492 // utility methods 1493 isEmptyC2Rect1494 inline constexpr bool isEmpty() const { 1495 return width == 0 || height == 0; 1496 } 1497 isValidC2Rect1498 inline constexpr bool isValid() const { 1499 return left <= ~width && top <= ~height; 1500 } 1501 1502 inline constexpr operator bool() const { 1503 return isValid() && !isEmpty(); 1504 } 1505 1506 inline constexpr bool operator!() const { 1507 return !bool(*this); 1508 } 1509 1510 C2_ALLOW_OVERFLOW containsC2Rect1511 inline constexpr bool contains(const C2Rect &other) const { 1512 if (!isValid() || !other.isValid()) { 1513 return false; 1514 } else { 1515 return left <= other.left && top <= other.top 1516 && left + width >= other.left + other.width 1517 && top + height >= other.top + other.height; 1518 } 1519 } 1520 1521 inline constexpr bool operator==(const C2Rect &other) const { 1522 if (!isValid()) { 1523 return !other.isValid(); 1524 } else { 1525 return left == other.left && top == other.top 1526 && width == other.width && height == other.height; 1527 } 1528 } 1529 1530 inline constexpr bool operator!=(const C2Rect &other) const { 1531 return !operator==(other); 1532 } 1533 1534 inline constexpr bool operator>=(const C2Rect &other) const { 1535 return contains(other); 1536 } 1537 1538 inline constexpr bool operator>(const C2Rect &other) const { 1539 return contains(other) && !operator==(other); 1540 } 1541 1542 inline constexpr bool operator<=(const C2Rect &other) const { 1543 return other.contains(*this); 1544 } 1545 1546 inline constexpr bool operator<(const C2Rect &other) const { 1547 return other.contains(*this) && !operator==(other); 1548 } 1549 1550 C2_ALLOW_OVERFLOW rightC2Rect1551 inline constexpr uint32_t right() const { 1552 return left + width; 1553 } 1554 1555 C2_ALLOW_OVERFLOW bottomC2Rect1556 inline constexpr uint32_t bottom() const { 1557 return top + height; 1558 } 1559 1560 C2_ALLOW_OVERFLOW intersectC2Rect1561 inline constexpr C2Rect intersect(const C2Rect &other) const { 1562 return C2Rect(c2_min(right(), other.right()) - c2_max(left, other.left), 1563 c2_min(bottom(), other.bottom()) - c2_max(top, other.top), 1564 c2_max(left, other.left), 1565 c2_max(top, other.top)); 1566 } 1567 1568 /** clamps right and bottom to top, left if they overflow */ normalizeC2Rect1569 inline constexpr C2Rect normalize() const { 1570 return C2Rect(c2_max(left, right()) - left, c2_max(top, bottom()) - top, left, top); 1571 } 1572 1573 private: 1574 /// note: potentially unusual argument order C2RectC2Rect1575 constexpr inline C2Rect(uint32_t width_, uint32_t height_, uint32_t left_, uint32_t top_) 1576 : width(width_), 1577 height(height_), 1578 left(left_), 1579 top(top_) { } 1580 }; 1581 1582 /** 1583 * Interface for objects that have a width and height (planar capacity). 1584 */ 1585 class _C2PlanarCapacityAspect { 1586 /// \name Planar capacity interface 1587 /// @{ 1588 public: width()1589 inline constexpr uint32_t width() const { return _mWidth; } height()1590 inline constexpr uint32_t height() const { return _mHeight; } 1591 C2Rect()1592 inline constexpr operator C2Rect() const { 1593 return C2Rect(_mWidth, _mHeight); 1594 } 1595 1596 protected: _C2PlanarCapacityAspect(uint32_t width,uint32_t height)1597 inline constexpr _C2PlanarCapacityAspect(uint32_t width, uint32_t height) 1598 : _mWidth(width), _mHeight(height) { } 1599 _C2PlanarCapacityAspect(const _C2PlanarCapacityAspect * parent)1600 inline explicit constexpr _C2PlanarCapacityAspect(const _C2PlanarCapacityAspect *parent) 1601 : _mWidth(parent == nullptr ? 0 : parent->width()), 1602 _mHeight(parent == nullptr ? 0 : parent->height()) { } 1603 1604 private: 1605 uint32_t _mWidth; 1606 uint32_t _mHeight; 1607 /// @} 1608 }; 1609 1610 /** 1611 * C2PlaneInfo: information on the layout of a singe flexible plane. 1612 * 1613 * Public fields without getters/setters. 1614 */ 1615 struct C2PlaneInfo { 1616 //public: 1617 enum channel_t : uint32_t { 1618 CHANNEL_Y, ///< luma 1619 CHANNEL_R, ///< red 1620 CHANNEL_G, ///< green 1621 CHANNEL_B, ///< blue 1622 CHANNEL_A, ///< alpha 1623 CHANNEL_CR, ///< Cr 1624 CHANNEL_CB, ///< Cb 1625 } channel; 1626 1627 int32_t colInc; ///< column increment in bytes. may be negative 1628 int32_t rowInc; ///< row increment in bytes. may be negative 1629 1630 uint32_t colSampling; ///< subsampling compared to width (must be a power of 2) 1631 uint32_t rowSampling; ///< subsampling compared to height (must be a power of 2) 1632 1633 uint32_t allocatedDepth; ///< size of each sample (must be a multiple of 8) 1634 uint32_t bitDepth; ///< significant bits per sample 1635 /** 1636 * the right shift of the significant bits in the sample. E.g. if a 10-bit significant 1637 * value is laid out in a 16-bit allocation aligned to LSB (values 0-1023), rightShift 1638 * would be 0 as the 16-bit value read from the sample does not need to be right shifted 1639 * and can be used as is (after applying a 10-bit mask of 0x3FF). 1640 * 1641 * +--------+--------+ 1642 * | VV|VVVVVVVV| 1643 * +--------+--------+ 1644 * 15 8 7 0 1645 * 1646 * If the value is laid out aligned to MSB, rightShift would be 6, as the value read 1647 * from the allocated sample must be right-shifted by 6 to get the actual sample value. 1648 * 1649 * +--------+--------+ 1650 * |VVVVVVVV|VV | 1651 * +--------+--------+ 1652 * 15 8 7 0 1653 */ 1654 uint32_t rightShift; 1655 1656 enum endianness_t : uint32_t { 1657 NATIVE, 1658 LITTLE_END, // LITTLE_ENDIAN is reserved macro 1659 BIG_END, // BIG_ENDIAN is a reserved macro 1660 } endianness; ///< endianness of the samples 1661 1662 /** 1663 * The following two fields define the relation between multiple planes. If multiple planes are 1664 * interleaved, they share a root plane (whichever plane's start address is the lowest), and 1665 * |offset| is the offset of this plane inside the root plane (in bytes). |rootIx| is the index 1666 * of the root plane. If a plane is independent, rootIx is its index and offset is 0. 1667 */ 1668 uint32_t rootIx; ///< index of the root plane 1669 uint32_t offset; ///< offset of this plane inside of the root plane 1670 minOffsetC2PlaneInfo1671 inline constexpr ssize_t minOffset(uint32_t width, uint32_t height) const { 1672 ssize_t offs = 0; 1673 if (width > 0 && colInc < 0) { 1674 offs += colInc * (ssize_t)(width - 1); 1675 } 1676 if (height > 0 && rowInc < 0) { 1677 offs += rowInc * (ssize_t)(height - 1); 1678 } 1679 return offs; 1680 } 1681 maxOffsetC2PlaneInfo1682 inline constexpr ssize_t maxOffset(uint32_t width, uint32_t height) const { 1683 ssize_t offs = (allocatedDepth + 7) >> 3; 1684 if (width > 0 && colInc > 0) { 1685 offs += colInc * (ssize_t)(width - 1); 1686 } 1687 if (height > 0 && rowInc > 0) { 1688 offs += rowInc * (ssize_t)(height - 1); 1689 } 1690 return offs; 1691 } 1692 } C2_PACK; 1693 1694 struct C2PlanarLayout { 1695 //public: 1696 enum type_t : uint32_t { 1697 TYPE_UNKNOWN = 0, 1698 TYPE_YUV = 0x100, ///< YUV image with 3 planes 1699 TYPE_YUVA, ///< YUVA image with 4 planes 1700 TYPE_RGB, ///< RGB image with 3 planes 1701 TYPE_RGBA, ///< RBGA image with 4 planes 1702 }; 1703 1704 type_t type; // image type 1705 uint32_t numPlanes; // number of component planes 1706 uint32_t rootPlanes; // number of layout planes (root planes) 1707 1708 enum plane_index_t : uint32_t { 1709 PLANE_Y = 0, 1710 PLANE_U = 1, 1711 PLANE_V = 2, 1712 PLANE_R = 0, 1713 PLANE_G = 1, 1714 PLANE_B = 2, 1715 PLANE_A = 3, 1716 MAX_NUM_PLANES = 4, 1717 }; 1718 1719 C2PlaneInfo planes[MAX_NUM_PLANES]; 1720 }; 1721 1722 /** 1723 * Aspect for objects that have a planar section (crop rectangle). 1724 * 1725 * This class is copiable. 1726 */ 1727 class _C2PlanarSectionAspect : public _C2PlanarCapacityAspect { 1728 /// \name Planar section interface 1729 /// @{ 1730 private: _C2PlanarSectionAspect(uint32_t width,uint32_t height,const C2Rect & crop)1731 inline constexpr _C2PlanarSectionAspect(uint32_t width, uint32_t height, const C2Rect &crop) 1732 : _C2PlanarCapacityAspect(width, height), 1733 mCrop(C2Rect(std::min(width - std::min(crop.left, width), crop.width), 1734 std::min(height - std::min(crop.top, height), crop.height)).at( 1735 std::min(crop.left, width), 1736 std::min(crop.height, height))) { 1737 } 1738 1739 public: 1740 // crop can be an empty rect, does not have to line up with subsampling 1741 // NOTE: we do not support floating-point crop crop()1742 inline constexpr C2Rect crop() const { return mCrop; } 1743 1744 /** 1745 * Returns a child planar section for |crop|, where the capacity represents this section. 1746 */ childSection(const C2Rect & crop)1747 inline constexpr _C2PlanarSectionAspect childSection(const C2Rect &crop) const { 1748 return _C2PlanarSectionAspect( 1749 mCrop.width, mCrop.height, 1750 // crop and translate |crop| rect 1751 C2Rect(c2_min(mCrop.right() - c2_clamp(mCrop.left, crop.left, mCrop.right()), 1752 crop.width), 1753 c2_min(mCrop.bottom() - c2_clamp(mCrop.top, crop.top, mCrop.bottom()), 1754 crop.height)) 1755 .at(c2_clamp(mCrop.left, crop.left, mCrop.right()) - mCrop.left, 1756 c2_clamp(mCrop.top, crop.top, mCrop.bottom()) - mCrop.top)); 1757 } 1758 1759 protected: _C2PlanarSectionAspect(const _C2PlanarCapacityAspect * parent)1760 inline constexpr _C2PlanarSectionAspect(const _C2PlanarCapacityAspect *parent) 1761 : _C2PlanarCapacityAspect(parent), mCrop(width(), height()) {} 1762 _C2PlanarSectionAspect(const _C2PlanarCapacityAspect * parent,const C2Rect & crop)1763 inline constexpr _C2PlanarSectionAspect(const _C2PlanarCapacityAspect *parent, const C2Rect &crop) 1764 : _C2PlanarCapacityAspect(parent), 1765 mCrop(parent == nullptr ? C2Rect() : ((C2Rect)*parent).intersect(crop).normalize()) { } 1766 _C2PlanarSectionAspect(const _C2PlanarSectionAspect * parent,const C2Rect & crop)1767 inline constexpr _C2PlanarSectionAspect(const _C2PlanarSectionAspect *parent, const C2Rect &crop) 1768 : _C2PlanarCapacityAspect(parent), 1769 mCrop(parent == nullptr ? C2Rect() : parent->crop().intersect(crop).normalize()) { } 1770 1771 private: 1772 friend class _C2EditablePlanarSectionAspect; 1773 C2Rect mCrop; 1774 /// @} 1775 }; 1776 1777 /** 1778 * Aspect for objects that have an editable planar section (crop rectangle). 1779 * 1780 * This class is copiable. 1781 */ 1782 class _C2EditablePlanarSectionAspect : public _C2PlanarSectionAspect { 1783 /// \name Planar section interface 1784 /// @{ 1785 using _C2PlanarSectionAspect::_C2PlanarSectionAspect; 1786 1787 public: 1788 // crop can be an empty rect, does not have to line up with subsampling 1789 // NOTE: we do not support floating-point crop crop()1790 inline constexpr C2Rect crop() const { return mCrop; } 1791 1792 /** 1793 * Sets crop to crop intersected with [(0,0) .. (width, height)] 1794 */ setCrop_be(const C2Rect & crop)1795 inline void setCrop_be(const C2Rect &crop) { 1796 mCrop.left = std::min(width(), crop.left); 1797 mCrop.top = std::min(height(), crop.top); 1798 // It's guaranteed that mCrop.left <= width() && mCrop.top <= height() 1799 mCrop.width = std::min(width() - mCrop.left, crop.width); 1800 mCrop.height = std::min(height() - mCrop.top, crop.height); 1801 } 1802 1803 /** 1804 * If crop is within the dimensions of this object, it sets crop to it. 1805 * 1806 * \return true iff crop is within the dimensions of this object 1807 */ setCrop(const C2Rect & crop)1808 inline bool setCrop(const C2Rect &crop) { 1809 if (width() < crop.width || height() < crop.height 1810 || width() - crop.width < crop.left || height() - crop.height < crop.top) { 1811 return false; 1812 } 1813 mCrop = crop; 1814 return true; 1815 } 1816 /// @} 1817 }; 1818 1819 /** 1820 * Utility class for safe range calculations using size_t-s. 1821 */ 1822 class C2PlanarSection : public _C2PlanarSectionAspect { 1823 public: C2PlanarSection(const _C2PlanarCapacityAspect & parent,const C2Rect & crop)1824 inline constexpr C2PlanarSection(const _C2PlanarCapacityAspect &parent, const C2Rect &crop) 1825 : _C2PlanarSectionAspect(&parent, crop) { } 1826 C2PlanarSection(const _C2PlanarSectionAspect & parent,const C2Rect & crop)1827 inline constexpr C2PlanarSection(const _C2PlanarSectionAspect &parent, const C2Rect &crop) 1828 : _C2PlanarSectionAspect(&parent, crop) { } 1829 intersect(const C2Rect & crop)1830 inline constexpr C2PlanarSection intersect(const C2Rect &crop) const { 1831 return C2PlanarSection(*this, crop); 1832 } 1833 }; 1834 1835 /** 1836 * Utility class for simple and safe planar capacity and section construction. 1837 */ 1838 class C2PlanarCapacity : public _C2PlanarCapacityAspect { 1839 public: C2PlanarCapacity(size_t width,size_t height)1840 inline constexpr explicit C2PlanarCapacity(size_t width, size_t height) 1841 : _C2PlanarCapacityAspect(c2_min(width, std::numeric_limits<uint32_t>::max()), 1842 c2_min(height, std::numeric_limits<uint32_t>::max())) { } 1843 section(const C2Rect & crop)1844 inline constexpr C2PlanarSection section(const C2Rect &crop) const { 1845 return C2PlanarSection(*this, crop); 1846 } 1847 }; 1848 1849 1850 /** 1851 * \ingroup graphic allocator 1852 * 2D allocation interface. 1853 */ 1854 class C2GraphicAllocation : public _C2PlanarCapacityAspect { 1855 public: 1856 /** 1857 * Maps a rectangular section (as defined by |rect|) of a 2D allocation into local process 1858 * memory for flexible access. On success, it fills out |layout| with the plane specifications 1859 * and fills the |addr| array with pointers to the first byte of the top-left pixel of each 1860 * plane used. Otherwise, it leaves |layout| and |addr| untouched. |fence| will contain 1861 * an acquire sync fence object. If it is already safe to access the 1862 * buffer contents, then it will be an empty (already fired) fence. 1863 * 1864 * Safe regions for the pointer addresses returned can be gotten via C2LayoutInfo.minOffset()/ 1865 * maxOffset(). 1866 * 1867 * \param rect section to be mapped (this does not have to be aligned) 1868 * \param usage the desired usage. \todo this must be kSoftwareRead and/or 1869 * kSoftwareWrite. 1870 * \param fence a pointer to a fence object if an async mapping is requested. If 1871 * not-null, and acquire fence will be stored here on success, or empty 1872 * fence on failure. If null, the mapping will be synchronous. 1873 * \param layout a pointer to where the mapped planes' descriptors will be 1874 * stored. On failure, nullptr will be stored here. 1875 * \param addr pointer to an array with at least C2PlanarLayout::MAX_NUM_PLANES 1876 * elements. Only layout.numPlanes elements will be modified on success. 1877 * 1878 * \retval C2_OK the operation was successful 1879 * \retval C2_REFUSED no permission to map the section 1880 * \retval C2_DUPLICATE there is already a mapped region and this allocation cannot support 1881 * multi-mapping (caller error) 1882 * \retval C2_TIMED_OUT the operation timed out 1883 * \retval C2_NO_MEMORY not enough memory to complete the operation 1884 * \retval C2_BAD_VALUE the parameters (rect) are invalid or outside the allocation, or the 1885 * usage flags are invalid (caller error) 1886 * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected) 1887 1888 */ 1889 virtual c2_status_t map( 1890 C2Rect rect, C2MemoryUsage usage, C2Fence *fence, 1891 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) = 0; 1892 1893 /** 1894 * Unmaps a section of an allocation at |addr| with |rect|. These must be parameters previously 1895 * passed to and returned by |map|; otherwise, this operation is a no-op. 1896 * 1897 * \param addr pointer to an array with at least C2PlanarLayout::MAX_NUM_PLANES 1898 * elements containing the starting addresses of the mapped layers 1899 * \param rect boundaries of the mapped section 1900 * \param fence a pointer to a fence object if an async unmapping is requested. If 1901 * not-null, a release fence will be stored here on success, or empty fence 1902 * on failure. This fence signals when the original allocation contains 1903 * all changes that happened to the mapped section. If null, the unmapping 1904 * will be synchronous. 1905 * 1906 * \retval C2_OK the operation was successful 1907 * \retval C2_TIMED_OUT the operation timed out 1908 * \retval C2_NOT_FOUND there is no such mapped region (caller error) 1909 * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected) 1910 * \retval C2_REFUSED no permission to unmap the section (unexpected - system) 1911 */ 1912 virtual c2_status_t unmap( 1913 uint8_t **addr /* nonnull */, C2Rect rect, C2Fence *fence /* nullable */) = 0; 1914 1915 /** 1916 * Returns the allocator ID for this allocation. This is useful to put the handle into context. 1917 */ 1918 virtual C2Allocator::id_t getAllocatorId() const = 0; 1919 1920 /** 1921 * Returns a pointer to the allocation handle. 1922 */ 1923 virtual const C2Handle *handle() const = 0; 1924 1925 /** 1926 * Returns true if this is the same allocation as |other|. 1927 */ 1928 virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const = 0; 1929 1930 protected: 1931 using _C2PlanarCapacityAspect::_C2PlanarCapacityAspect; 1932 virtual ~C2GraphicAllocation() = default; 1933 }; 1934 1935 class C2GraphicAllocation; 1936 1937 /** 1938 * A 2D block. 1939 * 1940 * \note width()/height() is not meaningful for users of blocks; instead, crop().width() and 1941 * crop().height() is the capacity of the usable portion. Use and crop() if accessing the block 1942 * directly through its handle to represent the allotted region of the underlying allocation to this 1943 * block. 1944 */ 1945 class C2Block2D : public _C2PlanarSectionAspect { 1946 public: 1947 /** 1948 * Returns the underlying handle for this allocation. 1949 * 1950 * \note that the block and its block pool has shared ownership of the handle 1951 * and if all references to the block are released, the underlying block 1952 * allocation may get reused even if a client keeps a clone of this handle. 1953 */ 1954 const C2Handle *handle() const; 1955 1956 /** 1957 * Returns the allocator's ID that created the underlying allocation for this block. This 1958 * provides the context for understanding the handle. 1959 */ 1960 C2Allocator::id_t getAllocatorId() const; 1961 1962 protected: 1963 class Impl; 1964 C2Block2D(std::shared_ptr<Impl> impl, const _C2PlanarSectionAspect §ion); 1965 1966 friend struct _C2BlockFactory; 1967 std::shared_ptr<Impl> mImpl; 1968 }; 1969 1970 /** 1971 * Graphic view provides read or read-write access for a graphic block. 1972 * 1973 * This class is copiable. 1974 * 1975 * \note Due to the subsampling of graphic buffers, a read view must still contain a crop rectangle 1976 * to ensure subsampling is followed. This results in nearly identical interface between read and 1977 * write views, so C2GraphicView can encompass both of them. 1978 */ 1979 class C2GraphicView : public _C2EditablePlanarSectionAspect { 1980 public: 1981 /** 1982 * \return array of pointers (of layout().numPlanes elements) to the start of the planes or 1983 * nullptr on error. Regardless of crop rect, they always point to the top-left corner of each 1984 * plane. Access outside of the crop rect results in an undefined behavior. 1985 */ 1986 const uint8_t *const *data() const; 1987 1988 /** 1989 * \return array of pointers (of layout().numPlanes elements) to the start of the planes or 1990 * nullptr on error. Regardless of crop rect, they always point to the top-left corner of each 1991 * plane. Access outside of the crop rect results in an undefined behavior. 1992 */ 1993 uint8_t *const *data(); 1994 1995 /** 1996 * \return layout of the graphic block to interpret the returned data. 1997 */ 1998 const C2PlanarLayout layout() const; 1999 2000 /** 2001 * Returns a section of this view. 2002 * 2003 * \param rect the dimension of the section. \note This is clamped to the crop of this view. 2004 * 2005 * \return a read view containing the requested section of this view 2006 */ 2007 const C2GraphicView subView(const C2Rect &rect) const; 2008 C2GraphicView subView(const C2Rect &rect); 2009 2010 /** 2011 * \return error during the creation/mapping of this view. 2012 */ 2013 c2_status_t error() const; 2014 2015 protected: 2016 class Impl; 2017 C2GraphicView(std::shared_ptr<Impl> impl, const _C2PlanarSectionAspect §ion); 2018 explicit C2GraphicView(c2_status_t error); 2019 2020 private: 2021 friend struct _C2BlockFactory; 2022 std::shared_ptr<Impl> mImpl; 2023 }; 2024 2025 /** 2026 * A constant (read-only) graphic block (portion of an allocation) with an acquire fence. 2027 * Blocks are unmapped when created, and can be mapped into a read view on demand. 2028 * 2029 * This class is copiable and contains a reference to the allocation that it is based on. 2030 */ 2031 class C2ConstGraphicBlock : public C2Block2D { 2032 public: 2033 /** 2034 * Maps this block into memory and returns a read view for it. 2035 * 2036 * \return a read view for this block. 2037 */ 2038 C2Acquirable<const C2GraphicView> map() const; 2039 2040 /** 2041 * Returns a section of this block. 2042 * 2043 * \param rect the coordinates of the section. \note This is clamped to the crop rectangle of 2044 * this block. 2045 * 2046 * \return a constant graphic block containing a portion of this block 2047 */ 2048 C2ConstGraphicBlock subBlock(const C2Rect &rect) const; 2049 2050 /** 2051 * Returns the acquire fence for this block. 2052 * 2053 * \return a fence that must be waited on before reading the block. 2054 */ fence()2055 C2Fence fence() const { return mFence; } 2056 2057 protected: 2058 C2ConstGraphicBlock( 2059 std::shared_ptr<Impl> impl, const _C2PlanarSectionAspect §ion, C2Fence fence); 2060 2061 private: 2062 friend struct _C2BlockFactory; 2063 C2Fence mFence; 2064 }; 2065 2066 /** 2067 * Graphic block is a writeable 2D block. Once written, it can be shared in whole or in part with 2068 * consumers/readers as read-only const graphic block. 2069 */ 2070 class C2GraphicBlock : public C2Block2D { 2071 public: 2072 /** 2073 * Maps this block into memory and returns a write view for it. 2074 * 2075 * \return a write view for this block. 2076 */ 2077 C2Acquirable<C2GraphicView> map(); 2078 2079 /** 2080 * Creates a read-only const linear block for a portion of this block; optionally protected 2081 * by an acquire fence. There are two ways to use this: 2082 * 2083 * 1) share ready block after writing data into the block. In this case no fence shall be 2084 * supplied, and the block shall not be modified after calling this method. 2085 * 2) share block metadata before actually (finishing) writing the data into the block. In 2086 * this case a fence must be supplied that will be triggered when the data is written. 2087 * The block shall be modified only until firing the event for the fence. 2088 */ 2089 C2ConstGraphicBlock share(const C2Rect &crop, C2Fence fence); 2090 2091 protected: 2092 C2GraphicBlock(std::shared_ptr<Impl> impl, const _C2PlanarSectionAspect §ion); 2093 2094 friend struct _C2BlockFactory; 2095 }; 2096 2097 /// @} 2098 2099 /// \defgroup buffer_onj Buffer objects 2100 /// @{ 2101 2102 // ================================================================================================ 2103 // BUFFERS 2104 // ================================================================================================ 2105 2106 /// \todo: Do we still need this? 2107 /// 2108 // There are 2 kinds of buffers: linear or graphic. Linear buffers can contain a single block, or 2109 // a list of blocks (LINEAR_CHUNKS). Support for list of blocks is optional, and can allow consuming 2110 // data from circular buffers or scattered data sources without extra memcpy. Currently, list of 2111 // graphic blocks is not supported. 2112 2113 class C2LinearBuffer; // read-write buffer 2114 class C2GraphicBuffer; // read-write buffer 2115 class C2LinearChunksBuffer; 2116 2117 /** 2118 * C2BufferData: the main, non-meta data of a buffer. A buffer can contain either linear blocks 2119 * or graphic blocks, and can contain either a single block or multiple blocks. This is determined 2120 * by its type. 2121 */ 2122 class C2BufferData { 2123 public: 2124 /** 2125 * The type of buffer data. 2126 */ 2127 enum type_t : uint32_t { 2128 INVALID, ///< invalid buffer type. Do not use. 2129 LINEAR, ///< the buffer contains a single linear block 2130 LINEAR_CHUNKS, ///< the buffer contains one or more linear blocks 2131 GRAPHIC, ///< the buffer contains a single graphic block 2132 GRAPHIC_CHUNKS, ///< the buffer contains one of more graphic blocks 2133 }; 2134 2135 /** 2136 * Gets the type of this buffer (data). 2137 * \return the type of this buffer data. 2138 */ 2139 type_t type() const; 2140 2141 /** 2142 * Gets the linear blocks of this buffer. 2143 * \return a constant list of const linear blocks of this buffer. 2144 * \retval empty list if this buffer does not contain linear block(s). 2145 */ 2146 const std::vector<C2ConstLinearBlock> linearBlocks() const; 2147 2148 /** 2149 * Gets the graphic blocks of this buffer. 2150 * \return a constant list of const graphic blocks of this buffer. 2151 * \retval empty list if this buffer does not contain graphic block(s). 2152 */ 2153 const std::vector<C2ConstGraphicBlock> graphicBlocks() const; 2154 2155 private: 2156 class Impl; 2157 std::shared_ptr<Impl> mImpl; 2158 2159 protected: 2160 // no public constructor 2161 explicit C2BufferData(const std::vector<C2ConstLinearBlock> &blocks); 2162 explicit C2BufferData(const std::vector<C2ConstGraphicBlock> &blocks); 2163 }; 2164 2165 /** 2166 * C2Buffer: buffer base class. These are always used as shared_ptrs. Though the underlying buffer 2167 * objects (native buffers, ion buffers, or dmabufs) are reference-counted by the system, 2168 * C2Buffers hold only a single reference. 2169 * 2170 * These objects cannot be used on the stack. 2171 */ 2172 class C2Buffer { 2173 public: 2174 /** 2175 * Gets the buffer's data. 2176 * 2177 * \return the buffer's data. 2178 */ 2179 const C2BufferData data() const; 2180 2181 ///@name Pre-destroy notification handling 2182 ///@{ 2183 2184 /** 2185 * Register for notification just prior to the destruction of this object. 2186 */ 2187 typedef void (*OnDestroyNotify) (const C2Buffer *buf, void *arg); 2188 2189 /** 2190 * Registers for a pre-destroy notification. This is called just prior to the destruction of 2191 * this buffer (when this buffer is no longer valid.) 2192 * 2193 * \param onDestroyNotify the notification callback 2194 * \param arg an arbitrary parameter passed to the callback 2195 * 2196 * \retval C2_OK the registration was successful. 2197 * \retval C2_DUPLICATE a notification was already registered for this callback and argument 2198 * \retval C2_NO_MEMORY not enough memory to register for this callback 2199 * \retval C2_CORRUPTED an unknown error prevented the registration (unexpected) 2200 */ 2201 c2_status_t registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr); 2202 2203 /** 2204 * Unregisters a previously registered pre-destroy notification. 2205 * 2206 * \param onDestroyNotify the notification callback 2207 * \param arg an arbitrary parameter passed to the callback 2208 * 2209 * \retval C2_OK the unregistration was successful. 2210 * \retval C2_NOT_FOUND the notification was not found 2211 * \retval C2_CORRUPTED an unknown error prevented the registration (unexpected) 2212 */ 2213 c2_status_t unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr); 2214 2215 ///@} 2216 2217 virtual ~C2Buffer() = default; 2218 2219 ///@name Buffer-specific arbitrary metadata handling 2220 ///@{ 2221 2222 /** 2223 * Gets the list of metadata associated with this buffer. 2224 * 2225 * \return a constant list of info objects associated with this buffer. 2226 */ 2227 const std::vector<std::shared_ptr<const C2Info>> info() const; 2228 2229 /** 2230 * Attaches (or updates) an (existing) metadata for this buffer. 2231 * If the metadata is stream specific, the stream information will be reset. 2232 * 2233 * \param info Metadata to update 2234 * 2235 * \retval C2_OK the metadata was successfully attached/updated. 2236 * \retval C2_NO_MEMORY not enough memory to attach the metadata (this return value is not 2237 * used if the same kind of metadata is already attached to the buffer). 2238 */ 2239 c2_status_t setInfo(const std::shared_ptr<C2Info> &info); 2240 2241 /** 2242 * Checks if there is a certain type of metadata attached to this buffer. 2243 * 2244 * \param index the parameter type of the metadata 2245 * 2246 * \return true iff there is a metadata with the parameter type attached to this buffer. 2247 */ 2248 bool hasInfo(C2Param::Type index) const; 2249 2250 /** 2251 * Checks if there is a certain type of metadata attached to this buffer, and returns a 2252 * shared pointer to it if there is. Returns an empty shared pointer object (nullptr) if there 2253 * is not. 2254 * 2255 * \param index the parameter type of the metadata 2256 * 2257 * \return shared pointer to the metadata. 2258 */ 2259 std::shared_ptr<const C2Info> getInfo(C2Param::Type index) const; 2260 2261 /** 2262 * Removes a metadata from the buffer. 2263 */ 2264 std::shared_ptr<C2Info> removeInfo(C2Param::Type index); 2265 ///@} 2266 2267 /** 2268 * Creates a buffer containing a single linear block. 2269 * 2270 * \param block the content of the buffer. 2271 * 2272 * \return shared pointer to the created buffer. 2273 */ 2274 static std::shared_ptr<C2Buffer> CreateLinearBuffer(const C2ConstLinearBlock &block); 2275 2276 /** 2277 * Creates a buffer containing a single graphic block. 2278 * 2279 * \param block the content of the buffer. 2280 * 2281 * \return shared pointer to the created buffer. 2282 */ 2283 static std::shared_ptr<C2Buffer> CreateGraphicBuffer(const C2ConstGraphicBlock &block); 2284 2285 protected: 2286 // no public constructor 2287 explicit C2Buffer(const std::vector<C2ConstLinearBlock> &blocks); 2288 explicit C2Buffer(const std::vector<C2ConstGraphicBlock> &blocks); 2289 2290 private: 2291 class Impl; 2292 std::shared_ptr<Impl> mImpl; 2293 }; 2294 2295 /** 2296 * A const metadata object that can contain arbitrary buffer data. 2297 * 2298 * This object is not an actual C2Info and is not attached to buffers (C2Buffer), but rather to 2299 * frames (C2FrameData). It is not describable via C2ParamDescriptor. 2300 * 2301 * C2InfoBuffer is a const object that can be allocated on stack and is copiable. 2302 */ 2303 class C2InfoBuffer { 2304 public: 2305 /** 2306 * Gets the index of this info object. 2307 * 2308 * \return the parameter index. 2309 */ index()2310 const C2Param::Index index() const { return mIndex; } 2311 2312 /** 2313 * Gets the buffer's data. 2314 * 2315 * \return the buffer's data. 2316 */ data()2317 const C2BufferData data() const { return mData; } 2318 2319 /// Returns a clone of this as a global info buffer. asGlobal()2320 C2InfoBuffer asGlobal() const { 2321 C2Param::Index index = mIndex; 2322 index.convertToGlobal(); 2323 return C2InfoBuffer(index, mData); 2324 } 2325 2326 /// Returns a clone of this as a port info buffer. asPort(bool output)2327 C2InfoBuffer asPort(bool output) const { 2328 C2Param::Index index = mIndex; 2329 index.convertToPort(output); 2330 return C2InfoBuffer(index, mData); 2331 } 2332 2333 /// Returns a clone of this as a stream info buffer. asStream(bool output,unsigned stream)2334 C2InfoBuffer asStream(bool output, unsigned stream) const { 2335 C2Param::Index index = mIndex; 2336 index.convertToStream(output, stream); 2337 return C2InfoBuffer(index, mData); 2338 } 2339 2340 /** 2341 * Creates a global info buffer containing a single linear block. 2342 * 2343 * \param index the core parameter index of this info buffer. 2344 * \param block the content of the info buffer. 2345 * 2346 * \return shared pointer to the created info buffer. 2347 */ 2348 static C2InfoBuffer CreateLinearBuffer(C2Param::CoreIndex index, const C2ConstLinearBlock &block); 2349 2350 /** 2351 * Creates a global info buffer containing a single graphic block. 2352 * 2353 * \param index the core parameter index of this info buffer. 2354 * \param block the content of the info buffer. 2355 * 2356 * \return shared pointer to the created info buffer. 2357 */ 2358 static C2InfoBuffer CreateGraphicBuffer(C2Param::CoreIndex index, const C2ConstGraphicBlock &block); 2359 2360 protected: 2361 // no public constructor 2362 explicit C2InfoBuffer(C2Param::Index index, const std::vector<C2ConstLinearBlock> &blocks); 2363 explicit C2InfoBuffer(C2Param::Index index, const std::vector<C2ConstGraphicBlock> &blocks); 2364 2365 private: 2366 C2Param::Index mIndex; 2367 C2BufferData mData; 2368 explicit C2InfoBuffer(C2Param::Index index, const C2BufferData &data); 2369 }; 2370 2371 /// @} 2372 2373 /// @} 2374 2375 #endif // C2BUFFER_H_ 2376