blob: d4dadec7b28b432f8e23f6ccdebe9d541ebab005 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
[DartPackage="mojo_services"]
module mojo.gfx.composition;
import "mojo/services/gfx/composition/interfaces/nodes.mojom";
import "mojo/services/gfx/composition/interfaces/resources.mojom";
import "mojo/services/gfx/composition/interfaces/scene_token.mojom";
import "mojo/services/gfx/composition/interfaces/scheduling.mojom";
// The node id which represents the root of a scene.
//
// Every scene should have a root node which uses this id unless the scene
// has no content at all.
const uint32 kSceneRootNodeId = 0;
// The scene version used as a placeholder when the version doesn't matter.
//
// This version code can be used by a consumer of a scene to express that
// it would like to consume the latest version of the scene.
//
// This version code can also be used by a scene itself if it has not
// received any other specific indications as to the version it should
// report when publishing its content.
const uint32 kSceneVersionNone = 0;
// A scene component maintains a description of some graphical content which
// an application would like to render. This description consists of
// resources and nodes.
//
// LIFECYCLE
//
// Use |Compositor.CreateScene()| to create a scene. The application
// uses the |Scene| interface to manage the scene's content and implements
// the |SceneListener| interface to handle events.
//
// To destroy a scene, simply close the |Scene| message pipe.
//
// CONTENT
//
// Resources are references to foreign objects which are being imported into
// the scene graph, such as images and other scenes. Each resource must be
// given a locally unique identifier when it is bound to the scene.
//
// Nodes express the geometry and content of the scene, such as images and
// references to embedded scenes. Nodes are arranged to form a directed
// acyclic graph of drawing commands.
//
// The root node of the scene has the special id of |kSceneRootNodeId|.
//
// ATOMICITY
//
// To ensure atomicity of updates, the evolution of a scene occurs in two
// phases: update and publish. Incremental changes to the scene made during
// the update phase are not observed until published.
//
// - Update phase: To construct the next state of a scene, the scene owner
// issues any number of scene update requests to add, update, or remove
// resources and nodes.
//
// - Publish phase: When the next state of a scene is fully constructed, the
// scene owner issues a request to publish its changes to the scene and
// assigns it a version identifier. The version identifer may be used
// in scene references to coordinate updates across multiple scenes which
// must be synchronized.
//
// Once the scene has been published, the scene owner may begin to construct
// the next state without disrupting the state just published.
//
// SYNCHRONIZATION
//
// To ensure synchronization of updates across scenes, some additional work
// is needed.
//
// For example, consider the case of a scene X which embeds two other scenes
// A and B. If X changes size, it may need to resize A and B as well to
// fit properly within its layout.
//
// To do so, X sends the owners of A and B each a message indicating the
// new size it desires along with new scene version identifiers V(A) and
// V(B) which the owners of A and B must use when they publish the new scene
// state which incorporates the requested size change.
//
// Meanwhile, X produces a new scene of its own taking into account its
// new size. As part of constructing this new scene, it binds to the V(A)
// and V(B) versions of A and B to express its dependence on A and B
// having been updated to the new size.
//
// Propagating version information top-down through the scene graph in
// this manner allows for state changes to be synchronized in a purely
// feed-forward manner.
//
// CONCURRENCY
//
// In the above synchronization example, version numbers were used to
// couple the state of one scene with others that it depends on.
// What should happen if these dependencies are not satisfied promptly?
//
// Suppose X and A quickly produce new scenes with the new size but
// B is taking longer than anticipated to do so. We have a few choices:
//
// - Stall: The compositor could continue to show the old state of X, A, and B
// until such time as all three have published their new versions.
//
// - Recover: The compositor could realize that X and A are already up to date
// but B is lagging and choose to apply a transformation to B's old content
// cover for the lag, such as by scaling, clipping, masking, or discarding
// B's old content.
//
// - Speculate: The compositor could allow X to provide alternate descriptions
// of the scene in the case where A or B are not keeping up so that it
// can more finely control the recovery policy.
//
// To maximize concurrency, we adopt the latter approach.
//
// SCHEDULING
//
// The scene provides support for scheduling frames via its associated
// |FrameScheduler| interface. Use the scheduler to obtain frame timing
// information and to throttle updates to match the display refresh rate
// (ie. with vsync).
interface Scene {
// Sets the listener for receiving events from the scene.
//
// If |listener| is null, then the previously set listener is removed.
SetListener(SceneListener? listener);
// Applies a batch of incremental updates to the contents of the scene.
//
// Incremental changes can be split across any number of updates but it is
// more efficient to process them in batches. Updates have no visible
// effect until the scene owner calls |Publish()| to publish them.
//
// Updates are buffered and applied when |Publish()| is called. This means
// it is safe to issue an update which adds a node that refers to a resource
// which is not added until a subsequent update as long as the scene is
// not published in between those updates.
Update(SceneUpdate update);
// Publishes the scene and tags it with the specified version.
//
// All pending incremental updates are applied atomically when the scene
// is published and the new state is labeled with the version indicated
// in the associated metadata.
//
// The |metadata| describes how the published scene should be presented.
// If null, this method behaves as if a |SceneMetadata| object initialized
// with default values had been supplied.
//
// Publishing a scene graph applies all pending updates. It is an error
// to publish updates which cause the scene state to become inconsistent,
// such as by having nodes which refer to non-existent resources or
// introducing cycles in the scene's nodes; the connection will be closed.
Publish(SceneMetadata? metadata);
// Gets a scheduler to receive frame timing information for the scene.
GetScheduler(FrameScheduler& scheduler);
};
// An interface applications may implement to receive events from a scene.
interface SceneListener {
// Called when a resource has become unavailable.
//
// Any nodes which are using the resource will be considered blocked
// until the resource is replaced or the nodes using it are removed.
OnResourceUnavailable(uint32 resource_id) => ();
};
// A batch of incremental changes to be applied to a scene.
struct SceneUpdate {
// If true, clears all resources before processing the update.
bool clear_resources = false;
// If true, clears all nodes before processing the update.
bool clear_nodes = false;
// Resources to be added, updated, or removed, indexed by resource id.
// The value replaces the definition of the resource with the given id.
// If the value is null, then the resource is removed from the scene.
map<uint32, Resource?>? resources;
// Nodes to be added, updated, or removed, indexed by node id.
// The value replaces the definition of the node with the given id.
// If the value is null, then the node is removed from the scene.
//
// The root node must have an id of 0.
map<uint32, Node?>? nodes;
};
// Describes how a published scene should be presented.
struct SceneMetadata {
// The scene's new version number.
//
// Version numbers are usually associated with requests to change the
// state of the scene. For example, the embedder of this scene may send
// it a request to resize its content or change its color and provide a
// new version number that this scene should apply when it publishes the
// first update which addresses this request.
//
// In general, the version number will be provided to the owner of the
// scene by some other party which is in change of synchronizing updates
// across multiple scenes including this one. The other party will
// frequently be the owner of some other scene which embeds this one.
//
// In certain cases there might not be a version number provided for
// synchronization. When this happens, set |version| to |kSceneVersionNone|.
//
// Note that version numbers are unordered; there is no need to increment
// them monotonically. Values may also be reused at will.
uint32 version = 0; // kSceneVersionNone
// A timestamp indicating approximately when the published contents of the
// scene are to be shown on the display output assuming everything is
// fully rendered and submitted by the appropriate deadline.
//
// Expressed in microseconds in the |MojoTimeTicks| timebase.
//
// A value of 0 means "as soon as possible".
//
// See also: |FrameInfo.presentation_time|.
int64 presentation_time = 0;
};