From e047fbec5e5b9edb46fca18c888827bc19ec2930 Mon Sep 17 00:00:00 2001 From: Heeyong Song Date: Fri, 14 Oct 2022 10:53:57 +0900 Subject: [PATCH] (Partial Update) Continue to calculate damaged rects even though there is a 3D transformed item Change-Id: I58136911893f488664ecff2f2ef616593efb8658 --- automated-tests/src/dali/utc-Dali-Actor.cpp | 151 ++++++++++++++++++++++++- dali/internal/render/common/render-manager.cpp | 32 +++++- 2 files changed, 179 insertions(+), 4 deletions(-) diff --git a/automated-tests/src/dali/utc-Dali-Actor.cpp b/automated-tests/src/dali/utc-Dali-Actor.cpp index 3574fba..09ec1a6 100644 --- a/automated-tests/src/dali/utc-Dali-Actor.cpp +++ b/automated-tests/src/dali/utc-Dali-Actor.cpp @@ -9885,7 +9885,7 @@ int utcDaliActorPartialUpdateChangeParentOpacity(void) END_TEST; } -int utcDaliActorPartialAddRemoveRenderer(void) +int utcDaliActorPartialUpdateAddRemoveRenderer(void) { TestApplication application( TestApplication::DEFAULT_SURFACE_WIDTH, @@ -9967,6 +9967,155 @@ int utcDaliActorPartialAddRemoveRenderer(void) END_TEST; } +int utcDaliActorPartialUpdate3DTransform(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 3D transformed actors"); + + const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams()); + + Actor actor1 = CreateRenderableActor(); + actor1[Actor::Property::ANCHOR_POINT] = AnchorPoint::TOP_LEFT; + actor1[Actor::Property::POSITION] = Vector3(16.0f, 16.0f, 0.0f); + actor1[Actor::Property::SIZE] = Vector3(16.0f, 16.0f, 0.0f); + actor1.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS); + application.GetScene().Add(actor1); + + // Add a new actor + Actor actor2 = CreateRenderableActor(); + actor2[Actor::Property::ANCHOR_POINT] = AnchorPoint::TOP_LEFT; + actor2[Actor::Property::POSITION] = Vector3(160.0f, 160.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 clippingRect1 = Rect(16, 768, 32, 32); // in screen coordinates + Rect clippingRect2 = Rect(160, 624, 32, 32); + DALI_TEST_EQUALS>(clippingRect1, damagedRects[0], TEST_LOCATION); + DALI_TEST_EQUALS>(clippingRect2, damagedRects[1], TEST_LOCATION); + + Rect surfaceRect = Rect(0, 0, TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT); + application.RenderWithPartialUpdate(damagedRects, surfaceRect); + + damagedRects.clear(); + surfaceRect = Rect(0, 0, TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + application.RenderWithPartialUpdate(damagedRects, surfaceRect); + + damagedRects.clear(); + surfaceRect = Rect(0, 0, TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + application.RenderWithPartialUpdate(damagedRects, surfaceRect); + + // Rotate actor1 on y axis + actor1[Actor::Property::ORIENTATION] = Quaternion(Radian(Degree(90.0)), Vector3::YAXIS); + + // Remove actor2 + actor2.Unparent(); + + application.SendNotification(); + + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + + // Should update full area + surfaceRect = Rect(0, 0, TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT); + DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); + DALI_TEST_EQUALS>(surfaceRect, damagedRects[0], TEST_LOCATION); + application.RenderWithPartialUpdate(damagedRects, surfaceRect); + + // Add actor2 again + application.GetScene().Add(actor2); + + application.SendNotification(); + + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + + // Should update full area + surfaceRect = Rect(0, 0, TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT); + DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); + DALI_TEST_EQUALS>(surfaceRect, damagedRects[0], TEST_LOCATION); + application.RenderWithPartialUpdate(damagedRects, surfaceRect); + + // Reset the orientation of actor1 + actor1[Actor::Property::ORIENTATION] = Quaternion::IDENTITY; + + application.SendNotification(); + + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + + // Should update full area + surfaceRect = Rect(0, 0, TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT); + DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); + DALI_TEST_EQUALS>(surfaceRect, damagedRects[0], TEST_LOCATION); + application.RenderWithPartialUpdate(damagedRects, surfaceRect); + + // Make actor2 dirty + actor2[Actor::Property::SIZE] = Vector3(32.0f, 32.0f, 0.0f); + + application.SendNotification(); + + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + + clippingRect2 = Rect(160, 608, 48, 48); + DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); + DALI_TEST_EQUALS>(clippingRect2, damagedRects[0], TEST_LOCATION); + + application.RenderWithPartialUpdate(damagedRects, clippingRect2); + DALI_TEST_EQUALS(clippingRect2.x, glScissorParams.x, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect2.y, glScissorParams.y, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect2.width, glScissorParams.width, TEST_LOCATION); + DALI_TEST_EQUALS(clippingRect2.height, glScissorParams.height, TEST_LOCATION); + + // Remove actor1 + actor1.Unparent(); + + application.SendNotification(); + + damagedRects.clear(); + surfaceRect = Rect(0, 0, TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + application.RenderWithPartialUpdate(damagedRects, surfaceRect); + + // Rotate actor1 on y axis + actor1[Actor::Property::ORIENTATION] = Quaternion(Radian(Degree(90.0)), Vector3::YAXIS); + + // Add actor1 again + application.GetScene().Add(actor1); + + application.SendNotification(); + + damagedRects.clear(); + application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects); + + // Should update full area + surfaceRect = Rect(0, 0, TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT); + DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION); + DALI_TEST_EQUALS>(surfaceRect, damagedRects[0], TEST_LOCATION); + application.RenderWithPartialUpdate(damagedRects, surfaceRect); + + END_TEST; +} + int UtcDaliActorCaptureAllTouchAfterStartPropertyP(void) { TestApplication application; diff --git a/dali/internal/render/common/render-manager.cpp b/dali/internal/render/common/render-manager.cpp index 3c6af61..bf8b4b2 100644 --- a/dali/internal/render/common/render-manager.cpp +++ b/dali/internal/render/common/render-manager.cpp @@ -521,6 +521,7 @@ void RenderManager::PreRender(Integration::Scene& scene, std::vector>& // Clean collected dirty/damaged rects on exit if 3d layer or 3d node or other conditions. DamagedRectsCleaner damagedRectCleaner(damagedRects, surfaceRect); + bool cleanDamagedRect = false; // Mark previous dirty rects in the sorted array. The array is already sorted by node and renderer, frame number. // so you don't need to sort: std::stable_sort(itemsDirtyRects.begin(), itemsDirtyRects.end()); @@ -601,10 +602,26 @@ void RenderManager::PreRender(Integration::Scene& scene, std::vector>& for(uint32_t listIndex = 0u; listIndex < listCount; ++listIndex) { RenderItem& item = renderList->GetItem(listIndex); - // If the item does 3D transformation, do early exit and clean the damaged rect array + // If the item does 3D transformation, make full update if(item.mUpdateArea == Vector4::ZERO) { - return; + cleanDamagedRect = true; + + // Save the full rect in the damaged list. We need it when this item is removed + DirtyRect dirtyRect(item.mNode, item.mRenderer, surfaceRect); + auto dirtyRectPos = std::lower_bound(itemsDirtyRects.begin(), itemsDirtyRects.end(), dirtyRect); + if(dirtyRectPos != itemsDirtyRects.end() && dirtyRectPos->node == item.mNode && dirtyRectPos->renderer == item.mRenderer) + { + // Replace the rect + dirtyRectPos->visited = true; + dirtyRectPos->rect = dirtyRect.rect; + } + else + { + // Else, just insert the new dirtyrect in the correct position + itemsDirtyRects.insert(dirtyRectPos, dirtyRect); + } + continue; } Rect rect; @@ -659,6 +676,11 @@ void RenderManager::PreRender(Integration::Scene& scene, std::vector>& { dirtyRectPos->visited = true; } + else + { + // The item is not in the list for some reason. Add it! + itemsDirtyRects.insert(dirtyRectPos, dirtyRect); + } } } } @@ -685,7 +707,11 @@ void RenderManager::PreRender(Integration::Scene& scene, std::vector>& } itemsDirtyRects.resize(j - itemsDirtyRects.begin()); - damagedRectCleaner.SetCleanOnReturn(false); + + if(!cleanDamagedRect) + { + damagedRectCleaner.SetCleanOnReturn(false); + } // Reset updated flag from the root Layer* root = sceneObject->GetRoot(); -- 2.7.4