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