From: Tom Robinson Date: Fri, 18 Mar 2016 17:05:28 +0000 (+0000) Subject: [3.0] Clipping API feature in Actor X-Git-Tag: accepted/tizen/3.0/ivi/20161011.043719~3 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-core.git;a=commitdiff_plain;h=9ac94c145f620fc90c39a0f3dadbd88cc4b01940 [3.0] Clipping API feature in Actor A clipping mode property has been added to Actor. This property controls how the actor will clip its children against it. Property: Actor::Property::ClippingMode / "clippingMode" Change-Id: I5f787d6986dc87089566b7a1f721ec4f4ae74b46 Values: DISABLED This Actor will not clip its children. CLIP_CHILDREN This Actor will clip all children to its contents (the actor will also be visible itself). --- diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.cpp index 3f2e6e5..0054e59 100644 --- a/automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.cpp +++ b/automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.cpp @@ -130,6 +130,18 @@ bool TraceCallStack::FindMethodAndParams(std::string method, const NamedParams& return FindIndexFromMethodAndParams( method, params ) > -1; } +bool TraceCallStack::FindMethodAndParamsFromStartIndex( std::string method, std::string params, size_t& startIndex ) const +{ + for( size_t i = startIndex; i < mCallStack.size(); ++i ) + { + if( ( mCallStack[i].method.compare( method ) == 0 ) && ( mCallStack[i].paramList.compare( params ) == 0 ) ) + { + startIndex = i; + return true; + } + } + return false; +} /** * Search for a method in the stack with the given parameter list diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.h b/automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.h index 137bfaf..e1882ea 100644 --- a/automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.h +++ b/automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.h @@ -102,6 +102,19 @@ public: bool FindMethodAndParams(std::string method, const NamedParams& params) const; /** + * Search for a method in the stack with the given parameter list. + * The search is done from a given index. + * This allows the order of methods and parameters to be checked. + * @param[in] method The name of the method + * @param[in] params A comma separated list of parameter values + * @param[in/out] startIndex The method index to start looking from. + * This is updated if a method is found so subsequent + * calls can search for methods occuring after this one. + * @return True if the method was in the stack + */ + bool FindMethodAndParamsFromStartIndex( std::string method, std::string params, size_t& startIndex ) const; + + /** * Search for a method in the stack with the given parameter list * @param[in] method The name of the method * @param[in] params A comma separated list of parameter values diff --git a/automated-tests/src/dali/utc-Dali-Actor.cpp b/automated-tests/src/dali/utc-Dali-Actor.cpp index f4f3fcc..c9966a4 100644 --- a/automated-tests/src/dali/utc-Dali-Actor.cpp +++ b/automated-tests/src/dali/utc-Dali-Actor.cpp @@ -2500,17 +2500,11 @@ int UtcDaliActorSetDrawMode(void) DALI_TEST_CHECK( DrawMode::OVERLAY_2D == a.GetDrawMode() ); // Check Actor is overlay - a.SetDrawMode( DrawMode::STENCIL ); - app.SendNotification(); - app.Render(1); - - DALI_TEST_CHECK( DrawMode::STENCIL == a.GetDrawMode() ); // Check Actor is stencil, not overlay - a.SetDrawMode( DrawMode::NORMAL ); app.SendNotification(); app.Render(1); - DALI_TEST_CHECK( DrawMode::NORMAL == a.GetDrawMode() ); // Check Actor is not stencil + DALI_TEST_CHECK( DrawMode::NORMAL == a.GetDrawMode() ); // Check Actor is normal END_TEST; } @@ -2855,6 +2849,8 @@ const PropertyStringIndex PROPERTY_TABLE[] = { "padding", Actor::Property::PADDING, Property::VECTOR4 }, { "minimumSize", Actor::Property::MINIMUM_SIZE, Property::VECTOR2 }, { "maximumSize", Actor::Property::MAXIMUM_SIZE, Property::VECTOR2 }, + { "inheritPosition", Actor::Property::INHERIT_POSITION, Property::BOOLEAN }, + { "clippingMode", Actor::Property::CLIPPING_MODE, Property::STRING }, }; const unsigned int PROPERTY_TABLE_COUNT = sizeof( PROPERTY_TABLE ) / sizeof( PROPERTY_TABLE[0] ); } // unnamed namespace @@ -3550,3 +3546,262 @@ int UtcDaliActorRemoveRendererN(void) END_TEST; } + +// Clipping test helper functions: +Actor CreateActorWithContent() +{ + BufferImage image = BufferImage::New( 16u, 16u ); + Actor actor = CreateRenderableActor( image ); + + // Setup dimensions and position so actor is not skipped by culling. + actor.SetResizePolicy( ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS ); + actor.SetSize( 16.0f, 16.0f ); + actor.SetParentOrigin( ParentOrigin::CENTER ); + actor.SetAnchorPoint( AnchorPoint::CENTER ); + + return actor; +} + +void GenerateTrace( TestApplication& application, TraceCallStack& enabledDisableTrace, TraceCallStack& stencilTrace ) +{ + enabledDisableTrace.Reset(); + stencilTrace.Reset(); + enabledDisableTrace.Enable( true ); + stencilTrace.Enable( true ); + + application.SendNotification(); + application.Render(); + + enabledDisableTrace.Enable( false ); + stencilTrace.Enable( false ); +} + +void CheckColorMask( TestGlAbstraction& glAbstraction, bool maskValue ) +{ + const TestGlAbstraction::ColorMaskParams& colorMaskParams = glAbstraction.GetColorMaskParams(); + + DALI_TEST_EQUALS( colorMaskParams.red, maskValue, TEST_LOCATION ); + DALI_TEST_EQUALS( colorMaskParams.green, maskValue, TEST_LOCATION ); + DALI_TEST_EQUALS( colorMaskParams.blue, maskValue, TEST_LOCATION ); + DALI_TEST_EQUALS( colorMaskParams.alpha, maskValue, TEST_LOCATION ); +} + +int UtcDaliActorPropertyClippingP(void) +{ + // This test checks the clippingMode property. + tet_infoline( "Testing Actor::Property::CLIPPING_MODE P" ); + TestApplication application; + + Actor actor = Actor::New(); + + // Check default clippingEnabled value. + Property::Value getValue( actor.GetProperty( Actor::Property::CLIPPING_MODE ) ); + + int value = 0; + bool getValueResult = getValue.Get( value ); + DALI_TEST_CHECK( getValueResult ); + + if( getValueResult ) + { + DALI_TEST_EQUALS( value, ClippingMode::DISABLED, TEST_LOCATION ); + } + + // Check setting the property. + actor.SetProperty( Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_CHILDREN ); + + // Check the new value was set. + getValue = actor.GetProperty( Actor::Property::CLIPPING_MODE ); + getValueResult = getValue.Get( value ); + DALI_TEST_CHECK( getValueResult ); + + if( getValueResult ) + { + DALI_TEST_EQUALS( value, ClippingMode::CLIP_CHILDREN, TEST_LOCATION ); + } + + END_TEST; +} + +int UtcDaliActorPropertyClippingN(void) +{ + // Negative test case for Clipping. + tet_infoline( "Testing Actor::Property::CLIPPING_MODE N" ); + TestApplication application; + + Actor actor = Actor::New(); + + // Check default clippingEnabled value. + Property::Value getValue( actor.GetProperty( Actor::Property::CLIPPING_MODE ) ); + + int value = 0; + bool getValueResult = getValue.Get( value ); + DALI_TEST_CHECK( getValueResult ); + + if( getValueResult ) + { + DALI_TEST_EQUALS( value, ClippingMode::DISABLED, TEST_LOCATION ); + } + + // Check setting an invalid property value won't change the current property value. + actor.SetProperty( Actor::Property::CLIPPING_MODE, "INVALID_PROPERTY" ); + + getValue = actor.GetProperty( Actor::Property::CLIPPING_MODE ); + getValueResult = getValue.Get( value ); + DALI_TEST_CHECK( getValueResult ); + + if( getValueResult ) + { + DALI_TEST_EQUALS( value, ClippingMode::DISABLED, TEST_LOCATION ); + } + + END_TEST; +} + +int UtcDaliActorPropertyClippingActor(void) +{ + // This test checks that an actor is correctly setup for clipping. + tet_infoline( "Testing Actor::Property::CLIPPING_MODE actor" ); + TestApplication application; + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& stencilTrace = glAbstraction.GetStencilFunctionTrace(); + TraceCallStack& enabledDisableTrace = glAbstraction.GetEnableDisableTrace(); + size_t startIndex = 0u; + + // Create a clipping actor. + Actor actorDepth1Clip = CreateActorWithContent(); + actorDepth1Clip.SetProperty( Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_CHILDREN ); + Stage::GetCurrent().Add( actorDepth1Clip ); + + // Gather the call trace. + GenerateTrace( application, enabledDisableTrace, stencilTrace ); + + // Check we are writing to the color buffer. + CheckColorMask( glAbstraction, true ); + + // Check the stencil buffer was enabled. + DALI_TEST_CHECK( enabledDisableTrace.FindMethodAndParams( "Enable", "2960" ) ); // 2960 is GL_STENCIL_TEST + + // Check the stencil buffer was cleared. + DALI_TEST_CHECK( stencilTrace.FindMethodAndParamsFromStartIndex( "ClearStencil", "0", startIndex ) ); + + // Check the correct setup was done to write to the first bit-plane (only) of the stencil buffer. + DALI_TEST_CHECK( stencilTrace.FindMethodAndParamsFromStartIndex( "StencilFunc", "514, 1, 0", startIndex ) ); // 514 is GL_EQUAL, But testing no bit-planes for the first clipping node. + DALI_TEST_CHECK( stencilTrace.FindMethodAndParamsFromStartIndex( "StencilMask", "1", startIndex ) ); + DALI_TEST_CHECK( stencilTrace.FindMethodAndParamsFromStartIndex( "StencilOp", "7680, 7681, 7681", startIndex ) ); // GL_KEEP, GL_REPLACE, GL_REPLACE + + END_TEST; +} + +int UtcDaliActorPropertyClippingNestedChildren(void) +{ + // This test checks that a hierarchy of actors are clipped correctly by + // writing to and reading from the correct bit-planes of the stencil buffer. + tet_infoline( "Testing Actor::Property::CLIPPING_MODE nested children" ); + TestApplication application; + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& stencilTrace = glAbstraction.GetStencilFunctionTrace(); + TraceCallStack& enabledDisableTrace = glAbstraction.GetEnableDisableTrace(); + + // Create a clipping actor. + Actor actorDepth1Clip = CreateActorWithContent(); + actorDepth1Clip.SetProperty( Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_CHILDREN ); + Stage::GetCurrent().Add( actorDepth1Clip ); + + // Create a child actor. + Actor childDepth2 = CreateActorWithContent(); + actorDepth1Clip.Add( childDepth2 ); + + // Create another clipping actor. + Actor childDepth2Clip = CreateActorWithContent(); + childDepth2Clip.SetProperty( Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_CHILDREN ); + childDepth2.Add( childDepth2Clip ); + + // Create another 2 child actors. We do this so 2 nodes will have the same clipping ID. + // This tests the sort algorithm. + Actor childDepth3 = CreateActorWithContent(); + childDepth2Clip.Add( childDepth3 ); + Actor childDepth4 = CreateActorWithContent(); + childDepth3.Add( childDepth4 ); + + // Gather the call trace. + GenerateTrace( application, enabledDisableTrace, stencilTrace ); + + // Check we are writing to the color buffer. + CheckColorMask( glAbstraction, true ); + + // Check the stencil buffer was enabled. + DALI_TEST_CHECK( enabledDisableTrace.FindMethodAndParams( "Enable", "2960" ) ); // 2960 is GL_STENCIL_TEST + + // Perform the test twice, once for 2D layer, and once for 3D. + for( unsigned int i = 0u ; i < 2u; ++i ) + { + size_t startIndex = 0u; + + // Check the stencil buffer was cleared. + DALI_TEST_CHECK( stencilTrace.FindMethodAndParamsFromStartIndex( "ClearStencil", "0", startIndex ) ); + + // Check the correct setup was done to write to the first bit-plane (only) of the stencil buffer. + DALI_TEST_CHECK( stencilTrace.FindMethodAndParamsFromStartIndex( "StencilFunc", "514, 1, 0", startIndex ) ); // 514 is GL_EQUAL, But testing no bit-planes for the first clipping node. + DALI_TEST_CHECK( stencilTrace.FindMethodAndParamsFromStartIndex( "StencilMask", "1", startIndex ) ); // Write to the first bit-plane + DALI_TEST_CHECK( stencilTrace.FindMethodAndParamsFromStartIndex( "StencilOp", "7680, 7681, 7681", startIndex ) ); // GL_KEEP, GL_REPLACE, GL_REPLACE + + // Check the correct setup was done to test against first bit-plane (only) of the stencil buffer. + DALI_TEST_CHECK( stencilTrace.FindMethodAndParamsFromStartIndex( "StencilFunc", "514, 1, 255", startIndex ) ); // 514 is GL_EQUAL + DALI_TEST_CHECK( stencilTrace.FindMethodAndParamsFromStartIndex( "StencilOp", "7680, 7680, 7680", startIndex ) ); // GL_KEEP, GL_KEEP, GL_KEEP + + // Check we are set up to write to the second bitplane of the stencil buffer (only). + DALI_TEST_CHECK( stencilTrace.FindMethodAndParamsFromStartIndex( "StencilFunc", "514, 3, 1", startIndex ) ); // 514 is GL_EQUAL, Test both bit-planes 1 & 2 + DALI_TEST_CHECK( stencilTrace.FindMethodAndParamsFromStartIndex( "StencilMask", "3", startIndex ) ); // Write to second (and previous) bit-planes + DALI_TEST_CHECK( stencilTrace.FindMethodAndParamsFromStartIndex( "StencilOp", "7680, 7681, 7681", startIndex ) ); // GL_KEEP, GL_REPLACE, GL_REPLACE + + // Check we are set up to test against both the first and second bit-planes of the stencil buffer. + // (Both must be set to pass the check). + DALI_TEST_CHECK( stencilTrace.FindMethodAndParamsFromStartIndex( "StencilFunc", "514, 3, 255", startIndex ) ); // 514 is GL_EQUAL, Test both bit-planes 1 & 2 + DALI_TEST_CHECK( stencilTrace.FindMethodAndParamsFromStartIndex( "StencilOp", "7680, 7680, 7680", startIndex ) ); // GL_KEEP, GL_KEEP, GL_KEEP + + // If we are on the first loop, set the layer to 3D and loop to perform the test again. + if( i == 0u ) + { + Stage::GetCurrent().GetRootLayer().SetBehavior( Layer::LAYER_3D ); + GenerateTrace( application, enabledDisableTrace, stencilTrace ); + } + } + + END_TEST; +} + +int UtcDaliActorPropertyClippingActorWithRendererOverride(void) +{ + // This test checks that an actor with clipping will be ignored if overridden by the Renderer properties. + tet_infoline( "Testing Actor::Property::CLIPPING_MODE actor with renderer override" ); + TestApplication application; + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& stencilTrace = glAbstraction.GetStencilFunctionTrace(); + TraceCallStack& enabledDisableTrace = glAbstraction.GetEnableDisableTrace(); + + // Create a clipping actor. + Actor actorDepth1Clip = CreateActorWithContent(); + actorDepth1Clip.SetProperty( Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_CHILDREN ); + Stage::GetCurrent().Add( actorDepth1Clip ); + + // Turn the RenderMode to just "COLOR" at the Renderer level to ignore the clippingMode. + actorDepth1Clip.GetRendererAt( 0 ).SetProperty( Renderer::Property::RENDER_MODE, RenderMode::COLOR ); + + // Gather the call trace. + GenerateTrace( application, enabledDisableTrace, stencilTrace ); + + // Check we are writing to the color buffer. + CheckColorMask( glAbstraction, true ); + + // Check the stencil buffer was not enabled. + DALI_TEST_CHECK( !enabledDisableTrace.FindMethodAndParams( "Enable", "2960" ) ); // 2960 is GL_STENCIL_TEST + + // Check stencil functions are not called. + DALI_TEST_CHECK( !stencilTrace.FindMethod( "StencilFunc" ) ); + DALI_TEST_CHECK( !stencilTrace.FindMethod( "StencilMask" ) ); + DALI_TEST_CHECK( !stencilTrace.FindMethod( "StencilOp" ) ); + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-HitTestAlgorithm.cpp b/automated-tests/src/dali/utc-Dali-HitTestAlgorithm.cpp index 99d16c4..b4cd632 100644 --- a/automated-tests/src/dali/utc-Dali-HitTestAlgorithm.cpp +++ b/automated-tests/src/dali/utc-Dali-HitTestAlgorithm.cpp @@ -361,7 +361,7 @@ int UtcDaliHitTestAlgorithmOrtho02(void) END_TEST; } -int UtcDaliHitTestAlgorithmStencil(void) +int UtcDaliHitTestAlgorithmClippingActor(void) { TestApplication application; tet_infoline("Testing Dali::HitTestAlgorithm with a stencil"); @@ -377,42 +377,38 @@ int UtcDaliHitTestAlgorithmStencil(void) layer.SetName( "layer" ); stage.Add( layer ); - // Create a stencil and add that to the layer - Actor stencil = CreateRenderableActor(Dali::BufferImage::WHITE() ); - stencil.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - stencil.SetParentOrigin( ParentOrigin::TOP_LEFT ); - stencil.SetSize( 50.0f, 50.0f ); - stencil.SetDrawMode( DrawMode::STENCIL ); - stencil.SetName( "stencil" ); - layer.Add( stencil ); - - // Create a renderable actor and add that to the layer - Actor layerHitActor = CreateRenderableActor( Dali::BufferImage::WHITE() ); - layerHitActor.SetSize( 100.0f, 100.0f ); - layerHitActor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - layerHitActor.SetParentOrigin( ParentOrigin::TOP_LEFT ); - layerHitActor.SetName( "layerHitActor" ); - layer.Add( layerHitActor ); + // Create a clipping actor and add it to the layer. + Actor clippingActor = CreateRenderableActor( Dali::BufferImage::WHITE() ); + clippingActor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + clippingActor.SetParentOrigin( ParentOrigin::TOP_LEFT ); + clippingActor.SetSize( 50.0f, 50.0f ); + clippingActor.SetProperty( Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_CHILDREN ); + clippingActor.SetName( "clippingActor" ); + layer.Add( clippingActor ); + + // Create a renderable actor and add it to the clipping actor. + Actor childActor = CreateRenderableActor( Dali::BufferImage::WHITE() ); + childActor.SetSize( 100.0f, 100.0f ); + childActor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + childActor.SetParentOrigin( ParentOrigin::TOP_LEFT ); + childActor.SetName( "childActor" ); + clippingActor.Add( childActor ); // Render and notify application.SendNotification(); application.Render(); - // Hit within stencil and actor - { - HitTestAlgorithm::Results results; - HitTest(stage, Vector2( 10.0f, 10.0f ), results, &DefaultIsActorTouchableFunction); - DALI_TEST_CHECK( results.actor == layerHitActor ); - tet_printf( "Hit: %s\n", ( results.actor ? results.actor.GetName().c_str() : "NULL" ) ); - } + // Hit within clippingActor and childActor. + HitTestAlgorithm::Results results; + HitTest( stage, Vector2( 10.0f, 10.0f ), results, &DefaultIsActorTouchableFunction ); + DALI_TEST_CHECK( results.actor == childActor ); + tet_printf( "Hit: %s\n", ( results.actor ? results.actor.GetName().c_str() : "NULL" ) ); + + // Hit within childActor but outside of clippingActor, should hit the root-layer instead. + HitTest( stage, Vector2( 60.0f, 60.0f ), results, &DefaultIsActorTouchableFunction); + DALI_TEST_CHECK( results.actor == rootLayer ); + tet_printf( "Hit: %s\n", ( results.actor ? results.actor.GetName().c_str() : "NULL" ) ); - // Hit within actor but outside of stencil, should hit the root-layer - { - HitTestAlgorithm::Results results; - HitTest(stage, Vector2( 60.0f, 60.0f ), results, &DefaultIsActorTouchableFunction); - DALI_TEST_CHECK( results.actor == rootLayer ); - tet_printf( "Hit: %s\n", ( results.actor ? results.actor.GetName().c_str() : "NULL" ) ); - } END_TEST; } diff --git a/automated-tests/src/dali/utc-Dali-HoverProcessing.cpp b/automated-tests/src/dali/utc-Dali-HoverProcessing.cpp index 7dd76a6..fd4a7e5 100644 --- a/automated-tests/src/dali/utc-Dali-HoverProcessing.cpp +++ b/automated-tests/src/dali/utc-Dali-HoverProcessing.cpp @@ -1248,38 +1248,37 @@ int UtcDaliHoverLeaveActorReadded(void) END_TEST; } - -int UtcDaliHoverStencilNonRenderableActor(void) +int UtcDaliHoverClippingActor(void) { TestApplication application; Stage stage = Stage::GetCurrent(); Actor actor = Actor::New(); - actor.SetSize(100.0f, 100.0f); - actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); - stage.Add(actor); + actor.SetSize( 100.0f, 100.0f ); + actor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + stage.Add( actor ); - Actor stencil = Actor::New(); - stencil.SetSize(50.0f, 50.0f); - stencil.SetAnchorPoint(AnchorPoint::TOP_LEFT); - stencil.SetDrawMode( DrawMode::STENCIL ); - stage.Add(stencil); + Actor clippingActor = Actor::New(); + clippingActor.SetSize( 50.0f, 50.0f ); + clippingActor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + clippingActor.SetProperty( Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_CHILDREN ); + stage.Add( clippingActor ); - // Render and notify + // Render and notify. application.SendNotification(); application.Render(); - // Connect to actor's hovered signal + // Connect to actor's hovered signal. SignalData data; HoverEventFunctor functor( data ); actor.HoveredSignal().Connect( &application, functor ); - // Emit an event within stencil area + // Emit an event within clipped area. application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); data.Reset(); - // Emit an event outside the stencil area but within the actor area, we should have a hit! + // Emit an event outside the clipped area but within the actor area, we should have a hit. application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 60.0f, 60.0f ) ) ); DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); data.Reset(); diff --git a/automated-tests/src/dali/utc-Dali-Layer.cpp b/automated-tests/src/dali/utc-Dali-Layer.cpp index 34c5741..7b31004 100644 --- a/automated-tests/src/dali/utc-Dali-Layer.cpp +++ b/automated-tests/src/dali/utc-Dali-Layer.cpp @@ -583,3 +583,58 @@ int UtcDaliLayerBehaviour(void) DALI_TEST_EQUALS( layer.GetBehavior(), Dali::Layer::LAYER_3D, TEST_LOCATION ); END_TEST; } + +Actor CreateActor( bool withAlpha ) +{ + Dali::BufferImage bufferImage; + + if( withAlpha ) + { + bufferImage = Dali::BufferImage::WHITE(); + } + else + { + bufferImage = BufferImage::New( 1u, 1u, Pixel::RGB888, Dali::Image::NEVER ); + PixelBuffer* pBuffer = bufferImage.GetBuffer(); + if( pBuffer ) + { + pBuffer[0] = pBuffer[1] = pBuffer[2] = 0xFF; + } + } + + Actor actor = CreateRenderableActor( bufferImage ); + actor.SetParentOrigin( ParentOrigin::CENTER ); + actor.SetAnchorPoint( AnchorPoint::CENTER ); + + return actor; +} + +int UtcDaliLayer3DSort(void) +{ + tet_infoline( "Testing LAYER_3D sort coverage test" ); + TestApplication application; + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& enabledDisableTrace = glAbstraction.GetEnableDisableTrace(); + + Stage::GetCurrent().GetRootLayer().SetBehavior( Layer::LAYER_3D ); + + // Create an actor. + Actor actor = CreateActor( false ); + Stage::GetCurrent().Add( actor ); + + // Create child actors. + Actor child1 = CreateActor( true ); + actor.Add( child1 ); + Actor child2 = CreateActor( false ); + child1.Add( child2 ); + + enabledDisableTrace.Reset(); + enabledDisableTrace.Enable( true ); + application.SendNotification(); + application.Render(); + enabledDisableTrace.Enable( false ); + + DALI_TEST_CHECK( enabledDisableTrace.FindMethodAndParams( "Enable", "2929" ) ); // 2929 is GL_DEPTH_TEST + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-Renderer.cpp b/automated-tests/src/dali/utc-Dali-Renderer.cpp index 0d93f91..6591dd9 100644 --- a/automated-tests/src/dali/utc-Dali-Renderer.cpp +++ b/automated-tests/src/dali/utc-Dali-Renderer.cpp @@ -2292,6 +2292,9 @@ int UtcDaliRendererSetRenderModeToUseStencilBuffer(void) DALI_TEST_CHECK( glStencilFunctionStack.FindMethod( methodString ) ); // Test the COLOR_STENCIL RenderMode as it also enables the stencil buffer. + // First set a mode to turn off the stencil buffer, so the enable is required. + renderer.SetProperty( Renderer::Property::RENDER_MODE, RenderMode::COLOR ); + ResetDebugAndFlush( application, glEnableDisableStack, glStencilFunctionStack ); renderer.SetProperty( Renderer::Property::RENDER_MODE, RenderMode::COLOR_STENCIL ); ResetDebugAndFlush( application, glEnableDisableStack, glStencilFunctionStack ); diff --git a/automated-tests/src/dali/utc-Dali-Scripting.cpp b/automated-tests/src/dali/utc-Dali-Scripting.cpp index e76ff62..12e50d0 100644 --- a/automated-tests/src/dali/utc-Dali-Scripting.cpp +++ b/automated-tests/src/dali/utc-Dali-Scripting.cpp @@ -49,8 +49,7 @@ const unsigned int POSITION_INHERITANCE_MODE_VALUES_COUNT = sizeof( POSITION_INH const StringEnum DRAW_MODE_VALUES[] = { { "NORMAL", DrawMode::NORMAL }, - { "OVERLAY_2D", DrawMode::OVERLAY_2D }, - { "STENCIL", DrawMode::STENCIL }, + { "OVERLAY_2D", DrawMode::OVERLAY_2D } }; const unsigned int DRAW_MODE_VALUES_COUNT = sizeof( DRAW_MODE_VALUES ) / sizeof( DRAW_MODE_VALUES[0] ); @@ -484,7 +483,7 @@ int UtcDaliScriptingNewActorProperties(void) map[ "sensitive" ] = false; map[ "leaveRequired" ] = true; map[ "positionInheritance" ] = "DONT_INHERIT_POSITION"; - map[ "drawMode" ] = "STENCIL"; + map[ "drawMode" ] = "OVERLAY_2D"; map[ "inheritOrientation" ] = false; map[ "inheritScale" ] = false; @@ -507,7 +506,7 @@ int UtcDaliScriptingNewActorProperties(void) DALI_TEST_EQUALS( handle.IsSensitive(), false, TEST_LOCATION ); DALI_TEST_EQUALS( handle.GetLeaveRequired(), true, TEST_LOCATION ); DALI_TEST_EQUALS( handle.GetPositionInheritanceMode(), DONT_INHERIT_POSITION, TEST_LOCATION ); - DALI_TEST_EQUALS( handle.GetDrawMode(), DrawMode::STENCIL, TEST_LOCATION ); + DALI_TEST_EQUALS( handle.GetDrawMode(), DrawMode::OVERLAY_2D, TEST_LOCATION ); DALI_TEST_EQUALS( handle.IsOrientationInherited(), false, TEST_LOCATION ); DALI_TEST_EQUALS( handle.IsScaleInherited(), false, TEST_LOCATION ); diff --git a/automated-tests/src/dali/utc-Dali-TouchDataProcessing.cpp b/automated-tests/src/dali/utc-Dali-TouchDataProcessing.cpp index 36e8488..9b519d3 100644 --- a/automated-tests/src/dali/utc-Dali-TouchDataProcessing.cpp +++ b/automated-tests/src/dali/utc-Dali-TouchDataProcessing.cpp @@ -1526,37 +1526,37 @@ int UtcDaliTouchDataLeaveActorReadded(void) END_TEST; } -int UtcDaliTouchDataStencilNonRenderableActor(void) +int UtcDaliTouchDataClippedActor(void) { TestApplication application; Stage stage = Stage::GetCurrent(); Actor actor = Actor::New(); - actor.SetSize(100.0f, 100.0f); - actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); - stage.Add(actor); + actor.SetSize( 100.0f, 100.0f ); + actor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + stage.Add( actor ); - Actor stencil = Actor::New(); - stencil.SetSize(50.0f, 50.0f); - stencil.SetAnchorPoint(AnchorPoint::TOP_LEFT); - stencil.SetDrawMode( DrawMode::STENCIL ); - stage.Add(stencil); + Actor clippingActor = Actor::New(); + clippingActor.SetSize( 50.0f, 50.0f ); + clippingActor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + clippingActor.SetProperty( Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_CHILDREN ); + stage.Add( clippingActor ); - // Render and notify + // Render and notify. application.SendNotification(); application.Render(); - // Connect to actor's touched signal + // Connect to actor's touch signal. SignalData data; TouchDataFunctor functor( data ); actor.TouchSignal().Connect( &application, functor ); - // Emit an event within stencil area + // Emit an event within clipped area. application.ProcessEvent( GenerateSingleTouch( PointState::DOWN, Vector2( 10.0f, 10.0f ) ) ); DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); data.Reset(); - // Emit an event outside the stencil area but within the actor area, we should have a hit! + // Emit an event outside the clipped area but within the actor area, we should have a hit. application.ProcessEvent( GenerateSingleTouch( PointState::DOWN, Vector2( 60.0f, 60.0f ) ) ); DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); data.Reset(); diff --git a/automated-tests/src/dali/utc-Dali-TouchProcessing.cpp b/automated-tests/src/dali/utc-Dali-TouchProcessing.cpp index 998b8ec..82d514b 100644 --- a/automated-tests/src/dali/utc-Dali-TouchProcessing.cpp +++ b/automated-tests/src/dali/utc-Dali-TouchProcessing.cpp @@ -1300,37 +1300,37 @@ int UtcDaliTouchLeaveActorReadded(void) END_TEST; } -int UtcDaliTouchStencilNonRenderableActor(void) +int UtcDaliTouchClippingActor(void) { TestApplication application; Stage stage = Stage::GetCurrent(); Actor actor = Actor::New(); - actor.SetSize(100.0f, 100.0f); - actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); - stage.Add(actor); + actor.SetSize( 100.0f, 100.0f ); + actor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + stage.Add( actor ); - Actor stencil = Actor::New(); - stencil.SetSize(50.0f, 50.0f); - stencil.SetAnchorPoint(AnchorPoint::TOP_LEFT); - stencil.SetDrawMode( DrawMode::STENCIL ); - stage.Add(stencil); + Actor clippingActor = Actor::New(); + clippingActor.SetSize( 50.0f, 50.0f ); + clippingActor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + clippingActor.SetProperty( Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_CHILDREN ); + stage.Add( clippingActor ); - // Render and notify + // Render and notify. application.SendNotification(); application.Render(); - // Connect to actor's touched signal + // Connect to actor's touched signal. SignalData data; TouchEventFunctor functor( data ); actor.TouchedSignal().Connect( &application, functor ); - // Emit an event within stencil area + // Emit an event within clipped area. application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); data.Reset(); - // Emit an event outside the stencil area but within the actor area, we should have a hit! + // Emit an event outside the clipped area but within the actor area, we should have a hit. application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 60.0f, 60.0f ) ) ); DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); data.Reset(); diff --git a/dali/internal/common/core-impl.cpp b/dali/internal/common/core-impl.cpp index 313fa72..7f2bc71 100644 --- a/dali/internal/common/core-impl.cpp +++ b/dali/internal/common/core-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * 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. @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -116,6 +117,8 @@ Core::Core( RenderController& renderController, PlatformAbstraction& platform, mRenderManager = RenderManager::New( glAbstraction, glSyncAbstraction, *mTextureUploadedQueue ); + mRenderTaskProcessor = new SceneGraph::RenderTaskProcessor(); + RenderQueue& renderQueue = mRenderManager->GetRenderQueue(); TextureCache& textureCache = mRenderManager->GetTextureCache(); @@ -145,7 +148,8 @@ Core::Core( RenderController& renderController, PlatformAbstraction& platform, renderController, *mRenderManager, renderQueue, - *mTextureCacheDispatcher ); + *mTextureCacheDispatcher, + *mRenderTaskProcessor ); mRenderManager->SetShaderSaver( *mUpdateManager ); @@ -210,6 +214,7 @@ Core::~Core() delete mTextureCacheDispatcher; delete mUpdateManager; delete mRenderManager; + delete mRenderTaskProcessor; delete mTextureUploadedQueue; } diff --git a/dali/internal/common/core-impl.h b/dali/internal/common/core-impl.h index b9472cd..61f20fd 100644 --- a/dali/internal/common/core-impl.h +++ b/dali/internal/common/core-impl.h @@ -1,8 +1,8 @@ -#ifndef __DALI_INTERNAL_CORE_H__ -#define __DALI_INTERNAL_CORE_H__ +#ifndef DALI_INTERNAL_CORE_H +#define DALI_INTERNAL_CORE_H /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * 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. @@ -66,6 +66,7 @@ class UpdateManager; class RenderManager; class DiscardQueue; class TextureCacheDispatcher; +class RenderTaskProcessor; } /** @@ -295,6 +296,7 @@ private: ResourceManager* mResourceManager; ///< Asynchronous Resource Loading IntrusivePtr< RelayoutController > mRelayoutController; ///< Size negotiation relayout controller + SceneGraph::RenderTaskProcessor* mRenderTaskProcessor; ///< Handles the processing of render tasks bool mIsActive : 1; ///< Whether Core is active or suspended bool mProcessingEvent : 1; ///< True during ProcessEvents() @@ -306,4 +308,4 @@ private: } // namespace Dali -#endif // __DALI_INTERNAL_CORE_H__ +#endif // DALI_INTERNAL_CORE_H diff --git a/dali/internal/event/actors/actor-impl.cpp b/dali/internal/event/actors/actor-impl.cpp index 5df7b5c..4f8b8f0 100644 --- a/dali/internal/event/actors/actor-impl.cpp +++ b/dali/internal/event/actors/actor-impl.cpp @@ -24,7 +24,6 @@ #include // INTERNAL INCLUDES - #include #include #include @@ -32,9 +31,7 @@ #include #include #include - #include - #include #include #include @@ -144,62 +141,63 @@ namespace // unnamed namespace /** * We want to discourage the use of property strings (minimize string comparisons), * particularly for the default properties. - * Name Type writable animatable constraint-input enum for index-checking + * Name Type writable animatable constraint-input enum for index-checking */ DALI_PROPERTY_TABLE_BEGIN -DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN ) -DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X ) -DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y ) -DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z ) -DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT ) -DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X ) -DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y ) -DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z ) -DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE ) -DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH ) -DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT ) -DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH ) -DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION ) -DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X ) -DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y ) -DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z ) -DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION ) -DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X ) -DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y ) -DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z ) -DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION ) -DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION ) -DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE ) -DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X ) -DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y ) -DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z ) -DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE ) -DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE ) -DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR ) -DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED ) -DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN ) -DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE ) -DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA ) -DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR ) -DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX ) -DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME ) -DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE ) -DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED ) -DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION ) -DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE ) -DALI_PROPERTY( "colorMode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE ) -DALI_PROPERTY( "positionInheritance", STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE ) -DALI_PROPERTY( "drawMode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE ) -DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR ) -DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY ) -DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY ) -DALI_PROPERTY( "sizeScalePolicy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY ) -DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT ) -DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH ) -DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING ) -DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE ) -DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE ) -DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION ) +DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN ) +DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X ) +DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y ) +DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z ) +DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT ) +DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X ) +DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y ) +DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z ) +DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE ) +DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH ) +DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT ) +DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH ) +DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION ) +DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X ) +DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y ) +DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z ) +DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION ) +DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X ) +DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y ) +DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z ) +DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION ) +DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION ) +DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE ) +DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X ) +DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y ) +DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z ) +DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE ) +DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE ) +DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR ) +DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED ) +DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN ) +DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE ) +DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA ) +DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR ) +DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX ) +DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME ) +DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE ) +DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED ) +DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION ) +DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE ) +DALI_PROPERTY( "colorMode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE ) +DALI_PROPERTY( "positionInheritance", STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE ) +DALI_PROPERTY( "drawMode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE ) +DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR ) +DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY ) +DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY ) +DALI_PROPERTY( "sizeScalePolicy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY ) +DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT ) +DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH ) +DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING ) +DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE ) +DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE ) +DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION ) +DALI_PROPERTY( "clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE ) DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX ) // Signals @@ -290,6 +288,12 @@ DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FIT_WITH_ASPECT_RATIO ) DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FILL_WITH_ASPECT_RATIO ) DALI_ENUM_TO_STRING_TABLE_END( SIZE_SCALE_POLICY ) +DALI_ENUM_TO_STRING_TABLE_BEGIN( CLIPPING_MODE ) +DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, DISABLED ) +DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, CLIP_CHILDREN ) +DALI_ENUM_TO_STRING_TABLE_END( CLIPPING_MODE ) + + bool GetAnchorPointConstant( const std::string& value, Vector3& anchor ) { for( unsigned int i = 0; i < ANCHOR_CONSTANT_TABLE_COUNT; ++i ) @@ -1000,6 +1004,11 @@ float Actor::GetCurrentOpacity() const return 1.0f; } +ClippingMode::Type Actor::GetClippingMode() const +{ + return mClippingMode; +} + const Vector4& Actor::GetCurrentWorldColor() const { if( NULL != mNode ) @@ -1504,7 +1513,7 @@ void Actor::SetDrawMode( DrawMode::Type drawMode ) { // this flag is not animatable so keep the value mDrawMode = drawMode; - if( NULL != mNode ) + if( ( NULL != mNode ) && ( drawMode != DrawMode::STENCIL ) ) { // mNode is being used in a separate thread; queue a message to set the value SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode ); @@ -1707,12 +1716,11 @@ bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) con return ( b2 * b2 - a * c ) >= 0.f; } -bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const +bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const { bool hit = false; - if( OnStage() && - NULL != mNode ) + if( OnStage() && NULL != mNode ) { // Transforms the ray to the local reference system. // Calculate the inverse of Model matrix @@ -1974,7 +1982,8 @@ Actor::Actor( DerivedType derivedType ) mInheritScale( true ), mDrawMode( DrawMode::NORMAL ), mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ), - mColorMode( Node::DEFAULT_COLOR_MODE ) + mColorMode( Node::DEFAULT_COLOR_MODE ), + mClippingMode( ClippingMode::DISABLED ) { } @@ -2648,6 +2657,20 @@ void Actor::SetDefaultProperty( Property::Index index, const Property::Value& pr break; } + case Dali::Actor::Property::CLIPPING_MODE: + { + ClippingMode::Type convertedValue = mClippingMode; + if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) ) + { + mClippingMode = convertedValue; + if( NULL != mNode ) + { + SetClippingModeMessage( GetEventThreadServices(), *mNode, mClippingMode ); + } + } + break; + } + default: { // this can happen in the case of a non-animatable default property so just do nothing @@ -3139,6 +3162,12 @@ Property::Value Actor::GetDefaultProperty( Property::Index index ) const break; } + case Dali::Actor::Property::CLIPPING_MODE: + { + value = mClippingMode; + 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 d38493b..e406bb0 100644 --- a/dali/internal/event/actors/actor-impl.h +++ b/dali/internal/event/actors/actor-impl.h @@ -1,5 +1,5 @@ -#ifndef __DALI_INTERNAL_ACTOR_H__ -#define __DALI_INTERNAL_ACTOR_H__ +#ifndef DALI_INTERNAL_ACTOR_H +#define DALI_INTERNAL_ACTOR_H /* * Copyright (c) 2016 Samsung Electronics Co., Ltd. @@ -636,6 +636,12 @@ public: float GetCurrentOpacity() const; /** + * Retrieve the actor's clipping mode. + * @return The actor's clipping mode (cached) + */ + ClippingMode::Type GetClippingMode() const; + + /** * Sets whether an actor should emit touch or hover signals; see SignalTouch() and SignalHover(). * An actor is sensitive by default, which means that as soon as an application connects to the SignalTouch(), * the touch event signal will be emitted, and as soon as an application connects to the SignalHover(), the @@ -1275,7 +1281,7 @@ public: */ bool RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, - Vector4& hitPointLocal, + Vector2& hitPointLocal, float& distance ) const; /** @@ -1827,6 +1833,7 @@ protected: DrawMode::Type mDrawMode : 2; ///< Cached: How the actor and its children should be drawn PositionInheritanceMode mPositionInheritanceMode : 2; ///< Cached: Determines how position is inherited ColorMode mColorMode : 2; ///< Cached: Determines whether mWorldColor is inherited + ClippingMode::Type mClippingMode : 2; ///< Cached: Determines which clipping mode (if any) to use. private: @@ -1859,4 +1866,4 @@ inline const Internal::Actor& GetImplementation( const Dali::Actor& actor ) } // namespace Dali -#endif // __DALI_INTERNAL_ACTOR_H__ +#endif // DALI_INTERNAL_ACTOR_H diff --git a/dali/internal/event/actors/layer-impl.h b/dali/internal/event/actors/layer-impl.h index 0e97f3a..d1ad93d 100644 --- a/dali/internal/event/actors/layer-impl.h +++ b/dali/internal/event/actors/layer-impl.h @@ -1,8 +1,8 @@ -#ifndef __DALI_INTERNAL_LAYER_H__ -#define __DALI_INTERNAL_LAYER_H__ +#ifndef DALI_INTERNAL_LAYER_H +#define DALI_INTERNAL_LAYER_H /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * 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. @@ -335,4 +335,4 @@ inline const Internal::Layer& GetImplementation(const Dali::Layer& layer) } // namespace Dali -#endif //__DALI_INTERNAL_LAYER_H__ +#endif // DALI_INTERNAL_LAYER_H diff --git a/dali/internal/event/events/gesture-processor.cpp b/dali/internal/event/events/gesture-processor.cpp index a196d1a..5ad06df 100644 --- a/dali/internal/event/events/gesture-processor.cpp +++ b/dali/internal/event/events/gesture-processor.cpp @@ -147,12 +147,12 @@ void GestureProcessor::ProcessAndEmit( HitTestAlgorithm::Results& hitTestResults // Ensure tap is within the actor's area if ( actor->RaySphereTest( hitTestResults.rayOrigin, hitTestResults.rayDirection ) ) // Quick check { - Vector4 hitPointLocal; + Vector2 hitPointLocal; float distance( 0.0f ); if( actor->RayActorTest( hitTestResults.rayOrigin, hitTestResults.rayDirection, hitPointLocal, distance ) ) { // One of the parents was the gestured actor so we can emit the signal for that actor. - EmitGestureSignal( actor, gestureDetectors, Vector2( hitPointLocal.x, hitPointLocal.y ) ); + EmitGestureSignal( actor, gestureDetectors, hitPointLocal ); break; // We have found AND emitted a signal on the gestured actor, break out. } } diff --git a/dali/internal/event/events/hit-test-algorithm-impl.cpp b/dali/internal/event/events/hit-test-algorithm-impl.cpp index 5c77ccc..5026b95 100644 --- a/dali/internal/event/events/hit-test-algorithm-impl.cpp +++ b/dali/internal/event/events/hit-test-algorithm-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * 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. @@ -52,19 +52,15 @@ struct HitActor { HitActor() : actor( NULL ), - x( 0 ), - y( 0 ), distance( std::numeric_limits::max() ), depth( std::numeric_limits::min() ) { } - Actor *actor; ///< the actor hit. (if actor hit, then initialised) - float x; ///< x position of hit (only valid if actor valid) - float y; ///< y position of hit (only valid if actor valid) - float distance; ///< distance from ray origin to hit actor - int depth; ///< depth index of this actor - + Actor *actor; ///< The actor hit (if actor is hit, then this is initialised). + Vector2 hitPosition; ///< Position of hit (only valid if actor valid). + float distance; ///< Distance from ray origin to hit actor. + int depth; ///< Depth index of this actor. }; /** @@ -135,16 +131,13 @@ bool IsActorExclusiveToAnotherRenderTask( const Actor& actor, const Vector< RenderTaskList::Exclusive >& exclusives ) { - if ( exclusives.Size() ) + if( exclusives.Size() ) { - for ( Vector< RenderTaskList::Exclusive >::Iterator exclusiveIt = exclusives.Begin(); exclusives.End() != exclusiveIt; ++exclusiveIt ) + for( Vector< RenderTaskList::Exclusive >::Iterator exclusiveIt = exclusives.Begin(); exclusives.End() != exclusiveIt; ++exclusiveIt ) { - if ( exclusiveIt->renderTaskPtr != &renderTask ) + if( ( exclusiveIt->renderTaskPtr != &renderTask ) && ( exclusiveIt->actorPtr == &actor ) ) { - if ( exclusiveIt->actorPtr == &actor ) - { - return true; - } + return true; } } } @@ -168,37 +161,39 @@ HitActor HitTestWithinLayer( Actor& actor, float& nearClippingPlane, float& farClippingPlane, HitTestInterface& hitCheck, - bool& stencilOnLayer, - bool& stencilHit, bool& overlayHit, - bool parentIsStencil, - bool layerIs3d ) + bool layerIs3d, + unsigned int clippingDepth, + unsigned int clippingBitPlaneMask ) { HitActor hit; - if ( IsActorExclusiveToAnotherRenderTask( actor, renderTask, exclusives ) ) + if( IsActorExclusiveToAnotherRenderTask( actor, renderTask, exclusives ) ) { return hit; } - // Children should inherit the stencil draw mode - bool isStencil = parentIsStencil; - - if ( actor.GetDrawMode() == DrawMode::STENCIL && actor.IsVisible() ) + // For clipping, regardless of whether we have hit this actor or not, + // we increase the clipping depth if we have hit a clipping actor. + // This is used later to ensure all nested clipped children have hit + // all clipping actors also for them to be counted as hit. + unsigned int newClippingDepth = clippingDepth; + bool clippingActor = actor.GetClippingMode() != ClippingMode::DISABLED; + if( clippingActor ) { - isStencil = true; - stencilOnLayer = true; + ++newClippingDepth; } - // If we are a stencil or hittable... - if ( isStencil || hitCheck.IsActorHittable( &actor ) ) + // If we are a clipping actor or hittable... + if( clippingActor || hitCheck.IsActorHittable( &actor ) ) { Vector3 size( actor.GetCurrentSize() ); - if ( size.x > 0.0f && size.y > 0.0f && // Ensure the actor has a valid size. - actor.RaySphereTest( rayOrigin, rayDir ) ) // Perform quicker ray sphere test to see if our ray is close to the actor. + // Ensure the actor has a valid size. + // If so, perform a quick ray sphere test to see if our ray is close to the actor. + if( size.x > 0.0f && size.y > 0.0f && actor.RaySphereTest( rayOrigin, rayDir ) ) { - Vector4 hitPointLocal; + Vector2 hitPointLocal; float distance; // Finally, perform a more accurate ray test to see if our ray actually hits the actor. @@ -206,36 +201,61 @@ HitActor HitTestWithinLayer( Actor& actor, { if( distance >= nearClippingPlane && distance <= farClippingPlane ) { - // If the hit has happened on a stencil then register, but don't record as hit result - if ( isStencil ) + // If the hit has happened on a clipping actor, then add this clipping depth to the mask of hit clipping depths. + // This mask shows all the actors that have been hit at different clipping depths. + if( clippingActor ) { - stencilHit = true; + clippingBitPlaneMask |= 1u << clippingDepth; + } + + if( overlayHit && !actor.IsOverlay() ) + { + // If we have already hit an overlay and current actor is not an overlay ignore current actor. } else { - if( overlayHit && !actor.IsOverlay() ) + if( actor.IsOverlay() ) { - //If we have already hit an overlay and current actor is not an overlay - //ignore current actor + overlayHit = true; } - else + + // At this point we have hit an actor. + // Now perform checks for clipping. + // Assume we have hit the actor first as if it is not clipped this would be the case. + bool haveHitActor = true; + + // Check if we are performing clipping. IE. if any actors so far have clipping enabled - not necessarily this one. + // We can do this by checking the clipping depth has a value 1 or above. + if( newClippingDepth >= 1u ) { - if( actor.IsOverlay() ) + // Now for us to count this actor as hit, we must have also hit + // all CLIPPING actors up to this point in the hierarchy as well. + // This information is stored in the clippingBitPlaneMask we updated above. + // Here we calculate a comparison mask by setting all the bits up to the current depth value. + // EG. a depth of 4 (10000 binary) = a mask of 1111 binary. + // This allows us a fast way of comparing all bits are set up to this depth. + unsigned int clippingDepthMask = ( 1u << clippingDepth ) - 1u; + + // The two masks must be equal to be a hit, as we are already assuming a hit + // (for non-clipping mode) then they must be not-equal to disqualify the hit. + if( clippingBitPlaneMask != clippingDepthMask ) { - overlayHit = true; + haveHitActor = false; } + } + if( haveHitActor ) + { hit.actor = &actor; - hit.x = hitPointLocal.x; - hit.y = hitPointLocal.y; + hit.hitPosition = hitPointLocal; hit.distance = distance; hit.depth = actor.GetHierarchyDepth() * Dali::Layer::TREE_DEPTH_MULTIPLIER; - if ( actor.GetRendererCount() > 0 ) + if( actor.GetRendererCount() > 0 ) { //Get renderer with maximum depth int rendererMaxDepth(actor.GetRendererAt( 0 ).Get()->GetDepthIndex()); - for( unsigned int i(1); iGetDepthIndex(); if( depth > rendererMaxDepth ) @@ -252,12 +272,6 @@ HitActor HitTestWithinLayer( Actor& actor, } } - // If we are a stencil (or a child of a stencil) and we have already ascertained that the stencil has been hit then there is no need to hit-test the children of this stencil-actor - if ( isStencil && stencilHit ) - { - return hit; - } - // Find a child hit, until we run out of actors in the current layer. HitActor childHit; if( actor.GetChildCount() > 0 ) @@ -272,30 +286,29 @@ HitActor HitTestWithinLayer( Actor& actor, for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter ) { // Descend tree only if... - if ( !(*iter)->IsLayer() && // Child is NOT a layer, hit testing current layer only or Child is not a layer and we've inherited the stencil draw mode - ( isStencil || hitCheck.DescendActorHierarchy( ( *iter ).Get() ) ) ) // We are a stencil OR we can descend into child hierarchy + if ( !( *iter )->IsLayer() && // Child is NOT a layer, hit testing current layer only + ( hitCheck.DescendActorHierarchy( ( *iter ).Get() ) ) ) // We can descend into child hierarchy { - HitActor currentHit( HitTestWithinLayer( (*iter->Get()), - renderTask, - exclusives, - rayOrigin, - rayDir, - nearClippingPlane, - farClippingPlane, - hitCheck, - stencilOnLayer, - stencilHit, - overlayHit, - isStencil, - layerIs3d) ); + HitActor currentHit( HitTestWithinLayer( ( *iter->Get() ), + renderTask, + exclusives, + rayOrigin, + rayDir, + nearClippingPlane, + farClippingPlane, + hitCheck, + overlayHit, + layerIs3d, + newClippingDepth, + clippingBitPlaneMask ) ); bool updateChildHit = false; - if ( currentHit.distance >= 0.0f ) + if( currentHit.distance >= 0.0f ) { if( layerIs3d ) { updateChildHit = ( ( currentHit.depth > childHit.depth ) || - ( ( currentHit.depth == childHit.depth ) && ( currentHit.distance < childHit.distance ) ) ); + ( ( currentHit.depth == childHit.depth ) && ( currentHit.distance < childHit.distance ) ) ); } else { @@ -303,17 +316,18 @@ HitActor HitTestWithinLayer( Actor& actor, } } - if ( updateChildHit ) + if( updateChildHit ) { if( !parentIsRenderable || currentHit.depth > hit.depth || ( layerIs3d && ( currentHit.depth == hit.depth && currentHit.distance < hit.distance )) ) - { - childHit = currentHit; - } + { + childHit = currentHit; + } } } } } + return ( childHit.actor ) ? childHit : hit; } @@ -326,13 +340,11 @@ bool IsWithinSourceActors( const Actor& sourceActor, const Actor& actor ) { return true; } - else + + Actor* parent = actor.GetParent(); + if ( parent ) { - Actor* parent = actor.GetParent(); - if ( parent ) - { - return IsWithinSourceActors( sourceActor, *parent ); - } + return IsWithinSourceActors( sourceActor, *parent ); } // Not within source actors @@ -346,7 +358,7 @@ inline bool IsActuallyHittable( Layer& layer, const Vector2& screenCoordinates, { bool hittable( true ); - if(layer.IsClipping()) + if( layer.IsClipping() ) { ClippingBox box = layer.GetClippingBox(); @@ -360,14 +372,14 @@ inline bool IsActuallyHittable( Layer& layer, const Vector2& screenCoordinates, } } - if(hittable) + if( hittable ) { Actor* actor( &layer ); // Ensure that we can descend into the layer's (or any of its parent's) hierarchy. - while ( actor && hittable ) + while( actor && hittable ) { - if ( ! hitCheck.DescendActorHierarchy( actor ) ) + if( ! hitCheck.DescendActorHierarchy( actor ) ) { hittable = false; break; @@ -414,14 +426,14 @@ bool HitTestRenderTask( const Vector< RenderTaskList::Exclusive >& exclusives, } float nearClippingPlane, farClippingPlane; - GetCameraClippingPlane(renderTask, nearClippingPlane, farClippingPlane); + GetCameraClippingPlane( renderTask, nearClippingPlane, farClippingPlane ); // Determine the layer depth of the source actor Actor* sourceActor( renderTask.GetSourceActor() ); - if ( sourceActor ) + if( sourceActor ) { Dali::Layer layer( sourceActor->GetLayer() ); - if ( layer ) + if( layer ) { const unsigned int sourceActorDepth( layer.GetDepth() ); @@ -438,26 +450,20 @@ bool HitTestRenderTask( const Vector< RenderTaskList::Exclusive >& exclusives, // Hit test starting with the top layer, working towards the bottom layer. HitActor hit; - bool stencilOnLayer = false; - bool stencilHit = false; bool overlayHit = false; bool layerConsumesHit = false; - const Vector2& stageSize = stage.GetSize(); - for (int i=layers.GetLayerCount()-1; i>=0 && !(hit.actor); --i) + for( int i = layers.GetLayerCount() - 1; i >= 0 && !( hit.actor ); --i ) { - Layer* layer( layers.GetLayer(i) ); - HitActor previousHit = hit; - stencilOnLayer = false; - stencilHit = false; + Layer* layer( layers.GetLayer( i ) ); overlayHit = false; // Ensure layer is touchable (also checks whether ancestors are also touchable) - if ( IsActuallyHittable ( *layer, screenCoordinates, stageSize, hitCheck ) ) + if( IsActuallyHittable( *layer, screenCoordinates, stageSize, hitCheck ) ) { // Always hit-test the source actor; otherwise test whether the layer is below the source actor in the hierarchy - if ( sourceActorDepth == static_cast(i) ) + if( sourceActorDepth == static_cast( i ) ) { // Recursively hit test the source actor & children, without crossing into other layers. hit = HitTestWithinLayer( *sourceActor, @@ -468,13 +474,12 @@ bool HitTestRenderTask( const Vector< RenderTaskList::Exclusive >& exclusives, nearClippingPlane, farClippingPlane, hitCheck, - stencilOnLayer, - stencilHit, overlayHit, - false, - layer->GetBehavior() == Dali::Layer::LAYER_3D); + layer->GetBehavior() == Dali::Layer::LAYER_3D, + 0u, + 0u ); } - else if ( IsWithinSourceActors( *sourceActor, *layer ) ) + else if( IsWithinSourceActors( *sourceActor, *layer ) ) { // Recursively hit test all the actors, without crossing into other layers. hit = HitTestWithinLayer( *layer, @@ -485,37 +490,31 @@ bool HitTestRenderTask( const Vector< RenderTaskList::Exclusive >& exclusives, nearClippingPlane, farClippingPlane, hitCheck, - stencilOnLayer, - stencilHit, overlayHit, - false, - layer->GetBehavior() == Dali::Layer::LAYER_3D); - } - - // If a stencil on this layer hasn't been hit, then discard hit results for this layer if our current hit actor is renderable - if ( stencilOnLayer && !stencilHit && - hit.actor && hit.actor->IsRenderable() ) - { - hit = previousHit; + layer->GetBehavior() == Dali::Layer::LAYER_3D, + 0u, + 0u ); } // If this layer is set to consume the hit, then do not check any layers behind it - if ( hitCheck.DoesLayerConsumeHit( layer ) ) + if( hitCheck.DoesLayerConsumeHit( layer ) ) { layerConsumesHit = true; break; } } } - if ( hit.actor ) + + if( hit.actor ) { - results.renderTask = Dali::RenderTask(&renderTask); - results.actor = Dali::Actor(hit.actor); - results.actorCoordinates.x = hit.x; - results.actorCoordinates.y = hit.y; + results.renderTask = Dali::RenderTask( &renderTask ); + results.actor = Dali::Actor( hit.actor ); + results.actorCoordinates = hit.hitPosition; + return true; // Success } - else if ( layerConsumesHit ) + + if( layerConsumesHit ) { return true; // Also success if layer is consuming the hit } @@ -526,76 +525,86 @@ bool HitTestRenderTask( const Vector< RenderTaskList::Exclusive >& exclusives, } /** - * Iterate through RenderTaskList and perform hit test. + * Iterate through the RenderTaskList and perform hit testing. * - * @return true if we have a hit, false otherwise + * @param[in] stage The stage the tests will be performed in + * @param[in] layers The list of layers to test + * @param[in] taskList The list of render tasks + * @param[out] results Ray information calculated by the camera + * @param[in] hitCheck The hit testing interface object to use + * @param[in] onScreen True to test on-screen, false to test off-screen + * @return True if we have a hit, false otherwise */ -bool HitTestForEachRenderTask( Stage& stage, - LayerList& layers, - RenderTaskList& taskList, - const Vector2& screenCoordinates, - Results& results, - HitTestInterface& hitCheck ) +bool HitTestRenderTaskList( Stage& stage, + LayerList& layers, + RenderTaskList& taskList, + const Vector2& screenCoordinates, + Results& results, + HitTestInterface& hitCheck, + bool onScreen ) { RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks(); RenderTaskList::RenderTaskContainer::reverse_iterator endIter = tasks.rend(); - const Vector< RenderTaskList::Exclusive >& exclusives = taskList.GetExclusivesList(); - // Check onscreen tasks before offscreen ones, hit test order should be reverse of draw order (see ProcessRenderTasks() where offscreen tasks are drawn first). - - // on screen - for ( RenderTaskList::RenderTaskContainer::reverse_iterator iter = tasks.rbegin(); endIter != iter; ++iter ) + for( RenderTaskList::RenderTaskContainer::reverse_iterator iter = tasks.rbegin(); endIter != iter; ++iter ) { RenderTask& renderTask = GetImplementation( *iter ); Dali::FrameBufferImage frameBufferImage = renderTask.GetTargetFrameBuffer(); // Note that if frameBufferImage is NULL we are using the default (on screen) render target - if(frameBufferImage) + if( frameBufferImage ) { - ResourceId id = GetImplementation(frameBufferImage).GetResourceId(); + ResourceId id = GetImplementation( frameBufferImage ).GetResourceId(); - // on screen only - if(0 != id) + // Change comparison depending on if on-screen or off-screen. + if( onScreen ? ( 0 != id ) : ( 0 == id ) ) { // Skip to next task continue; } } - if ( HitTestRenderTask( exclusives, stage, layers, renderTask, screenCoordinates, results, hitCheck ) ) + if( HitTestRenderTask( exclusives, stage, layers, renderTask, screenCoordinates, results, hitCheck ) ) { // Return true when an actor is hit (or layer in our render-task consumes the hit) return true; // don't bother checking off screen tasks } } - // off screen - for ( RenderTaskList::RenderTaskContainer::reverse_iterator iter = tasks.rbegin(); endIter != iter; ++iter ) - { - RenderTask& renderTask = GetImplementation( *iter ); - Dali::FrameBufferImage frameBufferImage = renderTask.GetTargetFrameBuffer(); - - // Note that if frameBufferImage is NULL we are using the default (on screen) render target - if(frameBufferImage) - { - ResourceId id = GetImplementation(frameBufferImage).GetResourceId(); + return false; +} - // off screen only - if(0 == id) - { - // Skip to next task - continue; - } +/** + * Iterate through the RenderTaskList and perform hit testing for both on-screen and off-screen. + * + * @param[in] stage The stage the tests will be performed in + * @param[in] layers The list of layers to test + * @param[in] taskList The list of render tasks + * @param[out] results Ray information calculated by the camera + * @param[in] hitCheck The hit testing interface object to use + * @param[in] onScreen True to test on-screen, false to test off-screen + * @return True if we have a hit, false otherwise + */ +bool HitTestForEachRenderTask( Stage& stage, + LayerList& layers, + RenderTaskList& taskList, + const Vector2& screenCoordinates, + Results& results, + HitTestInterface& hitCheck ) +{ + bool result = false; - if ( HitTestRenderTask( exclusives, stage, layers, renderTask, screenCoordinates, results, hitCheck ) ) - { - // Return true when an actor is hit (or a layer in our render-task consumes the hit) - return true; - } - } + // Check on-screen tasks before off-screen ones. + // Hit test order should be reverse of draw order (see ProcessRenderTasks() where off-screen tasks are drawn first). + if( HitTestRenderTaskList( stage, layers, taskList, screenCoordinates, results, hitCheck, true ) || + HitTestRenderTaskList( stage, layers, taskList, screenCoordinates, results, hitCheck, false ) ) + { + // Found hit. + result = true; } - return false; + + return result; } } // unnamed namespace @@ -609,7 +618,7 @@ bool HitTest( Stage& stage, const Vector2& screenCoordinates, Dali::HitTestAlgor Results hitTestResults; HitTestFunctionWrapper hitTestFunctionWrapper( func ); - if ( HitTestForEachRenderTask( stage, layerList, taskList, screenCoordinates, hitTestResults, hitTestFunctionWrapper ) ) + if( HitTestForEachRenderTask( stage, layerList, taskList, screenCoordinates, hitTestResults, hitTestFunctionWrapper ) ) { results.actor = hitTestResults.actor; results.actorCoordinates = hitTestResults.actorCoordinates; @@ -625,7 +634,7 @@ bool HitTest( Stage& stage, const Vector2& screenCoordinates, Results& results, // Hit-test the system-overlay actors first SystemOverlay* systemOverlay = stage.GetSystemOverlayInternal(); - if ( systemOverlay ) + if( systemOverlay ) { RenderTaskList& overlayTaskList = systemOverlay->GetOverlayRenderTasks(); LayerList& overlayLayerList = systemOverlay->GetLayerList(); @@ -634,7 +643,7 @@ bool HitTest( Stage& stage, const Vector2& screenCoordinates, Results& results, } // Hit-test the regular on-stage actors - if ( !wasHit ) + if( !wasHit ) { RenderTaskList& taskList = stage.GetRenderTaskList(); LayerList& layerList = stage.GetLayerList(); @@ -658,7 +667,7 @@ bool HitTest( Stage& stage, RenderTask& renderTask, const Vector2& screenCoordin const Vector< RenderTaskList::Exclusive >& exclusives = stage.GetRenderTaskList().GetExclusivesList(); HitTestFunctionWrapper hitTestFunctionWrapper( func ); - if ( HitTestRenderTask( exclusives, stage, stage.GetLayerList(), renderTask, screenCoordinates, hitTestResults, hitTestFunctionWrapper ) ) + if( HitTestRenderTask( exclusives, stage, stage.GetLayerList(), renderTask, screenCoordinates, hitTestResults, hitTestFunctionWrapper ) ) { results.actor = hitTestResults.actor; results.actorCoordinates = hitTestResults.actorCoordinates; @@ -667,6 +676,7 @@ bool HitTest( Stage& stage, RenderTask& renderTask, const Vector2& screenCoordin return wasHit; } + } // namespace HitTestAlgorithm } // namespace Internal diff --git a/dali/internal/event/events/hit-test-algorithm-impl.h b/dali/internal/event/events/hit-test-algorithm-impl.h index 07b2291..c0b68e3 100644 --- a/dali/internal/event/events/hit-test-algorithm-impl.h +++ b/dali/internal/event/events/hit-test-algorithm-impl.h @@ -1,8 +1,8 @@ -#ifndef __DALI_INTERNAL_HIT_TEST_ALGORITHM_H__ -#define __DALI_INTERNAL_HIT_TEST_ALGORITHM_H__ +#ifndef DALI_INTERNAL_HIT_TEST_ALGORITHM_H +#define DALI_INTERNAL_HIT_TEST_ALGORITHM_H /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * 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. @@ -138,10 +138,11 @@ bool HitTest( Stage& stage, const Vector2& screenCoordinates, Results& results ) bool HitTest( Stage& stage, RenderTask& renderTask, const Vector2& screenCoordinates, Dali::HitTestAlgorithm::Results& results, Dali::HitTestAlgorithm::HitTestFunction func ); + } // namespace HitTestAlgorithm } // namespace Internal } // namespace Dali -#endif // __DALI_INTERNAL_HIT_TEST_ALGORITHM_H__ +#endif // DALI_INTERNAL_HIT_TEST_ALGORITHM_H diff --git a/dali/internal/event/rendering/renderer-impl.cpp b/dali/internal/event/rendering/renderer-impl.cpp index b2f07e6..c430a5b 100644 --- a/dali/internal/event/rendering/renderer-impl.cpp +++ b/dali/internal/event/rendering/renderer-impl.cpp @@ -885,7 +885,7 @@ void Renderer::Disconnect() } Renderer::Renderer() -: mSceneObject (NULL ), +: mSceneObject(NULL ), mBlendColor( NULL ), mDepthIndex( 0 ), mOnStageCount( 0 ), diff --git a/dali/internal/file.list b/dali/internal/file.list index f7bcf2b..18b11cc 100644 --- a/dali/internal/file.list +++ b/dali/internal/file.list @@ -145,8 +145,8 @@ internal_src_files = \ $(internal_src_dir)/update/gestures/pan-gesture-profiling.cpp \ $(internal_src_dir)/update/gestures/scene-graph-pan-gesture.cpp \ $(internal_src_dir)/update/queue/update-message-queue.cpp \ - $(internal_src_dir)/update/manager/prepare-render-instructions.cpp \ - $(internal_src_dir)/update/manager/process-render-tasks.cpp \ + $(internal_src_dir)/update/manager/render-instruction-processor.cpp \ + $(internal_src_dir)/update/manager/render-task-processor.cpp \ $(internal_src_dir)/update/manager/transform-manager.cpp \ $(internal_src_dir)/update/manager/update-algorithms.cpp \ $(internal_src_dir)/update/manager/update-manager.cpp \ diff --git a/dali/internal/render/common/render-algorithms.cpp b/dali/internal/render/common/render-algorithms.cpp index ce56324..87b3658 100644 --- a/dali/internal/render/common/render-algorithms.cpp +++ b/dali/internal/render/common/render-algorithms.cpp @@ -70,7 +70,7 @@ inline void SetScissorTest( const RenderList& renderList, Context& context ) context.SetScissorTest( true ); const Dali::ClippingBox& clip = renderList.GetClippingBox(); - context.Scissor(clip.x, clip.y, clip.width, clip.height); + context.Scissor( clip.x, clip.y, clip.width, clip.height ); } else { @@ -79,141 +79,223 @@ inline void SetScissorTest( const RenderList& renderList, Context& context ) } /** - * Sets the render flags for the stencil buffer and clears all required buffers (depth and stencil if required). - * @param[in] renderList The render list from which to get the render flags - * @param[in] context The context - * @param[in] depthTestEnabled True if depth test is enabled for the layer - * @param[in] isLayer3D True if the layer is a 3D layer + * @brief Set up the stencil and color buffer for automatic clipping (StencilMode::AUTO). + * @param[in] item The current RenderItem about to be rendered + * @param[in] context The context + * @param[in/out] lastStencilDepth The stencil depth of the last renderer drawn. + * @param[in/out] lastClippingId The clipping ID of the last renderer drawn. */ -inline void SetRenderFlags( const RenderList& renderList, Context& context, bool depthTestEnabled ) +inline void SetupClipping( const RenderItem& item, Context& context, uint32_t& lastStencilDepth, uint32_t& lastClippingId ) { - const unsigned int renderFlags = renderList.GetFlags(); - GLbitfield clearMask = 0u; - - // Stencil enabled, writing, and clearing... - const bool enableStencilBuffer( renderFlags & RenderList::STENCIL_BUFFER_ENABLED ); - const bool enableStencilWrite( renderFlags & RenderList::STENCIL_WRITE ); - context.EnableStencilBuffer( enableStencilBuffer ); - if( enableStencilBuffer ) - { - context.StencilFunc( ( enableStencilWrite ? GL_ALWAYS : GL_EQUAL ), 1, 0xFF ); - context.StencilOp( GL_KEEP, GL_REPLACE, GL_REPLACE ); + const Dali::Internal::SceneGraph::Node* node = item.mNode; + const uint32_t clippingId = node->GetClippingId(); - // Write to stencil buffer or color buffer, but not both. - // These should only be set if the Actor::DrawMode is managing the stencil (and color) buffer. - context.StencilMask( enableStencilWrite ? 0xFF : 0x00 ); - context.ColorMask( !enableStencilWrite ); + // Turn the color buffer on as we always want to render this renderer, regardless of clipping hierarchy. + context.ColorMask( true ); - clearMask |= ( renderFlags & RenderList::STENCIL_CLEAR ) ? GL_STENCIL_BUFFER_BIT : 0u; + // If there is no clipping Id, then either we haven't reached a clipping Node yet, or there aren't any. + // Either way we can skip clipping setup for this renderer. + if( clippingId == 0u ) + { + // Exit immediately if there are no clipping actions to perform (EG. we have not yet hit a clipping node). + context.EnableStencilBuffer( false ); + return; } - // Enable and Clear the depth buffer if required. - if( depthTestEnabled ) + const ClippingMode::Type clippingMode( node->GetClippingMode() ); + const uint32_t currentStencilDepth( node->GetClippingDepth() ); + + context.EnableStencilBuffer( true ); + + // Pre-calculate a mask which has all bits set up to and including the current clipping depth. + // EG. If depth is 3, the mask would be "111" in binary. + const uint32_t currentDepthMask = ( 1u << currentStencilDepth ) - 1u; + + // If we have a clipping mode specified, we are writing to the stencil buffer. + if( clippingMode != ClippingMode::DISABLED ) { - clearMask |= GL_DEPTH_BUFFER_BIT; + // We are writing to the stencil buffer. + // If clipping Id is 1, this is the first clipping renderer within this render-list. + if( clippingId == 1u ) + { + // We are enabling the stencil-buffer for the first time within this render list. + // Clear the buffer at this point. + context.StencilMask( 0xff ); + context.Clear( GL_STENCIL_BUFFER_BIT, Context::CHECK_CACHED_VALUES ); + } + else if( ( currentStencilDepth < lastStencilDepth ) || ( clippingId != lastClippingId ) ) + { + // The above if() statement tests if we need to clear some (not all) stencil bit-planes. + // We need to do this if either of the following are true: + // 1) We traverse up the scene-graph to a previous stencil + // 2) We are at the same stencil depth but the clipping Id has changed. + // + // This calculation takes the new depth to move to, and creates an inverse-mask of that number of consecutive bits. + // This has the effect of clearing everything except the bit-planes up to (and including) our current depth. + const uint32_t stencilClearMask = ( currentDepthMask >> 1u ) ^ 0xff; + + context.StencilMask( stencilClearMask ); + context.Clear( GL_STENCIL_BUFFER_BIT, Context::CHECK_CACHED_VALUES ); + } - // We need to enable the depth buffer to clear it. - // Subsequently it is enabled and disabled on a per-RenderItem basis. - context.EnableDepthBuffer( true ); + // We keep track of the last clipping Id and depth so we can determine when we are + // moving back up the scene graph and require some of the stencil bit-planes to be deleted. + lastStencilDepth = currentStencilDepth; + lastClippingId = clippingId; + + // We only ever write to bit-planes up to the current depth as we may need + // to erase individual bit-planes and revert to a previous clipping area. + // Our reference value for testing (in StencilFunc) is written to to the buffer, but we actually + // want to test a different value. IE. All the bit-planes up to but not including the current depth. + // So we use the Mask parameter of StencilFunc to mask off the top bit-plane when testing. + // Here we create our test mask to innore the top bit of the reference test value. + // As the mask is made up of contiguous "1" values, we can do this quickly with a bit-shift. + const uint32_t testMask = currentDepthMask >> 1u; + + context.StencilFunc( GL_EQUAL, currentDepthMask, testMask ); // Test against existing stencil bit-planes. All must match up to (but not including) this depth. + context.StencilMask( currentDepthMask ); // Write to the new stencil bit-plane (the other previous bit-planes are also written to). + context.StencilOp( GL_KEEP, GL_REPLACE, GL_REPLACE ); } else { - context.EnableDepthBuffer( false ); + // We are reading from the stencil buffer. Set up the stencil accordingly + // This calculation sets all the bits up to the current depth bit. + // This has the effect of testing that the pixel being written to exists in every bit-plane up to the current depth. + context.StencilFunc( GL_EQUAL, currentDepthMask, 0xff ); + context.StencilOp( GL_KEEP, GL_KEEP, GL_KEEP ); } - - // Clear Depth and/or stencil buffers as required. - // Note: The buffers will only be cleared if written to since a previous clear. - context.Clear( clearMask, Context::CHECK_CACHED_VALUES ); } /** - * @brief This method sets up the stencil and color buffer based on the current Renderers flags. + * @brief Set up the stencil and color buffer based on the current Renderers properties. * @param[in] item The current RenderItem about to be rendered * @param[in] context The context - * @param[in/out] usedStencilBuffer True if the stencil buffer has been used so far within this RenderList - * @param[in] stencilManagedByDrawMode True if the stencil and color buffer is being managed by DrawMode::STENCIL + * @param[in/out] usedStencilBuffer True if the stencil buffer has been used so far within this RenderList. Used by StencilMode::ON. + * @param[in/out] lastStencilDepth The stencil depth of the last renderer drawn. Used by the clipping feature. + * @param[in/out] lastClippingId The clipping ID of the last renderer drawn. Used by the clipping feature. */ -inline void SetupPerRendererFlags( const RenderItem& item, Context& context, bool& usedStencilBuffer, bool stencilManagedByDrawMode ) +inline void SetupStencilBuffer( const RenderItem& item, Context& context, bool& usedStencilBuffer, uint32_t& lastStencilDepth, uint32_t& lastClippingId ) { - // DrawMode::STENCIL is deprecated, however to support it we must not set - // flags based on the renderer properties if it is in use. - if( stencilManagedByDrawMode ) - { - return; - } + const Renderer *renderer = item.mRenderer; - // Setup the color buffer based on the renderers properties. - Renderer *renderer = item.mRenderer; + // Setup the stencil using either the automatic clipping feature, or, the manual per-renderer stencil API. + // Note: This switch is in order of most likely value first. RenderMode::Type renderMode = renderer->GetRenderMode(); - const bool writeToColorBuffer = ( renderMode == RenderMode::AUTO ) || ( renderMode == RenderMode::COLOR ) || ( renderMode == RenderMode::COLOR_STENCIL ); - context.ColorMask( writeToColorBuffer ); - - // If the stencil buffer is disabled for this renderer, exit now to save unnecessary value setting. - if( ( renderMode != RenderMode::STENCIL ) && ( renderMode != RenderMode::COLOR_STENCIL ) ) + switch( renderMode ) { - // No per-renderer stencil setup, exit. - context.EnableStencilBuffer( false ); - return; - } + case RenderMode::AUTO: + { + // The automatic clipping feature will manage the stencil functions and color buffer mask. + SetupClipping( item, context, lastStencilDepth, lastClippingId ); + break; + } - // At this point, the stencil buffer is enabled. - context.EnableStencilBuffer( true ); + case RenderMode::NONE: + case RenderMode::COLOR: + { + // The stencil buffer will not be used at all. + context.EnableStencilBuffer( false ); - // If this is the first use of the stencil buffer within this RenderList, clear it now. - // This avoids unnecessary clears. - if( !usedStencilBuffer ) - { - context.Clear( GL_STENCIL_BUFFER_BIT, Context::CHECK_CACHED_VALUES ); - usedStencilBuffer = true; - } + // Setup the color buffer based on the RenderMode. + context.ColorMask( renderMode == RenderMode::COLOR ); + return; + break; // Break statement for consistency (although return will be called instead). + } + + case RenderMode::STENCIL: + case RenderMode::COLOR_STENCIL: + { + // We are using the low-level Renderer Stencil API. + // The stencil buffer must be enabled for every renderer with stencil mode on, as renderers in between can disable it. + // Note: As the command state is cached, it is only sent when needed. + context.EnableStencilBuffer( true ); + + // Setup the color buffer based on the RenderMode. + context.ColorMask( renderMode == RenderMode::COLOR_STENCIL ); - // Setup the stencil buffer based on the renderers properties. - context.StencilFunc( DaliStencilFunctionToGL[ renderer->GetStencilFunction() ], - renderer->GetStencilFunctionReference(), - renderer->GetStencilFunctionMask() ); - context.StencilOp( DaliStencilOperationToGL[ renderer->GetStencilOperationOnFail() ], - DaliStencilOperationToGL[ renderer->GetStencilOperationOnZFail() ], - DaliStencilOperationToGL[ renderer->GetStencilOperationOnZPass() ] ); - context.StencilMask( renderer->GetStencilMask() ); + // If this is the first use of the stencil buffer within this RenderList, clear it (this avoids unnecessary clears). + if( !usedStencilBuffer ) + { + context.Clear( GL_STENCIL_BUFFER_BIT, Context::CHECK_CACHED_VALUES ); + usedStencilBuffer = true; + } + + // Setup the stencil buffer based on the renderers properties. + context.StencilFunc( DaliStencilFunctionToGL[ renderer->GetStencilFunction() ], + renderer->GetStencilFunctionReference(), + renderer->GetStencilFunctionMask() ); + context.StencilOp( DaliStencilOperationToGL[ renderer->GetStencilOperationOnFail() ], + DaliStencilOperationToGL[ renderer->GetStencilOperationOnZFail() ], + DaliStencilOperationToGL[ renderer->GetStencilOperationOnZPass() ] ); + context.StencilMask( renderer->GetStencilMask() ); + break; + } + } } /** - * Sets up the depth buffer for reading and writing based on the current render item. + * @brief Sets up the depth buffer for reading and writing based on the current render item. * The items read and write mode are used if specified. - * If AUTO is selected for reading, the decision will be based on the Layer Behavior. - * If AUTO is selected for writing, the decision will be based on the items opacity. - * @param item The RenderItem to set up the depth buffer for - * @param context The context used to execute GL commands. - * @param depthTestEnabled True if depth testing has been enabled. + * - If AUTO is selected for reading, the decision will be based on the Layer Behavior. + * - If AUTO is selected for writing, the decision will be based on the items opacity. + * @param[in] item The RenderItem to set up the depth buffer for. + * @param[in] context The context used to execute GL commands. + * @param[in] depthTestEnabled True if depth testing has been enabled. + * @param[in/out] firstDepthBufferUse Initialise to true on the first call, this method will set it to false afterwards. */ -inline void SetupDepthBuffer( const RenderItem& item, Context& context, bool depthTestEnabled ) +inline void SetupDepthBuffer( const RenderItem& item, Context& context, bool depthTestEnabled, bool& firstDepthBufferUse ) { // Set up whether or not to write to the depth buffer. const DepthWriteMode::Type depthWriteMode = item.mRenderer->GetDepthWriteMode(); // Most common mode (AUTO) is tested first. - bool enableDepthWrite = ( ( depthWriteMode == DepthWriteMode::AUTO ) && depthTestEnabled && item.mIsOpaque ) || - ( depthWriteMode == DepthWriteMode::ON ); - context.DepthMask( enableDepthWrite ); + const bool enableDepthWrite = ( ( depthWriteMode == DepthWriteMode::AUTO ) && depthTestEnabled && item.mIsOpaque ) || + ( depthWriteMode == DepthWriteMode::ON ); // Set up whether or not to read from (test) the depth buffer. const DepthTestMode::Type depthTestMode = item.mRenderer->GetDepthTestMode(); // Most common mode (AUTO) is tested first. - bool enableDepthTest = ( ( depthTestMode == DepthTestMode::AUTO ) && depthTestEnabled ) || - ( depthTestMode == DepthTestMode::ON ); - // Look-up the GL depth function from the Dali::DepthFunction enum, and set it. - context.DepthFunc( DaliDepthToGLDepthTable[ item.mRenderer->GetDepthFunction() ] ); + const bool enableDepthTest = ( ( depthTestMode == DepthTestMode::AUTO ) && depthTestEnabled ) || + ( depthTestMode == DepthTestMode::ON ); - // The depth buffer must be enabled if either reading or writing. - context.EnableDepthBuffer( enableDepthWrite || enableDepthTest ); + // Is the depth buffer in use? + if( enableDepthWrite || enableDepthTest ) + { + // The depth buffer must be enabled if either reading or writing. + context.EnableDepthBuffer( true ); + + // Set up the depth mask based on our depth write setting. + context.DepthMask( enableDepthWrite ); + + // Look-up the GL depth function from the Dali::DepthFunction enum, and set it. + context.DepthFunc( DaliDepthToGLDepthTable[ item.mRenderer->GetDepthFunction() ] ); + + // If this is the first use of the depth buffer this RenderTask, perform a clear. + // Note: We could do this at the beginning of the RenderTask and rely on the + // context cache to ignore the clear if not required, but, we would have to enable + // the depth buffer to do so, which could be a redundant enable. + if( DALI_UNLIKELY( firstDepthBufferUse ) ) + { + // This is the first time the depth buffer is being written to or read. + firstDepthBufferUse = false; + + // Note: The buffer will only be cleared if written to since a previous clear. + context.Clear( GL_DEPTH_BUFFER_BIT, Context::CHECK_CACHED_VALUES ); + } + } + else + { + // The depth buffer is not being used by this renderer, so we must disable it to stop it being tested. + context.EnableDepthBuffer( false ); + } } /** - * Process a render-list. - * @param[in] renderList The render-list to process. - * @param[in] context The GL context. - * @param[in] defaultShader The default shader to use. - * @param[in] buffer The current render buffer index (previous update buffer) - * @param[in] viewMatrix The view matrix from the appropriate camera. + * @brief Process a render-list. + * @param[in] renderList The render-list to process. + * @param[in] context The GL context. + * @param[in] defaultShader The default shader to use. + * @param[in] buffer The current render buffer index (previous update buffer) + * @param[in] viewMatrix The view matrix from the appropriate camera. * @param[in] projectionMatrix The projection matrix from the appropriate camera. */ inline void ProcessRenderList( @@ -227,15 +309,18 @@ inline void ProcessRenderList( { DALI_PRINT_RENDER_LIST( renderList ); - bool autoDepthTestMode = !( renderList.GetSourceLayer()->IsDepthTestDisabled() ) && renderList.HasColorRenderItems(); - bool usedStencilBuffer = false; - bool stencilManagedByDrawMode = renderList.GetFlags() & RenderList::STENCIL_BUFFER_ENABLED; - SetScissorTest( renderList, context ); - SetRenderFlags( renderList, context, autoDepthTestMode ); - const size_t count = renderList.Count(); - for ( size_t index = 0; index < count; ++index ) + // Note: The depth buffer is enabled or disabled on a per-renderer basis. + // Here we pre-calculate the value to use if these modes are set to AUTO. + const bool autoDepthTestMode( !( renderList.GetSourceLayer()->IsDepthTestDisabled() ) && renderList.HasColorRenderItems() ); + const std::size_t count = renderList.Count(); + uint32_t lastStencilDepth( 0u ); + uint32_t lastClippingId( 0u ); + bool usedStencilBuffer( false ); + bool firstDepthBufferUse( true ); + + for( size_t index( 0u ); index < count; ++index ) { const RenderItem& item = renderList.GetItem( index ); DALI_PRINT_RENDER_ITEM( item ); @@ -245,8 +330,11 @@ inline void ProcessRenderList( // draw-mode state, such as Overlays. // If the flags are set to "AUTO", the behaviour then depends on the type of renderer. Overlay Renderers will always // disable depth testing and writing. Color Renderers will enable them if the Layer does. - SetupDepthBuffer( item, context, autoDepthTestMode ); - SetupPerRendererFlags( item, context, usedStencilBuffer, stencilManagedByDrawMode ); + SetupDepthBuffer( item, context, autoDepthTestMode, firstDepthBufferUse ); + + // Set up the stencil buffer based on both the Renderer and Actor APIs. + // The Renderer API will be used if specified. If AUTO, the Actors automatic clipping feature will be used. + SetupStencilBuffer( item, context, usedStencilBuffer, lastStencilDepth, lastClippingId ); item.mRenderer->Render( context, textureCache, bufferIndex, *item.mNode, defaultShader, item.mModelMatrix, item.mModelViewMatrix, viewMatrix, projectionMatrix, item.mSize, !item.mIsOpaque ); @@ -264,11 +352,10 @@ void ProcessRenderInstruction( const RenderInstruction& instruction, const Matrix* viewMatrix = instruction.GetViewMatrix( bufferIndex ); const Matrix* projectionMatrix = instruction.GetProjectionMatrix( bufferIndex ); - DALI_ASSERT_DEBUG( NULL != viewMatrix ); - DALI_ASSERT_DEBUG( NULL != projectionMatrix ); + DALI_ASSERT_DEBUG( viewMatrix ); + DALI_ASSERT_DEBUG( projectionMatrix ); - if( NULL != viewMatrix && - NULL != projectionMatrix ) + if( viewMatrix && projectionMatrix ) { const RenderListContainer::SizeType count = instruction.RenderListCount(); @@ -278,8 +365,7 @@ void ProcessRenderInstruction( const RenderInstruction& instruction, { const RenderList* renderList = instruction.GetRenderList( index ); - if( renderList && - !renderList->IsEmpty() ) + if( renderList && !renderList->IsEmpty() ) { ProcessRenderList( *renderList, context, textureCache, defaultShader, bufferIndex, *viewMatrix, *projectionMatrix ); } diff --git a/dali/internal/render/common/render-debug.cpp b/dali/internal/render/common/render-debug.cpp index d5f1165..e5e1d23 100644 --- a/dali/internal/render/common/render-debug.cpp +++ b/dali/internal/render/common/render-debug.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * 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. @@ -26,7 +26,9 @@ #include #include #include +#include +using Dali::Internal::SceneGraph::Node; using Dali::Internal::SceneGraph::RenderList; namespace Dali @@ -38,6 +40,10 @@ namespace Internal namespace Render { +// These functions should only be defined if they are being used by the #define in the header. +// Otherwise they will contribute negatively to code coverage. +#ifdef DALI_PRINT_RENDER_INFO + void PrintFrameStart( BufferIndex bufferIndex ) { DALI_LOG_RENDER_INFO( "RENDER START - bufferIndex: %d\n", bufferIndex ); @@ -71,35 +77,9 @@ void PrintRenderInstruction( const SceneGraph::RenderInstruction& instruction, B void PrintRenderList( const RenderList& list ) { - unsigned int flags = list.GetFlags(); - std::stringstream debugStream; debugStream << "Rendering items"; - if( flags ) - { - debugStream << " with:"; - - if( flags & RenderList::STENCIL_BUFFER_ENABLED ) - { - debugStream << " STENCIL_TEST"; - } - - if( flags & RenderList::STENCIL_WRITE ) - { - debugStream << " STENCIL_WRITE"; - } - - if( flags & RenderList::STENCIL_CLEAR ) - { - debugStream << " STENCIL_CLEAR"; - } - } - else - { - debugStream << " without any STENCIL settings"; - } - if( list.IsClipping() ) { debugStream << ", ClippingBox: " << list.GetClippingBox().x << "," << list.GetClippingBox().y << " " << list.GetClippingBox().width << "x" << list.GetClippingBox().height; @@ -126,6 +106,8 @@ void PrintRendererCount( unsigned int frameCount, unsigned int rendererCount ) } } +#endif + } // Render } // Internal diff --git a/dali/internal/render/common/render-debug.h b/dali/internal/render/common/render-debug.h index 8d5176e..5cb25be 100644 --- a/dali/internal/render/common/render-debug.h +++ b/dali/internal/render/common/render-debug.h @@ -64,6 +64,7 @@ class PropertyInputImpl; namespace SceneGraph { +class Node; class RenderInstruction; struct RenderList; struct RenderItem; @@ -109,6 +110,13 @@ void PrintRenderItem( const SceneGraph::RenderItem& item ); */ void PrintRendererCount( unsigned int frameCount, unsigned int rendererCount ); +/** + * Recursively dumps a Node tree. + * @param[in] node The starting node to dump from + * @param[in] indent Optional. Leave unset for default indent (used internally while recursing) + */ +void DumpNode( const SceneGraph::Node* node, unsigned int indent = 0 ); + } // Render } // Internal diff --git a/dali/internal/render/common/render-item.cpp b/dali/internal/render/common/render-item.cpp index d81f068..335492f 100644 --- a/dali/internal/render/common/render-item.cpp +++ b/dali/internal/render/common/render-item.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * 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. diff --git a/dali/internal/render/common/render-item.h b/dali/internal/render/common/render-item.h index d429452..7401280 100644 --- a/dali/internal/render/common/render-item.h +++ b/dali/internal/render/common/render-item.h @@ -1,8 +1,8 @@ -#ifndef __DALI_INTERNAL_SCENE_GRAPH_RENDER_ITEM_H__ -#define __DALI_INTERNAL_SCENE_GRAPH_RENDER_ITEM_H__ +#ifndef DALI_INTERNAL_SCENE_GRAPH_RENDER_ITEM_H +#define DALI_INTERNAL_SCENE_GRAPH_RENDER_ITEM_H /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * 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. @@ -45,6 +45,7 @@ struct RenderItem { /** * Construct a new RenderItem + * @return A pointer to a new RenderItem. */ static RenderItem* New(); @@ -56,6 +57,7 @@ struct RenderItem /** * Overriden delete operator. * Deletes the RenderItem from its global memory pool + * @param[in] A pointer to the RenderItem to delete. */ void operator delete( void* ptr ); @@ -78,6 +80,7 @@ private: // RenderItems should not be copied as they are heavy RenderItem( const RenderItem& item ); RenderItem& operator = ( const RenderItem& item ); + }; } // namespace SceneGraph @@ -86,4 +89,4 @@ private: } // namespace Dali -#endif // __DALI_INTERNAL_SCENE_GRAPH_RENDER_ITEM_H__ +#endif // DALI_INTERNAL_SCENE_GRAPH_RENDER_ITEM_H diff --git a/dali/internal/render/common/render-list.h b/dali/internal/render/common/render-list.h index 734ad0f..1aef561 100644 --- a/dali/internal/render/common/render-list.h +++ b/dali/internal/render/common/render-list.h @@ -1,8 +1,8 @@ -#ifndef __DALI_INTERNAL_SCENE_GRAPH_RENDER_LIST_H__ -#define __DALI_INTERNAL_SCENE_GRAPH_RENDER_LIST_H__ +#ifndef DALI_INTERNAL_SCENE_GRAPH_RENDER_LIST_H +#define DALI_INTERNAL_SCENE_GRAPH_RENDER_LIST_H /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * 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. @@ -47,29 +47,17 @@ struct RenderList; typedef OwnerContainer< RenderList* > RenderListContainer; /** - * The RenderList structure provides the renderer with a list of renderers and - * a set of flags to tell it what depth buffering is required. + * The RenderList structure provides the renderer with a list of renderers. */ struct RenderList { public: /** - * The RenderFlags describe how the objects are rendered using the stencil buffer. - */ - enum RenderFlags - { - STENCIL_BUFFER_ENABLED = 1 << 0, ///< If stencil buffer should be used for writing / test operation - STENCIL_WRITE = 1 << 1, ///< If the stencil buffer is writable - STENCIL_CLEAR = 1 << 2, ///< If the stencil buffer should first be cleared - }; - - /** * Constructor */ RenderList() : mNextFree( 0 ), - mRenderFlags( 0u ), mClippingBox( NULL ), mSourceLayer( NULL ), mHasColorRenderItems( false ) @@ -81,44 +69,17 @@ public: */ ~RenderList() { - // pointer container deletes the render items + // Pointer container deletes the render items delete mClippingBox; } /** - * Clear the render flags - */ - void ClearFlags() - { - mRenderFlags = 0u; - } - - /** - * Set particular render flags - * @param[in] flags The set of flags to bitwise or with existing flags - */ - void SetFlags( unsigned int flags ) - { - mRenderFlags |= flags; - } - - /** - * Retrieve the render flags. - * @return the render flags. - */ - unsigned int GetFlags() const - { - return mRenderFlags; - } - - /** * Reset the render list for next frame */ void Reset() { - // we dont want to delete and re-create the render items every frame + // We don't want to delete and re-create the render items every frame mNextFree = 0; - mRenderFlags = 0u; delete mClippingBox; mClippingBox = NULL; @@ -207,7 +168,7 @@ public: */ bool IsEmpty() const { - return (mNextFree == 0); + return ( mNextFree == 0 ); } /** @@ -219,9 +180,8 @@ public: { if( clipping ) { - ClippingBox* newBox = new ClippingBox( box ); delete mClippingBox; - mClippingBox = newBox; + mClippingBox = new ClippingBox( box );; } } @@ -230,7 +190,7 @@ public: */ bool IsClipping() const { - return (NULL != mClippingBox); + return ( NULL != mClippingBox ); } /** @@ -306,17 +266,17 @@ private: RenderItemContainer mItems; ///< Each item is a renderer and matrix pair RenderItemContainer::SizeType mNextFree; ///< index for the next free item to use - unsigned int mRenderFlags; ///< The render flags - ClippingBox* mClippingBox; ///< The clipping box, in window coordinates, when clipping is enabled Layer* mSourceLayer; ///< The originating layer where the renderers are from bool mHasColorRenderItems : 1; ///< True if list contains color render items + }; + } // namespace SceneGraph } // namespace Internal } // namespace Dali -#endif // __DALI_INTERNAL_SCENE_GRAPH_RENDER_LIST_H__ +#endif // DALI_INTERNAL_SCENE_GRAPH_RENDER_LIST_H diff --git a/dali/internal/render/renderers/render-renderer.cpp b/dali/internal/render/renderers/render-renderer.cpp index 4dfb27a..021c106 100644 --- a/dali/internal/render/renderers/render-renderer.cpp +++ b/dali/internal/render/renderers/render-renderer.cpp @@ -625,7 +625,7 @@ void Renderer::Render( Context& context, } } -void Renderer::SetSortAttributes( BufferIndex bufferIndex, SceneGraph::RendererWithSortAttributes& sortAttributes ) const +void Renderer::SetSortAttributes( BufferIndex bufferIndex, SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes ) const { sortAttributes.shader = &( mRenderDataProvider->GetShader() ); const std::vector& textures( mRenderDataProvider->GetTextures() ); diff --git a/dali/internal/render/renderers/render-renderer.h b/dali/internal/render/renderers/render-renderer.h index 0f17f26..fa04275 100644 --- a/dali/internal/render/renderers/render-renderer.h +++ b/dali/internal/render/renderers/render-renderer.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include namespace Dali @@ -50,7 +50,6 @@ class TextureCache; class NodeDataProvider; } - namespace Render { @@ -372,7 +371,7 @@ public: * @param[in] bufferIndex The current update buffer index. * @param[out] sortAttributes */ - void SetSortAttributes( BufferIndex bufferIndex, SceneGraph::RendererWithSortAttributes& sortAttributes ) const; + void SetSortAttributes( BufferIndex bufferIndex, SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes ) const; private: @@ -427,11 +426,12 @@ private: struct UniformIndexMap { - unsigned int uniformIndex; ///< The index of the cached location in the Program + unsigned int uniformIndex; ///< The index of the cached location in the Program const PropertyInputImpl* propertyValue; }; typedef Dali::Vector< UniformIndexMap > UniformIndexMappings; + UniformIndexMappings mUniformIndexMap; Vector mAttributesLocation; @@ -448,6 +448,7 @@ private: DepthTestMode::Type mDepthTestMode:2; ///< The depth test mode bool mUpdateAttributesLocation:1; ///< Indicates attribute locations have changed bool mPremultipledAlphaEnabled:1; ///< Flag indicating whether the Pre-multiplied Alpha Blending is required + }; } // namespace SceneGraph diff --git a/dali/internal/update/manager/prepare-render-instructions.cpp b/dali/internal/update/manager/prepare-render-instructions.cpp deleted file mode 100644 index 41616a1..0000000 --- a/dali/internal/update/manager/prepare-render-instructions.cpp +++ /dev/null @@ -1,516 +0,0 @@ -/* - * 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. - * - */ - -// CLASS HEADER -#include - -// INTERNAL INCLUDES -#include -#include -#include -#include // for the default sorting function -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace -{ -#if defined(DEBUG_ENABLED) -Debug::Filter* gRenderListLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RENDER_LISTS"); -#endif -} - -namespace Dali -{ - -namespace Internal -{ - -namespace SceneGraph -{ - -/** - * Add a renderer to the list - * @param updateBufferIndex to read the model matrix from - * @param renderList to add the item to - * @param renderable Node-Renderer pair - * @param viewMatrix used to calculate modelview matrix for the item - * @param camera The camera used to render - * @param isLayer3d Whether we are processing a 3D layer or not - * @param cull Whether frustum culling is enabled or not - */ -inline void AddRendererToRenderList( BufferIndex updateBufferIndex, - RenderList& renderList, - Renderable& renderable, - const Matrix& viewMatrix, - SceneGraph::Camera& camera, - bool isLayer3d, - bool cull ) -{ - bool inside( true ); - if ( cull && !renderable.mRenderer->GetShader().HintEnabled( Dali::Shader::Hint::MODIFIES_GEOMETRY ) ) - { - const Vector4& boundingSphere = renderable.mNode->GetBoundingSphere(); - inside = (boundingSphere.w > Math::MACHINE_EPSILON_1000) && - (camera.CheckSphereInFrustum( updateBufferIndex, Vector3(boundingSphere), boundingSphere.w ) ); - } - - if ( inside ) - { - Renderer::Opacity opacity = renderable.mRenderer->GetOpacity( updateBufferIndex, *renderable.mNode ); - if( opacity != Renderer::TRANSPARENT ) - { - // Get the next free RenderItem - RenderItem& item = renderList.GetNextFreeItem(); - item.mRenderer = &renderable.mRenderer->GetRenderer(); - item.mNode = renderable.mNode; - item.mIsOpaque = (opacity == Renderer::OPAQUE); - - if( isLayer3d ) - { - item.mDepthIndex = renderable.mRenderer->GetDepthIndex(); - } - else - { - item.mDepthIndex = renderable.mRenderer->GetDepthIndex() + static_cast( renderable.mNode->GetDepth() ) * Dali::Layer::TREE_DEPTH_MULTIPLIER; - } - // save MV matrix onto the item - renderable.mNode->GetWorldMatrixAndSize( item.mModelMatrix, item.mSize ); - Matrix::Multiply( item.mModelViewMatrix, item.mModelMatrix, viewMatrix ); - } - } -} - -/** - * Add all renderers to the list - * @param updateBufferIndex to read the model matrix from - * @param renderList to add the items to - * @param renderers to render - * NodeRendererContainer Node-Renderer pairs - * @param viewMatrix used to calculate modelview matrix for the items - * @param camera The camera used to render - * @param isLayer3d Whether we are processing a 3D layer or not - * @param cull Whether frustum culling is enabled or not - */ -inline void AddRenderersToRenderList( BufferIndex updateBufferIndex, - RenderList& renderList, - RenderableContainer& renderers, - const Matrix& viewMatrix, - SceneGraph::Camera& camera, - bool isLayer3d, - bool cull) -{ - DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "AddRenderersToRenderList()\n"); - - unsigned int rendererCount( renderers.Size() ); - for( unsigned int i(0); iGetRenderer(); - checkSumNew += size_t( &renderer ); - checkSumOld += size_t( &renderList.GetRenderer( index ) ); - } - if( checkSumNew == checkSumOld ) - { - // tell list to reuse its existing items - renderList.ReuseCachedItems(); - retValue = true; - } - } - return retValue; -} - -/** - * Function which sorts render items by depth index then by instance - * ptrs of shader/texture/geometry. - * @param lhs item - * @param rhs item - * @return true if left item is greater than right - */ -bool CompareItems( const RendererWithSortAttributes& lhs, const RendererWithSortAttributes& rhs ) -{ - if( lhs.renderItem->mDepthIndex == rhs.renderItem->mDepthIndex ) - { - if( lhs.shader == rhs.shader ) - { - if( lhs.textureResourceId == rhs.textureResourceId ) - { - return lhs.geometry < rhs.geometry; - } - return lhs.textureResourceId < rhs.textureResourceId; - } - return lhs.shader < rhs.shader; - } - return lhs.renderItem->mDepthIndex < rhs.renderItem->mDepthIndex; -} -/** - * Function which sorts the render items by Z function, then - * by instance ptrs of shader/texture/geometry. - * @param lhs item - * @param rhs item - * @return true if left item is greater than right - */ -bool CompareItems3D( const RendererWithSortAttributes& lhs, const RendererWithSortAttributes& rhs ) -{ - bool lhsIsOpaque = lhs.renderItem->mIsOpaque; - if( lhsIsOpaque == rhs.renderItem->mIsOpaque ) - { - if( lhsIsOpaque ) - { - //If both RenderItems are opaque, sort using shader, then texture then geometry - if( lhs.shader == rhs.shader ) - { - if( lhs.textureResourceId == rhs.textureResourceId ) - { - return lhs.geometry < rhs.geometry; - } - return lhs.textureResourceId < rhs.textureResourceId; - } - return lhs.shader < rhs.shader; - } - else - { - //If both RenderItems are transparent, sort using z,then shader, then texture, then geometry - if( Equals(lhs.zValue, rhs.zValue) ) - { - if( lhs.shader == rhs.shader ) - { - if( lhs.textureResourceId == rhs.textureResourceId ) - { - return lhs.geometry < rhs.geometry; - } - return lhs.textureResourceId < rhs.textureResourceId; - } - return lhs.shader < rhs.shader; - } - return lhs.zValue > rhs.zValue; - } - } - else - { - return lhsIsOpaque; - } -} - -/** - * Sort render items - * @param bufferIndex The buffer to read from - * @param renderList to sort - * @param layer where the renderers are from - * @param sortingHelper to use for sorting the renderitems (to avoid reallocating) - */ -inline void SortRenderItems( BufferIndex bufferIndex, RenderList& renderList, Layer& layer, RendererSortingHelper& sortingHelper ) -{ - const size_t renderableCount = renderList.Count(); - // reserve space if needed - const unsigned int oldcapacity = sortingHelper.size(); - if( oldcapacity < renderableCount ) - { - sortingHelper.reserve( renderableCount ); - // add real objects (reserve does not construct objects) - sortingHelper.insert( sortingHelper.begin() + oldcapacity, - (renderableCount - oldcapacity), - RendererWithSortAttributes() ); - } - else - { - // clear extra elements from helper, does not decrease capability - sortingHelper.resize( renderableCount ); - } - - // calculate the sorting value, once per item by calling the layers sort function - // Using an if and two for-loops rather than if inside for as its better for branch prediction - if( layer.UsesDefaultSortFunction() ) - { - for( size_t index = 0; index < renderableCount; ++index ) - { - RenderItem& item = renderList.GetItem( index ); - - item.mRenderer->SetSortAttributes( bufferIndex, sortingHelper[ index ] ); - - // the default sorting function should get inlined here - sortingHelper[ index ].zValue = Internal::Layer::ZValue( item.mModelViewMatrix.GetTranslation3() ) - item.mDepthIndex; - - // keep the renderitem pointer in the helper so we can quickly reorder items after sort - sortingHelper[ index ].renderItem = &item; - } - } - else - { - const Dali::Layer::SortFunctionType sortFunction = layer.GetSortFunction(); - for( size_t index = 0; index < renderableCount; ++index ) - { - RenderItem& item = renderList.GetItem( index ); - - item.mRenderer->SetSortAttributes( bufferIndex, sortingHelper[ index ] ); - sortingHelper[ index ].zValue = (*sortFunction)( item.mModelViewMatrix.GetTranslation3() ) - item.mDepthIndex; - - // keep the renderitem pointer in the helper so we can quickly reorder items after sort - sortingHelper[ index ].renderItem = &item; - } - } - - if( layer.GetBehavior() == Dali::Layer::LAYER_3D) - { - // sort the renderers back to front, Z Axis point from near plane to far plane - std::stable_sort( sortingHelper.begin(), sortingHelper.end(), CompareItems3D ); - } - else - { - // sort the renderers based on DepthIndex - std::stable_sort( sortingHelper.begin(), sortingHelper.end(), CompareItems ); - } - - // reorder/repopulate the renderitems in renderlist to correct order based on sortinghelper - DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "Sorted Transparent List:\n"); - RenderItemContainer::Iterator renderListIter = renderList.GetContainer().Begin(); - for( unsigned int index = 0; index < renderableCount; ++index, ++renderListIter ) - { - *renderListIter = sortingHelper[ index ].renderItem; - DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, " sortedList[%d] = %p\n", index, sortingHelper[ index ].renderItem->mRenderer); - } -} - -/** - * Add color renderers from the layer onto the next free render list - * @param updateBufferIndex to use - * @param layer to get the renderers from - * @param viewmatrix for the camera from rendertask - * @param camera to use the view frustum - * @param stencilRenderablesExist is true if there are stencil renderers on this layer - * @param instruction to fill in - * @param sortingHelper to use for sorting the renderitems (to avoid reallocating) - * @param tryReuseRenderList whether to try to reuse the cached items from the instruction - * @param cull Whether frustum culling is enabled or not - */ -inline void AddColorRenderers( BufferIndex updateBufferIndex, - Layer& layer, - const Matrix& viewMatrix, - SceneGraph::Camera& camera, - bool stencilRenderablesExist, - RenderInstruction& instruction, - RendererSortingHelper& sortingHelper, - bool tryReuseRenderList, - bool cull) -{ - RenderList& renderList = instruction.GetNextFreeRenderList( layer.colorRenderables.Size() ); - renderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() ); - renderList.SetSourceLayer( &layer ); - renderList.SetHasColorRenderItems( true ); - - // try to reuse cached renderitems from last time around - if( tryReuseRenderList ) - { - if( TryReuseCachedRenderers( layer, renderList, layer.colorRenderables ) ) - { - return; - } - } - - AddRenderersToRenderList( updateBufferIndex, renderList, layer.colorRenderables, viewMatrix, camera, layer.GetBehavior() == Dali::Layer::LAYER_3D, cull ); - SortRenderItems( updateBufferIndex, renderList, layer, sortingHelper ); - - // Setup the render flags for stencil. - renderList.ClearFlags(); - if( stencilRenderablesExist ) - { - // Note: SetFlags does not overwrite, it ORs, so ClearFlags() is also required. - renderList.SetFlags( RenderList::STENCIL_BUFFER_ENABLED ); - } -} - -/** - * Add overlay renderers from the layer onto the next free render list - * @param updateBufferIndex to use - * @param layer to get the renderers from - * @param viewmatrix for the camera from rendertask - * @param camera to use - * @param stencilRenderablesExist is true if there are stencil renderers on this layer - * @param instruction to fill in - * @param tryReuseRenderList whether to try to reuse the cached items from the instruction - * @param cull Whether frustum culling is enabled or not - */ -inline void AddOverlayRenderers( BufferIndex updateBufferIndex, - Layer& layer, - const Matrix& viewMatrix, - SceneGraph::Camera& camera, - bool stencilRenderablesExist, - RenderInstruction& instruction, - RendererSortingHelper& sortingHelper, - bool tryReuseRenderList, - bool cull ) -{ - RenderList& overlayRenderList = instruction.GetNextFreeRenderList( layer.overlayRenderables.Size() ); - overlayRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() ); - overlayRenderList.SetSourceLayer( &layer ); - overlayRenderList.SetHasColorRenderItems( false ); - - //Set render flags - overlayRenderList.ClearFlags(); - if(stencilRenderablesExist) - { - overlayRenderList.SetFlags(RenderList::STENCIL_BUFFER_ENABLED); - } - - // try to reuse cached renderitems from last time around - if( tryReuseRenderList ) - { - if( TryReuseCachedRenderers( layer, overlayRenderList, layer.overlayRenderables ) ) - { - return; - } - } - AddRenderersToRenderList( updateBufferIndex, overlayRenderList, layer.overlayRenderables, viewMatrix, camera, layer.GetBehavior() == Dali::Layer::LAYER_3D, cull ); - SortRenderItems( updateBufferIndex, overlayRenderList, layer, sortingHelper ); -} - -/** - * Add stencil renderers from the layer onto the next free render list - * @param updateBufferIndex to use - * @param layer to get the renderers from - * @param viewmatrix for the camera from rendertask - * @param camera to use - * @param instruction to fill in - * @param tryReuseRenderList whether to try to reuse the cached items from the instruction - * @param cull Whether frustum culling is enabled or not - */ -inline void AddStencilRenderers( BufferIndex updateBufferIndex, - Layer& layer, - const Matrix& viewMatrix, - SceneGraph::Camera& camera, - RenderInstruction& instruction, - bool tryReuseRenderList, - bool cull ) -{ - RenderList& stencilRenderList = instruction.GetNextFreeRenderList( layer.stencilRenderables.Size() ); - stencilRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() ); - stencilRenderList.SetSourceLayer( &layer ); - stencilRenderList.SetHasColorRenderItems( false ); - - //Set render flags - stencilRenderList.ClearFlags(); - stencilRenderList.SetFlags(RenderList::STENCIL_CLEAR | RenderList::STENCIL_WRITE | RenderList::STENCIL_BUFFER_ENABLED ); - - // try to reuse cached renderitems from last time around - if( tryReuseRenderList ) - { - if( TryReuseCachedRenderers( layer, stencilRenderList, layer.stencilRenderables ) ) - { - return; - } - } - AddRenderersToRenderList( updateBufferIndex, stencilRenderList, layer.stencilRenderables, viewMatrix, camera, layer.GetBehavior() == Dali::Layer::LAYER_3D, cull ); -} - -void PrepareRenderInstruction( BufferIndex updateBufferIndex, - SortedLayerPointers& sortedLayers, - RenderTask& renderTask, - RendererSortingHelper& sortingHelper, - bool cull, - RenderInstructionContainer& instructions ) -{ - // Retrieve the RenderInstruction buffer from the RenderInstructionContainer - // then populate with instructions. - RenderInstruction& instruction = instructions.GetNextInstruction( updateBufferIndex ); - renderTask.PrepareRenderInstruction( instruction, updateBufferIndex ); - bool viewMatrixHasNotChanged = !renderTask.ViewMatrixUpdated(); - - const Matrix& viewMatrix = renderTask.GetViewMatrix( updateBufferIndex ); - SceneGraph::Camera& camera = renderTask.GetCamera(); - - const SortedLayersIter endIter = sortedLayers.end(); - for ( SortedLayersIter iter = sortedLayers.begin(); iter != endIter; ++iter ) - { - Layer& layer = **iter; - - const bool stencilRenderablesExist( !layer.stencilRenderables.Empty() ); - const bool colorRenderablesExist( !layer.colorRenderables.Empty() ); - const bool overlayRenderablesExist( !layer.overlayRenderables.Empty() ); - const bool tryReuseRenderList( viewMatrixHasNotChanged && layer.CanReuseRenderers( &renderTask.GetCamera() ) ); - - // Ignore stencils if there's nothing to test - if( stencilRenderablesExist && - ( colorRenderablesExist || overlayRenderablesExist ) ) - { - AddStencilRenderers( updateBufferIndex, layer, viewMatrix, camera, instruction, tryReuseRenderList, cull ); - } - - if ( colorRenderablesExist ) - { - AddColorRenderers( updateBufferIndex, - layer, - viewMatrix, - camera, - stencilRenderablesExist, - instruction, - sortingHelper, - tryReuseRenderList, - cull ); - } - - if ( overlayRenderablesExist ) - { - AddOverlayRenderers( updateBufferIndex, layer, viewMatrix, camera, stencilRenderablesExist, - instruction, sortingHelper, tryReuseRenderList, cull ); - } - } - - // inform the render instruction that all renderers have been added and this frame is complete - instruction.UpdateCompleted(); -} - -} // SceneGraph - -} // Internal - -} // Dali diff --git a/dali/internal/update/manager/prepare-render-instructions.h b/dali/internal/update/manager/prepare-render-instructions.h deleted file mode 100644 index 0abbc2b..0000000 --- a/dali/internal/update/manager/prepare-render-instructions.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef __DALI_INTERNAL_SCENE_GRAPH_PREPARE_RENDER_INSTRUCTIONS_H__ -#define __DALI_INTERNAL_SCENE_GRAPH_PREPARE_RENDER_INSTRUCTIONS_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 -#include -#include - -namespace Dali -{ - -namespace Internal -{ - -namespace Render -{ -class Geometry; -} - -namespace SceneGraph -{ -class RenderTracker; -struct RenderItem; -class Shader; - -/** - * Structure to store information for sorting the renderers. - * (Note, depthIndex is stored within the renderItem). - */ -struct RendererWithSortAttributes -{ - RendererWithSortAttributes() - : renderItem( NULL ), - shader(NULL), - textureResourceId( Integration::InvalidResourceId ), - geometry(NULL), - zValue(0.0f) - { - } - - RenderItem* renderItem; ///< The render item that is being sorted (includes depth index) - const Shader* shader; ///< The shader instance - Integration::ResourceId textureResourceId;///< The first texture resource ID of the texture set instance, is InvalidResourceId if the texture set doesn't have any textures - const Render::Geometry* geometry; ///< The geometry instance - float zValue; ///< The zValue of the given renderer (either distance from camera, or a custom calculated value) -}; - -typedef std::vector< RendererWithSortAttributes > RendererSortingHelper; - -class RenderTask; -class RenderInstructionContainer; - -/** - * Sorts and prepares the list of opaque/transparent renderers for each layer. - * Whilst iterating through each layer, update the renderitems ModelView matrices - * - * The opaque and transparent render lists are sorted first by depth - * index, then by Z (for transparent only), then by shader, texture - * and geometry. The render algorithm should then work through both - * lists simultaneously, working through opaque then transparent - * items at each depth index, resetting the flags appropriately. - * - * @param[in] updateBufferIndex The current update buffer index. - * @param[in] sortedLayers The layers containing lists of opaque/transparent renderables. - * @param[in] renderTask The rendering task information. - * @param[in] sortingHelper to avoid allocating containers for sorting every frame - * @param[in] cull Whether frustum culling is enabled or not - * @param[out] instructions The rendering instructions for the next frame. - */ -void PrepareRenderInstruction( BufferIndex updateBufferIndex, - SortedLayerPointers& sortedLayers, - RenderTask& renderTask, - RendererSortingHelper& sortingHelper, - bool cull, - RenderInstructionContainer& instructions ); - -} // namespace SceneGraph - -} // namespace Internal - -} // namespace Dali - -#endif // __DALI_INTERNAL_SCENE_GRAPH_PREPARE_RENDER_INSTRUCTIONS_H__ diff --git a/dali/internal/update/manager/process-render-tasks.h b/dali/internal/update/manager/process-render-tasks.h deleted file mode 100644 index 24df0ea..0000000 --- a/dali/internal/update/manager/process-render-tasks.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef __DALI_INTERNAL_SCENE_GRAPH_PROCESS_RENDER_TASKS_H__ -#define __DALI_INTERNAL_SCENE_GRAPH_PROCESS_RENDER_TASKS_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 -#include - -namespace Dali -{ -namespace Internal -{ - -namespace SceneGraph -{ - -class RenderTaskList; - -/** - * Process the list of render-tasks; the output is a series of render instructions. - * @note When ProcessRenderTasks is called, the layers should already the transparent/opaque renderers which are ready to render. - * If there is only one default render-task, then no further processing is required. - * @param[in] updateBufferIndex The current update buffer index. - * @param[in] renderTasks The list of render-tasks. - * @param[in] rootNode The root node of the scene-graph. - * @param[in] sortedLayers The layers containing lists of opaque/transparent renderables. - * @param[in] sortingHelper Helper container for sorting transparent renderables. - * @param[out] instructions The instructions for rendering the next frame. - */ -void ProcessRenderTasks( BufferIndex updateBufferIndex, - RenderTaskList& renderTasks, - Layer& rootNode, - SortedLayerPointers& sortedLayers, - RendererSortingHelper& sortingHelper, - RenderInstructionContainer& instructions ); - -} // namespace SceneGraph - -} // namespace Internal - -} // namespace Dali - -#endif // __DALI_INTERNAL_SCENE_GRAPH_PROCESS_RENDER_TASKS_H__ diff --git a/dali/internal/update/manager/render-instruction-processor.cpp b/dali/internal/update/manager/render-instruction-processor.cpp new file mode 100644 index 0000000..76dcc26 --- /dev/null +++ b/dali/internal/update/manager/render-instruction-processor.cpp @@ -0,0 +1,450 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include // for the default sorting function +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ +#if defined(DEBUG_ENABLED) +Debug::Filter* gRenderListLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RENDER_LISTS"); +#endif +} + +namespace Dali +{ + +namespace Internal +{ + +namespace SceneGraph +{ + +namespace +{ + +/** + * Function which sorts render items by depth index then by instance + * ptrs of shader/geometry/material. + * @param[in] lhs Left hand side item + * @param[in] rhs Right hand side item + * @return True if left item is greater than right + */ +bool CompareItems( const RenderInstructionProcessor::SortAttributes& lhs, const RenderInstructionProcessor::SortAttributes& rhs ) +{ + // @todo Consider replacing all these sortAttributes with a single long int that + // encapsulates the same data (e.g. the middle-order bits of the ptrs). + if( lhs.renderItem->mDepthIndex == rhs.renderItem->mDepthIndex ) + { + if( lhs.shader == rhs.shader ) + { + if( lhs.textureResourceId == rhs.textureResourceId ) + { + return lhs.geometry < rhs.geometry; + } + return lhs.textureResourceId < rhs.textureResourceId; + } + return lhs.shader < rhs.shader; + } + return lhs.renderItem->mDepthIndex < rhs.renderItem->mDepthIndex; +} + +/** + * Function which sorts render items by clipping hierarchy, then depth index and instance + * ptrs of shader/geometry/material. + * @param[in] lhs Left hand side item + * @param[in] rhs Right hand side item + * @return True if left item is greater than right + */ +bool CompareItemsWithClipping( const RenderInstructionProcessor::SortAttributes& lhs, const RenderInstructionProcessor::SortAttributes& rhs ) +{ + // Items must be sorted in order of clipping first, otherwise incorrect clipping regions could be used. + if( lhs.renderItem->mNode->mClippingSortModifier == rhs.renderItem->mNode->mClippingSortModifier ) + { + return CompareItems( lhs, rhs ); + } + + return lhs.renderItem->mNode->mClippingSortModifier < rhs.renderItem->mNode->mClippingSortModifier; +} + +/** + * Function which sorts the render items by Z function, then + * by instance ptrs of shader / geometry / material. + * @param[in] lhs Left hand side item + * @param[in] rhs Right hand side item + * @return True if left item is greater than right + */ +bool CompareItems3D( const RenderInstructionProcessor::SortAttributes& lhs, const RenderInstructionProcessor::SortAttributes& rhs ) +{ + bool lhsIsOpaque = lhs.renderItem->mIsOpaque; + if( lhsIsOpaque == rhs.renderItem->mIsOpaque ) + { + if( lhsIsOpaque ) + { + // If both RenderItems are opaque, sort using shader, then material then geometry. + if( lhs.shader == rhs.shader ) + { + if( lhs.textureResourceId == rhs.textureResourceId ) + { + return lhs.geometry < rhs.geometry; + } + return lhs.textureResourceId < rhs.textureResourceId; + } + return lhs.shader < rhs.shader; + } + else + { + // If both RenderItems are transparent, sort using Z, then shader, then material, then geometry. + if( Equals( lhs.zValue, rhs.zValue ) ) + { + if( lhs.shader == rhs.shader ) + { + if( lhs.textureResourceId == rhs.textureResourceId ) + { + return lhs.geometry < rhs.geometry; + } + return lhs.textureResourceId < rhs.textureResourceId; + } + return lhs.shader < rhs.shader; + } + return lhs.zValue > rhs.zValue; + } + } + else + { + return lhsIsOpaque; + } +} + +/** + * Function which sorts render items by clipping hierarchy, then Z function and instance ptrs of shader / geometry / material. + * @param[in] lhs Left hand side item + * @param[in] rhs Right hand side item + * @return True if left item is greater than right + */ +bool CompareItems3DWithClipping( const RenderInstructionProcessor::SortAttributes& lhs, const RenderInstructionProcessor::SortAttributes& rhs ) +{ + // Items must be sorted in order of clipping first, otherwise incorrect clipping regions could be used. + if( lhs.renderItem->mNode->mClippingSortModifier == rhs.renderItem->mNode->mClippingSortModifier ) + { + return CompareItems3D( lhs, rhs ); + } + + return lhs.renderItem->mNode->mClippingSortModifier < rhs.renderItem->mNode->mClippingSortModifier; +} + +/** + * Add a renderer to the list + * @param updateBufferIndex to read the model matrix from + * @param renderList to add the item to + * @param renderable Node-Renderer pair + * @param viewMatrix used to calculate modelview matrix for the item + * @param camera The camera used to render + * @param isLayer3d Whether we are processing a 3D layer or not + * @param cull Whether frustum culling is enabled or not + */ +inline void AddRendererToRenderList( BufferIndex updateBufferIndex, + RenderList& renderList, + Renderable& renderable, + const Matrix& viewMatrix, + SceneGraph::Camera& camera, + bool isLayer3d, + bool cull ) +{ + bool inside( true ); + if ( cull && !renderable.mRenderer->GetShader().HintEnabled( Dali::Shader::Hint::MODIFIES_GEOMETRY ) ) + { + const Vector4& boundingSphere = renderable.mNode->GetBoundingSphere(); + inside = (boundingSphere.w > Math::MACHINE_EPSILON_1000) && + (camera.CheckSphereInFrustum( updateBufferIndex, Vector3(boundingSphere), boundingSphere.w ) ); + } + + if ( inside ) + { + Renderer::Opacity opacity = renderable.mRenderer->GetOpacity( updateBufferIndex, *renderable.mNode ); + if( opacity != Renderer::TRANSPARENT ) + { + // Get the next free RenderItem. + RenderItem& item = renderList.GetNextFreeItem(); + item.mRenderer = &renderable.mRenderer->GetRenderer(); + item.mNode = renderable.mNode; + item.mIsOpaque = ( opacity == Renderer::OPAQUE ); + item.mDepthIndex = renderable.mRenderer->GetDepthIndex(); + + if( !isLayer3d ) + { + item.mDepthIndex += static_cast( renderable.mNode->GetDepth() ) * Dali::Layer::TREE_DEPTH_MULTIPLIER; + } + + // Save ModelView matrix onto the item. + renderable.mNode->GetWorldMatrixAndSize( item.mModelMatrix, item.mSize ); + Matrix::Multiply( item.mModelViewMatrix, item.mModelMatrix, viewMatrix ); + } + } +} + +/** + * Add all renderers to the list + * @param updateBufferIndex to read the model matrix from + * @param renderList to add the items to + * @param renderers to render + * NodeRendererContainer Node-Renderer pairs + * @param viewMatrix used to calculate modelview matrix for the items + * @param camera The camera used to render + * @param isLayer3d Whether we are processing a 3D layer or not + * @param cull Whether frustum culling is enabled or not + */ +inline void AddRenderersToRenderList( BufferIndex updateBufferIndex, + RenderList& renderList, + RenderableContainer& renderers, + const Matrix& viewMatrix, + SceneGraph::Camera& camera, + bool isLayer3d, + bool cull ) +{ + DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "AddRenderersToRenderList()\n"); + + unsigned int rendererCount( renderers.Size() ); + for( unsigned int i(0); i < rendererCount; ++i ) + { + AddRendererToRenderList( updateBufferIndex, renderList, renderers[i], viewMatrix, camera, isLayer3d, cull ); + } +} + +/** + * Try to reuse cached RenderItems from the RenderList + * This avoids recalculating the model view matrices in case this part of the scene was static + * An example case is a toolbar layer that rarely changes or a popup on top of the rest of the stage + * @param layer that is being processed + * @param renderList that is cached from frame N-1 + * @param renderables list of renderables + */ +inline bool TryReuseCachedRenderers( Layer& layer, + RenderList& renderList, + RenderableContainer& renderables ) +{ + bool retValue = false; + size_t renderableCount = renderables.Size(); + // Check that the cached list originates from this layer and that the counts match + if( ( renderList.GetSourceLayer() == &layer )&& + ( renderList.GetCachedItemCount() == renderableCount ) ) + { + // Check that all the same renderers are there. This gives us additional security in avoiding rendering the wrong things. + // Render list is sorted so at this stage renderers may be in different order. + // Therefore we check a combined sum of all renderer addresses. + size_t checkSumNew = 0; + size_t checkSumOld = 0; + for( size_t index = 0; index < renderableCount; ++index ) + { + const Render::Renderer& renderer = renderables[index].mRenderer->GetRenderer(); + checkSumNew += size_t( &renderer ); + checkSumOld += size_t( &renderList.GetRenderer( index ) ); + } + if( checkSumNew == checkSumOld ) + { + // tell list to reuse its existing items + renderList.ReuseCachedItems(); + retValue = true; + } + } + return retValue; +} + +inline bool SetupRenderList( RenderableContainer& renderables, + Layer& layer, + RenderInstruction& instruction, + bool tryReuseRenderList, + RenderList** renderList ) +{ + *renderList = &( instruction.GetNextFreeRenderList( renderables.Size() ) ); + ( *renderList )->SetClipping( layer.IsClipping(), layer.GetClippingBox() ); + ( *renderList )->SetSourceLayer( &layer ); + + // Try to reuse cached RenderItems from last time around. + return ( tryReuseRenderList && TryReuseCachedRenderers( layer, **renderList, renderables ) ); +} + +} // Anonymous namespace. + + +RenderInstructionProcessor::RenderInstructionProcessor() +: mSortingHelper() +{ + // Set up a container of comparators for fast run-time selection. + mSortComparitors.Reserve( 4u ); + + mSortComparitors.PushBack( CompareItems ); + mSortComparitors.PushBack( CompareItemsWithClipping ); + mSortComparitors.PushBack( CompareItems3D ); + mSortComparitors.PushBack( CompareItems3DWithClipping ); +} + +RenderInstructionProcessor::~RenderInstructionProcessor() +{ +} + +inline void RenderInstructionProcessor::SortRenderItems( BufferIndex bufferIndex, RenderList& renderList, Layer& layer, bool respectClippingOrder ) +{ + const size_t renderableCount = renderList.Count(); + // Reserve space if needed. + const unsigned int oldcapacity = mSortingHelper.size(); + if( oldcapacity < renderableCount ) + { + mSortingHelper.reserve( renderableCount ); + // Add real objects (reserve does not construct objects). + mSortingHelper.insert( mSortingHelper.begin() + oldcapacity, + (renderableCount - oldcapacity), + RenderInstructionProcessor::SortAttributes() ); + } + else + { + // Clear extra elements from helper, does not decrease capability. + mSortingHelper.resize( renderableCount ); + } + + // Calculate the sorting value, once per item by calling the layers sort function. + // Using an if and two for-loops rather than if inside for as its better for branch prediction. + if( layer.UsesDefaultSortFunction() ) + { + for( size_t index = 0; index < renderableCount; ++index ) + { + RenderItem& item = renderList.GetItem( index ); + + item.mRenderer->SetSortAttributes( bufferIndex, mSortingHelper[ index ] ); + + // The default sorting function should get inlined here. + mSortingHelper[ index ].zValue = Internal::Layer::ZValue( item.mModelViewMatrix.GetTranslation3() ) - item.mDepthIndex; + + // Keep the renderitem pointer in the helper so we can quickly reorder items after sort. + mSortingHelper[ index ].renderItem = &item; + } + } + else + { + const Dali::Layer::SortFunctionType sortFunction = layer.GetSortFunction(); + for( size_t index = 0; index < renderableCount; ++index ) + { + RenderItem& item = renderList.GetItem( index ); + + item.mRenderer->SetSortAttributes( bufferIndex, mSortingHelper[ index ] ); + mSortingHelper[ index ].zValue = (*sortFunction)( item.mModelViewMatrix.GetTranslation3() ) - item.mDepthIndex; + + // Keep the RenderItem pointer in the helper so we can quickly reorder items after sort. + mSortingHelper[ index ].renderItem = &item; + } + } + + // Here we detemine which comparitor (of the 4) to use. + // The comparitors work like a bitmask. + // 1 << 0 is added to select a clipping comparitor. + // 1 << 1 is added for 3D comparitors. + const unsigned int comparitorIndex = ( respectClippingOrder ? ( 1u << 0u ) : 0u ) | + ( layer.GetBehavior() == Dali::Layer::LAYER_3D ? ( 1u << 1u ) : 0u ); + + std::stable_sort( mSortingHelper.begin(), mSortingHelper.end(), mSortComparitors[ comparitorIndex ] ); + + // Reorder / re-populate the RenderItems in the RenderList to correct order based on the sortinghelper. + DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "Sorted Transparent List:\n"); + RenderItemContainer::Iterator renderListIter = renderList.GetContainer().Begin(); + for( unsigned int index = 0; index < renderableCount; ++index, ++renderListIter ) + { + *renderListIter = mSortingHelper[ index ].renderItem; + DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, " sortedList[%d] = %p\n", index, mSortingHelper[ index ].renderItem->mRenderer); + } +} + +void RenderInstructionProcessor::Prepare( BufferIndex updateBufferIndex, + SortedLayerPointers& sortedLayers, + RenderTask& renderTask, + bool cull, + bool hasClippingNodes, + RenderInstructionContainer& instructions ) +{ + // Retrieve the RenderInstruction buffer from the RenderInstructionContainer + // then populate with instructions. + RenderInstruction& instruction = instructions.GetNextInstruction( updateBufferIndex ); + renderTask.PrepareRenderInstruction( instruction, updateBufferIndex ); + bool viewMatrixHasNotChanged = !renderTask.ViewMatrixUpdated(); + + const Matrix& viewMatrix = renderTask.GetViewMatrix( updateBufferIndex ); + SceneGraph::Camera& camera = renderTask.GetCamera(); + + const SortedLayersIter endIter = sortedLayers.end(); + for( SortedLayersIter iter = sortedLayers.begin(); iter != endIter; ++iter ) + { + Layer& layer = **iter; + const bool tryReuseRenderList( viewMatrixHasNotChanged && layer.CanReuseRenderers( &renderTask.GetCamera() ) ); + const bool isLayer3D = layer.GetBehavior() == Dali::Layer::LAYER_3D; + RenderList* renderList = NULL; + + if( !layer.colorRenderables.Empty() ) + { + RenderableContainer& renderables = layer.colorRenderables; + + if( !SetupRenderList( renderables, layer, instruction, tryReuseRenderList, &renderList ) ) + { + renderList->SetHasColorRenderItems( true ); + AddRenderersToRenderList( updateBufferIndex, *renderList, renderables, viewMatrix, camera, isLayer3D, cull ); + + // We only use the clipping version of the sort comparitor if any clipping nodes exist within the RenderList. + SortRenderItems( updateBufferIndex, *renderList, layer, hasClippingNodes ); + } + } + + if( !layer.overlayRenderables.Empty() ) + { + RenderableContainer& renderables = layer.overlayRenderables; + + if( !SetupRenderList( renderables, layer, instruction, tryReuseRenderList, &renderList ) ) + { + renderList->SetHasColorRenderItems( false ); + AddRenderersToRenderList( updateBufferIndex, *renderList, renderables, viewMatrix, camera, isLayer3D, cull ); + + // Clipping hierarchy is irrelevant when sorting overlay items, so we specify using the non-clipping version of the sort comparitor. + SortRenderItems( updateBufferIndex, *renderList, layer, false ); + } + } + } + + // Inform the render instruction that all renderers have been added and this frame is complete. + instruction.UpdateCompleted(); +} + + +} // SceneGraph + +} // Internal + +} // Dali diff --git a/dali/internal/update/manager/render-instruction-processor.h b/dali/internal/update/manager/render-instruction-processor.h new file mode 100644 index 0000000..a7bcfa3 --- /dev/null +++ b/dali/internal/update/manager/render-instruction-processor.h @@ -0,0 +1,148 @@ +#ifndef DALI_INTERNAL_SCENE_GRAPH_RENDER_INSTRUCTION_PROCESSOR_H +#define DALI_INTERNAL_SCENE_GRAPH_RENDER_INSTRUCTION_PROCESSOR_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 +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +namespace Render +{ +class Geometry; +} + +namespace SceneGraph +{ + +class RenderTracker; +struct RenderItem; +class Shader; +struct RenderList; +class RenderTask; +class RenderInstructionContainer; + + +/** + * @brief This class handles the sorting and preparation of Renderers for each layer. + */ +class RenderInstructionProcessor +{ +public: + + /** + * @brief Constructor. + */ + RenderInstructionProcessor(); + + /** + * @brief Destructor. + */ + ~RenderInstructionProcessor(); + + /** + * @brief Structure to store information for sorting the renderers. + * (Note, depthIndex is stored within the renderItem). + */ + struct SortAttributes + { + SortAttributes() + : renderItem( NULL ), + shader( NULL ), + textureResourceId( Integration::InvalidResourceId ), + geometry( NULL ), + zValue( 0.0f ) + { + } + + RenderItem* renderItem; ///< The render item that is being sorted (includes depth index) + const Shader* shader; ///< The shader instance + Integration::ResourceId textureResourceId; ///< The first texture resource ID of the texture set instance, is InvalidResourceId if the texture set doesn't have any textures + const Render::Geometry* geometry; ///< The geometry instance + float zValue; ///< The Z value of the given renderer (either distance from camera, or a custom calculated value) + }; + + + /** + * @brief Sorts and prepares the list of opaque/transparent Renderers for each layer. + * Whilst iterating through each layer, update the RenderItems ModelView matrices + * + * The opaque and transparent render lists are sorted first by depth + * index, then by Z (for transparent only), then by shader, texture + * and geometry. The render algorithm should then work through both + * lists simultaneously, working through opaque then transparent + * items at each depth index, resetting the flags appropriately. + * + * @param[in] updateBufferIndex The current update buffer index. + * @param[in] sortedLayers The layers containing lists of opaque/transparent renderables. + * @param[in] renderTask The rendering task information. + * @param[in] cull Whether frustum culling is enabled or not + * @param[in] hasClippingNodes Whether any clipping nodes exist within this layer, to optimize sorting if not + * @param[out] instructions The rendering instructions for the next frame. + */ + void Prepare( BufferIndex updateBufferIndex, + SortedLayerPointers& sortedLayers, + RenderTask& renderTask, + bool cull, + bool hasClippingNodes, + RenderInstructionContainer& instructions ); + +private: + + /** + * Undefine copy and assignment operators. + */ + RenderInstructionProcessor( const RenderInstructionProcessor& renderInstructionProcessor ); ///< No definition + RenderInstructionProcessor& operator=( const RenderInstructionProcessor& renderInstructionProcessor ); ///< No definition + +private: + + /** + * @brief Sort render items + * @param bufferIndex The buffer to read from + * @param renderList to sort + * @param layer where the Renderers are from + * @param respectClippingOrder Sort with the correct clipping hierarchy. + */ + inline void SortRenderItems( BufferIndex bufferIndex, RenderList& renderList, Layer& layer, bool respectClippingOrder ); + + /// Sort comparitor function pointer type. + typedef bool ( *ComparitorPointer )( const SortAttributes& lhs, const SortAttributes& rhs ); + typedef std::vector< SortAttributes > SortingHelper; + + Dali::Vector< ComparitorPointer > mSortComparitors; ///< Contains all sort comparitors, used for quick look-up + RenderInstructionProcessor::SortingHelper mSortingHelper; ///< Helper used to sort Renderers + +}; + + +} // namespace SceneGraph + +} // namespace Internal + +} // namespace Dali + +#endif // DALI_INTERNAL_SCENE_GRAPH_RENDER_INSTRUCTION_PROCESSOR_H diff --git a/dali/internal/update/manager/process-render-tasks.cpp b/dali/internal/update/manager/render-task-processor.cpp similarity index 52% rename from dali/internal/update/manager/process-render-tasks.cpp rename to dali/internal/update/manager/render-task-processor.cpp index 4ab67b4..db5afa1 100644 --- a/dali/internal/update/manager/process-render-tasks.cpp +++ b/dali/internal/update/manager/render-task-processor.cpp @@ -16,10 +16,9 @@ */ // CLASS HEADER -#include +#include // INTERNAL INCLUDES -#include #include #include #include @@ -48,22 +47,13 @@ namespace SceneGraph namespace //Unnamed namespace { -// Return false if the node or it's parents are exclusive to another render-task +// Return false if the node or it's parents are exclusive to another render-task. bool CheckExclusivity( const Node& node, const RenderTask& task ) { const RenderTask* exclusiveTo = node.GetExclusiveRenderTask(); - if ( exclusiveTo ) + if( exclusiveTo ) { - if ( exclusiveTo == &task ) - { - // Exclusive to the same render-task - return true; - } - else - { - // Exclusive to another render-task - return false; - } + return ( exclusiveTo == &task ); } const Node* parent = node.GetParent(); @@ -72,17 +62,17 @@ bool CheckExclusivity( const Node& node, const RenderTask& task ) return CheckExclusivity( *parent, task ); } - // No exclusive flags set + // No exclusive flags set. return true; } Layer* FindLayer( Node& node ) { Node* currentNode( &node ); - Layer* layer(NULL); + Layer* layer( NULL ); while( currentNode ) { - if( (layer = currentNode->GetLayer()) != NULL ) + if( ( layer = currentNode->GetLayer() ) != NULL ) { return layer; } @@ -94,45 +84,66 @@ Layer* FindLayer( Node& node ) } /** - * Rebuild the Layer::colorRenderables, stencilRenderables and overlayRenderables members, + * Rebuild the Layer::colorRenderables and overlayRenderables members, * including only renderers which are included in the current render-task. * Returns true if all renderers have finished acquiring resources. + * + * @param[in] updateBufferIndex The current update buffer index. + * @param[in] node The current node of the scene-graph. + * @param[in] currentLayer The current layer containing lists of opaque/transparent renderables. + * @param[in] renderTask The current render-task. + * @param[in] inheritedDrawMode The draw mode of the parent + * @param[in] currentClippingId The current Clipping Id + * Note: ClippingId is passed by reference, so it is permanently modified when traversing back up the tree for uniqueness. + * @param[in] clippingDepth The current clipping depth */ bool AddRenderablesForTask( BufferIndex updateBufferIndex, Node& node, Layer& currentLayer, RenderTask& renderTask, - int inheritedDrawMode ) + int inheritedDrawMode, + uint32_t& currentClippingId, + uint32_t clippingDepth ) { bool resourcesFinished = true; // Short-circuit for invisible nodes - if ( !node.IsVisible( updateBufferIndex ) ) + if( !node.IsVisible( updateBufferIndex ) ) { return resourcesFinished; } // Check whether node is exclusive to a different render-task const RenderTask* exclusiveTo = node.GetExclusiveRenderTask(); - if ( exclusiveTo && - exclusiveTo != &renderTask ) + if( exclusiveTo && ( exclusiveTo != &renderTask ) ) { return resourcesFinished; } - Layer* layer = ¤tLayer; - Layer* nodeIsLayer( node.GetLayer() ); - if ( nodeIsLayer ) + // Assume all children go to this layer (if this node is a layer). + Layer* layer = node.GetLayer(); + if( layer ) { - // All children go to this layer - layer = nodeIsLayer; - // Layers do not inherit the DrawMode from their parents - inheritedDrawMode = DrawMode::NORMAL; + inheritedDrawMode = node.GetDrawMode(); } + else + { + // This node is not a layer. + layer = ¤tLayer; + inheritedDrawMode |= node.GetDrawMode(); + } + DALI_ASSERT_DEBUG( NULL != layer ); - inheritedDrawMode |= node.GetDrawMode(); + // Update the clipping Id and depth for this node (if clipping is enabled). + if( DALI_UNLIKELY( node.GetClippingMode() != ClippingMode::DISABLED ) ) + { + ++currentClippingId; // This modifies the reference passed in as well as the local value, causing the value to be global to the recursion. + ++clippingDepth; // This only modifies the local value (which is passed in when the method recurses). + } + // Set the information in the node. + node.SetClippingInformation( currentClippingId, clippingDepth ); const unsigned int count = node.GetRendererCount(); for( unsigned int i = 0; i < count; ++i ) @@ -142,53 +153,57 @@ bool AddRenderablesForTask( BufferIndex updateBufferIndex, bool complete = false; renderer->GetReadyAndComplete( ready, complete ); - DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Testing renderable:%p ready:%s complete:%s\n", renderer, ready?"T":"F", complete?"T":"F"); + DALI_LOG_INFO( gRenderTaskLogFilter, Debug::General, "Testing renderable:%p ready:%s complete:%s\n", renderer, ready ? "T" : "F", complete ? "T" : "F" ); resourcesFinished &= complete; - if( ready ) // i.e. should be rendered (all resources are available) + if( ready ) // IE. should be rendered (all resources are available) { - if( DrawMode::STENCIL == inheritedDrawMode ) + // Normal is the more-likely draw mode to occur. + if( DALI_LIKELY( inheritedDrawMode == DrawMode::NORMAL ) ) { - layer->stencilRenderables.PushBack( Renderable(&node, renderer ) ); - } - else if( DrawMode::OVERLAY_2D == inheritedDrawMode ) - { - layer->overlayRenderables.PushBack( Renderable(&node, renderer ) ); + layer->colorRenderables.PushBack( Renderable( &node, renderer ) ); } else { - layer->colorRenderables.PushBack( Renderable(&node, renderer ) ); + layer->overlayRenderables.PushBack( Renderable( &node, renderer ) ); } } } - - - // Recurse children + // Recurse children. NodeContainer& children = node.GetChildren(); const NodeIter endIter = children.End(); - for ( NodeIter iter = children.Begin(); iter != endIter; ++iter ) + for( NodeIter iter = children.Begin(); iter != endIter; ++iter ) { Node& child = **iter; - bool childResourcesComplete = AddRenderablesForTask( updateBufferIndex, child, *layer, renderTask, inheritedDrawMode ); + bool childResourcesComplete = AddRenderablesForTask( updateBufferIndex, child, *layer, renderTask, inheritedDrawMode, currentClippingId, clippingDepth ); resourcesFinished &= childResourcesComplete; } return resourcesFinished; } -} //Unnamed namespace - -void ProcessRenderTasks( BufferIndex updateBufferIndex, - RenderTaskList& renderTasks, - Layer& rootNode, - SortedLayerPointers& sortedLayers, - RendererSortingHelper& sortingHelper, - RenderInstructionContainer& instructions ) + +} // Anonymous namespace. + + +RenderTaskProcessor::RenderTaskProcessor() +{ +} + +RenderTaskProcessor::~RenderTaskProcessor() +{ +} + +void RenderTaskProcessor::Process( BufferIndex updateBufferIndex, + RenderTaskList& renderTasks, + Layer& rootNode, + SortedLayerPointers& sortedLayers, + RenderInstructionContainer& instructions ) { RenderTaskList::RenderTaskContainer& taskContainer = renderTasks.GetTasks(); - if ( taskContainer.IsEmpty() ) + if( taskContainer.IsEmpty() ) { // Early-exit if there are no tasks to process return; @@ -200,32 +215,30 @@ void ProcessRenderTasks( BufferIndex updateBufferIndex, // 3) Traverse the scene-graph, filling the lists for the current render-task // 4) Prepare render-instructions - DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "ProcessRenderTasks() Offscreens first\n"); + DALI_LOG_INFO( gRenderTaskLogFilter, Debug::General, "RenderTaskProcessor::Process() Offscreens first\n" ); // First process off screen render tasks - we may need the results of these for the on screen renders + uint32_t clippingId = 0u; + bool hasClippingNodes = false; + RenderTaskList::RenderTaskContainer::ConstIterator endIter = taskContainer.End(); - for ( RenderTaskList::RenderTaskContainer::Iterator iter = taskContainer.Begin(); endIter != iter; ++iter ) + for( RenderTaskList::RenderTaskContainer::Iterator iter = taskContainer.Begin(); endIter != iter; ++iter ) { RenderTask& renderTask = **iter; - // off screen only - if(0 == renderTask.GetFrameBufferId() && renderTask.GetFrameBuffer() == 0 ) - { - // Skip to next task - continue; - } - - if ( !renderTask.ReadyToRender( updateBufferIndex ) ) + // Off screen only. + if( ( ( 0 == renderTask.GetFrameBufferId() ) && ( renderTask.GetFrameBuffer() == 0 ) ) || + ( !renderTask.ReadyToRender( updateBufferIndex ) ) ) { - // Skip to next task + // Skip to next task. continue; } Node* sourceNode = renderTask.GetSourceNode(); - DALI_ASSERT_DEBUG( NULL != sourceNode ); // otherwise Prepare() should return false + DALI_ASSERT_DEBUG( NULL != sourceNode ); // Otherwise Prepare() should return false - // Check that the source node is not exclusive to another task - if ( ! CheckExclusivity( *sourceNode, renderTask ) ) + // Check that the source node is not exclusive to another task. + if( ! CheckExclusivity( *sourceNode, renderTask ) ) { continue; } @@ -233,7 +246,7 @@ void ProcessRenderTasks( BufferIndex updateBufferIndex, Layer* layer = FindLayer( *sourceNode ); if( !layer ) { - // Skip to next task as no layer + // Skip to next task as no layer. continue; } @@ -250,15 +263,21 @@ void ProcessRenderTasks( BufferIndex updateBufferIndex, *sourceNode, *layer, renderTask, - sourceNode->GetDrawMode() ); + sourceNode->GetDrawMode(), + clippingId, + 0u ); renderTask.SetResourcesFinished( resourcesFinished ); - PrepareRenderInstruction( updateBufferIndex, - sortedLayers, - renderTask, - sortingHelper, - renderTask.GetCullMode(), - instructions ); + + // If the clipping Id is still 0 after adding all Renderables, there is no clipping required for this RenderTaskList. + hasClippingNodes = clippingId != 0u; + + mRenderInstructionProcessor.Prepare( updateBufferIndex, + sortedLayers, + renderTask, + renderTask.GetCullMode(), + hasClippingNodes, + instructions ); } else { @@ -266,30 +285,29 @@ void ProcessRenderTasks( BufferIndex updateBufferIndex, } } - DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "ProcessRenderTasks() Onscreen\n"); + DALI_LOG_INFO( gRenderTaskLogFilter, Debug::General, "RenderTaskProcessor::Process() Onscreen\n" ); - // Now that the off screen renders are done we can process on screen render tasks + // Now that the off screen renders are done we can process on screen render tasks. + // Reset the clipping Id for the OnScreen render tasks. + clippingId = 0u; for ( RenderTaskList::RenderTaskContainer::Iterator iter = taskContainer.Begin(); endIter != iter; ++iter ) { RenderTask& renderTask = **iter; - // on screen only - if(0 != renderTask.GetFrameBufferId() || renderTask.GetFrameBuffer() != 0 ) + // On screen only. + if( ( 0 != renderTask.GetFrameBufferId() ) || + ( renderTask.GetFrameBuffer() != 0 ) || + ( !renderTask.ReadyToRender( updateBufferIndex ) ) ) { - // Skip to next task - continue; - } - if ( !renderTask.ReadyToRender( updateBufferIndex ) ) - { - // Skip to next task + // Skip to next task. continue; } Node* sourceNode = renderTask.GetSourceNode(); - DALI_ASSERT_DEBUG( NULL != sourceNode ); // otherwise Prepare() should return false + DALI_ASSERT_DEBUG( NULL != sourceNode ); // Otherwise Prepare() should return false. - // Check that the source node is not exclusive to another task - if ( ! CheckExclusivity( *sourceNode, renderTask ) ) + // Check that the source node is not exclusive to another task. + if( ! CheckExclusivity( *sourceNode, renderTask ) ) { continue; } @@ -297,7 +315,7 @@ void ProcessRenderTasks( BufferIndex updateBufferIndex, Layer* layer = FindLayer( *sourceNode ); if( !layer ) { - // Skip to next task as no layer + // Skip to next task as no layer. continue; } @@ -305,7 +323,7 @@ void ProcessRenderTasks( BufferIndex updateBufferIndex, if( renderTask.IsRenderRequired() ) { size_t layerCount( sortedLayers.size() ); - for( size_t i(0); iClearRenderables(); } @@ -314,14 +332,19 @@ void ProcessRenderTasks( BufferIndex updateBufferIndex, *sourceNode, *layer, renderTask, - sourceNode->GetDrawMode() ); - - PrepareRenderInstruction( updateBufferIndex, - sortedLayers, - renderTask, - sortingHelper, - renderTask.GetCullMode(), - instructions ); + sourceNode->GetDrawMode(), + clippingId, + 0u ); + + // If the clipping Id is still 0 after adding all Renderables, there is no clipping required for this RenderTaskList. + hasClippingNodes = clippingId != 0; + + mRenderInstructionProcessor.Prepare( updateBufferIndex, + sortedLayers, + renderTask, + renderTask.GetCullMode(), + hasClippingNodes, + instructions ); } renderTask.SetResourcesFinished( resourcesFinished ); diff --git a/dali/internal/update/manager/render-task-processor.h b/dali/internal/update/manager/render-task-processor.h new file mode 100644 index 0000000..2b69406 --- /dev/null +++ b/dali/internal/update/manager/render-task-processor.h @@ -0,0 +1,89 @@ +#ifndef DALI_INTERNAL_SCENE_GRAPH_RENDER_TASK_PROCESSOR_H +#define DALI_INTERNAL_SCENE_GRAPH_RENDER_TASK_PROCESSOR_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 +#include + +namespace Dali +{ + +namespace Internal +{ + +namespace SceneGraph +{ + +class RenderTaskList; + +/** + * @brief This class handles processing a given list of render tasks and generating render instructions from them. + */ +class RenderTaskProcessor +{ +public: + + /** + * @brief Constructor. + */ + RenderTaskProcessor(); + + /** + * @brief Destructor. + */ + ~RenderTaskProcessor(); + + /** + * Process the list of render-tasks; the output is a series of render instructions. + * @note When ProcessRenderTasks is called, the layers should already the transparent/opaque renderers which are ready to render. + * If there is only one default render-task, then no further processing is required. + * @param[in] updateBufferIndex The current update buffer index. + * @param[in] renderTasks The list of render-tasks. + * @param[in] rootNode The root node of the scene-graph. + * @param[in] sortedLayers The layers containing lists of opaque / transparent renderables. + * @param[out] instructions The instructions for rendering the next frame. + */ + void Process( BufferIndex updateBufferIndex, + RenderTaskList& renderTasks, + Layer& rootNode, + SortedLayerPointers& sortedLayers, + RenderInstructionContainer& instructions ); + +private: + + /** + * Undefine copy and assignment operators. + */ + RenderTaskProcessor( const RenderTaskProcessor& renderTaskProcessor ); ///< No definition + RenderTaskProcessor& operator=( const RenderTaskProcessor& renderTaskProcessor ); ///< No definition + +private: + + RenderInstructionProcessor mRenderInstructionProcessor; ///< An instance of the RenderInstructionProcessor used to sort and handle the renderers for each layer. +}; + + +} // namespace SceneGraph + +} // namespace Internal + +} // namespace Dali + +#endif // DALI_INTERNAL_SCENE_GRAPH_RENDER_TASK_PROCESSOR_H diff --git a/dali/internal/update/manager/update-algorithms.cpp b/dali/internal/update/manager/update-algorithms.cpp index 6f1fb4d..405d76a 100644 --- a/dali/internal/update/manager/update-algorithms.cpp +++ b/dali/internal/update/manager/update-algorithms.cpp @@ -150,7 +150,7 @@ inline int UpdateNodes( Node& node, UpdateNodeOpacity( node, nodeDirtyFlags, updateBufferIndex ); - // Setting STENCIL will override OVERLAY_2D, if that would otherwise have been inherited. + // Draw mode inheritance is treated as or-ing the modes together (as they are a bit-mask). inheritedDrawMode |= node.GetDrawMode(); node.PrepareRender( updateBufferIndex ); diff --git a/dali/internal/update/manager/update-manager-debug.cpp b/dali/internal/update/manager/update-manager-debug.cpp index c5f6159..093f779 100644 --- a/dali/internal/update/manager/update-manager-debug.cpp +++ b/dali/internal/update/manager/update-manager-debug.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * 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. @@ -30,6 +30,8 @@ #include #include +#ifdef DALI_PRINT_UPDATE_INFO + namespace Dali { @@ -48,7 +50,6 @@ static Debug::Filter* gNodeLogFilter = Debug::Filter::New(Debug::Verbose, false, */ void PrintNodes( const Node& node, BufferIndex updateBufferIndex, int level ) { -#if defined(DEBUG_ENABLED) const Vector3& position = node.GetPosition(updateBufferIndex); const Vector3& scale = node.GetScale(updateBufferIndex); const Vector3& fullPos = node.GetWorldPosition(updateBufferIndex); @@ -94,13 +95,10 @@ void PrintNodes( const Node& node, BufferIndex updateBufferIndex, int level ) { PrintNodes(**iter, updateBufferIndex, level); } -#endif // DEBUG_ENABLED } void PrintNodeTree( const Node& node, BufferIndex bufferIndex, std::string indentation ) { -#if defined(DEBUG_ENABLED) - std::cout << "Node " << &node << " \"" << node.mDebugString << "\"" << " Origin: " << node.GetParentOrigin() @@ -135,8 +133,6 @@ void PrintNodeTree( const Node& node, BufferIndex bufferIndex, std::string inden PrintNodeTree(**iter, bufferIndex, nextIndent); } - -#endif // DEBUG_ENABLED } } // SceneGraph @@ -144,3 +140,5 @@ void PrintNodeTree( const Node& node, BufferIndex bufferIndex, std::string inden } // Internal } // Dali + +#endif diff --git a/dali/internal/update/manager/update-manager-debug.h b/dali/internal/update/manager/update-manager-debug.h index a5f98f4..122abc1 100644 --- a/dali/internal/update/manager/update-manager-debug.h +++ b/dali/internal/update/manager/update-manager-debug.h @@ -1,8 +1,8 @@ -#ifndef __DALI_INTERNAL_SCENE_GRAPH_UPDATE_MANAGER_DEBUG_H__ -#define __DALI_INTERNAL_SCENE_GRAPH_UPDATE_MANAGER_DEBUG_H__ +#ifndef DALI_INTERNAL_SCENE_GRAPH_UPDATE_MANAGER_DEBUG_H +#define DALI_INTERNAL_SCENE_GRAPH_UPDATE_MANAGER_DEBUG_H /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * 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. @@ -25,6 +25,11 @@ #include #include +// Define this to access debug functions for the update manager. +#undef DALI_PRINT_UPDATE_INFO + +#ifdef DALI_PRINT_UPDATE_INFO + namespace Dali { @@ -44,4 +49,6 @@ void PrintNodeTree( const Node& node, BufferIndex bufferIndex, std::string inden } // Dali -#endif // __DALI_INTERNAL_SCENE_GRAPH_UPDATE_MANAGER_DEBUG_H__ +#endif + +#endif // DALI_INTERNAL_SCENE_GRAPH_UPDATE_MANAGER_DEBUG_H diff --git a/dali/internal/update/manager/update-manager.cpp b/dali/internal/update/manager/update-manager.cpp index b2a52d9..951c4c5 100644 --- a/dali/internal/update/manager/update-manager.cpp +++ b/dali/internal/update/manager/update-manager.cpp @@ -46,7 +46,7 @@ #include #include #include -#include +#include #include #include #include @@ -131,7 +131,8 @@ struct UpdateManager::Impl RenderController& renderController, RenderManager& renderManager, RenderQueue& renderQueue, - SceneGraphBuffers& sceneGraphBuffers ) + SceneGraphBuffers& sceneGraphBuffers, + RenderTaskProcessor& renderTaskProcessor ) : renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ), notificationManager( notificationManager ), transformManager(), @@ -145,6 +146,7 @@ struct UpdateManager::Impl renderManager( renderManager ), renderQueue( renderQueue ), renderInstructions( renderManager.GetRenderInstructionContainer() ), + renderTaskProcessor( renderTaskProcessor ), backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ), taskList( renderMessageDispatcher, resourceManager ), systemLevelTaskList( renderMessageDispatcher, resourceManager ), @@ -158,7 +160,6 @@ struct UpdateManager::Impl nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update() previousUpdateScene( false ), frameCounter( 0 ), - renderSortingHelper(), renderTaskWaiting( false ) { sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue ); @@ -227,6 +228,7 @@ struct UpdateManager::Impl RenderManager& renderManager; ///< This is responsible for rendering the results of each "update" RenderQueue& renderQueue; ///< Used to queue messages for the next render RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions + RenderTaskProcessor& renderTaskProcessor; ///< Handles RenderTasks and RenderInstrucitons Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame. @@ -248,7 +250,7 @@ struct UpdateManager::Impl PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications. ObjectOwnerContainer renderers; - TextureSetContainer textureSets; ///< A container of texture sets + TextureSetContainer textureSets; ///< A container of texture sets ShaderContainer shaders; ///< A container of owned shaders @@ -264,7 +266,6 @@ struct UpdateManager::Impl bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out) int frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore. - RendererSortingHelper renderSortingHelper; ///< helper used to sort transparent renderers GestureContainer gestures; ///< A container of owned gesture detectors bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered @@ -278,7 +279,8 @@ UpdateManager::UpdateManager( NotificationManager& notificationManager, RenderController& controller, RenderManager& renderManager, RenderQueue& renderQueue, - TextureCacheDispatcher& textureCacheDispatcher ) + TextureCacheDispatcher& textureCacheDispatcher, + RenderTaskProcessor& renderTaskProcessor ) : mImpl(NULL) { mImpl = new Impl( notificationManager, @@ -289,7 +291,8 @@ UpdateManager::UpdateManager( NotificationManager& notificationManager, controller, renderManager, renderQueue, - mSceneGraphBuffers ); + mSceneGraphBuffers, + renderTaskProcessor ); textureCacheDispatcher.SetBufferIndices( &mSceneGraphBuffers ); } @@ -986,22 +989,20 @@ unsigned int UpdateManager::Update( float elapsedSeconds, if ( NULL != mImpl->root ) { - ProcessRenderTasks( bufferIndex, - mImpl->taskList, - *mImpl->root, - mImpl->sortedLayers, - mImpl->renderSortingHelper, - mImpl->renderInstructions ); + mImpl->renderTaskProcessor.Process( bufferIndex, + mImpl->taskList, + *mImpl->root, + mImpl->sortedLayers, + mImpl->renderInstructions ); // Process the system-level RenderTasks last if ( NULL != mImpl->systemLevelRoot ) { - ProcessRenderTasks( bufferIndex, - mImpl->systemLevelTaskList, - *mImpl->systemLevelRoot, - mImpl->systemLevelSortedLayers, - mImpl->renderSortingHelper, - mImpl->renderInstructions ); + mImpl->renderTaskProcessor.Process( bufferIndex, + mImpl->systemLevelTaskList, + *mImpl->systemLevelRoot, + mImpl->systemLevelSortedLayers, + mImpl->renderInstructions ); } } } diff --git a/dali/internal/update/manager/update-manager.h b/dali/internal/update/manager/update-manager.h index e90ab9d..9a285d3 100644 --- a/dali/internal/update/manager/update-manager.h +++ b/dali/internal/update/manager/update-manager.h @@ -1,5 +1,5 @@ -#ifndef __DALI_INTERNAL_SCENE_GRAPH_UPDATE_MANAGER_H__ -#define __DALI_INTERNAL_SCENE_GRAPH_UPDATE_MANAGER_H__ +#ifndef DALI_INTERNAL_SCENE_GRAPH_UPDATE_MANAGER_H +#define DALI_INTERNAL_SCENE_GRAPH_UPDATE_MANAGER_H /* * Copyright (c) 2016 Samsung Electronics Co., Ltd. @@ -75,6 +75,7 @@ class DiscardQueue; class PanGesture; class RenderManager; class RenderTaskList; +class RenderTaskProcessor; class RenderQueue; class TextureCacheDispatcher; class PropertyBuffer; @@ -104,6 +105,7 @@ public: * @param[in] renderManager This is responsible for rendering the results of each "update". * @param[in] renderQueue Used to queue messages for the next render. * @param[in] textureCacheDispatcher Used for sending messages to texture cache. + * @param[in] renderTaskProcessor Handles RenderTasks and RenderInstrucitons. */ UpdateManager( NotificationManager& notificationManager, CompleteNotificationInterface& animationFinishedNotifier, @@ -113,7 +115,8 @@ public: Integration::RenderController& controller, RenderManager& renderManager, RenderQueue& renderQueue, - TextureCacheDispatcher& textureCacheDispatcher ); + TextureCacheDispatcher& textureCacheDispatcher, + RenderTaskProcessor& renderTaskProcessor ); /** * Destructor. @@ -1278,10 +1281,11 @@ inline void AttachColorTextureToFrameBuffer( UpdateManager& manager, Render::Fra new (slot) LocalType( &manager, &UpdateManager::AttachColorTextureToFrameBuffer, &frameBuffer, texture, mipmapLevel, layer ); } + } // namespace SceneGraph } // namespace Internal } // namespace Dali -#endif // __DALI_INTERNAL_SCENE_GRAPH_UPDATE_MANAGER_H__ +#endif // DALI_INTERNAL_SCENE_GRAPH_UPDATE_MANAGER_H diff --git a/dali/internal/update/nodes/node.cpp b/dali/internal/update/nodes/node.cpp index b3a9767..e873a6f 100644 --- a/dali/internal/update/nodes/node.cpp +++ b/dali/internal/update/nodes/node.cpp @@ -53,26 +53,29 @@ Node::Node() mTransformId( INVALID_TRANSFORM_ID ), mParentOrigin( TRANSFORM_PROPERTY_PARENT_ORIGIN ), mAnchorPoint( TRANSFORM_PROPERTY_ANCHOR_POINT ), - mSize(TRANSFORM_PROPERTY_SIZE), // zero initialized by default - mPosition(TRANSFORM_PROPERTY_POSITION), // zero initialized by default - mOrientation(), // initialized to identity by default + mSize( TRANSFORM_PROPERTY_SIZE ), // Zero initialized by default + mPosition( TRANSFORM_PROPERTY_POSITION ), // Zero initialized by default + mOrientation(), // Initialized to identity by default mScale( TRANSFORM_PROPERTY_SCALE ), mVisible( true ), mColor( Color::WHITE ), - mWorldPosition(TRANSFORM_PROPERTY_WORLD_POSITION, Vector3(0.0f,0.0f,0.0f)), // zero initialized by default - mWorldScale( TRANSFORM_PROPERTY_WORLD_SCALE, Vector3(1.0f,1.0f,1.0f) ), - mWorldOrientation(), // initialized to identity by default + mWorldPosition( TRANSFORM_PROPERTY_WORLD_POSITION, Vector3( 0.0f,0.0f,0.0f ) ), // Zero initialized by default + mWorldScale( TRANSFORM_PROPERTY_WORLD_SCALE, Vector3( 1.0f,1.0f,1.0f ) ), + mWorldOrientation(), // Initialized to identity by default mWorldMatrix(), mWorldColor( Color::WHITE ), + mClippingSortModifier( 0u ), mParent( NULL ), mExclusiveRenderTask( NULL ), mChildren(), + mClippingDepth( 0u ), mRegenerateUniformMap( 0 ), - mDepth(0u), - mDirtyFlags(AllFlags), - mIsRoot( false ), + mDepth( 0u ), + mDirtyFlags( AllFlags ), mDrawMode( DrawMode::NORMAL ), - mColorMode( DEFAULT_COLOR_MODE ) + mColorMode( DEFAULT_COLOR_MODE ), + mClippingMode( ClippingMode::DISABLED ), + mIsRoot( false ) { mUniformMapChanged[0] = 0u; mUniformMapChanged[1] = 0u; diff --git a/dali/internal/update/nodes/node.h b/dali/internal/update/nodes/node.h index 4846122..0712b53 100644 --- a/dali/internal/update/nodes/node.h +++ b/dali/internal/update/nodes/node.h @@ -1,5 +1,5 @@ -#ifndef __DALI_INTERNAL_SCENE_GRAPH_NODE_H__ -#define __DALI_INTERNAL_SCENE_GRAPH_NODE_H__ +#ifndef DALI_INTERNAL_SCENE_GRAPH_NODE_H +#define DALI_INTERNAL_SCENE_GRAPH_NODE_H /* * Copyright (c) 2016 Samsung Electronics Co., Ltd. @@ -45,9 +45,10 @@ namespace Dali namespace Internal { -// value types used by messages +// Value types used by messages. template <> struct ParameterType< ColorMode > : public BasicType< ColorMode > {}; template <> struct ParameterType< PositionInheritanceMode > : public BasicType< PositionInheritanceMode > {}; +template <> struct ParameterType< ClippingMode::Type > : public BasicType< ClippingMode::Type > {}; namespace SceneGraph { @@ -69,7 +70,7 @@ enum NodePropertyFlags SizeFlag = 0x008, OverlayFlag = 0x010, SortModifierFlag = 0x020, - ChildDeletedFlag = 0x040 + ChildDeletedFlag = 0x040, }; static const int AllFlags = ( ChildDeletedFlag << 1 ) - 1; // all the flags @@ -142,6 +143,65 @@ public: } /** + * This method sets clipping information on the node based on its hierarchy in the scene-graph. + * A value is calculated that can be used during sorting to increase sort speed. + * @param[in] clippingId The Clipping ID of the node to set + * @param[in] clippingDepth The Clipping Depth of the node to set + */ + void SetClippingInformation( const uint32_t clippingId, const uint32_t clippingDepth ) + { + // We only set up the sort value if we have a clipping depth, IE. At least 1 clipping node has been hit. + // If not, if we traverse down a clipping tree and back up, and there is another + // node on the parent, this will have a non-zero clipping ID that must be ignored + if( DALI_LIKELY( clippingDepth > 0u ) ) + { + mClippingDepth = clippingDepth; + + // Calculate the sort value here on write, as when read (during sort) it may be accessed several times. + // The items must be sorted by Clipping ID first (so the ID is kept in the most-significant bits). + // For the same ID, the clipping nodes must be first, so we negate the + // clipping enabled flag and set it as the least significant bit. + mClippingSortModifier = ( clippingId << 1u ) | ( mClippingMode == ClippingMode::DISABLED ? 1u : 0u ); + } + } + + /** + * Gets the Clipping ID for this node. + * @return The Clipping ID for this node. + */ + uint32_t GetClippingId() const + { + return mClippingSortModifier >> 1u; + } + + /** + * Gets the Clipping Depth for this node. + * @return The Clipping Depth for this node. + */ + uint32_t GetClippingDepth() const + { + return mClippingDepth; + } + + /** + * Sets the clipping mode for this node. + * @param[in] clippingMode The ClippingMode to set + */ + void SetClippingMode( const ClippingMode::Type clippingMode ) + { + mClippingMode = clippingMode; + } + + /** + * Gets the Clipping Mode for this node. + * @return The ClippingMode of this node + */ + ClippingMode::Type GetClippingMode() const + { + return mClippingMode; + } + + /** * Add a renderer to the node * @param[in] renderer The renderer added to the node */ @@ -669,15 +729,11 @@ public: /** * Equality operator, checks for identity, not values. - * + * @param[in] */ bool operator==( const Node* rhs ) const { - if ( this == rhs ) - { - return true; - } - return false; + return ( this == rhs ); } unsigned short GetDepth() const @@ -781,47 +837,49 @@ private: public: // Default properties - TransformManager* mTransformManager; - TransformId mTransformId; - TransformManagerPropertyVector3 mParentOrigin; ///< Local transform; the position is relative to this. Sets the TransformFlag dirty when changed - TransformManagerPropertyVector3 mAnchorPoint; ///< Local transform; local center of rotation. Sets the TransformFlag dirty when changed - TransformManagerPropertyVector3 mSize; ///< Size is provided for layouting - TransformManagerPropertyVector3 mPosition; ///< Local transform; distance between parent-origin & anchor-point - TransformManagerPropertyQuaternion mOrientation; ///< Local transform; rotation relative to parent node - TransformManagerPropertyVector3 mScale; ///< Local transform; scale relative to parent node + TransformManager* mTransformManager; + TransformId mTransformId; + TransformManagerPropertyVector3 mParentOrigin; ///< Local transform; the position is relative to this. Sets the TransformFlag dirty when changed + TransformManagerPropertyVector3 mAnchorPoint; ///< Local transform; local center of rotation. Sets the TransformFlag dirty when changed + TransformManagerPropertyVector3 mSize; ///< Size is provided for layouting + TransformManagerPropertyVector3 mPosition; ///< Local transform; distance between parent-origin & anchor-point + TransformManagerPropertyQuaternion mOrientation; ///< Local transform; rotation relative to parent node + TransformManagerPropertyVector3 mScale; ///< Local transform; scale relative to parent node - AnimatableProperty mVisible; ///< Visibility can be inherited from the Node hierachy - AnimatableProperty mColor; ///< Color can be inherited from the Node hierarchy + AnimatableProperty mVisible; ///< Visibility can be inherited from the Node hierachy + AnimatableProperty mColor; ///< Color can be inherited from the Node hierarchy // Inherited properties; read-only from public API - TransformManagerVector3Input mWorldPosition; ///< Full inherited position - TransformManagerVector3Input mWorldScale; - TransformManagerQuaternionInput mWorldOrientation; ///< Full inherited orientation - TransformManagerMatrixInput mWorldMatrix; ///< Full inherited world matrix - InheritedColor mWorldColor; ///< Full inherited color + TransformManagerVector3Input mWorldPosition; ///< Full inherited position + TransformManagerVector3Input mWorldScale; + TransformManagerQuaternionInput mWorldOrientation; ///< Full inherited orientation + TransformManagerMatrixInput mWorldMatrix; ///< Full inherited world matrix + InheritedColor mWorldColor; ///< Full inherited color + + uint32_t mClippingSortModifier; ///< Contains bit-packed clipping information for quick access when sorting protected: - Node* mParent; ///< Pointer to parent node (a child is owned by its parent) - RenderTask* mExclusiveRenderTask; ///< Nodes can be marked as exclusive to a single RenderTask + Node* mParent; ///< Pointer to parent node (a child is owned by its parent) + RenderTask* mExclusiveRenderTask; ///< Nodes can be marked as exclusive to a single RenderTask - RendererContainer mRenderer; ///< Container of renderers; not owned + RendererContainer mRenderer; ///< Container of renderers; not owned - NodeContainer mChildren; ///< Container of children; not owned + NodeContainer mChildren; ///< Container of children; not owned - CollectedUniformMap mCollectedUniformMap[2]; ///< Uniform maps of the node - unsigned int mUniformMapChanged[2]; ///< Records if the uniform map has been altered this frame - unsigned int mRegenerateUniformMap : 2; ///< Indicate if the uniform map has to be regenerated this frame + 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 // flags, compressed to bitfield - unsigned short mDepth: 12; ///< Depth in the hierarchy - int mDirtyFlags:8; ///< A composite set of flags for each of the Node properties - - bool mIsRoot:1; ///< True if the node cannot have a parent - - 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 + unsigned short mDepth:12; ///< Depth in the hierarchy + 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 + ClippingMode::Type mClippingMode:2; ///< The clipping mode of this node + bool mIsRoot:1; ///< True if the node cannot have a parent // Changes scope, should be at end of class DALI_LOG_OBJECT_STRING_DECLARATION; @@ -927,10 +985,23 @@ inline void RemoveRendererMessage( EventThreadServices& eventThreadServices, con // Construct message in the message queue memory; note that delete should not be called on the return value new (slot) LocalType( &node, &Node::RemoveRenderer, renderer ); } + +inline void SetClippingModeMessage( EventThreadServices& eventThreadServices, const Node& node, ClippingMode::Type clippingMode ) +{ + typedef MessageValue1< Node, ClippingMode::Type > 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::SetClippingMode, clippingMode ); +} + + } // namespace SceneGraph } // namespace Internal } // namespace Dali -#endif // __DALI_INTERNAL_SCENE_GRAPH_NODE_H_ +#endif // DALI_INTERNAL_SCENE_GRAPH_NODE_H diff --git a/dali/internal/update/nodes/scene-graph-layer.cpp b/dali/internal/update/nodes/scene-graph-layer.cpp index 1d920be..573ccee 100644 --- a/dali/internal/update/nodes/scene-graph-layer.cpp +++ b/dali/internal/update/nodes/scene-graph-layer.cpp @@ -102,7 +102,6 @@ bool Layer::IsDepthTestDisabled() const void Layer::ClearRenderables() { - stencilRenderables.Clear(); colorRenderables.Clear(); overlayRenderables.Clear(); } diff --git a/dali/internal/update/nodes/scene-graph-layer.h b/dali/internal/update/nodes/scene-graph-layer.h index 89823a8..e036df1 100644 --- a/dali/internal/update/nodes/scene-graph-layer.h +++ b/dali/internal/update/nodes/scene-graph-layer.h @@ -1,5 +1,5 @@ -#ifndef __DALI_INTERNAL_SCENE_GRAPH_LAYER_H__ -#define __DALI_INTERNAL_SCENE_GRAPH_LAYER_H__ +#ifndef DALI_INTERNAL_SCENE_GRAPH_LAYER_H +#define DALI_INTERNAL_SCENE_GRAPH_LAYER_H /* * Copyright (c) 2016 Samsung Electronics Co., Ltd. @@ -45,13 +45,13 @@ class Camera; struct Renderable { Renderable() - :mNode(0), - mRenderer(0) + : mNode( 0 ), + mRenderer( 0 ) {} Renderable( Node* node, Renderer* renderer ) - :mNode(node), - mRenderer(renderer) + : mNode( node ), + mRenderer( renderer ) {} Node* mNode; @@ -222,13 +222,12 @@ private: public: // For update-algorithms - RenderableContainer stencilRenderables; RenderableContainer colorRenderables; RenderableContainer overlayRenderables; private: - SortFunctionType mSortFunction; ///< Used to sort semi-transparent geometry + SortFunctionType mSortFunction; ///< Used to sort semi-transparent geometry ClippingBox mClippingBox; ///< The clipping box, in window coordinates Camera* mLastCamera; ///< Pointer to the last camera that has rendered the layer @@ -236,8 +235,8 @@ private: Dali::Layer::Behavior mBehavior; ///< The behavior of the layer bool mAllChildTransformsClean[ 2 ]; ///< True if all child nodes transforms are clean, - /// double buffered as we need two clean frames before we can reuse N-1 for N+1 - /// this allows us to cache render items when layer is "static" + /// double buffered as we need two clean frames before we can reuse N-1 for N+1 + /// this allows us to cache render items when layer is "static" bool mIsClipping:1; ///< True when clipping is enabled bool mDepthTestDisabled:1; ///< Whether depth test is disabled. bool mIsDefaultSortFunction:1; ///< whether the default depth sort function is used @@ -337,4 +336,4 @@ inline void SetDepthTestDisabledMessage( EventThreadServices& eventThreadService } // namespace Dali -#endif // __DALI_INTERNAL_SCENE_GRAPH_LAYER_H__ +#endif // DALI_INTERNAL_SCENE_GRAPH_LAYER_H diff --git a/dali/internal/update/rendering/scene-graph-renderer.cpp b/dali/internal/update/rendering/scene-graph-renderer.cpp index b1926ba..75df93d 100644 --- a/dali/internal/update/rendering/scene-graph-renderer.cpp +++ b/dali/internal/update/rendering/scene-graph-renderer.cpp @@ -155,15 +155,15 @@ Renderer::Renderer() Renderer::~Renderer() { - if (mTextureSet) + if( mTextureSet ) { - mTextureSet->RemoveObserver(this); - mTextureSet=NULL; + mTextureSet->RemoveObserver( this ); + mTextureSet = NULL; } if( mShader ) { - mShader->RemoveConnectionObserver(*this); - mShader=NULL; + mShader->RemoveConnectionObserver( *this ); + mShader = NULL; } } @@ -647,7 +647,6 @@ Renderer::Opacity Renderer::GetOpacity( BufferIndex updateBufferIndex, const Nod } } - return opacity; } diff --git a/dali/internal/update/rendering/scene-graph-renderer.h b/dali/internal/update/rendering/scene-graph-renderer.h index 61605b6..a68db0f 100644 --- a/dali/internal/update/rendering/scene-graph-renderer.h +++ b/dali/internal/update/rendering/scene-graph-renderer.h @@ -30,6 +30,7 @@ namespace Dali { + namespace Internal { @@ -362,7 +363,7 @@ private: Shader* mShader; ///< The shader this renderer uses. (Not owned) Vector4* mBlendColor; ///< The blend color for blending operation - Render::Renderer::StencilParameters mStencilParameters; ///< Struct containing all stencil related options + Dali::Internal::Render::Renderer::StencilParameters mStencilParameters; ///< Struct containing all stencil related options size_t mIndexedDrawFirstElement; ///< first element index to be drawn using indexed draw size_t mIndexedDrawElementsCount; ///< number of elements to be drawn using indexed draw diff --git a/dali/public-api/actors/actor-enumerations.h b/dali/public-api/actors/actor-enumerations.h index bed10d2..78b861d 100644 --- a/dali/public-api/actors/actor-enumerations.h +++ b/dali/public-api/actors/actor-enumerations.h @@ -1,8 +1,8 @@ -#ifndef __DALI_ACTOR_ENUMERATIONS_H__ -#define __DALI_ACTOR_ENUMERATIONS_H__ +#ifndef DALI_ACTOR_ENUMERATIONS_H +#define DALI_ACTOR_ENUMERATIONS_H /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * 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. @@ -59,18 +59,18 @@ enum PositionInheritanceMode */ namespace Dimension { -enum Type -{ - WIDTH = 0x1, ///< Width dimension @SINCE_1_0.0 - HEIGHT = 0x2, ///< Height dimension @SINCE_1_0.0 + enum Type + { + WIDTH = 0x1, ///< Width dimension @SINCE_1_0.0 + HEIGHT = 0x2, ///< Height dimension @SINCE_1_0.0 - ALL_DIMENSIONS = 0x3 ///< Mask to cover all flags @SINCE_1_0.0 -}; + ALL_DIMENSIONS = 0x3 ///< Mask to cover all flags @SINCE_1_0.0 + }; -enum Meta -{ - DIMENSION_COUNT = 2 ///< Number of dimensions - update this if adding new dimension @SINCE_1_0.0 -}; + enum Meta + { + DIMENSION_COUNT = 2 ///< Number of dimensions - update this if adding new dimension @SINCE_1_0.0 + }; } /** @@ -79,18 +79,18 @@ enum Meta */ namespace ResizePolicy { -enum Type -{ - FIXED, ///< Size is fixed as set by SetSize @SINCE_1_0.0 - USE_NATURAL_SIZE, ///< Size is to use the actor's natural size @SINCE_1_0.0 @see Actor::GetNaturalSize() - FILL_TO_PARENT, ///< Size is to fill up to the actor's parent's bounds. Aspect ratio is not maintained. @SINCE_1_0.0 - SIZE_RELATIVE_TO_PARENT, ///< The actors size will be ( ParentSize * SizeRelativeToParentFactor ). @SINCE_1_0.0 - SIZE_FIXED_OFFSET_FROM_PARENT, ///< The actors size will be ( ParentSize + SizeRelativeToParentFactor ). @SINCE_1_0.0 - FIT_TO_CHILDREN, ///< Size will adjust to wrap around all children @SINCE_1_0.0 - DIMENSION_DEPENDENCY, ///< One dimension is dependent on the other @SINCE_1_0.0 - USE_ASSIGNED_SIZE ///< The size will be assigned to the actor @SINCE_1_0.0 -}; -const Type DEFAULT = USE_NATURAL_SIZE; ///< Default resize policy + enum Type + { + FIXED, ///< Size is fixed as set by SetSize @SINCE_1_0.0 + USE_NATURAL_SIZE, ///< Size is to use the actor's natural size @SINCE_1_0.0 @see Actor::GetNaturalSize() + FILL_TO_PARENT, ///< Size is to fill up to the actor's parent's bounds. Aspect ratio is not maintained. @SINCE_1_0.0 + SIZE_RELATIVE_TO_PARENT, ///< The actors size will be ( ParentSize * SizeRelativeToParentFactor ). @SINCE_1_0.0 + SIZE_FIXED_OFFSET_FROM_PARENT, ///< The actors size will be ( ParentSize + SizeRelativeToParentFactor ). @SINCE_1_0.0 + FIT_TO_CHILDREN, ///< Size will adjust to wrap around all children @SINCE_1_0.0 + DIMENSION_DEPENDENCY, ///< One dimension is dependent on the other @SINCE_1_0.0 + USE_ASSIGNED_SIZE ///< The size will be assigned to the actor @SINCE_1_0.0 + }; + const Type DEFAULT = USE_NATURAL_SIZE; ///< Default resize policy } /** @@ -99,12 +99,12 @@ const Type DEFAULT = USE_NATURAL_SIZE; ///< Default resize policy */ namespace SizeScalePolicy { -enum Type -{ - USE_SIZE_SET, ///< Use the size that was set @SINCE_1_0.0 - FIT_WITH_ASPECT_RATIO, ///< Fit within the size set maintaining natural size aspect ratio @SINCE_1_0.0 - FILL_WITH_ASPECT_RATIO ///< Fill up the size set maintaining natural size aspect ratio. May exceed size bounds in one dimension. @SINCE_1_0.0 -}; + enum Type + { + USE_SIZE_SET, ///< Use the size that was set @SINCE_1_0.0 + FIT_WITH_ASPECT_RATIO, ///< Fit within the size set maintaining natural size aspect ratio @SINCE_1_0.0 + FILL_WITH_ASPECT_RATIO ///< Fill up the size set maintaining natural size aspect ratio. May exceed size bounds in one dimension. @SINCE_1_0.0 + }; } /** @@ -113,12 +113,12 @@ enum Type */ namespace HorizontalAlignment { -enum Type -{ - LEFT, ///< Align horizontally left @SINCE_1_0.0 - CENTER, ///< Align horizontally center @SINCE_1_0.0 - RIGHT ///< Align horiztonally right @SINCE_1_0.0 -}; + enum Type + { + LEFT, ///< Align horizontally left @SINCE_1_0.0 + CENTER, ///< Align horizontally center @SINCE_1_0.0 + RIGHT ///< Align horizontally right @SINCE_1_0.0 + }; } /** @@ -127,17 +127,31 @@ enum Type */ namespace VerticalAlignment { -enum Type + enum Type + { + TOP, ///< Align vertically top @SINCE_1_0.0 + CENTER, ///< Align vertically center @SINCE_1_0.0 + BOTTOM ///< Align vertically bottom @SINCE_1_0.0 + }; +} + +/** + * @brief The ClippingMode describes how this Actors children will be clipped against it. + * @SINCE_1_2.5 + */ +namespace ClippingMode { - TOP, ///< Align vertically top @SINCE_1_0.0 - CENTER, ///< Align vertically center @SINCE_1_0.0 - BOTTOM ///< Align vertically bottom @SINCE_1_0.0 -}; + enum Type + { + DISABLED, ///< This Actor will not clip its children. @SINCE_1_2.5 + CLIP_CHILDREN, ///< This Actor will clip all children to within its boundaries (the actor will also be visible itself). @SINCE_1_2.5 + }; } + /** * @} */ } // namespace Dali -#endif // __DALI_ACTOR_ENUMERATIONS_H__ +#endif // DALI_ACTOR_ENUMERATIONS_H diff --git a/dali/public-api/actors/actor.h b/dali/public-api/actors/actor.h index 1040218..4e9731b 100644 --- a/dali/public-api/actors/actor.h +++ b/dali/public-api/actors/actor.h @@ -1,8 +1,8 @@ -#ifndef __DALI_ACTOR_H__ -#define __DALI_ACTOR_H__ +#ifndef DALI_ACTOR_H +#define DALI_ACTOR_H /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * 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. @@ -28,6 +28,7 @@ #include #include #include + namespace Dali { /** @@ -249,59 +250,60 @@ public: { enum { - PARENT_ORIGIN = DEFAULT_ACTOR_PROPERTY_START_INDEX, ///< name "parentOrigin", type Vector3 (constraint-input) @SINCE_1_0.0 - PARENT_ORIGIN_X, ///< name "parentOriginX", type float (constraint-input) @SINCE_1_0.0 - PARENT_ORIGIN_Y, ///< name "parentOriginY", type float (constraint-input) @SINCE_1_0.0 - PARENT_ORIGIN_Z, ///< name "parentOriginZ", type float (constraint-input) @SINCE_1_0.0 - ANCHOR_POINT, ///< name "anchorPoint", type Vector3 (constraint-input) @SINCE_1_0.0 - ANCHOR_POINT_X, ///< name "anchorPointX", type float (constraint-input) @SINCE_1_0.0 - ANCHOR_POINT_Y, ///< name "anchorPointY", type float (constraint-input) @SINCE_1_0.0 - ANCHOR_POINT_Z, ///< name "anchorPointZ", type float (constraint-input) @SINCE_1_0.0 - SIZE, ///< name "size", type Vector3 (animatable / constraint-input) @SINCE_1_0.0 - SIZE_WIDTH, ///< name "sizeWidth", type float (animatable / constraint-input) @SINCE_1_0.0 - SIZE_HEIGHT, ///< name "sizeHeight", type float (animatable / constraint-input) @SINCE_1_0.0 - SIZE_DEPTH, ///< name "sizeDepth", type float (animatable / constraint-input) @SINCE_1_0.0 - POSITION, ///< name "position", type Vector3 (animatable / constraint-input) @SINCE_1_0.0 - POSITION_X, ///< name "positionX", type float (animatable / constraint-input) @SINCE_1_0.0 - POSITION_Y, ///< name "positionY", type float (animatable / constraint-input) @SINCE_1_0.0 - POSITION_Z, ///< name "positionZ", type float (animatable / constraint-input) @SINCE_1_0.0 - WORLD_POSITION, ///< name "worldPosition", type Vector3 (read-only / constraint-input) @SINCE_1_0.0 - WORLD_POSITION_X, ///< name "worldPositionX", type float (read-only / constraint-input) @SINCE_1_0.0 - WORLD_POSITION_Y, ///< name "worldPositionY", type float (read-only / constraint-input) @SINCE_1_0.0 - WORLD_POSITION_Z, ///< name "worldPositionZ", type float (read-only / constraint-input) @SINCE_1_0.0 - ORIENTATION, ///< name "orientation", type Quaternion (animatable / constraint-input) @SINCE_1_0.0 - WORLD_ORIENTATION, ///< name "worldOrientation", type Quaternion (read-only / constraint-input) @SINCE_1_0.0 - SCALE, ///< name "scale", type Vector3 (animatable / constraint-input) @SINCE_1_0.0 - SCALE_X, ///< name "scaleX", type float (animatable / constraint-input) @SINCE_1_0.0 - SCALE_Y, ///< name "scaleY", type float (animatable / constraint-input) @SINCE_1_0.0 - SCALE_Z, ///< name "scaleZ", type float (animatable / constraint-input) @SINCE_1_0.0 - WORLD_SCALE, ///< name "worldScale", type Vector3 (read-only / constraint-input) @SINCE_1_0.0 - VISIBLE, ///< name "visible", type bool (animatable / constraint-input) @SINCE_1_0.0 - COLOR, ///< name "color", type Vector4 (animatable / constraint-input) @SINCE_1_0.0 - COLOR_RED, ///< name "colorRed", type float (animatable / constraint-input) @SINCE_1_0.0 - COLOR_GREEN, ///< name "colorGreen", type float (animatable / constraint-input) @SINCE_1_0.0 - COLOR_BLUE, ///< name "colorBlue", type float (animatable / constraint-input) @SINCE_1_0.0 - COLOR_ALPHA, ///< name "colorAlpha", type float (animatable / constraint-input) @SINCE_1_0.0 - WORLD_COLOR, ///< name "worldColor", type Vector4 (read-only / constraint-input) @SINCE_1_0.0 - WORLD_MATRIX, ///< name "worldMatrix", type Matrix (read-only / constraint-input) @SINCE_1_0.0 + PARENT_ORIGIN = DEFAULT_ACTOR_PROPERTY_START_INDEX, ///< name "parentOrigin", type Vector3 (constraint-input) @SINCE_1_0.0 + PARENT_ORIGIN_X, ///< name "parentOriginX", type float (constraint-input) @SINCE_1_0.0 + PARENT_ORIGIN_Y, ///< name "parentOriginY", type float (constraint-input) @SINCE_1_0.0 + PARENT_ORIGIN_Z, ///< name "parentOriginZ", type float (constraint-input) @SINCE_1_0.0 + ANCHOR_POINT, ///< name "anchorPoint", type Vector3 (constraint-input) @SINCE_1_0.0 + ANCHOR_POINT_X, ///< name "anchorPointX", type float (constraint-input) @SINCE_1_0.0 + ANCHOR_POINT_Y, ///< name "anchorPointY", type float (constraint-input) @SINCE_1_0.0 + ANCHOR_POINT_Z, ///< name "anchorPointZ", type float (constraint-input) @SINCE_1_0.0 + SIZE, ///< name "size", type Vector3 (animatable / constraint-input) @SINCE_1_0.0 + SIZE_WIDTH, ///< name "sizeWidth", type float (animatable / constraint-input) @SINCE_1_0.0 + SIZE_HEIGHT, ///< name "sizeHeight", type float (animatable / constraint-input) @SINCE_1_0.0 + SIZE_DEPTH, ///< name "sizeDepth", type float (animatable / constraint-input) @SINCE_1_0.0 + POSITION, ///< name "position", type Vector3 (animatable / constraint-input) @SINCE_1_0.0 + POSITION_X, ///< name "positionX", type float (animatable / constraint-input) @SINCE_1_0.0 + POSITION_Y, ///< name "positionY", type float (animatable / constraint-input) @SINCE_1_0.0 + POSITION_Z, ///< name "positionZ", type float (animatable / constraint-input) @SINCE_1_0.0 + WORLD_POSITION, ///< name "worldPosition", type Vector3 (read-only / constraint-input) @SINCE_1_0.0 + WORLD_POSITION_X, ///< name "worldPositionX", type float (read-only / constraint-input) @SINCE_1_0.0 + WORLD_POSITION_Y, ///< name "worldPositionY", type float (read-only / constraint-input) @SINCE_1_0.0 + WORLD_POSITION_Z, ///< name "worldPositionZ", type float (read-only / constraint-input) @SINCE_1_0.0 + ORIENTATION, ///< name "orientation", type Quaternion (animatable / constraint-input) @SINCE_1_0.0 + WORLD_ORIENTATION, ///< name "worldOrientation", type Quaternion (read-only / constraint-input) @SINCE_1_0.0 + SCALE, ///< name "scale", type Vector3 (animatable / constraint-input) @SINCE_1_0.0 + SCALE_X, ///< name "scaleX", type float (animatable / constraint-input) @SINCE_1_0.0 + SCALE_Y, ///< name "scaleY", type float (animatable / constraint-input) @SINCE_1_0.0 + SCALE_Z, ///< name "scaleZ", type float (animatable / constraint-input) @SINCE_1_0.0 + WORLD_SCALE, ///< name "worldScale", type Vector3 (read-only / constraint-input) @SINCE_1_0.0 + VISIBLE, ///< name "visible", type bool (animatable / constraint-input) @SINCE_1_0.0 + COLOR, ///< name "color", type Vector4 (animatable / constraint-input) @SINCE_1_0.0 + COLOR_RED, ///< name "colorRed", type float (animatable / constraint-input) @SINCE_1_0.0 + COLOR_GREEN, ///< name "colorGreen", type float (animatable / constraint-input) @SINCE_1_0.0 + COLOR_BLUE, ///< name "colorBlue", type float (animatable / constraint-input) @SINCE_1_0.0 + COLOR_ALPHA, ///< name "colorAlpha", type float (animatable / constraint-input) @SINCE_1_0.0 + WORLD_COLOR, ///< name "worldColor", type Vector4 (read-only / constraint-input) @SINCE_1_0.0 + WORLD_MATRIX, ///< name "worldMatrix", type Matrix (read-only / constraint-input) @SINCE_1_0.0 NAME, ///< name "name", type std::string @SINCE_1_0.0 - SENSITIVE, ///< name "sensitive", type bool @SINCE_1_0.0 - LEAVE_REQUIRED, ///< name "leaveRequired", type bool @SINCE_1_0.0 - INHERIT_ORIENTATION, ///< name "inheritOrientation", type bool @SINCE_1_0.0 - INHERIT_SCALE, ///< name "inheritScale", type bool @SINCE_1_0.0 + SENSITIVE, ///< name "sensitive", type bool @SINCE_1_0.0 + LEAVE_REQUIRED, ///< name "leaveRequired", type bool @SINCE_1_0.0 + INHERIT_ORIENTATION, ///< name "inheritOrientation", type bool @SINCE_1_0.0 + INHERIT_SCALE, ///< name "inheritScale", type bool @SINCE_1_0.0 COLOR_MODE, ///< name "colorMode", type std::string @SINCE_1_0.0 POSITION_INHERITANCE, ///< name "positionInheritance", type std::string @DEPRECATED_1_1.24 Use INHERIT_POSITION instead DRAW_MODE, ///< name "drawMode", type std::string @SINCE_1_0.0 - SIZE_MODE_FACTOR, ///< name "sizeModeFactor", type Vector3 @SINCE_1_0.0 - WIDTH_RESIZE_POLICY, ///< name "widthResizePolicy", type String @SINCE_1_0.0 - HEIGHT_RESIZE_POLICY, ///< name "heightResizePolicy", type String @SINCE_1_0.0 - SIZE_SCALE_POLICY, ///< name "sizeScalePolicy", type String @SINCE_1_0.0 - WIDTH_FOR_HEIGHT, ///< name "widthForHeight", type Boolean @SINCE_1_0.0 - HEIGHT_FOR_WIDTH, ///< name "heightForWidth", type Boolean @SINCE_1_0.0 - PADDING, ///< name "padding", type Vector4 @SINCE_1_0.0 - MINIMUM_SIZE, ///< name "minimumSize", type Vector2 @SINCE_1_0.0 - MAXIMUM_SIZE, ///< name "maximumSize", type Vector2 @SINCE_1_0.0 - INHERIT_POSITION, ///< name "inheritPosition", type bool @SINCE_1_1.24 + SIZE_MODE_FACTOR, ///< name "sizeModeFactor", type Vector3 @SINCE_1_0.0 + WIDTH_RESIZE_POLICY, ///< name "widthResizePolicy", type String @SINCE_1_0.0 + HEIGHT_RESIZE_POLICY, ///< name "heightResizePolicy", type String @SINCE_1_0.0 + SIZE_SCALE_POLICY, ///< name "sizeScalePolicy", type String @SINCE_1_0.0 + WIDTH_FOR_HEIGHT, ///< name "widthForHeight", type bool @SINCE_1_0.0 + HEIGHT_FOR_WIDTH, ///< name "heightForWidth", type bool @SINCE_1_0.0 + PADDING, ///< name "padding", type Vector4 @SINCE_1_0.0 + MINIMUM_SIZE, ///< name "minimumSize", type Vector2 @SINCE_1_0.0 + MAXIMUM_SIZE, ///< name "maximumSize", type Vector2 @SINCE_1_0.0 + INHERIT_POSITION, ///< name "inheritPosition", type bool @SINCE_1_1.24 + CLIPPING_MODE, ///< name "clippingMode", type String @SINCE_1_2.5 }; }; @@ -1115,14 +1117,9 @@ public: * Overlay actors are drawn in a separate pass, after all non-overlay actors within the Layer. * For overlay actors, the drawing order is with respect to tree levels of Actors, * and depth-testing will not be used. - * - * If DrawMode::STENCIL is used, the actor and its children will be used to stencil-test other actors - * within the Layer. Stencil actors are therefore drawn into the stencil buffer before any other - * actors within the Layer. - * + * @SINCE_1_0.0 * @param[in] drawMode The new draw-mode to use. - * @note Setting STENCIL will override OVERLAY_2D, if that would otherwise have been inherited. * @note Layers do not inherit the DrawMode from their parents. */ void SetDrawMode( DrawMode::Type drawMode ); @@ -1585,4 +1582,4 @@ inline void UnparentAndReset( Actor& actor ) */ } // namespace Dali -#endif // __DALI_ACTOR_H__ +#endif // DALI_ACTOR_H diff --git a/dali/public-api/actors/layer.h b/dali/public-api/actors/layer.h index 2f15cc8..8498550 100644 --- a/dali/public-api/actors/layer.h +++ b/dali/public-api/actors/layer.h @@ -1,8 +1,8 @@ -#ifndef __DALI_LAYER_H__ -#define __DALI_LAYER_H__ +#ifndef DALI_LAYER_H +#define DALI_LAYER_H /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * 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. @@ -360,7 +360,6 @@ public: * The contents of the layer will not be visible outside this box, when clipping is * enabled. The default clipping box is empty (0,0,0,0) which means everything is clipped. * You can only do rectangular clipping using this API in window coordinates. - * For other kinds of clipping, see Dali::Actor::SetDrawMode(). * @SINCE_1_0.0 * @param [in] x The X-coordinate of the top-left corner of the box * @param [in] y The Y-coordinate of the top-left corner of the box @@ -485,4 +484,4 @@ public: // Not intended for application developers */ } // namespace Dali -#endif //__DALI_LAYER_H__ +#endif // DALI_LAYER_H