slint
slint copied to clipboard
Optimization / GL backend: Create layer needed for non-rectangular clip lazily
Olivier had a great idea for the path clipping feature:
When using clip: true on a Rectangle that also has a non-zero border-radius declared, we are facing the situation that we need to clip the contents (including children) against a non-rectangular clip region. However femtovg only supports the scissor clip, which is strictly rectangular.
What the GL backend does to implement the non-rectangular clip is to render the content into an intermediate texture, then declare a "rounded rect path" (with said border radius) and fills it with that texture. That femtovg supports via stencil clip.
The rendering into an intermediate texture however comes at a cost, which could be avoided if we knew that none of the children intersect with this clip. This might happen after all, dynamically at run-time.
Olivier's idea is that if we detect such a clipping scenario we do optimistically continue rendering children without an intermediate texture. If during the rendering of any children, or grand children, etc. we detect that we /do/ intersect with said region, we lazily switch to layered rendering. Since we render strictly back-to-front, switching in-between /should/ still give the correct visual result.
Even if we can't create this lazily anymore, we can still achieve a similar effect of optimization:
When rendering a Clip element with a border radius:
- Check if any of the children intersect with the region covered by the radius (so inner rect with radius minus outer rect, gives four rectangles, any intersection with these).
- If they do not intersect, then we can do a rectangular scissor clip and don't have to do indirect layer rendering.
Note: For Rectangle { clip: true; @children } the hierarchy created is Rectangle { Clip { @children } }