• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &section);
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 &section);
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 &section, 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 &section);
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