From: seungho baek Date: Mon, 9 Jan 2023 01:23:21 +0000 (+0900) Subject: [Tizen] Add Overlay Layer in scene X-Git-Tag: accepted/tizen/7.0/unified/20230203.164137~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F08%2F286908%2F3;p=platform%2Fcore%2Fuifw%2Fdali-core.git [Tizen] Add Overlay Layer in scene Change-Id: I65447d7ace9e13f528f244234e139e3e9682291b Signed-off-by: seungho baek --- diff --git a/automated-tests/src/dali/utc-Dali-Scene.cpp b/automated-tests/src/dali/utc-Dali-Scene.cpp index 0dd5e19..959e5ee 100644 --- a/automated-tests/src/dali/utc-Dali-Scene.cpp +++ b/automated-tests/src/dali/utc-Dali-Scene.cpp @@ -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; +} diff --git a/dali/integration-api/scene.cpp b/dali/integration-api/scene.cpp index cce626d..26d72ac 100644 --- a/dali/integration-api/scene.cpp +++ b/dali/integration-api/scene.cpp @@ -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(); diff --git a/dali/integration-api/scene.h b/dali/integration-api/scene.h index bdaf814..4a851a2 100644 --- a/dali/integration-api/scene.h +++ b/dali/integration-api/scene.h @@ -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). diff --git a/dali/internal/event/common/scene-impl.cpp b/dali/internal/event/common/scene-impl.cpp index ea5c689..56ed507 100644 --- a/dali/internal/event/common/scene-impl.cpp +++ b/dali/internal/event/common/scene-impl.cpp @@ -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 diff --git a/dali/internal/event/common/scene-impl.h b/dali/internal/event/common/scene-impl.h index 52ea356..cda29a2 100644 --- a/dali/internal/event/common/scene-impl.h +++ b/dali/internal/event/common/scene-impl.h @@ -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 mLayerList; diff --git a/dali/internal/event/render-tasks/render-task-impl.cpp b/dali/internal/event/render-tasks/render-task-impl.cpp index 8069b54..a74bba0 100644 --- a/dali/internal/event/render-tasks/render-task-impl.cpp +++ b/dali/internal/event/render-tasks/render-task-impl.cpp @@ -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 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); diff --git a/dali/internal/event/render-tasks/render-task-impl.h b/dali/internal/event/render-tasks/render-task-impl.h index 828156f..c859227 100644 --- a/dali/internal/event/render-tasks/render-task-impl.h +++ b/dali/internal/event/render-tasks/render-task-impl.h @@ -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() 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 39a98ba..6f512d2 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,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? 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 6a8ed44..c01b981 100644 --- a/dali/internal/event/render-tasks/render-task-list-impl.h +++ b/dali/internal/event/render-tasks/render-task-list-impl.h @@ -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; + 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 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 8139c2b..d074c4c 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 @@ -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& 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& newTask) +{ + AddTask(newTask); + mOverlayRenderTask = mRenderTasks[mRenderTasks.Size() - 1]; } void RenderTaskList::RemoveTask(RenderTask* task) 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 c985491..a99e142 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 @@ -73,6 +73,12 @@ 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. */ @@ -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& task) +{ + // Message has ownership of the RenderTask while in transit from event -> update + 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); +} + inline void RemoveTaskMessage(EventThreadServices& eventThreadServices, const RenderTaskList& list, const RenderTask& constTask) { // Scene graph thread can destroy this object. diff --git a/dali/public-api/render-tasks/render-task-list.cpp b/dali/public-api/render-tasks/render-task-list.cpp index eabd958..941c6e7 100644 --- a/dali/public-api/render-tasks/render-task-list.cpp +++ b/dali/public-api/render-tasks/render-task-list.cpp @@ -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) { diff --git a/dali/public-api/render-tasks/render-task-list.h b/dali/public-api/render-tasks/render-task-list.h index ad33f96..0de427c 100644 --- a/dali/public-api/render-tasks/render-task-list.h +++ b/dali/public-api/render-tasks/render-task-list.h @@ -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 /**