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 occured during allocation (unexpected) 646 */ newLinearAllocation(uint32_t capacity __unused,C2MemoryUsage usage __unused,std::shared_ptr<C2LinearAllocation> * allocation)647 virtual c2_status_t newLinearAllocation( 648 uint32_t capacity __unused, C2MemoryUsage usage __unused, 649 std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) { 650 *allocation = nullptr; 651 return C2_OMITTED; 652 } 653 654 /** 655 * (Re)creates a 1D allocation from a native |handle|. If successful, the allocation is stored 656 * in |allocation|. Otherwise, |allocation| is set to 'nullptr'. 657 * 658 * \param handle the handle for the existing allocation. On success, the allocation will 659 * take ownership of |handle|. 660 * \param allocation pointer to where the allocation shall be stored on success. nullptr 661 * will be stored here on failure 662 * 663 * \retval C2_OK the allocation was recreated successfully 664 * \retval C2_NO_MEMORY not enough memory to recreate the allocation 665 * \retval C2_TIMED_OUT the recreation timed out (unexpected) 666 * \retval C2_REFUSED no permission to recreate the allocation 667 * \retval C2_BAD_VALUE invalid handle (caller error) 668 * \retval C2_OMITTED this allocator does not support 1D allocations 669 * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected) 670 */ priorLinearAllocation(const C2Handle * handle __unused,std::shared_ptr<C2LinearAllocation> * allocation)671 virtual c2_status_t priorLinearAllocation( 672 const C2Handle *handle __unused, 673 std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) { 674 *allocation = nullptr; 675 return C2_OMITTED; 676 } 677 678 /** 679 * Allocates a 2D allocation of given |width|, |height|, |format| and |usage|. If successful, 680 * the allocation is stored in |allocation|. Otherwise, |allocation| is set to 'nullptr'. 681 * 682 * \param width the width of requested allocation (the allocation could be slightly 683 * larger, e.g. to account for any system-required alignment) 684 * \param height the height of requested allocation (the allocation could be slightly 685 * larger, e.g. to account for any system-required alignment) 686 * \param format the pixel format of requested allocation. This could be a vendor 687 * specific format. 688 * \param usage the memory usage info for the requested allocation. \note that the 689 * returned allocation may be later used/mapped with different usage. 690 * The allocator should layout the buffer to be optimized for this usage, 691 * but must support any usage. One exception: protected buffers can 692 * only be used in a protected scenario. 693 * \param allocation pointer to where the allocation shall be stored on success. nullptr 694 * will be stored here on failure 695 * 696 * \retval C2_OK the allocation was successful 697 * \retval C2_NO_MEMORY not enough memory to complete the allocation 698 * \retval C2_TIMED_OUT the allocation timed out 699 * \retval C2_REFUSED no permission to complete the allocation 700 * \retval C2_BAD_VALUE width, height, format or usage are not supported (invalid) (caller error) 701 * \retval C2_OMITTED this allocator does not support 2D allocations 702 * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected) 703 */ newGraphicAllocation(uint32_t width __unused,uint32_t height __unused,uint32_t format __unused,C2MemoryUsage usage __unused,std::shared_ptr<C2GraphicAllocation> * allocation)704 virtual c2_status_t newGraphicAllocation( 705 uint32_t width __unused, uint32_t height __unused, uint32_t format __unused, 706 C2MemoryUsage usage __unused, 707 std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) { 708 *allocation = nullptr; 709 return C2_OMITTED; 710 } 711 712 /** 713 * (Re)creates a 2D allocation from a native handle. If successful, the allocation is stored 714 * in |allocation|. Otherwise, |allocation| is set to 'nullptr'. 715 * 716 * \param handle the handle for the existing allocation. On success, the allocation will 717 * take ownership of |handle|. 718 * \param allocation pointer to where the allocation shall be stored on success. nullptr 719 * will be stored here on failure 720 * 721 * \retval C2_OK the allocation was recreated successfully 722 * \retval C2_NO_MEMORY not enough memory to recreate the allocation 723 * \retval C2_TIMED_OUT the recreation timed out (unexpected) 724 * \retval C2_REFUSED no permission to recreate the allocation 725 * \retval C2_BAD_VALUE invalid handle (caller error) 726 * \retval C2_OMITTED this allocator does not support 2D allocations 727 * \retval C2_CORRUPTED some unknown, unrecoverable error occured during recreation (unexpected) 728 */ priorGraphicAllocation(const C2Handle * handle __unused,std::shared_ptr<C2GraphicAllocation> * allocation)729 virtual c2_status_t priorGraphicAllocation( 730 const C2Handle *handle __unused, 731 std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) { 732 *allocation = nullptr; 733 return C2_OMITTED; 734 } 735 736 virtual ~C2Allocator() = default; 737 protected: 738 C2Allocator() = default; 739 }; 740 741 /** 742 * \ingroup linear allocator 743 * 1D allocation interface. 744 */ 745 class C2LinearAllocation : public _C2LinearCapacityAspect { 746 public: 747 /** 748 * Maps a portion of an allocation starting from |offset| with |size| into local process memory. 749 * Stores the starting address into |addr|, or NULL if the operation was unsuccessful. 750 * |fence| will contain an acquire sync fence object. If it is already 751 * safe to access the buffer contents, then it will contain an empty (already fired) fence. 752 * 753 * \param offset starting position of the portion to be mapped (this does not have to 754 * be page aligned) 755 * \param size size of the portion to be mapped (this does not have to be page 756 * aligned) 757 * \param usage the desired usage. \todo this must be kSoftwareRead and/or 758 * kSoftwareWrite. 759 * \param fence a pointer to a fence object if an async mapping is requested. If 760 * not-null, and acquire fence will be stored here on success, or empty 761 * fence on failure. If null, the mapping will be synchronous. 762 * \param addr a pointer to where the starting address of the mapped portion will be 763 * stored. On failure, nullptr will be stored here. 764 * 765 * \todo Only one portion can be mapped at the same time - this is true for gralloc, but there 766 * is no need for this for 1D buffers. 767 * \todo Do we need to support sync operation as we could just wait for the fence? 768 * 769 * \retval C2_OK the operation was successful 770 * \retval C2_REFUSED no permission to map the portion 771 * \retval C2_TIMED_OUT the operation timed out 772 * \retval C2_DUPLICATE if the allocation is already mapped. 773 * \retval C2_NO_MEMORY not enough memory to complete the operation 774 * \retval C2_BAD_VALUE the parameters (offset/size) are invalid or outside the allocation, or 775 * the usage flags are invalid (caller error) 776 * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected) 777 */ 778 virtual c2_status_t map( 779 size_t offset, size_t size, C2MemoryUsage usage, C2Fence *fence /* nullable */, 780 void **addr /* nonnull */) = 0; 781 782 /** 783 * Unmaps a portion of an allocation at |addr| with |size|. These must be parameters previously 784 * passed to and returned by |map|; otherwise, this operation is a no-op. 785 * 786 * \param addr starting address of the mapped region 787 * \param size size of the mapped region 788 * \param fence a pointer to a fence object if an async unmapping is requested. If 789 * not-null, a release fence will be stored here on success, or empty fence 790 * on failure. This fence signals when the original allocation contains 791 * all changes that happened to the mapped region. If null, the unmapping 792 * will be synchronous. 793 * 794 * \retval C2_OK the operation was successful 795 * \retval C2_TIMED_OUT the operation timed out 796 * \retval C2_NOT_FOUND if the allocation was not mapped previously. 797 * \retval C2_BAD_VALUE the parameters (addr/size) do not correspond to previously mapped 798 * regions (caller error) 799 * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected) 800 * \retval C2_REFUSED no permission to unmap the portion (unexpected - system) 801 */ 802 virtual c2_status_t unmap(void *addr, size_t size, C2Fence *fence /* nullable */) = 0; 803 804 /** 805 * Returns the allocator ID for this allocation. This is useful to put the handle into context. 806 */ 807 virtual C2Allocator::id_t getAllocatorId() const = 0; 808 809 /** 810 * Returns a pointer to the allocation handle. 811 */ 812 virtual const C2Handle *handle() const = 0; 813 814 /** 815 * Returns true if this is the same allocation as |other|. 816 */ 817 virtual bool equals(const std::shared_ptr<C2LinearAllocation> &other) const = 0; 818 819 protected: 820 // \todo should we limit allocation directly? C2LinearAllocation(size_t capacity)821 C2LinearAllocation(size_t capacity) : _C2LinearCapacityAspect(c2_min(capacity, UINT32_MAX)) {} 822 virtual ~C2LinearAllocation() = default; 823 }; 824 825 class C2CircularBlock; 826 class C2LinearBlock; 827 class C2GraphicBlock; 828 829 /** 830 * Block pools are used by components to obtain output buffers in an efficient way. They can 831 * support either linear (1D), circular (1D) or graphic (2D) blocks. 832 * 833 * Block pools decouple the recycling of memory/allocations from the components. They are meant to 834 * be an opaque service (there are no public APIs other than obtaining blocks) provided by the 835 * platform. Block pools are also meant to decouple allocations from memory used by buffers. This 836 * is accomplished by allowing pools to allot multiple memory 'blocks' on a single allocation. As 837 * their name suggest, block pools maintain a pool of memory blocks. When a component asks for 838 * a memory block, pools will try to return a free memory block already in the pool. If no such 839 * block exists, they will allocate memory using the backing allocator and allot a block on that 840 * allocation. When blocks are no longer used in the system, they are recycled back to the block 841 * pool and are available as free blocks. 842 * 843 * Never constructed on stack. 844 */ 845 class C2BlockPool { 846 public: 847 /** 848 * Block pool ID type. 849 */ 850 typedef uint64_t local_id_t; 851 852 enum : local_id_t { 853 BASIC_LINEAR = 0, ///< ID of basic (unoptimized) block pool for fetching 1D blocks 854 BASIC_GRAPHIC = 1, ///< ID of basic (unoptimized) block pool for fetching 2D blocks 855 PLATFORM_START = 0x10, 856 }; 857 858 /** 859 * Returns the ID for this block pool. This ID is used to get this block pool from the platform. 860 * It is only valid in the current process. 861 * 862 * This method MUST be "non-blocking" and return within 1ms. 863 * 864 * \return a local ID for this block pool. 865 */ 866 virtual local_id_t getLocalId() const = 0; 867 868 /** 869 * Returns the ID of the backing allocator of this block pool. 870 * 871 * This method MUST be "non-blocking" and return within 1ms. 872 * 873 * \return the ID of the backing allocator of this block pool. 874 */ 875 virtual C2Allocator::id_t getAllocatorId() const = 0; 876 877 /** 878 * Obtains a linear writeable block of given |capacity| and |usage|. If successful, the 879 * block is stored in |block|. Otherwise, |block| is set to 'nullptr'. 880 * 881 * \param capacity the size of requested block. 882 * \param usage the memory usage info for the requested block. Returned blocks will be 883 * optimized for this usage, but may be used with any usage. One exception: 884 * protected blocks/buffers can only be used in a protected scenario. 885 * \param block pointer to where the obtained block shall be stored on success. nullptr will 886 * be stored here on failure 887 * 888 * \retval C2_OK the operation was successful 889 * \retval C2_NO_MEMORY not enough memory to complete any required allocation 890 * \retval C2_TIMED_OUT the operation timed out 891 * \retval C2_REFUSED no permission to complete any required allocation 892 * \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error) 893 * \retval C2_OMITTED this pool does not support linear blocks 894 * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected) 895 */ fetchLinearBlock(uint32_t capacity __unused,C2MemoryUsage usage __unused,std::shared_ptr<C2LinearBlock> * block)896 virtual c2_status_t fetchLinearBlock( 897 uint32_t capacity __unused, C2MemoryUsage usage __unused, 898 std::shared_ptr<C2LinearBlock> *block /* nonnull */) { 899 *block = nullptr; 900 return C2_OMITTED; 901 } 902 903 /** 904 * Obtains a circular writeable block of given |capacity| and |usage|. If successful, the 905 * block is stored in |block|. Otherwise, |block| is set to 'nullptr'. 906 * 907 * \param capacity the size of requested circular block. (note: the size of the obtained 908 * block could be slightly larger, e.g. to accommodate any system-required 909 * alignment) 910 * \param usage the memory usage info for the requested block. Returned blocks will be 911 * optimized for this usage, but may be used with any usage. One exception: 912 * protected blocks/buffers can only be used in a protected scenario. 913 * \param block pointer to where the obtained block shall be stored on success. nullptr 914 * will be stored here on failure 915 * 916 * \retval C2_OK the operation was successful 917 * \retval C2_NO_MEMORY not enough memory to complete any required allocation 918 * \retval C2_TIMED_OUT the operation timed out 919 * \retval C2_REFUSED no permission to complete any required allocation 920 * \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error) 921 * \retval C2_OMITTED this pool does not support circular blocks 922 * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected) 923 */ fetchCircularBlock(uint32_t capacity __unused,C2MemoryUsage usage __unused,std::shared_ptr<C2CircularBlock> * block)924 virtual c2_status_t fetchCircularBlock( 925 uint32_t capacity __unused, C2MemoryUsage usage __unused, 926 std::shared_ptr<C2CircularBlock> *block /* nonnull */) { 927 *block = nullptr; 928 return C2_OMITTED; 929 } 930 931 /** 932 * Obtains a 2D graphic block of given |width|, |height|, |format| and |usage|. If successful, 933 * the block is stored in |block|. Otherwise, |block| is set to 'nullptr'. 934 * 935 * \param width the width of requested block (the obtained block could be slightly larger, e.g. 936 * to accommodate any system-required alignment) 937 * \param height the height of requested block (the obtained block could be slightly larger, 938 * e.g. to accommodate any system-required alignment) 939 * \param format the pixel format of requested block. This could be a vendor specific format. 940 * \param usage the memory usage info for the requested block. Returned blocks will be 941 * optimized for this usage, but may be used with any usage. One exception: 942 * protected blocks/buffers can only be used in a protected scenario. 943 * \param block pointer to where the obtained block shall be stored on success. nullptr 944 * will be stored here on failure 945 * 946 * \retval C2_OK the operation was successful 947 * \retval C2_NO_MEMORY not enough memory to complete any required allocation 948 * \retval C2_TIMED_OUT the operation timed out 949 * \retval C2_REFUSED no permission to complete any required allocation 950 * \retval C2_BAD_VALUE width, height, format or usage are not supported (invalid) (caller 951 * error) 952 * \retval C2_OMITTED this pool does not support 2D blocks 953 * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected) 954 */ fetchGraphicBlock(uint32_t width __unused,uint32_t height __unused,uint32_t format __unused,C2MemoryUsage usage __unused,std::shared_ptr<C2GraphicBlock> * block)955 virtual c2_status_t fetchGraphicBlock( 956 uint32_t width __unused, uint32_t height __unused, uint32_t format __unused, 957 C2MemoryUsage usage __unused, 958 std::shared_ptr<C2GraphicBlock> *block /* nonnull */) { 959 *block = nullptr; 960 return C2_OMITTED; 961 } 962 963 virtual ~C2BlockPool() = default; 964 protected: 965 C2BlockPool() = default; 966 }; 967 968 /// @} 969 970 // ================================================================================================ 971 // BLOCKS 972 // ================================================================================================ 973 974 /** 975 * Blocks are sections of allocations. They can be either 1D or 2D. 976 */ 977 978 class C2LinearAllocation; 979 980 /** 981 * A 1D block. 982 * 983 * \note capacity() is not meaningful for users of blocks; instead size() is the capacity of the 984 * usable portion. Use and offset() and size() if accessing the block directly through its handle 985 * to represent the allotted range of the underlying allocation to this block. 986 */ 987 class C2Block1D : public _C2LinearRangeAspect { 988 public: 989 /** 990 * Returns the underlying handle for this allocation. 991 * 992 * \note that the block and its block pool has shared ownership of the handle 993 * and if all references to the block are released, the underlying block 994 * allocation may get reused even if a client keeps a clone of this handle. 995 */ 996 const C2Handle *handle() const; 997 998 /** 999 * Returns the allocator's ID that created the underlying allocation for this block. This 1000 * provides the context for understanding the handle. 1001 */ 1002 C2Allocator::id_t getAllocatorId() const; 1003 1004 protected: 1005 class Impl; 1006 /** construct a block. */ 1007 C2Block1D(std::shared_ptr<Impl> impl, const _C2LinearRangeAspect &range); 1008 1009 friend struct _C2BlockFactory; 1010 std::shared_ptr<Impl> mImpl; 1011 }; 1012 1013 /** 1014 * Read view provides read-only access for a linear memory segment. 1015 * 1016 * This class is copiable. 1017 */ 1018 class C2ReadView : public _C2LinearCapacityAspect { 1019 public: 1020 /** 1021 * \return pointer to the start of the block or nullptr on error. 1022 * This pointer is only valid during the lifetime of this view or until it is released. 1023 */ 1024 const uint8_t *data() const; 1025 1026 /** 1027 * Returns a portion of this view. 1028 * 1029 * \param offset the start offset of the portion. \note This is clamped to the capacity of this 1030 * view. 1031 * \param size the size of the portion. \note This is clamped to the remaining data from offset. 1032 * 1033 * \return a read view containing a portion of this view 1034 */ 1035 C2ReadView subView(size_t offset, size_t size) const; 1036 1037 /** 1038 * \return error during the creation/mapping of this view. 1039 */ 1040 c2_status_t error() const; 1041 1042 /** 1043 * Releases this view. This sets error to C2_NO_INIT. 1044 */ 1045 //void release(); 1046 1047 protected: 1048 class Impl; 1049 C2ReadView(std::shared_ptr<Impl> impl, uint32_t offset, uint32_t size); 1050 explicit C2ReadView(c2_status_t error); 1051 1052 private: 1053 friend struct _C2BlockFactory; 1054 std::shared_ptr<Impl> mImpl; 1055 uint32_t mOffset; /**< offset into the linear block backing this read view */ 1056 }; 1057 1058 /** 1059 * Write view provides read/write access for a linear memory segment. 1060 * 1061 * This class is copiable. \todo movable only? 1062 */ 1063 class C2WriteView : public _C2EditableLinearRangeAspect { 1064 public: 1065 /** 1066 * Start of the block. 1067 * 1068 * \return pointer to the start of the block or nullptr on error. 1069 * This pointer is only valid during the lifetime of this view or until it is released. 1070 */ 1071 uint8_t *base(); 1072 1073 /** 1074 * \return pointer to the block at the current offset or nullptr on error. 1075 * This pointer is only valid during the lifetime of this view or until it is released. 1076 */ 1077 uint8_t *data(); 1078 1079 /** 1080 * \return error during the creation/mapping of this view. 1081 */ 1082 c2_status_t error() const; 1083 1084 /** 1085 * Releases this view. This sets error to C2_NO_INIT. 1086 */ 1087 //void release(); 1088 1089 protected: 1090 class Impl; 1091 C2WriteView(std::shared_ptr<Impl> impl); 1092 explicit C2WriteView(c2_status_t error); 1093 1094 private: 1095 friend struct _C2BlockFactory; 1096 std::shared_ptr<Impl> mImpl; 1097 }; 1098 1099 /** 1100 * A constant (read-only) linear block (portion of an allocation) with an acquire fence. 1101 * Blocks are unmapped when created, and can be mapped into a read view on demand. 1102 * 1103 * This class is copiable and contains a reference to the allocation that it is based on. 1104 */ 1105 class C2ConstLinearBlock : public C2Block1D { 1106 public: 1107 /** 1108 * Maps this block into memory and returns a read view for it. 1109 * 1110 * \return a read view for this block. 1111 */ 1112 C2Acquirable<C2ReadView> map() const; 1113 1114 /** 1115 * Returns a portion of this block. 1116 * 1117 * \param offset the start offset of the portion. \note This is clamped to the capacity of this 1118 * block. 1119 * \param size the size of the portion. \note This is clamped to the remaining data from offset. 1120 * 1121 * \return a constant linear block containing a portion of this block 1122 */ 1123 C2ConstLinearBlock subBlock(size_t offset, size_t size) const; 1124 1125 /** 1126 * Returns the acquire fence for this block. 1127 * 1128 * \return a fence that must be waited on before reading the block. 1129 */ fence()1130 C2Fence fence() const { return mFence; } 1131 1132 protected: 1133 C2ConstLinearBlock(std::shared_ptr<Impl> impl, const _C2LinearRangeAspect &range, C2Fence mFence); 1134 1135 private: 1136 friend struct _C2BlockFactory; 1137 C2Fence mFence; 1138 }; 1139 1140 /** 1141 * Linear block is a writeable 1D block. Once written, it can be shared in whole or in parts with 1142 * consumers/readers as read-only const linear block(s). 1143 */ 1144 class C2LinearBlock : public C2Block1D { 1145 public: 1146 /** 1147 * Maps this block into memory and returns a write view for it. 1148 * 1149 * \return a write view for this block. 1150 */ 1151 C2Acquirable<C2WriteView> map(); 1152 1153 /** 1154 * Creates a read-only const linear block for a portion of this block; optionally protected 1155 * by an acquire fence. There are two ways to use this: 1156 * 1157 * 1) share ready block after writing data into the block. In this case no fence shall be 1158 * supplied, and the block shall not be modified after calling this method. 1159 * 2) share block metadata before actually (finishing) writing the data into the block. In 1160 * this case a fence must be supplied that will be triggered when the data is written. 1161 * The block shall be modified only until firing the event for the fence. 1162 */ 1163 C2ConstLinearBlock share(size_t offset, size_t size, C2Fence fence); 1164 1165 protected: 1166 C2LinearBlock(std::shared_ptr<Impl> impl, const _C2LinearRangeAspect &range); 1167 1168 friend struct _C2BlockFactory; 1169 }; 1170 1171 /// @} 1172 1173 /************************************************************************************************** 1174 CIRCULAR BLOCKS AND VIEWS 1175 **************************************************************************************************/ 1176 1177 /// \defgroup circular Circular buffer support 1178 /// @{ 1179 1180 /** 1181 * Circular blocks can be used to share data between a writer and a reader (and/or other consumers)- 1182 * in a memory-efficient way by reusing a section of memory. Circular blocks are a bit more complex 1183 * than single reader/single writer schemes to facilitate block-based consuming of data. 1184 * 1185 * They can operate in two modes: 1186 * 1187 * 1) one writer that creates blocks to be consumed (this model can be used by components) 1188 * 1189 * 2) one writer that writes continuously, and one reader that can creates blocks to be consumed 1190 * by further recipients (this model is used by the framework, and cannot be used by components.) 1191 * 1192 * Circular blocks have four segments with running pointers: 1193 * - reserved: data reserved and available for the writer 1194 * - committed: data committed by the writer and available to the reader (if present) 1195 * - used: data used by consumers (if present) 1196 * - available: unused data available to be reserved 1197 */ 1198 class C2CircularBlock : public C2Block1D { 1199 // TODO: add methods 1200 1201 private: 1202 size_t mReserved __unused; // end of reserved section 1203 size_t mCommitted __unused; // end of committed section 1204 size_t mUsed __unused; // end of used section 1205 size_t mFree __unused; // end of free section 1206 }; 1207 1208 class _C2CircularBlockSegment : public _C2LinearCapacityAspect { 1209 public: 1210 /** 1211 * Returns the available size for this segment. 1212 * 1213 * \return currently available size for this segment 1214 */ 1215 size_t available() const; 1216 1217 /** 1218 * Reserve some space for this segment from its current start. 1219 * 1220 * \param size desired space in bytes 1221 * \param fence a pointer to an acquire fence. If non-null, the reservation is asynchronous and 1222 * a fence will be stored here that will be signaled when the reservation is 1223 * complete. If null, the reservation is synchronous. 1224 * 1225 * \retval C2_OK the space was successfully reserved 1226 * \retval C2_NO_MEMORY the space requested cannot be reserved 1227 * \retval C2_TIMED_OUT the reservation timed out \todo when? 1228 * \retval C2_CORRUPTED some unknown error prevented reserving space. (unexpected) 1229 */ 1230 c2_status_t reserve(size_t size, C2Fence *fence /* nullable */); 1231 1232 /** 1233 * Abandons a portion of this segment. This will move to the beginning of this segment. 1234 * 1235 * \note This methods is only allowed if this segment is producing blocks. 1236 * 1237 * \param size number of bytes to abandon 1238 * 1239 * \retval C2_OK the data was successfully abandoned 1240 * \retval C2_TIMED_OUT the operation timed out (unexpected) 1241 * \retval C2_CORRUPTED some unknown error prevented abandoning the data (unexpected) 1242 */ 1243 c2_status_t abandon(size_t size); 1244 1245 /** 1246 * Share a portion as block(s) with consumers (these are moved to the used section). 1247 * 1248 * \note This methods is only allowed if this segment is producing blocks. 1249 * \note Share does not move the beginning of the segment. (\todo add abandon/offset?) 1250 * 1251 * \param size number of bytes to share 1252 * \param fence fence to be used for the section 1253 * \param blocks vector where the blocks of the section are appended to 1254 * 1255 * \retval C2_OK the portion was successfully shared 1256 * \retval C2_NO_MEMORY not enough memory to share the portion 1257 * \retval C2_TIMED_OUT the operation timed out (unexpected) 1258 * \retval C2_CORRUPTED some unknown error prevented sharing the data (unexpected) 1259 */ 1260 c2_status_t share(size_t size, C2Fence fence, std::vector<C2ConstLinearBlock> &blocks); 1261 1262 /** 1263 * Returns the beginning offset of this segment from the start of this circular block. 1264 * 1265 * @return beginning offset 1266 */ 1267 size_t begin(); 1268 1269 /** 1270 * Returns the end offset of this segment from the start of this circular block. 1271 * 1272 * @return end offset 1273 */ 1274 size_t end(); 1275 }; 1276 1277 /** 1278 * A circular write-view is a dynamic mapped view for a segment of a circular block. Care must be 1279 * taken when using this view so that only the section owned by the segment is modified. 1280 */ 1281 class C2CircularWriteView : public _C2LinearCapacityAspect { 1282 public: 1283 /** 1284 * Start of the circular block. 1285 * \note the segment does not own this pointer. 1286 * 1287 * \return pointer to the start of the circular block or nullptr on error. 1288 */ 1289 uint8_t *base(); 1290 1291 /** 1292 * \return error during the creation/mapping of this view. 1293 */ 1294 c2_status_t error() const; 1295 }; 1296 1297 /** 1298 * The writer of a circular buffer. 1299 * 1300 * Can commit data to a reader (not supported for components) OR share data blocks directly with a 1301 * consumer. 1302 * 1303 * If a component supports outputting data into circular buffers, it must allocate a circular 1304 * block and use a circular writer. 1305 */ 1306 class C2CircularWriter : public _C2CircularBlockSegment { 1307 public: 1308 /** 1309 * Commits a portion of this segment to the next segment. This moves the beginning of the 1310 * segment. 1311 * 1312 * \param size number of bytes to commit to the next segment 1313 * \param fence fence used for the commit (the fence must signal before the data is committed) 1314 */ 1315 c2_status_t commit(size_t size, C2Fence fence); 1316 1317 /** 1318 * Maps this block into memory and returns a write view for it. 1319 * 1320 * \return a write view for this block. 1321 */ 1322 C2Acquirable<C2CircularWriteView> map(); 1323 }; 1324 1325 /// @} 1326 1327 /// \defgroup graphic Graphic Data Blocks 1328 /// @{ 1329 1330 /** 1331 * C2Rect: rectangle type with non-negative coordinates. 1332 * 1333 * \note This struct has public fields without getters/setters. All methods are inline. 1334 */ 1335 struct C2Rect { 1336 // public: 1337 uint32_t width; 1338 uint32_t height; 1339 uint32_t left; 1340 uint32_t top; 1341 C2RectC2Rect1342 constexpr inline C2Rect() 1343 : C2Rect(0, 0, 0, 0) { } 1344 C2RectC2Rect1345 constexpr inline C2Rect(uint32_t width_, uint32_t height_) 1346 : C2Rect(width_, height_, 0, 0) { } 1347 atC2Rect1348 constexpr C2Rect inline at(uint32_t left_, uint32_t top_) const { 1349 return C2Rect(width, height, left_, top_); 1350 } 1351 1352 // utility methods 1353 isEmptyC2Rect1354 inline constexpr bool isEmpty() const { 1355 return width == 0 || height == 0; 1356 } 1357 isValidC2Rect1358 inline constexpr bool isValid() const { 1359 return left <= ~width && top <= ~height; 1360 } 1361 1362 inline constexpr operator bool() const { 1363 return isValid() && !isEmpty(); 1364 } 1365 1366 inline constexpr bool operator!() const { 1367 return !bool(*this); 1368 } 1369 1370 C2_ALLOW_OVERFLOW containsC2Rect1371 inline constexpr bool contains(const C2Rect &other) const { 1372 if (!isValid() || !other.isValid()) { 1373 return false; 1374 } else { 1375 return left <= other.left && top <= other.top 1376 && left + width >= other.left + other.width 1377 && top + height >= other.top + other.height; 1378 } 1379 } 1380 1381 inline constexpr bool operator==(const C2Rect &other) const { 1382 if (!isValid()) { 1383 return !other.isValid(); 1384 } else { 1385 return left == other.left && top == other.top 1386 && width == other.width && height == other.height; 1387 } 1388 } 1389 1390 inline constexpr bool operator!=(const C2Rect &other) const { 1391 return !operator==(other); 1392 } 1393 1394 inline constexpr bool operator>=(const C2Rect &other) const { 1395 return contains(other); 1396 } 1397 1398 inline constexpr bool operator>(const C2Rect &other) const { 1399 return contains(other) && !operator==(other); 1400 } 1401 1402 inline constexpr bool operator<=(const C2Rect &other) const { 1403 return other.contains(*this); 1404 } 1405 1406 inline constexpr bool operator<(const C2Rect &other) const { 1407 return other.contains(*this) && !operator==(other); 1408 } 1409 1410 C2_ALLOW_OVERFLOW rightC2Rect1411 inline constexpr uint32_t right() const { 1412 return left + width; 1413 } 1414 1415 C2_ALLOW_OVERFLOW bottomC2Rect1416 inline constexpr uint32_t bottom() const { 1417 return top + height; 1418 } 1419 1420 C2_ALLOW_OVERFLOW intersectC2Rect1421 inline constexpr C2Rect intersect(const C2Rect &other) const { 1422 return C2Rect(c2_min(right(), other.right()) - c2_max(left, other.left), 1423 c2_min(bottom(), other.bottom()) - c2_max(top, other.top), 1424 c2_max(left, other.left), 1425 c2_max(top, other.top)); 1426 } 1427 1428 /** clamps right and bottom to top, left if they overflow */ normalizeC2Rect1429 inline constexpr C2Rect normalize() const { 1430 return C2Rect(c2_max(left, right()) - left, c2_max(top, bottom()) - top, left, top); 1431 } 1432 1433 private: 1434 /// note: potentially unusual argument order C2RectC2Rect1435 constexpr inline C2Rect(uint32_t width_, uint32_t height_, uint32_t left_, uint32_t top_) 1436 : width(width_), 1437 height(height_), 1438 left(left_), 1439 top(top_) { } 1440 }; 1441 1442 /** 1443 * Interface for objects that have a width and height (planar capacity). 1444 */ 1445 class _C2PlanarCapacityAspect { 1446 /// \name Planar capacity interface 1447 /// @{ 1448 public: width()1449 inline constexpr uint32_t width() const { return _mWidth; } height()1450 inline constexpr uint32_t height() const { return _mHeight; } 1451 C2Rect()1452 inline constexpr operator C2Rect() const { 1453 return C2Rect(_mWidth, _mHeight); 1454 } 1455 1456 protected: _C2PlanarCapacityAspect(uint32_t width,uint32_t height)1457 inline constexpr _C2PlanarCapacityAspect(uint32_t width, uint32_t height) 1458 : _mWidth(width), _mHeight(height) { } 1459 _C2PlanarCapacityAspect(const _C2PlanarCapacityAspect * parent)1460 inline explicit constexpr _C2PlanarCapacityAspect(const _C2PlanarCapacityAspect *parent) 1461 : _mWidth(parent == nullptr ? 0 : parent->width()), 1462 _mHeight(parent == nullptr ? 0 : parent->height()) { } 1463 1464 private: 1465 uint32_t _mWidth; 1466 uint32_t _mHeight; 1467 /// @} 1468 }; 1469 1470 /** 1471 * C2PlaneInfo: information on the layout of a singe flexible plane. 1472 * 1473 * Public fields without getters/setters. 1474 */ 1475 struct C2PlaneInfo { 1476 //public: 1477 enum channel_t : uint32_t { 1478 CHANNEL_Y, ///< luma 1479 CHANNEL_R, ///< red 1480 CHANNEL_G, ///< green 1481 CHANNEL_B, ///< blue 1482 CHANNEL_A, ///< alpha 1483 CHANNEL_CR, ///< Cr 1484 CHANNEL_CB, ///< Cb 1485 } channel; 1486 1487 int32_t colInc; ///< column increment in bytes. may be negative 1488 int32_t rowInc; ///< row increment in bytes. may be negative 1489 1490 uint32_t colSampling; ///< subsampling compared to width (must be a power of 2) 1491 uint32_t rowSampling; ///< subsampling compared to height (must be a power of 2) 1492 1493 uint32_t allocatedDepth; ///< size of each sample (must be a multiple of 8) 1494 uint32_t bitDepth; ///< significant bits per sample 1495 /** 1496 * the right shift of the significant bits in the sample. E.g. if a 10-bit significant 1497 * value is laid out in a 16-bit allocation aligned to LSB (values 0-1023), rightShift 1498 * would be 0 as the 16-bit value read from the sample does not need to be right shifted 1499 * and can be used as is (after applying a 10-bit mask of 0x3FF). 1500 * 1501 * +--------+--------+ 1502 * | VV|VVVVVVVV| 1503 * +--------+--------+ 1504 * 15 8 7 0 1505 * 1506 * If the value is laid out aligned to MSB, rightShift would be 6, as the value read 1507 * from the allocated sample must be right-shifted by 6 to get the actual sample value. 1508 * 1509 * +--------+--------+ 1510 * |VVVVVVVV|VV | 1511 * +--------+--------+ 1512 * 15 8 7 0 1513 */ 1514 uint32_t rightShift; 1515 1516 enum endianness_t : uint32_t { 1517 NATIVE, 1518 LITTLE_END, // LITTLE_ENDIAN is reserved macro 1519 BIG_END, // BIG_ENDIAN is a reserved macro 1520 } endianness; ///< endianness of the samples 1521 1522 /** 1523 * The following two fields define the relation between multiple planes. If multiple planes are 1524 * interleaved, they share a root plane (whichever plane's start address is the lowest), and 1525 * |offset| is the offset of this plane inside the root plane (in bytes). |rootIx| is the index 1526 * of the root plane. If a plane is independent, rootIx is its index and offset is 0. 1527 */ 1528 uint32_t rootIx; ///< index of the root plane 1529 uint32_t offset; ///< offset of this plane inside of the root plane 1530 minOffsetC2PlaneInfo1531 inline constexpr ssize_t minOffset(uint32_t width, uint32_t height) const { 1532 ssize_t offs = 0; 1533 if (width > 0 && colInc < 0) { 1534 offs += colInc * (ssize_t)(width - 1); 1535 } 1536 if (height > 0 && rowInc < 0) { 1537 offs += rowInc * (ssize_t)(height - 1); 1538 } 1539 return offs; 1540 } 1541 maxOffsetC2PlaneInfo1542 inline constexpr ssize_t maxOffset(uint32_t width, uint32_t height) const { 1543 ssize_t offs = (allocatedDepth + 7) >> 3; 1544 if (width > 0 && colInc > 0) { 1545 offs += colInc * (ssize_t)(width - 1); 1546 } 1547 if (height > 0 && rowInc > 0) { 1548 offs += rowInc * (ssize_t)(height - 1); 1549 } 1550 return offs; 1551 } 1552 } C2_PACK; 1553 1554 struct C2PlanarLayout { 1555 //public: 1556 enum type_t : uint32_t { 1557 TYPE_UNKNOWN = 0, 1558 TYPE_YUV = 0x100, ///< YUV image with 3 planes 1559 TYPE_YUVA, ///< YUVA image with 4 planes 1560 TYPE_RGB, ///< RGB image with 3 planes 1561 TYPE_RGBA, ///< RBGA image with 4 planes 1562 }; 1563 1564 type_t type; // image type 1565 uint32_t numPlanes; // number of component planes 1566 uint32_t rootPlanes; // number of layout planes (root planes) 1567 1568 enum plane_index_t : uint32_t { 1569 PLANE_Y = 0, 1570 PLANE_U = 1, 1571 PLANE_V = 2, 1572 PLANE_R = 0, 1573 PLANE_G = 1, 1574 PLANE_B = 2, 1575 PLANE_A = 3, 1576 MAX_NUM_PLANES = 4, 1577 }; 1578 1579 C2PlaneInfo planes[MAX_NUM_PLANES]; 1580 }; 1581 1582 /** 1583 * Aspect for objects that have a planar section (crop rectangle). 1584 * 1585 * This class is copiable. 1586 */ 1587 class _C2PlanarSectionAspect : public _C2PlanarCapacityAspect { 1588 /// \name Planar section interface 1589 /// @{ 1590 private: _C2PlanarSectionAspect(uint32_t width,uint32_t height,const C2Rect & crop)1591 inline constexpr _C2PlanarSectionAspect(uint32_t width, uint32_t height, const C2Rect &crop) 1592 : _C2PlanarCapacityAspect(width, height), 1593 mCrop(C2Rect(std::min(width - std::min(crop.left, width), crop.width), 1594 std::min(height - std::min(crop.top, height), crop.height)).at( 1595 std::min(crop.left, width), 1596 std::min(crop.height, height))) { 1597 } 1598 1599 public: 1600 // crop can be an empty rect, does not have to line up with subsampling 1601 // NOTE: we do not support floating-point crop crop()1602 inline constexpr C2Rect crop() const { return mCrop; } 1603 1604 /** 1605 * Returns a child planar section for |crop|, where the capacity represents this section. 1606 */ childSection(const C2Rect & crop)1607 inline constexpr _C2PlanarSectionAspect childSection(const C2Rect &crop) const { 1608 return _C2PlanarSectionAspect( 1609 mCrop.width, mCrop.height, 1610 // crop and translate |crop| rect 1611 C2Rect(c2_min(mCrop.right() - c2_clamp(mCrop.left, crop.left, mCrop.right()), 1612 crop.width), 1613 c2_min(mCrop.bottom() - c2_clamp(mCrop.top, crop.top, mCrop.bottom()), 1614 crop.height)) 1615 .at(c2_clamp(mCrop.left, crop.left, mCrop.right()) - mCrop.left, 1616 c2_clamp(mCrop.top, crop.top, mCrop.bottom()) - mCrop.top)); 1617 } 1618 1619 protected: _C2PlanarSectionAspect(const _C2PlanarCapacityAspect * parent)1620 inline constexpr _C2PlanarSectionAspect(const _C2PlanarCapacityAspect *parent) 1621 : _C2PlanarCapacityAspect(parent), mCrop(width(), height()) {} 1622 _C2PlanarSectionAspect(const _C2PlanarCapacityAspect * parent,const C2Rect & crop)1623 inline constexpr _C2PlanarSectionAspect(const _C2PlanarCapacityAspect *parent, const C2Rect &crop) 1624 : _C2PlanarCapacityAspect(parent), 1625 mCrop(parent == nullptr ? C2Rect() : ((C2Rect)*parent).intersect(crop).normalize()) { } 1626 _C2PlanarSectionAspect(const _C2PlanarSectionAspect * parent,const C2Rect & crop)1627 inline constexpr _C2PlanarSectionAspect(const _C2PlanarSectionAspect *parent, const C2Rect &crop) 1628 : _C2PlanarCapacityAspect(parent), 1629 mCrop(parent == nullptr ? C2Rect() : parent->crop().intersect(crop).normalize()) { } 1630 1631 private: 1632 friend class _C2EditablePlanarSectionAspect; 1633 C2Rect mCrop; 1634 /// @} 1635 }; 1636 1637 /** 1638 * Aspect for objects that have an editable planar section (crop rectangle). 1639 * 1640 * This class is copiable. 1641 */ 1642 class _C2EditablePlanarSectionAspect : public _C2PlanarSectionAspect { 1643 /// \name Planar section interface 1644 /// @{ 1645 using _C2PlanarSectionAspect::_C2PlanarSectionAspect; 1646 1647 public: 1648 // crop can be an empty rect, does not have to line up with subsampling 1649 // NOTE: we do not support floating-point crop crop()1650 inline constexpr C2Rect crop() const { return mCrop; } 1651 1652 /** 1653 * Sets crop to crop intersected with [(0,0) .. (width, height)] 1654 */ setCrop_be(const C2Rect & crop)1655 inline void setCrop_be(const C2Rect &crop) { 1656 mCrop.left = std::min(width(), crop.left); 1657 mCrop.top = std::min(height(), crop.top); 1658 // It's guaranteed that mCrop.left <= width() && mCrop.top <= height() 1659 mCrop.width = std::min(width() - mCrop.left, crop.width); 1660 mCrop.height = std::min(height() - mCrop.top, crop.height); 1661 } 1662 1663 /** 1664 * If crop is within the dimensions of this object, it sets crop to it. 1665 * 1666 * \return true iff crop is within the dimensions of this object 1667 */ setCrop(const C2Rect & crop)1668 inline bool setCrop(const C2Rect &crop) { 1669 if (width() < crop.width || height() < crop.height 1670 || width() - crop.width < crop.left || height() - crop.height < crop.top) { 1671 return false; 1672 } 1673 mCrop = crop; 1674 return true; 1675 } 1676 /// @} 1677 }; 1678 1679 /** 1680 * Utility class for safe range calculations using size_t-s. 1681 */ 1682 class C2PlanarSection : public _C2PlanarSectionAspect { 1683 public: C2PlanarSection(const _C2PlanarCapacityAspect & parent,const C2Rect & crop)1684 inline constexpr C2PlanarSection(const _C2PlanarCapacityAspect &parent, const C2Rect &crop) 1685 : _C2PlanarSectionAspect(&parent, crop) { } 1686 C2PlanarSection(const _C2PlanarSectionAspect & parent,const C2Rect & crop)1687 inline constexpr C2PlanarSection(const _C2PlanarSectionAspect &parent, const C2Rect &crop) 1688 : _C2PlanarSectionAspect(&parent, crop) { } 1689 intersect(const C2Rect & crop)1690 inline constexpr C2PlanarSection intersect(const C2Rect &crop) const { 1691 return C2PlanarSection(*this, crop); 1692 } 1693 }; 1694 1695 /** 1696 * Utility class for simple and safe planar capacity and section construction. 1697 */ 1698 class C2PlanarCapacity : public _C2PlanarCapacityAspect { 1699 public: C2PlanarCapacity(size_t width,size_t height)1700 inline constexpr explicit C2PlanarCapacity(size_t width, size_t height) 1701 : _C2PlanarCapacityAspect(c2_min(width, std::numeric_limits<uint32_t>::max()), 1702 c2_min(height, std::numeric_limits<uint32_t>::max())) { } 1703 section(const C2Rect & crop)1704 inline constexpr C2PlanarSection section(const C2Rect &crop) const { 1705 return C2PlanarSection(*this, crop); 1706 } 1707 }; 1708 1709 1710 /** 1711 * \ingroup graphic allocator 1712 * 2D allocation interface. 1713 */ 1714 class C2GraphicAllocation : public _C2PlanarCapacityAspect { 1715 public: 1716 /** 1717 * Maps a rectangular section (as defined by |rect|) of a 2D allocation into local process 1718 * memory for flexible access. On success, it fills out |layout| with the plane specifications 1719 * and fills the |addr| array with pointers to the first byte of the top-left pixel of each 1720 * plane used. Otherwise, it leaves |layout| and |addr| untouched. |fence| will contain 1721 * an acquire sync fence object. If it is already safe to access the 1722 * buffer contents, then it will be an empty (already fired) fence. 1723 * 1724 * Safe regions for the pointer addresses returned can be gotten via C2LayoutInfo.minOffset()/ 1725 * maxOffset(). 1726 * 1727 * \param rect section to be mapped (this does not have to be aligned) 1728 * \param usage the desired usage. \todo this must be kSoftwareRead and/or 1729 * kSoftwareWrite. 1730 * \param fence a pointer to a fence object if an async mapping is requested. If 1731 * not-null, and acquire fence will be stored here on success, or empty 1732 * fence on failure. If null, the mapping will be synchronous. 1733 * \param layout a pointer to where the mapped planes' descriptors will be 1734 * stored. On failure, nullptr will be stored here. 1735 * \param addr pointer to an array with at least C2PlanarLayout::MAX_NUM_PLANES 1736 * elements. Only layout.numPlanes elements will be modified on success. 1737 * 1738 * \retval C2_OK the operation was successful 1739 * \retval C2_REFUSED no permission to map the section 1740 * \retval C2_DUPLICATE there is already a mapped region and this allocation cannot support 1741 * multi-mapping (caller error) 1742 * \retval C2_TIMED_OUT the operation timed out 1743 * \retval C2_NO_MEMORY not enough memory to complete the operation 1744 * \retval C2_BAD_VALUE the parameters (rect) are invalid or outside the allocation, or the 1745 * usage flags are invalid (caller error) 1746 * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected) 1747 1748 */ 1749 virtual c2_status_t map( 1750 C2Rect rect, C2MemoryUsage usage, C2Fence *fence, 1751 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) = 0; 1752 1753 /** 1754 * Unmaps a section of an allocation at |addr| with |rect|. These must be parameters previously 1755 * passed to and returned by |map|; otherwise, this operation is a no-op. 1756 * 1757 * \param addr pointer to an array with at least C2PlanarLayout::MAX_NUM_PLANES 1758 * elements containing the starting addresses of the mapped layers 1759 * \param rect boundaries of the mapped section 1760 * \param fence a pointer to a fence object if an async unmapping is requested. If 1761 * not-null, a release fence will be stored here on success, or empty fence 1762 * on failure. This fence signals when the original allocation contains 1763 * all changes that happened to the mapped section. If null, the unmapping 1764 * will be synchronous. 1765 * 1766 * \retval C2_OK the operation was successful 1767 * \retval C2_TIMED_OUT the operation timed out 1768 * \retval C2_NOT_FOUND there is no such mapped region (caller error) 1769 * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected) 1770 * \retval C2_REFUSED no permission to unmap the section (unexpected - system) 1771 */ 1772 virtual c2_status_t unmap( 1773 uint8_t **addr /* nonnull */, C2Rect rect, C2Fence *fence /* nullable */) = 0; 1774 1775 /** 1776 * Returns the allocator ID for this allocation. This is useful to put the handle into context. 1777 */ 1778 virtual C2Allocator::id_t getAllocatorId() const = 0; 1779 1780 /** 1781 * Returns a pointer to the allocation handle. 1782 */ 1783 virtual const C2Handle *handle() const = 0; 1784 1785 /** 1786 * Returns true if this is the same allocation as |other|. 1787 */ 1788 virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const = 0; 1789 1790 protected: 1791 using _C2PlanarCapacityAspect::_C2PlanarCapacityAspect; 1792 virtual ~C2GraphicAllocation() = default; 1793 }; 1794 1795 class C2GraphicAllocation; 1796 1797 /** 1798 * A 2D block. 1799 * 1800 * \note width()/height() is not meaningful for users of blocks; instead, crop().width() and 1801 * crop().height() is the capacity of the usable portion. Use and crop() if accessing the block 1802 * directly through its handle to represent the allotted region of the underlying allocation to this 1803 * block. 1804 */ 1805 class C2Block2D : public _C2PlanarSectionAspect { 1806 public: 1807 /** 1808 * Returns the underlying handle for this allocation. 1809 * 1810 * \note that the block and its block pool has shared ownership of the handle 1811 * and if all references to the block are released, the underlying block 1812 * allocation may get reused even if a client keeps a clone of this handle. 1813 */ 1814 const C2Handle *handle() const; 1815 1816 /** 1817 * Returns the allocator's ID that created the underlying allocation for this block. This 1818 * provides the context for understanding the handle. 1819 */ 1820 C2Allocator::id_t getAllocatorId() const; 1821 1822 protected: 1823 class Impl; 1824 C2Block2D(std::shared_ptr<Impl> impl, const _C2PlanarSectionAspect §ion); 1825 1826 friend struct _C2BlockFactory; 1827 std::shared_ptr<Impl> mImpl; 1828 }; 1829 1830 /** 1831 * Graphic view provides read or read-write access for a graphic block. 1832 * 1833 * This class is copiable. 1834 * 1835 * \note Due to the subsampling of graphic buffers, a read view must still contain a crop rectangle 1836 * to ensure subsampling is followed. This results in nearly identical interface between read and 1837 * write views, so C2GraphicView can encompass both of them. 1838 */ 1839 class C2GraphicView : public _C2EditablePlanarSectionAspect { 1840 public: 1841 /** 1842 * \return array of pointers (of layout().numPlanes elements) to the start of the planes or 1843 * nullptr on error. Regardless of crop rect, they always point to the top-left corner of each 1844 * plane. Access outside of the crop rect results in an undefined behavior. 1845 */ 1846 const uint8_t *const *data() const; 1847 1848 /** 1849 * \return array of pointers (of layout().numPlanes elements) to the start of the planes or 1850 * nullptr on error. Regardless of crop rect, they always point to the top-left corner of each 1851 * plane. Access outside of the crop rect results in an undefined behavior. 1852 */ 1853 uint8_t *const *data(); 1854 1855 /** 1856 * \return layout of the graphic block to interpret the returned data. 1857 */ 1858 const C2PlanarLayout layout() const; 1859 1860 /** 1861 * Returns a section of this view. 1862 * 1863 * \param rect the dimension of the section. \note This is clamped to the crop of this view. 1864 * 1865 * \return a read view containing the requested section of this view 1866 */ 1867 const C2GraphicView subView(const C2Rect &rect) const; 1868 C2GraphicView subView(const C2Rect &rect); 1869 1870 /** 1871 * \return error during the creation/mapping of this view. 1872 */ 1873 c2_status_t error() const; 1874 1875 protected: 1876 class Impl; 1877 C2GraphicView(std::shared_ptr<Impl> impl, const _C2PlanarSectionAspect §ion); 1878 explicit C2GraphicView(c2_status_t error); 1879 1880 private: 1881 friend struct _C2BlockFactory; 1882 std::shared_ptr<Impl> mImpl; 1883 }; 1884 1885 /** 1886 * A constant (read-only) graphic block (portion of an allocation) with an acquire fence. 1887 * Blocks are unmapped when created, and can be mapped into a read view on demand. 1888 * 1889 * This class is copiable and contains a reference to the allocation that it is based on. 1890 */ 1891 class C2ConstGraphicBlock : public C2Block2D { 1892 public: 1893 /** 1894 * Maps this block into memory and returns a read view for it. 1895 * 1896 * \return a read view for this block. 1897 */ 1898 C2Acquirable<const C2GraphicView> map() const; 1899 1900 /** 1901 * Returns a section of this block. 1902 * 1903 * \param rect the coordinates of the section. \note This is clamped to the crop rectangle of 1904 * this block. 1905 * 1906 * \return a constant graphic block containing a portion of this block 1907 */ 1908 C2ConstGraphicBlock subBlock(const C2Rect &rect) const; 1909 1910 /** 1911 * Returns the acquire fence for this block. 1912 * 1913 * \return a fence that must be waited on before reading the block. 1914 */ fence()1915 C2Fence fence() const { return mFence; } 1916 1917 protected: 1918 C2ConstGraphicBlock( 1919 std::shared_ptr<Impl> impl, const _C2PlanarSectionAspect §ion, C2Fence fence); 1920 1921 private: 1922 friend struct _C2BlockFactory; 1923 C2Fence mFence; 1924 }; 1925 1926 /** 1927 * Graphic block is a writeable 2D block. Once written, it can be shared in whole or in part with 1928 * consumers/readers as read-only const graphic block. 1929 */ 1930 class C2GraphicBlock : public C2Block2D { 1931 public: 1932 /** 1933 * Maps this block into memory and returns a write view for it. 1934 * 1935 * \return a write view for this block. 1936 */ 1937 C2Acquirable<C2GraphicView> map(); 1938 1939 /** 1940 * Creates a read-only const linear block for a portion of this block; optionally protected 1941 * by an acquire fence. There are two ways to use this: 1942 * 1943 * 1) share ready block after writing data into the block. In this case no fence shall be 1944 * supplied, and the block shall not be modified after calling this method. 1945 * 2) share block metadata before actually (finishing) writing the data into the block. In 1946 * this case a fence must be supplied that will be triggered when the data is written. 1947 * The block shall be modified only until firing the event for the fence. 1948 */ 1949 C2ConstGraphicBlock share(const C2Rect &crop, C2Fence fence); 1950 1951 protected: 1952 C2GraphicBlock(std::shared_ptr<Impl> impl, const _C2PlanarSectionAspect §ion); 1953 1954 friend struct _C2BlockFactory; 1955 }; 1956 1957 /// @} 1958 1959 /// \defgroup buffer_onj Buffer objects 1960 /// @{ 1961 1962 // ================================================================================================ 1963 // BUFFERS 1964 // ================================================================================================ 1965 1966 /// \todo: Do we still need this? 1967 /// 1968 // There are 2 kinds of buffers: linear or graphic. Linear buffers can contain a single block, or 1969 // a list of blocks (LINEAR_CHUNKS). Support for list of blocks is optional, and can allow consuming 1970 // data from circular buffers or scattered data sources without extra memcpy. Currently, list of 1971 // graphic blocks is not supported. 1972 1973 class C2LinearBuffer; // read-write buffer 1974 class C2GraphicBuffer; // read-write buffer 1975 class C2LinearChunksBuffer; 1976 1977 /** 1978 * C2BufferData: the main, non-meta data of a buffer. A buffer can contain either linear blocks 1979 * or graphic blocks, and can contain either a single block or multiple blocks. This is determined 1980 * by its type. 1981 */ 1982 class C2BufferData { 1983 public: 1984 /** 1985 * The type of buffer data. 1986 */ 1987 enum type_t : uint32_t { 1988 INVALID, ///< invalid buffer type. Do not use. 1989 LINEAR, ///< the buffer contains a single linear block 1990 LINEAR_CHUNKS, ///< the buffer contains one or more linear blocks 1991 GRAPHIC, ///< the buffer contains a single graphic block 1992 GRAPHIC_CHUNKS, ///< the buffer contains one of more graphic blocks 1993 }; 1994 typedef type_t Type; // deprecated 1995 1996 /** 1997 * Gets the type of this buffer (data). 1998 * \return the type of this buffer data. 1999 */ 2000 type_t type() const; 2001 2002 /** 2003 * Gets the linear blocks of this buffer. 2004 * \return a constant list of const linear blocks of this buffer. 2005 * \retval empty list if this buffer does not contain linear block(s). 2006 */ 2007 const std::vector<C2ConstLinearBlock> linearBlocks() const; 2008 2009 /** 2010 * Gets the graphic blocks of this buffer. 2011 * \return a constant list of const graphic blocks of this buffer. 2012 * \retval empty list if this buffer does not contain graphic block(s). 2013 */ 2014 const std::vector<C2ConstGraphicBlock> graphicBlocks() const; 2015 2016 private: 2017 class Impl; 2018 std::shared_ptr<Impl> mImpl; 2019 2020 protected: 2021 // no public constructor 2022 explicit C2BufferData(const std::vector<C2ConstLinearBlock> &blocks); 2023 explicit C2BufferData(const std::vector<C2ConstGraphicBlock> &blocks); 2024 }; 2025 2026 /** 2027 * C2Buffer: buffer base class. These are always used as shared_ptrs. Though the underlying buffer 2028 * objects (native buffers, ion buffers, or dmabufs) are reference-counted by the system, 2029 * C2Buffers hold only a single reference. 2030 * 2031 * These objects cannot be used on the stack. 2032 */ 2033 class C2Buffer { 2034 public: 2035 /** 2036 * Gets the buffer's data. 2037 * 2038 * \return the buffer's data. 2039 */ 2040 const C2BufferData data() const; 2041 2042 /** 2043 * These will still work if used in onDeathNotify. 2044 */ 2045 #if 0 2046 inline std::shared_ptr<C2LinearBuffer> asLinearBuffer() const { 2047 return mType == LINEAR ? std::shared_ptr::reinterpret_cast<C2LinearBuffer>(this) : nullptr; 2048 } 2049 2050 inline std::shared_ptr<C2GraphicBuffer> asGraphicBuffer() const { 2051 return mType == GRAPHIC ? std::shared_ptr::reinterpret_cast<C2GraphicBuffer>(this) : nullptr; 2052 } 2053 2054 inline std::shared_ptr<C2CircularBuffer> asCircularBuffer() const { 2055 return mType == CIRCULAR ? std::shared_ptr::reinterpret_cast<C2CircularBuffer>(this) : nullptr; 2056 } 2057 #endif 2058 2059 ///@name Pre-destroy notification handling 2060 ///@{ 2061 2062 /** 2063 * Register for notification just prior to the destruction of this object. 2064 */ 2065 typedef void (*OnDestroyNotify) (const C2Buffer *buf, void *arg); 2066 2067 /** 2068 * Registers for a pre-destroy notification. This is called just prior to the destruction of 2069 * this buffer (when this buffer is no longer valid.) 2070 * 2071 * \param onDestroyNotify the notification callback 2072 * \param arg an arbitrary parameter passed to the callback 2073 * 2074 * \retval C2_OK the registration was successful. 2075 * \retval C2_DUPLICATE a notification was already registered for this callback and argument 2076 * \retval C2_NO_MEMORY not enough memory to register for this callback 2077 * \retval C2_CORRUPTED an unknown error prevented the registration (unexpected) 2078 */ 2079 c2_status_t registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr); 2080 2081 /** 2082 * Unregisters a previously registered pre-destroy notification. 2083 * 2084 * \param onDestroyNotify the notification callback 2085 * \param arg an arbitrary parameter passed to the callback 2086 * 2087 * \retval C2_OK the unregistration was successful. 2088 * \retval C2_NOT_FOUND the notification was not found 2089 * \retval C2_CORRUPTED an unknown error prevented the registration (unexpected) 2090 */ 2091 c2_status_t unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr); 2092 2093 ///@} 2094 2095 virtual ~C2Buffer() = default; 2096 2097 ///@name Buffer-specific arbitrary metadata handling 2098 ///@{ 2099 2100 /** 2101 * Gets the list of metadata associated with this buffer. 2102 * 2103 * \return a constant list of info objects associated with this buffer. 2104 */ 2105 const std::vector<std::shared_ptr<const C2Info>> info() const; 2106 2107 /** 2108 * Attaches (or updates) an (existing) metadata for this buffer. 2109 * If the metadata is stream specific, the stream information will be reset. 2110 * 2111 * \param info Metadata to update 2112 * 2113 * \retval C2_OK the metadata was successfully attached/updated. 2114 * \retval C2_NO_MEMORY not enough memory to attach the metadata (this return value is not 2115 * used if the same kind of metadata is already attached to the buffer). 2116 */ 2117 c2_status_t setInfo(const std::shared_ptr<C2Info> &info); 2118 2119 /** 2120 * Checks if there is a certain type of metadata attached to this buffer. 2121 * 2122 * \param index the parameter type of the metadata 2123 * 2124 * \return true iff there is a metadata with the parameter type attached to this buffer. 2125 */ 2126 bool hasInfo(C2Param::Type index) const; 2127 2128 /** 2129 * Checks if there is a certain type of metadata attached to this buffer, and returns a 2130 * shared pointer to it if there is. Returns an empty shared pointer object (nullptr) if there 2131 * is not. 2132 * 2133 * \param index the parameter type of the metadata 2134 * 2135 * \return shared pointer to the metadata. 2136 */ 2137 std::shared_ptr<const C2Info> getInfo(C2Param::Type index) const; 2138 2139 /** 2140 * Removes a metadata from the buffer. 2141 */ 2142 std::shared_ptr<C2Info> removeInfo(C2Param::Type index); 2143 ///@} 2144 2145 /** 2146 * Creates a buffer containing a single linear block. 2147 * 2148 * \param block the content of the buffer. 2149 * 2150 * \return shared pointer to the created buffer. 2151 */ 2152 static std::shared_ptr<C2Buffer> CreateLinearBuffer(const C2ConstLinearBlock &block); 2153 2154 /** 2155 * Creates a buffer containing a single graphic block. 2156 * 2157 * \param block the content of the buffer. 2158 * 2159 * \return shared pointer to the created buffer. 2160 */ 2161 static std::shared_ptr<C2Buffer> CreateGraphicBuffer(const C2ConstGraphicBlock &block); 2162 2163 2164 2165 protected: 2166 // no public constructor 2167 explicit C2Buffer(const std::vector<C2ConstLinearBlock> &blocks); 2168 explicit C2Buffer(const std::vector<C2ConstGraphicBlock> &blocks); 2169 2170 private: 2171 class Impl; 2172 std::shared_ptr<Impl> mImpl; 2173 // Type _mType; 2174 }; 2175 2176 /** 2177 * An extension of C2Info objects that can contain arbitrary buffer data. 2178 * 2179 * \note This object is not describable and contains opaque data. 2180 */ 2181 class C2InfoBuffer { 2182 public: 2183 /** 2184 * Gets the index of this info object. 2185 * 2186 * \return the parameter index. 2187 */ 2188 const C2Param::Index index() const; 2189 2190 /** 2191 * Gets the buffer's data. 2192 * 2193 * \return the buffer's data. 2194 */ 2195 const C2BufferData data() const; 2196 }; 2197 2198 /// @} 2199 2200 /// \cond INTERNAL 2201 2202 /// \todo These are no longer used 2203 2204 /// \addtogroup linear 2205 /// @{ 2206 2207 /** \deprecated */ 2208 class C2LinearBuffer 2209 : public C2Buffer, public _C2LinearRangeAspect, 2210 public std::enable_shared_from_this<C2LinearBuffer> { 2211 public: 2212 /** \todo what is this? */ 2213 const C2Handle *handle() const; 2214 2215 protected: 2216 inline C2LinearBuffer(const C2ConstLinearBlock &block); 2217 2218 private: 2219 class Impl; 2220 Impl *mImpl; 2221 }; 2222 2223 class C2ReadCursor; 2224 2225 class C2WriteCursor { 2226 public: 2227 uint32_t remaining() const; // remaining data to be read 2228 void commit(); // commits the current position. discard data before current position 2229 void reset() const; // resets position to the last committed position 2230 // slices off at most |size| bytes, and moves cursor ahead by the number of bytes 2231 // sliced off. 2232 C2ReadCursor slice(uint32_t size) const; 2233 // slices off at most |size| bytes, and moves cursor ahead by the number of bytes 2234 // sliced off. 2235 C2WriteCursor reserve(uint32_t size); 2236 // bool read(T&); 2237 // bool write(T&); 2238 C2Fence waitForSpace(uint32_t size); 2239 }; 2240 2241 /// @} 2242 2243 /// \addtogroup graphic 2244 /// @{ 2245 2246 struct C2ColorSpace { 2247 //public: 2248 enum Standard { 2249 BT601, 2250 BT709, 2251 BT2020, 2252 // TODO 2253 }; 2254 2255 enum Range { 2256 LIMITED, 2257 FULL, 2258 // TODO 2259 }; 2260 2261 enum TransferFunction { 2262 BT709Transfer, 2263 BT2020Transfer, 2264 HybridLogGamma2, 2265 HybridLogGamma4, 2266 // TODO 2267 }; 2268 }; 2269 2270 /** \deprecated */ 2271 class C2GraphicBuffer : public C2Buffer { 2272 public: 2273 // constant attributes width()2274 inline uint32_t width() const { return mWidth; } height()2275 inline uint32_t height() const { return mHeight; } format()2276 inline uint32_t format() const { return mFormat; } usage()2277 inline const C2MemoryUsage usage() const { return mUsage; } 2278 2279 // modifiable attributes 2280 2281 2282 virtual const C2ColorSpace colorSpace() const = 0; 2283 // best effort 2284 virtual void setColorSpace_be(const C2ColorSpace &colorSpace) = 0; 2285 virtual bool setColorSpace(const C2ColorSpace &colorSpace) = 0; 2286 2287 const C2Handle *handle() const; 2288 2289 protected: 2290 uint32_t mWidth; 2291 uint32_t mHeight; 2292 uint32_t mFormat; 2293 C2MemoryUsage mUsage; 2294 2295 class Impl; 2296 Impl *mImpl; 2297 }; 2298 2299 /// @} 2300 2301 /// \endcond 2302 2303 /// @} 2304 2305 #endif // C2BUFFER_H_ 2306