feat(oakplugin): wire OpenFX plugins into the node graph and renderer
- oaknode: dynamic node factory registration, PluginNode value model pushing PluginJobPayload, traverser texture passthrough for texture inputs, type-stamped RefBox::get_checked. - oakrender: PluginExecutor dependency-inversion slot; eval resolves and executes plugin jobs, purple frame on failure. - oakplugin: node_factory with full OFX param -> node input translation (15 types, color semantics heuristic, combo ordering, secret/ui_group/ui_page, clip inputs), plugin instance registry, render executor + duplicator installation, progress reporter and active-viewer provider injection points, U8/U16/F16 input conversion with NaN scrubbing, in-place output frame writeback fix. - gl_bridge.rs documents the wgpu<->GL interop spike: Metal-first on macOS rules out wgpu-hal GL interop; offscreen GL context deferred. End-to-end tests cover registration, param translation, CPU render pixel assertions, identity passthrough and NaN fallback.
This commit is contained in:
@@ -37,13 +37,32 @@ use std::sync::atomic::{AtomicU32, Ordering};
|
||||
pub const OAKNODE_ABI_VERSION: u32 = 1;
|
||||
|
||||
/// Heap box behind a handle's `ctx`.
|
||||
///
|
||||
/// `repr(C)`: the field order is the stable prefix layout
|
||||
/// [`RefBoxHeader`] relies on for type discrimination across boxes of
|
||||
/// different payloads sharing one handle channel (the render seam
|
||||
/// downcasts plugin-job boxes vs texture boxes).
|
||||
#[repr(C)]
|
||||
pub struct RefBox<T: ?Sized> {
|
||||
/// Atomic reference count.
|
||||
pub refs: AtomicU32,
|
||||
/// Type identity of the boxed value (stamped by [`make_owned`];
|
||||
/// [`get_checked`] compares it before reading [`RefBox::value`]).
|
||||
pub type_id: std::any::TypeId,
|
||||
/// Boxed value.
|
||||
pub value: T,
|
||||
}
|
||||
|
||||
/// The fixed-size prefix of every [`RefBox`] (layout-stable across
|
||||
/// payload types because [`RefBox`] is `repr(C)`).
|
||||
#[repr(C)]
|
||||
struct RefBoxHeader {
|
||||
/// Mirror of [`RefBox::refs`] (present for the layout prefix;
|
||||
/// never read here).
|
||||
_refs: AtomicU32,
|
||||
type_id: std::any::TypeId,
|
||||
}
|
||||
|
||||
/// The shared ABI value-handle type (single-lib unification, see
|
||||
/// `docs/zh/plans/riir/single-lib.md`): one canonical
|
||||
/// `{ctx, addref, release, abi_version}` type in `oakcore-rs`, re-exported
|
||||
@@ -79,6 +98,7 @@ unsafe extern "C" fn refbox_release_owned<T: Any + Send>(ctx: *mut std::ffi::c_v
|
||||
pub fn make_owned<T: Any + Send>(value: T) -> CHandle {
|
||||
let rb = Box::into_raw(Box::new(RefBox {
|
||||
refs: AtomicU32::new(1),
|
||||
type_id: std::any::TypeId::of::<T>(),
|
||||
value,
|
||||
}));
|
||||
CHandle {
|
||||
@@ -98,6 +118,7 @@ pub fn make_owned_with<T: Any + Send>(
|
||||
) -> CHandle {
|
||||
let rb = Box::into_raw(Box::new(RefBox {
|
||||
refs: AtomicU32::new(1),
|
||||
type_id: std::any::TypeId::of::<T>(),
|
||||
value,
|
||||
}));
|
||||
CHandle {
|
||||
@@ -118,3 +139,24 @@ pub unsafe fn get<T: Any>(h: &CHandle) -> Option<&T> {
|
||||
}
|
||||
unsafe { Some(&(*(h.ctx as *const RefBox<T>)).value) }
|
||||
}
|
||||
|
||||
/// Typed view with type discrimination: `None` when the handle is
|
||||
/// empty **or** boxes a different payload type (the render seam probes
|
||||
/// texture-channel handles for plugin-job payloads this way without
|
||||
/// knowing the producer).
|
||||
///
|
||||
/// # Safety
|
||||
/// `h` must be either empty or a live handle created by
|
||||
/// [`make_owned`]/[`make_owned_with`] for the duration of the call.
|
||||
pub unsafe fn get_checked<T: Any>(h: &CHandle) -> Option<&T> {
|
||||
if h.ctx.is_null() {
|
||||
return None;
|
||||
}
|
||||
// SAFETY: every live box starts with the repr(C) RefBox prefix;
|
||||
// the caller guarantees the handle is alive.
|
||||
let header = unsafe { &*(h.ctx as *const RefBoxHeader) };
|
||||
if header.type_id != std::any::TypeId::of::<T>() {
|
||||
return None;
|
||||
}
|
||||
unsafe { Some(&(*(h.ctx as *const RefBox<T>)).value) }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user