Revert "License conversion from Flora to Apache 2.0"
[platform/core/uifw/dali-core.git] / dali / internal / update / render-tasks / scene-graph-render-task.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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 // CLASS HEADER
18 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
19
20 // INTERNAL INCLUDES
21 #include <dali/public-api/math/matrix.h>
22 #include <dali/internal/update/resources/resource-manager.h>
23 #include <dali/internal/update/resources/complete-status-manager.h>
24 #include <dali/internal/update/nodes/node.h>
25 #include <dali/internal/update/node-attachments/scene-graph-camera-attachment.h>
26 #include <dali/internal/render/common/render-instruction.h>
27
28 #include <dali/internal/update/render-tasks/scene-graph-render-task-debug.h>
29
30 namespace
31 {
32 const unsigned int NUM_FRAMES_BEFORE_NOTIFY_FINISHED(3);
33 const unsigned int COUNTDOWN_COMPLETE(-1);
34 } // anonymous namespace
35
36 namespace Dali
37 {
38 namespace Internal
39 {
40
41 namespace SceneGraph
42 {
43
44 RenderTask* RenderTask::New()
45 {
46   return new RenderTask();
47 }
48
49 RenderTask::~RenderTask()
50 {
51   // Remove exclusive flag from source node
52   if( mExclusive )
53   {
54     if( mSourceNode && (this == mSourceNode->GetExclusiveRenderTask() ) )
55     {
56       mSourceNode->SetExclusiveRenderTask( NULL );
57     }
58   }
59   if( mFrameBufferResourceId )
60   {
61     mCompleteStatusManager->StopTrackingResource( mFrameBufferResourceId );
62   }
63 }
64
65 void RenderTask::SetSourceNode( Node* node )
66 {
67   // Remove exclusive flag from the old node, if necessary
68   if ( mSourceNode &&
69        this == mSourceNode->GetExclusiveRenderTask() )
70   {
71     mSourceNode->SetExclusiveRenderTask( NULL );
72   }
73
74   mSourceNode = node;
75
76   if ( mSourceNode && mExclusive )
77   {
78     mSourceNode->SetExclusiveRenderTask( this );
79   }
80 }
81
82 Node* RenderTask::GetSourceNode() const
83 {
84   return mSourceNode;
85 }
86
87 void RenderTask::SetExclusive( bool exclusive )
88 {
89   mExclusive = exclusive;
90
91   if ( mSourceNode )
92   {
93     if ( mExclusive )
94     {
95       mSourceNode->SetExclusiveRenderTask( this );
96     }
97     else if ( this == mSourceNode->GetExclusiveRenderTask() )
98     {
99       mSourceNode->SetExclusiveRenderTask( NULL );
100     }
101   }
102 }
103
104 bool RenderTask::IsExclusive() const
105 {
106   return mExclusive;
107 }
108
109 void RenderTask::SetCameraNode( Node* cameraNode )
110 {
111   // if camera changed
112   if( cameraNode != mCameraNode )
113   {
114     if( cameraNode )
115     {
116       // get attachment. when camera node is changed we will get a message from event thread object
117       // so no need to observe the node here
118       mCameraAttachment = dynamic_cast< CameraAttachment* >( &cameraNode->GetAttachment() );
119       DALI_ASSERT_DEBUG( mCameraAttachment && "Camera without attachment" );
120     }
121     mCameraNode = cameraNode;
122   }
123 }
124
125 Node* RenderTask::GetCameraNode() const
126 {
127   return mCameraNode;
128 }
129
130 void RenderTask::SetFrameBufferId( unsigned int resourceId )
131 {
132   if ( mFrameBufferResourceId != resourceId )
133   {
134     DALI_ASSERT_DEBUG(mCompleteStatusManager && "Complete status tracker is null");
135     if( mCompleteStatusManager )
136     {
137       if( resourceId && mState == RENDER_ONCE_WAITING_FOR_RESOURCES )
138       {
139         mCompleteStatusManager->TrackResource( resourceId );
140       }
141
142       if( mFrameBufferResourceId )
143       {
144         mCompleteStatusManager->StopTrackingResource( mFrameBufferResourceId );
145       }
146     }
147
148     mFrameBufferResourceId = resourceId;
149   }
150 }
151
152 unsigned int RenderTask::GetFrameBufferId() const
153 {
154   return mFrameBufferResourceId;
155 }
156
157 bool RenderTask::QueryViewport( BufferIndex bufferIndex, Viewport& viewport ) const
158 {
159   if( ! GetViewportEnabled( bufferIndex ) )
160   {
161     return false;
162   }
163
164   viewport.x = mViewportPosition[bufferIndex].x;
165   viewport.y = mViewportPosition[bufferIndex].y;
166   viewport.width = mViewportSize[bufferIndex].width;
167   viewport.height = mViewportSize[bufferIndex].height;
168
169   return true;
170 }
171
172 void RenderTask::SetClearColor( BufferIndex updateBufferIndex, const Vector4& value )
173 {
174   mClearColor.Set( updateBufferIndex, value );
175 }
176
177 const Vector4& RenderTask::GetClearColor( BufferIndex bufferIndex ) const
178 {
179   return mClearColor[bufferIndex];
180 }
181
182 void RenderTask::BakeClearColor( BufferIndex updateBufferIndex, const Vector4& value )
183 {
184   mClearColor.Bake( updateBufferIndex, value );
185 }
186
187 void RenderTask::SetClearEnabled( bool enabled )
188 {
189   mClearEnabled = enabled;
190 }
191
192 bool RenderTask::GetClearEnabled() const
193 {
194   return mClearEnabled;
195 }
196
197 void RenderTask::SetRefreshRate( unsigned int refreshRate )
198 {
199   DALI_LOG_TRACE_METHOD_FMT(gRenderTaskLogFilter, "this:%p RefreshRate:%d\n", this, refreshRate);
200
201   mRefreshRate = refreshRate;
202
203   if( mRefreshRate > 0 )
204   {
205     mState = RENDER_CONTINUOUSLY;
206
207     if( mFrameBufferResourceId )
208     {
209       // Don't need tracking
210       DALI_ASSERT_DEBUG(mCompleteStatusManager && "Ready state tracker is null");
211       if( mCompleteStatusManager != NULL )
212       {
213         mCompleteStatusManager->StopTrackingResource( mFrameBufferResourceId );
214       }
215     }
216   }
217   else
218   {
219     mState = RENDER_ONCE_WAITING_FOR_RESOURCES;
220     mWaitingToRender = true;
221     mNotifyTrigger = false;
222
223     if( mFrameBufferResourceId )
224     {
225       DALI_ASSERT_DEBUG(mCompleteStatusManager && "Ready state tracker is null");
226       if( mCompleteStatusManager != NULL )
227       {
228         mCompleteStatusManager->TrackResource( mFrameBufferResourceId );
229       }
230     }
231   }
232
233   mFrameCounter = 0u;
234 }
235
236 unsigned int RenderTask::GetRefreshRate() const
237 {
238   return mRefreshRate;
239 }
240
241 bool RenderTask::ReadyToRender( BufferIndex updateBufferIndex )
242 {
243   if ( NULL == mSourceNode ||
244        ( !mSourceNode->IsRoot() && NULL == mSourceNode->GetParent() ) )
245   {
246     TASK_LOG_FMT(Debug::General, " =F  No source actor  FC:%d\n", mFrameCounter );
247
248     // Source node is missing or disconnected
249     return false;
250   }
251
252   // Check if the source node (root actor) and all its ancestors are visible.
253   if( !mSourceNode->IsFullyVisible( updateBufferIndex ) )
254   {
255     TASK_LOG_FMT(Debug::General, " =F  No visible source  FC:%d\n", mFrameCounter );
256     return false;
257   }
258
259   if ( NULL == mCameraNode ||
260        NULL == mCameraNode->GetParent() ||
261        !mCameraNode->HasAttachment() )
262   {
263     // Camera node is missing or disconnected
264     TASK_LOG_FMT(Debug::General, " =F  No Camera  FC:%d\n", mFrameCounter );
265
266     return false;
267   }
268
269   TASK_LOG_FMT(Debug::General, " =T (FBO ID:%d) FC:%d\n", mFrameBufferResourceId , mFrameCounter );
270   return true;
271 }
272
273 bool RenderTask::IsRenderRequired()
274 {
275   bool required = false;
276
277   switch( mState )
278   {
279     case RENDER_CONTINUOUSLY:
280       required = (mFrameCounter == 0);
281       break;
282
283     case RENDER_ONCE_WAITING_FOR_RESOURCES:
284       required = true;
285       break;
286
287     default:
288       required = false;
289       break;
290   }
291
292   TASK_LOG_FMT( Debug::General, " State:%s = %s\n", STATE_STRING(mState), required?"T":"F" );
293
294   return required;
295 }
296
297 // Called every frame regardless of whether render was required.
298 // If render was not required, ignore resourcesFinished.
299 void RenderTask::UpdateState(bool resourcesFinished)
300 {
301   TASK_LOG_FMT( Debug::General, "(resourcesFinished:%s)  FC:%d State:%s RR:%d\n", resourcesFinished?"T":"F", mFrameCounter, STATE_STRING(mState), mRefreshRate );
302
303   switch( mState )
304   {
305     case RENDER_CONTINUOUSLY:
306     {
307       if( mRefreshRate != Dali::RenderTask::REFRESH_ALWAYS )
308       {
309         if( mFrameCounter == 0 )
310         {
311           if( resourcesFinished )
312           {
313             ++mFrameCounter; // Only start missing frames when resources are loaded
314           }
315         }
316         else // Continue counting to miss frames
317         {
318           ++mFrameCounter;
319           if( mFrameCounter >= mRefreshRate )
320           {
321             mFrameCounter = 0;
322           }
323         }
324       }
325       // else do nothing
326     }
327     break;
328
329     case RENDER_ONCE_WAITING_FOR_RESOURCES:
330     {
331       if( resourcesFinished )
332       {
333         mState = RENDERED_ONCE;
334       }
335     }
336     break;
337
338     case RENDERED_ONCE:
339     {
340       if( mFrameBufferResourceId > 0 )
341       {
342         // Query if the framebuffer is complete:
343         DALI_ASSERT_DEBUG(mCompleteStatusManager && "Complete status tracker is null");
344         if( mCompleteStatusManager != NULL &&
345             CompleteStatusManager::COMPLETE == mCompleteStatusManager->GetStatus( mFrameBufferResourceId ) )
346         {
347           mWaitingToRender = false;
348           mNotifyTrigger = true;
349         }
350         else
351         {
352           mWaitingToRender = true;
353         }
354       }
355       else
356       {
357         mWaitingToRender = false;
358         mNotifyTrigger = true;
359       }
360     }
361     break;
362
363     default:
364       break;
365   }
366
367   TASK_LOG_FMT( Debug::General, " EXIT FC:%d State:%s Notify:%s\n", mFrameCounter, STATE_STRING(mState), mNotifyTrigger?"T":"F");
368 }
369
370 bool RenderTask::IsWaitingToRender()
371 {
372   TASK_LOG_FMT(Debug::Verbose, " State:%s waiting:%s \n", STATE_STRING(mState), mWaitingToRender?"T":"F");
373   return mWaitingToRender;
374 }
375
376 bool RenderTask::HasRendered()
377 {
378   bool notify = false;
379   if( mNotifyTrigger == true )
380   {
381     ++mRenderedOnceCounter;
382     mState = RENDERED_ONCE_AND_NOTIFIED;
383     mNotifyTrigger = false;
384     notify = true;
385   }
386
387   TASK_LOG_FMT(Debug::Verbose, " State:%s hasRendered:%s \n", STATE_STRING(mState), notify?"T":"F");
388   return notify;
389 }
390
391 unsigned int RenderTask::GetRenderedOnceCounter() const
392 {
393   return mRenderedOnceCounter;
394 }
395
396
397 const Matrix& RenderTask::GetViewMatrix( BufferIndex bufferIndex ) const
398 {
399   DALI_ASSERT_DEBUG( NULL != mCameraAttachment );
400
401   return mCameraAttachment->GetViewMatrix( bufferIndex );
402 }
403
404 const Matrix& RenderTask::GetProjectionMatrix( BufferIndex bufferIndex ) const
405 {
406   DALI_ASSERT_DEBUG( NULL != mCameraAttachment );
407
408   return mCameraAttachment->GetProjectionMatrix( bufferIndex );
409 }
410
411 void RenderTask::PrepareRenderInstruction( RenderInstruction& instruction, BufferIndex updateBufferIndex )
412 {
413   TASK_LOG(Debug::General);
414
415   Viewport viewport;
416   bool viewportSet = QueryViewport( updateBufferIndex, viewport );
417
418   instruction.Reset( &GetViewMatrix( updateBufferIndex ),
419                      &GetProjectionMatrix( updateBufferIndex ),
420                      GetFrameBufferId(),
421                      viewportSet ? &viewport : NULL,
422                      mClearEnabled ? &GetClearColor( updateBufferIndex ) : NULL );
423 }
424
425 bool RenderTask::ViewMatrixUpdated()
426 {
427   bool retval = false;
428   if( mCameraAttachment )
429   {
430     retval = mCameraAttachment->ViewMatrixUpdated();
431   }
432   return retval;
433 }
434
435 void RenderTask::SetCompleteStatusManager(CompleteStatusManager* completeStatusManager)
436 {
437   mCompleteStatusManager = completeStatusManager;
438 }
439
440 void RenderTask::SetViewportPosition( BufferIndex updateBufferIndex, const Vector2& value )
441 {
442   mViewportPosition.Set( updateBufferIndex, value );
443 }
444
445 const Vector2& RenderTask::GetViewportPosition( BufferIndex bufferIndex ) const
446 {
447   return mViewportPosition[bufferIndex];
448 }
449
450 void RenderTask::BakeViewportPosition( BufferIndex updateBufferIndex, const Vector2& value )
451 {
452   mViewportPosition.Bake( updateBufferIndex, value );
453 }
454
455 void RenderTask::SetViewportSize( BufferIndex updateBufferIndex, const Vector2& value )
456 {
457   mViewportSize.Set( updateBufferIndex, value );
458 }
459
460 const Vector2& RenderTask::GetViewportSize( BufferIndex bufferIndex ) const
461 {
462   return mViewportSize[bufferIndex];
463 }
464
465 void RenderTask::BakeViewportSize( BufferIndex updateBufferIndex, const Vector2& value )
466 {
467   mViewportSize.Bake( updateBufferIndex, value );
468 }
469
470 bool RenderTask::GetViewportEnabled( BufferIndex bufferIndex ) const
471 {
472   if(fabsf(mViewportPosition[bufferIndex].x) > Math::MACHINE_EPSILON_1 ||
473      fabsf(mViewportPosition[bufferIndex].y) > Math::MACHINE_EPSILON_1 ||
474      fabsf(mViewportSize[bufferIndex].width) > Math::MACHINE_EPSILON_1 ||
475      fabsf(mViewportSize[bufferIndex].height) > Math::MACHINE_EPSILON_1)
476   {
477     return true;
478   }
479
480   return false;
481 }
482
483 void RenderTask::ResetDefaultProperties( BufferIndex updateBufferIndex )
484 {
485   // Reset default properties
486   mViewportPosition.ResetToBaseValue( updateBufferIndex );
487   mViewportSize.ResetToBaseValue( updateBufferIndex );
488   mClearColor.ResetToBaseValue( updateBufferIndex );
489 }
490
491 RenderTask::RenderTask()
492 : mViewportPosition( Vector2::ZERO),
493   mViewportSize( Vector2::ZERO),
494   mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
495   mCompleteStatusManager( NULL ),
496   mSourceNode( NULL ),
497   mCameraNode( NULL ),
498   mCameraAttachment( NULL ),
499   mFrameBufferResourceId( 0 ),
500   mWaitingToRender( false ),
501   mNotifyTrigger( false ),
502   mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
503   mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
504   mRenderTarget( NULL ),
505   mState( (Dali::RenderTask::DEFAULT_REFRESH_RATE == Dali::RenderTask::REFRESH_ALWAYS)
506           ? RENDER_CONTINUOUSLY
507           : RENDER_ONCE_WAITING_FOR_RESOURCES ),
508   mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
509   mFrameCounter( 0u ),
510   mRenderedOnceCounter( 0u )
511 {
512 }
513
514 } // namespace SceneGraph
515
516 } // namespace Internal
517
518 } // namespace Dali