From fd2f99d83dc86de5e4e76fe1a1d0f97a008037f5 Mon Sep 17 00:00:00 2001 From: Heeyong Song Date: Fri, 25 Nov 2022 15:36:00 +0900 Subject: [PATCH] Fix partial update issues Try to reuse RenderItems of the default root layer Handle below cases for partial update - One actor has multiple renderers - One renderer is used by multiple actors - Update uniform hash every frame Change-Id: Iac12c5e00f9eb3fc507bbd4d15560f39f13b3061 --- automated-tests/src/dali/utc-Dali-Actor.cpp | 319 ++++++++++++++++++--- .../src/dali/utc-Dali-DecoratedVisualRenderer.cpp | 7 +- automated-tests/src/dali/utc-Dali-Renderer.cpp | 218 ++++++++++++++ automated-tests/src/dali/utc-Dali-Texture.cpp | 172 +++++++++++ .../src/dali/utc-Dali-VisualRenderer.cpp | 9 +- dali/internal/common/core-impl.cpp | 1 + dali/internal/render/common/render-algorithms.cpp | 3 +- dali/internal/render/common/render-manager.cpp | 19 +- .../render/data-providers/render-data-provider.h | 17 +- dali/internal/render/renderers/render-renderer.cpp | 66 +---- dali/internal/render/renderers/render-renderer.h | 16 +- dali/internal/render/renderers/render-texture.cpp | 13 +- dali/internal/render/renderers/render-texture.h | 28 ++ dali/internal/update/common/node-resetter.h | 5 +- .../manager/render-instruction-processor.cpp | 44 +-- dali/internal/update/manager/update-algorithms.cpp | 20 +- dali/internal/update/manager/update-manager.cpp | 14 + dali/internal/update/manager/update-manager.h | 5 + dali/internal/update/nodes/node.cpp | 20 ++ dali/internal/update/nodes/node.h | 14 +- .../internal/update/nodes/partial-rendering-data.h | 29 +- .../update/rendering/scene-graph-renderer.cpp | 76 ++++- .../update/rendering/scene-graph-renderer.h | 60 ++-- .../update/rendering/scene-graph-texture-set.cpp | 8 +- 24 files changed, 958 insertions(+), 225 deletions(-) diff --git a/automated-tests/src/dali/utc-Dali-Actor.cpp b/automated-tests/src/dali/utc-Dali-Actor.cpp index 09ec1a6..a4264a4 100644 --- a/automated-tests/src/dali/utc-Dali-Actor.cpp +++ b/automated-tests/src/dali/utc-Dali-Actor.cpp @@ -8790,9 +8790,11 @@ int utcDaliActorPartialUpdateSetColor(void) damagedRects.clear(); application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + application.RenderWithPartialUpdate(damagedRects, clippingRect); damagedRects.clear(); application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + application.RenderWithPartialUpdate(damagedRects, clippingRect); // 2. Set new color actor.SetProperty(Actor::Property::COLOR, Vector3(1.0f, 0.0f, 0.0f)); @@ -9000,7 +9002,7 @@ int utcDaliActorPartialUpdateTwoActors(void) END_TEST; } -int utcDaliActorPartialUpdateActorsWithSizeHint(void) +int utcDaliActorPartialUpdateActorsWithSizeHint01(void) { TestApplication application( TestApplication::DEFAULT_SURFACE_WIDTH, @@ -9053,10 +9055,6 @@ int utcDaliActorPartialUpdateActorsWithSizeHint(void) application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); application.RenderWithPartialUpdate(damagedRects, clippingRect); - damagedRects.clear(); - application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); - application.RenderWithPartialUpdate(damagedRects, clippingRect); - // Ensure the damaged rect is empty DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION); @@ -9095,6 +9093,67 @@ int utcDaliActorPartialUpdateActorsWithSizeHint(void) application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); application.RenderWithPartialUpdate(damagedRects, clippingRect); + // Ensure the damaged rect is empty + DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION); + + // Chnage UPDATE_AREA_HINT + actor.SetProperty(Actor::Property::UPDATE_AREA_HINT, Vector4(-32.0f, -16.0f, 64.0f, 64.0f)); + application.GetScene().Add(actor); + + application.SendNotification(); + application.PreRenderWithPartialUpdate(TestApplication::DEFAULT_RENDER_INTERVAL, nullptr, damagedRects); + + DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); + + clippingRect = Rect(0, 720, 80, 80); + DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); + + application.RenderWithPartialUpdate(damagedRects, clippingRect); + + DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); + + END_TEST; +} + +int utcDaliActorPartialUpdateActorsWithSizeHint02(void) +{ + TestApplication application( + TestApplication::DEFAULT_SURFACE_WIDTH, + TestApplication::DEFAULT_SURFACE_HEIGHT, + TestApplication::DEFAULT_HORIZONTAL_DPI, + TestApplication::DEFAULT_VERTICAL_DPI, + true, + true); + + tet_infoline("Check the damaged rect with partial update and actor size hint"); + + const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams()); + + Actor actor = CreateRenderableActor(); + actor.SetProperty(Actor::Property::POSITION, Vector3(64.0f, 64.0f, 0.0f)); + actor.SetProperty(Actor::Property::SIZE, Vector3(32.0f, 32.0f, 0.0f)); + actor.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS); + application.GetScene().Add(actor); + + application.SendNotification(); + std::vector> damagedRects; + application.PreRenderWithPartialUpdate(TestApplication::DEFAULT_RENDER_INTERVAL, nullptr, damagedRects); + + DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); + + Rect clippingRect = Rect(48, 720, 48, 48); + DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); + + application.RenderWithPartialUpdate(damagedRects, clippingRect); + + DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); + damagedRects.clear(); application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); application.RenderWithPartialUpdate(damagedRects, clippingRect); @@ -9103,7 +9162,32 @@ int utcDaliActorPartialUpdateActorsWithSizeHint(void) DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION); // Chnage UPDATE_AREA_HINT - actor.SetProperty(Actor::Property::UPDATE_AREA_HINT, Vector4(-32.0f, -16.0f, 64.0f, 64.0f)); + actor.SetProperty(Actor::Property::UPDATE_AREA_HINT, Vector4(0.0f, 0.0f, 64.0f, 64.0f)); + + application.SendNotification(); + application.PreRenderWithPartialUpdate(TestApplication::DEFAULT_RENDER_INTERVAL, nullptr, damagedRects); + + DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); + + clippingRect = Rect(32, 704, 80, 80); + DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); + + application.RenderWithPartialUpdate(damagedRects, clippingRect); + + DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); + + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + application.RenderWithPartialUpdate(damagedRects, clippingRect); + + // Ensure the damaged rect is empty + DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION); + + // Chnage UPDATE_AREA_HINT + actor.SetProperty(Actor::Property::UPDATE_AREA_HINT, Vector4(16.0f, 16.0f, 64.0f, 64.0f)); application.GetScene().Add(actor); application.SendNotification(); @@ -9111,7 +9195,7 @@ int utcDaliActorPartialUpdateActorsWithSizeHint(void) DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); - clippingRect = Rect(0, 720, 80, 80); + clippingRect = Rect(32, 688, 96, 96); DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); application.RenderWithPartialUpdate(damagedRects, clippingRect); @@ -9168,11 +9252,6 @@ int utcDaliActorPartialUpdateAnimation(void) clippingRect = TestApplication::DEFAULT_SURFACE_RECT; application.RenderWithPartialUpdate(damagedRects, clippingRect); - damagedRects.clear(); - clippingRect = TestApplication::DEFAULT_SURFACE_RECT; - application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); - application.RenderWithPartialUpdate(damagedRects, clippingRect); - // Make an animation Animation animation = Animation::New(1.0f); animation.AnimateTo(Property(actor2, Actor::Property::POSITION_X), 160.0f, TimePeriod(0.5f, 0.5f)); @@ -9235,8 +9314,7 @@ int utcDaliActorPartialUpdateAnimation(void) damagedRects.clear(); application.PreRenderWithPartialUpdate(500, nullptr, damagedRects); - DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); - DALI_TEST_EQUALS>(expectedRect2, damagedRects[0], TEST_LOCATION); + DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION); clippingRect = TestApplication::DEFAULT_SURFACE_RECT; application.RenderWithPartialUpdate(damagedRects, clippingRect); @@ -9672,7 +9750,7 @@ int utcDaliActorPartialUpdateChangeTransparency(void) DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); // Aligned by 16 - Rect clippingRect = Rect(16, 768, 32, 32); // in screen coordinates, includes 3 last frames updates + Rect clippingRect = Rect(16, 768, 32, 32); // in screen coordinates DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); application.RenderWithPartialUpdate(damagedRects, clippingRect); @@ -9685,9 +9763,8 @@ int utcDaliActorPartialUpdateChangeTransparency(void) application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); application.RenderWithPartialUpdate(damagedRects, clippingRect); - damagedRects.clear(); - application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); - application.RenderWithPartialUpdate(damagedRects, clippingRect); + // Ensure the damaged rect is empty + DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION); // Make the actor transparent by changing opacity of the Renderer // It changes a uniform value @@ -9699,9 +9776,9 @@ int utcDaliActorPartialUpdateChangeTransparency(void) // The damaged rect should be same damagedRects.clear(); application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); - application.RenderWithPartialUpdate(damagedRects, clippingRect); - DALI_TEST_CHECK(damagedRects.size() > 0); + DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); + application.RenderWithPartialUpdate(damagedRects, clippingRect); damagedRects.clear(); application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); @@ -9718,12 +9795,8 @@ int utcDaliActorPartialUpdateChangeTransparency(void) // The damaged rect should not be empty damagedRects.clear(); application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); - application.RenderWithPartialUpdate(damagedRects, clippingRect); DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); - - damagedRects.clear(); - application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); application.RenderWithPartialUpdate(damagedRects, clippingRect); damagedRects.clear(); @@ -9741,12 +9814,8 @@ int utcDaliActorPartialUpdateChangeTransparency(void) // The damaged rect should not be empty damagedRects.clear(); application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); - application.RenderWithPartialUpdate(damagedRects, clippingRect); DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); - - damagedRects.clear(); - application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); application.RenderWithPartialUpdate(damagedRects, clippingRect); damagedRects.clear(); @@ -9764,12 +9833,8 @@ int utcDaliActorPartialUpdateChangeTransparency(void) // The damaged rect should not be empty damagedRects.clear(); application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); - application.RenderWithPartialUpdate(damagedRects, clippingRect); DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); - - damagedRects.clear(); - application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); application.RenderWithPartialUpdate(damagedRects, clippingRect); damagedRects.clear(); @@ -9787,9 +9852,9 @@ int utcDaliActorPartialUpdateChangeTransparency(void) // The damaged rect should be same damagedRects.clear(); application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); - application.RenderWithPartialUpdate(damagedRects, clippingRect); DALI_TEST_CHECK(damagedRects.size() > 0); DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); + application.RenderWithPartialUpdate(damagedRects, clippingRect); damagedRects.clear(); application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); @@ -9806,9 +9871,9 @@ int utcDaliActorPartialUpdateChangeTransparency(void) // The damaged rect should not be empty damagedRects.clear(); application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); - application.RenderWithPartialUpdate(damagedRects, clippingRect); DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); + application.RenderWithPartialUpdate(damagedRects, clippingRect); END_TEST; } @@ -10116,6 +10181,192 @@ int utcDaliActorPartialUpdate3DTransform(void) END_TEST; } +int utcDaliActorPartialUpdateOneActorMultipleRenderers(void) +{ + TestApplication application( + TestApplication::DEFAULT_SURFACE_WIDTH, + TestApplication::DEFAULT_SURFACE_HEIGHT, + TestApplication::DEFAULT_HORIZONTAL_DPI, + TestApplication::DEFAULT_VERTICAL_DPI, + true, + true); + + tet_infoline("Check the damaged rect with one actor which has multiple renderers"); + + const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams()); + + Actor actor = CreateRenderableActor(); + + // Create another renderer + Geometry geometry = CreateQuadGeometry(); + Shader shader = CreateShader(); + Renderer renderer2 = Renderer::New(geometry, shader); + actor.AddRenderer(renderer2); + + actor[Actor::Property::ANCHOR_POINT] = AnchorPoint::TOP_LEFT; + actor[Actor::Property::POSITION] = Vector3(16.0f, 16.0f, 0.0f); + actor[Actor::Property::SIZE] = Vector3(16.0f, 16.0f, 0.0f); + actor.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS); + application.GetScene().Add(actor); + + application.SendNotification(); + + DALI_TEST_EQUALS(actor.GetRendererCount(), 2u, TEST_LOCATION); + + std::vector> damagedRects; + + // Actor added, damaged rect is added size of actor + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + DALI_TEST_EQUALS(damagedRects.size(), 2, TEST_LOCATION); + + // Aligned by 16 + Rect clippingRect = Rect(16, 768, 32, 32); // in screen coordinates + DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); + DALI_TEST_EQUALS>(clippingRect, damagedRects[1], TEST_LOCATION); + + application.RenderWithPartialUpdate(damagedRects, clippingRect); + DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); + + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + application.RenderWithPartialUpdate(damagedRects, clippingRect); + + // Ensure the damaged rect is empty + DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION); + + // Make renderer2 dirty + renderer2[DevelRenderer::Property::OPACITY] = 0.5f; + + application.SendNotification(); + + // The damaged rect should be the actor area + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + + clippingRect = Rect(16, 768, 32, 32); // in screen coordinates + DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); + DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); + + application.RenderWithPartialUpdate(damagedRects, clippingRect); + + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + application.RenderWithPartialUpdate(damagedRects, clippingRect); + + // Ensure the damaged rect is empty + DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION); + + // Make renderer2 dirty + renderer2[Renderer::Property::FACE_CULLING_MODE] = FaceCullingMode::BACK; + + application.SendNotification(); + + // The damaged rect should be the actor area + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + + clippingRect = Rect(16, 768, 32, 32); // in screen coordinates + DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); + DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); + + application.RenderWithPartialUpdate(damagedRects, clippingRect); + + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + application.RenderWithPartialUpdate(damagedRects, clippingRect); + + // Ensure the damaged rect is empty + DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION); + + END_TEST; +} + +int utcDaliActorPartialUpdateMultipleActorsOneRenderer(void) +{ + TestApplication application( + TestApplication::DEFAULT_SURFACE_WIDTH, + TestApplication::DEFAULT_SURFACE_HEIGHT, + TestApplication::DEFAULT_HORIZONTAL_DPI, + TestApplication::DEFAULT_VERTICAL_DPI, + true, + true); + + tet_infoline("Check the damaged rect with multiple actors which share a same renderer"); + + const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams()); + + Actor actor = CreateRenderableActor(); + actor[Actor::Property::ANCHOR_POINT] = AnchorPoint::TOP_LEFT; + actor[Actor::Property::POSITION] = Vector3(16.0f, 16.0f, 0.0f); + actor[Actor::Property::SIZE] = Vector3(16.0f, 16.0f, 0.0f); + actor.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS); + application.GetScene().Add(actor); + + // Create another actor which has the same renderer with actor1 + Actor actor2 = Actor::New(); + Renderer renderer = actor.GetRendererAt(0); + actor2.AddRenderer(renderer); + actor2[Actor::Property::ANCHOR_POINT] = AnchorPoint::TOP_LEFT; + actor2[Actor::Property::POSITION] = Vector3(16.0f, 16.0f, 0.0f); + actor2[Actor::Property::SIZE] = Vector3(16.0f, 16.0f, 0.0f); + actor2.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS); + application.GetScene().Add(actor2); + + application.SendNotification(); + + std::vector> damagedRects; + + // Actor added, damaged rect is added size of actor + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + DALI_TEST_EQUALS(damagedRects.size(), 2, TEST_LOCATION); + + // Aligned by 16 + Rect clippingRect = Rect(16, 768, 32, 32); // in screen coordinates + DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); + DALI_TEST_EQUALS>(clippingRect, damagedRects[1], TEST_LOCATION); + + application.RenderWithPartialUpdate(damagedRects, clippingRect); + DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); + + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + application.RenderWithPartialUpdate(damagedRects, clippingRect); + + // Ensure the damaged rect is empty + DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION); + + // Make renderer dirty + renderer[DevelRenderer::Property::OPACITY] = 0.5f; + + application.SendNotification(); + + // The damaged rect should be the actor area + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + + clippingRect = Rect(16, 768, 32, 32); // in screen coordinates + DALI_TEST_EQUALS(damagedRects.size(), 2, TEST_LOCATION); + DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); + DALI_TEST_EQUALS>(clippingRect, damagedRects[1], TEST_LOCATION); + + application.RenderWithPartialUpdate(damagedRects, clippingRect); + + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + application.RenderWithPartialUpdate(damagedRects, clippingRect); + + // Ensure the damaged rect is empty + DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION); + + END_TEST; +} + int UtcDaliActorCaptureAllTouchAfterStartPropertyP(void) { TestApplication application; diff --git a/automated-tests/src/dali/utc-Dali-DecoratedVisualRenderer.cpp b/automated-tests/src/dali/utc-Dali-DecoratedVisualRenderer.cpp index ab8eb18..e0f8c28 100644 --- a/automated-tests/src/dali/utc-Dali-DecoratedVisualRenderer.cpp +++ b/automated-tests/src/dali/utc-Dali-DecoratedVisualRenderer.cpp @@ -848,9 +848,8 @@ int UtcDaliDecoratedVisualRendererPartialUpdate(void) application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); application.RenderWithPartialUpdate(damagedRects, clippingRect); - damagedRects.clear(); - application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); - application.RenderWithPartialUpdate(damagedRects, clippingRect); + // Ensure the damaged rect is empty + DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION); // Set clippingRect as full surface now. TODO : Set valid rect if we can. clippingRect = TestApplication::DEFAULT_SURFACE_RECT; @@ -1027,4 +1026,4 @@ int UtcDaliDecoratedVisualRendererPartialUpdate(void) DALI_TEST_EQUALS(renderer.GetProperty(index), -1.0f, TEST_LOCATION); END_TEST; -} \ No newline at end of file +} diff --git a/automated-tests/src/dali/utc-Dali-Renderer.cpp b/automated-tests/src/dali/utc-Dali-Renderer.cpp index 0ae0595..3fd820b 100644 --- a/automated-tests/src/dali/utc-Dali-Renderer.cpp +++ b/automated-tests/src/dali/utc-Dali-Renderer.cpp @@ -3980,3 +3980,221 @@ int UtcDaliRendererUniformArrayOfStruct(void) END_TEST; } + +int utcDaliRendererPartialUpdateChangeUniform(void) +{ + TestApplication application( + TestApplication::DEFAULT_SURFACE_WIDTH, + TestApplication::DEFAULT_SURFACE_HEIGHT, + TestApplication::DEFAULT_HORIZONTAL_DPI, + TestApplication::DEFAULT_VERTICAL_DPI, + true, + true); + + tet_infoline("Check the damaged rect with changing uniform"); + + const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams()); + + std::vector> damagedRects; + Rect clippingRect; + application.SendNotification(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + + // First render pass, nothing to render, adaptor would just do swap buffer. + DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION); + application.RenderWithPartialUpdate(damagedRects, clippingRect); + + Shader shader = Shader::New("VertexSource", "FragmentSource"); + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New(geometry, shader); + + Property::Index colorIndex = renderer.RegisterProperty("uFadeColor", Color::WHITE); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + actor.SetProperty(Actor::Property::POSITION, Vector3(16.0f, 16.0f, 0.0f)); + actor.SetProperty(Actor::Property::SIZE, Vector3(16.0f, 16.0f, 0.0f)); + actor.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + + // 1. Actor added, damaged rect is added size of actor + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); + + // Aligned by 16 + clippingRect = Rect(16, 768, 32, 32); // in screen coordinates + DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); + application.RenderWithPartialUpdate(damagedRects, clippingRect); + DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); + + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + application.RenderWithPartialUpdate(damagedRects, clippingRect); + + // Ensure the damaged rect is empty + DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION); + + // 2. Change the uniform value + renderer.SetProperty(colorIndex, Color::RED); + application.SendNotification(); + + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); + + // Aligned by 16 + clippingRect = Rect(16, 768, 32, 32); // in screen coordinates + DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); + application.RenderWithPartialUpdate(damagedRects, clippingRect); + DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); + + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + application.RenderWithPartialUpdate(damagedRects, clippingRect); + + // 3. Change the uniform value and another property together + actor.SetProperty(Actor::Property::COLOR, Color::YELLOW); + renderer.SetProperty(colorIndex, Color::BLUE); + application.SendNotification(); + + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); + + // Aligned by 16 + clippingRect = Rect(16, 768, 32, 32); // in screen coordinates + DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); + application.RenderWithPartialUpdate(damagedRects, clippingRect); + DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); + + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + application.RenderWithPartialUpdate(damagedRects, clippingRect); + + // 4. Change the uniform value only + renderer.SetProperty(colorIndex, Color::RED); // Set the previous value (#2) + application.SendNotification(); + + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); + + // Aligned by 16 + clippingRect = Rect(16, 768, 32, 32); // in screen coordinates + DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); + application.RenderWithPartialUpdate(damagedRects, clippingRect); + DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); + + END_TEST; +} + +int utcDaliRendererPartialUpdateAddRemoveRenderer(void) +{ + TestApplication application( + TestApplication::DEFAULT_SURFACE_WIDTH, + TestApplication::DEFAULT_SURFACE_HEIGHT, + TestApplication::DEFAULT_HORIZONTAL_DPI, + TestApplication::DEFAULT_VERTICAL_DPI, + true, + true); + + tet_infoline("Check the damaged rect with adding / removing renderer"); + + const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams()); + + Shader shader = Shader::New("VertexSource", "FragmentSource"); + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New(geometry, shader); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + actor.SetProperty(Actor::Property::POSITION, Vector3(16.0f, 16.0f, 0.0f)); + actor.SetProperty(Actor::Property::SIZE, Vector3(16.0f, 16.0f, 0.0f)); + actor.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + + std::vector> damagedRects; + Rect clippingRect; + + // 1. Actor added, damaged rect is added size of actor + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); + + // Aligned by 16 + clippingRect = Rect(16, 768, 32, 32); // in screen coordinates + DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); + application.RenderWithPartialUpdate(damagedRects, clippingRect); + DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); + + // 2. Remove renderer + actor.RemoveRenderer(renderer); + application.SendNotification(); + + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + + DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); + DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); + + application.RenderWithPartialUpdate(damagedRects, clippingRect); + + // 3. Change a property value of the Renderer + renderer.SetProperty(DevelRenderer::Property::OPACITY, 0.5f); + application.SendNotification(); + + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + + DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION); + + application.RenderWithPartialUpdate(damagedRects, clippingRect); + + // 4. Add renderer again + actor.AddRenderer(renderer); + application.SendNotification(); + + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + + DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); + DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); + + application.RenderWithPartialUpdate(damagedRects, clippingRect); + + // 5. Remove renderer agin + actor.RemoveRenderer(renderer); + application.SendNotification(); + + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + + DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); + DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); + + application.RenderWithPartialUpdate(damagedRects, clippingRect); + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-Texture.cpp b/automated-tests/src/dali/utc-Dali-Texture.cpp index b16d10b..36ae1d3 100644 --- a/automated-tests/src/dali/utc-Dali-Texture.cpp +++ b/automated-tests/src/dali/utc-Dali-Texture.cpp @@ -1319,3 +1319,175 @@ int UtcDaliTextureGetPixelFormat(void) END_TEST; } + +int utcDaliTexturePartialUpdate01(void) +{ + TestApplication application( + TestApplication::DEFAULT_SURFACE_WIDTH, + TestApplication::DEFAULT_SURFACE_HEIGHT, + TestApplication::DEFAULT_HORIZONTAL_DPI, + TestApplication::DEFAULT_VERTICAL_DPI, + true, + true); + + tet_infoline("Check the damaged rect with partial update and texture change"); + + const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams()); + + std::vector> damagedRects; + Rect clippingRect; + + Geometry geometry = CreateQuadGeometry(); + Shader shader = Shader::New("vertexSrc", "fragmentSrc"); + Renderer renderer = Renderer::New(geometry, shader); + + uint32_t width(4); + uint32_t height(4); + Texture texture = Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, width, height); + TextureSet textureSet = TextureSet::New(); + textureSet.SetTexture(0u, texture); + renderer.SetTextures(textureSet); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + + actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + actor.SetProperty(Actor::Property::POSITION, Vector3(16.0f, 16.0f, 0.0f)); + actor.SetProperty(Actor::Property::SIZE, Vector3(16.0f, 16.0f, 0.0f)); + application.GetScene().Add(actor); + + damagedRects.clear(); + application.SendNotification(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); + + // Aligned by 16 + clippingRect = Rect(16, 768, 32, 32); // in screen coordinates + DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); + application.RenderWithPartialUpdate(damagedRects, clippingRect); + DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); + + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + application.RenderWithPartialUpdate(damagedRects, clippingRect); + + // Ensure the damaged rect is empty + DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION); + + // Upload texture + uint32_t bufferSize(width * height * 4); + uint8_t* buffer = reinterpret_cast(malloc(bufferSize)); + PixelData pixelData = PixelData::New(buffer, bufferSize, width, height, Pixel::RGBA8888, PixelData::FREE); + texture.Upload(pixelData); + + damagedRects.clear(); + application.SendNotification(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); + + // Aligned by 16 + clippingRect = Rect(16, 768, 32, 32); // in screen coordinates + DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); + application.RenderWithPartialUpdate(damagedRects, clippingRect); + DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); + + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + application.RenderWithPartialUpdate(damagedRects, clippingRect); + + // Ensure the damaged rect is empty + DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION); + + END_TEST; +} + +int utcDaliTexturePartialUpdate02(void) +{ + TestApplication application( + TestApplication::DEFAULT_SURFACE_WIDTH, + TestApplication::DEFAULT_SURFACE_HEIGHT, + TestApplication::DEFAULT_HORIZONTAL_DPI, + TestApplication::DEFAULT_VERTICAL_DPI, + true, + true); + + tet_infoline("Check the damaged rect with partial update and texture change"); + + const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams()); + + std::vector> damagedRects; + Rect clippingRect; + + Geometry geometry = CreateQuadGeometry(); + Shader shader = Shader::New("vertexSrc", "fragmentSrc"); + Renderer renderer = Renderer::New(geometry, shader); + + uint32_t width(4); + uint32_t height(4); + Texture texture1 = Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, width, height); + Texture texture2 = Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, width, height); + TextureSet textureSet = TextureSet::New(); + textureSet.SetTexture(0u, texture1); + renderer.SetTextures(textureSet); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + + actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + actor.SetProperty(Actor::Property::POSITION, Vector3(16.0f, 16.0f, 0.0f)); + actor.SetProperty(Actor::Property::SIZE, Vector3(16.0f, 16.0f, 0.0f)); + application.GetScene().Add(actor); + + damagedRects.clear(); + application.SendNotification(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); + + // Aligned by 16 + clippingRect = Rect(16, 768, 32, 32); // in screen coordinates, includes 3 last frames updates + DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); + application.RenderWithPartialUpdate(damagedRects, clippingRect); + DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); + + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + application.RenderWithPartialUpdate(damagedRects, clippingRect); + + // Ensure the damaged rect is empty + DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION); + + // Set another texture + textureSet.SetTexture(0u, texture2); + + damagedRects.clear(); + application.SendNotification(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); + + // Aligned by 16 + clippingRect = Rect(16, 768, 32, 32); // in screen coordinates, includes 3 last frames updates + DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); + application.RenderWithPartialUpdate(damagedRects, clippingRect); + DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); + + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + application.RenderWithPartialUpdate(damagedRects, clippingRect); + + // Ensure the damaged rect is empty + DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION); + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-VisualRenderer.cpp b/automated-tests/src/dali/utc-Dali-VisualRenderer.cpp index b274772..d5b2f70 100644 --- a/automated-tests/src/dali/utc-Dali-VisualRenderer.cpp +++ b/automated-tests/src/dali/utc-Dali-VisualRenderer.cpp @@ -723,7 +723,7 @@ int UtcDaliVisualRendererPartialUpdate(void) DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); // Aligned by 16 - Rect clippingRect = Rect(64, 672, 80, 80); // in screen coordinates, includes 3 last frames updates + Rect clippingRect = Rect(64, 672, 80, 80); // in screen coordinates DALI_TEST_EQUALS>(clippingRect, damagedRects[0], TEST_LOCATION); application.RenderWithPartialUpdate(damagedRects, clippingRect); @@ -736,9 +736,8 @@ int UtcDaliVisualRendererPartialUpdate(void) application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); application.RenderWithPartialUpdate(damagedRects, clippingRect); - damagedRects.clear(); - application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); - application.RenderWithPartialUpdate(damagedRects, clippingRect); + // Ensure the damaged rect is empty + DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION); // Set clippingRect as full surface now. TODO : Set valid rect if we can. clippingRect = TestApplication::DEFAULT_SURFACE_RECT; @@ -914,4 +913,4 @@ int UtcDaliVisualRendererPartialUpdate(void) DALI_TEST_EQUALS(renderer.GetProperty(index), Vector2(0.5f, 2.0f), TEST_LOCATION); END_TEST; -} \ No newline at end of file +} diff --git a/dali/internal/common/core-impl.cpp b/dali/internal/common/core-impl.cpp index 919d6f5..9a5c89e 100644 --- a/dali/internal/common/core-impl.cpp +++ b/dali/internal/common/core-impl.cpp @@ -234,6 +234,7 @@ void Core::RenderScene(RenderStatus& status, Integration::Scene& scene, bool ren void Core::PostRender() { + mUpdateManager->PostRender(); mRenderManager->PostRender(); } diff --git a/dali/internal/render/common/render-algorithms.cpp b/dali/internal/render/common/render-algorithms.cpp index 0a301cb..fac9fbe 100644 --- a/dali/internal/render/common/render-algorithms.cpp +++ b/dali/internal/render/common/render-algorithms.cpp @@ -651,7 +651,8 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList& bool skip = true; if(!rootClippingRect.IsEmpty()) { - auto rect = RenderItem::CalculateViewportSpaceAABB(item.mModelViewMatrix, Vector3(item.mUpdateArea.x, item.mUpdateArea.y, 0.0f), Vector3(item.mUpdateArea.z, item.mUpdateArea.w, 0.0f), mViewportRectangle.width, mViewportRectangle.height); + Vector4 updateArea = item.mRenderer ? item.mRenderer->GetVisualTransformedUpdateArea(bufferIndex, item.mUpdateArea) : item.mUpdateArea; + auto rect = RenderItem::CalculateViewportSpaceAABB(item.mModelViewMatrix, Vector3(updateArea.x, updateArea.y, 0.0f), Vector3(updateArea.z, updateArea.w, 0.0f), mViewportRectangle.width, mViewportRectangle.height); if(rect.Intersect(rootClippingRect)) { diff --git a/dali/internal/render/common/render-manager.cpp b/dali/internal/render/common/render-manager.cpp index 6c1b4de..c7b88c1 100644 --- a/dali/internal/render/common/render-manager.cpp +++ b/dali/internal/render/common/render-manager.cpp @@ -630,11 +630,13 @@ void RenderManager::PreRender(Integration::Scene& scene, std::vector>& // If the item refers to updated node or renderer. if(item.mIsUpdated || (item.mNode && - (item.mNode->Updated() || (item.mRenderer && item.mRenderer->Updated(mImpl->renderBufferIndex, item.mNode))))) + (item.mNode->Updated() || (item.mRenderer && item.mRenderer->Updated(mImpl->renderBufferIndex))))) { item.mIsUpdated = false; - rect = RenderItem::CalculateViewportSpaceAABB(item.mModelViewMatrix, Vector3(item.mUpdateArea.x, item.mUpdateArea.y, 0.0f), Vector3(item.mUpdateArea.z, item.mUpdateArea.w, 0.0f), viewportRect.width, viewportRect.height); + Vector4 updateArea = item.mRenderer ? item.mRenderer->GetVisualTransformedUpdateArea(mImpl->renderBufferIndex, item.mUpdateArea) : item.mUpdateArea; + + rect = RenderItem::CalculateViewportSpaceAABB(item.mModelViewMatrix, Vector3(updateArea.x, updateArea.y, 0.0f), Vector3(updateArea.z, updateArea.w, 0.0f), viewportRect.width, viewportRect.height); if(rect.IsValid() && rect.Intersect(viewportRect) && !rect.IsEmpty()) { const int left = rect.x; @@ -713,13 +715,6 @@ void RenderManager::PreRender(Integration::Scene& scene, std::vector>& { damagedRectCleaner.SetCleanOnReturn(false); } - - // Reset updated flag from the root - Layer* root = sceneObject->GetRoot(); - if(root) - { - root->SetUpdatedTree(false); - } } void RenderManager::RenderScene(Integration::RenderStatus& status, Integration::Scene& scene, bool renderToFbo) @@ -1013,6 +1008,12 @@ void RenderManager::PostRender() iter->OnRenderFinished(); } + // Notify RenderTexture that rendering has finished + for(auto&& iter : mImpl->textureContainer) + { + iter->OnRenderFinished(); + } + mImpl->UpdateTrackers(); uint32_t count = 0u; diff --git a/dali/internal/render/data-providers/render-data-provider.h b/dali/internal/render/data-providers/render-data-provider.h index f33822d..d8a3a0b 100644 --- a/dali/internal/render/data-providers/render-data-provider.h +++ b/dali/internal/render/data-providers/render-data-provider.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_SCENE_GRAPH_RENDER_DATA_PROVIDER_H /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -82,9 +82,24 @@ public: /** * Get the opacity + * @param[in] bufferIndex The current buffer index. * @return The opacity */ virtual float GetOpacity(BufferIndex bufferIndex) const = 0; + + /** + * @brief Retrieve if the render data is updated + * @return An updated flag + */ + virtual bool IsUpdated() const = 0; + + /** + * @brief Get the update area after visual properties applied. + * @param[in] bufferIndex The current buffer index. + * @param[in] originalUpdateArea The original update area before apply the visual properties. + * @return The recalculated size after visual properties applied. + */ + virtual Vector4 GetVisualTransformedUpdateArea(BufferIndex bufferIndex, const Vector4& originalUpdateArea) noexcept = 0; }; } // namespace SceneGraph diff --git a/dali/internal/render/renderers/render-renderer.cpp b/dali/internal/render/renderers/render-renderer.cpp index 4731747..b70408b 100644 --- a/dali/internal/render/renderers/render-renderer.cpp +++ b/dali/internal/render/renderers/render-renderer.cpp @@ -186,8 +186,7 @@ Renderer::Renderer(SceneGraph::RenderDataProvider* dataProvider, mDepthWriteMode(depthWriteMode), mDepthTestMode(depthTestMode), mPremultipliedAlphaEnabled(preMultipliedAlphaEnabled), - mShaderChanged(false), - mUpdated(true) + mShaderChanged(false) { if(blendingBitmask != 0u) { @@ -211,7 +210,6 @@ Renderer::~Renderer() = default; void Renderer::SetGeometry(Render::Geometry* geometry) { mGeometry = geometry; - mUpdated = true; } void Renderer::SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size) { @@ -264,49 +262,41 @@ void Renderer::BindTextures(Graphics::CommandBuffer& commandBuffer, VectorAttributesChanged()) + if(mRenderCallback || mShaderChanged || mGeometry->AttributesChanged() || mRenderDataProvider->IsUpdated()) { return true; } @@ -896,48 +870,26 @@ bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvid for(auto iter = textures->Begin(), end = textures->End(); iter < end; ++iter) { auto texture = *iter; - if(texture && texture->IsNativeImage()) + if(texture && texture->Updated()) { return true; } } } - - // Hash the property values. If the values are different, then rendering is required. - uint64_t hash = 0xc70f6907UL; - const SceneGraph::UniformMap& uniformMapNode = node->GetNodeUniformMap(); - for(uint32_t i = 0u, count = uniformMapNode.Count(); i < count; ++i) - { - hash = uniformMapNode[i].propertyPtr->Hash(bufferIndex, hash); - } - - const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMapDataProvider(); - const SceneGraph::CollectedUniformMap& collectedUniformMap = uniformMapDataProvider.GetCollectedUniformMap(); - for(uint32_t i = 0u, count = collectedUniformMap.Count(); i < count; ++i) - { - hash = collectedUniformMap.mUniformMap[i].propertyPtr->Hash(bufferIndex, hash); - } - - if(mUniformsHash != hash) - { - mUniformsHash = hash; - return true; - } - return false; } +Vector4 Renderer::GetVisualTransformedUpdateArea(BufferIndex bufferIndex, const Vector4& originalUpdateArea) const noexcept +{ + return mRenderDataProvider->GetVisualTransformedUpdateArea(bufferIndex, originalUpdateArea); +} + Graphics::Pipeline& Renderer::PrepareGraphicsPipeline( Program& program, const Dali::Internal::SceneGraph::RenderInstruction& instruction, const SceneGraph::NodeDataProvider& node, bool blend) { - if(mGeometry->AttributesChanged()) - { - mUpdated = true; - } - // Prepare query info PipelineCacheQueryInfo queryInfo{}; queryInfo.program = &program; diff --git a/dali/internal/render/renderers/render-renderer.h b/dali/internal/render/renderers/render-renderer.h index d548efc..51f661e 100644 --- a/dali/internal/render/renderers/render-renderer.h +++ b/dali/internal/render/renderers/render-renderer.h @@ -426,9 +426,8 @@ public: * Check if the renderer attributes/uniforms are updated and returns the flag * * @param[in] bufferIndex The current update buffer index. - * @param[in] node The node using this renderer */ - bool Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node); + bool Updated(BufferIndex bufferIndex); template bool WriteDefaultUniform(const Graphics::UniformInfo* uniformInfo, @@ -450,6 +449,16 @@ public: return mFaceCullingMode; } + /** + * @brief Gets update area after visual properties applied. + * + * @param[in] bufferIndex The index of the previous update buffer. + * @param[in] originalUpdateArea The original update area before apply the visual properties. + * + * @return The recalculated update area after visual properties applied. + */ + Vector4 GetVisualTransformedUpdateArea(BufferIndex bufferIndex, const Vector4& originalUpdateArea) const noexcept; + private: struct UniformIndexMap; @@ -585,15 +594,12 @@ private: using UniformIndexMappings = std::vector; std::vector mUniformIndexMaps; ///< Cached map per node/renderer/shader. - uint64_t mUniformsHash{0}; ///< Hash of uniform map property values - DepthFunction::Type mDepthFunction : 4; ///< The depth function FaceCullingMode::Type mFaceCullingMode : 3; ///< The mode of face culling DepthWriteMode::Type mDepthWriteMode : 3; ///< The depth write mode DepthTestMode::Type mDepthTestMode : 3; ///< The depth test mode bool mPremultipliedAlphaEnabled : 1; ///< Flag indicating whether the Pre-multiplied Alpha Blending is required bool mShaderChanged : 1; ///< Flag indicating the shader changed and uniform maps have to be updated - bool mUpdated : 1; std::vector mDrawCommands; // Devel stuff RenderCallback* mRenderCallback{nullptr}; diff --git a/dali/internal/render/renderers/render-texture.cpp b/dali/internal/render/renderers/render-texture.cpp index f2bc5a3..0d97e69 100644 --- a/dali/internal/render/renderers/render-texture.cpp +++ b/dali/internal/render/renderers/render-texture.cpp @@ -214,7 +214,8 @@ Texture::Texture(Type type, Pixel::Format format, ImageDimensions size) mWidth(size.GetWidth()), mHeight(size.GetHeight()), mType(type), - mHasAlpha(HasAlpha(format)) + mHasAlpha(HasAlpha(format)), + mUpdated(true) { } @@ -227,7 +228,8 @@ Texture::Texture(NativeImageInterfacePtr nativeImageInterface) mWidth(static_cast(nativeImageInterface->GetWidth())), // ignoring overflow, not happening in practice mHeight(static_cast(nativeImageInterface->GetHeight())), // ignoring overflow, not happening in practice mType(TextureType::TEXTURE_2D), - mHasAlpha(nativeImageInterface->RequiresBlending()) + mHasAlpha(nativeImageInterface->RequiresBlending()), + mUpdated(true) { } @@ -345,6 +347,8 @@ void Texture::Upload(PixelDataPtr pixelData, const Internal::Texture::UploadPara updateSourceInfo.memorySource.memory = pixelData->GetBuffer(); mGraphicsController->UpdateTextures({info}, {updateSourceInfo}); + + SetUpdated(true); } bool Texture::HasAlphaChannel() const @@ -367,6 +371,11 @@ void Texture::GenerateMipmaps() mGraphicsController->GenerateTextureMipmaps(*mGraphicsTexture.get()); } +void Texture::OnRenderFinished() +{ + SetUpdated(false); +} + } // namespace Render } // namespace Internal diff --git a/dali/internal/render/renderers/render-texture.h b/dali/internal/render/renderers/render-texture.h index a3945d8..dffbff9 100644 --- a/dali/internal/render/renderers/render-texture.h +++ b/dali/internal/render/renderers/render-texture.h @@ -131,6 +131,33 @@ public: return static_cast(mNativeImage); } + /** + * Called from RenderManager to notify the texture that current rendering pass has finished. + */ + void OnRenderFinished(); + + /** + * Set the updated flag. + * @param[in] updated The updated flag + */ + void SetUpdated(bool updated) + { + mUpdated = updated; + } + + /** + * Check if the texture is updated + * @return True if the texture is updated + */ + [[nodiscard]] bool Updated() + { + if(mUpdated || IsNativeImage()) + { + return true; + } + return false; + } + private: /** * Helper method to apply a sampler to the texture @@ -150,6 +177,7 @@ private: uint16_t mHeight; ///< Height of the texture Type mType : 3; ///< Type of the texture bool mHasAlpha : 1; ///< Whether the format has an alpha channel + bool mUpdated : 1; ///< Whether the texture is updated }; } // namespace Render diff --git a/dali/internal/update/common/node-resetter.h b/dali/internal/update/common/node-resetter.h index 6d31da5..7f27624 100644 --- a/dali/internal/update/common/node-resetter.h +++ b/dali/internal/update/common/node-resetter.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_SCENEGRAPH_NODE_RESETTER_H /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -84,6 +84,7 @@ public: mNode->mVisible.ResetToBaseValue(updateBufferIndex); mNode->mColor.ResetToBaseValue(updateBufferIndex); + mNode->mUpdateAreaHint.ResetToBaseValue(updateBufferIndex); } }; @@ -102,6 +103,7 @@ public: mNode->mVisible.MarkAsDirty(); mNode->mColor.MarkAsDirty(); + mNode->mUpdateAreaHint.MarkAsDirty(); } /** @@ -157,6 +159,7 @@ protected: { mNode->mVisible.MarkAsDirty(); mNode->mColor.MarkAsDirty(); + mNode->mUpdateAreaHint.MarkAsDirty(); } Node* mNode; ///< The node that owns the properties diff --git a/dali/internal/update/manager/render-instruction-processor.cpp b/dali/internal/update/manager/render-instruction-processor.cpp index 3bc7f79..50bdc0e 100644 --- a/dali/internal/update/manager/render-instruction-processor.cpp +++ b/dali/internal/update/manager/render-instruction-processor.cpp @@ -199,14 +199,13 @@ inline void AddRendererToRenderList(BufferIndex updateBufferIndex, Vector3 nodeSize; Vector4 nodeUpdateArea; bool nodeUpdateAreaSet(false); - bool nodeUpdateAreaUseHint(false); Matrix nodeModelViewMatrix(false); bool nodeModelViewMatrixSet(false); // Don't cull items which have render callback bool hasRenderCallback = (renderable.mRenderer && renderable.mRenderer->GetRenderCallback()); - if(cull && renderable.mRenderer && (hasRenderCallback || (!renderable.mRenderer->GetShader().HintEnabled(Dali::Shader::Hint::MODIFIES_GEOMETRY) && node->GetClippingMode() == ClippingMode::DISABLED))) + if(cull && renderable.mRenderer && !hasRenderCallback && !renderable.mRenderer->GetShader().HintEnabled(Dali::Shader::Hint::MODIFIES_GEOMETRY) && node->GetClippingMode() == ClippingMode::DISABLED) { const Vector4& boundingSphere = node->GetBoundingSphere(); inside = (boundingSphere.w > Math::MACHINE_EPSILON_1000) && @@ -214,8 +213,8 @@ inline void AddRendererToRenderList(BufferIndex updateBufferIndex, if(inside && !isLayer3d && viewportSet) { - nodeUpdateAreaUseHint = SetNodeUpdateArea(node, isLayer3d, nodeWorldMatrix, nodeSize, nodeUpdateArea); - nodeUpdateAreaSet = true; + SetNodeUpdateArea(node, isLayer3d, nodeWorldMatrix, nodeSize, nodeUpdateArea); + nodeUpdateAreaSet = true; const Vector3& scale = node->GetWorldScale(updateBufferIndex); const Vector3& size = Vector3(nodeUpdateArea.z, nodeUpdateArea.w, 1.0f) * scale; @@ -261,21 +260,6 @@ inline void AddRendererToRenderList(BufferIndex updateBufferIndex, // Get the next free RenderItem. RenderItem& item = renderList.GetNextFreeItem(); - PartialRenderingData partialRenderingData; - - partialRenderingData.node = node; - partialRenderingData.renderer = renderable.mRenderer; - partialRenderingData.color = node->GetWorldColor(updateBufferIndex); - partialRenderingData.depthIndex = node->GetDepthIndex(); - partialRenderingData.isOpaque = isOpaque; - - partialRenderingData.textureSet = nullptr; - if(DALI_LIKELY(renderable.mRenderer)) - { - partialRenderingData.color.a *= renderable.mRenderer->GetOpacity(updateBufferIndex); - partialRenderingData.textureSet = renderable.mRenderer->GetTextureSet(); - } - item.mNode = node; item.mIsOpaque = isOpaque; item.mColor = node->GetColor(updateBufferIndex); @@ -291,9 +275,6 @@ inline void AddRendererToRenderList(BufferIndex updateBufferIndex, item.mRenderer = &renderable.mRenderer->GetRenderer(); item.mTextureSet = renderable.mRenderer->GetTextureSet(); item.mDepthIndex += renderable.mRenderer->GetDepthIndex(); - - // Get whether collected map is up to date - item.mIsUpdated |= renderable.mRenderer->UniformMapUpdated(); } else { @@ -304,27 +285,22 @@ inline void AddRendererToRenderList(BufferIndex updateBufferIndex, if(!nodeUpdateAreaSet) { - nodeUpdateAreaUseHint = SetNodeUpdateArea(node, isLayer3d, nodeWorldMatrix, nodeSize, nodeUpdateArea); + SetNodeUpdateArea(node, isLayer3d, nodeWorldMatrix, nodeSize, nodeUpdateArea); } item.mSize = nodeSize; item.mUpdateArea = nodeUpdateArea; item.mModelMatrix = nodeWorldMatrix; - // Apply transform informations if node doesn't have update size hint and use VisualRenderer. - if(!nodeUpdateAreaUseHint && renderable.mRenderer && renderable.mRenderer->GetVisualProperties()) - { - Vector3 updateSize = renderable.mRenderer->CalculateVisualTransformedUpdateSize(updateBufferIndex, Vector3(item.mUpdateArea.z, item.mUpdateArea.w, 0.0f)); - item.mUpdateArea.z = updateSize.x; - item.mUpdateArea.w = updateSize.y; - } - if(!nodeModelViewMatrixSet) { MatrixUtils::Multiply(nodeModelViewMatrix, nodeWorldMatrix, viewMatrix); } item.mModelViewMatrix = nodeModelViewMatrix; + PartialRenderingData partialRenderingData; + partialRenderingData.color = node->GetWorldColor(updateBufferIndex); + partialRenderingData.depthIndex = node->GetDepthIndex(); partialRenderingData.matrix = item.mModelViewMatrix; partialRenderingData.updatedPositionSize = item.mUpdateArea; partialRenderingData.size = item.mSize; @@ -489,10 +465,8 @@ inline void RenderInstructionProcessor::SortRenderItems(BufferIndex bufferIndex, // List of zValue calculating functions. const Dali::Layer::SortFunctionType zValueFunctionFromVector3[] = { - [](const Vector3& position) - { return position.z; }, - [](const Vector3& position) - { return position.LengthSquared(); }, + [](const Vector3& position) { return position.z; }, + [](const Vector3& position) { return position.LengthSquared(); }, layer.GetSortFunction(), }; diff --git a/dali/internal/update/manager/update-algorithms.cpp b/dali/internal/update/manager/update-algorithms.cpp index 98e5a93..7cd6ac6 100644 --- a/dali/internal/update/manager/update-algorithms.cpp +++ b/dali/internal/update/manager/update-algorithms.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -113,7 +113,7 @@ inline NodePropertyFlags UpdateNodes(Node& node, UpdateNodeOpacity(node, nodeDirtyFlags, updateBufferIndex); - + node.UpdateUniformHash(updateBufferIndex); // For partial update, mark all children of an animating node as updated. if(updated) // Only set to updated if parent was updated. @@ -211,6 +211,20 @@ inline void UpdateLayers(Node& node, { layer->SetReuseRenderers(updateBufferIndex, false); } + else + { + // If the node is not dirty, then check renderers + const uint32_t count = node.GetRendererCount(); + for(uint32_t i = 0; i < count; ++i) + { + SceneGraph::Renderer* renderer = node.GetRendererAt(i); + if(renderer->IsDirty()) + { + layer->SetReuseRenderers(updateBufferIndex, false); + break; + } + } + } // recurse children NodeContainer& children = node.GetChildren(); @@ -228,6 +242,8 @@ void UpdateLayerTree(Layer& layer, NodePropertyFlags nodeDirtyFlags = layer.GetDirtyFlags(); nodeDirtyFlags |= (layer.IsLocalMatrixDirty() ? NodePropertyFlags::TRANSFORM : NodePropertyFlags::NOTHING); + layer.SetReuseRenderers(updateBufferIndex, nodeDirtyFlags == NodePropertyFlags::NOTHING); + // recurse children NodeContainer& children = layer.GetChildren(); const NodeIter endIter = children.End(); diff --git a/dali/internal/update/manager/update-manager.cpp b/dali/internal/update/manager/update-manager.cpp index 1574b5d..1b5c1a3 100644 --- a/dali/internal/update/manager/update-manager.cpp +++ b/dali/internal/update/manager/update-manager.cpp @@ -1140,6 +1140,20 @@ uint32_t UpdateManager::Update(float elapsedSeconds, return keepUpdating; } +void UpdateManager::PostRender() +{ + // Reset dirty flag + for(auto&& renderer : mImpl->renderers) + { + renderer->ResetDirtyFlag(); + } + + for(auto&& scene : mImpl->scenes) + { + scene->root->SetUpdatedTree(false); + } +} + uint32_t UpdateManager::KeepUpdatingCheck(float elapsedSeconds) const { // Update the duration set via Stage::KeepRendering() diff --git a/dali/internal/update/manager/update-manager.h b/dali/internal/update/manager/update-manager.h index d1f82be..3065d34 100644 --- a/dali/internal/update/manager/update-manager.h +++ b/dali/internal/update/manager/update-manager.h @@ -612,6 +612,11 @@ public: bool uploadOnly); /** + * This is called after rendering all the scenes in the next frame. + */ + void PostRender(); + + /** * @copydoc Dali::Stage::KeepRendering() */ void KeepRendering(float durationSeconds); diff --git a/dali/internal/update/nodes/node.cpp b/dali/internal/update/nodes/node.cpp index af5962d..f0f4943 100644 --- a/dali/internal/update/nodes/node.cpp +++ b/dali/internal/update/nodes/node.cpp @@ -270,6 +270,12 @@ NodePropertyFlags Node::GetDirtyFlags() const flags |= NodePropertyFlags::COLOR; } + // Check whether the update area property has changed + if(!mUpdateAreaHint.IsClean()) + { + flags |= NodePropertyFlags::TRANSFORM; + } + return flags; } @@ -288,6 +294,20 @@ void Node::ResetDirtyFlags(BufferIndex updateBufferIndex) mDirtyFlags = NodePropertyFlags::NOTHING; } +void Node::UpdateUniformHash(BufferIndex bufferIndex) +{ + uint64_t hash = 0xc70f6907UL; + for(uint32_t i = 0u, count = mUniformMaps.Count(); i < count; ++i) + { + hash = mUniformMaps[i].propertyPtr->Hash(bufferIndex, hash); + } + if(mUniformsHash != hash) + { + mUniformsHash = hash; + SetUpdated(true); + } +} + void Node::SetParent(Node& parentNode) { DALI_ASSERT_ALWAYS(this != &parentNode); diff --git a/dali/internal/update/nodes/node.h b/dali/internal/update/nodes/node.h index d9acd62..3e28d7b 100644 --- a/dali/internal/update/nodes/node.h +++ b/dali/internal/update/nodes/node.h @@ -212,6 +212,7 @@ public: void SetClippingMode(const ClippingMode::Type clippingMode) { mClippingMode = clippingMode; + SetDirtyFlag(NodePropertyFlags::TRANSFORM); } /** @@ -876,6 +877,12 @@ public: */ void ResetDirtyFlags(BufferIndex updateBufferIndex); + /** + * Update uniform hash + * @param[in] bufferIndex The buffer to read from. + */ + void UpdateUniformHash(BufferIndex bufferIndex); + protected: /** * Set the parent of a Node. @@ -914,10 +921,10 @@ private: // from NodeDataProvider private: // Delete copy and move - Node(const Node&) = delete; - Node(Node&&) = delete; + Node(const Node&) = delete; + Node(Node&&) = delete; Node& operator=(const Node& rhs) = delete; - Node& operator=(Node&& rhs) = delete; + Node& operator=(Node&& rhs) = delete; /** * Recursive helper to disconnect a Node and its children. @@ -955,6 +962,7 @@ public: // Default properties TransformManagerMatrixInput mWorldMatrix; ///< Full inherited world matrix InheritedColor mWorldColor; ///< Full inherited color + uint64_t mUniformsHash{0u}; ///< Hash of uniform map property values uint32_t mClippingSortModifier; ///< Contains bit-packed clipping information for quick access when sorting const uint32_t mId; ///< The Unique ID of the node. diff --git a/dali/internal/update/nodes/partial-rendering-data.h b/dali/internal/update/nodes/partial-rendering-data.h index d487908..cd52c50 100644 --- a/dali/internal/update/nodes/partial-rendering-data.h +++ b/dali/internal/update/nodes/partial-rendering-data.h @@ -33,16 +33,12 @@ class TextureSet; */ struct PartialRenderingData { - Node* node{nullptr}; /// Node associated with the entry - Renderer* renderer{nullptr}; /// Renderer object - const TextureSet* textureSet{nullptr}; /// TextureSet object - Matrix matrix{}; /// Model-view matrix - Vector4 color{}; /// Color - Vector4 updatedPositionSize{}; /// Updated position/size (x, y, width, height) - Vector3 size{}; /// Size - uint32_t depthIndex{0u}; /// Depth index - uint32_t hash; /// Last frame's hash - bool isOpaque{}; /// Opacity state + Matrix matrix{}; /// Model-view matrix + Vector4 color{}; /// Color + Vector4 updatedPositionSize{}; /// Updated position/size (x, y, width, height) + Vector3 size{}; /// Size + uint32_t depthIndex{0u}; /// Depth index + uint32_t hash; /// Last frame's hash bool mVisible{true}; /// Visible state (Not hashed) bool mRendered{false}; /// Rendering state (Not hashed) @@ -53,15 +49,11 @@ struct PartialRenderingData void CalculateHash() { hash = Dali::INITIAL_HASH_VALUE; - AddToHash(hash, &node, sizeof(decltype(node))); - AddToHash(hash, &renderer, sizeof(decltype(renderer))); - AddToHash(hash, &textureSet, sizeof(decltype(textureSet))); AddToHash(hash, &matrix, sizeof(decltype(matrix))); AddToHash(hash, &color, sizeof(decltype(color))); AddToHash(hash, &updatedPositionSize, sizeof(decltype(updatedPositionSize))); AddToHash(hash, &size, sizeof(decltype(size))); AddToHash(hash, &depthIndex, sizeof(decltype(depthIndex))); - AddToHash(hash, &isOpaque, sizeof(decltype(isOpaque))); } /** @@ -73,30 +65,21 @@ struct PartialRenderingData frameCache.CalculateHash(); return hash != frameCache.hash || - node != frameCache.node || - renderer != frameCache.renderer || - textureSet != frameCache.textureSet || matrix != frameCache.matrix || color != frameCache.color || updatedPositionSize != frameCache.updatedPositionSize || size != frameCache.size || depthIndex != frameCache.depthIndex || - isOpaque != frameCache.isOpaque || - !mRendered; // If everything is the same, check if we didn't render last frame. } void Update(const PartialRenderingData& frameCache) { - node = frameCache.node; - renderer = frameCache.renderer; - textureSet = frameCache.textureSet; matrix = frameCache.matrix; color = frameCache.color; updatedPositionSize = frameCache.updatedPositionSize; size = frameCache.size; depthIndex = frameCache.depthIndex; - isOpaque = frameCache.isOpaque; hash = frameCache.hash; mRendered = true; diff --git a/dali/internal/update/rendering/scene-graph-renderer.cpp b/dali/internal/update/rendering/scene-graph-renderer.cpp index 0036c92..6f4b485 100644 --- a/dali/internal/update/rendering/scene-graph-renderer.cpp +++ b/dali/internal/update/rendering/scene-graph-renderer.cpp @@ -104,8 +104,8 @@ Renderer::Renderer() mRenderingBehavior(DevelRenderer::Rendering::IF_REQUIRED), mUpdateDecay(Renderer::Decay::INITIAL), mRegenerateUniformMap(false), - mUniformMapUpdated(false), mPremultipledAlphaEnabled(false), + mDirtyFlag(true), mOpacity(1.0f), mDepthIndex(0) { @@ -293,11 +293,13 @@ bool Renderer::PrepareRender(BufferIndex updateBufferIndex) new(slot) DerivedType(mRenderer, &Render::Renderer::SetRenderCallback, mRenderCallback); } + SetUpdated(true); + mResendFlag = 0; } // Ensure collected map is up to date - UpdateUniformMap(); + UpdateUniformMap(updateBufferIndex); return rendererUpdated; } @@ -307,6 +309,9 @@ void Renderer::SetTextures(TextureSet* textureSet) DALI_ASSERT_DEBUG(textureSet != NULL && "Texture set pointer is NULL"); mTextureSet = textureSet; + + mDirtyFlag = true; + SetUpdated(true); } const Vector* Renderer::GetTextures() const @@ -332,6 +337,7 @@ void Renderer::SetShader(Shader* shader) mShader->AddUniformMapObserver(*this); mRegenerateUniformMap = true; mResendFlag |= RESEND_GEOMETRY | RESEND_SHADER; + mDirtyFlag = true; } void Renderer::SetGeometry(Render::Geometry* geometry) @@ -348,6 +354,9 @@ void Renderer::SetGeometry(Render::Geometry* geometry) void Renderer::SetDepthIndex(int depthIndex) { mDepthIndex = depthIndex; + + mDirtyFlag = true; + SetUpdated(true); } void Renderer::SetFaceCullingMode(FaceCullingMode::Type faceCullingMode) @@ -364,6 +373,9 @@ FaceCullingMode::Type Renderer::GetFaceCullingMode() const void Renderer::SetBlendMode(BlendMode::Type blendingMode) { mBlendMode = blendingMode; + + mDirtyFlag = true; + SetUpdated(true); } BlendMode::Type Renderer::GetBlendMode() const @@ -377,6 +389,7 @@ void Renderer::SetBlendingOptions(uint32_t options) { mBlendBitmask = options; mResendFlag |= RESEND_BLEND_BIT_MASK; + mDirtyFlag = true; } } @@ -533,6 +546,7 @@ void Renderer::SetRenderCallback(RenderCallback* callback) { mRenderCallback = callback; mResendFlag |= RESEND_SET_RENDER_CALLBACK; + mDirtyFlag = true; } const Render::Renderer::StencilParameters& Renderer::GetStencilParameters() const @@ -543,6 +557,9 @@ const Render::Renderer::StencilParameters& Renderer::GetStencilParameters() cons void Renderer::BakeOpacity(BufferIndex updateBufferIndex, float opacity) { mOpacity.Bake(updateBufferIndex, opacity); + + mDirtyFlag = true; + SetUpdated(true); } float Renderer::GetOpacity(BufferIndex updateBufferIndex) const @@ -553,6 +570,7 @@ float Renderer::GetOpacity(BufferIndex updateBufferIndex) const void Renderer::SetRenderingBehavior(DevelRenderer::Rendering::Type renderingBehavior) { mRenderingBehavior = renderingBehavior; + SetUpdated(true); } DevelRenderer::Rendering::Type Renderer::GetRenderingBehavior() const @@ -656,7 +674,7 @@ Renderer::OpacityType Renderer::GetOpacityType(BufferIndex updateBufferIndex, co return opacityType; } -void Renderer::UpdateUniformMap() +void Renderer::UpdateUniformMap(BufferIndex updateBufferIndex) { if(mRegenerateUniformMap) { @@ -679,7 +697,20 @@ void Renderer::UpdateUniformMap() } localMap.UpdateChangeCounter(); mRegenerateUniformMap = false; - mUniformMapUpdated = true; + SetUpdated(true); + } + + uint64_t hash = 0xc70f6907UL; + const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = GetUniformMapDataProvider(); + const SceneGraph::CollectedUniformMap& collectedUniformMap = uniformMapDataProvider.GetCollectedUniformMap(); + for(uint32_t i = 0u, count = collectedUniformMap.Count(); i < count; ++i) + { + hash = collectedUniformMap.mUniformMap[i].propertyPtr->Hash(updateBufferIndex, hash); + } + if(mUniformsHash != hash) + { + mUniformsHash = hash; + SetUpdated(true); } } @@ -690,6 +721,19 @@ void Renderer::SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, mResendFlag |= RESEND_DRAW_COMMANDS; } +bool Renderer::IsDirty() const +{ + // Check whether the opacity property has changed + return (mDirtyFlag || !mOpacity.IsClean()); +} + +void Renderer::ResetDirtyFlag() +{ + mDirtyFlag = false; + + SetUpdated(false); +} + void Renderer::UniformMappingsChanged(const UniformMap& mappings) { // The mappings are either from PropertyOwner base class, or the Shader @@ -701,7 +745,7 @@ const CollectedUniformMap& Renderer::GetCollectedUniformMap() const return mCollectedUniformMap; } -Vector3 Renderer::CalculateVisualTransformedUpdateSize(BufferIndex updateBufferIndex, const Vector3& originalSize) +Vector4 Renderer::GetVisualTransformedUpdateArea(BufferIndex updateBufferIndex, const Vector4& originalUpdateArea) noexcept { if(mVisualProperties) { @@ -819,19 +863,23 @@ Vector3 Renderer::CalculateVisualTransformedUpdateSize(BufferIndex updateBufferI // = scaleVertexPosition + 2.0f * abs(basicVertexPosition) // Cause transform matrix will think center of vertex is (0, 0) - const Vector2 basicVertexPosition = mVisualPropertiesCoefficient.coefXB * originalSize.GetVectorXY() + mVisualPropertiesCoefficient.coefCB; - const Vector2 scaleVertexPosition = mVisualPropertiesCoefficient.coefXA * originalSize.GetVectorXY() + mVisualPropertiesCoefficient.coefCA; + const Vector2 originalXY = Vector2(originalUpdateArea.x, originalUpdateArea.y); + const Vector2 originalWH = Vector2(originalUpdateArea.z, originalUpdateArea.w); + + const Vector2 basicVertexPosition = mVisualPropertiesCoefficient.coefXB * originalWH + mVisualPropertiesCoefficient.coefCB; + const Vector2 scaleVertexPosition = mVisualPropertiesCoefficient.coefXA * originalWH + mVisualPropertiesCoefficient.coefCA; - // VisualTransform don't set z value. Just copy from original z size - const Vector3 resultSize = Vector3(scaleVertexPosition.x + 2.0f * abs(basicVertexPosition.x) + mVisualPropertiesCoefficient.coefD, - scaleVertexPosition.y + 2.0f * abs(basicVertexPosition.y) + mVisualPropertiesCoefficient.coefD, - originalSize.z); + // TODO : We need to re-generate coefficient to consitder area width/height + const Vector4 resultArea = Vector4(originalXY.x, + originalXY.y, + scaleVertexPosition.x + 2.0f * abs(basicVertexPosition.x) + mVisualPropertiesCoefficient.coefD, + scaleVertexPosition.y + 2.0f * abs(basicVertexPosition.y) + mVisualPropertiesCoefficient.coefD); - DALI_LOG_INFO(gSceneGraphRendererLogFilter, Debug::Verbose, "%f %f --> %f %f\n", originalSize.x, originalSize.y, resultSize.x, resultSize.y); + DALI_LOG_INFO(gSceneGraphRendererLogFilter, Debug::Verbose, "%f %f %f %f--> %f %f %f %f\n", originalUpdateArea.x, originalUpdateArea.y, originalUpdateArea.z, originalUpdateArea.w, resultArea.x, resultArea.y, resultArea.z, resultArea.w); - return resultSize; + return resultArea; } - return originalSize; + return originalUpdateArea; } } // namespace SceneGraph diff --git a/dali/internal/update/rendering/scene-graph-renderer.h b/dali/internal/update/rendering/scene-graph-renderer.h index 1e672a0..f2a84d6 100644 --- a/dali/internal/update/rendering/scene-graph-renderer.h +++ b/dali/internal/update/rendering/scene-graph-renderer.h @@ -380,6 +380,19 @@ public: }; /** + * @copydoc RenderDataProvider::IsUpdated() + */ + bool IsUpdated() const override + { + return Updated(); + } + + /** + * @copydoc RenderDataProvider::GetVisualTransformedUpdateArea() + */ + Vector4 GetVisualTransformedUpdateArea(BufferIndex updateBufferIndex, const Vector4& originalUpdateArea) noexcept override; + + /** * Sets RenderCallback object * * @param[in] callback Valid pointer to RenderCallback object @@ -400,28 +413,27 @@ public: * Merge shader uniform map into renderer uniform map if any of the * maps have changed. Only update uniform map if added to render * instructions. + * @param[in] updateBufferIndex The current update buffer index. */ - void UpdateUniformMap(); + void UpdateUniformMap(BufferIndex updateBufferIndex); /** - * @brief CHeck if the uniformMap regenerated - * @return True if the uniformMap changed after latest checkup. - * @note The uniform map updated flag is reset after calling this. + * Set the given external draw commands on this renderer. */ - [[nodiscard]] inline bool UniformMapUpdated() noexcept - { - if(mUniformMapUpdated) - { - mUniformMapUpdated = false; - return true; - } - return false; - } + void SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size); /** - * Set the given external draw commands on this renderer. + * Query whether a renderer is dirty. + * @return true if the renderer is dirty. + * @note It is used to decide whether to reuse the RenderList. We can't reuse the RenderList if this is dirty. */ - void SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size); + bool IsDirty() const; + + /** + * Reset both dirty flag and updated flag. + * @note This is called after rendering has completed. + */ + void ResetDirtyFlag(); public: // UniformMap::Observer /** @@ -458,16 +470,6 @@ public: // For VisualProperties return mVisualProperties.Get(); } - /** - * @brief Recalculate size after visual properties applied. - * - * @param[in] updateBufferIndex The current update buffer index. - * @param[in] originalSize The original size before apply the visual properties. - * - * @return The recalculated size after visual properties applied. - */ - Vector3 CalculateVisualTransformedUpdateSize(BufferIndex updateBufferIndex, const Vector3& originalSize); - private: /** * Protected constructor; See also Renderer::New() @@ -496,6 +498,7 @@ private: Dali::Internal::Render::Renderer::StencilParameters mStencilParameters; ///< Struct containing all stencil related options + uint64_t mUniformsHash{0}; ///< Hash of uniform map property values uint32_t mIndexedDrawFirstElement; ///< first element index to be drawn using indexed draw uint32_t mIndexedDrawElementsCount; ///< number of elements to be drawn using indexed draw uint32_t mBlendBitmask; ///< The bitmask of blending options @@ -510,9 +513,10 @@ private: DevelRenderer::Rendering::Type mRenderingBehavior : 2; ///< The rendering behavior Decay mUpdateDecay : 2; ///< Update decay (aging) - bool mRegenerateUniformMap : 1; ///< true if the map should be regenerated - bool mUniformMapUpdated : 1; ///< true if the map regenerated recently. - bool mPremultipledAlphaEnabled : 1; ///< Flag indicating whether the Pre-multiplied Alpha Blending is required + bool mRegenerateUniformMap : 1; ///< true if the map should be regenerated + bool mPremultipledAlphaEnabled : 1; ///< Flag indicating whether the Pre-multiplied Alpha Blending is required + bool mDirtyFlag : 1; ///< Flag indicating whether the properties are changed + std::vector mDrawCommands; Dali::RenderCallback* mRenderCallback{nullptr}; diff --git a/dali/internal/update/rendering/scene-graph-texture-set.cpp b/dali/internal/update/rendering/scene-graph-texture-set.cpp index 0fa96f0..0269286 100644 --- a/dali/internal/update/rendering/scene-graph-texture-set.cpp +++ b/dali/internal/update/rendering/scene-graph-texture-set.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -68,6 +68,11 @@ void TextureSet::SetSampler(uint32_t index, Render::Sampler* sampler) } mSamplers[index] = sampler; + + if(index < static_cast(mTextures.Size())) + { + mTextures[index]->SetUpdated(true); + } } void TextureSet::SetTexture(uint32_t index, Render::Texture* texture) @@ -99,6 +104,7 @@ void TextureSet::SetTexture(uint32_t index, Render::Texture* texture) if(texture) { mHasAlpha |= texture->HasAlphaChannel(); + texture->SetUpdated(true); } } -- 2.7.4