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