Expand description
Retained Node IR - typed scene-graph tree produced from the flat Extracted* bag.
§Why a tree?
The render side previously consumed a flat ECS of one-component-per-drawable, painter-sorted at submit
(crate::render_world::ExtractedRect / ExtractedText / ExtractedShadow / ExtractedOutline).
The flat shape lost the parent-driven invariants every modern scenegraph relies on - opacity composition,
transform stacks, and clip regions all have to be reconstructed at submit. This module replaces that with
a typed Node tree owned per-frame by the render world.
§1:1 mapping to Qt SceneGraph + GTK GSK
The variants below were chosen to map directly onto the two reference scenegraphs - Qt 6.8 Scene Graph
(QSG*) and GTK 4 / GSK (gtk_snapshot_* / GskRenderNode). The renderer back-end only needs to know how
to translate each variant to its native equivalent.
Lumen Node | Qt SceneGraph | GTK 4 / GSK |
|---|---|---|
Node::Container | QSGNode (parent of children) | implicit container via gtk_snapshot_push_* / pop bracket |
Node::Transform | QSGTransformNode::setMatrix | gtk_snapshot_push_transform -> GskTransformNode |
Node::Opacity | QSGOpacityNode::setOpacity | gtk_snapshot_push_opacity -> GskOpacityNode |
Node::Clip (rect) | QSGClipNode { isRectangular = true } (scissor) | gtk_snapshot_push_clip -> GskClipNode |
Node::Clip (radii) | QSGClipNode + custom geometry | gtk_snapshot_push_rounded_clip -> GskRoundedClipNode |
Node::Rect (solid) | QSGSimpleRectNode | gtk_snapshot_append_color -> GskColorNode |
Node::Rect (gradient) | QSGGeometryNode + gradient QSGMaterial | GskLinearGradientNode / GskRadialGradientNode / GskConicGradientNode |
Node::Shadow (outer) | QSGGeometryNode + blur material | gtk_snapshot_append_outset_shadow -> GskOutsetShadowNode |
Node::Shadow (inner) | (custom material) | gtk_snapshot_append_inset_shadow -> GskInsetShadowNode |
Node::Outline | QSGGeometryNode (line list) | GskBorderNode (4-side uniform) or composed GskColorNodes |
Node::Text | QSGTextNode (via QSGRendererInterface::createTextNode) | gtk_snapshot_append_layout -> GskTextNode |
Node::Image | QSGSimpleTextureNode::setTexture + setSourceRect | gtk_snapshot_append_texture -> GskTextureNode |
Node::Native | QSGRenderNode | GskGLShaderNode / gtk_snapshot_push_gl_shader |
§Content sharing
Children are held in Arc<Node> so identical subtrees can share storage across frames - the diff can
short-circuit via Arc::ptr_eq and a renderer’s leaf-encoding fragment cache (lumen_paint::FragmentCache)
becomes a content-addressed layer on top.
§Producer and consumer
transform_extracted_to_nodes walks the extract output and produces a RetainedScene each frame; the
walker in lumen-paint consumes it for every renderer and every kind of target. Overflow clipping rides the
Node::Clip variant - see the [Clip] doc-comment.
Structs§
- Affine2
- A 2D affine transform stored as
[a, b, c, d, e, f]in column-major order - same convention asvello::kurbo::Affineso back-ends can construct without conversion glue. The default is the identity. - Previous
Scene - Snapshot of the previous tick’s
RetainedScene. Stored on the render world so the renderer can diff corresponding subtrees (short-circuiting onArc::ptr_eq) and skip a frame whose tree did not change. - Retained
Scene - The retained scene-graph root for the current frame.
Enums§
- Clip
Shape - Clip-region shape for
Node::Clip. Rectangular clips map onto scissor on backends that support it (QtQSGClipNode { isRectangular = true }, GSKGskClipNode); rounded clips require stencil / mask (QtQSGClipNode+ geometry, GSKGskRoundedClipNode). - Draw
Entry - One drawable entry produced during extract, sorted by
PaintOrderbefore tree assembly. - Node
- One node in the retained scene-graph tree. The tree is produced each tick by
transform_extracted_to_nodesand rendered by the back-end walker.
Functions§
- transform_
extracted_ to_ nodes - Builds a
RetainedScenefrom the flatExtracted*components in the render world.