Confirmed users
699
edits
| Line 92: | Line 92: | ||
[[File:Layer-trees-v0.png|thumb|650px|v0 layer tree]] | [[File:Layer-trees-v0.png|thumb|650px|v0 layer tree]] | ||
Like the first diagram, big boxes are processes. The circled item in the Content process is a decoder thread. The arrows drawn between processes indicate the direction that layer-tree updates will be pushed. All updates will be made through a <code>PLayers</code> protocol. This protocol will likely roughly correspond to a "remote layer subtree manager". A <code>ShadowContainerLayer</code> corresponds to the "other side" of a remote subtree manager; it's the entity that receives layer tree updates from a remote process. The dashed line between the decoder thread and the Content main thread just indicates their relationship; it's not clear what Layers-related information they'll need to exchange, if any. | Like the first diagram, big boxes are processes. The circled item in the Content process is a decoder thread. The arrows drawn between processes indicate the direction that layer-tree updates will be pushed. All updates will be made through a <code>PLayers</code> protocol. This protocol will likely roughly correspond to a "remote layer subtree manager". A <code>ShadowContainerLayer</code> corresponds to the "other side" of a remote subtree manager; it's the entity that receives layer tree updates from a remote process. The dashed line between the decoder thread and the Content main thread just indicates their relationship; it's not clear what Layers-related information they'll need to exchange, if any. | ||
NB: this diagram assumes that a remote layer tree will be published and updated in its entirety. However, it sometimes might be beneficial to partially composite a subtree before publishing it. This exposition ignores that possibility because it's the same problem wrt IPC. | |||
It's worth calling out in this picture the two types of (non-trivial) shared leaf layers: <code>ShmemLayer</code> and <code>PlaceholderLayer</code>. A <code>ShmemLayer</code> will wrap IPDL <code>Shmem</code>, using whichever backend is best for a particular platform (might be POSIX, SysV, VRAM mapping, ...). Any process holding on to a <code>ShmemLayer</code> can read and write the buffer contents within the constraints imposed by [[IPDL/Shmem|<code>Shmem</code> single-owner semantics]]. This means, e.g., that if Plugin pushes a <code>ShmemLayer</code> update to Content, Content can twiddle with Plugin's new front buffer before pushing the update to Chrome, and similarly for Chrome before pushing Chrome-->Compositor. We probably won't need this feature. | It's worth calling out in this picture the two types of (non-trivial) shared leaf layers: <code>ShmemLayer</code> and <code>PlaceholderLayer</code>. A <code>ShmemLayer</code> will wrap IPDL <code>Shmem</code>, using whichever backend is best for a particular platform (might be POSIX, SysV, VRAM mapping, ...). Any process holding on to a <code>ShmemLayer</code> can read and write the buffer contents within the constraints imposed by [[IPDL/Shmem|<code>Shmem</code> single-owner semantics]]. This means, e.g., that if Plugin pushes a <code>ShmemLayer</code> update to Content, Content can twiddle with Plugin's new front buffer before pushing the update to Chrome, and similarly for Chrome before pushing Chrome-->Compositor. We probably won't need this feature. | ||
| Line 97: | Line 99: | ||
A <code>PlaceholderLayer</code> refers to a "special" layer with a buffer that's inaccessible to the process with the <code>PlaceholderLayer</code> reference. Above, it refers to the video decoder thread's frame layer. When the decoder paints a new frame, it can immediately push its buffer to Compositor, bypassing Content and Chrome (which might be blocked for a "long time"). In Compositor, however, the <code>PlaceholderLayer</code> magically turns into a <code>ShmemLayer</code> with a readable and writeable front buffer, so there new frames can be painted immediately with proper Z-ordering wrt content and chrome layers. Content can arbitrarily fiddle with the <code>PlaceholderLayer</code> in its subtree while new frames are still being drawn, and on the next Content-->Chrome-->Compositor update push, the changes to <code>PlaceholderLayer</code> position/attributes/etc. will immediately take effect. | A <code>PlaceholderLayer</code> refers to a "special" layer with a buffer that's inaccessible to the process with the <code>PlaceholderLayer</code> reference. Above, it refers to the video decoder thread's frame layer. When the decoder paints a new frame, it can immediately push its buffer to Compositor, bypassing Content and Chrome (which might be blocked for a "long time"). In Compositor, however, the <code>PlaceholderLayer</code> magically turns into a <code>ShmemLayer</code> with a readable and writeable front buffer, so there new frames can be painted immediately with proper Z-ordering wrt content and chrome layers. Content can arbitrarily fiddle with the <code>PlaceholderLayer</code> in its subtree while new frames are still being drawn, and on the next Content-->Chrome-->Compositor update push, the changes to <code>PlaceholderLayer</code> position/attributes/etc. will immediately take effect. | ||
== Strawman PLayers protocol == | |||
The rough idea here is to capture all modifications made to a layer subtree during a <code>RemoteLayerManager</code> transaction, package them up into a "changeset" IPC message, send the message to the "other side", then have the other side replay that changeset on its shadow layer tree. | |||
// XXX: not clear whether we want a single PLayer managee or PColorLayer, PContainerLayer, et al. | |||
include protocol PLayer; | |||
// Remotable layer tree | |||
struct InternalNode { | |||
PLayer container; | |||
Node[] kids; | |||
}; | |||
union Node { | |||
InternalNode; | |||
PLayer; // leaf | |||
}; | |||
// Tree operations comprising an update | |||
struct Insert { Node x; PLayer after; }; | |||
struct Remove { PLayer x; }; | |||
struct Paint { PLayer x; Shmem frontBuffer; }; | |||
struct SetOpaque { PLayer x; bool opaque; }; | |||
struct SetClipRect { PLayer x; gfxRect clip; }; | |||
struct SetTransform { PLayer x; gfxMatrix tranform; }; | |||
// ... | |||
union Edit { | |||
Insert; | |||
Remove; | |||
Paint; | |||
SetOpaque; | |||
SetClipRect; | |||
SetTransform; | |||
// ... | |||
}; | |||
// Reply to an Update() | |||
// buffer-swap reply sent in response to Paint() | |||
struct SetBackBuffer { PLayer x; Shmem backBuffer; }; | |||
// ...? | |||
union EditReply { | |||
SetBackBuffer; | |||
//...? | |||
}; | |||
// From this spec, singleton PLayersParent/PLayersChild actors will be | |||
// generated. These will be singletons-per-protocol-tree roughly | |||
// corresponding to a "RemoteLayerManager" or somesuch | |||
sync protocol PLayers { | |||
// all the protocols with a "layers" mix-in | |||
manager PCompositor or PContent or PMedia or PPlugin; | |||
manages PLayer; | |||
parent: | |||
sync Publish(Node root); | |||
sync Update(Edit[] cset) | |||
returns(EditReply[] reply); | |||
// ... other lifetime management stuff here | |||
state INIT: | |||
recv Publish goto UPDATE; | |||
state UPDATE: | |||
recv Update goto UPDATE; | |||
//... other lifetime management stuff here | |||
}; | |||
What comprises a changeset is eminently fungible. For example, some operations may only apply to certain types of layers; IPDL's type system can capture this, if desired. | |||
union ClippableLayer { PImageLayer; PColorLayer; /*...*/ }; | |||
struct SetClip { ClippableLayer x; gfxRect clipRect; } | |||
Need lots of input from roc/Bas/jrmuizel here. | |||
== Recording modifications made to layer trees during transactions == | |||
Placeholder. | |||
== Strawman complete example == | |||
'''TODO | '''TODO''': assume processes have been launched per diagram above. Walk through layer tree creation and Publish()ing. Walk through transaction and Update() propagation. | ||