/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
// INTERNAL INCLUDES
#include <dali/public-api/common/stage.h>
-#include <dali/public-api/common/set-wrapper.h>
+#include <dali/devel-api/common/set-wrapper.h>
+#include <dali/devel-api/common/mutex.h>
#include <dali/integration-api/core.h>
#include <dali/integration-api/render-controller.h>
-#include <dali/integration-api/shader-data.h>
+#include <dali/internal/common/shader-data.h>
#include <dali/integration-api/debug.h>
#include <dali/internal/common/core-impl.h>
#include <dali/internal/event/common/notification-manager.h>
#include <dali/internal/event/common/property-notification-impl.h>
#include <dali/internal/event/common/property-notifier.h>
+#include <dali/internal/event/effects/shader-factory.h>
#include <dali/internal/update/animation/scene-graph-animator.h>
#include <dali/internal/update/animation/scene-graph-animation.h>
#include <dali/internal/update/common/discard-queue.h>
-#include <dali/internal/update/common/double-buffered.h>
+#include <dali/internal/update/common/scene-graph-buffers.h>
+#include <dali/internal/update/common/scene-graph-property-buffer.h>
+#include <dali/internal/update/controllers/render-message-dispatcher.h>
+#include <dali/internal/update/controllers/scene-controller-impl.h>
+#include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
+#include <dali/internal/update/manager/object-owner-container.h>
#include <dali/internal/update/manager/prepare-render-algorithms.h>
#include <dali/internal/update/manager/process-render-tasks.h>
-#include <dali/internal/update/resources/resource-manager.h>
-#include <dali/internal/update/resources/complete-status-manager.h>
-#include <dali/internal/update/common/scene-graph-buffers.h>
-#include <dali/internal/update/render-tasks/scene-graph-render-task.h>
-#include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
#include <dali/internal/update/manager/sorted-layers.h>
#include <dali/internal/update/manager/update-algorithms.h>
-#include <dali/internal/update/queue/update-message-queue.h>
#include <dali/internal/update/manager/update-manager-debug.h>
-#include <dali/internal/update/controllers/render-message-dispatcher.h>
-#include <dali/internal/update/controllers/scene-controller-impl.h>
-#include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
-#include <dali/internal/update/modeling/scene-graph-material.h>
#include <dali/internal/update/node-attachments/scene-graph-camera-attachment.h>
+#include <dali/internal/update/node-attachments/scene-graph-image-attachment.h>
#include <dali/internal/update/nodes/node.h>
#include <dali/internal/update/nodes/scene-graph-layer.h>
+#include <dali/internal/update/queue/update-message-queue.h>
+#include <dali/internal/update/render-tasks/scene-graph-render-task.h>
+#include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
+#include <dali/internal/update/rendering/scene-graph-material.h>
+#include <dali/internal/update/rendering/scene-graph-sampler.h>
+#include <dali/internal/update/rendering/scene-graph-geometry.h>
+#include <dali/internal/update/resources/resource-manager.h>
+#include <dali/internal/update/resources/complete-status-manager.h>
#include <dali/internal/update/touch/touch-resampler.h>
#include <dali/internal/render/common/render-instruction-container.h>
#include <dali/internal/render/queue/render-queue.h>
#include <dali/internal/render/common/performance-monitor.h>
#include <dali/internal/render/gl-resources/texture-cache.h>
-#include <dali/internal/render/renderers/render-material.h>
-#include <dali/internal/render/shaders/shader.h>
-
-#ifdef DYNAMICS_SUPPORT
-#include <dali/integration-api/dynamics/dynamics-world-settings.h>
-#include <dali/internal/update/dynamics/scene-graph-dynamics-world.h>
-#endif
+#include <dali/internal/render/shaders/scene-graph-shader.h>
// Un-comment to enable node tree debug logging
//#define NODE_TREE_LOGGING 1
namespace
{
-const int DEFAULT_CAMERA_INDEX = -1;
-
void DestroyNodeSet( std::set<Node*>& nodeSet )
{
for( std::set<Node*>::iterator iter = nodeSet.begin(); iter != nodeSet.end(); ++iter )
typedef ShaderContainer::Iterator ShaderIter;
typedef ShaderContainer::ConstIterator ShaderConstIter;
-typedef AnimatableMeshContainer::Iterator AnimatableMeshIter;
-typedef AnimatableMeshContainer::ConstIterator AnimatableMeshConstIter;
-typedef MaterialContainer::Iterator MaterialIter;
+typedef std::vector<Internal::ShaderDataPtr> ShaderDataBinaryQueue;
typedef OwnerContainer<PanGesture*> GestureContainer;
typedef GestureContainer::Iterator GestureIter;
notificationManager( notificationManager ),
animationFinishedNotifier( animationFinishedNotifier ),
propertyNotifier( propertyNotifier ),
+ shaderSaver( NULL ),
resourceManager( resourceManager ),
discardQueue( discardQueue ),
renderController( renderController ),
systemLevelTaskList ( completeStatusManager ),
root( NULL ),
systemLevelRoot( NULL ),
+ renderers( sceneGraphBuffers, discardQueue ),
+ geometries( sceneGraphBuffers, discardQueue ),
+ materials( sceneGraphBuffers, discardQueue ),
+ samplers( sceneGraphBuffers, discardQueue ),
+ propertyBuffers( sceneGraphBuffers, discardQueue ),
messageQueue( renderController, sceneGraphBuffers ),
- dynamicsChanged( false ),
keepRenderingSeconds( 0.0f ),
animationFinishedDuringUpdate( false ),
- activeConstraints( 0 ),
nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
previousUpdateScene( false ),
frameCounter( 0 ),
renderTaskWaiting( false )
{
sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue, textureCache, completeStatusManager );
+
+ renderers.SetSceneController( *sceneController );
+ geometries.SetSceneController( *sceneController );
+ materials.SetSceneController( *sceneController );
+ propertyBuffers.SetSceneController( *sceneController );
+ samplers.SetSceneController( *sceneController );
}
~Impl()
NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
CompleteNotificationInterface& animationFinishedNotifier; ///< Provides notification to applications when animations are finished.
PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
+ ShaderSaver* shaderSaver; ///< Saves shader binaries.
ResourceManager& resourceManager; ///< resource manager
DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
RenderController& renderController; ///< render controller
AnimationContainer animations; ///< A container of owned animations
PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
+ ObjectOwnerContainer<Renderer> renderers;
+ ObjectOwnerContainer<Geometry> geometries; ///< A container of geometries
+ ObjectOwnerContainer<Material> materials; ///< A container of materials
+ ObjectOwnerContainer<Sampler> samplers; ///< A container of samplers
+ ObjectOwnerContainer<PropertyBuffer> propertyBuffers; ///< A container of property buffers
+
ShaderContainer shaders; ///< A container of owned shaders
- AnimatableMeshContainer animatableMeshes; ///< A container of owned animatable meshes
- MaterialContainer materials; ///< A container of owned materials
MessageQueue messageQueue; ///< The messages queued from the event-thread
-
-#ifdef DYNAMICS_SUPPORT
- OwnerPointer<DynamicsWorld> dynamicsWorld; ///< Wrapper for dynamics simulation
-#endif
- bool dynamicsChanged; ///< This is set to true if an object is changed in the dynamics simulation tick
+ ShaderDataBinaryQueue renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
+ ShaderDataBinaryQueue updateCompiledShaders; ///< Shaders to be sent from Update to Event
+ Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
- unsigned int activeConstraints; ///< number of active constraints from previous frame
int nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
delete mImpl;
}
-EventToUpdate& UpdateManager::GetEventToUpdate()
-{
- return mImpl->messageQueue;
-}
-
void UpdateManager::InstallRoot( SceneGraph::Layer* layer, bool systemLevel )
{
DALI_ASSERT_DEBUG( layer->IsLayer() );
mImpl->activeDisconnectedNodes.insert( node ); // Takes ownership of node
}
-void UpdateManager::ConnectNode( Node* parent, Node* node, int index )
+void UpdateManager::ConnectNode( Node* parent, Node* node )
{
DALI_ASSERT_ALWAYS( NULL != parent );
DALI_ASSERT_ALWAYS( NULL != node );
node->SetActive( true );
- parent->ConnectChild( node, index );
+ parent->ConnectChild( node );
}
void UpdateManager::DisconnectNode( Node* node )
node->OnDestroy();
}
+//@todo MESH_REWORK Extend to allow arbitrary scene objects to connect to each other
void UpdateManager::AttachToNode( Node* node, NodeAttachment* attachment )
{
DALI_ASSERT_DEBUG( node != NULL );
// attach node to attachment first so that parent is known by the time attachment is connected
node->Attach( *attachment ); // node takes ownership
- attachment->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
+
+ // @todo MESH_REWORK Remove after merge of SceneGraph::RenderableAttachment and SceneGraph::RendererAttachment
+ if( dynamic_cast<SceneGraph::ImageAttachment*>( attachment ) != NULL )
+ {
+ attachment->Initialize( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
+ }
}
void UpdateManager::AddObject( PropertyOwner* object )
propertyNotification->SetNotifyMode( notifyMode );
}
+ObjectOwnerContainer<Geometry>& UpdateManager::GetGeometryOwner()
+{
+ return mImpl->geometries;
+}
+
+ObjectOwnerContainer<Renderer>& UpdateManager::GetRendererOwner()
+{
+ return mImpl->renderers;
+}
+
+
+ObjectOwnerContainer<Material>& UpdateManager::GetMaterialOwner()
+{
+ return mImpl->materials;
+}
+
+ObjectOwnerContainer<Sampler>& UpdateManager::GetSamplerOwner()
+{
+ return mImpl->samplers;
+}
+
+ObjectOwnerContainer<PropertyBuffer>& UpdateManager::GetPropertyBufferOwner()
+{
+ return mImpl->propertyBuffers;
+}
+
void UpdateManager::AddShader( Shader* shader )
{
DALI_ASSERT_DEBUG( NULL != shader );
shader->Initialize( mImpl->renderQueue, mImpl->sceneController->GetTextureCache() );
}
-void UpdateManager::RemoveShader(Shader* shader)
+void UpdateManager::RemoveShader( Shader* shader )
{
DALI_ASSERT_DEBUG(shader != NULL);
DALI_ASSERT_DEBUG(false);
}
-void UpdateManager::SetShaderProgram( Shader* shader, GeometryType geometryType, ShaderSubTypes subType, ResourceId resourceId, size_t shaderHash, bool modifiesGeometry )
+void UpdateManager::SetShaderProgram( Shader* shader,
+ Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
{
- DALI_LOG_TRACE_METHOD_FMT(Debug::Filter::gShader, " - (geometryType:%d subType:%d id:%d hash:%d)\n", geometryType, subType, resourceId, shaderHash);
-
- DALI_ASSERT_ALWAYS( NULL != shader && "shader is uninitialized" );
-
- Integration::ShaderDataPtr shaderData( mImpl->resourceManager.GetShaderData(resourceId) );
if( shaderData )
{
- shaderData->SetHashValue( shaderHash );
- shaderData->SetResourceId( resourceId );
- typedef MessageValue6< Shader, GeometryType, Internal::ShaderSubTypes, Integration::ResourceId, Integration::ShaderDataPtr, ProgramCache*, bool> DerivedType;
+ typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
// Reserve some memory inside the render queue
unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
// Construct message in the render queue memory; note that delete should not be called on the return value
- new (slot) DerivedType( shader, &Shader::SetProgram, geometryType, subType, resourceId, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
- }
-}
-
-void UpdateManager::AddAnimatableMesh( AnimatableMesh* animatableMesh )
-{
- mImpl->animatableMeshes.PushBack(animatableMesh);
-}
-
-void UpdateManager::RemoveAnimatableMesh( AnimatableMesh* animatableMesh )
-{
- DALI_ASSERT_DEBUG(animatableMesh != NULL);
-
- AnimatableMeshContainer& animatableMeshes = mImpl->animatableMeshes;
-
- // Find the animatableMesh and destroy it
- for ( AnimatableMeshIter iter = animatableMeshes.Begin(); iter != animatableMeshes.End(); ++iter )
- {
- AnimatableMesh& current = **iter;
- if ( ¤t == animatableMesh )
- {
- animatableMeshes.Erase( iter );
- break;
- }
+ new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
}
}
-void UpdateManager::AddMaterial( Material* material )
-{
- DALI_ASSERT_DEBUG( NULL != material );
-
- mImpl->materials.PushBack( material );
- RenderMaterial* renderMaterial = new RenderMaterial();
-
- typedef MessageValue1< RenderManager, RenderMaterial* > DerivedType;
-
- // Reserve some memory inside the render queue
- unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
-
- // Construct message in the render queue memory; note that delete should not be called on the return value
- new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddRenderMaterial, renderMaterial );
-
- material->SetRenderMaterial( renderMaterial );
- material->OnStageConnection( *mImpl->sceneController );
-}
-
-void UpdateManager::RemoveMaterial( Material* theMaterial )
+void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
{
- // Caused by last reference to material being released (e.g. app or internal mesh-actor)
-
- for ( MaterialIter iter=mImpl->materials.Begin(), end=mImpl->materials.End() ; iter != end ; ++iter )
+ DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
+ DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
{
- const Material* aMaterial = *iter;
-
- if( aMaterial == theMaterial )
- {
- typedef MessageValue1< RenderManager, RenderMaterial* > DerivedType;
-
- // Reserve some memory inside the render queue
- unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
-
- // Construct message in the render queue memory; note that delete should not be called on the return value
- new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveRenderMaterial, theMaterial->GetRenderMaterial() );
-
- mImpl->materials.Erase( iter );
- break;
- }
+ // lock as update might be sending previously compiled shaders to event thread
+ Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
+ mImpl->renderCompiledShaders.push_back( shaderData );
}
}
DALI_ASSERT_DEBUG(false);
}
-void UpdateManager::ResetNodeProperty( Node& node )
+unsigned int* UpdateManager::ReserveMessageSlot( std::size_t size, bool updateScene )
+{
+ return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
+}
+
+void UpdateManager::EventProcessingStarted()
+{
+ mImpl->messageQueue.EventProcessingStarted();
+}
+
+bool UpdateManager::FlushQueue()
{
- node.ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
+ return mImpl->messageQueue.FlushQueue();
}
-void UpdateManager::ResetProperties()
+void UpdateManager::ResetProperties( BufferIndex bufferIndex )
{
PERF_MONITOR_START(PerformanceMonitor::RESET_PROPERTIES);
// Animated properties have to be reset to their original value each frame
- // Reset node properties
+ // Reset root properties
if ( mImpl->root )
{
- ResetNodeProperty( *mImpl->root );
+ mImpl->root->ResetToBaseValues( bufferIndex );
}
-
if ( mImpl->systemLevelRoot )
{
- ResetNodeProperty( *mImpl->systemLevelRoot );
+ mImpl->systemLevelRoot->ResetToBaseValues( bufferIndex );
}
// Reset the Connected Nodes
const std::set<Node*>::iterator endIter = mImpl->connectedNodes.end();
for( std::set<Node*>::iterator iter = mImpl->connectedNodes.begin(); endIter != iter; ++iter )
{
- ResetNodeProperty( **iter );
+ (*iter)->ResetToBaseValues( bufferIndex );
}
// If a Node is disconnected, it may still be "active" (requires a reset in next frame)
for( std::set<Node*>::iterator iter = mImpl->activeDisconnectedNodes.begin(); mImpl->activeDisconnectedNodes.end() != iter; iter = mImpl->activeDisconnectedNodes.begin() )
{
Node* node = *iter;
- node->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
+ node->ResetToBaseValues( bufferIndex );
node->SetActive( false );
// Move everything from activeDisconnectedNodes to disconnectedNodes (no need to reset again)
for (RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
{
- (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
+ (*iter)->ResetToBaseValues( bufferIndex );
}
// Reset render-task list properties to base values.
for (RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
{
- (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
+ (*iter)->ResetToBaseValues( bufferIndex );
}
// Reset custom object properties to base values
for (OwnerContainer<PropertyOwner*>::Iterator iter = mImpl->customObjects.Begin(); iter != mImpl->customObjects.End(); ++iter)
{
- (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
+ (*iter)->ResetToBaseValues( bufferIndex );
}
+ mImpl->materials.ResetToBaseValues( bufferIndex );
+ mImpl->geometries.ResetToBaseValues( bufferIndex );
+ mImpl->propertyBuffers.ResetToBaseValues( bufferIndex );
+ mImpl->samplers.ResetToBaseValues( bufferIndex );
+ mImpl->renderers.ResetToBaseValues( bufferIndex );
+
+
// Reset animatable shader properties to base values
for (ShaderIter iter = mImpl->shaders.Begin(); iter != mImpl->shaders.End(); ++iter)
{
- (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
- }
-
- // Reset animatable mesh properties to base values
- for ( AnimatableMeshIter iter = mImpl->animatableMeshes.Begin(); iter != mImpl->animatableMeshes.End(); ++iter )
- {
- (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
+ (*iter)->ResetToBaseValues( bufferIndex );
}
PERF_MONITOR_END(PerformanceMonitor::RESET_PROPERTIES);
}
-bool UpdateManager::ProcessGestures( unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
+bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
{
bool gestureUpdated( false );
for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
{
PanGesture& gesture = **iter;
- gesture.ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() ); // Needs to be done every time as gesture data is written directly to an update-buffer rather than via a message
+ gesture.ResetToBaseValues( bufferIndex ); // Needs to be done every time as gesture data is written directly to an update-buffer rather than via a message
gestureUpdated |= gesture.UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
}
return gestureUpdated;
}
-void UpdateManager::Animate( float elapsedSeconds )
+void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
{
PERF_MONITOR_START(PerformanceMonitor::ANIMATE_NODES);
while ( iter != animations.End() )
{
Animation* animation = *iter;
- bool finished = animation->Update(mSceneGraphBuffers.GetUpdateBufferIndex(), elapsedSeconds);
+ bool finished = animation->Update( bufferIndex, elapsedSeconds );
mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
PERF_MONITOR_END(PerformanceMonitor::ANIMATE_NODES);
}
-void UpdateManager::ApplyConstraints()
+void UpdateManager::ApplyConstraints( BufferIndex bufferIndex )
{
PERF_MONITOR_START(PerformanceMonitor::APPLY_CONSTRAINTS);
- mImpl->activeConstraints = 0;
-
// constrain custom objects... (in construction order)
OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
{
PropertyOwner& object = **iter;
- mImpl->activeConstraints += ConstrainPropertyOwner( object, mSceneGraphBuffers.GetUpdateBufferIndex() );
+ ConstrainPropertyOwner( object, bufferIndex );
}
// constrain nodes... (in Depth First traversal order)
if ( mImpl->root )
{
- mImpl->activeConstraints += ConstrainNodes( *(mImpl->root), mSceneGraphBuffers.GetUpdateBufferIndex() );
+ ConstrainNodes( *(mImpl->root), bufferIndex );
}
if ( mImpl->systemLevelRoot )
{
- mImpl->activeConstraints += ConstrainNodes( *(mImpl->systemLevelRoot), mSceneGraphBuffers.GetUpdateBufferIndex() );
+ ConstrainNodes( *(mImpl->systemLevelRoot), bufferIndex );
}
// constrain other property-owners after nodes as they are more likely to depend on a node's
for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
{
RenderTask& task = **iter;
- mImpl->activeConstraints += ConstrainPropertyOwner( task, mSceneGraphBuffers.GetUpdateBufferIndex() );
+ ConstrainPropertyOwner( task, bufferIndex );
}
// Constrain render-tasks
for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
{
RenderTask& task = **iter;
- mImpl->activeConstraints += ConstrainPropertyOwner( task, mSceneGraphBuffers.GetUpdateBufferIndex() );
+ ConstrainPropertyOwner( task, bufferIndex );
}
- // constrain meshes (in construction order)
- AnimatableMeshContainer& meshes = mImpl->animatableMeshes;
- for ( AnimatableMeshIter iter = meshes.Begin(); iter != meshes.End(); ++iter )
- {
- AnimatableMesh& mesh = **iter;
- mImpl->activeConstraints += ConstrainPropertyOwner( mesh, mSceneGraphBuffers.GetUpdateBufferIndex() );
- }
+ // Constrain Materials and geometries
+ mImpl->materials.ConstrainObjects( bufferIndex );
+ mImpl->geometries.ConstrainObjects( bufferIndex );
+ mImpl->samplers.ConstrainObjects( bufferIndex );
+ mImpl->propertyBuffers.ConstrainObjects( bufferIndex );
+ mImpl->renderers.ConstrainObjects( bufferIndex );
// constrain shaders... (in construction order)
ShaderContainer& shaders = mImpl->shaders;
for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
{
Shader& shader = **iter;
- mImpl->activeConstraints += ConstrainPropertyOwner( shader, mSceneGraphBuffers.GetUpdateBufferIndex() );
+ ConstrainPropertyOwner( shader, bufferIndex );
}
PERF_MONITOR_END(PerformanceMonitor::APPLY_CONSTRAINTS);
}
-void UpdateManager::ProcessPropertyNotifications()
+void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
{
PropertyNotificationContainer ¬ifications = mImpl->propertyNotifications;
PropertyNotificationIter iter = notifications.Begin();
while ( iter != notifications.End() )
{
PropertyNotification* notification = *iter;
-
- bool valid = notification->Check( mSceneGraphBuffers.GetUpdateBufferIndex() );
-
+ bool valid = notification->Check( bufferIndex );
if(valid)
{
mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
}
}
-void UpdateManager::UpdateNodes()
+void UpdateManager::ForwardCompiledShadersToEventThread()
+{
+ DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
+ if( mImpl->shaderSaver )
+ {
+ // lock and swap the queues
+ {
+ // render might be attempting to send us more binaries at the same time
+ Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
+ mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
+ }
+
+ if( mImpl->updateCompiledShaders.size() > 0 )
+ {
+ ShaderSaver& factory = *mImpl->shaderSaver;
+ ShaderDataBinaryQueue::iterator i = mImpl->updateCompiledShaders.begin();
+ ShaderDataBinaryQueue::iterator end = mImpl->updateCompiledShaders.end();
+ for( ; i != end; ++i )
+ {
+ mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, *i ) );
+ }
+ // we don't need them in update anymore
+ mImpl->updateCompiledShaders.clear();
+ }
+ }
+}
+
+void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
+{
+ const Internal::OwnerContainer<Renderer*>& rendererContainer( mImpl->renderers.GetObjectContainer() );
+ unsigned int rendererCount( rendererContainer.Size() );
+ for( unsigned int i(0); i<rendererCount; ++i )
+ {
+ if( rendererContainer[i]->IsReferenced() )
+ {
+ rendererContainer[i]->PrepareResources(bufferIndex, mImpl->resourceManager);
+ rendererContainer[i]->PrepareRender( bufferIndex );
+ }
+ }
+}
+
+void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
{
mImpl->nodeDirtyFlags = NothingFlag;
// Prepare resources, update shaders, update attachments, for each node
// And add the renderers to the sorted layers. Start from root, which is also a layer
mImpl->nodeDirtyFlags = UpdateNodesAndAttachments( *( mImpl->root ),
- mSceneGraphBuffers.GetUpdateBufferIndex(),
+ bufferIndex,
mImpl->resourceManager,
mImpl->renderQueue );
if ( mImpl->systemLevelRoot )
{
mImpl->nodeDirtyFlags |= UpdateNodesAndAttachments( *( mImpl->systemLevelRoot ),
- mSceneGraphBuffers.GetUpdateBufferIndex(),
+ bufferIndex,
mImpl->resourceManager,
mImpl->renderQueue );
}
PERF_MONITOR_END( PerformanceMonitor::UPDATE_NODES );
}
-void UpdateManager::UpdateMeshes( BufferIndex updateBufferIndex, AnimatableMeshContainer& meshes )
-{
- for ( AnimatableMeshIter iter = meshes.Begin(); iter != meshes.End(); ++iter )
- {
- AnimatableMesh& current = **iter;
- current.UpdateMesh( updateBufferIndex );
- }
-}
-
-void UpdateManager::UpdateMaterials( BufferIndex updateBufferIndex, MaterialContainer& materials )
-{
- for( MaterialIter iter = materials.Begin(), end = materials.End(); iter != end; iter++ )
- {
- Material* material = *iter;
- material->PrepareResources( updateBufferIndex, mImpl->resourceManager );
- }
-}
-
-void UpdateManager::PrepareMaterials( BufferIndex updateBufferIndex, MaterialContainer& materials )
-{
- for( MaterialIter iter = materials.Begin(), end = materials.End(); iter != end; iter++ )
- {
- Material* material = *iter;
- material->PrepareRender( updateBufferIndex );
- }
-}
-
unsigned int UpdateManager::Update( float elapsedSeconds,
unsigned int lastVSyncTimeMilliseconds,
unsigned int nextVSyncTimeMilliseconds )
// Measure the time spent in UpdateManager::Update
PERF_MONITOR_START(PerformanceMonitor::UPDATE);
+ const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
+
// Update the frame time delta on the render thread.
mImpl->renderManager.SetFrameDeltaTime(elapsedSeconds);
// 1) Clear nodes/resources which were previously discarded
- mImpl->discardQueue.Clear( mSceneGraphBuffers.GetUpdateBufferIndex() );
+ mImpl->discardQueue.Clear( bufferIndex );
// 2) Grab any loaded resources
- bool resourceChanged = mImpl->resourceManager.UpdateCache( mSceneGraphBuffers.GetUpdateBufferIndex() );
+ bool resourceChanged = mImpl->resourceManager.UpdateCache( bufferIndex );
// 3) Process Touches & Gestures
mImpl->touchResampler.Update();
- const bool gestureUpdated = ProcessGestures( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
+ const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
+
+ const bool updateScene = // The scene-graph requires an update if..
+ (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
+ IsAnimationRunning() || // ..at least one animation is running OR
+ mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
+ resourceChanged || // ..one or more resources were updated/changed OR
+ gestureUpdated; // ..a gesture property was updated
- const bool updateScene = // The scene-graph requires an update if..
- mImpl->activeConstraints != 0 || // ..constraints were active in previous frame OR
- (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
- IsAnimationRunning() || // ..at least one animation is running OR
- mImpl->dynamicsChanged || // ..there was a change in the dynamics simulation OR
- mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
- resourceChanged || // ..one or more resources were updated/changed OR
- gestureUpdated; // ..a gesture property was updated
// Although the scene-graph may not require an update, we still need to synchronize double-buffered
// values if the scene was updated in the previous frame.
if( updateScene || mImpl->previousUpdateScene )
{
// 4) Reset properties from the previous update
- ResetProperties();
+ ResetProperties( bufferIndex );
}
// 5) Process the queued scene messages
- mImpl->messageQueue.ProcessMessages();
+ mImpl->messageQueue.ProcessMessages( bufferIndex );
// 6) Post Process Ids of resources updated by renderer
- mImpl->resourceManager.PostProcessResources( mSceneGraphBuffers.GetUpdateBufferIndex() );
+ mImpl->resourceManager.PostProcessResources( bufferIndex );
+
+ // 6.1) Forward compiled shader programs to event thread for saving
+ ForwardCompiledShadersToEventThread();
// Although the scene-graph may not require an update, we still need to synchronize double-buffered
// renderer lists if the scene was updated in the previous frame.
if( updateScene || mImpl->previousUpdateScene )
{
// 7) Animate
- Animate( elapsedSeconds );
+ Animate( bufferIndex, elapsedSeconds );
// 8) Apply Constraints
- ApplyConstraints();
+ ApplyConstraints( bufferIndex );
-#ifdef DYNAMICS_SUPPORT
- // 9) Update dynamics simulation
- mImpl->dynamicsChanged = false;
- if( mImpl->dynamicsWorld )
- {
- mImpl->dynamicsChanged = mImpl->dynamicsWorld->Update( elapsedSeconds );
- }
-#endif
+ // 9) Check Property Notifications
+ ProcessPropertyNotifications( bufferIndex );
- // 10) Check Property Notifications
- ProcessPropertyNotifications();
-
- // 11) Clear the lists of renderable-attachments from the previous update
+ // 10) Clear the lists of renderable-attachments from the previous update
ClearRenderables( mImpl->sortedLayers );
ClearRenderables( mImpl->systemLevelSortedLayers );
- // 12) Update animated meshes
- UpdateMeshes( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->animatableMeshes );
-
- // 13) Update materials. Prepares image resources
- UpdateMaterials( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->materials );
-
- // 14) Update node hierarchy and perform sorting / culling.
+ // 11) Update node hierarchy and perform sorting / culling.
// This will populate each Layer with a list of renderers which are ready.
- UpdateNodes();
+ UpdateNodes( bufferIndex );
+ UpdateRenderers( bufferIndex );
+
- // 15) Prepare for the next render
+ // 12) Prepare for the next render
PERF_MONITOR_START(PerformanceMonitor::PREPARE_RENDERABLES);
- PrepareMaterials( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->materials );
- PrepareRenderables( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->sortedLayers );
- PrepareRenderables( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->systemLevelSortedLayers );
+
+ PrepareRenderables( bufferIndex, mImpl->sortedLayers );
+ PrepareRenderables( bufferIndex, mImpl->systemLevelSortedLayers );
PERF_MONITOR_END(PerformanceMonitor::PREPARE_RENDERABLES);
PERF_MONITOR_START(PerformanceMonitor::PROCESS_RENDER_TASKS);
- // 16) Process the RenderTasks; this creates the instructions for rendering the next frame.
+ // 14) Process the RenderTasks; this creates the instructions for rendering the next frame.
// reset the update buffer index and make sure there is enough room in the instruction container
- mImpl->renderInstructions.ResetAndReserve( mSceneGraphBuffers.GetUpdateBufferIndex(),
+ mImpl->renderInstructions.ResetAndReserve( bufferIndex,
mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
if ( NULL != mImpl->root )
{
- ProcessRenderTasks( mSceneGraphBuffers.GetUpdateBufferIndex(),
+ ProcessRenderTasks( bufferIndex,
mImpl->completeStatusManager,
mImpl->taskList,
*mImpl->root,
// Process the system-level RenderTasks last
if ( NULL != mImpl->systemLevelRoot )
{
- ProcessRenderTasks( mSceneGraphBuffers.GetUpdateBufferIndex(),
+ ProcessRenderTasks( bufferIndex,
mImpl->completeStatusManager,
mImpl->systemLevelTaskList,
*mImpl->systemLevelRoot,
renderTask.UpdateState();
if( renderTask.IsWaitingToRender() &&
- renderTask.ReadyToRender(mSceneGraphBuffers.GetUpdateBufferIndex()) /*avoid updating forever when source actor is off-stage*/ )
+ renderTask.ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
{
mImpl->renderTaskWaiting = true; // keep update/render threads alive
}
keepUpdating |= KeepUpdating::MONITORING_PERFORMANCE;
#endif
- // The update has finished; swap the double-buffering indices
- mSceneGraphBuffers.Swap();
-
// tell the update manager that we're done so the queue can be given to event thread
mImpl->notificationManager.UpdateCompleted();
+ // The update has finished; swap the double-buffering indices
+ mSceneGraphBuffers.Swap();
+
PERF_MONITOR_END(PerformanceMonitor::UPDATE);
return keepUpdating;
keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
}
- if ( !mImpl->messageQueue.WasEmpty() )
- {
- keepUpdatingRequest |= KeepUpdating::INCOMING_MESSAGES;
- }
-
if ( IsAnimationRunning() ||
mImpl->animationFinishedDuringUpdate )
{
keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
}
- if ( mImpl->dynamicsChanged )
- {
- keepUpdatingRequest |= KeepUpdating::DYNAMICS_CHANGED;
- }
-
if ( mImpl->renderTaskWaiting )
{
keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
}
}
-#ifdef DYNAMICS_SUPPORT
-
-void UpdateManager::InitializeDynamicsWorld( SceneGraph::DynamicsWorld* dynamicsWorld, Integration::DynamicsWorldSettings* worldSettings )
+void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
{
- dynamicsWorld->Initialize( mImpl->sceneController, worldSettings, &mSceneGraphBuffers );
- mImpl->dynamicsWorld = dynamicsWorld;
+ mImpl->shaderSaver = &upstream;
}
-void UpdateManager::TerminateDynamicsWorld()
-{
- mImpl->dynamicsWorld.Reset();
-}
-
-#endif // DYNAMICS_SUPPORT
-
} // namespace SceneGraph
} // namespace Internal