From 1663aa40e07ab3389d4bab87464398ab8ae84352 Mon Sep 17 00:00:00 2001 From: seungho baek Date: Tue, 30 Jan 2024 18:14:19 +0900 Subject: [PATCH] [Tizen] Add OrderIndex to RenderTask to control rendering order between RenderTask Change-Id: I7aa9bec7a27c04878d1842751ea64813068d582f Signed-off-by: seungho baek --- automated-tests/src/dali/utc-Dali-RenderTask.cpp | 123 +++++++++++++++++++++ automated-tests/src/dali/utc-Dali-Scene.cpp | 1 + dali/internal/event/common/scene-impl.cpp | 1 + .../event/render-tasks/render-task-impl.cpp | 23 ++-- .../internal/event/render-tasks/render-task-impl.h | 11 ++ .../event/render-tasks/render-task-list-impl.cpp | 42 +++++-- .../event/render-tasks/render-task-list-impl.h | 17 ++- .../render-tasks/scene-graph-render-task-list.cpp | 33 ++---- .../render-tasks/scene-graph-render-task-list.h | 31 +++--- dali/public-api/render-tasks/render-task.cpp | 19 ++++ dali/public-api/render-tasks/render-task.h | 20 ++++ 11 files changed, 262 insertions(+), 59 deletions(-) diff --git a/automated-tests/src/dali/utc-Dali-RenderTask.cpp b/automated-tests/src/dali/utc-Dali-RenderTask.cpp index b92b19c..1d08d66 100644 --- a/automated-tests/src/dali/utc-Dali-RenderTask.cpp +++ b/automated-tests/src/dali/utc-Dali-RenderTask.cpp @@ -4261,3 +4261,126 @@ int UtcDaliRenderTaskWithWrongShaderData(void) END_TEST; } + +int UtcDaliRenderTaskOrderIndex01(void) +{ + TestApplication application; + tet_infoline("Testing RenderTask with OrderIndex"); + + Stage stage = Stage::GetCurrent(); + Vector2 stageSize(stage.GetSize()); + + RenderTaskList renderTaskList = stage.GetRenderTaskList(); + RenderTask renderTask1 = renderTaskList.CreateTask(); + + application.SendNotification(); + uint32_t answer1[2] = {0u, 0u}; + DALI_TEST_EQUALS(2, renderTaskList.GetTaskCount(), TEST_LOCATION); + for(uint32_t i = 0; i < 2; ++i) + { + DALI_TEST_EQUALS(answer1[i], renderTaskList.GetTask(i).GetOrderIndex(), TEST_LOCATION); + } + + RenderTask renderTask2 = renderTaskList.CreateTask(); + application.SendNotification(); + int32_t answer2[3] = {0u, 0u, 0u}; + DALI_TEST_EQUALS(3, renderTaskList.GetTaskCount(), TEST_LOCATION); + for(uint32_t i = 0; i < 3; ++i) + { + DALI_TEST_EQUALS(answer2[i], renderTaskList.GetTask(i).GetOrderIndex(), TEST_LOCATION); + } + + RenderTask renderTask3 = renderTaskList.CreateTask(); + application.SendNotification(); + int32_t answer3[4] = {0u, 0u, 0u, 0u}; + DALI_TEST_EQUALS(4, renderTaskList.GetTaskCount(), TEST_LOCATION); + for(uint32_t i = 0; i < 4; ++i) + { + DALI_TEST_EQUALS(answer3[i], renderTaskList.GetTask(i).GetOrderIndex(), TEST_LOCATION); + } + + renderTask1.SetOrderIndex(3); + application.SendNotification(); + int32_t answer4[4] = {0u, 0u, 0u, 3u}; + for(uint32_t i = 0; i < 4; ++i) + { + DALI_TEST_EQUALS(answer4[i], renderTaskList.GetTask(i).GetOrderIndex(), TEST_LOCATION); + } + + renderTask2.SetOrderIndex(7); + application.SendNotification(); + int32_t answer5[4] = {0u, 0u, 3u, 7u}; + for(uint32_t i = 0; i < 4; ++i) + { + DALI_TEST_EQUALS(answer5[i], renderTaskList.GetTask(i).GetOrderIndex(), TEST_LOCATION); + } + + Dali::Integration::Scene scene = application.GetScene(); + scene.GetOverlayLayer(); + application.SendNotification(); + DALI_TEST_EQUALS(5, renderTaskList.GetTaskCount(), TEST_LOCATION); + int32_t answer6[5] = {0u, 0u, 3u, 7u, INT32_MAX}; + for(uint32_t i = 0; i < 5; ++i) + { + DALI_TEST_EQUALS(answer6[i], renderTaskList.GetTask(i).GetOrderIndex(), TEST_LOCATION); + } + + renderTask3.SetOrderIndex(4); + application.SendNotification(); + int32_t answer7[5] = {0u, 3u, 4u, 7u, INT32_MAX}; + for(uint32_t i = 0; i < 5; ++i) + { + DALI_TEST_EQUALS(answer7[i], renderTaskList.GetTask(i).GetOrderIndex(), TEST_LOCATION); + } + + renderTask2.SetOrderIndex(2); + application.SendNotification(); + int32_t answer8[5] = {0u, 2u, 3u, 4u, INT32_MAX}; + for(uint32_t i = 0; i < 5; ++i) + { + DALI_TEST_EQUALS(answer8[i], renderTaskList.GetTask(i).GetOrderIndex(), TEST_LOCATION); + } + + END_TEST; +} + +int UtcDaliRenderTaskOrderIndex02(void) +{ + TestApplication application; + tet_infoline("Testing RenderTask with OrderIndex"); + + Stage stage = Stage::GetCurrent(); + Vector2 stageSize(stage.GetSize()); + + RenderTaskList renderTaskList = stage.GetRenderTaskList(); + RenderTask renderTask1 = renderTaskList.CreateTask(); + application.SendNotification(); + DALI_TEST_EQUALS(renderTask1, renderTaskList.GetTask(1u), TEST_LOCATION); + + RenderTask renderTask2 = renderTaskList.CreateTask(); + application.SendNotification(); + DALI_TEST_EQUALS(renderTask1, renderTaskList.GetTask(1u), TEST_LOCATION); + DALI_TEST_EQUALS(renderTask2, renderTaskList.GetTask(2u), TEST_LOCATION); + + RenderTask renderTask3 = renderTaskList.CreateTask(); + application.SendNotification(); + DALI_TEST_EQUALS(renderTask1, renderTaskList.GetTask(1u), TEST_LOCATION); + DALI_TEST_EQUALS(renderTask2, renderTaskList.GetTask(2u), TEST_LOCATION); + DALI_TEST_EQUALS(renderTask3, renderTaskList.GetTask(3u), TEST_LOCATION); + + RenderTask renderTask4 = renderTaskList.CreateTask(); + application.SendNotification(); + DALI_TEST_EQUALS(renderTask1, renderTaskList.GetTask(1u), TEST_LOCATION); + DALI_TEST_EQUALS(renderTask2, renderTaskList.GetTask(2u), TEST_LOCATION); + DALI_TEST_EQUALS(renderTask3, renderTaskList.GetTask(3u), TEST_LOCATION); + DALI_TEST_EQUALS(renderTask4, renderTaskList.GetTask(4u), TEST_LOCATION); + + renderTask2.SetOrderIndex(2); + application.SendNotification(); + DALI_TEST_EQUALS(renderTask1, renderTaskList.GetTask(1u), TEST_LOCATION); + DALI_TEST_EQUALS(renderTask3, renderTaskList.GetTask(2u), TEST_LOCATION); + DALI_TEST_EQUALS(renderTask4, renderTaskList.GetTask(3u), TEST_LOCATION); + DALI_TEST_EQUALS(renderTask2, renderTaskList.GetTask(4u), TEST_LOCATION); + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-Scene.cpp b/automated-tests/src/dali/utc-Dali-Scene.cpp index e80063d..d98c869 100644 --- a/automated-tests/src/dali/utc-Dali-Scene.cpp +++ b/automated-tests/src/dali/utc-Dali-Scene.cpp @@ -2673,6 +2673,7 @@ int UtcDaliSceneGetOverlayLayer(void) // If new render task is created, the last task is overlayTask RenderTask newTask = scene.GetRenderTaskList().CreateTask(); + application.SendNotification(); 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); diff --git a/dali/internal/event/common/scene-impl.cpp b/dali/internal/event/common/scene-impl.cpp index 7bb3ffd..7fab6c9 100644 --- a/dali/internal/event/common/scene-impl.cpp +++ b/dali/internal/event/common/scene-impl.cpp @@ -286,6 +286,7 @@ void Scene::RebuildDepthTree() actor->RebuildDepthTree(); mDepthTreeDirty = false; } + mRenderTaskList->SortTasks(); } void Scene::SetBackgroundColor(const Vector4& color) diff --git a/dali/internal/event/render-tasks/render-task-impl.cpp b/dali/internal/event/render-tasks/render-task-impl.cpp index c292d96..72c65b6 100644 --- a/dali/internal/event/render-tasks/render-task-impl.cpp +++ b/dali/internal/event/render-tasks/render-task-impl.cpp @@ -81,14 +81,7 @@ RenderTaskPtr RenderTask::New(Actor* sourceActor, CameraActor* cameraActor, Rend // transfer scene object ownership to update manager const SceneGraph::RenderTaskList& parentSceneObject = renderTaskList.GetSceneObject(); OwnerPointer transferOwnership(sceneObject); - if(isOverlayTask) - { - AddOverlayTaskMessage(task->GetEventThreadServices(), parentSceneObject, transferOwnership); - } - else - { - AddTaskMessage(task->GetEventThreadServices(), parentSceneObject, transferOwnership); - } + AddTaskMessage(task->GetEventThreadServices(), parentSceneObject, transferOwnership); // Set the default source & camera actors task->SetSourceActor(sourceActor); @@ -619,6 +612,20 @@ uint32_t RenderTask::GetRenderPassTag() const return mRenderPassTag; } +void RenderTask::SetOrderIndex(int32_t orderIndex) +{ + if(mOrderIndex != orderIndex) + { + mOrderIndex = orderIndex; + mRenderTaskList.RequestToSort(); + } +} + +int32_t RenderTask::GetOrderIndex() const +{ + return mOrderIndex; +} + const SceneGraph::RenderTask* RenderTask::GetRenderTaskSceneObject() const { return static_cast(mUpdateObject); diff --git a/dali/internal/event/render-tasks/render-task-impl.h b/dali/internal/event/render-tasks/render-task-impl.h index 4be6c7f..62ddd86 100644 --- a/dali/internal/event/render-tasks/render-task-impl.h +++ b/dali/internal/event/render-tasks/render-task-impl.h @@ -269,6 +269,16 @@ public: */ uint32_t GetRenderPassTag() const; + /** + * @copydoc Dali::RenderTask::SetOrderIndex() + */ + void SetOrderIndex(int32_t orderIndex); + + /** + * @copydoc Dali::RenderTask::GetOrderIndex() + */ + int32_t GetOrderIndex() const; + public: // Used by RenderTaskList, which owns the SceneGraph::RenderTasks /** * Retrieve the scene-graph RenderTask object. @@ -390,6 +400,7 @@ private: Dali::RenderTask::ScreenToFrameBufferFunction mScreenToFrameBufferFunction; ///< Used to convert screen to frame-buffer coordinates uint32_t mRenderPassTag{0u}; + int32_t mOrderIndex{0u}; bool mExclusive : 1; ///< True if the render-task has exclusive access to the source Nodes. bool mInputEnabled : 1; ///< True if the render-task should be considered for input handling. diff --git a/dali/internal/event/render-tasks/render-task-list-impl.cpp b/dali/internal/event/render-tasks/render-task-list-impl.cpp index 70cb524..34912a0 100644 --- a/dali/internal/event/render-tasks/render-task-list-impl.cpp +++ b/dali/internal/event/render-tasks/render-task-list-impl.cpp @@ -42,6 +42,11 @@ namespace Dali { namespace Internal { +namespace +{ +static constexpr uint32_t ORDER_INDEX_OVERLAY_RENDER_TASK = INT32_MAX; +} + RenderTaskListPtr RenderTaskList::New() { RenderTaskListPtr taskList = new RenderTaskList(); @@ -56,16 +61,14 @@ RenderTaskPtr RenderTaskList::CreateTask() return CreateTask(&mDefaults.GetDefaultRootActor(), &mDefaults.GetDefaultCameraActor()); } -RenderTaskPtr RenderTaskList::CreateTask(Actor* sourceActor, CameraActor* cameraActor) +RenderTaskPtr RenderTaskList::CreateTask(Actor* sourceActor, CameraActor* cameraActor, bool isOverlayTask) { RenderTaskPtr task = RenderTask::New(sourceActor, cameraActor, *this); - if(mOverlayRenderTask && mTasks.back() == mOverlayRenderTask) - { - mTasks.insert(mTasks.end() - 1, task); - } - else + mTasks.push_back(task); + + if(isOverlayTask) { - mTasks.push_back(task); + task->SetOrderIndex(ORDER_INDEX_OVERLAY_RENDER_TASK); } // Setup mapping infomations between scenegraph rendertask @@ -78,11 +81,7 @@ RenderTaskPtr RenderTaskList::CreateOverlayTask(Actor* sourceActor, CameraActor* { if(!mOverlayRenderTask) { - mOverlayRenderTask = RenderTask::New(sourceActor, cameraActor, *this, true); - mTasks.push_back(mOverlayRenderTask); - - // Setup mapping infomations between scenegraph rendertask - this->MapNotifier(mOverlayRenderTask->GetRenderTaskSceneObject(), *mOverlayRenderTask); + mOverlayRenderTask = CreateTask(sourceActor, cameraActor, true); } return mOverlayRenderTask; } @@ -170,6 +169,25 @@ void RenderTaskList::SetExclusive(RenderTask* task, bool exclusive) } } +void RenderTaskList::SortTasks() +{ + if(!mIsRequestedToSortTask) + { + return; + } + + std::stable_sort(mTasks.begin(), mTasks.end(), [](RenderTaskPtr first, RenderTaskPtr second) -> bool + { return first->GetOrderIndex() < second->GetOrderIndex(); }); + + OwnerPointer> sortedTasks(new std::vector()); + for(auto && task : mTasks) + { + sortedTasks->push_back(task->GetRenderTaskSceneObject()); + } + SortTasksMessage(mEventThreadServices, *mSceneObject, sortedTasks); + mIsRequestedToSortTask = false; +} + RenderTaskList::RenderTaskList() : mEventThreadServices(EventThreadServices::Get()), mDefaults(*Stage::GetCurrent()), diff --git a/dali/internal/event/render-tasks/render-task-list-impl.h b/dali/internal/event/render-tasks/render-task-list-impl.h index 2be8177..8fce92f 100644 --- a/dali/internal/event/render-tasks/render-task-list-impl.h +++ b/dali/internal/event/render-tasks/render-task-list-impl.h @@ -90,7 +90,7 @@ public: * @param[in] cameraActor The actor from which the scene is viewed for this render task. * @return A valid handle to a new RenderTask */ - RenderTaskPtr CreateTask(Actor* sourceActor, CameraActor* cameraActor); + RenderTaskPtr CreateTask(Actor* sourceActor, CameraActor* cameraActor, bool isOverlayTask = false); /** * @brief Creates a new RenderTask for overlay. @@ -150,6 +150,19 @@ public: } /** + * @brief Request to sort RenderTasks along OrderIndex + */ + void RequestToSort() + { + mIsRequestedToSortTask = true; + } + + /** + * @brief Sort RenderTasks along OrderIndex + */ + void SortTasks(); + + /** * Provide notification signals for a "Finished" render task. * This method should be called in the event-thread * Queue NotifyFinishedMessage() from update-thread @@ -200,6 +213,8 @@ private: RenderTaskContainer mTasks; ///< Reference counted render-tasks ExclusivesContainer mExclusives; ///< List of rendertasks with exclusively owned source actors. RenderTaskPtr mOverlayRenderTask{nullptr}; + + bool mIsRequestedToSortTask{false}; }; } // namespace Internal diff --git a/dali/internal/update/render-tasks/scene-graph-render-task-list.cpp b/dali/internal/update/render-tasks/scene-graph-render-task-list.cpp index deb1795..128c858 100644 --- a/dali/internal/update/render-tasks/scene-graph-render-task-list.cpp +++ b/dali/internal/update/render-tasks/scene-graph-render-task-list.cpp @@ -46,8 +46,7 @@ RenderTaskList* RenderTaskList::New() RenderTaskList::RenderTaskList() : mNotificationObject(nullptr), mResetterManager(nullptr), - mRenderMessageDispatcher(nullptr), - mOverlayRenderTask(nullptr) + mRenderMessageDispatcher(nullptr) { } @@ -71,20 +70,7 @@ void RenderTaskList::AddTask(OwnerPointer& newTask) newTask->Initialize(*mResetterManager, *mRenderMessageDispatcher); - if(mOverlayRenderTask && mRenderTasks[mRenderTasks.Size() - 1] == mOverlayRenderTask) - { - mRenderTasks.Insert(mRenderTasks.End() - 1, newTask.Release()); - } - else - { - mRenderTasks.PushBack(newTask.Release()); - } -} - -void RenderTaskList::AddOverlayTask(OwnerPointer& newTask) -{ - AddTask(newTask); - mOverlayRenderTask = mRenderTasks[mRenderTasks.Size() - 1]; + mRenderTasks.PushBack(newTask.Release()); } void RenderTaskList::RemoveTask(RenderTask* task) @@ -94,11 +80,6 @@ void RenderTaskList::RemoveTask(RenderTask* task) { if(*iter == task) { - if(mOverlayRenderTask == task) - { - mOverlayRenderTask = nullptr; - } - // Destroy the task mRenderTasks.Erase(iter); @@ -107,6 +88,16 @@ void RenderTaskList::RemoveTask(RenderTask* task) } } +void RenderTaskList::SortTasks(OwnerPointer>& sortedTasks) +{ + for(uint32_t i = 0; i < sortedTasks->size(); ++i) + { + const SceneGraph::RenderTask* task = (*sortedTasks)[i]; + SceneGraph::RenderTask* castedTask = const_cast(task); + mRenderTasks[i] = castedTask; + } +} + uint32_t RenderTaskList::GetTaskCount() { return static_cast(mRenderTasks.Count()); diff --git a/dali/internal/update/render-tasks/scene-graph-render-task-list.h b/dali/internal/update/render-tasks/scene-graph-render-task-list.h index dd78e0c..4df6ec2 100644 --- a/dali/internal/update/render-tasks/scene-graph-render-task-list.h +++ b/dali/internal/update/render-tasks/scene-graph-render-task-list.h @@ -75,12 +75,6 @@ public: void AddTask(OwnerPointer& newTask); /** - * Add a overlay RenderTask to the list. - * @param[in] newTask The RenderTaskList takes ownership of this overlay task. - */ - void AddOverlayTask(OwnerPointer& newTask); - - /** * Remove a RenderTask from the list. * @param[in] task The RenderTaskList will destroy this task. */ @@ -120,6 +114,11 @@ public: */ static uint32_t GetMemoryPoolCapacity(); + /** + * @brief Sort RenderTasks along OrderIndex + */ + void SortTasks(OwnerPointer>& sortedTasks); + protected: /** * Protected constructor. See New() @@ -138,7 +137,6 @@ private: ResetterManager* mResetterManager; ///< for sending bake resetter if rendertask initalized RenderMessageDispatcher* mRenderMessageDispatcher; ///< for sending messages to render thread RenderTaskContainer mRenderTasks; ///< A container of owned RenderTasks - RenderTask* mOverlayRenderTask; ///< OverlayRenderTask. }; // Messages for RenderTaskList @@ -155,30 +153,29 @@ inline void AddTaskMessage(EventThreadServices& eventThreadServices, const Rende new(slot) LocalType(&list, &RenderTaskList::AddTask, task); } -inline void AddOverlayTaskMessage(EventThreadServices& eventThreadServices, const RenderTaskList& list, OwnerPointer& task) +inline void RemoveTaskMessage(EventThreadServices& eventThreadServices, const RenderTaskList& list, const RenderTask& constTask) { - // Message has ownership of the RenderTask while in transit from event -> update - using LocalType = MessageValue1 >; + // Scene graph thread can destroy this object. + RenderTask& task = const_cast(constTask); + + using LocalType = MessageValue1; // 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); + new(slot) LocalType(&list, &RenderTaskList::RemoveTask, &task); } -inline void RemoveTaskMessage(EventThreadServices& eventThreadServices, const RenderTaskList& list, const RenderTask& constTask) +inline void SortTasksMessage(EventThreadServices& eventThreadServices, const RenderTaskList& list, OwnerPointer>& sortedTasks) { - // Scene graph thread can destroy this object. - RenderTask& task = const_cast(constTask); - - using LocalType = MessageValue1; + using LocalType = MessageValue1>>; // 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::RemoveTask, &task); + new(slot) LocalType(&list, &RenderTaskList::SortTasks, sortedTasks); } } // namespace SceneGraph diff --git a/dali/public-api/render-tasks/render-task.cpp b/dali/public-api/render-tasks/render-task.cpp index 9740581..aaa1328 100644 --- a/dali/public-api/render-tasks/render-task.cpp +++ b/dali/public-api/render-tasks/render-task.cpp @@ -48,6 +48,9 @@ const bool RenderTask::DEFAULT_CLEAR_ENABLED = false; const bool RenderTask::DEFAULT_CULL_MODE = true; const uint32_t RenderTask::DEFAULT_REFRESH_RATE = REFRESH_ALWAYS; +static constexpr int32_t MIN_ORDER_INDEX = -1000; +static constexpr int32_t MAX_ORDER_INDEX = 1000; + RenderTask::RenderTask() = default; RenderTask RenderTask::DownCast(BaseHandle handle) @@ -283,6 +286,22 @@ uint32_t RenderTask::GetRenderPassTag() const return GetImplementation(*this).GetRenderPassTag(); } +void RenderTask::SetOrderIndex(int32_t orderIndex) +{ + if(orderIndex < MIN_ORDER_INDEX || orderIndex > MAX_ORDER_INDEX) + { + DALI_LOG_ERROR("OrderIndex value can be available between [-1000, 1000].\n"); + orderIndex = std::min(orderIndex, MAX_ORDER_INDEX); + orderIndex = std::max(orderIndex, MIN_ORDER_INDEX); + } + GetImplementation(*this).SetOrderIndex(orderIndex); +} + +int32_t RenderTask::GetOrderIndex() const +{ + return GetImplementation(*this).GetOrderIndex(); +} + RenderTask::RenderTask(Internal::RenderTask* internal) : Handle(internal) { diff --git a/dali/public-api/render-tasks/render-task.h b/dali/public-api/render-tasks/render-task.h index 8d0b356..ea4265f 100644 --- a/dali/public-api/render-tasks/render-task.h +++ b/dali/public-api/render-tasks/render-task.h @@ -551,6 +551,26 @@ public: */ uint32_t GetRenderPassTag() const; + /** + * Sets Order Index to define rendering order for this RenderTask. + * In the DALi, offscreen renderTasks are rendered earlier than onscreen renderTask. + * In each category of OffScreen RenderTask and OnScreen RenderTask, + * a RenderTask with a smaller orderIndex is rendered first. + * The RenderTasks in RenderTaskList is always sorted as acending order of the OrderIndex. + * The OrderIndex value is needed to be set between [-1000, 1000]. + * Default orderIndex is 0. + * @param[in] orderIndex the order index for this render task. + * @note The order among RenderTasks whose OrderIndex has not changed follows the order in which they were created. + * @note Rendering order among RenderTasks those have same OrderIndex cannot be guaranteed after the OrderIndex is changed + */ + void SetOrderIndex(int32_t orderIndex); + + /** + * Gets Order Index for this RenderTask. + * @return OrderIndex value for this render task. + */ + int32_t GetOrderIndex() const; + public: // Signals /** * @brief If the refresh rate is REFRESH_ONCE, connect to this signal to be notified when a RenderTask has finished. -- 2.7.4