While porting GTK to GskRenderer we noticed that the current fallback
code for widgets using Cairo to draw is not enough to cover all the
possible cases.
For instance, if a container widget still uses GtkWidget::draw to render
its children, and at least one of them has been ported to using render
nodes instead, the container won't know how to draw it.
For this reason we want to provide to layers above GSK the ability to
create a "fallback" renderer instance, created using a "parent"
GskRenderer instance, but using a Cairo context as the rendering target
instead of a GdkDrawingContext.
GTK will use this inside the gtk_widget_draw() implementation, if a
widget implements GtkWidgetClass.get_render_node().
The renderer will always use nearest-neighbor filters because it renders
at 1:1 pixel to texel ratio.
On the other hand, render nodes may be scaled, so we need to offer a way
to control the minification and magnification filters.
The details of the modelview and projection matrices are only useful for
the GL renderer; there's really no point in having those details
available in the generic API — especially as the Cairo fallback renderer
cannot really set up a complex modelview or a projection matrix.
Render nodes need access to rendering information like scaling factors.
If we keep render nodes separate from renderers until we submit a nodes
tree for rendering we're going to have to duplicate all that information
in a way that makes the API more complicated and fuzzier on its
semantics.
By having GskRenderer create GskRenderNode instances we can tie nodes
and renderers together; since higher layers will also have access to
the renderer instance, this does not add any burden to callers.
Additionally, if memory measurements indicate that we are spending too
much time in the allocation of new render nodes, we can now easily
implement a free-list or a renderer-specific allocator without breaking
the API.
This commit changes the way GskRenderer and GskRenderNode interact and
are meant to be used.
GskRenderNode should represent a transient tree of rendering nodes,
which are submitted to the GskRenderer at render time; this allows the
renderer to take ownership of the render tree. Once the toolkit and
application code have finished assembling it, the render tree ownership
is transferred to the renderer.
GSK is conceptually split into two scene graphs:
* a simple rendering tree of operations
* a complex set of logical layers
The latter is built on the former, and adds convenience and high level
API for application developers.
The lower layer, though, is what gets transformed into the rendering
pipeline, as it's simple and thus can be transformed into appropriate
rendering commands with minimal state changes.
The lower layer is also suitable for reuse from more complex higher
layers, like the CSS machinery in GTK, without necessarily port those
layers to the GSK high level API.
This lower layer is based on GskRenderNode instances, which represent
the tree of rendering operations; and a GskRenderer instance, which
takes the render nodes and submits them (after potentially reordering
and transforming them to a more appropriate representation) to the
underlying graphic system.