From: jmm Date: Fri, 19 Apr 2024 11:52:19 +0000 (+0900) Subject: Add RenderTask::RenderUntil() X-Git-Tag: dali_2.3.22~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F44%2F310044%2F10;p=platform%2Fcore%2Fuifw%2Fdali-core.git Add RenderTask::RenderUntil() Change-Id: I264e29303deedaf0f8539137b26e7d0c3e8454ce --- diff --git a/automated-tests/src/dali/utc-Dali-RenderTask.cpp b/automated-tests/src/dali/utc-Dali-RenderTask.cpp index cf7bd97..a2d870e 100644 --- a/automated-tests/src/dali/utc-Dali-RenderTask.cpp +++ b/automated-tests/src/dali/utc-Dali-RenderTask.cpp @@ -692,6 +692,89 @@ int UtcDaliRenderTaskGetSourceActorN(void) END_TEST; } +int UtcDaliRenderTaskGetStopperActorP(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::GetStopperActor() Create a new render task, Add a new actor to the stage and set RenderTask::RenderUntil(actor). Get its stopper actor and check it is equivalent to what was set."); + + RenderTaskList taskList = application.GetScene().GetRenderTaskList(); + RenderTask task = taskList.CreateTask(); + Actor actor = Actor::New(); + application.GetScene().Add(actor); + task.RenderUntil(actor); + + DALI_TEST_EQUALS(actor, task.GetStopperActor(), TEST_LOCATION); + + END_TEST; +} + +int UtcDaliRenderTaskGetStopperActorN(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::GetStopperActor() Try with empty handle"); + + RenderTask task; + + try + { + Actor actor = task.GetStopperActor(); + } + catch(Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT(e); + DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION); + } + + END_TEST; +} + +int UtcDaliRenderTaskRenderUntil(void) +{ + TestApplication application; + tet_infoline("Testing RenderTask::RenderUntil(actor) Check that rendering stops at the actor."); + + // Make a new render task and compose a tree. + RenderTaskList taskList = application.GetScene().GetRenderTaskList(); + RenderTask task = taskList.GetTask(0u); + + Integration::Scene stage = application.GetScene(); + + Actor secondChild; + for(int i = 0; i < 5; i++) + { + Actor parent = CreateRenderableActor(); + parent.SetProperty(Actor::Property::SIZE, Vector2(1.0f, 1.0f)); + parent.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + Actor child = CreateRenderableActor(); + child.SetProperty(Actor::Property::SIZE, Vector2(1.0f, 1.0f)); + + stage.Add(parent); + parent.Add(child); + + if (i == 1) + { + secondChild = child; + } + } + task.RenderUntil(secondChild); + + // Update & Render with the actor on-stage + TestGlAbstraction& gl = application.GetGlAbstraction(); + TraceCallStack& drawTrace = gl.GetDrawTrace(); + drawTrace.Enable(true); + + // Update & Render + application.SendNotification(); + application.Render(); + + // Check that rendering was cut. + DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 3, TEST_LOCATION); + + END_TEST; +} + int UtcDaliRenderTaskSetExclusive(void) { TestApplication application; diff --git a/dali/internal/event/render-tasks/render-task-impl.cpp b/dali/internal/event/render-tasks/render-task-impl.cpp index 25ca2dc..b28f64c 100644 --- a/dali/internal/event/render-tasks/render-task-impl.cpp +++ b/dali/internal/event/render-tasks/render-task-impl.cpp @@ -117,6 +117,11 @@ Actor* RenderTask::GetSourceActor() const return mSourceActor.GetActor(); } +Actor* RenderTask::GetStopperActor() const +{ + return mStopperActor.GetActor(); +} + void RenderTask::SetExclusive(bool exclusive) { if(mExclusive != exclusive) @@ -640,6 +645,27 @@ uint32_t RenderTask::GetRenderTaskId() const return mRenderTaskId; } +void RenderTask::RenderUntil(Actor* actor) +{ + Actor* target = mSourceActor.GetActor(); + DALI_ASSERT_ALWAYS((target && actor) + && "RenderTask::RenderUntil() has empty actors."); + DALI_ASSERT_ALWAYS((target->GetHierarchyDepth() < actor->GetHierarchyDepth()) + && "RenderTask::RenderUntil() has reversed hierarchy."); + + Actor* parent = actor; + while(parent != target && !(parent->IsLayer())) + { + parent = parent->GetParent(); + } + + if(parent == target && GetRenderTaskSceneObject()) + { + mStopperActor.SetActor(actor); + SetStopperNodeMessage(GetEventThreadServices(), *GetRenderTaskSceneObject(), &actor->GetNode()); + } +} + 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 f8897b0..7c57c3e 100644 --- a/dali/internal/event/render-tasks/render-task-impl.h +++ b/dali/internal/event/render-tasks/render-task-impl.h @@ -71,6 +71,8 @@ public: */ Actor* GetSourceActor() const; + Actor* GetStopperActor() const; + /** * @copydoc Dali::RenderTask::SetExclusive() */ @@ -284,6 +286,8 @@ public: */ uint32_t GetRenderTaskId() const; + void RenderUntil(Actor* actor); + public: // Used by RenderTaskList, which owns the SceneGraph::RenderTasks /** * Retrieve the scene-graph RenderTask object. @@ -388,6 +392,7 @@ private: ActorObserver mSourceActor; ///< Source actor ActorObserver mCameraActor; ///< Camera actor ActorObserver mViewportGuideActor; ///< Actor to matching viewport of this render task to this Actor. + ActorObserver mStopperActor; ///< A child of mSourceActor. Actor to stop rendering. WeakHandle mInputMappingActor; /// used to mapping screen to frame buffer coordinate, not kept alive by rendertask RenderTaskList& mRenderTaskList; ///< The render task list diff --git a/dali/internal/update/manager/render-task-processor.cpp b/dali/internal/update/manager/render-task-processor.cpp index b3c3d20..6059a12 100644 --- a/dali/internal/update/manager/render-task-processor.cpp +++ b/dali/internal/update/manager/render-task-processor.cpp @@ -94,6 +94,7 @@ Layer* FindLayer(Node& node) * @param[in] clippingDepth The current scissor clipping depth * @param[out] clippingUsed Gets set to true if any clipping nodes have been found * @param[out] keepRendering Gets set to true if rendering should be kept. + * @param[out] renderStopped Gets set to true if rendering should be stopped. */ void AddRenderablesForTask(BufferIndex updateBufferIndex, Node& node, @@ -105,8 +106,14 @@ void AddRenderablesForTask(BufferIndex updateBufferIndex, uint32_t clippingDepth, uint32_t scissorDepth, bool& clippingUsed, - bool& keepRendering) + bool& keepRendering, + bool& renderStopped) { + if(renderStopped) + { + return; + } + // Short-circuit for invisible nodes if(!node.IsVisible(updateBufferIndex)) { @@ -188,10 +195,15 @@ void AddRenderablesForTask(BufferIndex updateBufferIndex, // Recurse children. NodeContainer& children = node.GetChildren(); const NodeIter endIter = children.End(); - for(NodeIter iter = children.Begin(); iter != endIter; ++iter) + for(NodeIter iter = children.Begin(); !renderStopped && iter != endIter; ++iter) { Node& child = **iter; - AddRenderablesForTask(updateBufferIndex, child, parentVisibilityChanged, *layer, renderTask, inheritedDrawMode, currentClippingId, clippingDepth, scissorDepth, clippingUsed, keepRendering); + if(child == renderTask.GetStopperNode()) + { + renderStopped = true; + break; + } + AddRenderablesForTask(updateBufferIndex, child, parentVisibilityChanged, *layer, renderTask, inheritedDrawMode, currentClippingId, clippingDepth, scissorDepth, clippingUsed, keepRendering, renderStopped); } } @@ -285,6 +297,8 @@ void ProcessTasks(BufferIndex updateBufferIndex, sortedLayer->ClearRenderables(); } + bool stopRendering = false; + AddRenderablesForTask(updateBufferIndex, *sourceNode, false, @@ -295,7 +309,8 @@ void ProcessTasks(BufferIndex updateBufferIndex, 0u, 0u, hasClippingNodes, - keepRendering); + keepRendering, + stopRendering); renderInstructionProcessor.Prepare(updateBufferIndex, sortedLayers, diff --git a/dali/internal/update/render-tasks/scene-graph-render-task-messages.h b/dali/internal/update/render-tasks/scene-graph-render-task-messages.h index b2de30a..f58a30c 100644 --- a/dali/internal/update/render-tasks/scene-graph-render-task-messages.h +++ b/dali/internal/update/render-tasks/scene-graph-render-task-messages.h @@ -91,6 +91,20 @@ inline void SetSourceNodeMessage(EventThreadServices& eventThreadServices, const new(slot) LocalType(&task, &RenderTask::SetSourceNode, node); } +inline void SetStopperNodeMessage(EventThreadServices& eventThreadServices, const RenderTask& task, const Node* constNode) +{ + // Scene graph thread can destroy this object. + Node* node = const_cast(constNode); + + 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(&task, &RenderTask::SetStopperNode, node); +} + inline void SetCameraMessage(EventThreadServices& eventThreadServices, const RenderTask& task, const Camera* constCamera) { using LocalType = MessageValue1; diff --git a/dali/internal/update/render-tasks/scene-graph-render-task.cpp b/dali/internal/update/render-tasks/scene-graph-render-task.cpp index bfe2f5e..dd58a5f 100644 --- a/dali/internal/update/render-tasks/scene-graph-render-task.cpp +++ b/dali/internal/update/render-tasks/scene-graph-render-task.cpp @@ -94,6 +94,16 @@ Node* RenderTask::GetSourceNode() const return mSourceNode; } +void RenderTask::SetStopperNode(Node* node) +{ + mStopperNode = node; +} + +Node* RenderTask::GetStopperNode() const +{ + return mStopperNode; +} + void RenderTask::SetViewportGuideNode(Node* node) { mViewportGuideNode = node; diff --git a/dali/internal/update/render-tasks/scene-graph-render-task.h b/dali/internal/update/render-tasks/scene-graph-render-task.h index 3ff90fc..7e07b08 100644 --- a/dali/internal/update/render-tasks/scene-graph-render-task.h +++ b/dali/internal/update/render-tasks/scene-graph-render-task.h @@ -87,6 +87,9 @@ public: */ Node* GetSourceNode() const; + void SetStopperNode(Node* node); + Node* GetStopperNode() const; + /** * Set the ViewportGuideNode. * @param[in] node This node is used to compute viewport of the render task. @@ -406,6 +409,7 @@ private: RenderMessageDispatcher* mRenderMessageDispatcher; Render::RenderTracker* mRenderSyncTracker; Node* mSourceNode; + Node* mStopperNode; SceneGraph::Camera* mCameraNode; Node* mViewportGuideNode; Render::FrameBuffer* mFrameBuffer; diff --git a/dali/public-api/render-tasks/render-task.cpp b/dali/public-api/render-tasks/render-task.cpp index 4521f44..7b26b56 100644 --- a/dali/public-api/render-tasks/render-task.cpp +++ b/dali/public-api/render-tasks/render-task.cpp @@ -85,6 +85,11 @@ Actor RenderTask::GetSourceActor() const return Dali::Actor(GetImplementation(*this).GetSourceActor()); } +Actor RenderTask::GetStopperActor() const +{ + return Dali::Actor(GetImplementation(*this).GetStopperActor()); +} + void RenderTask::SetExclusive(bool exclusive) { GetImplementation(*this).SetExclusive(exclusive); @@ -307,6 +312,13 @@ uint32_t RenderTask::GetRenderTaskId() const return GetImplementation(*this).GetRenderTaskId(); } +void RenderTask::RenderUntil(Actor actor) +{ + DALI_ASSERT_ALWAYS(actor && "RenderUntil() actor does not exist."); + Internal::Actor* actorImpl(&GetImplementation(actor)); + return GetImplementation(*this).RenderUntil(actorImpl); +} + 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 6eab3d4..5d6be1a 100644 --- a/dali/public-api/render-tasks/render-task.h +++ b/dali/public-api/render-tasks/render-task.h @@ -256,6 +256,8 @@ public: */ Actor GetSourceActor() const; + Actor GetStopperActor() const; + /** * @brief Sets whether the RenderTask has exclusive access to the source actors; the default is false. * @SINCE_1_0.0 @@ -579,6 +581,8 @@ public: */ uint32_t GetRenderTaskId() const; + void RenderUntil(Actor actor); + public: // Signals /** * @brief If the refresh rate is REFRESH_ONCE, connect to this signal to be notified when a RenderTask has finished.