This commit fixes crashes (SIGSEGV in CImg blur_bilateral) and black-frame
corruption artifacts during playback and scrubbing on macOS Apple Silicon.
Root cause analysis:
1. macOS uses Tile-Based Deferred Rendering (TBDR). glFlush() does not
guarantee tile memory writeback, causing glReadPixels to read incomplete
tiles (black/corrupted frames) and cache them to disk.
2. Olive uses multiple shared OpenGL contexts (RenderProcessor contexts vs.
thread-local PluginRenderer context). glFinish() only waits for the
current context, not the shared context that produced the texture. CPU
readback in PluginRenderer could read partially-rendered tiles.
3. OlivePluginInstance and OliveClipInstance are not thread-safe. Concurrent
RenderProcessors could corrupt internal QMap/images_ and params_ via
setInputTexture/renderAction races.
Fixes:
- OpenGLRenderer::Flush() on macOS now uses glFinish() unconditionally.
- OpenGLRenderer::DownloadFromTexture() and OpenGLRenderer::Blit() insert
glFinish() before readback/detach to ensure tile writeback completes.
- PluginRenderer::RenderPlugin() now acquires a per-instance mutex to
serialize concurrent OFX render calls.
- Before CPU readback in PluginRenderer, flush the renderer that originally
produced each input texture, ensuring cross-context synchronization.
- RenderProcessor::ProcessVideoFootage() flushes after BlitColorManaged.
- Add black-frame detection in ProcessVideoCacheJob() to auto-purge TBDR-
corrupted cache files.
- Add diagnostic qDebug() logging in viewer, decoder, renderer, and plugin
paths to aid future debugging.
This commit resolves several categories of OFX plugin failures that
manifested as magenta (pink) render output or crashes:
1. Param default-value initialization
- IntegerInstance, DoubleInstance, BooleanInstance, ChoiceInstance,
and StringInstance now read kOfxParamPropDefault from the descriptor
at construction time. Previously, when no PluginNode was attached
(integration-test mode), get() returned 0/0.0/false, causing
generator plugins to receive invalid extent/format/PAR values and
crash in coordinate assertions.
- IntegerInstance also fixed uninitialized `id` that caused
kOfxStatErrBadHandle in CImg plugins.
2. Clip property initialization
- newClipInstance() now seeds pixelDepth and components from the
host VideoParams instead of leaving them as None. This prevents
Transform3x3Plugin and similar plugins from asserting on
getPixelComponentCount() during fetchClip inside createInstance.
- getAspectRatio() and getProjectPixelAspectRatio() now fall back
to 1.0 when the project's PAR is not yet set, avoiding division-
by-zero in coordinate conversion.
3. Frame-rate and time-base preservation
- setInputTexture() no longer overwrites the clip's frame_rate or
time_base with the input texture's values. Multi-input plugins
were crashing because setupClipPreferencesArgs throws when inputs
have mismatched rates.
4. Render loop hardening
- getClipPreferences() is now wrapped in try/catch so that frame-
rate mismatch exceptions mark render failure instead of aborting
the render thread.
- getRegionOfInterestAction() treats kOfxStatErrBadHandle as non-
fatal and falls back to default RoI.
- RenderPlugin syncs all clip instances after setVideoParam so that
getAspectRatio/getFrameRate return valid values before
createInstanceAction queries them.
5. Test suite updates
- All PluginMisc tests now use F32 input to match the host pipeline
default.
- CreateGradientTexture fixed to support F32 pixel format.
- Added CImgBilateral and CImgGuided_MultiInput tests.
- Secret parameters are now registered as hidden Node inputs so that
getClipPreferences can read them (fixes generator pink screen).
6. Debug logging in HostSupport
- clipGetImage and clipGetRegionOfDefinition now catch exceptions
and log the failing clip name for easier debugging.
- Fix SIGSEGV in PluginMisc.Keyer by linking Param::SetInstance to instances.
Olive's custom param instances (IntegerInstance, DoubleInstance, etc.) were
not passing the SetInstance pointer to the OpenFX HostSupport base class,
leaving _paramSetInstance as nullptr. When Keyer called paramSetValue during
createInstanceAction, the suite function dereferenced the null pointer in
paramChangedByPlugin(). Now newParam() passes 'this' to every constructor.
- Fix render-thread crash when OFX plugins set params during rendering.
MinOFX calls paramSetValue inside createInstanceAction from the render
thread. SubmitUndoCommand() used to push undo commands directly to
UndoStack, which modifies QAction state (GUI-only). Added IsGuiThread()
check: non-GUI threads execute redo_now() and discard the command without
touching the undo stack.
- Enable PluginMisc.MergeOver and PluginMisc.Keyer integration tests.
MergeOver now supplies both Source and Bg textures; Keyer uses U16 format.
Both pass in the full test suite.
- Make ViewerQueue thread-safe with QMutex around AppendTimewise/PurgeBefore.
Adds copy ctor and assignment to support mutex-per-instance semantics.
This commit extends the OFX plugin support in Olive by:
- Initializing and scanning for OFX plugins
- Updating PluginNode to handle OFX plugin parameters and inputs
- Adding necessary methods and properties for OFX plugin integration
- Enhancing NodeFactory to include OFX plugin nodes
- Refactoring and renaming OliveInstance to OlivePluginInstance
- Introducing new classes for parameter handling (ParamInstance)
- Adding PluginJob for rendering OFX plugins
- Adjusting CMakeLists.txt files to include new source files