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