Merge "Added signal to inform when an Actor's children have changed order" into devel...
[platform/core/uifw/dali-core.git] / dali / internal / update / render-tasks / scene-graph-render-task.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/update/render-tasks/scene-graph-render-task.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/public-api/math/matrix.h>
23 #include <dali/internal/update/controllers/render-message-dispatcher.h>
24 #include <dali/internal/update/nodes/node.h>
25 #include <dali/internal/render/common/render-instruction.h>
26 #include <dali/internal/render/common/render-tracker.h>
27
28 #include <dali/internal/update/render-tasks/scene-graph-render-task-debug.h>
29
30 namespace Dali
31 {
32 namespace Internal
33 {
34
35 namespace SceneGraph
36 {
37
38 RenderTask* RenderTask::New()
39 {
40   return new RenderTask();
41 }
42
43 RenderTask::~RenderTask()
44 {
45   // Remove exclusive flag from source node
46   if( mExclusive )
47   {
48     if( mSourceNode && (this == mSourceNode->GetExclusiveRenderTask() ) )
49     {
50       mSourceNode->SetExclusiveRenderTask( NULL );
51     }
52   }
53   if( mRenderSyncTracker )
54   {
55     mRenderMessageDispatcher->RemoveRenderTracker( *mRenderSyncTracker );
56   }
57 }
58
59 void RenderTask::Initialize( RenderMessageDispatcher& renderMessageDispatcher )
60 {
61   mRenderMessageDispatcher = &renderMessageDispatcher;
62 }
63
64 void RenderTask::SetSourceNode( Node* node )
65 {
66   // Remove exclusive flag from the old node, if necessary
67   if ( mSourceNode &&
68        this == mSourceNode->GetExclusiveRenderTask() )
69   {
70     mSourceNode->SetExclusiveRenderTask( NULL );
71   }
72
73   mSourceNode = node;
74
75   if ( mSourceNode && mExclusive )
76   {
77     mSourceNode->SetExclusiveRenderTask( this );
78   }
79 }
80
81 Node* RenderTask::GetSourceNode() const
82 {
83   return mSourceNode;
84 }
85
86 void RenderTask::SetExclusive( bool exclusive )
87 {
88   mExclusive = exclusive;
89
90   if ( mSourceNode )
91   {
92     if ( mExclusive )
93     {
94       mSourceNode->SetExclusiveRenderTask( this );
95     }
96     else if ( this == mSourceNode->GetExclusiveRenderTask() )
97     {
98       mSourceNode->SetExclusiveRenderTask( NULL );
99     }
100   }
101 }
102
103 bool RenderTask::IsExclusive() const
104 {
105   return mExclusive;
106 }
107
108 void RenderTask::SetCamera( Node* cameraNode, Camera* camera )
109 {
110   mCameraNode = cameraNode;
111   mCamera = camera;
112 }
113
114 void RenderTask::SetFrameBuffer( Render::FrameBuffer* frameBuffer )
115 {
116   mFrameBuffer = frameBuffer;
117 }
118
119 Render::FrameBuffer* RenderTask::GetFrameBuffer()
120 {
121   return mFrameBuffer;
122 }
123
124 bool RenderTask::QueryViewport( BufferIndex bufferIndex, Viewport& viewport ) const
125 {
126   if( ! GetViewportEnabled( bufferIndex ) )
127   {
128     return false;
129   }
130
131   viewport.x = mViewportPosition[bufferIndex].x;
132   viewport.y = mViewportPosition[bufferIndex].y;
133   viewport.width = mViewportSize[bufferIndex].width;
134   viewport.height = mViewportSize[bufferIndex].height;
135
136   return true;
137 }
138
139 void RenderTask::SetClearColor( BufferIndex updateBufferIndex, const Vector4& value )
140 {
141   mClearColor.Set( updateBufferIndex, value );
142 }
143
144 const Vector4& RenderTask::GetClearColor( BufferIndex bufferIndex ) const
145 {
146   return mClearColor[bufferIndex];
147 }
148
149 void RenderTask::BakeClearColor( BufferIndex updateBufferIndex, const Vector4& value )
150 {
151   mClearColor.Bake( updateBufferIndex, value );
152 }
153
154 void RenderTask::SetClearEnabled( bool enabled )
155 {
156   mClearEnabled = enabled;
157 }
158
159 bool RenderTask::GetClearEnabled() const
160 {
161   return mClearEnabled;
162 }
163
164 void RenderTask::SetCullMode( bool mode )
165 {
166   mCullMode = mode;
167 }
168
169 bool RenderTask::GetCullMode() const
170 {
171   return mCullMode;
172 }
173
174 void RenderTask::SetRefreshRate( unsigned int refreshRate )
175 {
176   DALI_LOG_TRACE_METHOD_FMT(gRenderTaskLogFilter, "this:%p RefreshRate:%d\n", this, refreshRate);
177
178   mRefreshRate = refreshRate;
179
180   if( mRefreshRate > 0 )
181   {
182     mState = RENDER_CONTINUOUSLY;
183   }
184   else
185   {
186     mState = RENDER_ONCE_WAITING_FOR_RESOURCES;
187     mWaitingToRender = true;
188     mNotifyTrigger = false;
189   }
190
191   mFrameCounter = 0u;
192 }
193
194 unsigned int RenderTask::GetRefreshRate() const
195 {
196   return mRefreshRate;
197 }
198
199 bool RenderTask::ReadyToRender( BufferIndex updateBufferIndex )
200 {
201   // If the source node of the render task is invisible we should still render
202   // We want the render task to complete and possible clear colors to happen
203
204   // Check the source node.
205   if( NULL == mSourceNode ||
206       ( !mSourceNode->IsRoot() && NULL == mSourceNode->GetParent() ) )
207   {
208     TASK_LOG_FMT( Debug::General, " Source actor not on stage.  Frame counter: %d\n", mFrameCounter );
209
210     // The source node is missing or disconnected.
211     return false;
212   }
213
214   // Check camera node
215   if( NULL == mCameraNode ||
216       NULL == mCameraNode->GetParent() ||
217       NULL == mCamera )
218   {
219     // The camera node is missing or disconnected.
220     TASK_LOG_FMT(Debug::General, " =F  No Camera  FC:%d\n", mFrameCounter );
221     return false;
222   }
223
224   return true;
225 }
226
227 bool RenderTask::IsRenderRequired()
228 {
229   bool required = false;
230
231   switch( mState )
232   {
233     case RENDER_CONTINUOUSLY:
234     {
235       required = (mFrameCounter == 0);
236       break;
237     }
238     case RENDER_ONCE_WAITING_FOR_RESOURCES:
239     {
240       required = true;
241       break;
242     }
243     default:
244     {
245       required = false;
246       break;
247     }
248   }
249
250   TASK_LOG_FMT( Debug::General, " State:%s = %s\n", STATE_STRING(mState), required?"T":"F" );
251
252   return required;
253 }
254
255 // Called every frame regardless of whether render was required.
256 // If render was not required, ignore resourcesFinished.
257 void RenderTask::UpdateState()
258 {
259   TASK_LOG_FMT( Debug::General, "FC:%d State:%s RR:%d\n", mFrameCounter, STATE_STRING(mState), mRefreshRate );
260
261   switch( mState )
262   {
263     case RENDER_CONTINUOUSLY:
264     {
265       if( mRefreshRate != Dali::RenderTask::REFRESH_ALWAYS )
266       {
267         if( mFrameCounter == 0 )
268         {
269           ++mFrameCounter; // Only start skipping frames when resources are loaded
270         }
271         else // Continue counting to skip frames
272         {
273           ++mFrameCounter;
274           if( mFrameCounter >= mRefreshRate )
275           {
276             mFrameCounter = 0;
277           }
278         }
279       }
280       // else do nothing
281     }
282     break;
283
284     case RENDER_ONCE_WAITING_FOR_RESOURCES:
285     {
286       mState = RENDERED_ONCE;
287     }
288     break;
289
290     case RENDERED_ONCE:
291     {
292       mWaitingToRender = true;
293       mNotifyTrigger = false;
294       if( mFrameBuffer )
295       {
296         if( !mRenderSyncTracker || (mRenderSyncTracker && mRenderSyncTracker->IsSynced() ))
297         {
298           mWaitingToRender = false;
299           mNotifyTrigger = true;
300         }
301       }
302       else
303       {
304         mWaitingToRender = false;
305         mNotifyTrigger = true;
306       }
307     }
308
309     break;
310
311     default:
312       break;
313   }
314
315   TASK_LOG_FMT( Debug::General, " EXIT FC:%d State:%s Notify:%s\n", mFrameCounter, STATE_STRING(mState), mNotifyTrigger?"T":"F");
316 }
317
318 bool RenderTask::IsWaitingToRender()
319 {
320   TASK_LOG_FMT(Debug::Verbose, " State:%s waiting:%s \n", STATE_STRING(mState), mWaitingToRender?"T":"F");
321   return mWaitingToRender;
322 }
323
324 bool RenderTask::HasRendered()
325 {
326   bool notify = false;
327   if( mNotifyTrigger == true )
328   {
329     ++mRenderedOnceCounter;
330     mState = RENDERED_ONCE_AND_NOTIFIED;
331     mNotifyTrigger = false;
332     notify = true;
333   }
334
335   TASK_LOG_FMT(Debug::Verbose, " State:%s hasRendered:%s \n", STATE_STRING(mState), notify?"T":"F");
336   return notify;
337 }
338
339 unsigned int RenderTask::GetRenderedOnceCounter() const
340 {
341   return mRenderedOnceCounter;
342 }
343
344
345 const Matrix& RenderTask::GetViewMatrix( BufferIndex bufferIndex ) const
346 {
347   DALI_ASSERT_DEBUG( NULL != mCamera );
348
349   return mCamera->GetViewMatrix( bufferIndex );
350 }
351
352 SceneGraph::Camera& RenderTask::GetCamera() const
353 {
354   DALI_ASSERT_DEBUG( NULL != mCamera );
355   return *mCamera;
356 }
357
358 const Matrix& RenderTask::GetProjectionMatrix( BufferIndex bufferIndex ) const
359 {
360   DALI_ASSERT_DEBUG( NULL != mCamera );
361
362   return mCamera->GetProjectionMatrix( bufferIndex );
363 }
364
365 void RenderTask::PrepareRenderInstruction( RenderInstruction& instruction, BufferIndex updateBufferIndex )
366 {
367   DALI_ASSERT_DEBUG( NULL != mCamera );
368
369   TASK_LOG(Debug::General);
370
371   Viewport viewport;
372   bool viewportSet = QueryViewport( updateBufferIndex, viewport );
373
374   instruction.Reset( mCamera,
375                      GetFrameBuffer(),
376                      viewportSet ? &viewport : NULL,
377                      mClearEnabled ? &GetClearColor( updateBufferIndex ) : NULL );
378
379   if( mRequiresSync &&
380       mRefreshRate == Dali::RenderTask::REFRESH_ONCE )
381   {
382     // create tracker if one doesn't yet exist.
383     if( !mRenderSyncTracker )
384     {
385       mRenderSyncTracker = new Render::RenderTracker();
386       mRenderMessageDispatcher->AddRenderTracker( *mRenderSyncTracker );
387     }
388     instruction.mRenderTracker = mRenderSyncTracker;
389   }
390   else
391   {
392     // no sync needed, texture FBOs are "ready" the same frame they are rendered to
393     instruction.mRenderTracker = NULL;
394   }
395 }
396
397 bool RenderTask::ViewMatrixUpdated()
398 {
399   bool retval = false;
400   if( mCamera )
401   {
402     retval = mCamera->ViewMatrixUpdated();
403   }
404   return retval;
405 }
406
407 void RenderTask::SetViewportPosition( BufferIndex updateBufferIndex, const Vector2& value )
408 {
409   mViewportPosition.Set( updateBufferIndex, value );
410 }
411
412 const Vector2& RenderTask::GetViewportPosition( BufferIndex bufferIndex ) const
413 {
414   return mViewportPosition[bufferIndex];
415 }
416
417 void RenderTask::BakeViewportPosition( BufferIndex updateBufferIndex, const Vector2& value )
418 {
419   mViewportPosition.Bake( updateBufferIndex, value );
420 }
421
422 void RenderTask::SetViewportSize( BufferIndex updateBufferIndex, const Vector2& value )
423 {
424   mViewportSize.Set( updateBufferIndex, value );
425 }
426
427 const Vector2& RenderTask::GetViewportSize( BufferIndex bufferIndex ) const
428 {
429   return mViewportSize[bufferIndex];
430 }
431
432 void RenderTask::BakeViewportSize( BufferIndex updateBufferIndex, const Vector2& value )
433 {
434   mViewportSize.Bake( updateBufferIndex, value );
435 }
436
437 bool RenderTask::GetViewportEnabled( BufferIndex bufferIndex ) const
438 {
439   if(fabsf(mViewportPosition[bufferIndex].x) > Math::MACHINE_EPSILON_1 ||
440      fabsf(mViewportPosition[bufferIndex].y) > Math::MACHINE_EPSILON_1 ||
441      fabsf(mViewportSize[bufferIndex].width) > Math::MACHINE_EPSILON_1 ||
442      fabsf(mViewportSize[bufferIndex].height) > Math::MACHINE_EPSILON_1)
443   {
444     return true;
445   }
446
447   return false;
448 }
449
450 void RenderTask::SetSyncRequired( bool requiresSync )
451 {
452   mRequiresSync = requiresSync;
453 }
454
455
456 RenderTask::RenderTask()
457 : mViewportPosition( Vector2::ZERO),
458   mViewportSize( Vector2::ZERO),
459   mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
460   mRenderMessageDispatcher( NULL ),
461   mRenderSyncTracker( NULL ),
462   mSourceNode( NULL ),
463   mCameraNode( NULL ),
464   mCamera( NULL ),
465   mFrameBuffer(0),
466   mWaitingToRender( false ),
467   mNotifyTrigger( false ),
468   mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
469   mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
470   mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE ),
471   mState( (Dali::RenderTask::DEFAULT_REFRESH_RATE == Dali::RenderTask::REFRESH_ALWAYS)
472           ? RENDER_CONTINUOUSLY
473           : RENDER_ONCE_WAITING_FOR_RESOURCES ),
474   mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
475   mFrameCounter( 0u ),
476   mRenderedOnceCounter( 0u ),
477   mRequiresSync( false )
478 {
479 }
480
481 } // namespace SceneGraph
482
483 } // namespace Internal
484
485 } // namespace Dali