const uint32_t FRAME_COUNT_TRIGGER = 16;\
if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
{\
- if ( NULL != mImpl->root )\
+ for( auto root : mImpl->roots )
{\
- mImpl->frameCounter = 0;\
- PrintNodeTree( *mImpl->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
+ if ( NULL != root )\
+ {\
+ mImpl->frameCounter = 0;\
+ PrintNodeTree( *root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
+ }\
}\
}\
mImpl->frameCounter++;
renderInstructions( renderManager.GetRenderInstructionContainer() ),
renderTaskProcessor( renderTaskProcessor ),
backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
- taskList( renderMessageDispatcher ),
- systemLevelTaskList( renderMessageDispatcher ),
- root( NULL ),
- systemLevelRoot( NULL ),
renderers(),
textureSets(),
shaders(),
~Impl()
{
// Disconnect render tasks from nodes, before destroying the nodes
- RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
- for ( auto&& iter : tasks )
+ for( auto taskList : taskLists )
{
- iter->SetSourceNode( NULL );
- }
- // ..repeat for system level RenderTasks
- RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
- for ( auto&& iter : systemLevelTasks )
- {
- iter->SetSourceNode( NULL );
+ RenderTaskList::RenderTaskContainer& tasks = taskList->GetTasks();
+ for ( auto&& task : tasks )
+ {
+ task->SetSourceNode( NULL );
+ }
}
// UpdateManager owns the Nodes. Although Nodes are pool allocated they contain heap allocated parts
Node::Delete(*iter);
}
- // If there is root, reset it, otherwise do nothing as rendering was never started
- if( root )
+ for( auto root : roots )
{
root->OnDestroy();
-
- Node::Delete( root );
- root = NULL;
- }
-
- if( systemLevelRoot )
- {
- systemLevelRoot->OnDestroy();
-
- Node::Delete( systemLevelRoot );
- systemLevelRoot = NULL;
}
delete sceneController;
Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
- RenderTaskList taskList; ///< The list of scene graph render-tasks
- RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
+ OwnerContainer<RenderTaskList*> taskLists; ///< A container of scene graph render task lists
- Layer* root; ///< The root node (root is a layer)
- Layer* systemLevelRoot; ///< A separate root-node for system-level content
+ OwnerContainer<Layer*> roots; ///< A container of root nodes (root is a layer). The layers are not stored in the node memory pool.
Vector<Node*> nodes; ///< A container of all instantiated nodes
- SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
- SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
+ std::vector<SortedLayerPointers> sortedLayerLists; ///< A container of lists of Layer pointers sorted by depth (one list of sorted layers per root)
OwnerContainer< Camera* > cameras; ///< A container of cameras
OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
delete mImpl;
}
-void UpdateManager::InstallRoot( OwnerPointer<Layer>& layer, bool systemLevel )
+void UpdateManager::InstallRoot( OwnerPointer<Layer>& layer )
{
DALI_ASSERT_DEBUG( layer->IsLayer() );
DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
- if ( !systemLevel )
- {
- DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
- mImpl->root = layer.Release();
- mImpl->root->CreateTransform( &mImpl->transformManager );
- mImpl->root->SetRoot(true);
- }
- else
- {
- DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
- mImpl->systemLevelRoot = layer.Release();
- mImpl->systemLevelRoot->CreateTransform( &mImpl->transformManager );
- mImpl->systemLevelRoot->SetRoot(true);
- }
+ Layer* rootLayer = layer.Release();
+
+ DALI_ASSERT_DEBUG( std::find( mImpl->roots.begin(), mImpl->roots.end(), rootLayer ) == mImpl->roots.end() && "Root Node already installed" );
+ rootLayer->CreateTransform( &mImpl->transformManager );
+ rootLayer->SetRoot(true);
+ mImpl->roots.PushBack( rootLayer );
}
void UpdateManager::AddNode( OwnerPointer<Node>& node )
mImpl->customObjects.EraseObject( object );
}
+void UpdateManager::AddRenderTaskList( OwnerPointer<RenderTaskList>& taskList )
+{
+ RenderTaskList* taskListPointer = taskList.Release();
+ taskListPointer->SetRenderMessageDispatcher( &mImpl->renderMessageDispatcher );
+ mImpl->taskLists.PushBack( taskListPointer );
+}
+
+void UpdateManager::RemoveRenderTaskList( RenderTaskList* taskList )
+{
+ mImpl->taskLists.EraseObject( taskList );
+}
+
void UpdateManager::AddAnimation( OwnerPointer< SceneGraph::Animation >& animation )
{
mImpl->animations.PushBack( animation.Release() );
mImpl->textureSets.EraseObject( textureSet );
}
-RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
-{
- if ( !systemLevel )
- {
- // copy the list, this is only likely to happen once in application life cycle
- return &(mImpl->taskList);
- }
- else
- {
- // copy the list, this is only likely to happen once in application life cycle
- return &(mImpl->systemLevelTaskList);
- }
-}
-
uint32_t* UpdateManager::ReserveMessageSlot( uint32_t size, bool updateScene )
{
return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
void UpdateManager::ConstrainRenderTasks( BufferIndex bufferIndex )
{
- // Constrain system-level render-tasks
- const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
- for ( auto&& task : systemLevelTasks )
- {
- ConstrainPropertyOwner( *task, bufferIndex );
- }
-
// Constrain render-tasks
- const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
- for ( auto&& task : tasks )
+ for( auto taskList : mImpl->taskLists )
{
- ConstrainPropertyOwner( *task, bufferIndex );
+ RenderTaskList::RenderTaskContainer& tasks = taskList->GetTasks();
+ for ( auto&& task : tasks )
+ {
+ ConstrainPropertyOwner( *task, bufferIndex );
+ }
}
}
{
mImpl->nodeDirtyFlags = NodePropertyFlags::NOTHING;
- if ( !mImpl->root )
+ for( auto&& rootLayer : mImpl->roots )
{
- return;
- }
-
- // Prepare resources, update shaders, for each node
- // And add the renderers to the sorted layers. Start from root, which is also a layer
- mImpl->nodeDirtyFlags = UpdateNodeTree( *( mImpl->root ),
- bufferIndex,
- mImpl->renderQueue );
-
- if ( mImpl->systemLevelRoot )
- {
- mImpl->nodeDirtyFlags |= UpdateNodeTree( *( mImpl->systemLevelRoot ),
- bufferIndex,
- mImpl->renderQueue );
+ // Prepare resources, update shaders, for each node
+ // And add the renderers to the sorted layers. Start from root, which is also a layer
+ mImpl->nodeDirtyFlags |= UpdateNodeTree( *rootLayer,
+ bufferIndex,
+ mImpl->renderQueue );
}
}
ConstrainCustomObjects( bufferIndex );
//Clear the lists of renderers from the previous update
- for( auto&& layer : mImpl->sortedLayers )
+ for( auto sortedLayers : mImpl->sortedLayerLists )
{
- layer->ClearRenderables();
- }
-
- for( auto&& layer : mImpl->systemLevelSortedLayers )
- {
- layer->ClearRenderables();
+ for( auto&& layer : sortedLayers )
+ {
+ layer->ClearRenderables();
+ }
}
//Update node hierarchy, apply constraints and perform sorting / culling.
//reset the update buffer index and make sure there is enough room in the instruction container
if( mImpl->renderersAdded )
{
- mImpl->renderInstructions.ResetAndReserve( bufferIndex, mImpl->taskList.GetTaskCount() + mImpl->systemLevelTaskList.GetTaskCount() );
+ // Calculate how many render tasks we have in total
+ VectorBase::SizeType numberOfRenderTasks = 0;
+
+ const VectorBase::SizeType taskListCount = mImpl->taskLists.Count();
+ for ( VectorBase::SizeType index = 0u; index < taskListCount; index++ )
+ {
+ numberOfRenderTasks += mImpl->taskLists[index]->GetTasks().Count();
+ }
- if ( NULL != mImpl->root )
+ mImpl->renderInstructions.ResetAndReserve( bufferIndex,
+ static_cast<uint32_t>( numberOfRenderTasks ) );
+
+ for ( VectorBase::SizeType index = 0u; index < taskListCount; index++ )
{
- mImpl->renderTaskProcessor.Process( bufferIndex,
- mImpl->taskList,
- *mImpl->root,
- mImpl->sortedLayers,
- mImpl->renderInstructions,
- renderToFboEnabled,
- isRenderingToFbo );
-
- // Process the system-level RenderTasks last
- if ( NULL != mImpl->systemLevelRoot )
+ if ( NULL != mImpl->roots[index] )
{
mImpl->renderTaskProcessor.Process( bufferIndex,
- mImpl->systemLevelTaskList,
- *mImpl->systemLevelRoot,
- mImpl->systemLevelSortedLayers,
+ *mImpl->taskLists[index],
+ *mImpl->roots[index],
+ mImpl->sortedLayerLists[index],
mImpl->renderInstructions,
renderToFboEnabled,
isRenderingToFbo );
}
}
- // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
- bool doRenderOnceNotify = false;
- mImpl->renderTaskWaiting = false;
- for ( auto&& renderTask : mImpl->taskList.GetTasks() )
+ for( auto taskList : mImpl->taskLists )
{
- renderTask->UpdateState();
+ RenderTaskList::RenderTaskContainer& tasks = taskList->GetTasks();
- if( renderTask->IsWaitingToRender() &&
- renderTask->ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
+ // check the countdown and notify
+ bool doRenderOnceNotify = false;
+ mImpl->renderTaskWaiting = false;
+ for ( auto&& renderTask : tasks )
{
- mImpl->renderTaskWaiting = true; // keep update/render threads alive
+ renderTask->UpdateState();
+
+ if( renderTask->IsWaitingToRender() &&
+ renderTask->ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
+ {
+ mImpl->renderTaskWaiting = true; // keep update/render threads alive
+ }
+
+ if( renderTask->HasRendered() )
+ {
+ doRenderOnceNotify = true;
+ }
}
- if( renderTask->HasRendered() )
+ if( doRenderOnceNotify )
{
- doRenderOnceNotify = true;
+ DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
+ mImpl->notificationManager.QueueCompleteNotification( taskList->GetCompleteNotificationInterface() );
}
}
- if( doRenderOnceNotify )
- {
- DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
- mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
- }
-
// Macro is undefined in release build.
SNAPSHOT_NODE_LOGGING;
mImpl->renderingBehavior = renderingBehavior;
}
-void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
+void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, const Layer* rootLayer )
{
- if ( !systemLevel )
- {
- // just copy the vector of pointers
- mImpl->sortedLayers = layers;
- }
- else
+ const VectorBase::SizeType rootCount = mImpl->roots.Count();
+
+ // Make sure we reserve the correct size for the container so that
+ // we can save the sorted layers in the same order as the root layer
+ mImpl->sortedLayerLists.resize( rootCount );
+
+ for ( VectorBase::SizeType rootIndex = 0u; rootIndex < rootCount; rootIndex++ )
{
- mImpl->systemLevelSortedLayers = layers;
+ Layer* root = mImpl->roots[rootIndex];
+ if ( root == rootLayer )
+ {
+ mImpl->sortedLayerLists[rootIndex] = layers;
+ break;
+ }
}
}
iter.node->SetDepthIndex( iter.sortedDepth );
}
- // Go through node hierarchy and rearrange siblings according to depth-index
- SortSiblingNodesRecursively( *( mImpl->root ) );
+ for( auto root : mImpl->roots )
+ {
+ // Go through node hierarchy and rearrange siblings according to depth-index
+ SortSiblingNodesRecursively( *root );
+ }
}
bool UpdateManager::IsDefaultSurfaceRectChanged()