// 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.sysmem;

// The set of error codes returned by Flatland::Present().
enum Error {
    BAD_OPERATION = 0;
};

// TODO(36766): Unify with math types for other APIs.
struct Vec2 {
    float32 x;
    float32 y;
};

enum Orientation {
    CCW_0_DEGREES = 0;
    CCW_90_DEGREES = 1;
    CCW_180_DEGREES = 2;
    CCW_270_DEGREES = 3;
};

/// 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: Vec2 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: Vec2 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 = 0;
    DISCONNECTED_FROM_DISPLAY = 1;
};

/// 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.
    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.
    GetStatus() -> (GraphLinkStatus status);
};

enum ContentLinkStatus {
    /// The underlying Graph has connected its Link, called Present(), the acquisition fences of
    /// the Present() call have all be reached, and the Graph's content has been rendered to an
    /// output device.
    CONTENT_HAS_PRESENTED = 0;
};

/// 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.
    GetStatus() -> (ContentLinkStatus status);
};

/// A typed wrapper for an eventpair, representing the child endpoint of a Link.
struct GraphLinkToken {
    handle<eventpair> value;
};

/// A typed wrapper for an eventpair, representing the parent endpoint of a Link.
struct ContentLinkToken {
    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: Vec2 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 width of the Image in pixels.
    1: uint32 width;
    /// The height of the Image in pixels.
    2: uint32 height;
};

/// A user-defined identifier for a particular transform. See CreateTransform() and
/// ReleaseTransform() for more information.
using TransformId = uint64;

/// A user-defined identifier for a particular Link. See CreateLink() for more information.
using LinkId = uint64;

/// A user-defined identifier for a particular BufferCollection. See RegisterBufferCollection()
/// for more information.
using BufferCollectionId = uint64;

/// A user-defined identifier for a particular Image. See CreateImage() for more information.
using ImageId = uint64;

/// 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.
protocol Flatland {
    /// Complete execution of all feed-forward operations.
    ///
    /// If executing an operation produces an error (e.g., CreateTransform(0)), Present() will
    /// return an error. Operations that produce errors are ignored. Future operations are still
    /// executed.
    ///
    /// TODO(36166): Present should stop execution, and kill the channel, when irrecoverable errors
    /// are detected.
    ///
    /// The client may only call Present() a certain number of times before it must wait for this
    /// function to return. This number or presents remaining is the return value of this function.
    /// The number of presents remaining will never drop without a corresponding call to Present()
    /// by the client. However, it may stay the same, or even increase, with each return from
    /// Present().
    ///
    /// num_presents_remaining will always be >= 1. Present() will not return until the client is
    /// allowed to call Present() again.
    Present() -> (uint32 num_presents_remaining) 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 is formed by creating an event pair, passing one end to the parent (which calls
    /// CreateLink()) and the other end 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 GraphLinkListener (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(), if they wish.
    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.
    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)
    /// 3. Scale (relative to the new rotated origin)
    /// 4. Crop (in the scaled coordinate space)
    ///
    /// Sets the translation on a Transform. The order of geometric attribute application is
    /// addressed above.
    SetTranslation(TransformId transform_id, Vec2 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);

    /// Sets the scale on a Transform. The order of geometric attribute application is addressed
    /// in the documentation for SetTranslation().
    SetScale(TransformId transform_id, Vec2 scale);

    // 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);

    // ***** 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 can be resized using either
    // scale attributes on transforms, or the appropriate Content mutators.

    // 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.
    ///
    /// `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 (see ReleaseLink() for more details).
    CreateLink(LinkId link_id, ContentLinkToken token, LinkProperties properties,
               request<ContentLink> content_link);

    /// A BufferCollection is a set of VMOs created by Sysmem and shared by a number of
    /// participants, one of which is the Flatland Renderer. Some content, such as Images, use a
    /// BufferCollection as their backing memory.
    ///
    /// Flatland participates in the allocation of buffers by setting constraints on the
    /// BufferCollection referenced by the token. It will not block on buffers being allocated
    /// until the client creates content using the BufferCollection.
    ///
    /// Zero is not a valid buffer collection id. All other values are valid, assuming they are not
    /// already in use (see UnregisterBufferCollection() for more details).
    RegisterBufferCollection(BufferCollectionId buffer_id,
                             fuchsia.sysmem.BufferCollectionToken token);

    /// An Image is a bitmap backed by a specific VMO in a BufferCollection.
    ///
    /// Image creation requires an allocated BufferCollection. 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, accepted pixel format, etc.)
    ///
    /// Zero is not a valid image id. All other values are valid, assuming they are not already in
    /// use (see ReleaseImage() for more details).
    CreateImage(ImageId image_id, BufferCollectionId buffer_id, uint32 vmo_index,
                ImageProperties properties);

    // Content management

    /// Setting a Link on a Transform makes the content from the Link visible in the render tree
    /// as long as the Transform is visible from the root Transform. The contents of the Link will
    /// be rendered before, and therefore "behind", any content attached to the descendants of the
    /// Transform.
    ///
    /// Note that setting a Link on a Transform will remove any other content currently attached to
    /// that Transform.
    ///
    /// Calling this function with a Link id of zero will remove any content currently attached to
    /// the given Transform id, including other non-Link Content.
    SetLinkOnTransform(LinkId link_id, TransformId transform_id);

    /// Setting an Image on a Transform makes the contents of the Image visible in the render tree
    /// as long as the Transform is visible from the root Transfrm. The contents of the Image will
    /// be rendered before, and therefore "behind", any content attached to the descendants of the
    /// Transform.
    ///
    /// Note that setting an Image on a Transform will remove any other content currently attached
    /// to that Transform.
    ///
    /// Calling this function with a Image id of zero will remove any content currently attached to
    /// the given Transform id, including other non-Image content.
    SetImageOnTransform(ImageId image_id, TransformId transform_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(LinkId link_id, LinkProperties properties);

    /// The Content size for a Link is the size of the rectangle in the parent's space that the
    /// Link occupies. This effectively applies a scale to the Link Content equal to the ratio from
    /// its Content size to its logical_size.
    ///
    /// The Link Content size must have positive X and Y components.
    SetLinkSize(LinkId link_id, Vec2 size);

    // ***** Cleanup operations *****

    /// Released Transforms and Content will be garbage collected by the system once they are no
    /// longer necessary for rendering (i.e., there is no path from the Root Transform to the
    /// object, all pending rendering has completed, and new Content is available). The only
    /// exceptions are Link objects (see ReleaseLink() for more details).
    ///
    /// However, once released, the id immediately goes out of scope for future function calls, and
    /// can be reused by the client when creating new Transforms and Content.
    ///
    /// It is an error to call Graph functions on a released id (unless that id has been reused to
    /// construct a new object).
    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 Content, Links are garbage collected by the system
    /// during the next Present() because a released Link is guaranteed to provide no renderable
    /// content.
    ///
    /// Use SetLinkOnTransform(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(LinkId id) -> (ContentLinkToken token);
};
