2 * Copyright (c) 2024 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
22 #include <dali/internal/event/actors/camera-actor-impl.h>
23 #include <dali/internal/event/common/event-thread-services.h>
24 #include <dali/internal/event/common/stage-impl.h>
25 #include <dali/internal/event/render-tasks/render-task-defaults.h>
26 #include <dali/internal/event/render-tasks/render-task-impl.h>
27 #include <dali/internal/update/manager/update-manager.h>
28 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
29 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
30 #include <dali/public-api/common/dali-common.h>
32 using Dali::Internal::SceneGraph::UpdateManager;
34 #if defined(DEBUG_ENABLED)
37 Debug::Filter* gLogRenderList = Debug::Filter::New(Debug::Concise, false, "LOG_RENDER_TASK_LIST");
47 static constexpr uint32_t ORDER_INDEX_OVERLAY_RENDER_TASK = INT32_MAX;
50 RenderTaskListPtr RenderTaskList::New()
52 RenderTaskListPtr taskList = new RenderTaskList();
54 taskList->Initialize();
59 RenderTaskPtr RenderTaskList::CreateTask()
61 return CreateTask(&mDefaults.GetDefaultRootActor(), &mDefaults.GetDefaultCameraActor());
64 RenderTaskPtr RenderTaskList::CreateTask(Actor* sourceActor, CameraActor* cameraActor, bool isOverlayTask)
66 RenderTaskPtr task = RenderTask::New(sourceActor, cameraActor, *this);
67 mTasks.push_back(task);
71 task->SetOrderIndex(ORDER_INDEX_OVERLAY_RENDER_TASK);
74 // Setup mapping infomations between scenegraph rendertask
75 this->MapNotifier(task->GetRenderTaskSceneObject(), *task);
80 RenderTaskPtr RenderTaskList::CreateOverlayTask(Actor* sourceActor, CameraActor* cameraActor)
82 if(!mOverlayRenderTask)
84 mOverlayRenderTask = CreateTask(sourceActor, cameraActor, true);
86 return mOverlayRenderTask;
89 void RenderTaskList::RemoveTask(Internal::RenderTask& task)
91 for(RenderTaskContainer::iterator iter = mTasks.begin(); mTasks.end() != iter; ++iter)
93 RenderTask* ptr = iter->Get();
97 if(mOverlayRenderTask == &task)
99 mOverlayRenderTask.Reset();
102 // Remove mapping infomations
103 this->UnmapNotifier(task.GetRenderTaskSceneObject());
108 task.RemoveRenderTaskSceneObject(*this);
110 Exclusive exclusive{ptr, ActorObserver()};
111 ExclusivesContainer::iterator exclusiveIter = find(mExclusives.begin(), mExclusives.end(), exclusive);
112 if(exclusiveIter != mExclusives.end())
114 mExclusives.erase(exclusiveIter);
116 break; // we're finished
121 uint32_t RenderTaskList::GetTaskCount() const
123 return static_cast<uint32_t>(mTasks.size()); // only 4,294,967,295 render tasks supported
126 RenderTaskPtr RenderTaskList::GetTask(uint32_t index) const
128 DALI_ASSERT_ALWAYS((index < mTasks.size()) && "RenderTask index out-of-range");
130 return mTasks[index];
133 RenderTaskPtr RenderTaskList::GetOverlayTask() const
135 RenderTaskPtr overlayRenderTask;
136 if(mOverlayRenderTask)
138 overlayRenderTask = mOverlayRenderTask;
140 return overlayRenderTask;
143 void RenderTaskList::SetExclusive(RenderTask* task, bool exclusive)
145 // Check to see if this rendertask has an entry?
146 for(auto exclusiveIt = mExclusives.begin(); exclusiveIt != mExclusives.end(); ++exclusiveIt)
148 if(exclusiveIt->renderTaskPtr == task)
152 mExclusives.erase(exclusiveIt);
157 exclusiveIt->actor.SetActor(task->GetSourceActor());
165 Exclusive exclusiveSlot;
166 exclusiveSlot.renderTaskPtr = task;
167 exclusiveSlot.actor.SetActor(task->GetSourceActor());
168 mExclusives.emplace_back(std::move(exclusiveSlot));
172 void RenderTaskList::SortTasks()
174 if(!mIsRequestedToSortTask)
179 std::stable_sort(mTasks.begin(), mTasks.end(), [](RenderTaskPtr first, RenderTaskPtr second) -> bool { return first->GetOrderIndex() < second->GetOrderIndex(); });
181 OwnerPointer<std::vector<const SceneGraph::RenderTask*>> sortedTasks(new std::vector<const SceneGraph::RenderTask*>());
182 for(auto&& task : mTasks)
184 sortedTasks->push_back(task->GetRenderTaskSceneObject());
186 SortTasksMessage(mEventThreadServices, *mSceneObject, sortedTasks);
187 mIsRequestedToSortTask = false;
190 RenderTaskList::RenderTaskList()
191 : mEventThreadServices(EventThreadServices::Get()),
192 mDefaults(*Stage::GetCurrent()),
193 mSceneObject(nullptr)
197 RenderTaskList::~RenderTaskList()
199 if(DALI_UNLIKELY(!Dali::Stage::IsCoreThread()))
201 DALI_LOG_ERROR("~RenderTaskList[%p] called from non-UI thread! something unknown issue will be happened!\n", this);
204 if(DALI_LIKELY(EventThreadServices::IsCoreRunning() && mSceneObject))
206 // Remove the render task list using a message to the update manager
207 RemoveRenderTaskListMessage(mEventThreadServices.GetUpdateManager(), *mSceneObject);
211 void RenderTaskList::Initialize()
213 // Create a new render task list, Keep a const pointer to the render task list.
214 mSceneObject = SceneGraph::RenderTaskList::New();
216 OwnerPointer<SceneGraph::RenderTaskList> transferOwnership(const_cast<SceneGraph::RenderTaskList*>(mSceneObject));
217 AddRenderTaskListMessage(mEventThreadServices.GetUpdateManager(), transferOwnership);
219 // set the callback to call us back when tasks are completed
220 mSceneObject->SetCompleteNotificationInterface(this);
223 void RenderTaskList::NotifyCompleted(CompleteNotificationInterface::ParameterList notifierIdList)
225 DALI_LOG_TRACE_METHOD(gLogRenderList);
227 RenderTaskContainer finishedRenderTasks;
229 for(const auto& notifierId : notifierIdList)
231 auto* renderTask = GetEventObject(notifierId);
232 if(DALI_LIKELY(renderTask))
234 // Check if this render task hold inputed scenegraph render task.
235 DALI_ASSERT_DEBUG(renderTask->GetRenderTaskSceneObject()->GetNotifyId() == notifierId);
237 if(renderTask->HasFinished())
239 finishedRenderTasks.push_back(renderTask);
244 // Now it's safe to emit the signals
245 for(auto&& item : finishedRenderTasks)
247 item->EmitSignalFinish();
251 void RenderTaskList::RecoverFromContextLoss()
253 for(auto&& item : mTasks)
255 // If the render target renders only once to an offscreen, re-render the render task
256 if(item->GetRefreshRate() == Dali::RenderTask::REFRESH_ONCE && item->GetFrameBuffer())
258 item->SetRefreshRate(Dali::RenderTask::REFRESH_ONCE);
263 const SceneGraph::RenderTaskList& RenderTaskList::GetSceneObject() const
265 return *mSceneObject;
268 } // namespace Internal