Jeff Brown | 751f4d3 | 2016-01-26 15:51:01 -0800 | [diff] [blame] | 1 | // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | // Primitives express the geometry of the scene, such as quads and references |
| 6 | // to embedded scenes. Primitives are arranged hierarchically as nodes, |
| 7 | // each with an associated transformation matrix. |
| 8 | |
| 9 | [DartPackage="mojo_services"] |
| 10 | module mojo.gfx.composition; |
| 11 | |
| 12 | import "mojo/services/geometry/interfaces/geometry.mojom"; |
| 13 | import "mojo/services/gfx/composition/interfaces/hit_tests.mojom"; |
| 14 | |
| 15 | // Nodes express the geometry and content of the scene, such as images and |
| 16 | // references to embedded scenes. Nodes are arranged to form a directed |
| 17 | // acyclic graph of drawing commands. |
| 18 | // |
Jeff Brown | 33eb773 | 2016-03-02 11:17:31 -0800 | [diff] [blame] | 19 | // RENDERING |
| 20 | // |
| 21 | // The node graph is renderer in pre-order traversal. Starting from the |
Jeff Brown | 8e37223 | 2016-02-24 14:11:56 -0800 | [diff] [blame] | 22 | // root, the compositor applies the transformation, clip, applies the |
| 23 | // node's operation (if any), then recursively processes the node's children |
| 24 | // according to the node's combinator rule. |
Jeff Brown | 751f4d3 | 2016-01-26 15:51:01 -0800 | [diff] [blame] | 25 | // |
| 26 | // BLOCKED NODES |
| 27 | // |
| 28 | // Due to the asynchronous nature of the system, it may happen that some |
| 29 | // nodes cannot be processed immediately at drawing time because they require |
| 30 | // access to certain resources which are not available, such as a specific |
| 31 | // version of a scene which has yet to be produced by some other application. |
| 32 | // |
| 33 | // When a node cannot be drawn due to an unsatisfied dependency, it is |
| 34 | // said to be "blocked". Blocked nodes prevent rendering of the entire |
| 35 | // subgraph below them. |
| 36 | // |
| 37 | // NODE COMBINATORS |
| 38 | // |
| 39 | // Node combinator rules describe what should happen when a node which is |
| 40 | // otherwise unblocked has one or more blocked children. |
| 41 | // |
| 42 | // With the |MERGE| combinator, the children of a node are all drawn in |
| 43 | // sequence if none of them are blocked, otherwise the node itself is |
| 44 | // blocked. This is the default. |
| 45 | // |
| 46 | // With the |PRUNE| combinator, the children of a node are all drawn in |
| 47 | // sequence while skipping over any of them which are blocked. Blocked |
| 48 | // children will not appear in the output. |
| 49 | // |
| 50 | // With the |FALLBACK| combinator, the first unblocked child of a node is |
| 51 | // drawn and the remaining nodes are ignored. If the node has children |
| 52 | // and all of them are blocked then the node itself is blocked. |
| 53 | // |
| 54 | // Combinators make it possible to express complex rules such as substituting |
| 55 | // missing content for an earlier version of that content or for a placeholder |
| 56 | // if not available. |
| 57 | // |
Jeff Brown | c1287c1 | 2016-03-02 11:17:58 -0800 | [diff] [blame] | 58 | // HIT TESTING |
| 59 | // |
| 60 | // Hit testing is the process of determining which nodes within a scene graph |
| 61 | // should be responsible for handling events which occur within their visual |
| 62 | // space on the screen. |
| 63 | // |
| 64 | // For example, when the user touches objects on a touch screen, the input |
| 65 | // system asks the compositor to performs a hit test at the contact point to |
| 66 | // find the nodes which represent the objects the user wants to interact with. |
| 67 | // The result of the hit test is a list of nodes, in dispatch order, which |
| 68 | // have asked to participate in handling events related to the contact point. |
| 69 | // |
| 70 | // Nodes may be opaque, translucent, or invisible to the hit testing |
| 71 | // process depending on whether they prevent or allow targets visually |
| 72 | // behind them from being hit and whether they can actually be hit, |
| 73 | // as specified by |HitTestBehavior.visibility|. |
| 74 | // |
| 75 | // Nodes are added to the hit test result whenever one of their opaque children |
| 76 | // is hit. This is useful for scrolling containers which may need to intercept |
| 77 | // certain gestures within the space of their children and therefore need to |
| 78 | // be added to the hit test result themselves. |
| 79 | // |
| 80 | // Nodes can also request to prune hit testing for their children, which |
| 81 | // prevents their children from being hit. |
| 82 | // |
| 83 | // Hit testing proceeds recursively in post-order traversal (the reverse of |
| 84 | // the drawing order). Intuitively, this means that the most specific |
| 85 | // (deepest) nodes of the tree are tested before their ancestors. |
| 86 | // |
| 87 | // Starting from the root, the compositor transforms the point of interest |
| 88 | // into the node's coordinate system, rejects the node if the point is |
| 89 | // outside of the node's clip region, otherwise recursively tests the |
| 90 | // node's children (those which were selected by the combinator rule) |
| 91 | // until the first opaque target hit is found, then evaluates the node's |
| 92 | // |HitTestBehavior| to determine whether the node was hit. Nodes are |
| 93 | // accumulated into a hit test result in the order in which they were |
| 94 | // determined to have been hit. |
| 95 | // |
| 96 | // See |HitTestBehavior| for more details. |
| 97 | // |
Jeff Brown | 33eb773 | 2016-03-02 11:17:31 -0800 | [diff] [blame] | 98 | // INSTANCING |
| 99 | // |
| 100 | // The compositor allows nodes to be referenced and reused multiple times |
| 101 | // within a scene (this is known as instancing). Instancing makes it easier |
| 102 | // to take advantage of combinators for interleaving placeholder content |
| 103 | // when certain nodes are blocked from rendering (see above). It also allows |
| 104 | // common elements to be reused if desired. |
| 105 | // |
| 106 | // Likewise, the compositor allows scenes to be multiply referenced so that |
| 107 | // the same content can be presented simultaneously in several places. |
| 108 | // |
| 109 | // CYCLES |
| 110 | // |
| 111 | // The compositor forbids cycles among nodes within scenes and will |
| 112 | // reject scene updates which introduce node cycles by closing the client's |
| 113 | // connection. |
| 114 | // |
| 115 | // Likewise, the compositor forbids cycles across scenes and will respond |
| 116 | // to them by considering any scene within a cycle to be blocked from |
| 117 | // rendering. |
| 118 | // |
| 119 | // For example, if there are scenes A, B, and C linked such that rendering |
| 120 | // would traverse a path A -> B -> C -> B, the compositor will consider both |
| 121 | // scenes B and C to be blocked and will apply A's combinator rules as required |
| 122 | // to resolve the problem at the point where it would have entered the cycle. |
| 123 | // This may cause A itself to be blocked if there are no applicable |PRUNE| |
| 124 | // or |FALLBACK| predicated alternatives. |
| 125 | // |
| 126 | // This policy protects clients from cross-scene cycles which may have been |
| 127 | // introduced downstream in the graph without their knowledge or which may |
| 128 | // occur transiently, so long as they are not within the cycle themselves. |
| 129 | // It also ensures that cycles are resolved deterministically regardless of |
| 130 | // where they are encountered during traversal; all scenes within the cycle |
| 131 | // are suppressed. |
| 132 | // |
Jeff Brown | 751f4d3 | 2016-01-26 15:51:01 -0800 | [diff] [blame] | 133 | // TIPS |
| 134 | // |
| 135 | // 1. Reuse nodes when possible to reduce the size of the graph. Consider |
| 136 | // using LayerNodeOps to flatten common elements to a texture which can |
| 137 | // be redrawn efficiently in many places. |
| 138 | // |
Jeff Brown | 33eb773 | 2016-03-02 11:17:31 -0800 | [diff] [blame] | 139 | // 2. Insert |PRUNE| or |FALLBACK| nodes in places where blocking is likely to |
Jeff Brown | 751f4d3 | 2016-01-26 15:51:01 -0800 | [diff] [blame] | 140 | // occur, such as when embedding scenes produced by other applications. |
Jeff Brown | 33eb773 | 2016-03-02 11:17:31 -0800 | [diff] [blame] | 141 | // Provide alternate content where possible to avoid stalling the |
| 142 | // rendering pipeline at these points. |
Jeff Brown | 751f4d3 | 2016-01-26 15:51:01 -0800 | [diff] [blame] | 143 | // |
| 144 | struct Node { |
| 145 | // The combinator specifies how child nodes are processed. |
| 146 | enum Combinator { |
| 147 | // All children are drawn in sequence, blocking if any are blocked. |
| 148 | MERGE, |
| 149 | // All children are drawn in sequence, skipping any that are blocked. |
| 150 | PRUNE, |
| 151 | // The first unblocked node is drawn, blocking if there are children |
| 152 | // and all of them are blocked. |
| 153 | FALLBACK, |
| 154 | }; |
| 155 | |
| 156 | // The forward transformation from the node's content space to its |
| 157 | // containing node's content space. If null, an identity transformation |
| 158 | // is assumed. |
| 159 | // |
| 160 | // For example, if you want to translate the content of the node so that |
| 161 | // it is drawn at X = 100 relative to its containing node's origin, simply |
| 162 | // set a transformation matrix with the X translation component equal to 100. |
| 163 | // Take care not to specify the inverse transform by mistake. |
| 164 | mojo.Transform? content_transform; |
| 165 | |
| 166 | // The clip rectangle to apply to this node's content and to its children |
| 167 | // in content space in addition to any clipping performed by the container. |
| 168 | // If null, the node does not apply any clipping of its own. |
Jeff Brown | 563af9f | 2016-03-10 08:24:46 -0800 | [diff] [blame] | 169 | mojo.RectF? content_clip; |
Jeff Brown | 751f4d3 | 2016-01-26 15:51:01 -0800 | [diff] [blame] | 170 | |
Jeff Brown | 751f4d3 | 2016-01-26 15:51:01 -0800 | [diff] [blame] | 171 | // The Combinator to apply when processing the children of this node. |
| 172 | Combinator combinator = Combinator.MERGE; |
| 173 | |
Jeff Brown | c1287c1 | 2016-03-02 11:17:58 -0800 | [diff] [blame] | 174 | // The hit testing behavior of the node. |
| 175 | // If null, the node is considered invisible for hit testing. |
| 176 | HitTestBehavior? hit_test_behavior; |
| 177 | |
Jeff Brown | 751f4d3 | 2016-01-26 15:51:01 -0800 | [diff] [blame] | 178 | // The ids of the children of this node. |
| 179 | // It is an error to specify a node id that does not refer to a valid |
Jeff Brown | 33eb773 | 2016-03-02 11:17:31 -0800 | [diff] [blame] | 180 | // node or which creates a cycle in the graph; the compositor will close |
| 181 | // the connection when the scene is published. |
Jeff Brown | 751f4d3 | 2016-01-26 15:51:01 -0800 | [diff] [blame] | 182 | array<uint32>? child_node_ids; |
| 183 | |
| 184 | // The drawing operation to apply when processing this node. |
| 185 | // If null, no drawing operation occurs at this node. |
| 186 | NodeOp? op; |
| 187 | }; |
| 188 | |
| 189 | // A drawing operation to apply when processing the node. |
| 190 | union NodeOp { |
| 191 | RectNodeOp rect; |
| 192 | ImageNodeOp image; |
| 193 | SceneNodeOp scene; |
| 194 | LayerNodeOp layer; |
| 195 | // TODO(jeffbrown): Color filters. |
| 196 | }; |
| 197 | |
| 198 | // Fills a rectangle with a solid color. |
| 199 | struct RectNodeOp { |
| 200 | // The rectangle to fill in content space. |
Jeff Brown | 563af9f | 2016-03-10 08:24:46 -0800 | [diff] [blame] | 201 | mojo.RectF content_rect; |
Jeff Brown | 751f4d3 | 2016-01-26 15:51:01 -0800 | [diff] [blame] | 202 | |
| 203 | // The rectangle's color. |
| 204 | Color color; |
| 205 | }; |
| 206 | |
| 207 | // Draws an image at the specified location. |
| 208 | // |
| 209 | // The node containing this operation will be blocked if the image resource |
| 210 | // is not ready for use at draw time. |
| 211 | struct ImageNodeOp { |
| 212 | // The rectangle in which to draw the image in content space. |
Jeff Brown | 563af9f | 2016-03-10 08:24:46 -0800 | [diff] [blame] | 213 | mojo.RectF content_rect; |
Jeff Brown | 751f4d3 | 2016-01-26 15:51:01 -0800 | [diff] [blame] | 214 | |
| 215 | // The portion of the image to draw. |
| 216 | // If null, draws the entire image. |
Jeff Brown | 563af9f | 2016-03-10 08:24:46 -0800 | [diff] [blame] | 217 | mojo.RectF? image_rect; |
Jeff Brown | 751f4d3 | 2016-01-26 15:51:01 -0800 | [diff] [blame] | 218 | |
| 219 | // The resource id of a valid |MailboxTextureResource| to draw. |
| 220 | // It is an error to specify a resource id that does not refer to an image |
| 221 | // resource; the compositor will close the connection when the scene |
| 222 | // is published. |
| 223 | uint32 image_resource_id; |
| 224 | |
| 225 | // The blending parameters. If null, uses the default values specified |
| 226 | // in the |Blend| structure declaration. |
| 227 | Blend? blend; |
| 228 | }; |
| 229 | |
| 230 | // Draws a scene. |
| 231 | // |
| 232 | // A scene operation embeds another scene at this point in the scene graph. |
| 233 | // It has essentially the same effect as drawing the root node of the |
| 234 | // referenced scene and drawing it as if it were a child of this node. |
| 235 | // |
| 236 | // The node containing this operation will be blocked if the specified |
| 237 | // version of the scene is not ready for use at draw time or if it too |
| 238 | // is blocked. |
| 239 | // |
| 240 | // It is often useful to wrap this node with a |LayerNodeOp| when blending |
| 241 | // the scene with other content. |
| 242 | struct SceneNodeOp { |
| 243 | // The resource id of a valid |SceneResource| to link into the scene. |
| 244 | // It is an error to specify a resource id that does not refer to a scene |
| 245 | // resource; the compositor will close the connection when the scene |
| 246 | // is published. |
Jeff Brown | 33eb773 | 2016-03-02 11:17:31 -0800 | [diff] [blame] | 247 | // If a cycle is introduced then the scene will be substituted with |
| 248 | // placeholder content by the compositor. |
Jeff Brown | 751f4d3 | 2016-01-26 15:51:01 -0800 | [diff] [blame] | 249 | uint32 scene_resource_id; |
| 250 | |
| 251 | // The version of the scene that we would like to reference. |
| 252 | // Use |kSceneVersionNone| to request the most recently published |
| 253 | // version of the scene if synchronization is unimportant. |
Alexandre Zani | d26dd21 | 2016-03-24 13:24:48 -0700 | [diff] [blame] | 254 | uint32 scene_version = 0; // kSceneVersionNone |
Jeff Brown | 751f4d3 | 2016-01-26 15:51:01 -0800 | [diff] [blame] | 255 | }; |
| 256 | |
| 257 | // Draws a layer. |
| 258 | // |
| 259 | // Conceptually, this operation has the effect of drawing the children of |
Jeff Brown | 563af9f | 2016-03-10 08:24:46 -0800 | [diff] [blame] | 260 | // the node to a temporary buffer which is then composited in place like an |
| 261 | // image. This is useful for ensuring correct blending of layered content. |
Jeff Brown | 751f4d3 | 2016-01-26 15:51:01 -0800 | [diff] [blame] | 262 | struct LayerNodeOp { |
Jeff Brown | 563af9f | 2016-03-10 08:24:46 -0800 | [diff] [blame] | 263 | // The region of the node's content space to render to a layer. |
| 264 | // Drawing within this region will be included in the layer. |
| 265 | mojo.RectF layer_rect; |
Jeff Brown | 751f4d3 | 2016-01-26 15:51:01 -0800 | [diff] [blame] | 266 | |
| 267 | // The blending parameters. If null, uses the default values specified |
| 268 | // in the |Blend| structure declaration. |
| 269 | Blend? blend; |
| 270 | }; |
| 271 | |
| 272 | // Specifies a color to draw. |
| 273 | // TODO(jeffbrown): This is silly but unambiguous for prototyping. |
| 274 | // Make it less silly. |
| 275 | struct Color { |
| 276 | uint8 red; |
| 277 | uint8 green; |
| 278 | uint8 blue; |
| 279 | uint8 alpha; |
| 280 | }; |
| 281 | |
| 282 | // Specifies how blending should take place. |
| 283 | struct Blend { |
| 284 | // The opacity for composition in a range from 0 (fully transparent) |
| 285 | // to 255 (fully opaque). |
| 286 | uint8 alpha = 255; |
| 287 | |
| 288 | // TODO(jeffbrown): Blend modes and texture filtering. |
| 289 | }; |