blob: e1fc72109c3c327ab79932c029b190d93d0ea40e [file] [log] [blame]
// Copyright 2021 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.
deprecated_syntax;
library fuchsia.ui.composition;
using fuchsia.math;
using fuchsia.scenic.scheduling;
using zx;
/// The set of error codes returned in [`OnNextFrameBegin`]. Everything except NO_ERROR, causes
/// Flatland channel to be closed.
enum Error {
/// Indicates that the parameters used the function calls are invalid.
BAD_OPERATION = 1;
/// Indicates that `additional_present_credits` 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 [`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 that handed out GraphLink 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 that handed out GraphLink 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 that handed out ContentLink to be closed.
GetStatus() -> (ContentLinkStatus status);
};
/// A typed wrapper for a channel, representing the child endpoint of a Link. No messages will be
/// sent over this channel, because it is only used as an unclonable object with peer.
resource struct GraphLinkToken {
zx.handle:CHANNEL value;
};
/// A typed wrapper for a channel, representing the parent endpoint of a Link. No messages will be
/// sent over this channel, because it is only used as an unclonable object with peer.
resource struct ContentLinkToken {
zx.handle:CHANNEL 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. Not signaling `acquire_fences` will block the current [`Present`]
/// as well as the following ones even if their `acquire_fences` are signaled.
///
/// 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 `unsquashable` is true, then the update is guaranteed to be uniquely shown for at
/// least one vsync interval.
///
/// If `unsquashable` is false, then the update can be combined with those that come after
/// it.
///
/// If absent, `unsquashable` is false.
4: bool unsquashable;
};
/// 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.scenic.scheduling.PresentationInfo>:8;
/// Fields that a client needs in order to produce its next frame, returned in
/// [`OnNextFrameBegin`]. Each field is guaranteed to be set and contain valid information.
table OnNextFrameBeginValues {
/// The number of *additional* [`Present`] calls allowed to the client so that they
/// can call [`Present`] further times. This is a delta in the present
/// credit budget, not the absolute number of present credits.
1: uint32 additional_present_credits;
/// Information about future presentation and latch times that a client may aim for
/// precise scheduling behavior.
2: FuturePresentationInfos future_presentation_infos;
};
/// 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)),
/// an [`OnError`] event is emitted. Operations that produce errors are ignored and
/// the channel is closed.
///
/// If the execution is completed successfully, [`OnNextFrameBegin`] emits NO_ERROR along
/// with other valid fields.
///
/// The client may only call [`Present`] when they have a non-zero number
/// of present credits, which are tracked by the server. The server may
/// increment the number of credits when it fires the [`OnNextFrameBegin`] event, which
/// informs the client when it receives additional present credits. Each [`Present`]
/// call uses one present credit and decrements the server count by one. If
/// the client calls [`Present`] with no present credits, the server will return a
/// `NO_PRESENTS_REMAINING` error.
///
/// The client should assume that prior to receiving any [`OnNextFrameBegin`]
/// events, they have one present credit.
///
/// Every [`Present`] call results in one [`OnNextFrameBegin`] 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.composition/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 decisions.
///
/// Importantly, OnNextFrameBegin is only fired when the client has one or
/// more present credits, including what is returned in this event. It is
/// therefore safe to present once every time this event fires.
///
/// - response `values` the table of information a client needs to produce
/// its next frame. See [`OnNextFrameBeginValues`] for more information.
-> OnNextFrameBegin(OnNextFrameBeginValues values);
/// This event is fired whenever a set of one or more [`Present`]s are
/// presented simultaneously, and are therefore no longer in flight.
///
/// This event signifies that the commands enqueued before the [`Present`]
/// have taken effect in the scene graph, and are globally visible.
///
/// Clients do NOT have to implement a handler for this event for basic
/// frame scheduling, unless they explicitly want feedback on prior frame
/// presentation. All future frame information is given in the [`OnNextFrameBegin`]
/// event.
///
/// TODO(fxbug.dev/63305): remove `num_presents_allowed` from this event.
-> OnFramePresented(fuchsia.scenic.scheduling.FramePresentedInfo frame_presented_info);
/// If an error occurrs after a [`Present`], an `OnError` event will fire
/// with associated information.
///
/// Errors will close the connection with the client.
///
/// - response `error` the error a client may receive after performing some
/// invalid operations.
-> OnError(Error error);
// ***** 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 two endpoints of channel 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. Each Graph can only have one parent.
///
/// This function is queued, 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 [`SetRootTransform`]. 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 *****
/// 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);
// ***** Transform 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.
/// 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,
BufferCollectionImportToken import_token,
uint32 vmo_index,
ImageProperties properties);
/// This function is used to determine the region (in texel space) of an image that will be
/// used by Flatland when rendering. The image to be sampled is referenced by |image_id| and
/// the sample region is specified by |rect| which itself is comprised of an origin point (x,y)
/// as well as a width and height, in unnormalized coordinates. It is illegal to call this
/// function on non-image content, or to sample a region outside of the texel space of the
/// image. In other words, the region specifed by |rect| must not exceed the ranges
/// (0, image_width) and (0, image_height). If (rect.x + rect.width > image_width) or
/// (rect.y + rect.height > image_height) or if any of the values are negative, this will
/// result in an error.
SetImageSampleRegion(ContentId image_id, fuchsia.math.RectF rect);
/// 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.
///
/// A Content may be set on more than one Transform.
///
/// 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);
};