Donner SVG 0.8.0-pre
SVG editor and embeddable C⁠+⁠+⁠20 engine.
Loading...
Searching...
No Matches
donner::svg::compositor::CompositorConfig Struct Reference

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.

Detailed Description

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.

Member Data Documentation

◆ autoPromoteAnimations

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.

◆ autoPromoteInteractions

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.

◆ complexityBucketing

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.

◆ deferFirstFrameWarmup

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.

◆ dynamicImmediateStaticSpans

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.

◆ immediateStaticSpans

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

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.

◆ tightBoundedSegments

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.

◆ verifyPixelIdentity

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.

◆ yieldBetweenTiles

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.


The documentation for this struct was generated from the following file: