Hi everyone,

My initial work on the implementation of `opacity`, as well as discussions with Martin Robinson last week, have begun to make me wonder whether we should modify Servo's layerization/display list model somewhat. Currently, the output of layout (i.e. what layout sends to the painting thread) is a tree† of `RenderLayer`s with a flat list of `DisplayItem`s for each such layer. Every `RenderLayer` corresponds to a tiled hardware surface. For each fragment, layout decides whether it should get a layer or whether it should just contribute display items to its parent.

The simplicity of this scheme is great, but there are a number of issues we've run into:

1. It's not clear how to represent `transform`, especially nested ones combined with complex clipping regions (like those generated by `border-radius`), with a flat list of display items. We would either need each set of display items to carry a stack of transform matrices and clips (like Skia's `MCStack`) or to make the display list into a tree, causing annoyances similar to those that Gecko's old `nsDisplayClip` (and Servo's `ClipDisplayItem`) caused.

2. `DisplayList::flatten`, which shuffles display items into the proper order to form a new stacking context, is surprisingly high in the profile, accounting for as much as 20% of display list construction in some cases.

3. Having layout choose whether each item gets a layer is annoying due to having to scatter "should I layerize this?" logic throughout layout. It was manageable when `position: fixed` and the root element were the only things that could make layers, but with `opacity` on the scene every fragment can potentially make a layer (and you clearly don't want to make hardware layers for every element with `opacity` < 1, so we would need both code paths).

I came up with a potential solution: Instead of having layout send a tree of render layers, have it send a tree of *stacking contexts*. A stacking context is a set of display lists (one for each "layer" defined in CSS 2.1 Appendix E), plus a z-index and a set of child stacking contexts. The painting thread makes the decision as to whether each stacking context gets a hardware layer; it may want to layerize some and not others. Layout does not have to care whether each stacking context is layerized in the accelerated compositing sense or not.

This provides a solution for problems (1)-(3). For problem (1), `transform` always creates a stacking context, so we neatly avoid having to have a stack of clip regions and transform matrices per display item: the tree of stacking contexts implicitly defines that stack. We solve problem (2) by avoiding having to explicitly shuffle display items around; for each stacking context, the painting thread just paints the lists in the right order, which both reduces the work to be done and moves the remaining work from the layout thread to the painting thread. And problem (3) is solved because layout no longer cares about hardware layerization; it's all stacking contexts as far as layout is concerned. (There is still the annoyance that `opacity` < 1 always creates a new stacking context, but that is complexity we have to buy into no matter what.)

Note that this does *not* solve the problem of not being able to layerize things that are not true stacking contexts (which is an issue that also applies to Blink and WebKit). However, I can see ways in which it could be extended to a more `FrameLayerBuilder`-like approach without rewriting all our painting code if it becomes important to do so in the future.

It's also not immediately clear to me how this integrates with the per-tile display list construction stuff that we want to do, but I don't think it's an insurmountable problem.

Thoughts?

Patrick

† This is actually not true in the current implementation; rather RenderLayers are a flat list, with the first layer in the list representing the "root layer". But this is obviously wrong and we are working on changing it.
_______________________________________________
dev-servo mailing list
dev-servo@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-servo

Reply via email to