| // Copyright 2019 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.ui.scenic.internal; |
| |
| using fuchsia.math; |
| using fuchsia.ui.composition; |
| using zx; |
| |
| /// The set of error codes returned in [`OnPresentProcessed`]. Everything except NO_ERROR, causes |
| /// Flatland channel to be closed. |
| enum Error { |
| /// Indicates that the operation was successful. |
| NO_ERROR = 0; |
| /// Indicates that the parameters used the function calls are invalid. |
| BAD_OPERATION = 1; |
| /// Indicates that `num_presents_returned` field was not properly processed and the client queued more |
| /// [`Present`]s than allowed. |
| NO_PRESENTS_REMAINING = 2; |
| /// Indicates that the client has overwritten hanging gets in the protocols returned. |
| BAD_HANGING_GET = 3; |
| }; |
| |
| enum Orientation { |
| CCW_0_DEGREES = 1; |
| CCW_90_DEGREES = 2; |
| CCW_180_DEGREES = 3; |
| CCW_270_DEGREES = 4; |
| }; |
| |
| /// The return type of GraphLink::GetLayout(). This table contains most of the information necessary |
| /// for a client to decide how to layout their content in a Flatland instance. This data may be |
| /// provided to the client before the command that creates the Link is presented, so that the client |
| /// may lay out content properly before their first call to Present(). |
| table LayoutInfo { |
| /// The layout size of a Graph in logical pixels, defined by the parent's call to |
| /// SetLinkProperties(). Clients should re-layout their content when this value changes. |
| 1: fuchsia.math.SizeU logical_size; |
| /// The ratio from physical display pixels to logical pixels, defined by the sizes and scale |
| /// transforms of the parent. Clients should not necessarily re-layout their content when this |
| /// value changes. |
| 2: fuchsia.math.SizeU pixel_scale; |
| }; |
| |
| /// GraphLinks will be informed when they are actively attached to a output display (either |
| /// directly, or through a chain of parent links) and when they are not. Until they are connected to |
| /// a display, some pieces of information (such as pixel scale) may be unavailable. |
| enum GraphLinkStatus { |
| CONNECTED_TO_DISPLAY = 1; |
| DISCONNECTED_FROM_DISPLAY = 2; |
| }; |
| |
| /// A protocol that provides information about a particular Link to the child client. Each Flatland |
| /// instance may only specify a single root transform, so other objects in the graph can only be |
| /// children of a single GraphLink. However, more than one GraphLink protocol may be active at a |
| /// time for a particular Flatland instance. Specifically, when a Flatland instance is transitioning |
| /// from using one Link to another, each Link will have a separate protocol instance, and more than |
| /// one protocol may receive certain updates. |
| protocol GraphLink { |
| /// A hanging get for receiving layout information. Clients may receive layout information |
| /// before the GraphLink operation has been presented. This allows children to layout their |
| /// content before their first call to Present(). In transition cases where two GraphLink |
| /// channels exist at the same time, both protocol instances will be receiving different layout |
| /// information. |
| /// |
| /// This hanging get will only fire when the LayoutInfo is different than the previously |
| /// returned LayoutInfo. Note that, since LayoutInfo is a table, only some fields may have |
| /// changed. |
| /// |
| /// It is invalid to call `GetLayout` while a previous call is still pending. Doing so will |
| /// cause both this channel and the Flatland channel to be closed. |
| GetLayout() -> (LayoutInfo info); |
| |
| /// A hanging get for receiving the status of the Link. This provides global connectivity |
| /// information to the child. |
| /// |
| /// This hanging get will only fire when the GraphLinkStatus is different than the previously |
| /// returned GraphLinkStatus. |
| /// |
| /// It is invalid to call `GetStatus` while a previous call is still pending. Doing so will |
| /// cause both this channel and the Flatland channel to be closed. |
| GetStatus() -> (GraphLinkStatus status); |
| }; |
| |
| enum ContentLinkStatus { |
| /// The underlying Graph has connected its Link, called Present(), and the acquisition fences |
| /// of the Present() call have all be reached, indicating that it has some content ready to be |
| /// displayed. |
| CONTENT_HAS_PRESENTED = 1; |
| }; |
| |
| /// A protocol that provides information about a particular Link to the parent client. Flatland |
| /// instances may contain any number of ContentLinks, each of which may or may not be attached to |
| /// the Root Transform. Each ContentLink has its own protocol instance. |
| protocol ContentLink { |
| /// A hanging get for receiving the status of a Link. This provides information to the parent, |
| /// such as whether or not the child has successfully presented content through this Link. |
| /// |
| /// This hanging get will only fire when the ContentLinkStatus is different than the previously |
| /// returned ContentLinkStatus. |
| /// |
| /// It is invalid to call `GetStatus` while a previous call is still pending. Doing so will |
| /// cause both this channel and the Flatland channel to be closed. |
| GetStatus() -> (ContentLinkStatus status); |
| }; |
| |
| /// A typed wrapper for an eventpair, representing the child endpoint of a Link. |
| /// The eventpair object must not be cloned; object uniqueness is used as part |
| /// of lifecycle management. |
| resource struct GraphLinkToken { |
| zx.handle:EVENTPAIR value; |
| }; |
| |
| /// A typed wrapper for an eventpair, representing the parent endpoint of a Link. |
| /// The eventpair object must not be cloned; object uniqueness is used as part |
| /// of lifecycle management. |
| resource struct ContentLinkToken { |
| zx.handle:EVENTPAIR value; |
| }; |
| |
| /// The properties of a Link as defined by the parent. This data, along with the set of attached |
| /// Transforms, will be used to compute the LayoutInfo for the child of the Link. |
| table LinkProperties { |
| /// The size of the Link in logical pixels. This maps directly to the logical_size field in |
| /// LayoutInfo. |
| 1: fuchsia.math.SizeU logical_size; |
| }; |
| |
| /// The properties of an Image as defined by the client. These properties determine how an Image |
| /// uses the backing BufferCollection. See CreateImage() for more information. |
| table ImageProperties { |
| /// The size of the Image in pixels. |
| 1: fuchsia.math.SizeU size; |
| }; |
| |
| /// A user-defined identifier for a particular transform. See CreateTransform() and |
| /// ReleaseTransform() for more information. |
| struct TransformId { |
| uint64 value; |
| }; |
| |
| /// A user-defined identifier for a particular piece of Content. See Content creation functions |
| /// (e.g. CreateLink(), CreateImage()) for more information. |
| struct ContentId { |
| uint64 value; |
| }; |
| |
| // A maximum of 16 fences is enough for the current usage of these APIs. |
| const int32 MAX_ACQUIRE_RELEASE_FENCE_COUNT = 16; |
| |
| /// Arguments passed into Present(). All arguments are optional, and if an |
| /// argument is omitted Flatland will use a reasonable default, specified below. |
| resource table PresentArgs { |
| /// `requested_presentation_time` specifies the time on or after which the client would like the |
| /// enqueued operations to take visible effect (light up pixels on the screen), expressed in |
| /// nanoseconds in the `CLOCK_MONOTONIC` timebase. |
| /// |
| /// The default `requested_presentation_time` is 0. |
| /// |
| /// Using a `requested_presentation_time` in the present or past (such as 0) schedules enqueued |
| /// operations to take visible effect as soon as possible, during the next frame to be prepared. |
| /// |
| /// Using a `requested_presentation_time` in the future schedules the enqueued operations to |
| /// take visible effect on or as closely as possible after the stated time, but no earlier. |
| /// |
| /// Each rendered frame has a target presentation time. This is when Flatland aims to have the |
| /// frame presented to the user. Before rendering a frame, Flatland applies all |
| /// enqueued operations associated with all squashable calls to Present() whose |
| /// `requested_presentation_time` is on or before the frame's target presentation time. |
| 1: zx.time requested_presentation_time; |
| |
| /// Flatland will wait until all of a session's `acquire_fences` are ready before it will |
| /// execute the presented commands. |
| /// |
| /// The default `acquire_fences` value is the empty vector. |
| 2: vector<zx.handle:EVENT>:MAX_ACQUIRE_RELEASE_FENCE_COUNT acquire_fences; |
| |
| /// Flatland will signal all `release_fences` when the resources and shared buffers from this |
| /// Present() are no longer in use. Callers should not modify shared resources, such as |
| /// BufferCollections, until after these fences are signaled. |
| /// |
| /// If an error occurrs, release fences are not necessarily fired as Flatland can close the |
| /// client's instance at any point. |
| /// |
| /// The default `release_fences` value is the empty vector. |
| 3: vector<zx.handle:EVENT>:MAX_ACQUIRE_RELEASE_FENCE_COUNT release_fences; |
| |
| /// If `squashable` is true, then an update can be combined with those that |
| /// come after it. If `squashable` is false, then the update is guaranteed |
| /// to be shown for at least one vsync interval. |
| /// |
| /// The default `squashable` value is true. |
| 4: bool squashable; |
| }; |
| |
| /// A user-defined identifier for future presentation info. A maximum of 8 |
| /// future presentation counts is enough for the current usage of these APIs. |
| alias FuturePresentationInfos = vector<fuchsia.ui.composition.PresentationInfo>:8; |
| |
| /// Each Flatland instance contains a Graph, which consists of a set of objects, and the |
| /// relationships between those objects. The client can specify a subset of those objects |
| /// (specifically, the directed acyclic graph starting at the root transform) to be presented as |
| /// content to some kind of output -- usually, a display. |
| /// |
| /// Flatland Graphs are both hierarchical, and distributed. Graphs from different Flatland instances |
| /// may be linked together, allowing multiple processes to be involved in authoring content for a |
| /// particular output. |
| /// |
| /// All functions in this protocol are feed-forward. The operations they represent are not fully |
| /// executed until Present() is called. |
| [Discoverable] |
| protocol Flatland { |
| /// Complete execution of all feed-forward operations. |
| /// |
| /// If executing an operation produces an error (e.g., CreateTransform(0)), |
| /// [`OnPresentProcessed`] emits a non-success Error type. Operations that produce errors |
| /// are ignored and the channel is closed. If the execution is completed successfully, |
| /// [`OnPresentProcessed`] emits NO_ERROR along with other parameters. |
| /// |
| /// The client may only call [`Present`] when they have a non-zero number |
| /// of `num_presents_returned`, which are tracked by the server. The server may |
| /// increment the counter when it fires the [`OnPresentProcessed`] event, which |
| /// informs the client when it receives additional [`Present`] allowance. Each [`Present`] |
| /// call uses one of `num_presents_returned` and decrements the server count by one. If |
| /// the client calls [`Present`] when no [`Present`] allowance remain, it will return |
| /// `NO_PRESENTS_REMAINING`. |
| /// |
| /// The client should assume that prior to receiving any [`OnPresentProcessed`] |
| /// events, they have one [`Present`] allowance. |
| /// |
| /// Every [`Present`] call results in one [`OnPresentProcessed`] event, and one |
| /// [`OnFramePresented`] event, typically in that order. |
| /// |
| /// When the commands flushed by [`Present`] make it to display, an |
| /// [`OnFramePresented`] event is fired. This event includes information |
| /// pertaining to all [`Present`]s that had content that were part of that |
| /// frame. |
| /// |
| /// See [`fuchsia.ui.scenic.internal/PresentArgs`] documentation above for |
| /// more detailed information on what arguments are passed in and their |
| /// role. |
| Present(PresentArgs args); |
| |
| /// This event is fired when clients should expect minimal resource |
| /// contention. Clients may use the timing of this event to begin their |
| /// rendering work, using the information returned to inform their |
| /// scheduling decsisions. |
| /// |
| /// - response `num_presents_returned` the number of additional [`Present`] calls allowed to |
| /// the client so that they can call [`Present`] further times. |
| /// - response `future_presentation_infos` information about future |
| /// presentation and latch times. |
| -> OnPresentProcessed(Error error, uint32 num_presents_returned, |
| FuturePresentationInfos future_presentation_infos); |
| |
| /// This event is fired whenever a set of one or more [`Present`]s are |
| /// presented simultaneously, and are therefore no longer in flight. |
| /// TODO(fxbug.dev/63305): remove `num_presents_allowed` from this event. |
| -> OnFramePresented(fuchsia.ui.composition.FramePresentedInfo frame_presented_info); |
| |
| // ***** Graph management ***** |
| |
| /// A Link is a connection between the objects authored in this Graph, and the objects in |
| /// the Graph of another process. The parent process has control over how the linked content is |
| /// integrated into their Graph. |
| /// |
| /// A link starts with a pair of eventpair objects: a ContentLinkToken and GraphLinkToken. |
| /// Out-of-band protocols pass the ContentLinkToken to the parent, which calls CreateLink(), and |
| /// the GraphLinkToken to the child, which calls LinkToParent(). |
| /// |
| /// Only nodes connected to the Root Transform in this Flatland instance will be rendered as |
| /// part of the parent's Graph. |
| /// |
| /// Calling LinkToParent() a second time will disconnect the Root Transform from the existing |
| /// parent's Graph, and attach it to a new parent's Graph. |
| /// |
| /// This function is feed-forward, meaning that the Root Transform will not be attached to the |
| /// parent Graph until Present() is called. However, Clients will receive information through |
| /// their GraphLink (e.g., LayoutInfo) immediately after calling this function, even if they |
| /// have not called Present() or SetRoot(). This allows clients to wait for layout information |
| /// from their parent before calling Present(). |
| /// |
| /// Any illegal operations on GraphLink will cause both GraphLink channel and this Flatland |
| /// channel to be torn down. |
| /// |
| /// Lifecycle note. The lifetime of the GraphLink channel is bound by the peer ContentLinkToken. |
| /// When the ContentLinkToken dies, this GraphLink channel is destroyed. |
| LinkToParent(GraphLinkToken token, request<GraphLink> graph_link); |
| |
| /// Disconnects this Graph from its parent Graph and returns the GraphLinkToken used to |
| /// establish the link. This token can then be used to establish a new link with the Parent |
| /// graph. |
| /// |
| /// To clear the existing content from the screen without unlinking the current Graph, use |
| /// SetRootTransform(0) instead. |
| /// |
| /// Despite having a return type, this function is still feed-forward Like LinkToParent() and |
| /// requires a call to Present() to be executed. The GraphLinkToken will be returned after the |
| /// presented operations have been executed. |
| UnlinkFromParent() -> (GraphLinkToken token); |
| |
| /// This function will reset all state on this interface. This includes destroying all existing |
| /// Links without returning the associated Token to the caller. |
| ClearGraph(); |
| |
| // ***** Transforms ***** |
| |
| // Transform constructors. |
| |
| /// Creates a new Transform node. Transforms are a hierarchical piece of a Flatland graph. They |
| /// can have children, and can reference Content. A sub-graph represented by a Transform and its |
| /// descendants can be rendered to a display. |
| /// |
| /// Transforms are kept alive, even when released, as long as they are children of either an |
| /// unreleased Transform, or the Root Transform. |
| /// |
| /// Each Transform can have a single piece of attached Content. Common types of Content include |
| /// bitmaps, asynchronous streams of images, and links to Transforms in other processes. |
| /// |
| /// Transforms have attributes. Child Transforms inherit the combined attributes of their |
| /// parents. Content attached to a Transform is also affected by that Transform's attributes. |
| /// |
| /// When a sub-graph of Transforms is rendered, Content will be rendered back-to-front, starting |
| /// with the Content on the root transform, and continuing recursively through all of its child |
| /// Transforms in the order the children were added. See AddChild() for more information. |
| /// |
| /// Zero is not a valid transform id. All other values are valid, assuming they are not already |
| /// in use (see ReleaseTransform() for more details). |
| CreateTransform(TransformId transform_id); |
| |
| // ***** Attributes ***** |
| |
| /// All Transform objects support all attributes. |
| /// |
| /// Geometric attributes are applied in the following order: |
| /// 1. Translation (relative to the parent's coordinate space) |
| /// 2. Orientation (around the new origin as defined by the translation) |
| /// |
| /// Sets the translation on a Transform. The order of geometric attribute application is |
| /// addressed above. |
| SetTranslation(TransformId transform_id, fuchsia.math.Vec translation); |
| |
| /// Sets the orientation on a Transform. The order of geometric attribute application is |
| /// addressed in the documentation for SetTranslation(). |
| SetOrientation(TransformId transform_id, Orientation orientation); |
| |
| // Transform management |
| |
| /// Adds a child Transform to a parent Transform. The new child Transform, and any Content |
| /// attached to it or its children, will be rendered on top of the parent's Content, as well as |
| /// any previously added children. |
| AddChild(TransformId parent_transform_id, TransformId child_transform_id); |
| |
| /// Removes a child Transform from a parent Transform. |
| RemoveChild(TransformId parent_transform_id, TransformId child_transform_id); |
| |
| /// Sets the Root Transform for the graph. |
| /// |
| /// The sub-graph defined by the Root Transform and its children will be rendered as Content |
| /// in the linked parent Graph (see LinkToParent()). Any parents of the Root Transform in this |
| /// Graph will be ignored. |
| /// |
| /// The Root Transform, and all children of the Root Transform, are kept alive if they are |
| /// released (see ReleaseTransform() for more details). |
| /// |
| /// There is only ever one Root. Since 0 is not a valid transform id (see CreateTransform()), |
| /// calling SetRootTransform(0) clears the current Root, destroying any previously released |
| /// objects that are not referenced by the new root. |
| SetRootTransform(TransformId transform_id); |
| |
| /// Sets an opacity in linear space to be applied to a transform and its descendents, |
| /// which include other transforms and content. This is meant to support "group opacity", |
| /// which allows multiple images to be rendered as a unit with the same opacity value |
| /// applied over the whole. |
| /// |
| /// TODO (fxbug.dev/44255): The implementation for group opacity is not complete, so at |
| /// the moment |SetOpacity| is only valid when called on a leaf transform. Flatland will |
| /// report an error if the opacity is changed to be anything other than 1.0 on a non-leaf |
| /// node, or if a child is added to an existing leaf node with an opacity value < 1.0. |
| SetOpacity(TransformId transform_id, float32 val); |
| |
| // ***** Content ***** |
| |
| // Content comes in many forms, but most content can be treated conceptually as a bitmap. |
| // Content is attached to Transforms. Each Transform can have, at most, one piece of attached |
| // Content. Content will inherit all of the attributes from its attached Transform (which |
| // inherits the attributes of its parent Transform, and so on). |
| |
| // Content is contained within a unit rectangle, with the top-left corner at the origin of the |
| // coordinate space defined by the attached Transform. |
| |
| // Content constructors |
| |
| /// A Link is a connection between the objects authored in this Graph, and the objects in |
| /// another process. The parent process has control over how the linked Content is integrated |
| /// into their Graph through this Link object, and the object's associated Link properties. |
| /// |
| /// Any illegal operations on ContentLink will cause both ContentLink channel and this Flatland |
| /// channel to be torn down. |
| /// |
| /// `LinkProperties` must have logical_size set. This is the initial size that will drive the |
| /// layout of the child. The logical_size is also used as the default Content size, but |
| /// subsequent changes to the logical_size will have no effect on the Content size. |
| /// |
| /// The logical_size must have positive X and Y components. |
| /// |
| /// Zero is not a valid Link id. All other values are valid, assuming they are not already |
| /// in use for another piece of Content (see ReleaseLink() for more details). |
| /// |
| /// Lifecycle note. The lifetime of the ContentLink channel is bound by the peer GraphLinkToken. |
| /// When the GraphLinkToken dies, this ContentLink channel is destroyed. |
| CreateLink(ContentId link_id, ContentLinkToken token, LinkProperties properties, |
| request<ContentLink> content_link); |
| |
| /// An Image is a bitmap backed by a specific VMO in a BufferCollection. |
| /// |
| /// Image creation requires an allocated BufferCollection registered with Allocator. This |
| /// function will fail unless all clients of the specified BufferCollection have set their |
| /// constraints. |
| /// |
| /// The Image must reference a valid VMO index and must have ImageProperties that fall within |
| /// the constraints specified by the backing BufferCollection (i.e. width and height within a |
| /// valid range, etc.) |
| /// |
| /// Zero is not a valid Image id. All other values are valid, assuming they are not already in |
| /// use for another piece of Content (see ReleaseImage() for more details). |
| CreateImage(ContentId image_id, |
| fuchsia.ui.composition.BufferCollectionImportToken import_token, |
| uint32 vmo_index, |
| ImageProperties properties); |
| |
| /// The content size for an Image is the size of the rectangle in the parent's space that the |
| /// image occupies. This combined with the global translation of the transform it is attached |
| /// to determines the size and location of where the content is rendered on the display. |
| SetImageDestinationSize(ContentId image_id, fuchsia.math.SizeU size); |
| |
| // Content management |
| |
| /// Setting a piece of Content on a Transform makes that Content visible in the render tree as |
| /// long as the Transform is visible from the root Transform. The Content will be rendered |
| /// before, and therefore "behind", any Content attached to the descendants of the Transform. |
| /// |
| /// Because each Transform can have, at most, a single piece of Content on it, calling this |
| /// function on a Transform that already has Content will replace that Content. |
| /// |
| /// Calling this function with a Content id of 0 will remove any Content currently on the |
| /// Transform. |
| SetContent(TransformId transform_id, ContentId content_id); |
| |
| // Content mutators |
| |
| /// Transforms are usually sufficient to change how Content is presented. Links, however, have |
| /// special properties that are not part of the Transform hierarchy. Those properties can be set |
| /// using this function. |
| /// |
| /// The logical_size must have positive X and Y components. |
| SetLinkProperties(ContentId link_id, LinkProperties properties); |
| |
| // ***** Cleanup operations ***** |
| |
| /// Released Transforms will be garbage collected by the system once they are no longer |
| /// necessary for rendering. For Transforms, this means there is no path from any unreleased |
| /// Transform to the newly-released Transform. |
| /// |
| /// Once released, the id immediately goes out of scope for future function calls and can be |
| /// reused when creating new Transforms. |
| /// |
| /// It is an error to call functions with a released id (unless that id has been reused to |
| /// construct a new Transform). |
| ReleaseTransform(TransformId transform_id); |
| |
| /// Releasing a Link removes the attached sub-Graph from the scene, even if the Link is still |
| /// connected to a Transform. Unlike other resources, Links are garbage collected by the system |
| /// during the next Present() because a released Link is guaranteed to provide no renderable |
| /// content. |
| /// |
| /// Use SetContent(transform_id, 0) to clean up references to deleted Links. |
| /// |
| /// Despite having a return type, this function is still feed-forward like LinkToParent() and |
| /// requires a call to Present() to be executed. The ContentLinkToken will be returned after the |
| /// presented operations have been executed. |
| ReleaseLink(ContentId link_id) -> (ContentLinkToken tokid); |
| |
| /// Released Images will be garbage collected by the system once they are no longer necessary |
| /// for rendering. For Images, this means the Image is no longer attached to any Transform and |
| /// any pending rendering that references the Image is complete. |
| /// |
| /// Use SetContent(transform_id, 0) to clean up references to released Images. |
| /// |
| /// Once released, the id immediately goes out of scope for future function calls and can be |
| /// reused when creating new Images. |
| /// |
| /// It is an error to call functions with a released id (unless that id has been reused to |
| /// construct a new Image). |
| ReleaseImage(ContentId image_id); |
| |
| /// Set debug name of the current client that can be used by Flatland to print as a prefix |
| /// to logs to help client distinguish what is theirs. |name| can be an arbitrary string, but |
| /// the current process name (see fsl::GetCurrentProcessName()) is a good default. |
| SetDebugName(string:64 name); |
| }; |
| |
| /// This API connects to the singleton "primary display", and allows a tree of Flatland content to |
| /// be attached underneath. Only one FlatlandDisplay client connection is allowed at one time. |
| // TODO(fxbug.dev/76643): In the future this will be replaced with something |
| // that allows control over which hardware display to use. This API is sufficient for the purpose |
| // of initial bringup of Flatland. |
| [Discoverable] |
| protocol FlatlandDisplay { |
| // TODO(fxbug.dev/76643): Consider whether this should be: |
| // SetLink(ContentLinkToken token) -> (ContentLinkToken? previous_content_token); |
| // ... this way, whoever is using the display can keep track of multiple different pieces |
| // of content, and choose which to display. OTOH, an argument could be made that this API |
| // should be kept as simple as possible, and if one wanted to do this sort of thing they should |
| // create their own Flatland instance and do the content management there. |
| SetContent(ContentLinkToken token, request<ContentLink> content_link); |
| }; |