Hosts are generally multi-threaded, those with a GUI will most likely have an interactive thread and a rendering thread, while any host running on a multi-CPU machine may have a render thread per CPU. Host may batch effects off to a render farm, where the same effect has separate frames rendered on completely different machines. OFX needs to address all these situations.
Threads in the host application can be broken into two categories...
For a given effect instance, there can be only one main thread and zero or more render threads. An instance must be able to handle simultaneous actions called on the main and render threads. A plugin can control the number of simultaneous render threads via the
kOfxImageEffectPluginRenderThreadSafety
effect descriptor property.
The only actions that can be called on a render thread are...
If a plugin cannot support this multi-threading behaviour, it will need to perform explicit locking itself, using the locking mechanisms in the suites defined in ofxMultiThread.h
This will also mean that the host may need to perform locking on the various function calls over the API. For example, a main and render thread may both simultaneously attempt to access a parameter from a single effect instance. The locking should...
For example, a render thread will only cause a parameter to lock out writes only for the duration of the call that reads the parameter, not for the duration of the whole render action. This will allow a main thread to continue writing to the parameter during a render. This is especially important if you have a custom interactive GUI that you want to keep working during a render call.
Note that a main thread should generally issue an abort to any linked render thread when a parameter or other value affecting the effect (eg: time) has been changed by the user. A re-render should then be issued so that a correct frame is created.
How an effect handles simulanteous calls to render is dealt with in \ref ImageEffectsMultiThreadingRendering.
Many hosts get around the problem of sharing a single instance in a UI thread and a render thread by having two instances, one for the user to interact with and a render only one that shadows the UI instance.
When running on a main thread, some actions may end up being called recursively. A plug-in must be able to deal with this. For example consider the following sequence of events in a plugin...
kOfxActionInstanceChanged
action
kOfxActionInstanceChanged
action for parameter B
kOfxInteractActionDraw
issued to the effect's overlay
kOfxInteractActionDraw
returns
kOfxActionInstanceChanged
action for parameter B returns
kOfxActionInstanceChanged
action returns
The image effect actions which may trigger a recursive action call on a single instance are...
The interact actions which may trigger a recursive action to be called on the associated plugin instance are...
The image effect actions which may be called recursively are...
kOfxActionBeginInstanceChanged
kOfxActionInstanceChanged
kOfxActionEndInstanceChanged
kOfxImageEffectActionGetClipPreferences
kOfxImageEffectActionGetRegionOfDefinition
(as a result of calling
OfxImageEffectSuiteV1::clipGetImage
from
kOfxActionInstanceChanged
)
kOfxImageEffectActionGetRegionsOfInterest
(as a result of calling
OfxImageEffectSuiteV1::clipGetImage
from
kOfxActionInstanceChanged
)
The interact actions which may be called recursively are...