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
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;
: Object(sceneObject),
mSourceActor(),
mCameraActor(),
+ mViewportGuideActor(),
mInputMappingActor(),
mRenderTaskList(renderTaskList),
mClearColor(Dali::RenderTask::DEFAULT_CLEAR_COLOR),
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);
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
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;
continue;
}
+ renderTask.UpdateViewport(updateBufferIndex, sceneSize, defaultCameraPosition);
+
const uint32_t currentNumberOfInstructions = instructions.Count(updateBufferIndex);
if(renderTask.IsRenderRequired())
return mSourceNode;
}
+void RenderTask::SetViewportGuideNode(Node* node)
+{
+ mViewportGuideNode = node;
+}
+
+Node* RenderTask::GetViewportGuideNode() const
+{
+ return mViewportGuideNode;
+}
+
void RenderTask::SetExclusive(bool exclusive)
{
mExclusive = exclusive;
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);
mRenderSyncTracker(nullptr),
mSourceNode(nullptr),
mCameraNode(nullptr),
+ mViewportGuideNode(nullptr),
mCamera(nullptr),
mFrameBuffer(nullptr),
mRefreshRate(Dali::RenderTask::DEFAULT_REFRESH_RATE),
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.
*/
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.
Render::RenderTracker* mRenderSyncTracker;
Node* mSourceNode;
Node* mCameraNode;
+ Node* mViewportGuideNode;
SceneGraph::Camera* mCamera;
Render::FrameBuffer* mFrameBuffer;
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>;
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);
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.