[Tizen] Add Overlay Layer in scene 08/286908/3
authorseungho baek <sbsh.baek@samsung.com>
Mon, 9 Jan 2023 01:23:21 +0000 (10:23 +0900)
committerseungho baek <sbsh.baek@samsung.com>
Wed, 25 Jan 2023 04:57:41 +0000 (13:57 +0900)
Change-Id: I65447d7ace9e13f528f244234e139e3e9682291b
Signed-off-by: seungho baek <sbsh.baek@samsung.com>
13 files changed:
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-impl.cpp
dali/internal/event/render-tasks/render-task-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;
 }
+
+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 cce626d..26d72ac 100644 (file)
@@ -99,6 +99,11 @@ Layer Scene::GetRootLayer() const
   return GetImplementation(*this).GetRootLayer();
 }
 
+Layer Scene::GetOverlayLayer()
+{
+  return GetImplementation(*this).GetOverlayLayer();
+}
+
 uint32_t Scene::GetLayerCount() const
 {
   return GetImplementation(*this).GetLayerCount();
index bdaf814..4a851a2 100644 (file)
@@ -192,6 +192,14 @@ public:
   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).
index ea5c689..56ed507 100644 (file)
@@ -85,6 +85,11 @@ Scene::~Scene()
     mRootLayer.Reset();
   }
 
+  if(mOverlayLayer)
+  {
+    mOverlayLayer.Reset();
+  }
+
   if(mRenderTaskList)
   {
     mRenderTaskList.Reset();
@@ -174,6 +179,26 @@ Dali::Layer Scene::GetRootLayer() const
   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;
@@ -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 overlay render-task viewport parameters
+  RenderTaskPtr overlayRenderTask = mRenderTaskList->GetOverlayTask();
+  if(overlayRenderTask)
+  {
+    overlayRenderTask->SetViewport(newSize);
+  }
 }
 
 bool Scene::IsSurfaceRectChanged() const
index 52ea356..cda29a2 100644 (file)
@@ -105,6 +105,11 @@ public:
   Dali::Layer GetRootLayer() const;
 
   /**
+   * @copydoc Dali::Integration::Scene::GetOverlayLayer
+   */
+  Dali::Layer GetOverlayLayer();
+
+  /**
    * @copydoc Dali::Integration::Scene::GetLayerCount
    */
   uint32_t GetLayerCount() const;
@@ -380,6 +385,8 @@ private:
 
   LayerPtr mRootLayer;
 
+  LayerPtr mOverlayLayer;
+
   // Ordered list of currently on-stage layers
   OwnerPointer<LayerList> mLayerList;
 
index 8069b54..a74bba0 100644 (file)
@@ -67,7 +67,7 @@ SignalConnectorType signalConnector1(mType, SIGNAL_FINISHED, &RenderTask::DoConn
 
 } // Unnamed namespace
 
-RenderTaskPtr RenderTask::New(Actor* sourceActor, CameraActor* cameraActor, RenderTaskList& renderTaskList)
+RenderTaskPtr RenderTask::New(Actor* sourceActor, CameraActor* cameraActor, RenderTaskList& renderTaskList, bool isOverlayTask)
 {
   // create scene object first so it's guaranteed to exist for the event side
   auto sceneObject = SceneGraph::RenderTask::New();
@@ -78,7 +78,14 @@ RenderTaskPtr RenderTask::New(Actor* sourceActor, CameraActor* cameraActor, Rend
   // transfer scene object ownership to update manager
   const SceneGraph::RenderTaskList&    parentSceneObject = renderTaskList.GetSceneObject();
   OwnerPointer<SceneGraph::RenderTask> transferOwnership(sceneObject);
-  AddTaskMessage(task->GetEventThreadServices(), parentSceneObject, transferOwnership);
+  if(isOverlayTask)
+  {
+    AddOverlayTaskMessage(task->GetEventThreadServices(), parentSceneObject, transferOwnership);
+  }
+  else
+  {
+    AddTaskMessage(task->GetEventThreadServices(), parentSceneObject, transferOwnership);
+  }
 
   // Set the default source & camera actors
   task->SetSourceActor(sourceActor);
index 828156f..c859227 100644 (file)
@@ -57,9 +57,10 @@ public:
    * @param[in] sourceActor The source actor.
    * @param[in] cameraActor The camera actor.
    * @param[in] renderTaskList The render task list.
+   * @param[in] isOverlayTask True if this render task is overlay task. default is false.
    * @return The created render task
    */
-  static RenderTaskPtr New(Actor* sourceActor, CameraActor* cameraActor, RenderTaskList& renderTaskList);
+  static RenderTaskPtr New(Actor* sourceActor, CameraActor* cameraActor, RenderTaskList& renderTaskList, bool isOverlayTask = false);
 
   /**
    * @copydoc Dali::RenderTask::SetSourceActor()
index 39a98ba..6f512d2 100644 (file)
@@ -42,6 +42,7 @@ namespace Dali
 {
 namespace Internal
 {
+
 RenderTaskListPtr RenderTaskList::New()
 {
   RenderTaskListPtr taskList = new RenderTaskList();
@@ -59,12 +60,28 @@ RenderTaskPtr RenderTaskList::CreateTask()
 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;
 }
 
+RenderTaskPtr RenderTaskList::CreateOverlayTask(Actor* sourceActor, CameraActor* cameraActor)
+{
+  if(!mOverlayRenderTask)
+  {
+    mOverlayRenderTask = RenderTask::New(sourceActor, cameraActor, *this, true);
+    mTasks.push_back(mOverlayRenderTask);
+  }
+  return mOverlayRenderTask;
+}
+
 void RenderTaskList::RemoveTask(Internal::RenderTask& task)
 {
   for(RenderTaskContainer::iterator iter = mTasks.begin(); mTasks.end() != iter; ++iter)
@@ -80,13 +97,11 @@ void RenderTaskList::RemoveTask(Internal::RenderTask& task)
       // 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
     }
@@ -105,6 +120,16 @@ RenderTaskPtr RenderTaskList::GetTask(uint32_t index) const
   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?
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.
+
+    bool operator==(const Exclusive& other) const
+    {
+      return renderTaskPtr == other.renderTaskPtr;
+    }
   };
 
   using ExclusivesContainer = std::vector<Exclusive>;
+  using ExclusiveIter       = ExclusivesContainer::iterator;
 
   /**
    * Create a RenderTaskList.
@@ -86,6 +92,16 @@ public:
   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);
@@ -101,6 +117,11 @@ public:
   RenderTaskPtr GetTask(uint32_t index) const;
 
   /**
+   * @copydoc Dali::RenderTaskList::GetOverlayTask()
+   */
+  RenderTaskPtr GetOverlayTask() const;
+
+  /**
    * 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.
+  RenderTaskPtr       mOverlayRenderTask{nullptr};
 };
 
 } // namespace Internal
index 8139c2b..d074c4c 100644 (file)
@@ -41,7 +41,8 @@ RenderTaskList* RenderTaskList::New()
 
 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);
-  // 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)
index c985491..a99e142 100644 (file)
@@ -73,6 +73,12 @@ public:
   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.
    */
@@ -124,6 +130,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
+  RenderTask*                    mOverlayRenderTask;       ///< OverlayRenderTask.
 };
 
 // Messages for RenderTaskList
@@ -140,6 +147,18 @@ inline void AddTaskMessage(EventThreadServices& eventThreadServices, const Rende
   new(slot) LocalType(&list, &RenderTaskList::AddTask, task);
 }
 
+inline void AddOverlayTaskMessage(EventThreadServices& eventThreadServices, const RenderTaskList& list, OwnerPointer<RenderTask>& task)
+{
+  // Message has ownership of the RenderTask while in transit from event -> update
+  using LocalType = MessageValue1<RenderTaskList, OwnerPointer<RenderTask> >;
+
+  // 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(&list, &RenderTaskList::AddOverlayTask, task);
+}
+
 inline void RemoveTaskMessage(EventThreadServices& eventThreadServices, const RenderTaskList& list, const RenderTask& constTask)
 {
   // Scene graph thread can destroy this object.
index eabd958..941c6e7 100644 (file)
@@ -63,6 +63,11 @@ RenderTask RenderTaskList::GetTask(uint32_t index) const
   return RenderTask(GetImplementation(*this).GetTask(index).Get());
 }
 
+RenderTask RenderTaskList::GetOverlayTask() const
+{
+  return RenderTask(GetImplementation(*this).GetOverlayTask().Get());
+}
+
 RenderTaskList::RenderTaskList(Internal::RenderTaskList* internal)
 : BaseHandle(internal)
 {
index ad33f96..0de427c 100644 (file)
@@ -144,6 +144,14 @@ public:
    */
   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
   /**