|
|
Donner SVG 0.8.0-pre
SVG editor and embeddable C++20 engine.
|
Runtime feature gates for CompositorController. More...
#include "donner/svg/compositor/CompositorController.h"
Public Attributes | |
| bool | autoPromoteInteractions = true |
| Editor-published InteractionHint hints promote the selected / dragged entity to its own layer. When false, the editor falls back to the explicit promoteEntity escape hatch. | |
| bool | autoPromoteAnimations = true |
| Animation-system-published hints promote animated subtrees so per-tick cost stays O(animated subtree). When false, animations re-render the whole document per tick; selection / drag compositing is unaffected. | |
| MandatoryHintScope | mandatoryHintScope = MandatoryHintScope::All |
| Which mandatory-compositing signals MandatoryHintDetector publishes hints for. FilterOnly is the editor's "filter-only" composited rendering mode: filters (the expensive re-render case) keep their cached isolated layers while opacity groups, blend modes, and masks render inline every frame. Fixed at construction - changing it means reconstructing the controller. | |
| bool | complexityBucketing = true |
| ComplexityBucketer pre-splits the document into a small number of layers at load / structural rebuild to reduce click-to-first-drag-update latency. When false, the root layer stays monolithic. | |
| bool | verifyPixelIdentity = false |
| When true, renderFrame additionally runs a full-document reference render after the composited path completes and asserts pixel identity via UTILS_RELEASE_ASSERT. Doubles per-frame cost - intended for CI compositor test targets and --config=compositor-debug local runs, not for interactive editor use. See 0025 § Dual-path debug assertion. | |
| bool | tightBoundedSegments = true |
| When true, rasterizeDirtyStaticSegments calls RendererDriver::computeEntityRangeBounds and sizes each segment's offscreen bitmap to the tight canvas-space rectangle its contents paint into (with a 1-px AA padding + 75% coverage cutoff). When false, every segment rasterizes full-canvas - slower and more memory, but bypasses every code path added for tight bounds, which is the bisection fast-path for any visual regression suspected to originate in tight-bounded rasterization. | |
| bool | immediateStaticSpans = true |
| Allow cheap static spans to be presented as immediate geometry and re-rasterized on every compositor update. Backends with high per-draw submission overhead, notably browser WebGPU, disable this so a span is rasterized once and then reused as a cached tile. | |
| bool | dynamicImmediateStaticSpans = true |
| When true, a static segment that the deterministic cost heuristic would cache may additionally be promoted to an immediate (re-rasterized every frame) span when its measured rasterize time fits the per-frame immediate budget. This promotion is wall-clock-dependent: on a slow or heavily-shared host a span can be immediate on one frame and demote to a cached tile on the next as its measured time crosses the budget. That is correct adaptive behavior for the interactive editor, but it makes the immediate-vs-cached tile partition non-deterministic across hosts. Deterministic tests that assert on that partition set this false so only the (host-independent) cost heuristic classifies spans. Default on. | |
| bool | deferFirstFrameWarmup = false |
| Return the first correct full-document draw before rasterizing retained layer and segment caches. The owner must call warmPendingFirstFrameCaches from a later, cancellable idle task. This keeps cache preparation off the click-to-present critical path without abandoning the prewarm that makes the first drag responsive. | |
| std::function< void()> | yieldBetweenTiles |
| Invoked between tile rasterizations (the same coarse safe points where isCancelled() is polled). Owners whose event delivery requires the rendering thread to periodically service its event loop install a bounded yield here: the browser worker's canvas-size commits and WebGPU callbacks arrive as worker events, and a multi-tile rasterize pass with pooled offscreen renderers otherwise never yields mid-pass. The callback must be cheap and reentrancy-safe with respect to compositor state: it may deliver a cancellation (observed at the next isCancelled() poll) but must not call back into this controller. Empty means no yield. | |
Runtime feature gates for CompositorController.
Each field toggles an independent auto-promotion source. The primary kill-switch - "don't use the compositor at all" - is a linkage / construction decision: a consumer that doesn't want compositing simply doesn't instantiate a CompositorController. These gates only affect what hint sources run inside a live compositor.
Default-constructed config has all features enabled. Mandatory hints (opacity < 1, filter, mask, blend-mode, isolation) are always detected and cannot be turned off entirely - but mandatoryHintScope can narrow which signals publish hints. Narrowing never changes pixels: an unhinted signal renders through the driver's inline isolation path (the same path entities under compositing-breaking ancestors already take); it only trades retained layer caching for per-frame re-render cost.
| bool donner::svg::compositor::CompositorConfig::autoPromoteAnimations = true |
Animation-system-published hints promote animated subtrees so per-tick cost stays O(animated subtree). When false, animations re-render the whole document per tick; selection / drag compositing is unaffected.
| bool donner::svg::compositor::CompositorConfig::autoPromoteInteractions = true |
Editor-published InteractionHint hints promote the selected / dragged entity to its own layer. When false, the editor falls back to the explicit promoteEntity escape hatch.
| bool donner::svg::compositor::CompositorConfig::complexityBucketing = true |
ComplexityBucketer pre-splits the document into a small number of layers at load / structural rebuild to reduce click-to-first-drag-update latency. When false, the root layer stays monolithic.
| bool donner::svg::compositor::CompositorConfig::deferFirstFrameWarmup = false |
Return the first correct full-document draw before rasterizing retained layer and segment caches. The owner must call warmPendingFirstFrameCaches from a later, cancellable idle task. This keeps cache preparation off the click-to-present critical path without abandoning the prewarm that makes the first drag responsive.
| bool donner::svg::compositor::CompositorConfig::dynamicImmediateStaticSpans = true |
When true, a static segment that the deterministic cost heuristic would cache may additionally be promoted to an immediate (re-rasterized every frame) span when its measured rasterize time fits the per-frame immediate budget. This promotion is wall-clock-dependent: on a slow or heavily-shared host a span can be immediate on one frame and demote to a cached tile on the next as its measured time crosses the budget. That is correct adaptive behavior for the interactive editor, but it makes the immediate-vs-cached tile partition non-deterministic across hosts. Deterministic tests that assert on that partition set this false so only the (host-independent) cost heuristic classifies spans. Default on.
| bool donner::svg::compositor::CompositorConfig::immediateStaticSpans = true |
Allow cheap static spans to be presented as immediate geometry and re-rasterized on every compositor update. Backends with high per-draw submission overhead, notably browser WebGPU, disable this so a span is rasterized once and then reused as a cached tile.
| MandatoryHintScope donner::svg::compositor::CompositorConfig::mandatoryHintScope = MandatoryHintScope::All |
Which mandatory-compositing signals MandatoryHintDetector publishes hints for. FilterOnly is the editor's "filter-only" composited rendering mode: filters (the expensive re-render case) keep their cached isolated layers while opacity groups, blend modes, and masks render inline every frame. Fixed at construction - changing it means reconstructing the controller.
| bool donner::svg::compositor::CompositorConfig::tightBoundedSegments = true |
When true, rasterizeDirtyStaticSegments calls RendererDriver::computeEntityRangeBounds and sizes each segment's offscreen bitmap to the tight canvas-space rectangle its contents paint into (with a 1-px AA padding + 75% coverage cutoff). When false, every segment rasterizes full-canvas - slower and more memory, but bypasses every code path added for tight bounds, which is the bisection fast-path for any visual regression suspected to originate in tight-bounded rasterization.
Flipping the field at runtime (via CompositorController::setTightBoundedSegmentsEnabled) marks all cached segments dirty so the next frame re-rasterizes under the new policy.
| bool donner::svg::compositor::CompositorConfig::verifyPixelIdentity = false |
When true, renderFrame additionally runs a full-document reference render after the composited path completes and asserts pixel identity via UTILS_RELEASE_ASSERT. Doubles per-frame cost - intended for CI compositor test targets and --config=compositor-debug local runs, not for interactive editor use. See 0025 § Dual-path debug assertion.
Default is false; CI and debug test configurations flip it on for the covered test targets.
| std::function<void()> donner::svg::compositor::CompositorConfig::yieldBetweenTiles |
Invoked between tile rasterizations (the same coarse safe points where isCancelled() is polled). Owners whose event delivery requires the rendering thread to periodically service its event loop install a bounded yield here: the browser worker's canvas-size commits and WebGPU callbacks arrive as worker events, and a multi-tile rasterize pass with pooled offscreen renderers otherwise never yields mid-pass. The callback must be cheap and reentrancy-safe with respect to compositor state: it may deliver a cancellation (observed at the next isCancelled() poll) but must not call back into this controller. Empty means no yield.