Add Overlay Layer in scene 75/286475/11
authorseungho baek <sbsh.baek@samsung.com>
Mon, 9 Jan 2023 01:23:21 +0000 (10:23 +0900)
committerseungho baek <sbsh.baek@samsung.com>
Mon, 16 Jan 2023 08:10:55 +0000 (17:10 +0900)
Change-Id: I65447d7ace9e13f528f244234e139e3e9682291b
Signed-off-by: seungho baek <sbsh.baek@samsung.com>
automated-tests/src/dali/utc-Dali-Scene.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/event/render-tasks/render-task-list-impl.cpp
dali/internal/event/render-tasks/render-task-list-impl.h
dali/internal/update/render-tasks/scene-graph-render-task-list.cpp
dali/internal/update/render-tasks/scene-graph-render-task-list.h
dali/public-api/render-tasks/render-task-list.cpp
dali/public-api/render-tasks/render-task-list.h

index 0dd5e19..959e5ee 100644 (file)
@@ -2592,3 +2592,86 @@ int UtcDaliSceneSignalInterceptKeyEventN(void)
 
   END_TEST;
 }
 
   END_TEST;
 }
+
+int UtcDaliSceneGetOverlayLayer(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::Integration::Scene::GetOverlayLayer");
+
+  Dali::Integration::Scene scene = application.GetScene();
+
+  // Check we get a valid instance.
+  RenderTaskList tasks = scene.GetRenderTaskList();
+
+  // There should be 1 task by default.
+  DALI_TEST_EQUALS(tasks.GetTaskCount(), 1u, TEST_LOCATION);
+  RenderTask defaultTask = tasks.GetTask(0u);
+  DALI_TEST_EQUALS(scene.GetRootLayer(), defaultTask.GetSourceActor(), TEST_LOCATION);
+
+  Layer layer = scene.GetOverlayLayer();
+  // There should be 2 task by default.
+  DALI_TEST_EQUALS(tasks.GetTaskCount(), 2u, TEST_LOCATION);
+  RenderTask overlayTask = tasks.GetTask(1u);
+  DALI_TEST_EQUALS(overlayTask, tasks.GetOverlayTask(), TEST_LOCATION);
+  DALI_TEST_CHECK(scene.GetRootLayer() != overlayTask.GetSourceActor());
+  DALI_TEST_CHECK(overlayTask != defaultTask);
+  DALI_TEST_EQUALS(overlayTask.GetClearEnabled(), false, TEST_LOCATION);
+  DALI_TEST_EQUALS(overlayTask.IsExclusive(), true, TEST_LOCATION);
+
+  // If new render task is created, the last task is overlayTask
+  RenderTask newTask = scene.GetRenderTaskList().CreateTask();
+  DALI_TEST_EQUALS(tasks.GetTaskCount(), 3u, TEST_LOCATION);
+  DALI_TEST_EQUALS(newTask, tasks.GetTask(1u), TEST_LOCATION);
+  DALI_TEST_EQUALS(overlayTask, tasks.GetTask(2u), TEST_LOCATION);
+
+  // Render
+  application.SendNotification();
+  application.Render();
+
+  tasks.RemoveTask(overlayTask);
+  DALI_TEST_EQUALS(tasks.GetTaskCount(), 2u, TEST_LOCATION);
+  DALI_TEST_EQUALS(tasks.GetTask(0u), defaultTask, TEST_LOCATION);
+  DALI_TEST_EQUALS(tasks.GetTask(1u), newTask, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliSceneSurfaceResizedWithOverlayLayer(void)
+{
+  tet_infoline("Ensure resizing of the surface is handled properly");
+
+  TestApplication application;
+
+  auto scene = application.GetScene();
+  DALI_TEST_CHECK(scene);
+
+  const RenderTaskList& tasks = scene.GetRenderTaskList();
+  DALI_TEST_EQUALS(tasks.GetTaskCount(), 1u, TEST_LOCATION);
+  RenderTask defaultTask = tasks.GetTask(0u);
+  DALI_TEST_EQUALS(scene.GetRootLayer(), defaultTask.GetSourceActor(), TEST_LOCATION);
+
+  // Ensure stage size matches the scene size
+  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();
+  DALI_TEST_EQUALS(defaultViewport, sceneViewport, TEST_LOCATION);
+
+  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 = defaultTask.GetViewport();
+  DALI_TEST_EQUALS(defaultViewport, overlayViewport, TEST_LOCATION);
+
+  // Resize the scene
+  Vector2 newSize(1000.0f, 2000.0f);
+  DALI_TEST_CHECK(stage.GetSize() != newSize);
+  scene.SurfaceResized(newSize.width, newSize.height);
+  Viewport newViewport(0, 0, newSize.x, newSize.y);
+  DALI_TEST_EQUALS(newViewport, defaultTask.GetViewport(), TEST_LOCATION);
+  DALI_TEST_EQUALS(newViewport, defaultTask.GetViewport(), TEST_LOCATION);
+
+  END_TEST;
+}
index 20f85f2..5eedf5c 100644 (file)
@@ -103,6 +103,11 @@ Layer Scene::GetRootLayer() const
   return GetImplementation(*this).GetRootLayer();
 }
 
   return GetImplementation(*this).GetRootLayer();
 }
 
+Layer Scene::GetOverlayLayer()
+{
+  return GetImplementation(*this).GetOverlayLayer();
+}
+
 uint32_t Scene::GetLayerCount() const
 {
   return GetImplementation(*this).GetLayerCount();
 uint32_t Scene::GetLayerCount() const
 {
   return GetImplementation(*this).GetLayerCount();
index aac126f..51a8572 100644 (file)
@@ -207,6 +207,14 @@ public:
   Layer GetRootLayer() const;
 
   /**
   Layer GetRootLayer() const;
 
   /**
+   * @brief Returns the Scene's Overlay Layer.
+   * If there is no overlay layer yet, this creates the layer and an associated render task.
+   *
+   * @return The overlay layer
+   */
+  Layer GetOverlayLayer();
+
+  /**
    * @brief Queries the number of on-stage layers.
    *
    * Note that a default layer is always provided (count >= 1).
    * @brief Queries the number of on-stage layers.
    *
    * Note that a default layer is always provided (count >= 1).
index ea5c689..56ed507 100644 (file)
@@ -85,6 +85,11 @@ Scene::~Scene()
     mRootLayer.Reset();
   }
 
     mRootLayer.Reset();
   }
 
+  if(mOverlayLayer)
+  {
+    mOverlayLayer.Reset();
+  }
+
   if(mRenderTaskList)
   {
     mRenderTaskList.Reset();
   if(mRenderTaskList)
   {
     mRenderTaskList.Reset();
@@ -174,6 +179,26 @@ Dali::Layer Scene::GetRootLayer() const
   return Dali::Layer(mRootLayer.Get());
 }
 
   return Dali::Layer(mRootLayer.Get());
 }
 
+Dali::Layer Scene::GetOverlayLayer()
+{
+  if(!mOverlayLayer)
+  {
+    // Creates overlay layer.
+    mOverlayLayer = Layer::New();
+    mOverlayLayer->SetName("OverlayLayer");
+    mOverlayLayer->SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+    mOverlayLayer->SetParentOrigin(Dali::ParentOrigin::TOP_LEFT);
+    mOverlayLayer->SetAnchorPoint(Dali::AnchorPoint::TOP_LEFT);
+    mRootLayer->Add(*mOverlayLayer);
+
+    // Create the overlay render-task and set exclusive to true.
+    RenderTaskPtr renderTask = mRenderTaskList->CreateOverlayTask(mOverlayLayer.Get(), mDefaultCamera.Get());
+    renderTask->SetExclusive(true);
+    renderTask->SetInputEnabled(true);
+  }
+  return Dali::Layer(mOverlayLayer.Get());
+}
+
 LayerList& Scene::GetLayerList() const
 {
   return *mLayerList;
 LayerList& Scene::GetLayerList() const
 {
   return *mLayerList;
@@ -337,6 +362,12 @@ void Scene::ChangedSurface(float width, float height, int32_t windowOrientation,
   // set default render-task viewport parameters
   RenderTaskPtr defaultRenderTask = mRenderTaskList->GetTask(0u);
   defaultRenderTask->SetViewport(newSize);
   // set default render-task viewport parameters
   RenderTaskPtr defaultRenderTask = mRenderTaskList->GetTask(0u);
   defaultRenderTask->SetViewport(newSize);
+  // set overlay render-task viewport parameters
+  RenderTaskPtr overlayRenderTask = mRenderTaskList->GetOverlayTask();
+  if(overlayRenderTask)
+  {
+    overlayRenderTask->SetViewport(newSize);
+  }
 }
 
 bool Scene::IsSurfaceRectChanged() const
 }
 
 bool Scene::IsSurfaceRectChanged() const
index 52ea356..cda29a2 100644 (file)
@@ -105,6 +105,11 @@ public:
   Dali::Layer GetRootLayer() const;
 
   /**
   Dali::Layer GetRootLayer() const;
 
   /**
+   * @copydoc Dali::Integration::Scene::GetOverlayLayer
+   */
+  Dali::Layer GetOverlayLayer();
+
+  /**
    * @copydoc Dali::Integration::Scene::GetLayerCount
    */
   uint32_t GetLayerCount() const;
    * @copydoc Dali::Integration::Scene::GetLayerCount
    */
   uint32_t GetLayerCount() const;
@@ -380,6 +385,8 @@ private:
 
   LayerPtr mRootLayer;
 
 
   LayerPtr mRootLayer;
 
+  LayerPtr mOverlayLayer;
+
   // Ordered list of currently on-stage layers
   OwnerPointer<LayerList> mLayerList;
 
   // Ordered list of currently on-stage layers
   OwnerPointer<LayerList> mLayerList;
 
index 39a98ba..42722b8 100644 (file)
@@ -42,6 +42,7 @@ namespace Dali
 {
 namespace Internal
 {
 {
 namespace Internal
 {
+
 RenderTaskListPtr RenderTaskList::New()
 {
   RenderTaskListPtr taskList = new RenderTaskList();
 RenderTaskListPtr RenderTaskList::New()
 {
   RenderTaskListPtr taskList = new RenderTaskList();
@@ -59,12 +60,27 @@ RenderTaskPtr RenderTaskList::CreateTask()
 RenderTaskPtr RenderTaskList::CreateTask(Actor* sourceActor, CameraActor* cameraActor)
 {
   RenderTaskPtr task = RenderTask::New(sourceActor, cameraActor, *this);
 RenderTaskPtr RenderTaskList::CreateTask(Actor* sourceActor, CameraActor* cameraActor)
 {
   RenderTaskPtr task = RenderTask::New(sourceActor, cameraActor, *this);
-
-  mTasks.push_back(task);
+  if(mOverlayRenderTask && mTasks.back() == mOverlayRenderTask)
+  {
+    mTasks.insert(mTasks.end() - 1, task);
+  }
+  else
+  {
+    mTasks.push_back(task);
+  }
 
   return task;
 }
 
 
   return task;
 }
 
+RenderTaskPtr RenderTaskList::CreateOverlayTask(Actor* sourceActor, CameraActor* cameraActor)
+{
+  if(!mOverlayRenderTask)
+  {
+    mOverlayRenderTask = CreateTask(sourceActor, &mDefaults.GetDefaultCameraActor());
+  }
+  return mOverlayRenderTask;
+}
+
 void RenderTaskList::RemoveTask(Internal::RenderTask& task)
 {
   for(RenderTaskContainer::iterator iter = mTasks.begin(); mTasks.end() != iter; ++iter)
 void RenderTaskList::RemoveTask(Internal::RenderTask& task)
 {
   for(RenderTaskContainer::iterator iter = mTasks.begin(); mTasks.end() != iter; ++iter)
@@ -80,13 +96,11 @@ void RenderTaskList::RemoveTask(Internal::RenderTask& task)
       // send a message to remove the scene-graph RenderTask
       RemoveTaskMessage(mEventThreadServices, *mSceneObject, sceneObject);
 
       // send a message to remove the scene-graph RenderTask
       RemoveTaskMessage(mEventThreadServices, *mSceneObject, sceneObject);
 
-      for(auto exclusiveIt = mExclusives.begin(); exclusiveIt != mExclusives.end(); ++exclusiveIt)
+      Exclusive exclusive{ptr, ActorObserver()};
+      ExclusivesContainer::iterator exclusiveIter = find(mExclusives.begin(), mExclusives.end(), exclusive);
+      if(exclusiveIter != mExclusives.end())
       {
       {
-        if(exclusiveIt->renderTaskPtr == ptr)
-        {
-          mExclusives.erase(exclusiveIt);
-          break;
-        }
+        mExclusives.erase(exclusiveIter);
       }
       break; // we're finished
     }
       }
       break; // we're finished
     }
@@ -105,6 +119,16 @@ RenderTaskPtr RenderTaskList::GetTask(uint32_t index) const
   return mTasks[index];
 }
 
   return mTasks[index];
 }
 
+RenderTaskPtr RenderTaskList::GetOverlayTask() const
+{
+  RenderTaskPtr overlayRenderTask;
+  if(mOverlayRenderTask)
+  {
+    overlayRenderTask = mOverlayRenderTask;
+  }
+  return overlayRenderTask;
+}
+
 void RenderTaskList::SetExclusive(RenderTask* task, bool exclusive)
 {
   // Check to see if this rendertask has an entry?
 void RenderTaskList::SetExclusive(RenderTask* task, bool exclusive)
 {
   // Check to see if this rendertask has an entry?
index 6a8ed44..c01b981 100644 (file)
@@ -59,9 +59,15 @@ public:
   {
     RenderTask*   renderTaskPtr; ///< Pointer for comparison with current rendertask.
     ActorObserver actor;         ///< For comparison with current actor.
   {
     RenderTask*   renderTaskPtr; ///< Pointer for comparison with current rendertask.
     ActorObserver actor;         ///< For comparison with current actor.
+
+    bool operator==(const Exclusive& other) const
+    {
+      return renderTaskPtr == other.renderTaskPtr;
+    }
   };
 
   using ExclusivesContainer = std::vector<Exclusive>;
   };
 
   using ExclusivesContainer = std::vector<Exclusive>;
+  using ExclusiveIter       = ExclusivesContainer::iterator;
 
   /**
    * Create a RenderTaskList.
 
   /**
    * Create a RenderTaskList.
@@ -86,6 +92,16 @@ public:
   RenderTaskPtr CreateTask(Actor* sourceActor, CameraActor* cameraActor);
 
   /**
   RenderTaskPtr CreateTask(Actor* sourceActor, CameraActor* cameraActor);
 
   /**
+   * @brief Creates a new RenderTask for overlay.
+   * This will be appended to the end of render-task list.
+   * @param[in] sourceActor The actor and its children to be rendered for this render task.
+   * @param[in] cameraActor The actor from which the scene is viewed for this render task.
+   * @return A valid handle to a new overlay RenderTask
+   * @note The Overlay RenderTask will be rendered after all the other render tasks are rendered.
+   */
+  RenderTaskPtr CreateOverlayTask(Actor* sourceActor, CameraActor* cameraActor);
+
+  /**
    * @copydoc Dali::RenderTaskList::RemoveTask()
    */
   void RemoveTask(Internal::RenderTask& task);
    * @copydoc Dali::RenderTaskList::RemoveTask()
    */
   void RemoveTask(Internal::RenderTask& task);
@@ -101,6 +117,11 @@ public:
   RenderTaskPtr GetTask(uint32_t index) const;
 
   /**
   RenderTaskPtr GetTask(uint32_t index) const;
 
   /**
+   * @copydoc Dali::RenderTaskList::GetOverlayTask()
+   */
+  RenderTaskPtr GetOverlayTask() const;
+
+  /**
    * Retrieve the container of render-tasks.
    * @return The container.
    */
    * Retrieve the container of render-tasks.
    * @return The container.
    */
@@ -177,6 +198,7 @@ private:
 
   RenderTaskContainer mTasks;      ///< Reference counted render-tasks
   ExclusivesContainer mExclusives; ///< List of rendertasks with exclusively owned source actors.
 
   RenderTaskContainer mTasks;      ///< Reference counted render-tasks
   ExclusivesContainer mExclusives; ///< List of rendertasks with exclusively owned source actors.
+  RenderTaskPtr       mOverlayRenderTask{nullptr};
 };
 
 } // namespace Internal
 };
 
 } // namespace Internal
index 03c39fd..edbbe4a 100644 (file)
@@ -41,7 +41,8 @@ RenderTaskList* RenderTaskList::New()
 
 RenderTaskList::RenderTaskList()
 : mNotificationObject(nullptr),
 
 RenderTaskList::RenderTaskList()
 : mNotificationObject(nullptr),
-  mRenderMessageDispatcher(nullptr)
+  mRenderMessageDispatcher(nullptr),
+  mOverlayRenderTask(nullptr)
 {
 }
 
 {
 }
 
@@ -63,8 +64,21 @@ void RenderTaskList::AddTask(OwnerPointer<RenderTask>& newTask)
   DALI_ASSERT_DEBUG(mRenderMessageDispatcher != NULL && "RenderMessageDispatcher is null");
 
   newTask->Initialize(*mRenderMessageDispatcher);
   DALI_ASSERT_DEBUG(mRenderMessageDispatcher != NULL && "RenderMessageDispatcher is null");
 
   newTask->Initialize(*mRenderMessageDispatcher);
-  // mRenderTasks container takes ownership
-  mRenderTasks.PushBack(newTask.Release());
+
+  if(mOverlayRenderTask && mRenderTasks[mRenderTasks.Size() - 1] == mOverlayRenderTask)
+  {
+    mRenderTasks.Insert(mRenderTasks.End() - 1, newTask.Release());
+  }
+  else
+  {
+    mRenderTasks.PushBack(newTask.Release());
+  }
+}
+
+void RenderTaskList::AddOverlayTask(OwnerPointer<RenderTask>& newTask)
+{
+  AddTask(newTask);
+  mOverlayRenderTask = mRenderTasks[mRenderTasks.Size() - 1];
 }
 
 void RenderTaskList::RemoveTask(RenderTask* task)
 }
 
 void RenderTaskList::RemoveTask(RenderTask* task)
index 84058fc..2b7242d 100644 (file)
@@ -73,6 +73,12 @@ public:
   void AddTask(OwnerPointer<RenderTask>& newTask);
 
   /**
   void AddTask(OwnerPointer<RenderTask>& newTask);
 
   /**
+   * Add a overlay RenderTask to the list.
+   * @param[in] newTask The RenderTaskList takes ownership of this overlay task.
+   */
+  void AddOverlayTask(OwnerPointer<RenderTask>& newTask);
+
+  /**
    * Remove a RenderTask from the list.
    * @param[in] task The RenderTaskList will destroy this task.
    */
    * Remove a RenderTask from the list.
    * @param[in] task The RenderTaskList will destroy this task.
    */
@@ -129,6 +135,7 @@ private:
   CompleteNotificationInterface* mNotificationObject;      ///< object to pass in to the complete notification
   RenderMessageDispatcher*       mRenderMessageDispatcher; ///< for sending messages to render thread
   RenderTaskContainer            mRenderTasks;             ///< A container of owned RenderTasks
   CompleteNotificationInterface* mNotificationObject;      ///< object to pass in to the complete notification
   RenderMessageDispatcher*       mRenderMessageDispatcher; ///< for sending messages to render thread
   RenderTaskContainer            mRenderTasks;             ///< A container of owned RenderTasks
+  RenderTask*                    mOverlayRenderTask;       ///< OverlayRenderTask.
 };
 
 // Messages for RenderTaskList
 };
 
 // Messages for RenderTaskList
index eabd958..941c6e7 100644 (file)
@@ -63,6 +63,11 @@ RenderTask RenderTaskList::GetTask(uint32_t index) const
   return RenderTask(GetImplementation(*this).GetTask(index).Get());
 }
 
   return RenderTask(GetImplementation(*this).GetTask(index).Get());
 }
 
+RenderTask RenderTaskList::GetOverlayTask() const
+{
+  return RenderTask(GetImplementation(*this).GetOverlayTask().Get());
+}
+
 RenderTaskList::RenderTaskList(Internal::RenderTaskList* internal)
 : BaseHandle(internal)
 {
 RenderTaskList::RenderTaskList(Internal::RenderTaskList* internal)
 : BaseHandle(internal)
 {
index ad33f96..0de427c 100644 (file)
@@ -144,6 +144,14 @@ public:
    */
   RenderTask GetTask(uint32_t index) const;
 
    */
   RenderTask GetTask(uint32_t index) const;
 
+  /**
+   * @brief Retrieves a RenderTask for Overlay
+   * @SINCE_2_2.10
+   * @return A handle to the overlay RenderTask.
+   * If the scene has not created an overlay render task, this returns empty handle.
+   */
+  RenderTask GetOverlayTask() const;
+
 public: // Not intended for application developers
   /// @cond internal
   /**
 public: // Not intended for application developers
   /// @cond internal
   /**