Added new mechanism to order actor depths 74/126474/7
authorDavid Steele <david.steele@samsung.com>
Mon, 10 Apr 2017 18:38:01 +0000 (19:38 +0100)
committerDavid Steele <david.steele@samsung.com>
Tue, 2 May 2017 16:40:51 +0000 (16:40 +0000)
At the end of each frame, if the actor tree was changed, or the
sibling order of any actor was modified, then the actor tree is
traversed to determine the new depth orders.

Currently, the depth order is written back to each actor's mSortedDepth,
and the nodes are updated with a single message containing the nodes
in depth order. (Could be used in a future patch to reduce renderer sorting)

Created a memory pool for managing the lifetime of the depth nodes that
exists for the lifetime of the application.

Change-Id: Iaed004eb8dc790fcc0f6f1b4822037054193b552

13 files changed:
automated-tests/src/dali-internal/CMakeLists.txt
automated-tests/src/dali-internal/utc-Dali-Internal-ActorDepth.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Actor.cpp
automated-tests/src/dali/utc-Dali-Renderer.cpp
dali/integration-api/debug.cpp
dali/integration-api/debug.h
dali/internal/common/core-impl.cpp
dali/internal/event/actors/actor-impl.cpp
dali/internal/event/actors/actor-impl.h
dali/internal/event/common/stage-impl.cpp
dali/internal/event/common/stage-impl.h
dali/internal/update/manager/update-manager.cpp
dali/internal/update/manager/update-manager.h

index d4a459f..56ae01c 100644 (file)
@@ -11,6 +11,7 @@ SET(TC_SOURCES
         utc-Dali-Internal-FixedSizeMemoryPool.cpp
         utc-Dali-Internal-MemoryPoolObjectAllocator.cpp
         utc-Dali-Internal-FrustumCulling.cpp
+        utc-Dali-Internal-ActorDepth.cpp
 )
 
 LIST(APPEND TC_SOURCES
diff --git a/automated-tests/src/dali-internal/utc-Dali-Internal-ActorDepth.cpp b/automated-tests/src/dali-internal/utc-Dali-Internal-ActorDepth.cpp
new file mode 100644 (file)
index 0000000..f5a9482
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2017 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+
+#include <dali-test-suite-utils.h>
+#include <dali/devel-api/actors/actor-devel.h>
+
+// Internal headers are allowed here
+#define protected public
+#include <dali/internal/event/actors/actor-impl.h>
+
+using namespace Dali;
+
+void utc_dali_internal_actor_depth_startup()
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_internal_actor_depth_cleanup()
+{
+  test_return_value = TET_PASS;
+}
+
+Actor CreateActor( Actor parent, int siblingOrder, const char* name )
+{
+  Actor actor = Actor::New();
+  actor.SetProperty( DevelActor::Property::SIBLING_ORDER, siblingOrder);
+  actor.SetName( name );
+  parent.Add(actor);
+  return actor;
+}
+
+void PrintActor(Dali::Actor a, int depth)
+{
+  int siblingOrder;
+  Dali::Property::Value v = a.GetProperty( Dali::DevelActor::Property::SIBLING_ORDER );
+  v.Get(siblingOrder);
+
+  Dali::Internal::Actor& actorImpl = GetImplementation(a);
+  for( int i=0; i<depth; ++i)
+    std::cout << "  ";
+  std::cout << "Actor: " << a.GetName() << "(" << a.GetId() << ") siblingOrder: " <<
+    siblingOrder << " depthOrder: " << actorImpl.GetSortingDepth() << std::endl;
+}
+
+void PrintActorTree( Dali::Actor a, int depth )
+{
+  PrintActor( a, depth );
+  for( unsigned int i=0; i<a.GetChildCount(); ++i )
+  {
+    PrintActorTree( a.GetChildAt(i), depth+1 );
+  }
+}
+
+void PrintNode( Dali::Internal::ActorDepthTreeNode& node, int depth )
+{
+  for( int i=0; i<depth; ++i)
+    std::cout << "  ";
+  std::cout << "Node: " << &node << "  siblingOrder:" << node.mSiblingOrder << " Actors:";
+  for( std::vector<Internal::Actor*>::iterator iter = node.mActors.begin() ;
+       iter != node.mActors.end(); ++iter )
+  {
+    std::cout << (*iter)->GetName() << ", ";
+  }
+  std::cout << std::endl;
+
+  if( node.mFirstChildNode )
+    PrintNode( *node.mFirstChildNode, depth+1);
+
+  if( node.mNextSiblingNode )
+  {
+    PrintNode( *node.mNextSiblingNode, depth );
+  }
+}
+
+void CheckNodeForActor( Dali::Internal::ActorDepthTreeNode*node, Actor actor, const char* loc )
+{
+  bool found = false;
+  Dali::Internal::Actor& actorImpl = Dali::GetImplementation(actor);
+
+  for( std::vector<Internal::Actor*>::iterator iter = node->mActors.begin(); iter != node->mActors.end(); ++iter )
+  {
+    if( *iter == &actorImpl )
+    {
+      found = true;
+      break;
+    }
+  }
+  DALI_TEST_EQUALS( found, true, loc );
+}
+
+unsigned int GetActorCount( Dali::Internal::ActorDepthTreeNode*node )
+{
+  unsigned int size = node->mActors.size();
+
+  for( Dali::Internal::ActorDepthTreeNode* childNode = node->mFirstChildNode;
+       childNode != NULL;
+       childNode = childNode->mNextSiblingNode )
+  {
+    size += GetActorCount( childNode );
+  }
+
+  return size;
+}
+
+int UtcDaliActorDepthTreeTest01(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Actor tree depth");
+
+  Stage stage = Stage::GetCurrent();
+
+  Actor Root = CreateActor(stage.GetRootLayer(), 0, "ROOT" );
+  Actor A = CreateActor( Root, 0, "A");
+  Actor B = CreateActor( Root, 2, "B");
+  Actor C = CreateActor( Root, 0, "C");
+  Actor D = CreateActor( Root, 1, "D");
+
+  Actor E = CreateActor(A, 0, "E");
+  Actor F = CreateActor(A, 2, "F");
+  Actor G = CreateActor(A, 1, "G");
+
+  Actor H = CreateActor(B, 2, "H");
+  Actor I = CreateActor(B, 1, "I");
+  Actor J = CreateActor(B, 0, "J");
+
+  Actor K = CreateActor(C, 1, "K");
+  Actor L = CreateActor(C, 2, "L");
+  Actor M = CreateActor(C, 0, "M");
+
+  Actor N = CreateActor(D, 2, "N");
+  Actor O = CreateActor(D, 2, "O");
+  Actor P = CreateActor(D, 1, "P");
+
+  PrintActorTree( Root, 0 );
+
+  Internal::Actor& rootLayerImpl = GetImplementation(Root);
+
+  Internal::DepthNodeMemoryPool nodeMemoryPool;
+  Internal::ActorDepthTreeNode* rootNode = new (nodeMemoryPool.AllocateRaw()) Internal::ActorDepthTreeNode( &rootLayerImpl, 0 );
+  rootLayerImpl.BuildDepthTree( nodeMemoryPool, rootNode ) ;
+
+  int depth=0;
+  PrintNode( *rootNode, depth );
+
+  // Check that first child node contains actors A and C
+  // check that first grand child node contains actors E, M
+  // check that it's sibling node contains actors G, K
+  // check that it's sibling node contains actors F, L
+  // Check that tree only contains 16 actors.
+  CheckNodeForActor( rootNode->mFirstChildNode, A, TEST_LOCATION );
+  CheckNodeForActor( rootNode->mFirstChildNode, C, TEST_LOCATION );
+  CheckNodeForActor( rootNode->mFirstChildNode->mFirstChildNode, E, TEST_LOCATION );
+  CheckNodeForActor( rootNode->mFirstChildNode->mFirstChildNode, M, TEST_LOCATION );
+  CheckNodeForActor( rootNode->mFirstChildNode->mFirstChildNode->mNextSiblingNode, G, TEST_LOCATION );
+  CheckNodeForActor( rootNode->mFirstChildNode->mFirstChildNode->mNextSiblingNode, K, TEST_LOCATION );
+  CheckNodeForActor( rootNode->mFirstChildNode->mFirstChildNode->mNextSiblingNode->mNextSiblingNode, F, TEST_LOCATION );
+  CheckNodeForActor( rootNode->mFirstChildNode->mFirstChildNode->mNextSiblingNode->mNextSiblingNode, L, TEST_LOCATION );
+  CheckNodeForActor( rootNode->mFirstChildNode->mNextSiblingNode->mNextSiblingNode, B, TEST_LOCATION );
+
+  unsigned int actorCount = GetActorCount( rootNode );
+  DALI_TEST_EQUALS( actorCount, 17, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+
+int UtcDaliActorDepthTreeTest02(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Actor tree depth");
+
+  Stage stage = Stage::GetCurrent();
+
+  Actor Root = CreateActor(stage.GetRootLayer(), 0, "ROOT" );
+  Actor A = CreateActor( Root, 0, "A");
+  Actor B = CreateActor( Root, 0, "B");
+  Actor C = CreateActor( Root, 0, "C");
+  Actor D = CreateActor( Root, 0, "D");
+
+  Actor E = CreateActor(A, 0, "E");
+  Actor F = CreateActor(A, 0, "F");
+  Actor G = CreateActor(A, 0, "G");
+
+  Actor H = CreateActor(B, 0, "H");
+  Actor I = CreateActor(B, 0, "I");
+  Actor J = CreateActor(B, 0, "J");
+
+  Actor K = CreateActor(C, 0, "K");
+  Actor L = CreateActor(C, 0, "L");
+  Actor M = CreateActor(C, 0, "M");
+
+  Actor N = CreateActor(D, 0, "N");
+  Actor O = CreateActor(D, 0, "O");
+  Actor P = CreateActor(D, 0, "P");
+
+  PrintActorTree( Root, 0 );
+
+  Internal::Actor& rootLayerImpl = GetImplementation(Root);
+
+  Internal::DepthNodeMemoryPool nodeMemoryPool;
+  Internal::ActorDepthTreeNode* rootNode = new (nodeMemoryPool.AllocateRaw()) Internal::ActorDepthTreeNode( &rootLayerImpl, 0 );
+  rootLayerImpl.BuildDepthTree( nodeMemoryPool, rootNode ) ;
+
+  int depth=0;
+  PrintNode( *rootNode, depth );
+
+  CheckNodeForActor( rootNode->mFirstChildNode, A, TEST_LOCATION );
+  CheckNodeForActor( rootNode->mFirstChildNode, C, TEST_LOCATION );
+  CheckNodeForActor( rootNode->mFirstChildNode->mFirstChildNode, E, TEST_LOCATION );
+  CheckNodeForActor( rootNode->mFirstChildNode->mFirstChildNode, M, TEST_LOCATION );
+  CheckNodeForActor( rootNode->mFirstChildNode->mFirstChildNode, G, TEST_LOCATION );
+  CheckNodeForActor( rootNode->mFirstChildNode->mFirstChildNode, K, TEST_LOCATION );
+  CheckNodeForActor( rootNode->mFirstChildNode->mFirstChildNode, F, TEST_LOCATION );
+  CheckNodeForActor( rootNode->mFirstChildNode->mFirstChildNode, L, TEST_LOCATION );
+  CheckNodeForActor( rootNode->mFirstChildNode, B, TEST_LOCATION );
+
+  unsigned int actorCount = GetActorCount( rootNode );
+  DALI_TEST_EQUALS( actorCount, 17, TEST_LOCATION );
+
+  END_TEST;
+}
index 2381786..9a41831 100644 (file)
@@ -2483,9 +2483,9 @@ int UtcDaliActorTouchedSignal(void)
   point.SetDeviceId( 1 );
   point.SetState( PointState::DOWN );
   point.SetScreenPosition( Vector2( touchPoint.x, touchPoint.y ) );
-  Dali::Integration::TouchEvent event;
-  event.AddPoint( point );
-  application.ProcessEvent( event );
+  Dali::Integration::TouchEvent touchEvent;
+  touchEvent.AddPoint( point );
+  application.ProcessEvent( touchEvent );
 
   DALI_TEST_CHECK( gTouchCallBackCalled == true );
   END_TEST;
@@ -2513,9 +2513,9 @@ int UtcDaliActorHoveredSignal(void)
   point.SetDeviceId( 1 );
   point.SetState( PointState::MOTION );
   point.SetScreenPosition( Vector2( touchPoint.x, touchPoint.y ) );
-  Dali::Integration::HoverEvent event;
-  event.AddPoint( point );
-  application.ProcessEvent( event );
+  Dali::Integration::HoverEvent hoverEvent;
+  hoverEvent.AddPoint( point );
+  application.ProcessEvent( hoverEvent );
 
   DALI_TEST_CHECK( gHoverCallBackCalled == true );
   END_TEST;
@@ -4297,10 +4297,10 @@ int UtcDaliActorRaiseLower(void)
   point.SetDeviceId( 1 );
   point.SetState( PointState::DOWN );
   point.SetScreenPosition( Vector2( 10.f, 10.f ) );
-  Dali::Integration::TouchEvent event;
-  event.AddPoint( point );
+  Dali::Integration::TouchEvent touchEvent;
+  touchEvent.AddPoint( point );
 
-  application.ProcessEvent( event );
+  application.ProcessEvent( touchEvent );
 
   DALI_TEST_EQUALS( gTouchCallBackCalled,  false, TEST_LOCATION );
   DALI_TEST_EQUALS( gTouchCallBackCalled2,  false, TEST_LOCATION );
@@ -4317,13 +4317,15 @@ int UtcDaliActorRaiseLower(void)
   value.Get( preActorOrder );
 
   DevelActor::Raise( actorB );
+  // Ensure sort order is calculated before next touch event
+  application.SendNotification();
 
   value  = actorB.GetProperty(Dali::DevelActor::Property::SIBLING_ORDER );
   value.Get( postActorOrder );
 
   tet_printf( "Raised ActorB from (%d) to (%d) \n", preActorOrder, postActorOrder );
 
-  application.ProcessEvent( event );
+  application.ProcessEvent( touchEvent );
 
   DALI_TEST_EQUALS( gTouchCallBackCalled,  false, TEST_LOCATION );
   DALI_TEST_EQUALS( gTouchCallBackCalled2,  true , TEST_LOCATION );
@@ -4337,13 +4339,14 @@ int UtcDaliActorRaiseLower(void)
   value.Get( preActorOrder );
 
   DevelActor::Lower( actorB );
+  application.SendNotification(); // ensure sort order calculated before next touch event
 
   value  = actorB.GetProperty(Dali::DevelActor::Property::SIBLING_ORDER );
   value.Get( postActorOrder );
 
   tet_printf( "Lowered ActorB from (%d) to (%d) \n", preActorOrder, postActorOrder );
 
-  application.ProcessEvent( event );
+  application.ProcessEvent( touchEvent );
 
   DALI_TEST_EQUALS( gTouchCallBackCalled,  false, TEST_LOCATION );
   DALI_TEST_EQUALS( gTouchCallBackCalled2,  false , TEST_LOCATION );
@@ -4449,10 +4452,10 @@ int UtcDaliActorRaiseToTopLowerToBottom(void)
   point.SetDeviceId( 1 );
   point.SetState( PointState::DOWN );
   point.SetScreenPosition( Vector2( 10.f, 10.f ) );
-  Dali::Integration::TouchEvent event;
-  event.AddPoint( point );
+  Dali::Integration::TouchEvent touchEvent;
+  touchEvent.AddPoint( point );
 
-  application.ProcessEvent( event );
+  application.ProcessEvent( touchEvent );
 
   DALI_TEST_EQUALS( gTouchCallBackCalled,  false, TEST_LOCATION );
   DALI_TEST_EQUALS( gTouchCallBackCalled2,  false, TEST_LOCATION );
@@ -4463,8 +4466,9 @@ int UtcDaliActorRaiseToTopLowerToBottom(void)
   tet_printf( "RaiseToTop ActorA\n" );
 
   DevelActor::RaiseToTop( actorA );
+  application.SendNotification(); // ensure sorting order is calculated before next touch event
 
-  application.ProcessEvent( event );
+  application.ProcessEvent( touchEvent );
 
   glAbstraction.ResetSetUniformCallStack();
   glSetUniformStack = glAbstraction.GetSetUniformTrace();
@@ -4493,8 +4497,9 @@ int UtcDaliActorRaiseToTopLowerToBottom(void)
   tet_printf( "RaiseToTop ActorB\n" );
 
   DevelActor::RaiseToTop( actorB );
+  application.SendNotification(); // Ensure sort order is calculated before next touch event
 
-  application.ProcessEvent( event );
+  application.ProcessEvent( touchEvent );
 
   glAbstraction.ResetSetUniformCallStack();
   glSetUniformStack = glAbstraction.GetSetUniformTrace();
@@ -4530,7 +4535,7 @@ int UtcDaliActorRaiseToTopLowerToBottom(void)
   application.SendNotification();
   application.Render();
 
-  application.ProcessEvent( event );
+  application.ProcessEvent( touchEvent );
 
   glAbstraction.ResetSetUniformCallStack();
   glSetUniformStack = glAbstraction.GetSetUniformTrace();
@@ -4612,10 +4617,10 @@ int UtcDaliActorRaiseAbove(void)
   point.SetDeviceId( 1 );
   point.SetState( PointState::DOWN );
   point.SetScreenPosition( Vector2( 10.f, 10.f ) );
-  Dali::Integration::TouchEvent event;
-  event.AddPoint( point );
+  Dali::Integration::TouchEvent touchEvent;
+  touchEvent.AddPoint( point );
 
-  application.ProcessEvent( event );
+  application.ProcessEvent( touchEvent );
 
   DALI_TEST_EQUALS( gTouchCallBackCalled,  false, TEST_LOCATION );
   DALI_TEST_EQUALS( gTouchCallBackCalled2,  false, TEST_LOCATION );
@@ -4626,8 +4631,10 @@ int UtcDaliActorRaiseAbove(void)
   tet_printf( "Raise actor B Above Actor C\n" );
 
   DevelActor::RaiseAbove( actorB, actorC );
+  // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+  application.SendNotification();
 
-  application.ProcessEvent( event );
+  application.ProcessEvent( touchEvent );
 
   DALI_TEST_EQUALS( gTouchCallBackCalled,  false, TEST_LOCATION );
   DALI_TEST_EQUALS( gTouchCallBackCalled2,  true, TEST_LOCATION );
@@ -4639,7 +4646,10 @@ int UtcDaliActorRaiseAbove(void)
 
   DevelActor::RaiseAbove( actorA, actorB );
 
-  application.ProcessEvent( event );
+  // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+  application.SendNotification();
+
+  application.ProcessEvent( touchEvent ); // process a touch event on ordered actors.
 
   DALI_TEST_EQUALS( gTouchCallBackCalled,  true, TEST_LOCATION );
   DALI_TEST_EQUALS( gTouchCallBackCalled2,  false, TEST_LOCATION );
@@ -4748,12 +4758,12 @@ int UtcDaliActorLowerBelow(void)
   point.SetDeviceId( 1 );
   point.SetState( PointState::DOWN );
   point.SetScreenPosition( Vector2( 10.f, 10.f ) );
-  Dali::Integration::TouchEvent event;
-  event.AddPoint( point );
+  Dali::Integration::TouchEvent touchEvent;
+  touchEvent.AddPoint( point );
 
   tet_infoline( "UtcDaliActor Test Set up completed \n" );
 
-  application.ProcessEvent( event );
+  application.ProcessEvent( touchEvent );
 
   DALI_TEST_EQUALS( gTouchCallBackCalled, false, TEST_LOCATION );
   DALI_TEST_EQUALS( gTouchCallBackCalled2, false, TEST_LOCATION );
@@ -4764,11 +4774,11 @@ int UtcDaliActorLowerBelow(void)
   tet_printf( "Lower actor C below Actor B ( actor B and A on same level due to insertion order) so C is below both \n" );
 
   DevelActor::LowerBelow( actorC, actorB );
-
+  // Ensure sorting happens at end of Core::ProcessEvents() before next touch
   application.SendNotification();
   application.Render();
 
-  application.ProcessEvent( event );
+  application.ProcessEvent( touchEvent ); // touch event
 
   glAbstraction.ResetSetUniformCallStack();
   glSetUniformStack = glAbstraction.GetSetUniformTrace();
@@ -4797,11 +4807,11 @@ int UtcDaliActorLowerBelow(void)
   tet_printf( "Lower actor B below Actor C leaving A on top\n" );
 
   DevelActor::LowerBelow( actorB, actorC );
-
+  // Ensure sorting happens at end of Core::ProcessEvents() before next touch
   application.SendNotification();
   application.Render();
 
-  application.ProcessEvent( event );
+  application.ProcessEvent( touchEvent );
 
   glAbstraction.ResetSetUniformCallStack();
   glSetUniformStack = glAbstraction.GetSetUniformTrace();
@@ -4827,11 +4837,11 @@ int UtcDaliActorLowerBelow(void)
   tet_printf( "Lower actor A below Actor C leaving C on top\n" );
 
   DevelActor::LowerBelow( actorA, actorC );
-
+  // Ensure sorting happens at end of Core::ProcessEvents() before next touch
   application.SendNotification();
   application.Render();
 
-  application.ProcessEvent( event );
+  application.ProcessEvent( touchEvent );
 
   glAbstraction.ResetSetUniformCallStack();
   glSetUniformStack = glAbstraction.GetSetUniformTrace();
@@ -4888,6 +4898,7 @@ int UtcDaliActorMaxSiblingOrder(void)
   Actor sibling = parent.GetChildAt( 5 );
   DevelActor::RaiseToTop( sibling );
 
+  // Ensure sorting happens at end of Core::ProcessEvents()
   application.SendNotification();
   application.Render();
 
@@ -4978,10 +4989,10 @@ int UtcDaliActorRaiseAboveLowerBelowDifferentParentsN(void)
   point.SetDeviceId( 1 );
   point.SetState( PointState::DOWN );
   point.SetScreenPosition( Vector2( 10.f, 10.f ) );
-  Dali::Integration::TouchEvent event;
-  event.AddPoint( point );
+  Dali::Integration::TouchEvent touchEvent;
+  touchEvent.AddPoint( point );
 
-  application.ProcessEvent( event );
+  application.ProcessEvent( touchEvent );
 
   DALI_TEST_EQUALS( gTouchCallBackCalled,  false, TEST_LOCATION );
   DALI_TEST_EQUALS( gTouchCallBackCalled2, false, TEST_LOCATION );
@@ -4992,8 +5003,10 @@ int UtcDaliActorRaiseAboveLowerBelowDifferentParentsN(void)
   tet_printf( "Raise actor A Above Actor C which have different parents\n" );
 
   DevelActor::RaiseAbove( actorA, actorC );
+  // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+  application.SendNotification();
 
-  application.ProcessEvent( event );
+  application.ProcessEvent( touchEvent ); // touch event
 
   DALI_TEST_EQUALS( gTouchCallBackCalled,  false, TEST_LOCATION );
   DALI_TEST_EQUALS( gTouchCallBackCalled2,  false, TEST_LOCATION );
@@ -5053,14 +5066,16 @@ int UtcDaliActorRaiseLowerWhenUnparentedTargetN(void)
   point.SetDeviceId( 1 );
   point.SetState( PointState::DOWN );
   point.SetScreenPosition( Vector2( 10.f, 10.f ) );
-  Dali::Integration::TouchEvent event;
-  event.AddPoint( point );
+  Dali::Integration::TouchEvent touchEvent;
+  touchEvent.AddPoint( point );
 
   tet_printf( "Raise actor A Above Actor C which have no parents\n" );
 
   DevelActor::RaiseAbove( actorA, actorC );
+  // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+  application.SendNotification();
 
-  application.ProcessEvent( event );
+  application.ProcessEvent( touchEvent );
 
   tet_printf( "Not parented so RaiseAbove should show no effect\n" );
 
@@ -5071,13 +5086,14 @@ int UtcDaliActorRaiseLowerWhenUnparentedTargetN(void)
   ResetTouchCallbacks();
 
   stage.Add ( actorB );
+  tet_printf( "Lower actor A below Actor C when only A is not on stage \n" );
+  DevelActor::LowerBelow( actorA, actorC );
 
+  // Ensure sorting happens at end of Core::ProcessEvents() before next touch
   application.SendNotification();
   application.Render();
 
-  tet_printf( "Lower actor A below Actor C when only A is not on stage \n" );
-  DevelActor::LowerBelow( actorA, actorC );
-  application.ProcessEvent( event );
+  application.ProcessEvent( touchEvent );
 
   tet_printf( "Actor A not parented so LowerBelow should show no effect\n" );
   DALI_TEST_EQUALS( gTouchCallBackCalled,  false, TEST_LOCATION );
@@ -5094,7 +5110,10 @@ int UtcDaliActorRaiseLowerWhenUnparentedTargetN(void)
 
   tet_printf( "Raise actor B Above Actor C when only B has a parent\n" );
   DevelActor::RaiseAbove( actorB, actorC );
-  application.ProcessEvent( event );
+  // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+  application.SendNotification();
+
+  application.ProcessEvent( touchEvent );
 
   tet_printf( "C not parented so RaiseAbove should show no effect\n" );
   DALI_TEST_EQUALS( gTouchCallBackCalled,  true, TEST_LOCATION );
@@ -5105,7 +5124,10 @@ int UtcDaliActorRaiseLowerWhenUnparentedTargetN(void)
 
   tet_printf( "Lower actor A below Actor C when only A has a parent\n" );
   DevelActor::LowerBelow( actorA, actorC );
-  application.ProcessEvent( event );
+  // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+  application.SendNotification();
+
+  application.ProcessEvent( touchEvent );
 
   tet_printf( "C not parented so LowerBelow should show no effect\n" );
   DALI_TEST_EQUALS( gTouchCallBackCalled,  true, TEST_LOCATION );
@@ -5115,12 +5137,12 @@ int UtcDaliActorRaiseLowerWhenUnparentedTargetN(void)
   ResetTouchCallbacks();
 
   stage.Add ( actorC );
-
+  DevelActor::RaiseAbove( actorA, actorC );
+  // Ensure sorting happens at end of Core::ProcessEvents() before next touch
   application.SendNotification();
   application.Render();
 
-  DevelActor::RaiseAbove( actorA, actorC );
-  application.ProcessEvent( event );
+  application.ProcessEvent( touchEvent );
 
   tet_printf( "Raise actor A Above Actor C, now both have same parent \n" );
   DALI_TEST_EQUALS( gTouchCallBackCalled,  true, TEST_LOCATION );
@@ -5172,19 +5194,17 @@ int UtcDaliActorTestAllAPIwhenActorNotParented(void)
   point.SetDeviceId( 1 );
   point.SetState( PointState::DOWN );
   point.SetScreenPosition( Vector2( 10.f, 10.f ) );
-  Dali::Integration::TouchEvent event;
-  event.AddPoint( point );
+  Dali::Integration::TouchEvent touchEvent;
+  touchEvent.AddPoint( point );
 
   stage.Add ( actorA );
+  tet_printf( "Raise actor B Above Actor C but B not parented\n" );
+  DevelActor::Raise( actorB );
 
   application.SendNotification();
   application.Render();
 
-  tet_printf( "Raise actor B Above Actor C but B not parented\n" );
-
-  DevelActor::Raise( actorB );
-
-  application.ProcessEvent( event );
+  application.ProcessEvent( touchEvent );
 
   tet_printf( "Not parented so RaiseAbove should show no effect\n" );
 
@@ -5196,8 +5216,11 @@ int UtcDaliActorTestAllAPIwhenActorNotParented(void)
   ResetTouchCallbacks();
 
   DevelActor::Lower( actorC );
+  // Sort actor tree before next touch event
+  application.SendNotification();
+  application.Render();
 
-  application.ProcessEvent( event );
+  application.ProcessEvent( touchEvent );
 
   tet_printf( "Not parented so RaiseAbove should show no effect\n" );
 
@@ -5209,8 +5232,11 @@ int UtcDaliActorTestAllAPIwhenActorNotParented(void)
   tet_printf( "Lower actor C below B but C not parented\n" );
 
   DevelActor::Lower( actorB );
+  // Sort actor tree before next touch event
+  application.SendNotification();
+  application.Render();
 
-  application.ProcessEvent( event );
+  application.ProcessEvent( touchEvent );
 
   tet_printf( "Not parented so Lower should show no effect\n" );
 
@@ -5222,8 +5248,11 @@ int UtcDaliActorTestAllAPIwhenActorNotParented(void)
   tet_printf( "Raise actor B to top\n" );
 
   DevelActor::RaiseToTop( actorB );
+  // Sort actor tree before next touch event
+  application.SendNotification();
+  application.Render();
 
-  application.ProcessEvent( event );
+  application.ProcessEvent( touchEvent );
 
   tet_printf( "Not parented so RaiseToTop should show no effect\n" );
 
@@ -5236,14 +5265,13 @@ int UtcDaliActorTestAllAPIwhenActorNotParented(void)
 
   stage.Add ( actorB );
 
-  application.SendNotification();
-  application.Render();
-
   tet_printf( "Lower actor C to Bottom, B stays at top\n" );
 
   DevelActor::LowerToBottom( actorC );
+  application.SendNotification();
+  application.Render();
 
-  application.ProcessEvent( event );
+  application.ProcessEvent( touchEvent );
 
   tet_printf( "Not parented so LowerToBottom should show no effect\n" );
 
@@ -5305,10 +5333,10 @@ int UtcDaliActorRaiseAboveActorAndTargetTheSameN(void)
   point.SetDeviceId( 1 );
   point.SetState( PointState::DOWN );
   point.SetScreenPosition( Vector2( 10.f, 10.f ) );
-  Dali::Integration::TouchEvent event;
-  event.AddPoint( point );
+  Dali::Integration::TouchEvent touchEvent;
+  touchEvent.AddPoint( point );
 
-  application.ProcessEvent( event );
+  application.ProcessEvent( touchEvent );
 
   DALI_TEST_EQUALS( gTouchCallBackCalled, false, TEST_LOCATION );
   DALI_TEST_EQUALS( gTouchCallBackCalled2, false, TEST_LOCATION );
@@ -5319,8 +5347,10 @@ int UtcDaliActorRaiseAboveActorAndTargetTheSameN(void)
   tet_infoline( "Raise actor A Above Actor A which is the same actor!!\n" );
 
   DevelActor::RaiseAbove( actorA, actorA );
+  application.SendNotification();
+  application.Render();
 
-  application.ProcessEvent( event );
+  application.ProcessEvent( touchEvent );
 
   tet_infoline( "No target is source Actor so RaiseAbove should show no effect\n" );
 
@@ -5331,7 +5361,10 @@ int UtcDaliActorRaiseAboveActorAndTargetTheSameN(void)
   ResetTouchCallbacks();
 
   DevelActor::RaiseAbove( actorA, actorC );
-  application.ProcessEvent( event );
+  application.SendNotification();
+  application.Render();
+
+  application.ProcessEvent( touchEvent );
 
   tet_infoline( "Raise actor A Above Actor C which will now be successful \n" );
   DALI_TEST_EQUALS( gTouchCallBackCalled,  true, TEST_LOCATION );
@@ -5905,7 +5938,6 @@ int utcDaliActorPositionUsesAnchorPointOnlyInheritPosition(void)
 
   END_TEST;
 }
-
 int utcDaliActorVisibilityChangeSignalSelf(void)
 {
   TestApplication application;
index 7028a79..240d1a0 100644 (file)
@@ -1403,6 +1403,33 @@ int UtcDaliRendererUniformMapMultipleUniforms02(void)
   END_TEST;
 }
 
+
+Renderer CreateRenderer( Actor actor, Geometry geometry, Shader shader, int depthIndex )
+{
+  Image image0 = BufferImage::New( 64, 64, Pixel::RGB888 );
+  TextureSet textureSet0 = CreateTextureSet( image0 );
+  Renderer renderer0 = Renderer::New( geometry, shader );
+  renderer0.SetTextures( textureSet0 );
+  renderer0.SetProperty( Renderer::Property::DEPTH_INDEX, depthIndex );
+  actor.AddRenderer(renderer0);
+  return renderer0;
+}
+
+
+Actor CreateActor( Actor parent, int siblingOrder, const char* location )
+{
+  Actor actor0 = Actor::New();
+  actor0.SetAnchorPoint(AnchorPoint::CENTER);
+  actor0.SetParentOrigin(AnchorPoint::CENTER);
+  actor0.SetPosition(0.0f,0.0f);
+  actor0.SetSize(100, 100);
+  actor0.SetProperty( Dali::DevelActor::Property::SIBLING_ORDER, siblingOrder );
+  DALI_TEST_EQUALS( actor0.GetProperty<int>( Dali::DevelActor::Property::SIBLING_ORDER), siblingOrder, TEST_INNER_LOCATION(location) );
+  parent.Add(actor0);
+
+  return actor0;
+}
+
 int UtcDaliRendererRenderOrder2DLayer(void)
 {
   TestApplication application;
@@ -1411,59 +1438,20 @@ int UtcDaliRendererRenderOrder2DLayer(void)
   Shader shader = Shader::New("VertexSource", "FragmentSource");
   Geometry geometry = CreateQuadGeometry();
 
-  Actor actor0 = Actor::New();
-  actor0.SetAnchorPoint(AnchorPoint::CENTER);
-  actor0.SetParentOrigin(AnchorPoint::CENTER);
-  actor0.SetPosition(0.0f,0.0f);
-  Image image0 = BufferImage::New( 64, 64, Pixel::RGB888 );
-  TextureSet textureSet0 = CreateTextureSet( image0 );
-  Renderer renderer0 = Renderer::New( geometry, shader );
-  renderer0.SetTextures( textureSet0 );
-  actor0.AddRenderer(renderer0);
-  actor0.SetSize(1, 1);
-  Stage::GetCurrent().Add(actor0);
-  application.SendNotification();
-  application.Render(0);
+  Actor root = Stage::GetCurrent().GetRootLayer();
 
-  Actor actor1 = Actor::New();
-  actor1.SetAnchorPoint(AnchorPoint::CENTER);
-  actor1.SetParentOrigin(AnchorPoint::CENTER);
-  actor1.SetPosition(0.0f,0.0f);
-  Image image1= BufferImage::New( 64, 64, Pixel::RGB888 );
-  TextureSet textureSet1 = CreateTextureSet( image1 );
-  Renderer renderer1 = Renderer::New( geometry, shader );
-  renderer1.SetTextures( textureSet1 );
-  actor1.AddRenderer(renderer1);
-  actor1.SetSize(1, 1);
-  Stage::GetCurrent().Add(actor1);
-  application.SendNotification();
-  application.Render(0);
+  Actor actor0 = CreateActor( root, 0, TEST_LOCATION );
+  Renderer renderer0 = CreateRenderer( actor0, geometry, shader, 0 );
 
-  Actor actor2 = Actor::New();
-  actor2.SetAnchorPoint(AnchorPoint::CENTER);
-  actor2.SetParentOrigin(AnchorPoint::CENTER);
-  actor2.SetPosition(0.0f,0.0f);
-  Image image2= BufferImage::New( 64, 64, Pixel::RGB888 );
-  TextureSet textureSet2 = CreateTextureSet( image2 );
-  Renderer renderer2 = Renderer::New( geometry, shader );
-  renderer2.SetTextures( textureSet2 );
-  actor2.AddRenderer(renderer2);
-  actor2.SetSize(1, 1);
-  Stage::GetCurrent().Add(actor2);
-  application.SendNotification();
-  application.Render(0);
+  Actor actor1 = CreateActor( root, 0, TEST_LOCATION );
+  Renderer renderer1 = CreateRenderer( actor1, geometry, shader, 0 );
+
+  Actor actor2 = CreateActor( root, 0, TEST_LOCATION );
+  Renderer renderer2 = CreateRenderer( actor2, geometry, shader, 0 );
+
+  Actor actor3 = CreateActor( root, 0, TEST_LOCATION );
+  Renderer renderer3 = CreateRenderer( actor3, geometry, shader, 0 );
 
-  Actor actor3 = Actor::New();
-  actor3.SetAnchorPoint(AnchorPoint::CENTER);
-  actor3.SetParentOrigin(AnchorPoint::CENTER);
-  actor3.SetPosition(0.0f,0.0f);
-  Image image3 = BufferImage::New( 64, 64, Pixel::RGB888 );
-  TextureSet textureSet3 = CreateTextureSet( image3 );
-  Renderer renderer3 = Renderer::New( geometry, shader );
-  renderer3.SetTextures( textureSet3 );
-  actor3.AddRenderer(renderer3);
-  actor3.SetSize(1, 1);
-  Stage::GetCurrent().Add(actor3);
   application.SendNotification();
   application.Render(0);
 
@@ -1542,81 +1530,20 @@ int UtcDaliRendererRenderOrder2DLayerMultipleRenderers(void)
   Shader shader = Shader::New("VertexSource", "FragmentSource");
   Geometry geometry = CreateQuadGeometry();
 
-  Actor actor0 = Actor::New();
-  actor0.SetAnchorPoint(AnchorPoint::CENTER);
-  actor0.SetParentOrigin(AnchorPoint::CENTER);
-  actor0.SetPosition(0.0f,0.0f);
-  actor0.SetSize(1, 1);
-  Stage::GetCurrent().Add(actor0);
-
-  Actor actor1 = Actor::New();
-  actor1.SetAnchorPoint(AnchorPoint::CENTER);
-  actor1.SetParentOrigin(AnchorPoint::CENTER);
-  actor1.SetPosition(0.0f,0.0f);
-  actor1.SetSize(1, 1);
-  actor0.Add(actor1);
-
-  //Renderer0
-  Image image0 = BufferImage::New( 64, 64, Pixel::RGB888 );
-  TextureSet textureSet0 = CreateTextureSet( image0 );
-  Renderer renderer0 = Renderer::New( geometry, shader );
-  renderer0.SetTextures( textureSet0 );
-  renderer0.SetProperty( Renderer::Property::DEPTH_INDEX, 2 );
-  actor0.AddRenderer(renderer0);
-  application.SendNotification();
-  application.Render(0);
-
-  //Renderer1
-  Image image1= BufferImage::New( 64, 64, Pixel::RGB888 );
-  TextureSet textureSet1 = CreateTextureSet( image1 );
-  Renderer renderer1 = Renderer::New( geometry, shader );
-  renderer1.SetTextures( textureSet1 );
-  renderer1.SetProperty( Renderer::Property::DEPTH_INDEX, 0 );
-  actor0.AddRenderer(renderer1);
-  application.SendNotification();
-  application.Render(0);
-
-  //Renderer2
-  Image image2= BufferImage::New( 64, 64, Pixel::RGB888 );
-  TextureSet textureSet2 = CreateTextureSet( image2 );
-  Renderer renderer2 = Renderer::New( geometry, shader );
-  renderer2.SetTextures( textureSet2 );
-  renderer2.SetProperty( Renderer::Property::DEPTH_INDEX, 1 );
-  actor0.AddRenderer(renderer2);
-  application.SendNotification();
-  application.Render(0);
-
-  //Renderer3
-  Image image3 = BufferImage::New( 64, 64, Pixel::RGB888 );
-  TextureSet textureSet3 = CreateTextureSet( image3 );
-  Renderer renderer3 = Renderer::New( geometry, shader );
-  renderer3.SetTextures( textureSet3 );
-  renderer3.SetProperty( Renderer::Property::DEPTH_INDEX, 1 );
-  actor1.AddRenderer(renderer3);
-  application.SendNotification();
-  application.Render(0);
+  Actor root = Stage::GetCurrent().GetRootLayer();
 
-  //Renderer4
-  Image image4= BufferImage::New( 64, 64, Pixel::RGB888 );
-  TextureSet textureSet4 = CreateTextureSet( image4 );
-  Renderer renderer4 = Renderer::New( geometry, shader );
-  renderer4.SetTextures( textureSet4 );
-  renderer4.SetProperty( Renderer::Property::DEPTH_INDEX, 0 );
-  actor1.AddRenderer(renderer4);
-  application.SendNotification();
-  application.Render(0);
+  Actor actor0 = CreateActor( root, 0, TEST_LOCATION );
+  Actor actor1 = CreateActor( actor0, 0, TEST_LOCATION );
+  Renderer renderer0 = CreateRenderer( actor0, geometry, shader, 2 );
+  Renderer renderer1 = CreateRenderer( actor0, geometry, shader, 0 );
+  Renderer renderer2 = CreateRenderer( actor0, geometry, shader, 1 );
+  Renderer renderer3 = CreateRenderer( actor1, geometry, shader, 1 );
+  Renderer renderer4 = CreateRenderer( actor1, geometry, shader, 0 );
+  Renderer renderer5 = CreateRenderer( actor1, geometry, shader, -1 );
 
-  //Renderer5
-  Image image5= BufferImage::New( 64, 64, Pixel::RGB888 );
-  TextureSet textureSet5 = CreateTextureSet( image5 );
-  Renderer renderer5 = Renderer::New( geometry, shader );
-  renderer5.SetTextures( textureSet5 );
-  renderer5.SetProperty( Renderer::Property::DEPTH_INDEX, -1 );
-  actor1.AddRenderer(renderer5);
   application.SendNotification();
   application.Render(0);
 
-
   TestGlAbstraction& gl = application.GetGlAbstraction();
   gl.EnableTextureCallTrace(true);
   application.SendNotification();
@@ -1648,6 +1575,7 @@ int UtcDaliRendererRenderOrder2DLayerMultipleRenderers(void)
   END_TEST;
 }
 
+
 int UtcDaliRendererRenderOrder2DLayerSiblingOrder(void)
 {
   TestApplication application;
@@ -1667,9 +1595,10 @@ int UtcDaliRendererRenderOrder2DLayerSiblingOrder(void)
    *          /     |     \                /     |     \
    *        /       |       \            /       |       \
    * renderer0 renderer1  actor2     renderer2 renderer3 renderer4
-   *                        |
+   *    DI:2      DI:0      |           DI:0      DI:1      DI:2
    *                        |
    *                   renderer5
+   *                      DI:-1
    *
    *  actor0 has sibling order 1
    *  actor1 has sibling order 0
@@ -1689,92 +1618,20 @@ int UtcDaliRendererRenderOrder2DLayerSiblingOrder(void)
 
   Shader shader = Shader::New("VertexSource", "FragmentSource");
   Geometry geometry = CreateQuadGeometry();
+  Actor root = Stage::GetCurrent().GetRootLayer();
+  Actor actor0 = CreateActor( root,   1, TEST_LOCATION );
+  Actor actor1 = CreateActor( root,   0, TEST_LOCATION );
+  Actor actor2 = CreateActor( actor0, 0, TEST_LOCATION );
 
-  Actor actor0 = Actor::New();
-  actor0.SetAnchorPoint(AnchorPoint::CENTER);
-  actor0.SetParentOrigin(AnchorPoint::CENTER);
-  actor0.SetPosition(0.0f,0.0f);
-  actor0.SetSize(1, 1);
-  actor0.SetProperty( Dali::DevelActor::Property::SIBLING_ORDER, 1 );
-  DALI_TEST_EQUALS( actor0.GetProperty<int>( Dali::DevelActor::Property::SIBLING_ORDER), 1, TEST_LOCATION );
-  Stage::GetCurrent().Add(actor0);
-
-  Actor actor1 = Actor::New();
-  actor1.SetAnchorPoint(AnchorPoint::CENTER);
-  actor1.SetParentOrigin(AnchorPoint::CENTER);
-  actor1.SetPosition(0.0f,0.0f);
-  actor1.SetSize(1, 1);
-  DALI_TEST_EQUALS( actor1.GetProperty<int>( Dali::DevelActor::Property::SIBLING_ORDER), 0, TEST_LOCATION );
-  Stage::GetCurrent().Add(actor1);
-
-  Actor actor2 = Actor::New();
-  actor2.SetAnchorPoint(AnchorPoint::CENTER);
-  actor2.SetParentOrigin(AnchorPoint::CENTER);
-  actor2.SetPosition(0.0f,0.0f);
-  actor2.SetSize(1, 1);
-  DALI_TEST_EQUALS( actor1.GetProperty<int>( Dali::DevelActor::Property::SIBLING_ORDER), 0, TEST_LOCATION );
-  actor0.Add(actor2);
-
-  //Renderer0
-  Image image0 = BufferImage::New( 64, 64, Pixel::RGB888 );
-  TextureSet textureSet0 = CreateTextureSet( image0 );
-  Renderer renderer0 = Renderer::New( geometry, shader );
-  renderer0.SetTextures( textureSet0 );
-  renderer0.SetProperty( Renderer::Property::DEPTH_INDEX, 2 );
-  actor0.AddRenderer(renderer0);
-  application.SendNotification();
-  application.Render(0);
-
-  //Renderer1
-  Image image1= BufferImage::New( 64, 64, Pixel::RGB888 );
-  TextureSet textureSet1 = CreateTextureSet( image1 );
-  Renderer renderer1 = Renderer::New( geometry, shader );
-  renderer1.SetTextures( textureSet1 );
-  renderer1.SetProperty( Renderer::Property::DEPTH_INDEX, 0 );
-  actor0.AddRenderer(renderer1);
-  application.SendNotification();
-  application.Render(0);
-
-  //Renderer2
-  Image image2= BufferImage::New( 64, 64, Pixel::RGB888 );
-  TextureSet textureSet2 = CreateTextureSet( image2 );
-  Renderer renderer2 = Renderer::New( geometry, shader );
-  renderer2.SetTextures( textureSet2 );
-  renderer2.SetProperty( Renderer::Property::DEPTH_INDEX, 0 );
-  actor1.AddRenderer(renderer2);
-  application.SendNotification();
-  application.Render(0);
-
-  //Renderer3
-  Image image3 = BufferImage::New( 64, 64, Pixel::RGB888 );
-  TextureSet textureSet3 = CreateTextureSet( image3 );
-  Renderer renderer3 = Renderer::New( geometry, shader );
-  renderer3.SetTextures( textureSet3 );
-  renderer3.SetProperty( Renderer::Property::DEPTH_INDEX, 1 );
-  actor1.AddRenderer(renderer3);
-  application.SendNotification();
-  application.Render(0);
-
-  //Renderer4
-  Image image4= BufferImage::New( 64, 64, Pixel::RGB888 );
-  TextureSet textureSet4 = CreateTextureSet( image4 );
-  Renderer renderer4 = Renderer::New( geometry, shader );
-  renderer4.SetTextures( textureSet4 );
-  renderer4.SetProperty( Renderer::Property::DEPTH_INDEX, 2 );
-  actor1.AddRenderer(renderer4);
-  application.SendNotification();
-  application.Render(0);
+  Renderer renderer0 = CreateRenderer( actor0, geometry, shader, 2 );
+  Renderer renderer1 = CreateRenderer( actor0, geometry, shader, 0 );
+  Renderer renderer2 = CreateRenderer( actor1, geometry, shader, 0 );
+  Renderer renderer3 = CreateRenderer( actor1, geometry, shader, 1 );
+  Renderer renderer4 = CreateRenderer( actor1, geometry, shader, 2 );
+  Renderer renderer5 = CreateRenderer( actor2, geometry, shader, -1 );
 
-  //Renderer5
-  Image image5= BufferImage::New( 64, 64, Pixel::RGB888 );
-  TextureSet textureSet5 = CreateTextureSet( image5 );
-  Renderer renderer5 = Renderer::New( geometry, shader );
-  renderer5.SetTextures( textureSet5 );
-  renderer5.SetProperty( Renderer::Property::DEPTH_INDEX, -1 );
-  actor2.AddRenderer(renderer5);
   application.SendNotification();
-  application.Render(0);
-
+  application.Render();
 
   TestGlAbstraction& gl = application.GetGlAbstraction();
   gl.EnableTextureCallTrace(true);
@@ -1796,8 +1653,8 @@ int UtcDaliRendererRenderOrder2DLayerSiblingOrder(void)
   DALI_TEST_EQUALS( textureBindIndex[0], 4, TEST_LOCATION );
   DALI_TEST_EQUALS( textureBindIndex[5], 5, TEST_LOCATION );
 
-  //Change sibling order of actor1
-  //New Expected rendering order: renderer1 - renderer0 - renderer2 - renderer3 - renderer4  - renderer5
+  // Change sibling order of actor1
+  // New Expected rendering order: renderer1 - renderer0 - renderer 5 - renderer2 - renderer3 - renderer4
   actor1.SetProperty( Dali::DevelActor::Property::SIBLING_ORDER, 2 );
 
   gl.GetTextureTrace().Reset();
@@ -1813,10 +1670,10 @@ int UtcDaliRendererRenderOrder2DLayerSiblingOrder(void)
 
   DALI_TEST_EQUALS( textureBindIndex[1], 0, TEST_LOCATION );
   DALI_TEST_EQUALS( textureBindIndex[0], 1, TEST_LOCATION );
-  DALI_TEST_EQUALS( textureBindIndex[2], 2, TEST_LOCATION );
-  DALI_TEST_EQUALS( textureBindIndex[3], 3, TEST_LOCATION );
-  DALI_TEST_EQUALS( textureBindIndex[4], 4, TEST_LOCATION );
-  DALI_TEST_EQUALS( textureBindIndex[5], 5, TEST_LOCATION );
+  DALI_TEST_EQUALS( textureBindIndex[5], 2, TEST_LOCATION );
+  DALI_TEST_EQUALS( textureBindIndex[2], 3, TEST_LOCATION );
+  DALI_TEST_EQUALS( textureBindIndex[3], 4, TEST_LOCATION );
+  DALI_TEST_EQUALS( textureBindIndex[4], 5, TEST_LOCATION );
 
   END_TEST;
 }
@@ -1828,79 +1685,7 @@ int UtcDaliRendererRenderOrder2DLayerOverlay(void)
 
   Shader shader = Shader::New("VertexSource", "FragmentSource");
   Geometry geometry = CreateQuadGeometry();
-
-  Actor actor0 = Actor::New();
-  actor0.SetAnchorPoint(AnchorPoint::CENTER);
-  actor0.SetParentOrigin(AnchorPoint::CENTER);
-  Image image0 = BufferImage::New( 64, 64, Pixel::RGB888 );
-  TextureSet textureSet0 = CreateTextureSet( image0 );
-  Renderer renderer0 = Renderer::New( geometry, shader );
-  renderer0.SetTextures( textureSet0 );
-  actor0.AddRenderer(renderer0);
-  actor0.SetPosition(0.0f,0.0f);
-  actor0.SetSize(100, 100);
-  Stage::GetCurrent().Add(actor0);
-  actor0.SetDrawMode( DrawMode::OVERLAY_2D );
-  application.SendNotification();
-  application.Render(0);
-
-  Actor actor1 = Actor::New();
-  actor1.SetAnchorPoint(AnchorPoint::CENTER);
-  actor1.SetParentOrigin(AnchorPoint::CENTER);
-  Image image1= BufferImage::New( 64, 64, Pixel::RGB888 );
-  TextureSet textureSet1 = CreateTextureSet( image1 );
-  Renderer renderer1 = Renderer::New( geometry, shader );
-  renderer1.SetTextures( textureSet1 );
-  actor1.SetPosition(0.0f,0.0f);
-  actor1.AddRenderer(renderer1);
-  actor1.SetSize(100, 100);
-  Stage::GetCurrent().Add(actor1);
-  actor1.SetDrawMode( DrawMode::OVERLAY_2D );
-  application.SendNotification();
-  application.Render(0);
-
-  Actor actor2 = Actor::New();
-  actor2.SetAnchorPoint(AnchorPoint::CENTER);
-  actor2.SetParentOrigin(AnchorPoint::CENTER);
-  Image image2= BufferImage::New( 64, 64, Pixel::RGB888 );
-  TextureSet textureSet2 = CreateTextureSet( image2 );
-  Renderer renderer2 = Renderer::New( geometry, shader );
-  renderer2.SetTextures( textureSet2 );
-  actor2.AddRenderer(renderer2);
-  actor2.SetPosition(0.0f,0.0f);
-  actor2.SetSize(100, 100);
-  Stage::GetCurrent().Add(actor2);
-  application.SendNotification();
-  application.Render(0);
-
-  Actor actor3 = Actor::New();
-  actor3.SetAnchorPoint(AnchorPoint::CENTER);
-  actor3.SetParentOrigin(AnchorPoint::CENTER);
-  Image image3 = BufferImage::New( 64, 64, Pixel::RGB888 );
-  TextureSet textureSet3 = CreateTextureSet( image3 );
-  Renderer renderer3 = Renderer::New( geometry, shader );
-  renderer3.SetTextures( textureSet3 );
-  actor3.SetPosition(0.0f,0.0f);
-  actor3.AddRenderer(renderer3);
-  actor3.SetSize(100, 100);
-  Stage::GetCurrent().Add(actor3);
-  actor3.SetDrawMode( DrawMode::OVERLAY_2D );
-  application.SendNotification();
-  application.Render(0);
-
-  Actor actor4 = Actor::New();
-  actor4.SetAnchorPoint(AnchorPoint::CENTER);
-  actor4.SetParentOrigin(AnchorPoint::CENTER);
-  Image image4 = BufferImage::New( 64, 64, Pixel::RGB888 );
-  TextureSet textureSet4 = CreateTextureSet( image4 );
-  Renderer renderer4 = Renderer::New( geometry, shader );
-  renderer4.SetTextures( textureSet4 );
-  actor4.AddRenderer(renderer4);
-  actor4.SetPosition(0.0f,0.0f);
-  actor4.SetSize(100, 100);
-  Stage::GetCurrent().Add(actor4);
-  application.SendNotification();
-  application.Render(0);
+  Actor root = Stage::GetCurrent().GetRootLayer();
 
   /*
    * Create the following hierarchy:
@@ -1922,13 +1707,32 @@ int UtcDaliRendererRenderOrder2DLayerOverlay(void)
    *
    *  Expected rendering order : actor2 - actor4 - actor1 - actor0 - actor3
    */
-  Stage::GetCurrent().Add( actor2 );
+
+  Actor actor0 = CreateActor( root, 0, TEST_LOCATION );
+  actor0.SetDrawMode( DrawMode::OVERLAY_2D );
+  Renderer renderer0 = CreateRenderer( actor0, geometry, shader, 0 );
+
+  Actor actor1 = CreateActor( root, 0, TEST_LOCATION );
+  actor1.SetDrawMode( DrawMode::OVERLAY_2D );
+  Renderer renderer1 = CreateRenderer( actor1, geometry, shader, 0 );
+
+  Actor actor2 = CreateActor( root, 0, TEST_LOCATION );
+  Renderer renderer2 = CreateRenderer( actor2, geometry, shader, 0 );
+
+  Actor actor3 = CreateActor( root, 0, TEST_LOCATION );
+  actor3.SetDrawMode( DrawMode::OVERLAY_2D );
+  Renderer renderer3 = CreateRenderer( actor3, geometry, shader, 0 );
+
+  Actor actor4 = CreateActor( root, 0, TEST_LOCATION );
+  Renderer renderer4 = CreateRenderer( actor4, geometry, shader, 0 );
+
+  application.SendNotification();
+  application.Render(0);
+
   actor2.Add(actor1);
   actor2.Add(actor4);
   actor1.Add(actor0);
   actor0.Add(actor3);
-  application.SendNotification();
-  application.Render(0);
 
   TestGlAbstraction& gl = application.GetGlAbstraction();
   gl.EnableTextureCallTrace(true);
index e67b165..dc6a90c 100644 (file)
@@ -25,6 +25,7 @@
 #include <cstdlib>
 #include <sstream>
 #include <iomanip>
+#include <ctime>
 
 // INTERNAL INCLUDES
 #include <dali/public-api/common/constants.h>
@@ -41,6 +42,8 @@ namespace Dali
 namespace // unnamed namespace
 {
 
+const uint64_t NANOSECONDS_PER_SECOND = 1e+9;
+
 /**
  * Generic function to print out any 2-Dimensional array
  * @param[in] data pointer to the source data stored as float[rows][cols]
@@ -325,6 +328,15 @@ std::string MatrixToString(const Matrix& m, size_t precision, size_t indent)
   return Array2DToString(m.AsFloat(), 4, 4, precision, indent);
 }
 
+void GetNanoseconds( uint64_t& timeInNanoseconds )
+{
+  timespec timeSpec;
+  clock_gettime( CLOCK_MONOTONIC, &timeSpec );
+
+  // Convert all values to uint64_t to match our return type
+  timeInNanoseconds = ( static_cast< uint64_t >( timeSpec.tv_sec ) * NANOSECONDS_PER_SECOND ) + static_cast< uint64_t >( timeSpec.tv_nsec );
+}
+
 } // namespace Log
 
 } // namespace Integration
index 828aa3a..b22a5fe 100644 (file)
@@ -22,6 +22,7 @@
 #include <string>
 #include <sstream>
 #include <list>
+#include <stdint.h>
 
 // INTERNAL INCLUDES
 #include <dali/public-api/common/dali-common.h>
@@ -485,7 +486,33 @@ DALI_IMPORT_API std::string MatrixToString(const Matrix& m, size_t precision=3,
 
 #endif
 
-}}} // Dali/Integration/Debug namespaces
+/********************************************************************************
+ *                            Time instrumentation                              *
+ ********************************************************************************/
+
+#if defined(DEBUG_ENABLED)
+
+void GetNanoseconds( uint64_t& timeInNanoseconds );
+
+#define DALI_LOG_TIMER_START( timeVariable )      \
+  uint64_t timeVariable##1; \
+  Debug::GetNanoseconds( timeVariable##1 );
+
+#define DALI_LOG_TIMER_END( timeVariable, filter, level, preString)  \
+  uint64_t timeVariable##2; \
+  Debug::GetNanoseconds( timeVariable##2 );                             \
+  DALI_LOG_INFO( filter, level, preString " %ld uSec\n", ((timeVariable##2-timeVariable##1)/1000));
+
+#else // DEBUG_ENABLED
+
+#define DALI_LOG_TIMER_START( timeVariable )
+#define DALI_LOG_TIMER_END( timeVariable, filter, level, preString)
+
+#endif
+
+} // Debug
+} // Integration
+} // Dali
 
 
 #endif // __DALI_INTEGRATION_DEBUG_H__
index 0534dd7..e37d59a 100644 (file)
@@ -285,6 +285,9 @@ void Core::ProcessEvents()
     // Run the size negotiation after event processing finished signal
     mRelayoutController->Relayout();
 
+    // Rebuild depth tree after event processing has finished
+    mStage->RebuildDepthTree();
+
     // Flush any queued messages for the update-thread
     const bool messagesToProcess = mUpdateManager->FlushQueue();
 
index ee60892..eae9ef9 100644 (file)
@@ -33,6 +33,7 @@
 #include <dali/public-api/math/radian.h>
 #include <dali/public-api/object/type-registry.h>
 #include <dali/devel-api/actors/actor-devel.h>
+#include <dali/devel-api/object/weak-handle.h>
 #include <dali/devel-api/scripting/scripting.h>
 #include <dali/internal/common/internal-constants.h>
 #include <dali/internal/event/common/event-thread-services.h>
@@ -57,6 +58,11 @@ using Dali::Internal::SceneGraph::Node;
 using Dali::Internal::SceneGraph::AnimatableProperty;
 using Dali::Internal::SceneGraph::PropertyBase;
 
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER" );
+Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER" );
+#endif
+
 namespace Dali
 {
 
@@ -385,11 +391,6 @@ float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
   return GetDimensionValue( values.GetVectorXY(), dimension );
 }
 
-unsigned int GetDepthIndex( uint16_t depth, uint16_t siblingOrder )
-{
-  return depth * Dali::DevelLayer::ACTOR_DEPTH_MULTIPLIER + siblingOrder * Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
-}
-
 /**
  * @brief Recursively emits the visibility-changed-signal on the actor tree.
  * @param[in] actor The actor to emit the signal on
@@ -1108,7 +1109,7 @@ ClippingMode::Type Actor::GetClippingMode() const
 
 unsigned int Actor::GetSortingDepth()
 {
-  return GetDepthIndex( mDepth, mSiblingOrder );
+  return mSortedDepth;
 }
 
 const Vector4& Actor::GetCurrentWorldColor() const
@@ -2139,6 +2140,7 @@ Actor::Actor( DerivedType derivedType )
   mTargetScale( Vector3::ONE ),
   mName(),
   mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
+  mSortedDepth( 0u ),
   mDepth( 0u ),
   mSiblingOrder(0u),
   mIsRoot( ROOT_LAYER == derivedType ),
@@ -2224,6 +2226,12 @@ void Actor::ConnectToStage( unsigned int parentDepth )
   // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
   ActorContainer connectionList;
 
+  StagePtr stage = Stage::GetCurrent();
+  if( stage )
+  {
+    stage->RequestRebuildDepthTree();
+  }
+
   // This stage is atomic i.e. not interrupted by user callbacks.
   RecursiveConnectToStage( connectionList, parentDepth + 1 );
 
@@ -2243,7 +2251,6 @@ void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned in
 
   mIsOnStage = true;
   mDepth = depth;
-  SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) );
 
   ConnectToSceneGraph();
 
@@ -2316,6 +2323,12 @@ void Actor::DisconnectFromStage()
   // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
   ActorContainer disconnectionList;
 
+  StagePtr stage = Stage::GetCurrent();
+  if( stage )
+  {
+    stage->RequestRebuildDepthTree();
+  }
+
   // This stage is atomic i.e. not interrupted by user callbacks
   RecursiveDisconnectFromStage( disconnectionList );
 
@@ -2401,6 +2414,205 @@ bool Actor::IsNodeConnected() const
   return connected;
 }
 
+// This method generates the depth tree using the recursive function below,
+// then walks the tree and sets a depth index based on traversal order. It
+// sends a single message to update manager to update all the actor's nodes in this
+// tree with the depth index. The sceneGraphNodeDepths vector's elements are ordered
+// by depth, and could be used to reduce sorting in the update thread.
+void Actor::RebuildDepthTree()
+{
+  DALI_LOG_TIMER_START(depthTimer);
+
+  DepthNodeMemoryPool nodeMemoryPool;
+  ActorDepthTreeNode* rootNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( this, mSiblingOrder );
+
+  int actorCount = BuildDepthTree( nodeMemoryPool, rootNode );
+
+  // Vector of scene-graph nodes and their depths to send to UpdateManager
+  // in a single message
+  SceneGraph::NodeDepths* sceneGraphNodeDepths = new SceneGraph::NodeDepths(actorCount);
+
+  // Traverse depth tree and set mSortedDepth on each actor and scenegraph node
+  uint32_t sortOrder = 1u; // Don't start at zero, as visual depth can be negative
+  ActorDepthTreeNode* currentNode = rootNode;
+  bool firstVisit = true;
+  while( currentNode != rootNode || firstVisit)
+  {
+    firstVisit = false;
+
+    // Visit node, performing action
+    for( std::vector<Actor*>::iterator iter = currentNode->mActors.begin(); iter != currentNode->mActors.end(); ++iter )
+    {
+      (*iter)->mSortedDepth = sortOrder * DevelLayer::SIBLING_ORDER_MULTIPLIER;
+      sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>((*iter)->mNode), (*iter)->mSortedDepth );
+    }
+    ++sortOrder;
+
+    // Descend tree
+    if( currentNode->mFirstChildNode )
+    {
+      currentNode = currentNode->mFirstChildNode;
+    }
+    else // leaf node, goto next sibling, or return up tree.
+    {
+      bool breakout=false;
+      while( ! currentNode->mNextSiblingNode )
+      {
+        if( currentNode == rootNode ) // If we get to root of tree, stop
+        {
+          breakout = true;
+          break;
+        }
+        currentNode = currentNode->mParentNode;
+      }
+
+      if( breakout )
+      {
+        break;
+      }
+      currentNode = currentNode->mNextSiblingNode;
+    }
+  }
+
+  SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
+  DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree create time: ");
+}
+
+/**
+ * Structure to store the actor's associated node in the depth tree for child
+ * traversal
+ */
+struct ActorNodePair
+{
+  Actor* actor;
+  ActorDepthTreeNode* node;
+  ActorNodePair( Actor* actor, ActorDepthTreeNode* node )
+  : actor(actor),
+    node(node)
+  {
+  }
+};
+
+/*
+ * Descend actor tree, building a depth tree based on actor's sibling order.
+ * Actors with the same sibling order share the same depth tree. Siblings
+ * in the depth tree are ordered by actor's sibling order.
+ *
+ * An actor tree like this:
+ *
+ *                  Root (SO:0)
+ *                 _/    |   \_
+ *               _/      |     \_
+ *             _/        |       \_
+ *            /          |         \
+ *        A(SO:1)     B(SO:2)    C(SO:1)
+ *         _/\_          |         _/ \_
+ *        /    \         |       /       \
+ *     D(SO:0) E(SO:0) F(SO:0) G(SO:1)  H(SO:0)
+ *
+ * will end up as a depth tree like this:
+ *
+ *     RootNode [ Root ] -> NULL
+ *       |(mFC)
+ *       V                (mNS)
+ *     Node [ A, C ] ------------------------>  Node [ B ] -> NULL
+ *       |                                        |
+ *       V                                        V
+ *     Node [ D, E, H ] -> Node [ G ] -> NULL   Node [ F ] -> NULL
+ *       |                   |                    |
+ *       V                   V                    V
+ *     NULL                NULL                 NULL
+ *
+ * (All nodes also point to their parents to enable storage free traversal)
+ */
+int Actor::BuildDepthTree( DepthNodeMemoryPool& nodeMemoryPool, ActorDepthTreeNode* node )
+{
+  int treeCount=1; // Count self and children
+
+  // Create/add to children of this node
+  if( mChildren )
+  {
+    std::vector<ActorNodePair> storedChildren;
+    storedChildren.reserve( mChildren->size() );
+
+    for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
+    {
+      Actor* childActor = (*it).Get();
+      if( childActor->IsLayer() )
+      {
+        Layer* layer = static_cast<Layer*>(childActor);
+        if( layer->GetBehavior() == Dali::Layer::LAYER_3D )
+        {
+          // Ignore this actor and children.
+          continue;
+        }
+      }
+
+      // If no existing depth node children
+      if( node->mFirstChildNode == NULL )
+      {
+        node->mFirstChildNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( childActor, childActor->mSiblingOrder );
+        node->mFirstChildNode->mParentNode = node;
+        storedChildren.push_back(ActorNodePair( childActor, node->mFirstChildNode ));
+      }
+      else // find child node with matching sibling order (insertion sort)
+      {
+        bool addedChildActor = false;
+
+        // depth tree child nodes ordered by sibling order
+        ActorDepthTreeNode* lastNode = NULL;
+        for( ActorDepthTreeNode* childNode = node->mFirstChildNode; childNode != NULL; childNode = childNode->mNextSiblingNode )
+        {
+          uint16_t actorSiblingOrder = childActor->mSiblingOrder;
+          uint16_t currentSiblingOrder = childNode->GetSiblingOrder();
+
+          if( actorSiblingOrder == currentSiblingOrder )
+          {
+            // Don't need a new depth node, add to existing node
+            childNode->AddActor( childActor );
+            storedChildren.push_back(ActorNodePair( childActor, childNode ));
+            addedChildActor = true;
+            break;
+          }
+          else if( actorSiblingOrder < currentSiblingOrder )
+          {
+            break;
+          }
+          lastNode = childNode;
+        }
+
+        // No matching sibling order - create new node and insert into sibling list
+        if( !addedChildActor )
+        {
+          ActorDepthTreeNode* newNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( childActor, childActor->mSiblingOrder );
+
+          newNode->mParentNode = node;
+          storedChildren.push_back(ActorNodePair( childActor, newNode ));
+
+          if( lastNode == NULL ) // Insert at start of siblings
+          {
+            ActorDepthTreeNode* nextNode = node->mFirstChildNode;
+            node->mFirstChildNode = newNode;
+            newNode->mNextSiblingNode = nextNode;
+          }
+          else // insert into siblings after last node
+          {
+            newNode->mNextSiblingNode = lastNode->mNextSiblingNode;
+            lastNode->mNextSiblingNode = newNode;
+          }
+        }
+      }
+    }
+
+    // Order of descent doesn't matter; we're using insertion to sort.
+    for( std::vector<ActorNodePair>::iterator iter = storedChildren.begin(); iter != storedChildren.end(); ++iter )
+    {
+      treeCount += iter->actor->BuildDepthTree( nodeMemoryPool, iter->node );
+    }
+  }
+  return treeCount;
+}
+
 unsigned int Actor::GetDefaultPropertyCount() const
 {
   return DEFAULT_PROPERTY_COUNT;
@@ -4575,6 +4787,8 @@ void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& cont
   // relayout container afterwards, the dirty flags would still be clear...
   // causing a relayout to be skipped. Here we force any actors added to the
   // container to be relayed out.
+  DALI_LOG_TIMER_START( NegSizeTimer1 );
+
   if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
   {
     SetLayoutNegotiated(false, Dimension::WIDTH);
@@ -4616,6 +4830,7 @@ void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& cont
       container.Add( Dali::Actor( child.Get() ), newBounds );
     }
   }
+  DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
 }
 
 void Actor::RelayoutRequest( Dimension::Type dimension )
@@ -4735,9 +4950,14 @@ Object* Actor::GetParentObject() const
 void Actor::SetSiblingOrder( unsigned int order )
 {
   mSiblingOrder = std::min( order, static_cast<unsigned int>( DevelLayer::SIBLING_ORDER_MULTIPLIER ) );
+
   if( mIsOnStage )
   {
-    SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) );
+    StagePtr stage = Stage::GetCurrent();
+    if( stage )
+    {
+      stage->RequestRebuildDepthTree();
+    }
   }
 }
 
index b30787d..c7de97a 100644 (file)
@@ -30,6 +30,7 @@
 #include <dali/public-api/math/viewport.h>
 #include <dali/public-api/object/ref-object.h>
 #include <dali/public-api/size-negotiation/relayout-container.h>
+#include <dali/internal/common/memory-pool-object-allocator.h>
 #include <dali/internal/event/actors/actor-declarations.h>
 #include <dali/internal/event/common/object-impl.h>
 #include <dali/internal/event/common/stage-def.h>
@@ -60,6 +61,9 @@ typedef ActorContainer::const_iterator ActorConstIter;
 typedef std::vector< RendererPtr > RendererContainer;
 typedef RendererContainer::iterator RendererIter;
 
+class ActorDepthTreeNode;
+typedef Dali::Internal::MemoryPoolObjectAllocator< ActorDepthTreeNode > DepthNodeMemoryPool;
+
 /**
  * Actor is the primary object which Dali applications interact with.
  * UI controls can be built by combining multiple actors.
@@ -756,8 +760,7 @@ public:
   }
 
   /**
-   * Get the actor's sorting depth (The hierarchy depth combined with
-   * the sibling order)
+   * Get the actor's sorting depth
    *
    * @return The depth used for hit-testing and renderer sorting
    */
@@ -1583,6 +1586,26 @@ protected:
   bool IsNodeConnected() const;
 
 public:
+  /**
+   * Trigger a rebuild of the actor depth tree from this root
+   * If a Layer3D is encountered, then this doesn't descend any further.
+   * The mSortedDepth of each actor is set appropriately.
+   */
+  void RebuildDepthTree();
+
+protected:
+
+  /**
+   * Traverse the actor tree, inserting actors into the depth tree in sibling order.
+   * For all actors that share a sibling order, they also share a depth tree, for
+   * optimal render performance.
+   * @param[in] nodeMemoryPool The memory pool used to allocate depth nodes
+   * @param[in,out] depthTreeNode The depth tree node to which to add this actor's children
+   * @return The count of actors in this depth tree
+   */
+  int BuildDepthTree( DepthNodeMemoryPool& nodeMemoryPool, ActorDepthTreeNode* depthTreeNode );
+
+public:
 
   // Default property extensions from Object
 
@@ -1923,6 +1946,7 @@ protected:
   std::string     mName;      ///< Name of the actor
   unsigned int    mId;        ///< A unique ID to identify the actor starting from 1, and 0 is reserved
 
+  uint32_t mSortedDepth;      ///< The sorted depth index. A combination of tree traversal and sibling order.
   uint16_t mDepth;            ///< The depth in the hierarchy of the actor. Only 4096 levels of depth are supported
   uint16_t mSiblingOrder;     ///< The sibling order of the actor
 
@@ -1953,6 +1977,67 @@ private:
   static unsigned int mActorCounter;    ///< A counter to track the actor instance creation
 };
 
+/**
+ * Helper class to create sorted depth index
+ */
+class ActorDepthTreeNode
+{
+public:
+  ActorDepthTreeNode()
+  : mParentNode(NULL),
+    mNextSiblingNode(NULL),
+    mFirstChildNode(NULL),
+    mSiblingOrder( 0 )
+  {
+  }
+
+  ActorDepthTreeNode( Actor* actor, uint16_t siblingOrder )
+  : mParentNode(NULL),
+    mNextSiblingNode(NULL),
+    mFirstChildNode(NULL),
+    mSiblingOrder( siblingOrder )
+  {
+    mActors.push_back( actor );
+  }
+
+  ~ActorDepthTreeNode()
+  {
+    if( mFirstChildNode )
+    {
+      delete mFirstChildNode;
+      mFirstChildNode = NULL;
+    }
+    if( mNextSiblingNode )
+    {
+      delete mNextSiblingNode;
+      mNextSiblingNode = NULL;
+    }
+    mParentNode = NULL;
+  }
+
+  uint16_t GetSiblingOrder()
+  {
+    return mSiblingOrder;
+  }
+
+  void AddActor( Actor* actor )
+  {
+    mActors.push_back( actor );
+  }
+
+public:
+  std::vector<Actor*> mActors; // Array of actors with the same sibling order and same ancestor sibling orders
+  ActorDepthTreeNode* mParentNode;
+  ActorDepthTreeNode* mNextSiblingNode;
+  ActorDepthTreeNode* mFirstChildNode;
+  uint16_t mSiblingOrder;
+
+private:
+  ActorDepthTreeNode( ActorDepthTreeNode& );
+  ActorDepthTreeNode& operator=(const ActorDepthTreeNode& );
+};
+
+
 } // namespace Internal
 
 // Helpers for public-api forwarding methods
index c036a5d..905cfba 100644 (file)
 
 using Dali::Internal::SceneGraph::Node;
 
+namespace
+{
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER" );
+#endif
+}
+
 namespace Dali
 {
 
@@ -664,6 +671,27 @@ void Stage::NotifyContextRegained()
   mContextRegainedSignal.Emit();
 }
 
+
+void Stage::RequestRebuildDepthTree()
+{
+  DALI_LOG_INFO(gLogFilter, Debug::General, "RequestRebuildDepthTree()\n");
+  mDepthTreeDirty = true;
+}
+
+void Stage::RebuildDepthTree()
+{
+  // If the depth tree needs rebuilding, do it in this frame only.
+  if( mDepthTreeDirty )
+  {
+    DALI_LOG_INFO(gLogFilter, Debug::Concise, "RebuildDepthTree() dirty:T\n");
+
+    ActorPtr actor( mRootLayer.Get() );
+    actor->RebuildDepthTree();
+    mDepthTreeDirty = false;
+  }
+}
+
+
 Stage::Stage( AnimationPlaylist& playlist,
               PropertyNotificationManager& propertyNotificationManager,
               SceneGraph::UpdateManager& updateManager,
index ef2c2c4..52d68ee 100644 (file)
@@ -434,6 +434,17 @@ public: // Implementation of EventThreadServices
    */
   virtual BufferIndex GetEventBufferIndex() const;
 
+  /**
+   * Request that the depth tree is rebuilt
+   */
+  void RequestRebuildDepthTree();
+
+  /**
+   * Rebuilds the depth tree at the end of the event frame if
+   * it was requested this frame.
+   */
+  void RebuildDepthTree();
+
 private:
 
   /**
@@ -503,6 +514,7 @@ private:
   // The touched signals
   Dali::Stage::TouchedSignalType                  mTouchedSignal;
   Dali::Stage::TouchSignalType                    mTouchSignal;
+  bool mDepthTreeDirty; ///< True if the depth tree needs recalculating
 
   // The wheel event signal
   Dali::Stage::WheelEventSignalType               mWheelEventSignal;
index 224f972..cac355a 100644 (file)
@@ -1092,6 +1092,21 @@ void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool syst
   }
 }
 
+void UpdateManager::SetDepthIndices( NodeDepths* nodeDepths )
+{
+  if( nodeDepths )
+  {
+    // note,this vector is already in depth order. It could be used as-is to
+    // remove sorting in update algorithm. However, it lacks layer boundary markers.
+    for( std::vector<NodeDepthPair>::iterator iter = nodeDepths->nodeDepths.begin(),
+           end = nodeDepths->nodeDepths.end() ;
+         iter != end ; ++iter )
+    {
+      iter->node->SetDepthIndex( iter->sortedDepth );
+    }
+  }
+}
+
 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
 {
   mImpl->shaderSaver = &upstream;
index 022a08d..ffde6fc 100644 (file)
@@ -80,6 +80,32 @@ class RenderQueue;
 class PropertyBuffer;
 class TextureSet;
 
+struct NodeDepthPair
+{
+  SceneGraph::Node* node;
+  uint32_t sortedDepth;
+  NodeDepthPair( SceneGraph::Node* node, uint32_t sortedDepth )
+  : node(node),
+    sortedDepth(sortedDepth)
+  {
+  }
+};
+
+struct NodeDepths
+{
+  std::vector<NodeDepthPair> nodeDepths;
+  NodeDepths( int reserveSize )
+  {
+    nodeDepths.reserve(reserveSize);
+  }
+
+  void Add( SceneGraph::Node* node, uint32_t sortedDepth )
+  {
+    nodeDepths.push_back( NodeDepthPair( node, sortedDepth ) );
+  }
+};
+
+
 /**
  * UpdateManager maintains a scene graph i.e. a tree of nodes as well as
  * other scene graph property owning objects.
@@ -557,6 +583,12 @@ public:
    */
   void SetLayerDepths( const std::vector< Layer* >& layers, bool systemLevel );
 
+  /**
+   * Set the depth indices of all nodes (in LayerUI's)
+   * @param[in] nodeDepths A vector of nodes and associated depth indices
+   */
+  void SetDepthIndices( NodeDepths* nodeDepths );
+
 private:
 
   // Undefined
@@ -1282,6 +1314,17 @@ inline void AttachColorTextureToFrameBuffer( UpdateManager& manager, Render::Fra
   new (slot) LocalType( &manager, &UpdateManager::AttachColorTextureToFrameBuffer, &frameBuffer, texture, mipmapLevel, layer );
 }
 
+inline void SetDepthIndicesMessage( UpdateManager& manager, NodeDepths* nodeDepths )
+{
+  typedef MessageValue1< UpdateManager, OwnerPointer< NodeDepths > > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::SetDepthIndices, nodeDepths );
+}
+
 
 } // namespace SceneGraph