From 9006930522d5b8a124062b6119f236e7d57fb475 Mon Sep 17 00:00:00 2001 From: Ferran Sole Date: Thu, 8 Dec 2016 15:26:03 +0000 Subject: [PATCH] [3.0] Added sibling order property to Actor - Added a sibling order to allow the user to control drawing order in LAYER_UI Change-Id: I0000fd7091647bda1e5637dfcef11090188ac823 --- automated-tests/src/dali/utc-Dali-Renderer.cpp | 153 +++++++++++++++++++++ dali/devel-api/actors/actor-devel.h | 105 ++++++++++++++ dali/devel-api/actors/layer-devel.h | 52 +++++++ dali/devel-api/file.list | 4 + dali/internal/event/actors/actor-impl.cpp | 32 +++++ dali/internal/event/actors/actor-impl.h | 4 +- .../manager/render-instruction-processor.cpp | 2 +- dali/internal/update/nodes/node.cpp | 4 +- dali/internal/update/nodes/node.h | 32 ++++- 9 files changed, 377 insertions(+), 11 deletions(-) create mode 100644 dali/devel-api/actors/actor-devel.h create mode 100644 dali/devel-api/actors/layer-devel.h diff --git a/automated-tests/src/dali/utc-Dali-Renderer.cpp b/automated-tests/src/dali/utc-Dali-Renderer.cpp index 6591dd9..ea9db2c 100644 --- a/automated-tests/src/dali/utc-Dali-Renderer.cpp +++ b/automated-tests/src/dali/utc-Dali-Renderer.cpp @@ -16,6 +16,8 @@ */ // EXTERNAL INCLUDES +#include + #include #include #include @@ -1645,6 +1647,157 @@ int UtcDaliRendererRenderOrder2DLayerMultipleRenderers(void) END_TEST; } +int UtcDaliRendererRenderOrder2DLayerDepthIndex(void) +{ + TestApplication application; + tet_infoline("Test the rendering order in a 2D layer is correct using multiple renderers per actor"); + + /* + * Creates the following hierarchy: + * + * Layer + * / \ + * / \ + * / \ + * / \ + * / \ + * actor0 (SIBLING_ORDER:1) actor1 (SIBLING_ORDER:0) + * / | \ / | \ + * / | \ / | \ + * / | \ / | \ + * renderer0 renderer1 actor2 renderer2 renderer3 renderer4 + * | + * | + * renderer5 + * + * actor0 has sibling order 1 + * actor1 has sibling order 0 + * actor2 has sibling order 0 + * + * renderer0 has depth index 2 + * renderer1 has depth index 0 + * + * renderer2 has depth index 0 + * renderer3 has depth index 1 + * renderer4 has depth index 2 + * + * renderer5 has depth index -1 + * + * Expected rendering order: renderer2 - renderer3 - renderer4 - renderer1 - renderer0 - renderer5 + */ + + 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); + actor0.SetProperty( Dali::DevelActor::Property::SIBLING_ORDER, 1 ); + DALI_TEST_EQUALS( actor0.GetProperty( 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( 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( 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); + + //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); + + + TestGlAbstraction& gl = application.GetGlAbstraction(); + gl.EnableTextureCallTrace(true); + application.SendNotification(); + application.Render(0); + + int textureBindIndex[6]; + for( unsigned int i(0); i<6; ++i ) + { + std::stringstream params; + params << GL_TEXTURE_2D<<", "< + +namespace Dali +{ + +namespace DevelActor +{ + +namespace Property +{ + +enum Type +{ + PARENT_ORIGIN = Dali::Actor::Property::PARENT_ORIGIN, + PARENT_ORIGIN_X = Dali::Actor::Property::PARENT_ORIGIN_X, + PARENT_ORIGIN_Y = Dali::Actor::Property::PARENT_ORIGIN_Y, + PARENT_ORIGIN_Z = Dali::Actor::Property::PARENT_ORIGIN_Z, + ANCHOR_POINT = Dali::Actor::Property::ANCHOR_POINT, + ANCHOR_POINT_X = Dali::Actor::Property::ANCHOR_POINT_X, + ANCHOR_POINT_Y = Dali::Actor::Property::ANCHOR_POINT_Y, + ANCHOR_POINT_Z = Dali::Actor::Property::ANCHOR_POINT_Z, + SIZE = Dali::Actor::Property::SIZE, + SIZE_WIDTH = Dali::Actor::Property::SIZE_WIDTH, + SIZE_HEIGHT = Dali::Actor::Property::SIZE_HEIGHT, + SIZE_DEPTH = Dali::Actor::Property::SIZE_DEPTH, + POSITION = Dali::Actor::Property::POSITION, + POSITION_X = Dali::Actor::Property::POSITION_X, + POSITION_Y = Dali::Actor::Property::POSITION_Y, + POSITION_Z = Dali::Actor::Property::POSITION_Z, + WORLD_POSITION = Dali::Actor::Property::WORLD_POSITION, + WORLD_POSITION_X = Dali::Actor::Property::WORLD_POSITION_X, + WORLD_POSITION_Y = Dali::Actor::Property::WORLD_POSITION_Y, + WORLD_POSITION_Z = Dali::Actor::Property::WORLD_POSITION_Z, + ORIENTATION = Dali::Actor::Property::ORIENTATION, + WORLD_ORIENTATION = Dali::Actor::Property::WORLD_ORIENTATION, + SCALE = Dali::Actor::Property::SCALE, + SCALE_X = Dali::Actor::Property::SCALE_X, + SCALE_Y = Dali::Actor::Property::SCALE_Y, + SCALE_Z = Dali::Actor::Property::SCALE_Z, + WORLD_SCALE = Dali::Actor::Property::WORLD_SCALE, + VISIBLE = Dali::Actor::Property::VISIBLE, + COLOR = Dali::Actor::Property::COLOR, + COLOR_RED = Dali::Actor::Property::COLOR_RED, + COLOR_GREEN = Dali::Actor::Property::COLOR_GREEN, + COLOR_BLUE = Dali::Actor::Property::COLOR_BLUE, + COLOR_ALPHA = Dali::Actor::Property::COLOR_ALPHA, + WORLD_COLOR = Dali::Actor::Property::WORLD_COLOR, + WORLD_MATRIX = Dali::Actor::Property::WORLD_MATRIX, + NAME = Dali::Actor::Property::NAME, + SENSITIVE = Dali::Actor::Property::SENSITIVE, + LEAVE_REQUIRED = Dali::Actor::Property::LEAVE_REQUIRED, + INHERIT_ORIENTATION = Dali::Actor::Property::INHERIT_ORIENTATION, + INHERIT_SCALE = Dali::Actor::Property::INHERIT_SCALE, + COLOR_MODE = Dali::Actor::Property::COLOR_MODE, + POSITION_INHERITANCE = Dali::Actor::Property::POSITION_INHERITANCE, + DRAW_MODE = Dali::Actor::Property::DRAW_MODE, + SIZE_MODE_FACTOR = Dali::Actor::Property::SIZE_MODE_FACTOR, + WIDTH_RESIZE_POLICY = Dali::Actor::Property::WIDTH_RESIZE_POLICY, + HEIGHT_RESIZE_POLICY = Dali::Actor::Property::HEIGHT_RESIZE_POLICY, + SIZE_SCALE_POLICY = Dali::Actor::Property::SIZE_SCALE_POLICY, + WIDTH_FOR_HEIGHT = Dali::Actor::Property::WIDTH_FOR_HEIGHT, + HEIGHT_FOR_WIDTH = Dali::Actor::Property::HEIGHT_FOR_WIDTH, + PADDING = Dali::Actor::Property::PADDING, + MINIMUM_SIZE = Dali::Actor::Property::MINIMUM_SIZE, + MAXIMUM_SIZE = Dali::Actor::Property::MAXIMUM_SIZE, + INHERIT_POSITION = Dali::Actor::Property::INHERIT_POSITION, + CLIPPING_MODE = Dali::Actor::Property::CLIPPING_MODE, + + /** + * @brief name "batchParent", type BOOLEAN + * @see Batching + * @note The default value is 'false' + */ + BATCH_PARENT = CLIPPING_MODE + 1, + SIBLING_ORDER = CLIPPING_MODE + 2, +}; + +} // namespace Property + +} // namespace DevelActor + +} // namespace Dali + +#endif // DALI_ACTOR_DEVEL_H diff --git a/dali/devel-api/actors/layer-devel.h b/dali/devel-api/actors/layer-devel.h new file mode 100644 index 0000000..47e7a02 --- /dev/null +++ b/dali/devel-api/actors/layer-devel.h @@ -0,0 +1,52 @@ +#ifndef DALI_LAYER_DEVEL_H +#define DALI_LAYER_DEVEL_H + +/* + * Copyright (c) 2016 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. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace DevelLayer +{ + + /** + * @brief TREE_DEPTH_MULTIPLIER is used by the rendering sorting algorithm to decide which actors to render first. + * @SINCE_1_0.0 + */ + enum TreeDepthMultiplier + { + TREE_DEPTH_MULTIPLIER = 1000000, + }; + + /** + * @brief SIBLING_ORDER_MULTIPLIER is used by the rendering sorting algorithm to decide which actors to render first. + * @SINCE_1_2.16 + */ + enum SiblingOrderMultiplier + { + SIBLING_ORDER_MULTIPLIER = 1000, + }; + +} + +} + +#endif //DALI_LAYER_DEVEL_H diff --git a/dali/devel-api/file.list b/dali/devel-api/file.list index 3543712..6094b7c 100644 --- a/dali/devel-api/file.list +++ b/dali/devel-api/file.list @@ -18,6 +18,10 @@ devel_api_src_files = \ # Add devel header files here DALi internal developer files used by Adaptor & Toolkit +devel_api_core_actors_header_files = \ + $(devel_api_src_dir)/actors/actor-devel.h \ + $(devel_api_src_dir)/actors/layer-devel.h + devel_api_core_animation_header_files = \ $(devel_api_src_dir)/animation/animation-data.h \ $(devel_api_src_dir)/animation/path-constrainer.h diff --git a/dali/internal/event/actors/actor-impl.cpp b/dali/internal/event/actors/actor-impl.cpp index 4f8b8f0..753bf7a 100644 --- a/dali/internal/event/actors/actor-impl.cpp +++ b/dali/internal/event/actors/actor-impl.cpp @@ -24,6 +24,8 @@ #include // INTERNAL INCLUDES +#include +#include #include #include #include @@ -353,6 +355,10 @@ 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::TREE_DEPTH_MULTIPLIER + siblingOrder * Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER; +} } // unnamed namespace @@ -1966,6 +1972,7 @@ Actor::Actor( DerivedType derivedType ) mName(), mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved mDepth( 0u ), + mSiblingOrder(0u), mIsRoot( ROOT_LAYER == derivedType ), mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ), mIsOnStage( false ), @@ -2066,6 +2073,7 @@ void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned in mIsOnStage = true; mDepth = depth; + SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) ); ConnectToSceneGraph(); @@ -2657,6 +2665,24 @@ void Actor::SetDefaultProperty( Property::Index index, const Property::Value& pr break; } + case Dali::DevelActor::Property::SIBLING_ORDER: + { + int value; + + if( property.Get( value ) ) + { + if( static_cast(value) != mSiblingOrder ) + { + mSiblingOrder = value; + if( mIsOnStage ) + { + SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) ); + } + } + } + break; + } + case Dali::Actor::Property::CLIPPING_MODE: { ClippingMode::Type convertedValue = mClippingMode; @@ -3168,6 +3194,12 @@ Property::Value Actor::GetDefaultProperty( Property::Index index ) const break; } + case Dali::DevelActor::Property::SIBLING_ORDER: + { + value = static_cast(mSiblingOrder); + break; + } + default: { DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here diff --git a/dali/internal/event/actors/actor-impl.h b/dali/internal/event/actors/actor-impl.h index e406bb0..5e9b6ab 100644 --- a/dali/internal/event/actors/actor-impl.h +++ b/dali/internal/event/actors/actor-impl.h @@ -1815,7 +1815,9 @@ 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 - unsigned short mDepth :12; ///< Cached: The depth in the hierarchy of the actor. Only 4096 levels of depth are supported + 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 + const bool mIsRoot : 1; ///< Flag to identify the root actor const bool mIsLayer : 1; ///< Flag to identify that this is a layer bool mIsOnStage : 1; ///< Flag to identify whether the actor is on-stage diff --git a/dali/internal/update/manager/render-instruction-processor.cpp b/dali/internal/update/manager/render-instruction-processor.cpp index bbb216a..560dcf1 100644 --- a/dali/internal/update/manager/render-instruction-processor.cpp +++ b/dali/internal/update/manager/render-instruction-processor.cpp @@ -205,7 +205,7 @@ inline void AddRendererToRenderList( BufferIndex updateBufferIndex, if( !isLayer3d ) { - item.mDepthIndex += static_cast( renderable.mNode->GetDepth() ) * Dali::Layer::TREE_DEPTH_MULTIPLIER; + item.mDepthIndex += renderable.mNode->GetDepthIndex(); } // Save ModelView matrix onto the item. diff --git a/dali/internal/update/nodes/node.cpp b/dali/internal/update/nodes/node.cpp index e873a6f..1465543 100644 --- a/dali/internal/update/nodes/node.cpp +++ b/dali/internal/update/nodes/node.cpp @@ -69,8 +69,8 @@ Node::Node() mExclusiveRenderTask( NULL ), mChildren(), mClippingDepth( 0u ), + mDepthIndex( 0u ), mRegenerateUniformMap( 0 ), - mDepth( 0u ), mDirtyFlags( AllFlags ), mDrawMode( DrawMode::NORMAL ), mColorMode( DEFAULT_COLOR_MODE ), @@ -262,7 +262,6 @@ void Node::SetParent(Node& parentNode) DALI_ASSERT_ALWAYS(mParent == NULL); mParent = &parentNode; - mDepth = mParent->GetDepth() + 1u; if( mTransformId != INVALID_TRANSFORM_ID ) { @@ -286,7 +285,6 @@ void Node::RecursiveDisconnectFromSceneGraph( BufferIndex updateBufferIndex ) // Remove back-pointer to parent mParent = NULL; - mDepth = 0u; // Remove all child pointers mChildren.Clear(); diff --git a/dali/internal/update/nodes/node.h b/dali/internal/update/nodes/node.h index 0712b53..01bc76f 100644 --- a/dali/internal/update/nodes/node.h +++ b/dali/internal/update/nodes/node.h @@ -736,10 +736,18 @@ public: return ( this == rhs ); } - unsigned short GetDepth() const - { - return mDepth; - } + /** + * @brief Sets the sibling order of the node + * @param[in] order The new order + */ + void SetDepthIndex( unsigned int depthIndex ){ mDepthIndex = depthIndex; } + + /** + * @brief Get the depth index of the node + * @return Current depth index + */ + unsigned int GetDepthIndex(){ return mDepthIndex; } + public: /** @@ -871,10 +879,11 @@ protected: CollectedUniformMap mCollectedUniformMap[2]; ///< Uniform maps of the node unsigned int mUniformMapChanged[2]; ///< Records if the uniform map has been altered this frame uint32_t mClippingDepth; ///< The number of clipping nodes deep this node is - unsigned int mRegenerateUniformMap:2; ///< Indicate if the uniform map has to be regenerated this frame + + uint32_t mDepthIndex; ///< Depth index of the node // flags, compressed to bitfield - unsigned short mDepth:12; ///< Depth in the hierarchy + unsigned int mRegenerateUniformMap:2; ///< Indicate if the uniform map has to be regenerated this frame int mDirtyFlags:8; ///< A composite set of flags for each of the Node properties DrawMode::Type mDrawMode:2; ///< How the Node and its children should be drawn ColorMode mColorMode:2; ///< Determines whether mWorldColor is inherited, 2 bits is enough @@ -986,6 +995,17 @@ inline void RemoveRendererMessage( EventThreadServices& eventThreadServices, con new (slot) LocalType( &node, &Node::RemoveRenderer, renderer ); } +inline void SetDepthIndexMessage( EventThreadServices& eventThreadServices, const Node& node, unsigned int depthIndex ) +{ + typedef MessageValue1< Node, unsigned int > LocalType; + + // Reserve some memory inside the message queue + unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) ); + + // Construct message in the message queue memory; note that delete should not be called on the return value + new (slot) LocalType( &node, &Node::SetDepthIndex, depthIndex ); +} + inline void SetClippingModeMessage( EventThreadServices& eventThreadServices, const Node& node, ClippingMode::Type clippingMode ) { typedef MessageValue1< Node, ClippingMode::Type > LocalType; -- 2.7.4