From 9c10746b2b943035acf1150f59d4cb3146e077f8 Mon Sep 17 00:00:00 2001 From: Heeyong Song Date: Thu, 25 May 2023 18:04:50 +0900 Subject: [PATCH] Add KeepRendering method to Scene Change-Id: I71e79a9a54e589f269f066cd93b13c57637b239c --- .../dali-test-suite-utils/test-application.cpp | 49 ++++- .../dali/dali-test-suite-utils/test-application.h | 9 +- automated-tests/src/dali/utc-Dali-Scene.cpp | 231 +++++++++++++++++---- automated-tests/src/dali/utc-Dali-Stage.cpp | 9 +- dali/integration-api/scene.cpp | 5 + dali/integration-api/scene.h | 10 + dali/internal/event/common/scene-impl.cpp | 6 + dali/internal/event/common/scene-impl.h | 5 + dali/internal/render/common/render-manager.cpp | 5 + dali/internal/update/common/scene-graph-scene.cpp | 26 ++- dali/internal/update/common/scene-graph-scene.h | 50 ++++- dali/internal/update/manager/update-manager.cpp | 42 ++-- 12 files changed, 368 insertions(+), 79 deletions(-) diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-application.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-application.cpp index a8354e8..47487e2 100644 --- a/automated-tests/src/dali/dali-test-suite-utils/test-application.cpp +++ b/automated-tests/src/dali/dali-test-suite-utils/test-application.cpp @@ -85,6 +85,8 @@ void TestApplication::CreateScene() rtInfo.SetSurface(&mSurfaceWidth); // Can point to anything, really. mScene.SetSurfaceRenderTarget(rtInfo); + + mScenes.push_back(mScene); } void TestApplication::InitializeCore() @@ -212,8 +214,11 @@ bool TestApplication::Render(uint32_t intervalMilliseconds, const char* location mCore->PreRender(mRenderStatus, false /*do not force clear*/); if(!uploadOnly) { - mCore->RenderScene(mRenderStatus, mScene, true /*render the off-screen buffers*/); - mCore->RenderScene(mRenderStatus, mScene, false /*render the surface*/); + for(auto&& scene : mScenes) + { + mCore->RenderScene(mRenderStatus, scene, true /*render the off-screen buffers*/); + mCore->RenderScene(mRenderStatus, scene, false /*render the surface*/); + } } mCore->PostRender(); @@ -243,6 +248,36 @@ bool TestApplication::RenderWithPartialUpdate(std::vector>& damagedRec return mStatus.KeepUpdating() || mRenderStatus.NeedsUpdate(); } +bool TestApplication::RenderWithPartialUpdate(uint32_t intervalMilliseconds, const char* location) +{ + DoUpdate(intervalMilliseconds, location); + + // Reset the status + mRenderStatus.SetNeedsUpdate(false); + mRenderStatus.SetNeedsPostRender(false); + + mCore->PreRender(mRenderStatus, false /*do not force clear*/); + + for(auto&& scene : mScenes) + { + std::vector> damagedRects; + Rect clippingRect{}; + + mCore->PreRender(scene, damagedRects); + mCore->RenderScene(mRenderStatus, scene, true /*render the off-screen buffers*/); + for(auto&& iter : damagedRects) + { + clippingRect.Merge(iter); + } + mCore->RenderScene(mRenderStatus, scene, false /*render the surface*/, clippingRect); + } + mCore->PostRender(); + + mFrame++; + + return mStatus.KeepUpdating() || mRenderStatus.NeedsUpdate(); +} + uint32_t TestApplication::GetUpdateStatus() { return mStatus.KeepUpdating(); @@ -297,4 +332,14 @@ uint32_t TestApplication::Wait(uint32_t durationToWait) return time; } +void TestApplication::AddScene(Integration::Scene scene) +{ + mScenes.push_back(scene); +} + +void TestApplication::RemoveScene(Integration::Scene scene) +{ + mScenes.erase(std::remove(mScenes.begin(), mScenes.end(), scene), mScenes.end()); +} + } // namespace Dali diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-application.h b/automated-tests/src/dali/dali-test-suite-utils/test-application.h index ce0e151..5e86b3c 100644 --- a/automated-tests/src/dali/dali-test-suite-utils/test-application.h +++ b/automated-tests/src/dali/dali-test-suite-utils/test-application.h @@ -75,6 +75,7 @@ public: bool Render(uint32_t intervalMilliseconds = DEFAULT_RENDER_INTERVAL, const char* location = NULL, bool uploadOnly = false); bool PreRenderWithPartialUpdate(uint32_t intervalMilliseconds, const char* location, std::vector>& damagedRects); bool RenderWithPartialUpdate(std::vector>& damagedRects, Rect& clippingRect); + bool RenderWithPartialUpdate(uint32_t intervalMilliseconds, const char* location = NULL); uint32_t GetUpdateStatus(); bool UpdateOnly(uint32_t intervalMilliseconds = DEFAULT_RENDER_INTERVAL); bool RenderOnly(); @@ -92,6 +93,9 @@ public: return mScene; } + void AddScene(Integration::Scene scene); + void RemoveScene(Integration::Scene scene); + private: void DoUpdate(uint32_t intervalMilliseconds, const char* location = NULL, bool uploadOnly = false); @@ -103,8 +107,9 @@ protected: Integration::UpdateStatus mStatus; Integration::RenderStatus mRenderStatus; - Integration::Core* mCore; - Dali::Integration::Scene mScene; + Integration::Core* mCore; + Dali::Integration::Scene mScene; + std::vector mScenes; uint32_t mSurfaceWidth; uint32_t mSurfaceHeight; diff --git a/automated-tests/src/dali/utc-Dali-Scene.cpp b/automated-tests/src/dali/utc-Dali-Scene.cpp index 90d7d9e..3beb0b5 100644 --- a/automated-tests/src/dali/utc-Dali-Scene.cpp +++ b/automated-tests/src/dali/utc-Dali-Scene.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * Copyright (c) 2023 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. @@ -1178,10 +1178,11 @@ int UtcDaliSceneSurfaceRotatedWithAngle0(void) damagedRects.clear(); application.GetScene().SurfaceRotated(TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT, - 0, 0); + 0, + 0); // Check current orientations - int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); + int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); int32_t screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should not be changed yet. @@ -1202,7 +1203,7 @@ int UtcDaliSceneSurfaceRotatedWithAngle0(void) DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); // Check current orientations - orientation = application.GetScene().GetCurrentSurfaceOrientation(); + orientation = application.GetScene().GetCurrentSurfaceOrientation(); screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should be changed. @@ -1248,10 +1249,11 @@ int UtcDaliSceneSurfaceRotatedWithAngle90(void) damagedRects.clear(); application.GetScene().SurfaceRotated(TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT, - 90, 0); + 90, + 0); // Check current surface orientation - int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); + int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); int32_t screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should not be changed yet. @@ -1280,7 +1282,7 @@ int UtcDaliSceneSurfaceRotatedWithAngle90(void) DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); // Check current orientations - orientation = application.GetScene().GetCurrentSurfaceOrientation(); + orientation = application.GetScene().GetCurrentSurfaceOrientation(); screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should be changed. @@ -1326,10 +1328,11 @@ int UtcDaliSceneScreenRotatedWithAngle90(void) damagedRects.clear(); application.GetScene().SurfaceRotated(TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT, - 0, 90); + 0, + 90); // Check current surface orientation - int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); + int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); int32_t screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should not be changed yet. @@ -1358,7 +1361,7 @@ int UtcDaliSceneScreenRotatedWithAngle90(void) DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); // Check current orientations - orientation = application.GetScene().GetCurrentSurfaceOrientation(); + orientation = application.GetScene().GetCurrentSurfaceOrientation(); screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should be changed. @@ -1404,10 +1407,11 @@ int UtcDaliSceneSurfaceAndScreenRotatedWithAngle90(void) damagedRects.clear(); application.GetScene().SurfaceRotated(TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT, - 90, 90); + 90, + 90); // Check current surface orientation - int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); + int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); int32_t screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should not be changed yet. @@ -1436,7 +1440,7 @@ int UtcDaliSceneSurfaceAndScreenRotatedWithAngle90(void) DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); // Check current orientations - orientation = application.GetScene().GetCurrentSurfaceOrientation(); + orientation = application.GetScene().GetCurrentSurfaceOrientation(); screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should be changed. @@ -1482,10 +1486,11 @@ int UtcDaliSceneSurfaceRotatedWithAngle180(void) damagedRects.clear(); application.GetScene().SurfaceRotated(TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT, - 180, 0); + 180, + 0); // Check current surface orientation - int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); + int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); int32_t screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should not be changed yet. @@ -1513,7 +1518,7 @@ int UtcDaliSceneSurfaceRotatedWithAngle180(void) DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); // Check current orientations - orientation = application.GetScene().GetCurrentSurfaceOrientation(); + orientation = application.GetScene().GetCurrentSurfaceOrientation(); screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should be changed. @@ -1559,10 +1564,11 @@ int UtcDaliSceneScreenRotatedWithAngle180(void) damagedRects.clear(); application.GetScene().SurfaceRotated(TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT, - 0, 180); + 0, + 180); // Check current surface orientation - int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); + int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); int32_t screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should not be changed yet. @@ -1590,7 +1596,7 @@ int UtcDaliSceneScreenRotatedWithAngle180(void) DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); // Check current orientations - orientation = application.GetScene().GetCurrentSurfaceOrientation(); + orientation = application.GetScene().GetCurrentSurfaceOrientation(); screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should be changed. @@ -1637,10 +1643,11 @@ int UtcDaliSceneSurfaceAndScreenRotatedWithAngle180(void) damagedRects.clear(); application.GetScene().SurfaceRotated(TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT, - 180, 180); + 180, + 180); // Check current orientations - int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); + int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); int32_t screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should not be changed yet. @@ -1661,7 +1668,7 @@ int UtcDaliSceneSurfaceAndScreenRotatedWithAngle180(void) DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); // Check current orientations - orientation = application.GetScene().GetCurrentSurfaceOrientation(); + orientation = application.GetScene().GetCurrentSurfaceOrientation(); screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should be changed. @@ -1707,10 +1714,11 @@ int UtcDaliSceneSurfaceRotatedWithAngle270(void) damagedRects.clear(); application.GetScene().SurfaceRotated(TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT, - 270, 0); + 270, + 0); // Check current surface orientation - int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); + int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); int32_t screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should not be changed yet. @@ -1739,7 +1747,7 @@ int UtcDaliSceneSurfaceRotatedWithAngle270(void) DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); // Check current orientations - orientation = application.GetScene().GetCurrentSurfaceOrientation(); + orientation = application.GetScene().GetCurrentSurfaceOrientation(); screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should be changed. @@ -1785,10 +1793,11 @@ int UtcDaliSceneScreenRotatedWithAngle270(void) damagedRects.clear(); application.GetScene().SurfaceRotated(TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT, - 0, 270); + 0, + 270); // Check current surface orientation - int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); + int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); int32_t screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should not be changed yet. @@ -1817,7 +1826,7 @@ int UtcDaliSceneScreenRotatedWithAngle270(void) DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); // Check current orientations - orientation = application.GetScene().GetCurrentSurfaceOrientation(); + orientation = application.GetScene().GetCurrentSurfaceOrientation(); screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should be changed. @@ -1863,10 +1872,11 @@ int UtcDaliSceneSurfaceAndScreenRotatedWithAngle270(void) damagedRects.clear(); application.GetScene().SurfaceRotated(TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT, - 270, 270); + 270, + 270); // Check current surface orientation - int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); + int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); int32_t screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should not be changed yet. @@ -1895,7 +1905,7 @@ int UtcDaliSceneSurfaceAndScreenRotatedWithAngle270(void) DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); // Check current orientations - orientation = application.GetScene().GetCurrentSurfaceOrientation(); + orientation = application.GetScene().GetCurrentSurfaceOrientation(); screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should be changed. @@ -1939,10 +1949,11 @@ int UtcDaliSceneSetSurfaceRotationCompletedAcknowledgementWithAngle90(void) damagedRects.clear(); application.GetScene().SurfaceRotated(TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT, - 90, 0); + 90, + 0); // Check current surface orientation - int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); + int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); int32_t screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should not be changed yet. @@ -1972,7 +1983,7 @@ int UtcDaliSceneSetSurfaceRotationCompletedAcknowledgementWithAngle90(void) DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); // Check current orientations - orientation = application.GetScene().GetCurrentSurfaceOrientation(); + orientation = application.GetScene().GetCurrentSurfaceOrientation(); screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should be changed. @@ -2019,10 +2030,11 @@ int UtcDaliSceneSetScreenRotationCompletedAcknowledgementWithAngle90(void) damagedRects.clear(); application.GetScene().SurfaceRotated(TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT, - 0, 90); + 0, + 90); // Check current surface orientation - int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); + int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); int32_t screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should not be changed yet. @@ -2052,7 +2064,7 @@ int UtcDaliSceneSetScreenRotationCompletedAcknowledgementWithAngle90(void) DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); // Check current orientations - orientation = application.GetScene().GetCurrentSurfaceOrientation(); + orientation = application.GetScene().GetCurrentSurfaceOrientation(); screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should be changed. @@ -2099,10 +2111,11 @@ int UtcDaliSceneSetSurfaceAndScreenRotationCompletedAcknowledgementWithAngle90(v damagedRects.clear(); application.GetScene().SurfaceRotated(TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT, - 90, 90); + 90, + 90); // Check current surface orientation - int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); + int32_t orientation = application.GetScene().GetCurrentSurfaceOrientation(); int32_t screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should not be changed yet. @@ -2132,7 +2145,7 @@ int UtcDaliSceneSetSurfaceAndScreenRotationCompletedAcknowledgementWithAngle90(v DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION); // Check current orientations - orientation = application.GetScene().GetCurrentSurfaceOrientation(); + orientation = application.GetScene().GetCurrentSurfaceOrientation(); screenOrientation = application.GetScene().GetCurrentScreenOrientation(); // It should be changed. @@ -2204,7 +2217,8 @@ int UtcDaliSceneSurfaceRotatedPartialUpdate(void) // Rotate surface application.GetScene().SurfaceRotated(TestApplication::DEFAULT_SURFACE_HEIGHT, TestApplication::DEFAULT_SURFACE_WIDTH, - 90, 0); + 90, + 0); damagedRects.clear(); @@ -2657,8 +2671,8 @@ int UtcDaliSceneSurfaceResizedWithOverlayLayer(void) DALI_TEST_EQUALS(scene.GetRootLayer(), defaultTask.GetSourceActor(), TEST_LOCATION); // Ensure stage size matches the scene size - auto stage = Stage::GetCurrent(); - Vector2 sceneSize = stage.GetSize(); + auto stage = Stage::GetCurrent(); + Vector2 sceneSize = stage.GetSize(); Viewport sceneViewport(0, 0, sceneSize.x, sceneSize.y); DALI_TEST_EQUALS(stage.GetSize(), scene.GetSize(), TEST_LOCATION); Viewport defaultViewport = defaultTask.GetViewport(); @@ -2667,8 +2681,8 @@ int UtcDaliSceneSurfaceResizedWithOverlayLayer(void) Layer layer = scene.GetOverlayLayer(); // There should be 2 task by default. DALI_TEST_EQUALS(tasks.GetTaskCount(), 2u, TEST_LOCATION); - RenderTask overlayTask = tasks.GetTask(1u); - Viewport overlayViewport = overlayTask.GetViewport(); + RenderTask overlayTask = tasks.GetTask(1u); + Viewport overlayViewport = overlayTask.GetViewport(); DALI_TEST_EQUALS(defaultViewport, overlayViewport, TEST_LOCATION); // Resize the scene @@ -2681,3 +2695,130 @@ int UtcDaliSceneSurfaceResizedWithOverlayLayer(void) END_TEST; } + +int UtcDaliSceneKeepRendering(void) +{ + tet_infoline("Test keep rendering"); + + TestApplication application; + + auto scene = application.GetScene(); + DALI_TEST_CHECK(scene); + + Actor actor = CreateRenderableActor(); + scene.Add(actor); + + // Run core until it wants to sleep + bool keepUpdating(true); + while(keepUpdating) + { + application.SendNotification(); + keepUpdating = application.Render(1000.0f /*1 second*/); + } + + // Force rendering for the next 5 seconds + scene.KeepRendering(5.0f); + + application.SendNotification(); + + keepUpdating = application.Render(1000.0f /*1 second*/); + DALI_TEST_CHECK(keepUpdating); + keepUpdating = application.Render(1000.0f /*2 seconds*/); + DALI_TEST_CHECK(keepUpdating); + keepUpdating = application.Render(1000.0f /*3 seconds*/); + DALI_TEST_CHECK(keepUpdating); + keepUpdating = application.Render(1000.0f /*4 seconds*/); + DALI_TEST_CHECK(keepUpdating); + keepUpdating = application.Render(1000.0f /*5 seconds*/); + DALI_TEST_CHECK(keepUpdating); + keepUpdating = application.Render(1000.0f /*6 seconds*/); // After 5 sec + DALI_TEST_CHECK(!keepUpdating); + + END_TEST; +} + +int UtcDaliSceneKeepRenderingMultipleScene(void) +{ + tet_infoline("Test keep rendering - multiple scene"); + + TestApplication application( + TestApplication::DEFAULT_SURFACE_WIDTH, + TestApplication::DEFAULT_SURFACE_HEIGHT, + TestApplication::DEFAULT_HORIZONTAL_DPI, + TestApplication::DEFAULT_VERTICAL_DPI, + true, + true); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + + auto defaultScene = application.GetScene(); + DALI_TEST_CHECK(defaultScene); + + Actor actor1 = CreateRenderableActor(); + actor1.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS); + actor1.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f)); + defaultScene.Add(actor1); + + // Create a Scene + Dali::Integration::Scene scene = Dali::Integration::Scene::New(Size(480.0f, 800.0f)); + DALI_TEST_CHECK(scene); + + application.AddScene(scene); + + Actor actor2 = CreateRenderableActor(); + actor2.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS); + actor2.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f)); + scene.Add(actor2); + + // Run core until it wants to sleep + bool keepUpdating(true); + while(keepUpdating) + { + application.SendNotification(); + keepUpdating = application.RenderWithPartialUpdate(1000.0f /*1 second*/); + } + + drawTrace.Enable(true); + + // Force rendering of the default scene for the next 5 seconds (0sec ~ 5sec) + defaultScene.KeepRendering(5.0f); + + application.SendNotification(); + keepUpdating = application.RenderWithPartialUpdate(1000.0f /*1 second*/); + + DALI_TEST_CHECK(keepUpdating); + DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 1, TEST_LOCATION); // Only default scene should be drawn + + drawTrace.Reset(); + + // Force rendering of the new scene for the next 5 seconds (1sec ~ 6sec) + scene.KeepRendering(5.0f); + + application.SendNotification(); + keepUpdating = application.RenderWithPartialUpdate(3000.0f /*4 second*/); + + DALI_TEST_CHECK(keepUpdating); + DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 2, TEST_LOCATION); // Both scenes should be drawn + + drawTrace.Reset(); + + keepUpdating = application.RenderWithPartialUpdate(1000.0f /*5 second*/); + + DALI_TEST_CHECK(keepUpdating); + DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 2, TEST_LOCATION); // Still both scenes should be drawn + + drawTrace.Reset(); + + keepUpdating = application.RenderWithPartialUpdate(1000.0f /*6 second*/); + + DALI_TEST_CHECK(keepUpdating); + DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 1, TEST_LOCATION); // Only the new scenes should be drawn + + drawTrace.Reset(); + + keepUpdating = application.RenderWithPartialUpdate(1000.0f /*7 second*/); + + DALI_TEST_CHECK(!keepUpdating); + DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 0, TEST_LOCATION); // Nothing drawn + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-Stage.cpp b/automated-tests/src/dali/utc-Dali-Stage.cpp index fb9df29..b9b8050 100644 --- a/automated-tests/src/dali/utc-Dali-Stage.cpp +++ b/automated-tests/src/dali/utc-Dali-Stage.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2023 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. @@ -791,6 +791,9 @@ int UtcDaliStageKeepRenderingP(void) Stage stage = Stage::GetCurrent(); + Actor actor = CreateRenderableActor(); + stage.Add(actor); + // Run core until it wants to sleep bool keepUpdating(true); while(keepUpdating) @@ -804,7 +807,7 @@ int UtcDaliStageKeepRenderingP(void) application.SendNotification(); - // Test that core wants to sleep after 10 seconds + // Test that core wants to sleep after 5 seconds keepUpdating = application.Render(1000.0f /*1 second*/); DALI_TEST_CHECK(keepUpdating); keepUpdating = application.Render(1000.0f /*2 seconds*/); @@ -814,6 +817,8 @@ int UtcDaliStageKeepRenderingP(void) keepUpdating = application.Render(1000.0f /*4 seconds*/); DALI_TEST_CHECK(keepUpdating); keepUpdating = application.Render(1000.0f /*5 seconds*/); + DALI_TEST_CHECK(keepUpdating); + keepUpdating = application.Render(1000.0f /*6 seconds*/); // After 5 sec DALI_TEST_CHECK(!keepUpdating); END_TEST; } diff --git a/dali/integration-api/scene.cpp b/dali/integration-api/scene.cpp index d84c422..820dfce 100644 --- a/dali/integration-api/scene.cpp +++ b/dali/integration-api/scene.cpp @@ -213,6 +213,11 @@ bool Scene::IsRotationCompletedAcknowledgementSet() const return GetImplementation(*this).IsRotationCompletedAcknowledgementSet(); } +void Scene::KeepRendering(float durationSeconds) +{ + GetImplementation(*this).KeepRendering(durationSeconds); +} + Scene::EventProcessingFinishedSignalType& Scene::EventProcessingFinishedSignal() { return GetImplementation(*this).EventProcessingFinishedSignal(); diff --git a/dali/integration-api/scene.h b/dali/integration-api/scene.h index 75d4939..66ab16a 100644 --- a/dali/integration-api/scene.h +++ b/dali/integration-api/scene.h @@ -390,6 +390,16 @@ public: bool IsRotationCompletedAcknowledgementSet() const; /** + * @brief Keep rendering for at least the given amount of time. + * + * By default, Dali will stop rendering when no Actor positions are being set, and when no animations are running etc. + * This method is useful to force screen refreshes. + * + * @param[in] durationSeconds Time to keep rendering, 0 means render at least one more frame + */ + void KeepRendering(float durationSeconds); + + /** * @brief This signal is emitted just after the event processing is finished. * * @return The signal to connect to diff --git a/dali/internal/event/common/scene-impl.cpp b/dali/internal/event/common/scene-impl.cpp index d60e48b..7995f17 100644 --- a/dali/internal/event/common/scene-impl.cpp +++ b/dali/internal/event/common/scene-impl.cpp @@ -474,6 +474,12 @@ void Scene::GetFramePresentedCallback(Dali::Integration::Scene::FrameCallbackCon } } +void Scene::KeepRendering(float durationSeconds) +{ + ThreadLocalStorage* tls = ThreadLocalStorage::GetInternal(); + KeepRenderingMessage(tls->GetEventThreadServices(), *mSceneObject, durationSeconds); +} + Integration::Scene::KeyEventSignalType& Scene::KeyEventSignal() { return mKeyEventSignal; diff --git a/dali/internal/event/common/scene-impl.h b/dali/internal/event/common/scene-impl.h index c431fee..02bb666 100644 --- a/dali/internal/event/common/scene-impl.h +++ b/dali/internal/event/common/scene-impl.h @@ -303,6 +303,11 @@ public: void GetFramePresentedCallback(Dali::Integration::Scene::FrameCallbackContainer& callbacks); /** + * @copydoc Dali::Integration::Scene::KeepRendering + */ + void KeepRendering(float durationSeconds); + + /** * @copydoc Integration::Scene::KeyEventSignal() */ Integration::Scene::KeyEventSignalType& KeyEventSignal(); diff --git a/dali/internal/render/common/render-manager.cpp b/dali/internal/render/common/render-manager.cpp index 2dff2e5..ca862d1 100644 --- a/dali/internal/render/common/render-manager.cpp +++ b/dali/internal/render/common/render-manager.cpp @@ -710,6 +710,11 @@ void RenderManager::PreRender(Integration::Scene& scene, std::vector>& } } + if(sceneObject->IsNeededFullUpdate()) + { + cleanDamagedRect = true; // And make full update at this frame + } + if(!cleanDamagedRect) { damagedRectCleaner.SetCleanOnReturn(false); diff --git a/dali/internal/update/common/scene-graph-scene.cpp b/dali/internal/update/common/scene-graph-scene.cpp index 7313724..2ca0e6b 100644 --- a/dali/internal/update/common/scene-graph-scene.cpp +++ b/dali/internal/update/common/scene-graph-scene.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * Copyright (c) 2023 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,12 +30,13 @@ namespace SceneGraph Scene::Scene() : mFrameRenderedCallbacks(), mFramePresentedCallbacks(), - mSkipRendering(false), mSurfaceRect(), mSurfaceOrientation(0), mScreenOrientation(0), mSurfaceRectChanged(false), - mRotationCompletedAcknowledgement(false) + mRotationCompletedAcknowledgement(false), + mSkipRendering(false), + mNeedFullUpdate(false) { } @@ -232,6 +233,25 @@ void Scene::SetSurfaceRenderTargetCreateInfo(const Graphics::RenderTargetCreateI } } +void Scene::KeepRendering(float durationSeconds) +{ + mKeepRenderingSeconds = std::max(mKeepRenderingSeconds, durationSeconds); +} + +bool Scene::KeepRenderingCheck(float elapsedSeconds) +{ + if(mKeepRenderingSeconds > 0.0f) + { + mNeedFullUpdate = true; // Full update if KeepRendering is required + mKeepRenderingSeconds = std::max(0.0f, mKeepRenderingSeconds - elapsedSeconds); + return true; + } + + mNeedFullUpdate = false; + mKeepRenderingSeconds = 0.0f; + return false; +} + } // namespace SceneGraph } // namespace Internal diff --git a/dali/internal/update/common/scene-graph-scene.h b/dali/internal/update/common/scene-graph-scene.h index 88e93dd..7f7f82a 100644 --- a/dali/internal/update/common/scene-graph-scene.h +++ b/dali/internal/update/common/scene-graph-scene.h @@ -240,6 +240,30 @@ public: void SetSurfaceRenderTargetCreateInfo(const Graphics::RenderTargetCreateInfo& renderTargetCreateInfo); /** + * @brief Keep rendering for at least the given amount of time. + * + * @param[in] durationSeconds Time to keep rendering, 0 means render at least one more frame + */ + void KeepRendering(float durationSeconds); + + /** + * @brief Check whether rendering should keep going. + * + * @param[in] elapsedSeconds The time in seconds since the previous update. + * @return True if rendering should keep going. + */ + bool KeepRenderingCheck(float elapsedSeconds); + + /** + * @brief Query if the scene needs full update + * @return True if the scene needs full update + */ + bool IsNeededFullUpdate() const + { + return mNeedFullUpdate; + } + + /** * Get the render target created for the scene * * @return the render target @@ -322,13 +346,16 @@ private: Dali::Integration::Scene::FrameCallbackContainer mFrameRenderedCallbacks; ///< Frame rendered callbacks Dali::Integration::Scene::FrameCallbackContainer mFramePresentedCallbacks; ///< Frame presented callbacks - bool mSkipRendering; ///< A flag to skip rendering + Rect mSurfaceRect; ///< The rectangle of surface which is related ot this scene. + int32_t mSurfaceOrientation; ///< The orientation of surface which is related of this scene + int32_t mScreenOrientation; ///< The orientation of screen + + float mKeepRenderingSeconds{0.0f}; ///< Time to keep rendering - Rect mSurfaceRect; ///< The rectangle of surface which is related ot this scene. - int32_t mSurfaceOrientation; ///< The orientation of surface which is related of this scene - int32_t mScreenOrientation; ///< The orientation of screen - bool mSurfaceRectChanged; ///< The flag of surface's rectangle is changed when is resized or moved. - bool mRotationCompletedAcknowledgement; ///< The flag of sending the acknowledgement to complete window rotation. + bool mSurfaceRectChanged; ///< The flag of surface's rectangle is changed when is resized or moved. + bool mRotationCompletedAcknowledgement; ///< The flag of sending the acknowledgement to complete window rotation. + bool mSkipRendering; ///< A flag to skip rendering + bool mNeedFullUpdate; ///< A flag to update full area // Render pass and render target @@ -416,6 +443,17 @@ inline void SetSurfaceRenderTargetCreateInfoMessage(EventThreadServices& eventTh new(slot) LocalType(&scene, &Scene::SetSurfaceRenderTargetCreateInfo, renderTargetCreateInfo); } +inline void KeepRenderingMessage(EventThreadServices& eventThreadServices, const Scene& scene, float durationSeconds) +{ + using LocalType = MessageValue1; + + // Reserve some memory inside the message queue + uint32_t* 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(&scene, &Scene::KeepRendering, durationSeconds); +} + } // namespace SceneGraph } // namespace Internal diff --git a/dali/internal/update/manager/update-manager.cpp b/dali/internal/update/manager/update-manager.cpp index 03659c3..2723a7b 100644 --- a/dali/internal/update/manager/update-manager.cpp +++ b/dali/internal/update/manager/update-manager.cpp @@ -185,7 +185,6 @@ struct UpdateManager::Impl panGestureProcessor(nullptr), messageQueue(renderController, sceneGraphBuffers), frameCallbackProcessor(nullptr), - keepRenderingSeconds(0.0f), nodeDirtyFlags(NodePropertyFlags::TRANSFORM), // set to TransformFlag to ensure full update the first time through Update() frameCounter(0), renderingBehavior(DevelStage::Rendering::IF_REQUIRED), @@ -305,10 +304,9 @@ struct UpdateManager::Impl OwnerPointer frameCallbackProcessor; ///< Owned FrameCallbackProcessor, only created if required. std::atomic renderInstructionCapacity{0u}; - float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering - NodePropertyFlags nodeDirtyFlags; ///< cumulative node dirty flags from previous frame - uint32_t frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore. - DevelStage::Rendering renderingBehavior; ///< Set via DevelStage::SetRenderingBehavior + NodePropertyFlags nodeDirtyFlags; ///< cumulative node dirty flags from previous frame + uint32_t frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore. + DevelStage::Rendering renderingBehavior; ///< Set via DevelStage::SetRenderingBehavior bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update() bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out) @@ -986,8 +984,9 @@ uint32_t UpdateManager::Update(float elapsedSeconds, mImpl->frameCallbackProcessor || // ..a frame callback processor is existed OR gestureUpdated; // ..a gesture property was updated - bool keepRendererRendering = false; - mImpl->renderingRequired = false; + uint32_t keepUpdating = 0; + bool keepRendererRendering = false; + mImpl->renderingRequired = false; // Although the scene-graph may not require an update, we still need to synchronize double-buffered // values if the scene was updated in the previous frame. @@ -1096,9 +1095,16 @@ uint32_t UpdateManager::Update(float elapsedSeconds, scene->scene->GetRenderInstructions().ResetAndReserve(bufferIndex, static_cast(scene->taskList->GetTasks().Count())); + bool sceneKeepUpdating = scene->scene->KeepRenderingCheck(elapsedSeconds); + if(sceneKeepUpdating) + { + keepUpdating |= KeepUpdating::STAGE_KEEP_RENDERING; + } + // If there are animations running, only add render instruction if at least one animation is currently active (i.e. not delayed) // or the nodes are dirty - if(!isAnimationRunning || animationActive || mImpl->renderingRequired || (mImpl->nodeDirtyFlags & RenderableUpdateFlags)) + // or keep rendering is requested + if(!isAnimationRunning || animationActive || mImpl->renderingRequired || (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || sceneKeepUpdating) { keepRendererRendering |= mImpl->renderTaskProcessor.Process(bufferIndex, *scene->taskList, @@ -1167,12 +1173,15 @@ uint32_t UpdateManager::Update(float elapsedSeconds, mImpl->previousUpdateScene = updateScene; // Check whether further updates are required - uint32_t keepUpdating = KeepUpdatingCheck(elapsedSeconds); + keepUpdating |= KeepUpdatingCheck(elapsedSeconds); if(keepRendererRendering) { keepUpdating |= KeepUpdating::STAGE_KEEP_RENDERING; + } + if(keepUpdating & KeepUpdating::STAGE_KEEP_RENDERING) + { // Set dirty flags for next frame to continue rendering mImpl->nodeDirtyFlags |= RenderableUpdateFlags; } @@ -1207,23 +1216,15 @@ void UpdateManager::PostRender() uint32_t UpdateManager::KeepUpdatingCheck(float elapsedSeconds) const { - // Update the duration set via Stage::KeepRendering() - if(mImpl->keepRenderingSeconds > 0.0f) - { - mImpl->keepRenderingSeconds -= elapsedSeconds; - } - uint32_t keepUpdatingRequest = KeepUpdating::NOT_REQUESTED; // If the rendering behavior is set to continuously render, then continue to render. - // If Stage::KeepRendering() has been called, then continue until the duration has elapsed. // Keep updating until no messages are received and no animations are running. // If an animation has just finished, update at least once more for Discard end-actions. // No need to check for renderQueue as there is always a render after update and if that // render needs another update it will tell the adaptor to call update again - if((mImpl->renderingBehavior == DevelStage::Rendering::CONTINUOUSLY) || - (mImpl->keepRenderingSeconds > 0.0f)) + if(mImpl->renderingBehavior == DevelStage::Rendering::CONTINUOUSLY) { keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING; } @@ -1255,7 +1256,10 @@ void UpdateManager::SurfaceReplaced(Scene* scene) void UpdateManager::KeepRendering(float durationSeconds) { - mImpl->keepRenderingSeconds = std::max(mImpl->keepRenderingSeconds, durationSeconds); + for(auto&& scene : mImpl->scenes) + { + scene->scene->KeepRendering(durationSeconds); + } } void UpdateManager::SetRenderingBehavior(DevelStage::Rendering renderingBehavior) -- 2.7.4