| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| library fuchsia.sysmem2; |
| |
| using fuchsia.images2; |
| using fuchsia.math; |
| |
| const MAX_COUNT_BUFFER_COLLECTION_CONSTRAINTS_IMAGE_FORMAT_CONSTRAINTS uint32 = 64; |
| const MAX_COUNT_BUFFER_MEMORY_CONSTRAINTS_HEAP_PERMITTED uint32 = 64; |
| const MAX_COUNT_IMAGE_FORMAT_CONSTRAINTS_COLOR_SPACES uint32 = 32; |
| |
| // The contents of this file are not final. Incompatible changes are still |
| // being made to this file. Do not rely on the contents of this file to provide |
| // backward compatibility (yet). |
| // |
| // TODO(fxbug.dev/34192): Sysmem should use llcpp and FIDL tables. The |
| // fuchsia.sysmem2.BufferCollectionConstraints defined here are part of that |
| // transition, but the definitions here are not final. For now, the definition |
| // here is only used internally to sysmem (not between processes), and therefore |
| // this definition can change for now. Later after we're happy with this |
| // representation, we'll create |
| // fuchsia.sysmem2.BufferCollection.SetConstraints() which will accept |
| // constraints as defined here. |
| |
| /// Constraints on BufferCollection parameters. These constraints can be |
| /// specified per-participant. The sysmem service implements aggregation of |
| /// constraints from multiple participants. |
| type BufferCollectionConstraints = table { |
| /// The usage is only meant as a hint to help sysmem choose a more optimal |
| /// PixelFormat or similar when multiple compatible options exist. |
| /// |
| /// When aggregating BufferCollectionConstraints, these values bitwise-OR. |
| /// |
| /// At least one usage bit must be specified unless the whole |
| /// BufferCollectionConstraints is logically null (no fields set). |
| 1: usage BufferUsage; |
| |
| /// Per-participant number of buffers that the participant may concurrently |
| /// hold for its exclusive use for a non-transient period of time (camp on). |
| /// |
| /// For example, a video decoder would specify (at least) the maximum number |
| /// of reference frames + 1 frame currently being decoded into. |
| /// |
| /// A participant must not camp on more buffers than specified here (except |
| /// very transiently) else processing may get stuck. |
| /// |
| /// When aggregating BufferCollectionConstraints, these values add. |
| /// |
| /// In testing scenarios, camping on more buffers than this for any |
| /// significant duration may (ideally will) be flagged as a failure. In |
| /// testing scenarios, the participant may not be provided with more buffers |
| /// than this concurrently. |
| 2: min_buffer_count_for_camping uint32; |
| |
| /// Per-participant minimum number of buffers that are needed for slack |
| /// reasons, for better overlap of processing / better performance. |
| /// |
| /// When aggregating BufferCollectionConstraints, these values add. |
| /// |
| /// A participant should typically specify 0 or 1 here - typically 0 is |
| /// appropriate if min_buffer_count_for_camping is already enough to keep |
| /// the participant busy 100% of the time when the participant is slightly |
| /// behind, while 1 can be appropriate if 1 more buffer than strictly needed |
| /// for min-camping reasons gives enough slack to stay busy 100% of the time |
| /// (when slightly behind, vs. lower % without the extra buffer). |
| /// |
| /// In testing scenarios, this field may be forced to 0, and all |
| /// participants are expected to continue to work without getting stuck. If |
| /// a buffer is needed for forward progress reasons, that buffer should be |
| /// accounted for in min_buffer_count_for_camping. |
| 3: min_buffer_count_for_dedicated_slack uint32; |
| |
| /// Similar to min_buffer_count_for_dedicated_slack, except when aggregating |
| /// these values max (instead of add). The value here is not shared with |
| /// any participant's min_buffer_count_for_dedicated_slack. |
| /// |
| /// A participant can specify > 0 here if a participant would like to ensure |
| /// there's some slack overall, but doesn't need that slack to be dedicated. |
| /// |
| /// The choice whether to use min_buffer_count_for_dedicated_slack or |
| /// min_buffer_count_for_shared_slack (or both) will typically be about the |
| /// degree to which the extra slack improves performance. |
| /// |
| /// In testing scenarios, this field may be forced to 0, and all |
| /// participants are expected to continue to work without getting stuck. If |
| /// a buffer is needed for forward progress reasons, that buffer should be |
| /// accounted for in min_buffer_count_for_camping. |
| 4: min_buffer_count_for_shared_slack uint32; |
| |
| /// A particularly-picky participant may unfortunately need to demand a |
| /// tight range of buffer_count, or even a specific buffer_count. This |
| /// field should remain 0 unless a participant really must set this field to |
| /// constrain the overall BufferCollectionInfo_2.buffer_count. Any such |
| /// participant should still fill out the min_buffer_count_for_* fields. |
| /// |
| /// If this field is un-set, the logical min_buffer_count is 1. |
| 5: min_buffer_count uint32; |
| /// A particularly-picky participant may unfortunately need to demand a |
| /// tight range of buffer_count, or even a specific buffer_count. This |
| /// field should remain 0 unless a participant really must set this field to |
| /// constrain the overall BufferCollectionInfo_2.buffer_count. Any such |
| /// participant should still fill out the min_buffer_count_for_* fields. |
| /// |
| /// If this field is un-set, the logical max_buffer_count is 0xFFFFFFFF. |
| 6: max_buffer_count uint32; |
| |
| /// Optional constraints on BufferCollectionSettings.buffer_settings. |
| /// |
| /// A participant that intends to specify image_format_constraints_count > 1 |
| /// will typically specify the minimum buffer size implicitly via |
| /// image_format_constraints, and possibly specify only the max buffer size |
| /// via buffer_memory_constraints. |
| /// |
| /// If un-set, the client is specifying "don't care" re. any buffer memory |
| /// constraints. |
| 7: buffer_memory_constraints BufferMemoryConstraints; |
| |
| /// Optional constraints on the image format parameters of an image stored |
| /// in a buffer of the BufferCollection. This includes pixel format and |
| /// image layout. These constraints are per-pixel-format, so more than one |
| /// is permitted. Entries in the list must have unique pixel_formats. |
| /// |
| /// When aggregating, only pixel formats that are specified by all |
| /// particpants with non-zero image_format_constraints_count (and non-Null) |
| /// BufferCollectionConstraints) are retained. |
| /// |
| /// Un-set means no image format constraints. set but zero length is an |
| /// error. |
| 8: image_format_constraints |
| vector<ImageFormatConstraints>:MAX_COUNT_BUFFER_COLLECTION_CONSTRAINTS_IMAGE_FORMAT_CONSTRAINTS; |
| |
| /// If true, a secure heap may only be selected if all participants with |
| /// BufferMemoryConstraints specify allow_clear_aux_buffers_for_secure. If |
| /// "need" is true, "allow" must also be true. |
| /// |
| /// If false (or unset), the participant can still work, potentially even |
| /// with secure memory (depending on supported heaps), without clear aux |
| /// buffers. |
| 9: need_clear_aux_buffers_for_secure bool; |
| |
| /// If true, the participant will use clear aux buffers, if they are |
| /// allocated, as appropriate to the participant's role. If the participant |
| /// is a writer, then the participant writer will populate the clear aux |
| /// buffers with the clear (not-encrypted, not-DRM-protected) bytes, and |
| /// fill protected bytes with data that does not emulate start codes, such |
| /// as 0xFF. |
| /// |
| /// If un-set, then allow_clear_aux_buffers_for_secure is true iff the |
| /// participant specifies usage which is read-only. |
| /// |
| /// If un-set from a participant with write usage, or false, the buffer |
| /// collection won't be able to allocate if any participant specifies |
| /// need_clear_aux_buffers_for_secure true. |
| 10: allow_clear_aux_buffers_for_secure bool; |
| }; |
| |
| /// Known heap types. |
| /// Device specific types should have bit 60 set. Top order bit is reserved |
| /// and should not be set. |
| type HeapType = flexible enum : uint64 { |
| SYSTEM_RAM = 0x0000000000000000; |
| |
| /// Heap used for amlogic protected memory. |
| AMLOGIC_SECURE = 0x1000000000010000; |
| |
| /// Heap used for amlogic protected memory between decrypt and video decode. |
| AMLOGIC_SECURE_VDEC = 0x1000000000010001; |
| |
| /// Heap used by goldfish vulkan for device-local memory. |
| GOLDFISH_DEVICE_LOCAL = 0x1000000000020000; |
| |
| /// Heap used by goldfish vulkan for host-visible memory. |
| GOLDFISH_HOST_VISIBLE = 0x1000000000020001; |
| |
| /// Heap used for display framebuffer. This is used by display drivers |
| /// limited to a single framebuffer located at a specific physical address. |
| /// The framebuffer heap makes it possible to create buffer collections |
| /// for the framebuffer and enables sysmem support in these drivers. |
| FRAMEBUFFER = 0x1000000000030001; |
| }; |
| |
| type BufferMemoryConstraints = table { |
| 1: min_size_bytes uint32; |
| /// un-set is treated as 0xFFFFFFFF. |
| 2: max_size_bytes uint32; |
| |
| 3: physically_contiguous_required bool; |
| |
| /// If true, at least one participant requires secure memory. |
| /// |
| /// When aggregating BufferCollectionConstraints, these values boolean-OR. |
| 4: secure_required bool; |
| |
| /// By default, participants must ensure the CPU can read or write data to |
| /// the buffer without cache operations. If they support using the RAM |
| /// domain, data must be available in RAM (with CPU cache state such that |
| /// the RAM data won't get corrupted by a dirty CPU cache line writing |
| /// incorrect data to RAM), and a consumer reading using the CPU must |
| /// invalidate CPU cache before reading (the producer doesn't guarantee |
| /// zero stale "clean" cache lines) |
| 5: cpu_domain_supported bool; |
| 6: ram_domain_supported bool; |
| 7: inaccessible_domain_supported bool; |
| |
| /// Optional heap constraints. Participants that don't care which heap |
| /// memory is allocated on should leave this field un-set. |
| 8: heap_permitted vector<HeapType>:MAX_COUNT_BUFFER_MEMORY_CONSTRAINTS_HEAP_PERMITTED; |
| }; |
| |
| /// Inaccessible is only for cases where there is no CPU-based access to the |
| /// buffers. A secure_required buffer can still have CoherencyDomain Cpu or |
| /// Ram even if the secure_required buffer can only be accessed by the CPU when |
| /// the CPU is running in secure mode (or similar). In contrast, device-local |
| /// memory that isn't reachable from the CPU is CoherencyDomain Inaccessible, |
| /// even if it's possible to cause a device (physical or virtual) to copy the |
| /// data from the Inaccessible buffers to buffers that are visible to the CPU. |
| type CoherencyDomain = flexible enum { |
| CPU = 0; |
| RAM = 1; |
| INACCESSIBLE = 2; |
| }; |
| |
| /// Describes constraints on layout of image data in buffers. |
| // TODO(fxbug.dev/32119): change struct to table |
| type ImageFormatConstraints = table { |
| /// The PixelFormat for which the following constraints apply. A |
| /// participant may have more than one PixelFormat that's supported, in |
| /// which case that participant can use a list of ImageFormatConstraints |
| /// with an entry per PixelFormat. It's not uncommon for the other fields |
| /// of ImageFormatConstraints to vary by PixelFormat - for example for a |
| /// linear format to support smaller max size than a tiled format. |
| /// |
| /// If not set, these ImageFormatConstraints apply to all PixelFormat(s), |
| /// and this ImageFormatConstraints does not constrain which PixelFormat is |
| /// chosen. For example this can be used to set required_max_coded_width |
| /// and required_max_coded_height fields to force allocating large-enough |
| /// buffers to hold particular video dimensions, without needing to list |
| /// every PixelFormat. |
| 1: pixel_format fuchsia.images2.PixelFormat; |
| |
| 2: pixel_format_modifier uint64; |
| |
| /// Empty is an error. Redundant entries are an error. Arbitrary ordering |
| /// is not an error. |
| 3: color_spaces |
| vector<fuchsia.images2.ColorSpace>:MAX_COUNT_IMAGE_FORMAT_CONSTRAINTS_COLOR_SPACES; |
| |
| /// Minimum permitted size in pixels. |
| /// |
| /// For example a video decoder participant may set this field to the |
| /// minimum size that might potentially be specified by a stream. In |
| /// contrast, `required_min_size` would be set to the current size specified |
| /// by the stream. While `min_size` aggregates by taking the max, |
| /// `required_min_size` aggregates by taking the min. |
| /// |
| /// When sending to sysmem, this field can be un-set if the participant is |
| /// prepared to deal with the smallest possible non-zero image layout |
| /// limited only by the constraints implicitly imposed by the `pixel_format` |
| /// and `pixel_format_modifier`. Or this field can be set to the actual |
| /// minimum size the participant can handle. |
| /// |
| /// Producers should set min_size and set both width and height to the |
| /// actual non-zero smallest width and height that the producer might |
| /// generate. For example, a video decoder can set the size of a single |
| /// macroblock here. |
| /// |
| /// When receiving from sysmem, this field will always be set, and neither |
| /// width nor height will be 0, because at least one participant must |
| /// specify a non-zero minimum size (where both width and height aren't |
| /// zero). |
| /// |
| /// See also `required_min_size`. |
| 4: min_size fuchsia.math.SizeU; |
| /// Maximum size in pixels. For example Scenic may set this field (directly |
| /// or via sub-participants) to the maximum size that can be composited. |
| /// |
| /// Sending to sysmem, un-set is treated as 0xFFFFFFFF, 0xFFFFFFFF. |
| /// |
| /// Receiving from sysmem, this field will always be set. For width and |
| /// height separately, if there is no enforced max, that sub-field will be |
| /// 0xFFFFFFFF. |
| 5: max_size fuchsia.math.SizeU; |
| |
| /// The minimum number of bytes per row, including any padding beyond the |
| /// last image data in a row. |
| /// |
| /// This is sometimes called the "stride" or the "line to line offset". For |
| /// single-plane formats, this is the number of bytes per row of pixels. For |
| /// multi-plane formats, this is the number of bytes per row of samples in |
| /// plane 0 (for example, the number of bytes per row of luma samples in the |
| /// case of a multi-plane YUV format). For multi-plane formats, the bytes |
| /// per row in planes other than plane 0 is format specific but always a |
| /// specific relationship to the plane 0 bytes per row. |
| /// |
| /// When sending `ImageFormatConstraints` to sysmem, setting this field is |
| /// optional. Not setting this field is recommended unless the participant |
| /// needs to force the `bytes_per_row` to be larger than the minimum value |
| /// implied by min_size.width, the "stride bytes per width pixel" of the |
| /// `pixel_format` plus `pixel_format_modifier` (see also |
| /// `ImageFormatStrideBytesPerWidthPixel`), and `bytes_per_row_divisor`. |
| /// |
| /// When this structure is received from sysmem, this field will always be |
| /// set (when the parent structure is present), and will always be at least |
| /// the value implied by min_size.width, the "stride bytes per width pixel" |
| /// of the `pixel_format` plus `pixel_format_modifier`, and |
| /// `bytes_per_row_divisor`. Some producer participants may prefer to simply |
| /// set `ImageFormat.bytes_per_row` to |
| /// `ImageFormatConstraints.min_bytes_per_row` since sysmem is guaranteeing |
| /// that `min_bytes_per_row` is compatible with an image of width |
| /// min_size.width. Producer participants that need to have `size.width` > |
| /// `min_size.width` can get a corresponding `min_bytes_per_row` from |
| /// ImageFormatMinimumRowBytes (in C++), or can just calculate the |
| /// `bytes_per_row` directly. |
| 6: min_bytes_per_row uint32; |
| |
| /// The maximum number of bytes per row, including any padding beyond the |
| /// last image data in a row. |
| /// |
| /// When sent to sysmem, must be >= the value implied by `max_size.width`, |
| /// "stride bytes per width pixel", and `bytes_per_row_divisor`, or |
| /// constraints aggregation will fail. Un-set means the participant doesn't |
| /// need/want to set a strict max. |
| /// |
| /// When a participant wants to not specify any maximum, the participant can |
| /// either not set this field, or set this field to 0xFFFFFFFF. |
| /// |
| /// When received from sysmem, this field will always be set. If the max is |
| /// effectively infinite, the value will be 0xFFFFFFFF (not zero). |
| 7: max_bytes_per_row uint32; |
| |
| /// The max image area in pixels is limited indirectly via |
| /// `BufferSettings.size_bytes`, and can also be enforced directly via this |
| /// field. |
| /// |
| /// Sending to sysmem, un-set is treated as 0xFFFFFFFF. |
| /// |
| /// Receiving from sysmem, this field will always be set, and can be set to |
| /// 0xFFFFFFFF. |
| 8: max_surface_width_times_surface_height uint32; |
| |
| /// * `size.width % size_alignment.width` must be 0. |
| /// * `size.height % size_alignment.height` must be 0. Un-set is treated as |
| /// 1, 1. |
| 9: size_alignment fuchsia.math.SizeU; |
| |
| /// * `display_rect.x % display_rect_alignment.width` must be 0. |
| /// * `display_rect.y % display_rect_alignment.height` must be 0. |
| /// * `display_rect.width % display_rect_alignment.width` must be 0. |
| /// * `display_rect.height % display_rect_alignment.height` must be 0. |
| /// Un-set is treated as 1, 1. |
| 10: display_rect_alignment fuchsia.math.SizeU; |
| |
| /// These fields can be used to ensure the aggregated constraints have |
| /// min_size and max_size such that both required_min_size and |
| /// required_max_size (and anything in between) are permitted values of |
| /// ImageFormat.size. |
| /// |
| /// For example, a producer video decoder doesn't want to constrain the |
| /// allowed ImageFormat.size, as a compressed stream can change dimensions |
| /// mid-stream, but the producer video decoder needs to ensure that the |
| /// aggregated constraints allow for at least the current dimensions of |
| /// uncompressed frames at the current position in the stream. |
| /// |
| /// As another example, an initiator that's intending to decode video may |
| /// know what the maximum expected size of frames in the stream(s) can be, |
| /// so by setting `required_max_size`, can ensure that the allocated buffers |
| /// are large enough to support that max `size`. In addition on successful |
| /// allocation the initiator also knows that the consumer participants are |
| /// ok with receiving up to that max `size`. |
| /// |
| /// It's much more common for a producer or initiator to set these fields |
| /// than for a consumer to set these fields. |
| /// |
| /// While `min_size` and `max_size` aggregate by effectively taking the |
| /// intersection, the `required_min_size` and `required_max_size` aggregate |
| /// by effectively taking the union. |
| /// |
| /// TODO(fxbug.dev/34192): Make it easier to allocate buffers of minimal |
| /// size that can (optionally) also handle 90 degree rotated version of the |
| /// max dimensions / alternate required bounds for another main aspect |
| /// ratio. Un-set is treated as 0xFFFFFFFF, 0xFFFFFFFF. |
| 11: required_min_size fuchsia.math.SizeU; |
| /// See also required_min_size. Un-set is treated as 0, 0. |
| 12: required_max_size fuchsia.math.SizeU; |
| |
| /// `fuchsia_images2.ImageFormat.bytes_per_row % bytes_per_row_divisor` must |
| /// be 0. un-set is treated as 1. When set, this must be a power of 2. |
| /// |
| /// Prefer to use `size_alignment.width` when the intent is to ensure that |
| /// the width in pixels is aligned. In contrast, this field can specify that |
| /// the "stride" (byte offset from start of image to start of row n minus |
| /// byte offset from start of image to start of row n-1, with result in |
| /// bytes) needs to be aligned to the specified number of bytes. For |
| /// example, when `PixelFormat.BGR24` (24 bit color; 3 bytes per pixel) is |
| /// used, it's not uncommon for a participant to need each row of pixels to |
| /// start at a 4 byte aligned offset from the start of the image, which can |
| /// imply some padding bytes at the end of each row of pixels, before the |
| /// start of the next row of pixels. |
| /// |
| /// While any value of `bytes_per_row_divisor` could instead be enforced by |
| /// setting `size_alignment.width` to the least-common-multiple of the |
| /// "stride bytes per width pixel" and the stride alignment requirement, |
| /// enforcing the stride alignment requirement that way can lead to more |
| /// padding than necessary (implying larger buffer than necessary), and also |
| /// results in a "fake" `size.width`; this field exists to avoid that |
| /// situation. Instead, the stride alignment requirement in bytes is |
| /// specified directly here. |
| 13: bytes_per_row_divisor uint32; |
| |
| /// `vmo_usable_start % start_offset_divisor` must be 0. Un-set is treated |
| /// as 1. |
| /// |
| /// Producer participants are discouraged from setting non-zero image start |
| /// offset (from the buffer base) unless actually required, as not all |
| /// participants correctly handle non-zero image start offset. |
| 14: start_offset_divisor uint32; |
| }; |