Add ViewportGuideActor to RenderTask 97/279397/10
authorseungho <sbsh.baek@samsung.com>
Mon, 8 Aug 2022 14:13:14 +0000 (23:13 +0900)
committerseungho <sbsh.baek@samsung.com>
Wed, 17 Aug 2022 08:46:08 +0000 (17:46 +0900)
Change-Id: Ie33b8b1c9587649e6f173c664cc781d76d281b1a
Signed-off-by: seungho <sbsh.baek@samsung.com>
automated-tests/src/dali/utc-Dali-RenderTask.cpp
dali/internal/event/render-tasks/render-task-impl.cpp
dali/internal/event/render-tasks/render-task-impl.h
dali/internal/update/manager/render-task-processor.cpp
dali/internal/update/render-tasks/scene-graph-render-task.cpp
dali/internal/update/render-tasks/scene-graph-render-task.h
dali/public-api/render-tasks/render-task.cpp
dali/public-api/render-tasks/render-task.h

index 9b5e9de..53ba954 100644 (file)
@@ -3524,4 +3524,86 @@ int UtcDaliRenderTaskUploadOnly(void)
 
   DALI_TEST_CHECK(!finished);
   END_TEST;
+}
+
+int UtcDaliRenderTaskSetGetViewportGuideActor(void)
+{
+  TestApplication application;
+  tet_infoline("Testing RenderTask with Set/Get ViewportGuideActor");
+
+  Stage   stage = Stage::GetCurrent();
+  Vector2 stageSize(stage.GetSize());
+
+  Actor blue                                 = Actor::New();
+  blue[Dali::Actor::Property::NAME]          = "Blue";
+  blue[Dali::Actor::Property::ANCHOR_POINT]  = AnchorPoint::CENTER;
+  blue[Dali::Actor::Property::PARENT_ORIGIN] = ParentOrigin::CENTER;
+  blue[Dali::Actor::Property::SIZE]          = Vector2(300, 300);
+  blue[Dali::Actor::Property::POSITION]      = Vector2(0, 0);
+
+  stage.Add(blue);
+
+  RenderTaskList renderTaskList = stage.GetRenderTaskList();
+  RenderTask     renderTask     = renderTaskList.CreateTask();
+
+  renderTask.SetViewportGuideActor(blue);
+
+  Actor actor = renderTask.GetViewportGuideActor();
+  DALI_TEST_EQUALS(actor, blue, TEST_LOCATION);
+
+  renderTask.ResetViewportGuideActor();
+  actor = renderTask.GetViewportGuideActor();
+
+  DALI_TEST_CHECK(!actor);
+
+  END_TEST;
+}
+
+int UtcDaliRenderTaskViewportGuideActor(void)
+{
+  TestApplication application;
+  tet_infoline("Testing RenderTask with ViewportGuideActor");
+
+  Stage   stage = Stage::GetCurrent();
+  Vector2 stageSize(stage.GetSize());
+
+  Actor blue                                 = Actor::New();
+  blue[Dali::Actor::Property::NAME]          = "Blue";
+  blue[Dali::Actor::Property::ANCHOR_POINT]  = AnchorPoint::CENTER;
+  blue[Dali::Actor::Property::PARENT_ORIGIN] = ParentOrigin::CENTER;
+  blue[Dali::Actor::Property::SIZE]          = Vector2(300, 300);
+  blue[Dali::Actor::Property::POSITION]      = Vector2(0, 0);
+
+  Geometry geometry = Geometry::New();
+  Shader   shader   = Shader::New("vertexSrc", "fragmentSrc");
+  Renderer renderer = Renderer::New(geometry, shader);
+  blue.AddRenderer(renderer);
+
+  stage.Add(blue);
+
+  RenderTaskList renderTaskList = stage.GetRenderTaskList();
+  RenderTask     renderTask     = renderTaskList.CreateTask();
+
+  Dali::CameraActor cameraActor                     = Dali::CameraActor::New(stageSize);
+  cameraActor[Dali::Actor::Property::ANCHOR_POINT]  = AnchorPoint::CENTER;
+  cameraActor[Dali::Actor::Property::PARENT_ORIGIN] = ParentOrigin::CENTER;
+  stage.Add(cameraActor);
+
+  renderTask.SetExclusive(true);
+  renderTask.SetInputEnabled(true);
+  renderTask.SetCameraActor(cameraActor);
+  renderTask.SetSourceActor(blue);
+  renderTask.SetViewportGuideActor(blue);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render(16);
+
+  Vector2 viewportPosition = renderTask.GetCurrentViewportPosition();
+  Vector2 viewportSize     = renderTask.GetCurrentViewportSize();
+
+  DALI_TEST_EQUALS(viewportSize, Vector2(300, 300), TEST_LOCATION);
+  DALI_TEST_EQUALS(viewportPosition, Vector2(90, 250), TEST_LOCATION);
+
+  END_TEST;
 }
\ No newline at end of file
index 5d5dc87..6abed7f 100644 (file)
@@ -199,6 +199,32 @@ Dali::Actor RenderTask::GetScreenToFrameBufferMappingActor() const
   return mInputMappingActor.GetHandle();
 }
 
+void RenderTask::SetViewportGuideActor(Actor* actor)
+{
+  mViewportGuideActor.SetActor(actor);
+  if(actor)
+  {
+    SetViewportGuideNodeMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), &actor->GetNode());
+  }
+  else
+  {
+    SetViewportGuideNodeMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), nullptr);
+  }
+}
+
+Actor* RenderTask::GetViewportGuideActor() const
+{
+  return mViewportGuideActor.GetActor();
+}
+
+void RenderTask::ResetViewportGuideActor()
+{
+  SetViewportGuideActor(nullptr);
+
+  BakeViewportPositionMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), mViewportPosition);
+  BakeViewportSizeMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), mViewportSize);
+}
+
 void RenderTask::SetViewportPosition(const Vector2& value)
 {
   mViewportPosition = value;
@@ -742,6 +768,7 @@ RenderTask::RenderTask(const SceneGraph::RenderTask* sceneObject, RenderTaskList
 : Object(sceneObject),
   mSourceActor(),
   mCameraActor(),
+  mViewportGuideActor(),
   mInputMappingActor(),
   mRenderTaskList(renderTaskList),
   mClearColor(Dali::RenderTask::DEFAULT_CLEAR_COLOR),
index 96888e3..828156f 100644 (file)
@@ -122,16 +122,31 @@ public:
   ScreenToFrameBufferFunction GetScreenToFrameBufferFunction() const;
 
   /**
-   * copydoc Dali::RenderTask::SetScreenToFrameBufferMappingActor
+   * @copydoc Dali::RenderTask::SetScreenToFrameBufferMappingActor
    */
   void SetScreenToFrameBufferMappingActor(Dali::Actor& mappingActor);
 
   /**
-   * copydoc Dali::RenderTask::GetScreenToFrameBufferMAppingActor
+   * @copydoc Dali::RenderTask::GetScreenToFrameBufferMAppingActor
    */
   Dali::Actor GetScreenToFrameBufferMappingActor() const;
 
   /**
+   * @copydoc Dali::RenderTask::SetViewportGuideActor
+   */
+  void SetViewportGuideActor(Actor* actor);
+
+  /**
+   * @copydoc Dali::RenderTask::GetViewportGuideActor
+   */
+  Actor* GetViewportGuideActor() const;
+
+  /**
+   * @copydoc Dali::RenderTask::ResetViewportGuideActor
+   */
+  void ResetViewportGuideActor();
+
+  /**
    * @copydoc Dali::RenderTask::SetViewportPosition
    */
   void SetViewportPosition(const Vector2& value);
@@ -332,10 +347,11 @@ private: // not copyable
   RenderTask& operator=(const RenderTask&) = delete;
 
 private:
-  ActorObserver           mSourceActor;       ///< Source actor
-  ActorObserver           mCameraActor;       ///< Camera actor
-  WeakHandle<Dali::Actor> mInputMappingActor; /// used to mapping screen to frame buffer coordinate, not kept alive by rendertask
-  RenderTaskList&         mRenderTaskList;    ///< The render task list
+  ActorObserver           mSourceActor;        ///< Source actor
+  ActorObserver           mCameraActor;        ///< Camera actor
+  ActorObserver           mViewportGuideActor; ///< Actor to matching viewport of this render task to this Actor.
+  WeakHandle<Dali::Actor> mInputMappingActor;  /// used to mapping screen to frame buffer coordinate, not kept alive by rendertask
+  RenderTaskList&         mRenderTaskList;     ///< The render task list
 
   Vector4 mClearColor; ///< Optional clear color
 
index 30d9257..4aaee3b 100644 (file)
@@ -222,6 +222,20 @@ bool ProcessTasks(BufferIndex                          updateBufferIndex,
 
   bool isFirstRenderTask = true;
   bool keepRendering     = false;
+
+  // Retrieve size of Scene and default camera position to update viewport of each RenderTask if the RenderTask uses ViewportGuideNode.
+  RenderTaskList::RenderTaskContainer::Iterator iter                  = taskContainer.Begin();
+  RenderTask&                                   defaultRenderTask     = **iter;
+  auto                                          defaultCamera         = defaultRenderTask.GetCamera().GetNode();
+  auto                                          defaultRootNode       = defaultRenderTask.GetSourceNode();
+  Vector3                                       defaultCameraPosition = Vector3::ZERO;
+  Vector2                                       sceneSize             = Vector2::ZERO;
+  if(defaultCamera && defaultRootNode)
+  {
+    defaultCameraPosition = defaultCamera->GetWorldPosition(updateBufferIndex);
+    sceneSize             = Vector2(defaultRootNode->GetSize(updateBufferIndex) * defaultRootNode->GetWorldScale(updateBufferIndex));
+  }
+
   for(RenderTaskList::RenderTaskContainer::Iterator iter = taskContainer.Begin(), endIter = taskContainer.End(); endIter != iter; ++iter)
   {
     RenderTask& renderTask = **iter;
@@ -257,6 +271,8 @@ bool ProcessTasks(BufferIndex                          updateBufferIndex,
       continue;
     }
 
+    renderTask.UpdateViewport(updateBufferIndex, sceneSize, defaultCameraPosition);
+
     const uint32_t currentNumberOfInstructions = instructions.Count(updateBufferIndex);
 
     if(renderTask.IsRenderRequired())
index 3196166..b155781 100644 (file)
@@ -93,6 +93,16 @@ Node* RenderTask::GetSourceNode() const
   return mSourceNode;
 }
 
+void RenderTask::SetViewportGuideNode(Node* node)
+{
+  mViewportGuideNode = node;
+}
+
+Node* RenderTask::GetViewportGuideNode() const
+{
+  return mViewportGuideNode;
+}
+
 void RenderTask::SetExclusive(bool exclusive)
 {
   mExclusive = exclusive;
@@ -403,6 +413,23 @@ bool RenderTask::ViewMatrixUpdated()
   return retval;
 }
 
+void RenderTask::UpdateViewport(BufferIndex updateBufferIndex, Vector2 sceneSize, Vector3 cameraPosition)
+{
+  if(GetViewportGuideNode() && GetViewportGuideNode()->ConnectedToScene())
+  {
+    Vector3 worldPosition  = GetViewportGuideNode()->GetWorldPosition(updateBufferIndex);
+    worldPosition -= cameraPosition;
+
+    Vector3 nodeSize = GetViewportGuideNode()->GetSize(updateBufferIndex) * GetViewportGuideNode()->GetWorldScale(updateBufferIndex);
+    Vector2 halfSceneSize(sceneSize.width * 0.5f, sceneSize.height * 0.5f); // World position origin is center of scene
+    Vector3 halfNodeSize(nodeSize * 0.5f);
+    Vector2 screenPosition(halfSceneSize.width + worldPosition.x - halfNodeSize.x,
+                           halfSceneSize.height + worldPosition.y - halfNodeSize.y);
+    SetViewportPosition(updateBufferIndex, screenPosition);
+    SetViewportSize(updateBufferIndex, Vector2(nodeSize));
+  }
+}
+
 void RenderTask::SetViewportPosition(BufferIndex updateBufferIndex, const Vector2& value)
 {
   mViewportPosition.Set(updateBufferIndex, value);
@@ -482,6 +509,7 @@ RenderTask::RenderTask()
   mRenderSyncTracker(nullptr),
   mSourceNode(nullptr),
   mCameraNode(nullptr),
+  mViewportGuideNode(nullptr),
   mCamera(nullptr),
   mFrameBuffer(nullptr),
   mRefreshRate(Dali::RenderTask::DEFAULT_REFRESH_RATE),
index 7a28016..7dfb7c1 100644 (file)
@@ -88,6 +88,18 @@ public:
   Node* GetSourceNode() const;
 
   /**
+   * Set the ViewportGuideNode.
+   * @param[in] node This node is used to compute viewport of the render task.
+   */
+  void SetViewportGuideNode(Node* node);
+
+  /**
+   * Retrieve the ViewportGuideNode.
+   * @return This node is used to compute viewport of the render task.
+   */
+  Node* GetViewportGuideNode() const;
+
+  /**
    * Set whether the RenderTask has exclusive access to the source nodes.
    * @param[in] exclusive True if the source nodes will only be rendered by this render-task.
    */
@@ -119,6 +131,14 @@ public:
   Render::FrameBuffer* GetFrameBuffer();
 
   /**
+   * Update viewport by using viewport guide node
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] sceneSize The size of scene.
+   * @param[in] cameraPosition The position of default camera of the scene.
+   */
+  void UpdateViewport(BufferIndex updateBufferIndex, Vector2 sceneSize, Vector3 cameraPosition);
+
+  /**
    * Set the value of property viewportPosition
    * This value will persist only for the current frame.
    * @param[in] updateBufferIndex The current update buffer index.
@@ -372,6 +392,7 @@ private:
   Render::RenderTracker*   mRenderSyncTracker;
   Node*                    mSourceNode;
   Node*                    mCameraNode;
+  Node*                    mViewportGuideNode;
   SceneGraph::Camera*      mCamera;
   Render::FrameBuffer*     mFrameBuffer;
 
@@ -486,6 +507,20 @@ inline void SetCameraMessage(EventThreadServices& eventThreadServices, const Ren
   new(slot) LocalType(&task, &RenderTask::SetCamera, node, camera);
 }
 
+inline void SetViewportGuideNodeMessage(EventThreadServices& eventThreadServices, const RenderTask& task, const Node* constNode)
+{
+  // Scene graph thread can destroy this object.
+  Node* node = const_cast<Node*>(constNode);
+
+  using LocalType = MessageValue1<RenderTask, Node*>;
+
+  // 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(&task, &RenderTask::SetViewportGuideNode, node);
+}
+
 inline void SetExclusiveMessage(EventThreadServices& eventThreadServices, const RenderTask& task, bool exclusive)
 {
   using LocalType = MessageValue1<RenderTask, bool>;
index 1688b26..e59bd82 100644 (file)
@@ -146,6 +146,28 @@ Dali::Actor RenderTask::GetScreenToFrameBufferMappingActor() const
   return GetImplementation(*this).GetScreenToFrameBufferMappingActor();
 }
 
+void RenderTask::SetViewportGuideActor(Actor actor)
+{
+  // NULL handle is allowed
+  Internal::Actor* actorImpl(nullptr);
+  if(actor)
+  {
+    actorImpl = &GetImplementation(actor);
+  }
+
+  GetImplementation(*this).SetViewportGuideActor(actorImpl);
+}
+
+Actor RenderTask::GetViewportGuideActor() const
+{
+  return Dali::Actor(GetImplementation(*this).GetViewportGuideActor());
+}
+
+void RenderTask::ResetViewportGuideActor()
+{
+  GetImplementation(*this).ResetViewportGuideActor();
+}
+
 void RenderTask::SetViewportPosition(Vector2 position)
 {
   GetImplementation(*this).SetViewportPosition(position);
index 9e95672..0832c4b 100644 (file)
@@ -352,6 +352,30 @@ public:
   Actor GetScreenToFrameBufferMappingActor() const;
 
   /**
+   * @brief Sets the actor to compute viewport of this render task.
+   * Actor should be added on Scene.
+   * @SINCE_2_1.36
+   * @param[in] actor This actor is used to compute viewport of the render task.
+   * @note If window default camera is rotated and the actor is no longer a rectangle on the screen, Viewport may be computed incorrectly.
+   * The Viewport properties VIEWPORT_POSITION and VIEWPORT_SIZE is kept during using ViewportGuideActor, but only current value is changed.
+   */
+  void SetViewportGuideActor(Actor actor);
+
+  /**
+   * @brief Retrieves the actor to compute viewport of this render task.
+   * @SINCE_2_1.36
+   * @return This actor is used to compute viewport of the render task.
+   */
+  Actor GetViewportGuideActor() const;
+
+  /**
+   * @brief Resets the actor to compute viewport of this render task.
+   * @SINCE_2_1.36
+   * @note The Viewport properties VIEWPORT_POSITION and VIEWPORT_SIZE is still kept.
+   */
+  void ResetViewportGuideActor();
+
+  /**
    * @brief Sets the GL viewport position used when rendering.
    *
    * This specifies the transformation between normalized device coordinates and target window (or frame-buffer) coordinates.