(CanvasView) Support rasterization request manually 75/312975/3
authorEunki, Hong <eunkiki.hong@samsung.com>
Tue, 18 Jun 2024 03:58:10 +0000 (12:58 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Tue, 18 Jun 2024 05:58:55 +0000 (14:58 +0900)
Let we support to make user request rasterization manually.
If user mark it as true, we should call RequestRasterization manullay.

It will be reduce overhead when user add CanvasView very large amount.

Change-Id: Ib404b0b3fd0adb76cf9c5f85476be26eefa4def9
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
automated-tests/src/dali-toolkit/utc-Dali-CanvasView.cpp
dali-toolkit/devel-api/controls/canvas-view/canvas-view.cpp
dali-toolkit/devel-api/controls/canvas-view/canvas-view.h
dali-toolkit/internal/controls/canvas-view/canvas-view-impl.cpp
dali-toolkit/internal/controls/canvas-view/canvas-view-impl.h

index 6d29bf5..febdf97 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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,8 +30,8 @@
 #include <dali-toolkit/internal/controls/canvas-view/canvas-view-rasterize-task.h>
 #include <dali/devel-api/adaptor-framework/canvas-renderer/canvas-renderer-shape.h>
 #include <dali/devel-api/adaptor-framework/canvas-renderer/canvas-renderer.h>
-#include <dali/public-api/images/pixel-data.h>
 #include <dali/public-api/adaptor-framework/async-task-manager.h>
+#include <dali/public-api/images/pixel-data.h>
 
 using namespace Dali;
 using namespace Toolkit;
@@ -357,7 +357,7 @@ int UtcDaliCanvasViewRasterizeThreadRasterizationCompletedSignalP(void)
 
   gRasterizationCompletedSignal = false;
 
-  Dali::Toolkit::CanvasView            canvasView              = Dali::Toolkit::CanvasView::New(Vector2(100, 100));
+  Dali::Toolkit::CanvasView canvasView = Dali::Toolkit::CanvasView::New(Vector2(100, 100));
 
   Dali::CanvasRenderer dummyCanvasRenderer = Dali::CanvasRenderer::New(Vector2(100, 100));
   DALI_TEST_CHECK(dummyCanvasRenderer);
@@ -503,3 +503,85 @@ int UtcDaliCanvasViewSychronousLoading(void)
 
   END_TEST;
 }
+
+int UtcDaliCanvasViewRasterizationRequestManually(void)
+{
+  ToolkitTestApplication application;
+
+  CanvasView canvasView = CanvasView::New(Vector2(300, 300));
+  DALI_TEST_CHECK(canvasView);
+
+  application.GetScene().Add(canvasView);
+
+  canvasView.SetProperty(Actor::Property::SIZE, Vector2(300, 300));
+  canvasView.SetProperty(Toolkit::CanvasView::Property::SYNCHRONOUS_LOADING, false);
+
+  Dali::CanvasRenderer::Shape shape = Dali::CanvasRenderer::Shape::New();
+
+  shape.AddRect(Rect<float>(10, 10, 10, 10), Vector2(0, 0));
+
+  canvasView.AddDrawable(shape);
+
+  application.SendNotification();
+  application.Render();
+
+  // Rasterization occured
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+  bool isRasterizationManually = canvasView.GetProperty(Toolkit::CanvasView::Property::RASTERIZATION_REQUEST_MANUALLY).Get<bool>();
+  DALI_TEST_EQUALS(isRasterizationManually, false, TEST_LOCATION);
+
+  shape.AddRect(Rect<float>(10, 10, 10, 10), Vector2(0, 0));
+  application.SendNotification();
+  application.Render();
+
+  shape.AddRect(Rect<float>(10, 10, 10, 10), Vector2(0, 0));
+  application.SendNotification();
+  application.Render();
+
+  // Check if the canvasView is rasterized.
+  // Rasterization occured
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+  canvasView.SetProperty(Toolkit::CanvasView::Property::RASTERIZATION_REQUEST_MANUALLY, true);
+
+  application.SendNotification();
+  application.Render();
+
+  // Rasterization occured
+  // (Note that we cannot 'cancel' the latest rasterization request even if we set RASTERIZATION_REQUEST_MANUALLY to true)
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+  isRasterizationManually = canvasView.GetProperty(Toolkit::CanvasView::Property::RASTERIZATION_REQUEST_MANUALLY).Get<bool>();
+  DALI_TEST_EQUALS(isRasterizationManually, true, TEST_LOCATION);
+
+  shape.AddRect(Rect<float>(10, 10, 10, 10), Vector2(0, 0));
+  application.SendNotification();
+  application.Render();
+
+  // Check if the canvasView is not rasterized.
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1, 0), false, TEST_LOCATION);
+
+  Dali::CanvasRenderer::Shape shape2 = Dali::CanvasRenderer::Shape::New();
+
+  shape2.AddRect(Rect<float>(10, 10, 10, 10), Vector2(0, 0));
+
+  canvasView.AddDrawable(shape2);
+
+  application.SendNotification();
+  application.Render();
+
+  // Check whether the canvasView is not rasterized even if we add drawables.
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1, 0), false, TEST_LOCATION);
+
+  // Request rasterize manually
+  canvasView.RequestRasterization();
+
+  application.SendNotification();
+  application.Render();
+
+  // Check if the canvasView is rasterized.
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+  END_TEST;
+}
index a00cd35..db2c5da 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
@@ -83,6 +83,11 @@ void CanvasView::RemoveAllDrawables()
   Dali::Toolkit::GetImpl(*this).RemoveAllDrawables();
 }
 
+void CanvasView::RequestRasterization()
+{
+  Dali::Toolkit::GetImpl(*this).RequestRasterization();
+}
+
 CanvasView::CanvasView(Internal::CanvasView& implementation)
 : Control(implementation)
 {
index 026d3fa..db5c900 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_CANVAS_VIEW_H
 
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
@@ -87,10 +87,19 @@ public:
       /**
        * @brief Whether to load the canvas synchronously.
        * @details Name "synchronousLoading", type Property::BOOLEAN.
+       * @note Default is true.
        */
       SYNCHRONOUS_LOADING,
+
+      /**
+       * @brief Whether to request rasterize canvas manually or automatically
+       * @details Name "rasterizationRequestManually", type Property::BOOLEAN.
+       * @note Default is false.
+       */
+      RASTERIZATION_REQUEST_MANUALLY,
     };
   };
+
 public:
   /**
    * @brief Creates an uninitialized CanvasView.
@@ -180,6 +189,11 @@ public:
    */
   void RemoveAllDrawables();
 
+  /**
+   * @brief Request to rasterize the CanvasView.
+   */
+  void RequestRasterization();
+
 public: // Not intended for application developers
   /// @cond internal
   /**
index 282ebb4..1b3cae7 100644 (file)
@@ -47,6 +47,7 @@ BaseHandle Create()
 DALI_TYPE_REGISTRATION_BEGIN(Toolkit::CanvasView, Toolkit::Control, Create);
 DALI_PROPERTY_REGISTRATION(Toolkit, CanvasView, "viewBox", VECTOR2, VIEW_BOX)
 DALI_PROPERTY_REGISTRATION(Toolkit, CanvasView, "synchronousLoading", BOOLEAN, SYNCHRONOUS_LOADING)
+DALI_PROPERTY_REGISTRATION(Toolkit, CanvasView, "rasterizationRequestManually", BOOLEAN, RASTERIZATION_REQUEST_MANUALLY)
 DALI_TYPE_REGISTRATION_END()
 } // anonymous namespace
 
@@ -58,17 +59,22 @@ CanvasView::CanvasView(const Vector2& viewBox)
   mTexture(),
   mTextureSet(),
   mSize(viewBox),
-  mIsSynchronous(true)
+  mIsSynchronous(true),
+  mManualRasterization(false),
+  mProcessorRegistered(false)
 {
 }
 
 CanvasView::~CanvasView()
 {
-  if(Adaptor::IsAvailable())
+  if(Adaptor::IsAvailable() && mProcessorRegistered)
   {
-    Dali::AsyncTaskManager::Get().RemoveTask(mRasterizingTask);
-    mRasterizingTask.Reset();
-    Adaptor::Get().UnregisterProcessor(*this, true);
+    if(mRasterizingTask)
+    {
+      Dali::AsyncTaskManager::Get().RemoveTask(mRasterizingTask);
+      mRasterizingTask.Reset();
+    }
+    Adaptor::Get().UnregisterProcessorOnce(*this, true);
   }
 }
 
@@ -94,7 +100,8 @@ void CanvasView::OnInitialize()
 
   Self().SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::IMAGE);
 
-  Adaptor::Get().RegisterProcessor(*this, true);
+  // Request rasterization once at very first time.
+  RequestRasterization();
 }
 
 void CanvasView::OnRelayout(const Vector2& size, RelayoutContainer& container)
@@ -147,6 +154,15 @@ void CanvasView::SetProperty(BaseObject* object, Property::Index propertyIndex,
         }
         break;
       }
+      case Toolkit::CanvasView::Property::RASTERIZATION_REQUEST_MANUALLY:
+      {
+        bool isRasterizationManually;
+        if(value.Get(isRasterizationManually))
+        {
+          canvasViewImpl.SetRasterizationRequestManually(isRasterizationManually);
+        }
+        break;
+      }
     }
   }
 }
@@ -173,6 +189,11 @@ Property::Value CanvasView::GetProperty(BaseObject* object, Property::Index prop
         value = canvasViewImpl.IsSynchronous();
         break;
       }
+      case Toolkit::CanvasView::Property::RASTERIZATION_REQUEST_MANUALLY:
+      {
+        value = canvasViewImpl.IsRasterizationRequestManually();
+        break;
+      }
     }
   }
   return value;
@@ -180,27 +201,39 @@ Property::Value CanvasView::GetProperty(BaseObject* object, Property::Index prop
 
 void CanvasView::Process(bool postProcessor)
 {
+  mProcessorRegistered = false;
+
   if(mCanvasRenderer && mCanvasRenderer.IsCanvasChanged() && mSize.width > 0 && mSize.height > 0)
   {
     AddRasterizationTask();
   }
+
+  // If we are not doing manual rasterization, register processor once again.
+  // TODO : Could we reqest it only if IsCanvasChagned() is true?
+  if(!mManualRasterization)
+  {
+    RequestRasterization();
+  }
 }
 
 void CanvasView::AddRasterizationTask()
 {
-  mRasterizingTask = new CanvasRendererRasterizingTask(mCanvasRenderer, MakeCallback(this, &CanvasView::ApplyRasterizedImage));
-
-  if(mCanvasRenderer.Commit())
+  if(mCanvasRenderer && mCanvasRenderer.Commit())
   {
     if(mIsSynchronous)
     {
-      mRasterizingTask->Process();
-      ApplyRasterizedImage(mRasterizingTask);
-      mRasterizingTask.Reset(); // We don't need it anymore.
+      CanvasRendererRasterizingTaskPtr rasterizingTask = new CanvasRendererRasterizingTask(mCanvasRenderer, MakeCallback(this, &CanvasView::ApplyRasterizedImage));
+      rasterizingTask->Process();
+      ApplyRasterizedImage(rasterizingTask);
+      rasterizingTask.Reset(); // We don't need it anymore.
     }
     else
     {
-      AsyncTaskManager::Get().AddTask(mRasterizingTask);
+      if(!mRasterizingTask)
+      {
+        mRasterizingTask = new CanvasRendererRasterizingTask(mCanvasRenderer, MakeCallback(this, &CanvasView::ApplyRasterizedImage));
+        AsyncTaskManager::Get().AddTask(mRasterizingTask);
+      }
     }
   }
 }
@@ -230,10 +263,13 @@ void CanvasView::ApplyRasterizedImage(CanvasRendererRasterizingTaskPtr task)
     }
   }
 
-  mRasterizingTask.Reset(); // We don't need it anymore
+  if(task == mRasterizingTask)
+  {
+    mRasterizingTask.Reset(); // We don't need it anymore
+  }
 
   //If there are accumulated changes to CanvasRenderer during Rasterize, Rasterize once again.
-  if(!mIsSynchronous && mCanvasRenderer && mCanvasRenderer.IsCanvasChanged())
+  if(!mIsSynchronous && !mManualRasterization && mCanvasRenderer && mCanvasRenderer.IsCanvasChanged())
   {
     AddRasterizationTask();
   }
@@ -266,6 +302,15 @@ bool CanvasView::RemoveAllDrawables()
   return false;
 }
 
+void CanvasView::RequestRasterization()
+{
+  if(!mProcessorRegistered && Adaptor::IsAvailable())
+  {
+    mProcessorRegistered = true;
+    Adaptor::Get().RegisterProcessorOnce(*this, true);
+  }
+}
+
 bool CanvasView::SetViewBox(const Vector2& viewBox)
 {
   if(mCanvasRenderer && mCanvasRenderer.SetViewBox(viewBox))
@@ -289,11 +334,28 @@ void CanvasView::SetSynchronous(const bool isSynchronous)
   mIsSynchronous = isSynchronous;
 }
 
-const bool CanvasView::IsSynchronous()
+const bool CanvasView::IsSynchronous() const
 {
   return mIsSynchronous;
 }
 
+void CanvasView::SetRasterizationRequestManually(const bool isRasterizationManually)
+{
+  if(mManualRasterization != isRasterizationManually)
+  {
+    mManualRasterization = isRasterizationManually;
+    if(!mManualRasterization)
+    {
+      RequestRasterization();
+    }
+  }
+}
+
+const bool CanvasView::IsRasterizationRequestManually() const
+{
+  return mManualRasterization;
+}
+
 } // namespace Internal
 } // namespace Toolkit
 } // namespace Dali
index 6f0fa11..82f7ff3 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_INTERNAL_CANVAS_VIEW_H
 
 /*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
@@ -90,6 +90,11 @@ public:
    */
   bool RemoveAllDrawables();
 
+  /**
+   * @copydoc Toolkit::Control::CanvasView::RequestRasterization
+   */
+  void RequestRasterization();
+
 private: // From Control
   /**
    * @copydoc Control::OnRelayout
@@ -131,7 +136,21 @@ private: // From Control
    *
    * @return Returns true if synchronously.
    */
-  const bool IsSynchronous();
+  const bool IsSynchronous() const;
+
+  /**
+   * @brief Set to request rasterize canvas manually or automatically
+   *
+   * @param isRasterizationManually True if rasterize canvas manually.
+   */
+  void SetRasterizationRequestManually(const bool isRasterizationManually);
+
+  /**
+   * @brief Whether to request rasterize canvas manually or automatically
+   *
+   * @return Returns true if rasterize canvas manually.
+   */
+  const bool IsRasterizationRequestManually() const;
 
   /**
    * @bried Rasterize the canvas, and add it to the view.
@@ -172,7 +191,9 @@ private:
   TextureSet                       mTextureSet;
   Vector2                          mSize;
   CanvasRendererRasterizingTaskPtr mRasterizingTask;
-  bool                             mIsSynchronous;
+  bool                             mIsSynchronous : 1;
+  bool                             mManualRasterization : 1;
+  bool                             mProcessorRegistered : 1;
 };
 
 } // namespace Internal