transformManager(),
animationPlaylist( animationPlaylist ),
propertyNotifier( propertyNotifier ),
- shaderSaver( NULL ),
+ shaderSaver( nullptr ),
discardQueue( discardQueue ),
renderController( renderController ),
- sceneController( NULL ),
+ sceneController( nullptr ),
renderManager( renderManager ),
renderQueue( renderQueue ),
renderTaskProcessor( renderTaskProcessor ),
renderers(),
textureSets(),
shaders(),
- panGestureProcessor( NULL ),
+ panGestureProcessor( nullptr ),
messageQueue( renderController, sceneGraphBuffers ),
- frameCallbackProcessor( NULL ),
+ frameCallbackProcessor( nullptr ),
keepRenderingSeconds( 0.0f ),
nodeDirtyFlags( NodePropertyFlags::TRANSFORM ), // set to TransformFlag to ensure full update the first time through Update()
frameCounter( 0 ),
previousUpdateScene( false ),
renderTaskWaiting( false ),
renderersAdded( false ),
- surfaceRectChanged( false )
+ surfaceRectChanged( false ),
+ renderingRequired( false )
{
sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue );
// create first 'dummy' node
- nodes.PushBack(0u);
+ nodes.PushBack(nullptr);
}
~Impl()
RenderTaskList::RenderTaskContainer& tasks = scene->taskList->GetTasks();
for ( auto&& task : tasks )
{
- task->SetSourceNode( NULL );
+ task->SetSourceNode( nullptr );
}
}
}
bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
bool renderersAdded; ///< Flag to keep track when renderers have been added to avoid unnecessary processing
bool surfaceRectChanged; ///< True if the default surface rect is changed
+ bool renderingRequired; ///< True if required to render the current frame
private:
RenderManager& renderManager,
RenderQueue& renderQueue,
RenderTaskProcessor& renderTaskProcessor )
- : mImpl(NULL)
+ : mImpl(nullptr)
{
mImpl = new Impl( notificationManager,
animationFinishedNotifier,
void UpdateManager::AddNode( OwnerPointer<Node>& node )
{
- DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
+ DALI_ASSERT_ALWAYS( nullptr == node->GetParent() ); // Should not have a parent yet
// Nodes must be sorted by pointer
Node* rawNode = node.Release();
void UpdateManager::ConnectNode( Node* parent, Node* node )
{
- DALI_ASSERT_ALWAYS( NULL != parent );
- DALI_ASSERT_ALWAYS( NULL != node );
- DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
+ DALI_ASSERT_ALWAYS( nullptr != parent );
+ DALI_ASSERT_ALWAYS( nullptr != node );
+ DALI_ASSERT_ALWAYS( nullptr == node->GetParent() ); // Should not have a parent yet
DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] ConnectNode\n", node );
DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] DisconnectNode\n", node );
Node* parent = node->GetParent();
- DALI_ASSERT_ALWAYS( NULL != parent );
+ DALI_ASSERT_ALWAYS( nullptr != parent );
parent->SetDirtyFlag( NodePropertyFlags::CHILD_DELETED ); // make parent dirty so that render items dont get reused
parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node );
void UpdateManager::DestroyNode( Node* node )
{
- DALI_ASSERT_ALWAYS( NULL != node );
- DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
+ DALI_ASSERT_ALWAYS( nullptr != node );
+ DALI_ASSERT_ALWAYS( nullptr == node->GetParent() ); // Should have been disconnected
DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] DestroyNode\n", node );
return gestureUpdated;
}
-void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
+bool UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
{
+ bool animationActive = false;
+
auto&& iter = mImpl->animations.Begin();
bool animationLooped = false;
bool progressMarkerReached = false;
animation->Update( bufferIndex, elapsedSeconds, looped, finished, progressMarkerReached );
+ animationActive = animationActive || animation->IsActive();
+
if ( progressMarkerReached )
{
mImpl->notificationManager.QueueMessage( Internal::NotifyProgressReachedMessage( mImpl->animationPlaylist, animation ) );
// The application should be notified by NotificationManager, in another thread
mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationPlaylist );
}
+
+ return animationActive;
}
void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
//Apply constraints
ConstrainPropertyOwner( *renderer, bufferIndex );
- renderer->PrepareRender( bufferIndex );
+ mImpl->renderingRequired = renderer->PrepareRender( bufferIndex ) || mImpl->renderingRequired;
}
}
//Clear nodes/resources which were previously discarded
mImpl->discardQueue.Clear( bufferIndex );
+ bool isAnimationRunning = IsAnimationRunning();
+
//Process Touches & Gestures
const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
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
+ isAnimationRunning || // ..at least one animation is running OR
mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
+ mImpl->frameCallbackProcessor || // ..a frame callback processor is existed OR
gestureUpdated; // ..a gesture property was updated
bool keepRendererRendering = false;
+ mImpl->renderingRequired = false;
// 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 )
{
//Animate
- Animate( bufferIndex, elapsedSeconds );
+ bool animationActive = Animate( bufferIndex, elapsedSeconds );
//Constraint custom objects
ConstrainCustomObjects( bufferIndex );
UpdateRenderers( bufferIndex );
//Update the transformations of all the nodes
- mImpl->transformManager.Update();
+ if ( mImpl->transformManager.Update() )
+ {
+ mImpl->nodeDirtyFlags |= NodePropertyFlags::TRANSFORM;
+ }
//Process Property Notifications
ProcessPropertyNotifications( bufferIndex );
}
}
-
std::size_t numberOfRenderInstructions = 0;
for ( auto&& scene : mImpl->scenes )
{
scene->scene->GetRenderInstructions().ResetAndReserve( bufferIndex,
static_cast<uint32_t>( scene->taskList->GetTasks().Count() ) );
- keepRendererRendering |= mImpl->renderTaskProcessor.Process( bufferIndex,
- *scene->taskList,
- *scene->root,
- scene->sortedLayerList,
- scene->scene->GetRenderInstructions(),
- renderToFboEnabled,
- isRenderingToFbo );
+ // If there are animations running, only add render instruction if at least one animation is currently active (i.e. not delayed)
+ // or the nodes are dirty
+ if ( !isAnimationRunning || animationActive || mImpl->renderingRequired || (mImpl->nodeDirtyFlags & RenderableUpdateFlags) )
+ {
+ keepRendererRendering |= mImpl->renderTaskProcessor.Process( bufferIndex,
+ *scene->taskList,
+ *scene->root,
+ scene->sortedLayerList,
+ scene->scene->GetRenderInstructions(),
+ renderToFboEnabled,
+ isRenderingToFbo );
+
+ }
numberOfRenderInstructions += scene->scene->GetRenderInstructions().Count( bufferIndex );
}
mImpl->renderingBehavior = renderingBehavior;
}
+void UpdateManager::RequestRendering()
+{
+ mImpl->renderingRequired = true;
+}
+
void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, const Layer* rootLayer )
{
for ( auto&& scene : mImpl->scenes )