Change RenderTaskList to behave like any other SceneGraph object
[platform/core/uifw/dali-core.git] / dali / internal / event / render-tasks / render-task-list-impl.cpp
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/public-api/common/dali-common.h>
23 #include <dali/internal/event/common/event-thread-services.h>
24 #include <dali/internal/event/common/thread-local-storage.h>
25 #include <dali/internal/event/common/stage-impl.h>
26 #include <dali/internal/event/render-tasks/render-task-defaults.h>
27 #include <dali/internal/event/render-tasks/render-task-impl.h>
28 #include <dali/internal/event/actors/camera-actor-impl.h>
29 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
30 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
31 #include <dali/internal/update/manager/update-manager.h>
32
33 using Dali::Internal::SceneGraph::UpdateManager;
34
35 #if defined(DEBUG_ENABLED)
36 namespace
37 {
38 Debug::Filter* gLogRenderList = Debug::Filter::New(Debug::Concise, false, "LOG_RENDER_TASK_LIST");
39 }
40 #endif
41
42 namespace Dali
43 {
44 namespace Internal
45 {
46
47 RenderTaskListPtr RenderTaskList::New()
48 {
49   RenderTaskListPtr taskList = new RenderTaskList();
50
51   taskList->Initialize();
52
53   return taskList;
54 }
55
56 Dali::RenderTask RenderTaskList::CreateTask()
57 {
58   return CreateTask( &mDefaults.GetDefaultRootActor(), &mDefaults.GetDefaultCameraActor() );
59 }
60
61 Dali::RenderTask RenderTaskList::CreateTask( Actor* sourceActor, CameraActor* cameraActor)
62 {
63   RenderTask* taskImpl = RenderTask::New();
64
65   Dali::RenderTask newTask( taskImpl );
66   mTasks.push_back( newTask );
67
68   if ( mSceneObject )
69   {
70     SceneGraph::RenderTask* sceneObject = taskImpl->CreateSceneObject();
71
72     OwnerPointer< SceneGraph::RenderTask > transferOwnership( sceneObject );
73     AddTaskMessage( mEventThreadServices, *mSceneObject, transferOwnership );
74   }
75
76   // Set the default source & camera actors
77   taskImpl->SetSourceActor( sourceActor );
78   taskImpl->SetCameraActor( cameraActor );
79
80   return newTask;
81 }
82
83 void RenderTaskList::RemoveTask( Dali::RenderTask task )
84 {
85   for ( RenderTaskContainer::iterator iter = mTasks.begin(); mTasks.end() != iter; ++iter )
86   {
87     if ( *iter == task )
88     {
89       RenderTask& taskImpl = GetImplementation( task );
90       if ( mSceneObject )
91       {
92         SceneGraph::RenderTask* sceneObject = taskImpl.GetRenderTaskSceneObject();
93         DALI_ASSERT_DEBUG( NULL != sceneObject );
94
95         // Send a message to remove the scene-graph RenderTask
96         RemoveTaskMessage( mEventThreadServices, *mSceneObject, *sceneObject );
97
98         // The scene-graph RenderTask will be destroyed soon; discard the raw-pointer
99         taskImpl.DiscardSceneObject();
100       }
101
102       mTasks.erase( iter );
103
104       for ( Vector< Exclusive >::Iterator exclusiveIt = mExclusives.Begin(); exclusiveIt != mExclusives.End(); ++exclusiveIt )
105       {
106         if ( exclusiveIt->renderTaskPtr == &taskImpl )
107         {
108           mExclusives.Erase( exclusiveIt );
109           break;
110         }
111       }
112       break; // we're finished
113     }
114   }
115 }
116
117 uint32_t RenderTaskList::GetTaskCount() const
118 {
119   return static_cast<uint32_t>( mTasks.size() ); // only 4,294,967,295 render tasks supported
120 }
121
122 Dali::RenderTask RenderTaskList::GetTask( uint32_t index ) const
123 {
124   DALI_ASSERT_ALWAYS( ( index < mTasks.size() ) && "RenderTask index out-of-range" );
125
126   return mTasks[index];
127 }
128
129 void RenderTaskList::SetExclusive( RenderTask* task, bool exclusive )
130 {
131   // Check to see if this rendertask has an entry?
132   for ( Vector< Exclusive >::Iterator exclusiveIt = mExclusives.Begin(); exclusiveIt != mExclusives.End(); ++exclusiveIt )
133   {
134     if ( exclusiveIt->renderTaskPtr == task )
135     {
136       if ( !exclusive )
137       {
138         mExclusives.Erase( exclusiveIt );
139         break;
140       }
141       else
142       {
143         exclusiveIt->actorPtr = task->GetSourceActor();
144         exclusive = false;
145         break;
146       }
147     }
148   }
149   if ( exclusive )
150   {
151     Exclusive exclusiveSlot;
152     exclusiveSlot.renderTaskPtr = task;
153     exclusiveSlot.actorPtr = task->GetSourceActor();
154     mExclusives.PushBack( exclusiveSlot );
155   }
156 }
157
158 RenderTaskList::RenderTaskList()
159 : mEventThreadServices( *Stage::GetCurrent() ),
160   mDefaults( *Stage::GetCurrent() ),
161   mSceneObject( NULL )
162 {
163 }
164
165 RenderTaskList::~RenderTaskList()
166 {
167   if( EventThreadServices::IsCoreRunning() )
168   {
169     DestroySceneObject();
170   }
171 }
172
173 void RenderTaskList::Initialize()
174 {
175   // This should only be called once, with no existing scene-object
176   DALI_ASSERT_DEBUG( NULL == mSceneObject );
177
178   CreateSceneObject();
179
180   // set the callback to call us back when tasks are completed
181   mSceneObject->SetCompleteNotificationInterface( this );
182 }
183
184 void RenderTaskList::CreateSceneObject()
185 {
186   DALI_ASSERT_DEBUG( mSceneObject == NULL );
187
188   // Create a new render task list, Keep a const pointer to the render task list.
189   mSceneObject = SceneGraph::RenderTaskList::New();
190
191   OwnerPointer< SceneGraph::RenderTaskList > transferOwnership( const_cast< SceneGraph::RenderTaskList* >( mSceneObject ) );
192   AddRenderTaskListMessage( mEventThreadServices.GetUpdateManager(), transferOwnership );
193 }
194
195 void RenderTaskList::DestroySceneObject()
196 {
197   if ( mSceneObject != NULL )
198   {
199     // Remove the render task list using a message to the update manager
200     RemoveRenderTaskListMessage( mEventThreadServices.GetUpdateManager(), *mSceneObject );
201     mSceneObject = NULL;
202   }
203 }
204
205 void RenderTaskList::NotifyCompleted()
206 {
207   DALI_LOG_TRACE_METHOD(gLogRenderList);
208
209   std::vector< Dali::RenderTask > finishedRenderTasks;
210
211   // Since render tasks can be unreferenced during the signal emissions, iterators into render tasks pointers may be invalidated.
212   // First copy the finished render tasks, then emit signals
213   for ( std::vector<Dali::RenderTask>::iterator it = mTasks.begin(), endIt = mTasks.end(); it != endIt; ++it )
214   {
215     Dali::RenderTask& renderTask( *it );
216
217     if( GetImplementation( renderTask ).HasFinished() )
218     {
219       finishedRenderTasks.push_back( Dali::RenderTask( renderTask ) );
220     }
221   }
222
223   // Now it's safe to emit the signals
224   for ( std::vector<Dali::RenderTask>::iterator it = finishedRenderTasks.begin(), endIt = finishedRenderTasks.end(); it != endIt; ++it )
225   {
226     Dali::RenderTask& handle( *it );
227
228     GetImplementation(handle).EmitSignalFinish();
229   }
230 }
231
232 void RenderTaskList::RecoverFromContextLoss()
233 {
234   for ( RenderTaskContainer::iterator iter = mTasks.begin(); mTasks.end() != iter; ++iter )
235   {
236     Dali::RenderTask task = *iter;
237
238     // If the render target renders only once to an offscreen, re-render the render task
239     if( task.GetRefreshRate() == Dali::RenderTask::REFRESH_ONCE && task.GetTargetFrameBuffer() )
240     {
241       task.SetRefreshRate( Dali::RenderTask::REFRESH_ONCE );
242     }
243   }
244 }
245
246 } // namespace Internal
247
248 } // namespace Dali