| // 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.ui.scenic; | 
 |  | 
 | using zx; | 
 | using fuchsia.images; | 
 | using fuchsia.scenic.scheduling; | 
 | using fuchsia.sysmem; | 
 |  | 
 | /// Arguments passed into Present2(). Note that every argument is mandatory. | 
 | type Present2Args = resource table { | 
 |     /// `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. | 
 |     /// | 
 |     /// 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. Requested presentation | 
 |     /// times must be monotonically increasing. | 
 |     /// | 
 |     /// Using a `requested_presentation_time` in the future schedules the enqueued | 
 |     /// operations to take visible effect as closely as possible to or after | 
 |     /// the stated time, but no earlier. | 
 |     /// | 
 |     /// Each rendered frame has a target presentation time. This is when Scenic | 
 |     /// aims to have the frame presented to the user. Before rendering a frame, | 
 |     /// the scene manager applies all enqueued operations associated with all | 
 |     /// prior calls to Present2 whose `requested_presentation_time` is on or | 
 |     /// before the frame's target presentation time. | 
 |     1: requested_presentation_time zx.time; | 
 |  | 
 |     /// Scenic will wait until all of a session's `acquire_fences` are ready | 
 |     /// before it will execute the presented commands. | 
 |     2: acquire_fences vector<zx.handle:EVENT>; | 
 |  | 
 |     /// `release_fences` is the list of events that will be signalled by Scenic when | 
 |     /// the following Present2 call's `acquire_fences` has been signalled, and | 
 |     /// the updated session state has been fully committed: future frames will be | 
 |     /// rendered using this state, and all frames generated using previous session | 
 |     /// states have been fully-rendered and presented to the display. | 
 |     3: release_fences vector<zx.handle:EVENT>; | 
 |  | 
 |     /// `requested_prediction_span` is the amount of time into the future Scenic | 
 |     /// will provide predictions for. A span of 0 is guaranteed to provide at | 
 |     /// least one future time. | 
 |     4: requested_prediction_span zx.duration; | 
 | }; | 
 |  | 
 | /// Client use Sessions to interact with a Scenic instance by enqueuing commands | 
 | /// that create or modify resources. | 
 | protocol Session { | 
 |     Enqueue(resource struct { | 
 |         cmds vector<Command>; | 
 |     }); | 
 |  | 
 |     // TODO(jeffbrown): Defining presentation time in terms of `CLOCK_MONOTONIC` | 
 |     // simplifies synchronization across subsystems but it might be too simple. | 
 |     // We should consider using a synthetic timebase and describing its relation | 
 |     // to other clocks separately.  That would make it possible to present | 
 |     // content (animations, media, and UI) in "slow mode" simply by varying the | 
 |     // timing relation, assuming clients play along. | 
 |     // TODO(fxbug.dev/23637): document invariants that apply to `presentation_info`.  Is it | 
 |     // strong enough to guarantee that receiving the response means that all | 
 |     // previously-enqueued Commands have been applied?  Or does it need to be stronger, | 
 |     // e.g. that all frames based on previous presentations are completely done, | 
 |     // and subsequent frames will be rendered based on the most recent presented | 
 |     // content? | 
 |     /// Present all previously enqueued operations.  In order to pipeline the | 
 |     /// preparation of the resources required to render the scene, two lists of | 
 |     /// fences (implemented as events) are passed. | 
 |     /// | 
 |     /// SCHEDULING PRESENTATION | 
 |     /// | 
 |     /// `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. | 
 |     /// | 
 |     /// Using a desired 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 desired presentation time in the future schedules the enqueued | 
 |     /// operations to take visible effect as closely as possible to or after | 
 |     /// the stated time (but no earlier). | 
 |     /// | 
 |     /// Each rendered frame has a target presentation time.  Before rendering | 
 |     /// a frame, the scene manager applies all enqueued operations associated | 
 |     /// with all prior calls to `Present()` whose desired presentation time | 
 |     /// is on or before the frame's target presentation time. | 
 |     /// | 
 |     /// The `Present()` method does not return until the scene manager begins | 
 |     /// preparing the first frame which includes its presented content. | 
 |     /// Upon return, the `PresentationInfo` provides timing information for the | 
 |     /// frame which includes the presented content. | 
 |     /// | 
 |     /// To present new content on each successive frame, wait for `Present()` | 
 |     /// to return before calling `Present()` again with content for the next | 
 |     /// frame. | 
 |     /// | 
 |     /// It is also possible to enqueue and present successive frames of content | 
 |     /// all at once with increasing desired presentation times, incrementing by | 
 |     /// `PresentationInfo.presentation_interval` for each one. | 
 |     /// | 
 |     /// Animation updates are also coordinated in terms of presentation time. | 
 |     /// | 
 |     /// SYNCHRONIZATION | 
 |     /// | 
 |     /// `acquire_fences` are used by Scenic to wait until all of the session's | 
 |     /// resources are ready to render (or to allow downstream components, such as | 
 |     /// the Vulkan driver, to wait for these resources). | 
 |     /// | 
 |     /// For example, Fuchsia's Vulkan driver allows an zx::event to be obtained | 
 |     /// from a VkSemaphore.  This allows a Scenic client to submit a Vulkan command | 
 |     /// buffer to generate images/meshes/etc., and instructing Vulkan to signal a | 
 |     /// VkSemaphore when it is done.  By inserting the zx::event corresponding to | 
 |     /// this semaphore into `acquire_fences`, the client allows Scenic to submit work | 
 |     /// to the Vulkan driver without waiting on the CPU for the event to be | 
 |     /// signalled. | 
 |     /// | 
 |     /// `release_fences` is a list of events that will be signalled by Scenic when | 
 |     /// the updated session state has been fully committed: future frames will be | 
 |     /// rendered using this state, and all frames generated using previous session | 
 |     /// states have been fully-rendered and presented to the display. | 
 |     /// | 
 |     /// Together, `acquire_fences` and `release_fences` are intended to allow clients | 
 |     /// to implement strategies such as double-buffering.  For example, a client | 
 |     /// might do the following in the Scenic subsystem: | 
 |     ///   1) create two Image with resource IDs #1 and #2. | 
 |     ///   2) create two Materials with resource IDs #3 and #4, which respectively | 
 |     ///      use Images #1 and #2 as their texture. | 
 |     ///   3) create a tree of Nodes and attach them to the scene. | 
 |     ///   4) set one of the nodes above, say #5, to use Material #3. | 
 |     ///   5) submit a Vulkan command-buffer which renders into Image #1, and | 
 |     ///      will signal a VkSemaphore. | 
 |     ///   6) call Present() with one acquire-fence (obtained from the VkSemaphore | 
 |     ///      above) and one newly-created release-fence. | 
 |     /// | 
 |     /// After the steps above, Scenic will use the committed session state to render | 
 |     /// frames whenever necessary.  When the client wants to display something | 
 |     /// different than Image #1, it would do something similar to steps 4) to 6): | 
 |     ///   7) set Node #5 to use Material #4. | 
 |     ///   8) submit a Vulkan command-buffer which renders into Image #1, and | 
 |     ///      will signal a VkSemaphore. | 
 |     ///   9) call Present() with one acquire-fence (obtained from the VkSemaphore | 
 |     ///      above) and one newly-created release-fence. | 
 |     /// | 
 |     /// Finally, to continually draw new content, the client could repeat steps | 
 |     /// 4) to 9), with one important difference: step 5) must wait on the event | 
 |     /// signalled by step 9).  Otherwise, it might render into Image #1 while that | 
 |     /// image is still being used by Scenic to render a frame.  Similarly, step 8) | 
 |     /// must wait on the event signalled by step 6). | 
 |     /// | 
 |     /// The scenario described above uses one acquire-fence and one release-fence, | 
 |     /// but it is easy to imagine cases that require more.  For example, in addition | 
 |     /// to using Vulkan to render into Images #1 and #2, the client might also | 
 |     /// upload other resources to Vulkan on a different VkQueue, which would | 
 |     /// would signal a separate semaphore, and therefore require an additional | 
 |     /// acquire-fence. | 
 |     /// | 
 |     /// Note: `acquire_fences` and `release_fences` are only necessary to synchronize | 
 |     /// access to memory (and other external resources).  Any modification to | 
 |     /// resources made via the Session API are automatically synchronized. | 
 |     @transitional | 
 |     Present(resource struct { | 
 |         presentation_time uint64; | 
 |         acquire_fences vector<zx.handle:EVENT>; | 
 |         release_fences vector<zx.handle:EVENT>; | 
 |     }) -> (struct { | 
 |         presentation_info fuchsia.images.PresentationInfo; | 
 |     }); | 
 |  | 
 |     /// Present all previously enqueued operations. In order to pipeline the | 
 |     /// preparation of the resources required to render the scene, two lists of | 
 |     /// fences, implemented as events, are passed. | 
 |     /// | 
 |     /// When a client calls Present2, they receive an immediate callback | 
 |     /// consisting of the same information they would get as if they had called | 
 |     /// `RequestPresentationTimes` with the equivalent | 
 |     /// `requested_prediction_span`. See its documentation below for more | 
 |     /// information, as Present2's functionality is a superset of it. | 
 |     /// | 
 |     /// Then, when the commands flushed by Present2 make it to display, an | 
 |     /// `OnFramePresented` event is fired. This event includes information | 
 |     /// pertaining to all Present2s that had content that were part of that | 
 |     /// frame. | 
 |     /// | 
 |     /// Clients may only use one of Present/Present2 per Session. | 
 |     /// Switching between both is an error that will result in the Session being | 
 |     /// closed. | 
 |     /// | 
 |     /// See `Present2Args` documentation above for more detailed information on | 
 |     /// what arguments are passed in and their role. | 
 |     Present2(resource struct { | 
 |         args Present2Args; | 
 |     }) -> (struct { | 
 |         request_presentation_times_info fuchsia.scenic.scheduling.FuturePresentationTimes; | 
 |     }); | 
 |  | 
 |     /// This event is fired whenever a set of one or more Present2s are | 
 |     /// presented simultaenously, and are therefore no longer in flight. | 
 |     -> OnFramePresented(struct { | 
 |         frame_presented_info fuchsia.scenic.scheduling.FramePresentedInfo; | 
 |     }); | 
 |  | 
 |     /// Returns information about future presentation times, and their | 
 |     /// respective latch points. Clients can use the returned information to | 
 |     /// make informed scheduling decisions: if a client wants their frame to be | 
 |     /// displayed at a given `presentation_time`, they should aim to have all | 
 |     /// `acquire_fences` fired before the associated `latch_point`. | 
 |     /// | 
 |     /// Scenic will attempt to return predictions that span a duration equal to | 
 |     /// `requested_prediction_span`, up to a limit. | 
 |     /// | 
 |     /// A value of 0 is guaranteed to give at least one future presentation info. | 
 |     RequestPresentationTimes(struct { | 
 |         requested_prediction_span zx.duration; | 
 |     }) -> (struct { | 
 |         request_presentation_times_info fuchsia.scenic.scheduling.FuturePresentationTimes; | 
 |     }); | 
 |  | 
 |     /// Registers BufferCollection referenced by the `token` and sets contraints on it. | 
 |     /// It does not block on the buffers being allocated until content backed by one of the | 
 |     /// collection's VMOs is created, e.g. an Image2. | 
 |     /// | 
 |     /// A value of 0 for the `buffer_id` is invalid. All other values are valid as long as they | 
 |     /// are not currently in use. | 
 |     RegisterBufferCollection(resource struct { | 
 |         buffer_id uint32; | 
 |         token client_end:fuchsia.sysmem.BufferCollectionToken; | 
 |     }); | 
 |  | 
 |     /// Deregisters the BufferCollection previously registered with the `buffer_id` and sets it | 
 |     /// to be garbage collected as soon as it is no longer referenced by any resources. | 
 |     /// | 
 |     /// Only `buffer_id` that have been previously registered and not yet deregistered are valid. | 
 |     DeregisterBufferCollection(struct { | 
 |         buffer_id uint32; | 
 |     }); | 
 |  | 
 |     /// Set an optional debug name for the session. The debug name will be | 
 |     /// output in things such as logging and trace events. | 
 |     SetDebugName(struct { | 
 |         debug_name string; | 
 |     }); | 
 | }; | 
 |  | 
 | /// Listens for events which occur within the session. | 
 | protocol SessionListener { | 
 |     /// Called when an error has occurred and the session will be torn down. | 
 |     OnScenicError(struct { | 
 |         error string; | 
 |     }); | 
 |  | 
 |     /// Called to deliver a batch of one or more events to the listener. | 
 |     /// Use `SetEventMaskCmd` to enable event delivery for a resource. | 
 |     OnScenicEvent(resource struct { | 
 |         events vector<Event>; | 
 |     }); | 
 | }; |