From 351157fba6c189ed1a8c25a30feba77874950ed8 Mon Sep 17 00:00:00 2001 From: Adeel Kazmi Date: Wed, 19 Jun 2019 17:06:43 +0100 Subject: [PATCH] Ensure we render once more when we remove all renderers from the scene Change-Id: I3d67c6ceee6bcf4424c8cb3c2fcf3452f82f07e0 --- automated-tests/src/dali/utc-Dali-Actor.cpp | 29 ++++++++++++++++++- dali/internal/render/common/render-manager.cpp | 15 ++++++++++ dali/internal/update/manager/update-manager.cpp | 37 +++++++++++++++++++++++-- 3 files changed, 78 insertions(+), 3 deletions(-) diff --git a/automated-tests/src/dali/utc-Dali-Actor.cpp b/automated-tests/src/dali/utc-Dali-Actor.cpp index fad466a..b8c7e95 100644 --- a/automated-tests/src/dali/utc-Dali-Actor.cpp +++ b/automated-tests/src/dali/utc-Dali-Actor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2019 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. @@ -7172,3 +7172,30 @@ int utcDaliActorCulled(void) END_TEST; } + +int utcDaliEnsureRenderWhenRemovingLastRenderableActor(void) +{ + TestApplication application; + auto stage = Stage::GetCurrent(); + + tet_infoline( "Ensure we clear the screen when the last actor is removed" ); + + Actor actor = CreateRenderableActor(); + actor.SetSize( 100.0f, 100.0f ); + stage.Add( actor ); + + application.SendNotification(); + application.Render(); + + auto& glAbstraction = application.GetGlAbstraction(); + const auto clearCountBefore = glAbstraction.GetClearCountCalled(); + + actor.Unparent(); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( glAbstraction.GetClearCountCalled(), clearCountBefore + 1, TEST_LOCATION ); + + END_TEST; +} diff --git a/dali/internal/render/common/render-manager.cpp b/dali/internal/render/common/render-manager.cpp index ee70d89..2d550b5 100644 --- a/dali/internal/render/common/render-manager.cpp +++ b/dali/internal/render/common/render-manager.cpp @@ -50,6 +50,13 @@ namespace Internal namespace SceneGraph { +#if defined(DEBUG_ENABLED) +namespace +{ +Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RENDER_MANAGER" ); +} // unnamed namespace +#endif + /** * Structure to contain internal data */ @@ -451,9 +458,17 @@ void RenderManager::Render( Integration::RenderStatus& status, bool forceClear ) const uint32_t count = mImpl->instructions.Count( mImpl->renderBufferIndex ); const bool haveInstructions = count > 0u; + DALI_LOG_INFO( gLogFilter, Debug::General, + "Render: haveInstructions(%s) || mImpl->lastFrameWasRendered(%s) || forceClear(%s)\n", + haveInstructions ? "true" : "false", + mImpl->lastFrameWasRendered ? "true" : "false", + forceClear ? "true" : "false" ); + // Only render if we have instructions to render, or the last frame was rendered (and therefore a clear is required). if( haveInstructions || mImpl->lastFrameWasRendered || forceClear ) { + DALI_LOG_INFO( gLogFilter, Debug::General, "Render: Processing\n" ); + // Mark that we will require a post-render step to be performed (includes swap-buffers). status.SetNeedsPostRender( true ); diff --git a/dali/internal/update/manager/update-manager.cpp b/dali/internal/update/manager/update-manager.cpp index 9fd71a1..e98f8b7 100644 --- a/dali/internal/update/manager/update-manager.cpp +++ b/dali/internal/update/manager/update-manager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2019 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. @@ -87,6 +87,10 @@ mImpl->frameCounter++; #if defined(DEBUG_ENABLED) extern Debug::Filter* gRenderTaskLogFilter; +namespace +{ +Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_UPDATE_MANAGER" ); +} // unnamed namespace #endif @@ -189,7 +193,8 @@ struct UpdateManager::Impl previousUpdateScene( false ), renderTaskWaiting( false ), renderersAdded( false ), - surfaceRectChanged( false ) + surfaceRectChanged( false ), + nodeDisconnected( false ) { sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue ); @@ -295,6 +300,7 @@ struct UpdateManager::Impl 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 nodeDisconnected; ///< True if a node is disconnected in the current update private: @@ -369,6 +375,8 @@ void UpdateManager::AddNode( OwnerPointer& node ) // Nodes must be sorted by pointer Node* rawNode = node.Release(); + DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] AddNode\n", rawNode ); + Vector::Iterator begin = mImpl->nodes.Begin(); for( Vector::Iterator iter = mImpl->nodes.End()-1; iter >= begin; --iter ) { @@ -387,6 +395,8 @@ void UpdateManager::ConnectNode( Node* parent, Node* node ) DALI_ASSERT_ALWAYS( NULL != node ); DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet + DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] ConnectNode\n", node ); + parent->ConnectChild( node ); // Inform the frame-callback-processor, if set, about the node-hierarchy changing @@ -398,6 +408,10 @@ void UpdateManager::ConnectNode( Node* parent, Node* node ) void UpdateManager::DisconnectNode( Node* node ) { + DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] DisconnectNode\n", node ); + + mImpl->nodeDisconnected = true; + Node* parent = node->GetParent(); DALI_ASSERT_ALWAYS( NULL != parent ); parent->SetDirtyFlag( NodePropertyFlags::CHILD_DELETED ); // make parent dirty so that render items dont get reused @@ -416,6 +430,8 @@ void UpdateManager::DestroyNode( Node* node ) DALI_ASSERT_ALWAYS( NULL != node ); DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected + DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] DestroyNode\n", node ); + Vector::Iterator iter = mImpl->nodes.Begin()+1; Vector::Iterator endIter = mImpl->nodes.End(); for(;iter!=endIter;++iter) @@ -573,6 +589,8 @@ void UpdateManager::SetShaderSaver( ShaderSaver& upstream ) void UpdateManager::AddRenderer( OwnerPointer< Renderer >& renderer ) { + DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] AddRenderer\n", renderer.Get() ); + renderer->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() ); mImpl->renderers.PushBack( renderer.Release() ); mImpl->renderersAdded = true; @@ -580,6 +598,8 @@ void UpdateManager::AddRenderer( OwnerPointer< Renderer >& renderer ) void UpdateManager::RemoveRenderer( Renderer* renderer ) { + DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] RemoveRenderer\n", renderer ); + // Find the renderer and destroy it EraseUsingDiscardQueue( mImpl->renderers, renderer, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() ); // Need to remove the render object as well @@ -913,6 +933,19 @@ uint32_t UpdateManager::Update( float elapsedSeconds, isRenderingToFbo ); } } + + DALI_LOG_INFO( gLogFilter, Debug::General, + "Update: numberOfRenderTasks(%d), taskListCount(%d), Render Instructions(%d)\n", + numberOfRenderTasks, taskListCount, mImpl->renderInstructions.Count( bufferIndex ) ); + + // If a node has been disconnected in this update and we do not have any instructions to send, then generate a dummy instruction to force another render + if( mImpl->nodeDisconnected && ( mImpl->renderInstructions.Count( bufferIndex ) == 0 ) ) + { + DALI_LOG_INFO( gLogFilter, Debug::General, "Node disconnected, creating dummy instruction\n" ); + mImpl->renderInstructions.GetNextInstruction( bufferIndex ); // This creates and adds an empty instruction. We do not need to modify it. + } + + mImpl->nodeDisconnected = false; } } -- 2.7.4