Add KeepRendering method to Scene
authorHeeyong Song <heeyong.song@samsung.com>
Thu, 25 May 2023 09:04:50 +0000 (18:04 +0900)
committerJiyun Yang <ji.yang@samsung.com>
Wed, 31 May 2023 04:40:01 +0000 (13:40 +0900)
Change-Id: I71e79a9a54e589f269f066cd93b13c57637b239c

12 files changed:
automated-tests/src/dali/dali-test-suite-utils/test-application.cpp
automated-tests/src/dali/dali-test-suite-utils/test-application.h
automated-tests/src/dali/utc-Dali-Scene.cpp
automated-tests/src/dali/utc-Dali-Stage.cpp
dali/integration-api/scene.cpp
dali/integration-api/scene.h
dali/internal/event/common/scene-impl.cpp
dali/internal/event/common/scene-impl.h
dali/internal/render/common/render-manager.cpp
dali/internal/update/common/scene-graph-scene.cpp
dali/internal/update/common/scene-graph-scene.h
dali/internal/update/manager/update-manager.cpp

index a8354e8..47487e2 100644 (file)
@@ -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<Rect<int>>& 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<Rect<int>> damagedRects;
+    Rect<int>              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
index ce0e151..5e86b3c 100644 (file)
@@ -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<Rect<int>>& damagedRects);
   bool        RenderWithPartialUpdate(std::vector<Rect<int>>& damagedRects, Rect<int>& 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<Integration::Scene> mScenes;
 
   uint32_t mSurfaceWidth;
   uint32_t mSurfaceHeight;
index 90d7d9e..3beb0b5 100644 (file)
@@ -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;
+}
index fb9df29..b9b8050 100644 (file)
@@ -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;
 }
index d84c422..820dfce 100644 (file)
@@ -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();
index 75d4939..66ab16a 100644 (file)
@@ -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
index d60e48b..7995f17 100644 (file)
@@ -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;
index c431fee..02bb666 100644 (file)
@@ -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();
index 2dff2e5..ca862d1 100644 (file)
@@ -710,6 +710,11 @@ void RenderManager::PreRender(Integration::Scene& scene, std::vector<Rect<int>>&
     }
   }
 
+  if(sceneObject->IsNeededFullUpdate())
+  {
+    cleanDamagedRect = true; // And make full update at this frame
+  }
+
   if(!cleanDamagedRect)
   {
     damagedRectCleaner.SetCleanOnReturn(false);
index 7313724..2ca0e6b 100644 (file)
@@ -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
index 88e93dd..7f7f82a 100644 (file)
@@ -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<int32_t> 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<int32_t> 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<Scene, float>;
+
+  // 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
index 03659c3..2723a7b 100644 (file)
@@ -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> frameCallbackProcessor; ///< Owned FrameCallbackProcessor, only created if required.
 
   std::atomic<std::size_t> 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<uint32_t>(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)