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: