// Copyright 2018 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.images;

using zx;

/// ImagePipe is a mechanism for streaming shared images between a producer
/// and a consumer which may be running in different processes.
///
/// Conceptually, the image pipe maintains a table of image resources supplied
/// by the producer into which graphical content may be stored as well as a
/// presentation queue containing a sequence of images which the producer has
/// asked the consumer to present.
///
/// The presentation queue is initially empty.
///
/// Each entry in the presentation queue consists of an image together with a
/// pair of optional synchronization fences:
/// - Acquire fence: signaled by the producer when the image is ready to be consumed
/// - Release fence: signaled by the consumer when the image is free to be freed or
///   modified by the producer
///
/// The producer performs the following sequence of steps to present content:
/// - Allocate and add some number of images (often 2 or 3) to the image pipe
///   to establish a pool using `AddImage()`.
/// - Obtain the next available image from the pool.
/// - Ask the consumer to enqueue an image for presentation and provide fences
///   using `PresentImage()`.
/// - Start rendering the image.
/// - Signal the image's acquire fence when rendering is complete.
/// - Loop to present more image, listen for signals on release fences to recycle
///   images back into the pool.
///
/// The consumer performs the following sequence of steps for each image which
/// is enqueued in the presentation queue:
/// - Await signals on the image's acquire fence.
/// - If the fence wait cannot be satisfied or if some other error is detected,
///   close the image pipe.
///   Otherwise, begin presenting the image's content.
/// - Retire the previously presented image (if any) from the presentation queue
///   and signal its release fence when no longer needed.
/// - Continue presenting the same image until the next one is ready.  Loop.
///
/// If the producer wants to close the image pipe, it should:
/// - Close its side of the connection.
/// - Wait on all release fences for buffers that it has submitted with
///   `PresentImage()`.
/// - Proceed with resource cleanup.
///
/// When the consumer detects the image pipe has closed, it should:
/// - Stop using/presenting any images from the pipe.
/// - Unmap all VMOs associated with the images in the pipe.
/// - Close all handles to the VMOs.
/// - Signal all release fences for presented and queued buffers.
/// - Close all handles to fences.
/// - Close its side of the connection.
///
/// When either party detects that a fence has been abandoned (remotely closed
/// without being signaled) it should assume that the associated image is in
/// an indeterminate state.  This will typically happen when the other party
/// (or one of its delegates) has crashed.  The safest course of action is to
/// close the image pipe, release all resources which were shared with the
/// other party, and re-establish the connection to recover.
protocol ImagePipe {
    /// Adds an image resource to image pipe.
    ///
    /// The `memory` is the handle of a memory object which contains the image
    /// data.  It is valid to create multiple images backed by the same memory
    /// object; they may even overlap.  Consumers must detect this and handle
    /// it accordingly.  The `offset_bytes` indicates the offset within the
    /// memory object at which the image data begins.  The `size_bytes`
    /// indicates the amount of memory from `memory` that should be utilized.
    /// The type of memory stored in the VMO is `memory_type` (e.g. GPU memory,
    /// host memory).
    ///
    /// The following errors will cause the connection to be closed:
    /// - `image_id` is already registered
    /// - `image_info` represents a format not supported by the consumer
    /// - `memory` is not a handle for a readable VMO
    /// - the image data expected at `offset_bytes` according to the `image_info`
    ///   exceeds the memory object's bounds
    AddImage(uint32 image_id, ImageInfo image_info,
             zx.handle:VMO memory, uint64 offset_bytes, uint64 size_bytes, MemoryType memory_type);

    /// Removes an image resource from the pipe.
    ///
    /// The `image_id` is detached from the image resource and is free to be
    /// reused to add a new image resource.
    ///
    /// Removing an image from the image pipe does not affect the presentation
    /// queue or the currently presented image.
    ///
    /// The producer must wait for all release fences associated with the image to
    /// be signaled before freeing or modifying the underlying memory object since
    /// the image may still be in use in the presentation queue.
    ///
    /// The following errors will cause the connection to be closed:
    /// - `image_id` does not reference a currently registered image resource
    RemoveImage(uint32 image_id);

    /// Enqueues the specified image for presentation by the consumer.
    ///
    /// The `acquire_fences` are a set of fences which must all be signaled by the
    /// producer before the consumer presents the image.
    /// The `release_fences` are set of fences which must all be signaled by the
    /// consumer before it is safe for the producer to free or modify the image.
    /// `presentation_time` specifies the time on or after which the
    /// client would like the enqueued operations should take visible effect
    /// (light up pixels on the screen), expressed in nanoseconds in the
    /// `CLOCK_MONOTONIC` timebase.  Desired presentation times must be
    /// monotonically non-decreasing.
    ///
    /// `presentation_info` returns timing information about the submitted frame
    /// and future frames (see presentation_info.fidl).
    ///
    /// The following errors will cause the connection to be closed:
    /// - `image_id` does not reference a currently registered image resource
    PresentImage(uint32 image_id, uint64 presentation_time,
                 vector<zx.handle:EVENT> acquire_fences, vector<zx.handle:EVENT> release_fences)
        -> (PresentationInfo presentation_info);
};
