Do not calculate dirty rects when rendering is skipped 78/250678/2
authorHeeyong Song <heeyong.song@samsung.com>
Thu, 31 Dec 2020 04:41:49 +0000 (13:41 +0900)
committerHeeyong Song <heeyong.song@samsung.com>
Sun, 10 Jan 2021 23:43:17 +0000 (23:43 +0000)
- Dirty rect should not be calculated when rendring is skipped
- Fix also RenderItem::mUpdateSize value

Change-Id: I82472d2f1fdeccd5e1d29517cfe5cc80d3169e8d

automated-tests/src/dali/utc-Dali-Actor.cpp
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/render-instruction-processor.cpp
dali/internal/update/manager/update-manager.cpp

index f552fd6..9f49464 100644 (file)
@@ -7929,7 +7929,7 @@ int utcDaliActorPartialUpdate(void)
   DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
 
   // Aligned by 16
-  clippingRect = Rect<int>(16, 736, 48, 64); // in screen coordinates, includes 3 last frames updates
+  clippingRect = Rect<int>(16, 736, 64, 64); // in screen coordinates, includes 3 last frames updates
   DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
   application.RenderWithPartialUpdate(damagedRects, clippingRect);
   DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
@@ -7951,7 +7951,7 @@ int utcDaliActorPartialUpdate(void)
 
   DALI_TEST_EQUALS(clippingRect.IsEmpty(), false, TEST_LOCATION);
   DALI_TEST_EQUALS(clippingRect.IsValid(), true, TEST_LOCATION);
-  DALI_TEST_EQUALS<Rect<int>>(clippingRect, Rect<int>(16, 736, 48, 64), TEST_LOCATION);
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, Rect<int>(16, 736, 64, 64), TEST_LOCATION);
 
   application.RenderWithPartialUpdate(damagedRects, clippingRect);
   DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
@@ -8208,9 +8208,9 @@ int utcDaliActorPartialUpdateActorsWithSizeHint(void)
   const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams());
 
   Actor actor = CreateRenderableActor();
-  actor.SetProperty(Actor::Property::POSITION, Vector3(75.0f, 150.0f, 0.0f));
-  actor.SetProperty(Actor::Property::SIZE, Vector3(75.0f, 150.0f, 0.0f));
-  actor.SetProperty(DevelActor::Property::UPDATE_SIZE_HINT, Vector3(150, 300, 0));
+  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.SetProperty(DevelActor::Property::UPDATE_SIZE_HINT, Vector3(64.0f, 64.0f, 0.0f));
   actor.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS);
   application.GetScene().Add(actor);
 
@@ -8220,7 +8220,7 @@ int utcDaliActorPartialUpdateActorsWithSizeHint(void)
 
   DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
 
-  Rect<int> clippingRect = Rect<int>(32, 560, 96, 176);
+  Rect<int> clippingRect = Rect<int>(32, 704, 80, 80);
   DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
 
   application.RenderWithPartialUpdate(damagedRects, clippingRect);
@@ -8233,6 +8233,119 @@ int utcDaliActorPartialUpdateActorsWithSizeHint(void)
   END_TEST;
 }
 
+int utcDaliActorPartialUpdateAnimation(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 area with partial update and animation");
+
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+  drawTrace.Reset();
+
+  Actor actor1 = CreateRenderableActor();
+  actor1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+  actor1.SetProperty(Actor::Property::SIZE, Vector3(80.0f, 80.0f, 0.0f));
+  application.GetScene().Add(actor1);
+
+  Actor actor2 = CreateRenderableActor();
+  actor2.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+  actor2.SetProperty(Actor::Property::SIZE, Vector3(16.0f, 16.0f, 0.0f));
+  application.GetScene().Add(actor2);
+
+  std::vector<Rect<int>> damagedRects;
+  Rect<int>              clippingRect;
+  Rect<int>              expectedRect1, expectedRect2;
+
+  application.SendNotification();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+
+  DALI_TEST_EQUALS(damagedRects.size(), 2, TEST_LOCATION);
+
+  // Aligned by 16
+  expectedRect1 = Rect<int>(0, 720, 96, 96); // in screen coordinates, includes 3 last frames updates
+  expectedRect2 = Rect<int>(0, 784, 32, 32); // in screen coordinates, includes 3 last frames updates
+  DALI_TEST_EQUALS<Rect<int>>(expectedRect1, damagedRects[0], TEST_LOCATION);
+  DALI_TEST_EQUALS<Rect<int>>(expectedRect2, damagedRects[1], TEST_LOCATION);
+
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  damagedRects.clear();
+  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));
+  animation.Play();
+
+  application.SendNotification();
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  drawTrace.Reset();
+  damagedRects.clear();
+
+  // In animation deley time
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // Skip rendering
+  DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 0, TEST_LOCATION);
+
+  drawTrace.Reset();
+  damagedRects.clear();
+
+  // Also in animation deley time
+  application.PreRenderWithPartialUpdate(100, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // Skip rendering
+  DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 0, TEST_LOCATION);
+
+  // Unparent 2 actors and make a new actor
+  actor1.Unparent();
+  actor2.Unparent();
+
+  Actor actor3 = CreateRenderableActor();
+  actor3.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+  actor3.SetProperty(Actor::Property::SIZE, Vector3(16.0f, 16.0f, 0.0f));
+  application.GetScene().Add(actor3);
+
+  application.SendNotification();
+
+  // Started animation
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(500, nullptr, damagedRects);
+  DALI_TEST_EQUALS(damagedRects.size(), 5, TEST_LOCATION);
+
+  // The first dirty rect is actor3's.
+  // We don't know the exact dirty rect of actor2
+  DALI_TEST_EQUALS<Rect<int>>(expectedRect2, damagedRects[0], TEST_LOCATION);
+  DALI_TEST_EQUALS<Rect<int>>(expectedRect1, damagedRects[1], TEST_LOCATION);
+
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // Finished animation, but the actior was already unparented
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(500, nullptr, damagedRects);
+
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+  DALI_TEST_EQUALS<Rect<int>>(expectedRect2, damagedRects[0], TEST_LOCATION);
+
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  END_TEST;
+}
+
 int UtcDaliActorCaptureAllTouchAfterStartPropertyP(void)
 {
   TestApplication application;
index 3f3d319..54c31af 100755 (executable)
@@ -575,6 +575,15 @@ void RenderManager::PreRender( Integration::Scene& scene, std::vector<Rect<int>>
     return;
   }
 
+  Internal::Scene& sceneInternal = GetImplementation(scene);
+  SceneGraph::Scene* sceneObject = sceneInternal.GetSceneObject();
+
+  if( sceneObject->IsRenderingSkipped() )
+  {
+    // We don't need to calculate dirty rects
+    return;
+  }
+
   class DamagedRectsCleaner
   {
   public:
@@ -607,11 +616,6 @@ void RenderManager::PreRender( Integration::Scene& scene, std::vector<Rect<int>>
   // Clean collected dirty/damaged rects on exit if 3d layer or 3d node or other conditions.
   DamagedRectsCleaner damagedRectCleaner(damagedRects);
 
-
-
-  Internal::Scene& sceneInternal = GetImplementation(scene);
-  SceneGraph::Scene* sceneObject = sceneInternal.GetSceneObject();
-
   // 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());
   std::vector<DirtyRect>& itemsDirtyRects = sceneInternal.GetItemsDirtyRects();
index 9b7ddcc..fa14393 100644 (file)
@@ -31,7 +31,8 @@ namespace SceneGraph
 Scene::Scene()
 : mContext( nullptr ),
   mFrameRenderedCallbacks(),
-  mFramePresentedCallbacks()
+  mFramePresentedCallbacks(),
+  mSkipRendering( false )
 {
 }
 
@@ -88,6 +89,16 @@ void Scene::GetFramePresentedCallback( Dali::Integration::Scene::FrameCallbackCo
   mFramePresentedCallbacks.clear();
 }
 
+void Scene::SetSkipRendering( bool skip )
+{
+  mSkipRendering = skip;
+}
+
+bool Scene::IsRenderingSkipped() const
+{
+  return mSkipRendering;
+}
+
 } //SceneGraph
 
 } //Internal
index 97af1d5..140d49a 100644 (file)
@@ -115,6 +115,18 @@ public:
    */
   void GetFramePresentedCallback( Dali::Integration::Scene::FrameCallbackContainer& callbacks );
 
+  /**
+   * @brief Sets whether rendering should be skipped or not.
+   * @param[in] skip true if rendering should be skipped.
+   */
+  void SetSkipRendering( bool skip );
+
+  /**
+   * @brief Query whether rendering should be skipped or not.
+   * @return true if rendering should be skipped, false otherwise.
+   */
+  bool IsRenderingSkipped() const;
+
 private:
 
   Context*                    mContext;   ///< The context holding the GL state of rendering for the scene, not owned
@@ -126,6 +138,8 @@ private:
 
   Dali::Integration::Scene::FrameCallbackContainer mFrameRenderedCallbacks;   ///< Frame rendered callbacks
   Dali::Integration::Scene::FrameCallbackContainer mFramePresentedCallbacks;  ///< Frame presented callbacks
+
+  bool                        mSkipRendering;  ///< A flag to skip rendering
 };
 
 /// Messages
index 7508c73..f512314 100644 (file)
@@ -222,7 +222,7 @@ inline void AddRendererToRenderList(BufferIndex updateBufferIndex,
       partialRenderingCacheInfo.matrix = item.mModelViewMatrix;
       partialRenderingCacheInfo.size = item.mSize;
 
-      if (item.mUpdateSize == Vector3::ZERO)
+      if (renderable.mNode->GetUpdateSizeHint() == Vector3::ZERO)
       {
         // RenderItem::CalculateViewportSpaceAABB cannot cope with z transform
         // I don't use item.mModelMatrix.GetTransformComponents() for z transform, would be to slow
@@ -231,6 +231,11 @@ inline void AddRendererToRenderList(BufferIndex updateBufferIndex,
           item.mUpdateSize = item.mSize;
         }
       }
+      else
+      {
+        item.mUpdateSize = renderable.mNode->GetUpdateSizeHint();
+      }
+
       partialRenderingCacheInfo.updatedSize = item.mUpdateSize;
 
       item.mIsUpdated = partialRenderingData.IsUpdated() || item.mIsUpdated;
index 3127eab..f60bbdf 100644 (file)
@@ -1016,6 +1016,11 @@ uint32_t UpdateManager::Update( float elapsedSeconds,
                                                 renderToFboEnabled,
                                                 isRenderingToFbo );
 
+            scene->scene->SetSkipRendering( false );
+          }
+          else
+          {
+            scene->scene->SetSkipRendering( true );
           }
 
           numberOfRenderInstructions += scene->scene->GetRenderInstructions().Count( bufferIndex );