With multi-threaded rendering, the traditional rendering loop is split up into two pieces: the advance/input processing logic executed by the advance thread and the render-thread loop that executes drawing commands such “draw frame”. Scaleform 4.0 APIs accommodate multi-threading by defining GFx::MovieDisplayHandle that can be safely passed to the rendering thread. The GFx::Movie object itself should not be passed to the rendering thread since it is not inherently thread-safe and no longer contains the Display method.
The general movie rendering process can be broken down into the following steps:
The following reference demonstrates these steps in detail.
//------------------------------------------------------------------------
// 1. Movie Initialization
Ptr<GFx::Movie> pMovie = ...;
GFx::MovieDisplayHandle hMovieDisplay;
// Configure viewport after movie creation and grab the
// display handle.
pMovie->SetViewport(width, height, 0,0, width, height);
hMovieDisplay = pMovie->GetDisplayHandle();
// Pass the handle to render thread; this is engine-specific. In Scaleform Player,
// this is done by queuing up an internal function call.
pRenderThread->AddDisplayHandle(hMovieDisplay);
//------------------------------------------------------------------------
// 2. Processing loop
// Handle input and processing on the main thread. Movie callbacks
// such as ExternalInterface are also called here from Advance.
float deltaT = ...;
pMovie->HandleEvent(...);
pMovie->Advance(deltaT);
// Wait for previous frame rendering to complete and queue up
// a draw frame request.
pRenderThread->WaitForOutstandingDrawFrame();
pRenderThread->DrawFrame();
//------------------------------------------------------------------------
// 3. Rendering – Render thread DrawFrame logic
Ptr<Render::HAL> pHAL = ...;
pHAL->BeginFrame();
bool hasData = hMovieDisplay.NextCapture(pHAL->GetContextNotify());
if (hasData)
pHAL->Display(hMovieDisplay);
pHAL->EndFrame();
While most of the logic is self-explanatory, a couple of details stand out: