|
|
Donner 0.5.1
Embeddable browser-grade SVG2 engine
|
PipelinedRenderer — a multi-threaded, in-process renderer that reuses the sandbox wire format as a producer/consumer boundary between the main thread (parser + driver + serializer) and a worker thread (deserializer + real backend). More...
#include <atomic>#include <condition_variable>#include <cstddef>#include <cstdint>#include <memory>#include <mutex>#include <optional>#include <span>#include <string>#include <thread>#include <vector>#include "donner/svg/renderer/RendererInterface.h"Classes | |
| struct | donner::editor::sandbox::PipelinedFrame |
| One frame's worth of rendered pixels and metadata handed back to the main thread after PipelinedRenderer completes a submission. More... | |
| class | donner::editor::sandbox::PipelinedRenderer |
| A pipelined renderer that moves rasterization off the caller's thread. More... | |
Namespaces | |
| namespace | donner |
| Top-level Donner namespace, which is split into different sub-namespaces such as donner::svg and donner::css. | |
| namespace | donner::svg |
| Donner SVG library, which can load, manipulate and render SVG files. | |
Typedefs | |
| using | donner::editor::sandbox::RendererFactory = std::unique_ptr<svg::RendererInterface> (*)() |
| Factory for the real backend the worker thread should rasterize into. Called exactly once, on the worker thread, before the first replay. The worker owns the returned renderer for its whole lifetime. | |
Functions | |
| std::unique_ptr< svg::RendererInterface > | donner::editor::sandbox::MakeDefaultRenderer () |
| Default factory that returns a Renderer backed by whichever renderer backend was selected at build time (tiny-skia or Geode). | |
PipelinedRenderer — a multi-threaded, in-process renderer that reuses the sandbox wire format as a producer/consumer boundary between the main thread (parser + driver + serializer) and a worker thread (deserializer + real backend).
Motivation: the same observation that drives the sandbox design — RendererInterface is a self-contained command stream — means the same serialize/replay pipeline works across any boundary:
| Boundary | Producer → Consumer | Transport |
|---|---|---|
| Process (sandbox) | child → host | pipe |
| Thread (this file) | main → render worker | std::vector buf |
| Time (frame inspect) | last frame → inspector pane | in-memory replay |
| File (record/replay) | now → later | .rnr file |
PipelinedRenderer targets the threading case. The main thread calls submit(document), which runs the parser/driver inline (fast, mostly cache-local) and serializes the RendererInterface calls into a byte buffer. The buffer is handed off to a worker thread that decodes it and invokes a real backend (Renderer, resolving to the build-selected backend). The main thread returns as soon as serialization completes, freeing it to mutate the document for frame N+1 while frame N rasterizes in parallel.
This is "newest wins": if submit() is called while a previous frame is still rasterizing, the old frame is abandoned on the worker side. We're building an interactive editor — the user cares about the current frame, not the complete history.
Why not just pass SVGDocument across threads? Two reasons: