We're going to need to allow rendering on a specific cairo_t in order to
implement fallback code paths inside GTK; this means that there will be
times when we have a transient GskRenderer instance that does not have a
GdkDrawingContext to draw on.
Instead of adding a new render() implementation for those cases and then
decide which one to use, we can remove the drawing context argument from
the virtual function itself, and allow using a NULL GdkDrawingContext
when calling gsk_renderer_render(). A later commit will add a generic
function to create a transient GskRenderer with a cairo_t attached to
it.
Renderers inside GSK will have to check whether we have access to a
GdkDrawingContext, in which case we're going to use it; or if we have
access to a cairo_t and a window.
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.
Using GObject as the base type for a transient tree may prove to be too
intensive, especially when creating a lot of node instances. Since we
don't need properties or signals, and we don't need complex destruction
semantics, we can use GTypeInstance directly as the base type for
GskRenderNode.
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.