- process_shader_job: bind all texture params by name, recurse into nested
shader payloads (depth cap 8), fall back to frame size without inputs
- run_effect: take iterative_input so dropshadow previous_iteration_in works
- merge: actually composite inputs; keyer mask, opacity modulation, math
texture ops and mrg generator layers now bind their textures
- transform distort: real fragment-side inverse-matrix sampling
- time offset / time remap: wire NodeBehavior time adjustment hooks
- plugin: fix first-node identity colliding with unbound sentinel
oak-common is gone; its modules (configstore, xmlutils, ocioutils,
oiioutils, colormath, colortransform, videoparams, ffmpegutils, ...)
now live in oak-core alongside the value types. The render value/GPU
types moved too: backend (wgpu context + DisplayRenderer), color
(ColorProcessor over ocio-rs), texture, frame, and the commonutil
config helpers.
Fix-ups to make the merged tree build and pass tests:
- oak-core Cargo.toml: wgpu back to 25 (the moved backend code is
written against that API generation); add the toml/quick-xml/image
deps oak-common carried.
- lib.rs: drop the duplicate 'pub mod error;'.
- error.rs: unified OAKCORE_* codes; restore Error::new() and
From<OcioError> from oak-common's error type.
- backend.rs/color.rs: oak_core::/oak_render:: self-references
rewritten to crate::; the shaderfx-dependent GPU effect test moved
to oak-render's shaderfx tests (shaderfx depends on oak-node and
cannot live in oak-core).
- oak-render's error module re-exports oak_core::error::{Error,
Result}; the OAKRENDER_* codes stay as the public-code contract.
- oak-node jobs.rs: ColorProcessor imported from oak_core::color.
- Integration tests repointed at oak_core::{texture, frame, backend,
color, colormath}.
- the display-ICC regression test treats an empty OAK_DISPLAY_ICC as
unset, matching displayicc::env_override_icc.
Three independent host-side gaps kept real plugins from instantiating:
- clips now define OfxImageClipPropFieldOrder (default OfxFieldNone):
ofxs Clip::getFieldOrder() is a strong read with no default, so
field-aware plugins (Mirror) threw PropertyUnknownToHost ->
MissingHostFeature from createInstance
- OfxParamPropParametricUIColour is no longer predefined as an empty
array: the OFX implicit-create semantics let the plugin's first
propSetDouble create the property and grow it index by index, while
the empty predefined array rejected every write at index >= 1 with
BadIndex (ColorLookup, HueCorrect describeInContext)
- Host::create_instance_preferred: context selection with fallback
(filter -> general -> tracker -> paint -> rest). TrackerPM advertises
the filter context but its createInstance fetches a Mask clip that
its describe only defines for tracker/general/paint; Natron simply
instantiates it in the tracker context, and now so do we. Both the
node-registration scan and the shared instance factory use it.
Still unsupported, by design: Premult/Unpremult (this openfx-misc
build hard-requires the Nuke multi-plane suite + dynamic choices) and
the stereo view plugins (Switch/anaglyph/joinViews/etc. need Natron's
isNatron multi-clip folding or view rendering).
Verified: ColorLookup, HueCorrect, Mirror, TrackerPM now instantiate;
full oak-plugin suite green.
The OFX abort contract is "0 = keep rendering, anything else = stop"
and the ofxs support library literally checks abort(...) != 0. Our
host answered kOfxStatReplyNo (13) for "not cancelled", so every
openfx-misc processor aborted its pixel loop before writing a single
row: the render action returned OK with the output buffer untouched —
a solid black frame everywhere an effect was applied (the previous
smoke test only asserted "not the purple failure frame", which let
this slip through as a fake pass).
- image-effect abort: return 0 when not cancelled, 1 when cancelled
(instance cancel flag or progress cancellation), BadHandle for
descriptor handles as before
- strengthen the real-plugin smoke tests to also reject an all-zero
output frame, so a silent no-write can no longer pass
- more trace-gated [ofx] diagnostics (value dumps for propGetN /
propGetPointer / clipGetImage fetches, multiThread entry, render
output buffer address) — the tooling that pinned this down
Verified with lldb watchpoints: the AddOFX/ChromaKeyerOFX processors
now write the real pixels through the executor path.
Real plugins (CImg ChromaKeyerOFX, AddOFX) failed the render action with
kOfxStatFailed / MissingHostFeature and painted the magenta failure frame:
- images lacked the mandatory ImageBase properties (OfxPropType,
PixelAspectRatio, PreMultiplication, Field, RenderScale); the ofxs
ImageBase constructor throws on the missing/invalid strong reads
- PreMultiplication used the made-up string "OfxImagePreMultiplied";
kOfxImagePreMultiplied is actually "OfxImageAlphaPremultiplied", the
only value mapStrToPreMultiplicationEnum accepts (lldb __cxa_throw
backtrace pinpointed this)
- RenderWindow is Int x4 per ofxsPropertyValidation, not Double x4
- field strings use the real constant "OfxFieldNone"
- clips define OfxImageClipPropConnected (isConnected is a strong read;
optional mask clips blew up without it)
- choice params predefine empty ChoiceEnum / ChoiceLabelOption arrays
- isIdentity failure is no longer fatal (the C++ plugin renderer never
calls it; plugins that error on it simply render normally)
- property suite coerces Int <-> Double on reads (the CImg framework
reads the render window with propGetIntN against a Double store)
- in-args carry NatronOfxPropNativeOverlays=0 for the Natron framework
- plugin jobs pass a GL-kind marker so GL-only plugins take the real
gl_bridge offscreen path instead of the CPU MissingHostFeature path
- trace-gated [ofx] diagnostics for property misses and suite calls
Verified with new smoke tests that render the real AddOFX and
ChromaKeyerOFX plugins through the executor and assert the output is
not the purple failure frame.
All crates take the oak-* kebab-case naming (oak-audio, oak-codec,
oak-common, oak-core, oak-ffmpeg-link, oak-node, oak-otio, oak-plugin,
oak-render, oak-storage, oak-task, oak-timeline, oak-undo), with the
lib identifiers rewritten (oakrender:: -> oak_render::, oakcore_rs:: ->
oak_core::, ...) across all 226 referencing files.
The GUI application moves from the workspace root into
crates/oak-app/: src/, build.rs (paths fixed for the new location) and
tests/ travel with it, the root Cargo.toml becomes workspace-only
([workspace] + workspace.package + profiles), and the app package
inherits the workspace version. The screenshots example becomes a
standalone crate examples/simple_player/ with its own Cargo.toml.
Every crate now inherits the single workspace version
(version.workspace = true), and the workflows' crate paths and the
build docs follow the renames.
Validated with a clean cargo check --workspace.