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