Gecko:CrossProcessLayers: Difference between revisions

Jump to navigation Jump to search
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.


'''TODO strawman PLayers protocol'''
== 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 example of PLayers::Update(cset) propagation'''
'''TODO''': assume processes have been launched per diagram above.  Walk through layer tree creation and Publish()ing.  Walk through transaction and Update() propagation.
Confirmed users
699

edits

Navigation menu