27acf09c516249ccff5ea6a2347bf816ca621fb2
[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 void RenderTask::SetFrameBufferId( unsigned int resourceId )
127 {
128   if ( mFrameBufferResourceId != resourceId )
129   {
130     DALI_ASSERT_DEBUG(mCompleteStatusManager && "Complete status tracker is null");
131     if( mCompleteStatusManager )
132     {
133       if( resourceId && mState == RENDER_ONCE_WAITING_FOR_RESOURCES )
134       {
135         mCompleteStatusManager->TrackResource( resourceId );
136       }
137
138       if( mFrameBufferResourceId )
139       {
140         mCompleteStatusManager->StopTrackingResource( mFrameBufferResourceId );
141       }
142     }
143
144     mFrameBufferResourceId = resourceId;
145   }
146 }
147
148 unsigned int RenderTask::GetFrameBufferId() const
149 {
150   return mFrameBufferResourceId;
151 }
152
153 bool RenderTask::QueryViewport( BufferIndex bufferIndex, Viewport& viewport ) const
154 {
155   if( ! GetViewportEnabled( bufferIndex ) )
156   {
157     return false;
158   }
159
160   viewport.x = mViewportPosition[bufferIndex].x;
161   viewport.y = mViewportPosition[bufferIndex].y;
162   viewport.width = mViewportSize[bufferIndex].width;
163   viewport.height = mViewportSize[bufferIndex].height;
164
165   return true;
166 }
167
168 void RenderTask::SetClearColor( BufferIndex updateBufferIndex, const Vector4& value )
169 {
170   mClearColor.Set( updateBufferIndex, value );
171 }
172
173 const Vector4& RenderTask::GetClearColor( BufferIndex bufferIndex ) const
174 {
175   return mClearColor[bufferIndex];
176 }
177
178 void RenderTask::BakeClearColor( BufferIndex updateBufferIndex, const Vector4& value )
179 {
180   mClearColor.Bake( updateBufferIndex, value );
181 }
182
183 void RenderTask::SetClearEnabled( bool enabled )
184 {
185   mClearEnabled = enabled;
186 }
187
188 bool RenderTask::GetClearEnabled() const
189 {
190   return mClearEnabled;
191 }
192
193 void RenderTask::SetCullMode( bool mode )
194 {
195   mCullMode = mode;
196 }
197
198 bool RenderTask::GetCullMode() const
199 {
200   return mCullMode;
201 }
202
203 void RenderTask::SetRefreshRate( unsigned int refreshRate )
204 {
205   DALI_LOG_TRACE_METHOD_FMT(gRenderTaskLogFilter, "this:%p RefreshRate:%d\n", this, refreshRate);
206
207   mRefreshRate = refreshRate;
208
209   if( mRefreshRate > 0 )
210   {
211     mState = RENDER_CONTINUOUSLY;
212
213     if( mFrameBufferResourceId )
214     {
215       // Don't need tracking
216       DALI_ASSERT_DEBUG(mCompleteStatusManager && "Ready state tracker is null");
217       if( mCompleteStatusManager != NULL )
218       {
219         mCompleteStatusManager->StopTrackingResource( mFrameBufferResourceId );
220       }
221     }
222   }
223   else
224   {
225     mState = RENDER_ONCE_WAITING_FOR_RESOURCES;
226     mWaitingToRender = true;
227     mNotifyTrigger = false;
228
229     if( mFrameBufferResourceId )
230     {
231       DALI_ASSERT_DEBUG(mCompleteStatusManager && "Ready state tracker is null");
232       if( mCompleteStatusManager != NULL )
233       {
234         mCompleteStatusManager->TrackResource( mFrameBufferResourceId );
235       }
236     }
237   }
238
239   mFrameCounter = 0u;
240 }
241
242 unsigned int RenderTask::GetRefreshRate() const
243 {
244   return mRefreshRate;
245 }
246
247 bool RenderTask::ReadyToRender( BufferIndex updateBufferIndex )
248 {
249   if ( NULL == mSourceNode ||
250        ( !mSourceNode->IsRoot() && NULL == mSourceNode->GetParent() ) )
251   {
252     TASK_LOG_FMT(Debug::General, " =F  No source actor  FC:%d\n", mFrameCounter );
253
254     // Source node is missing or disconnected
255     return false;
256   }
257
258   // Check if the source node (root actor) and all its ancestors are visible.
259   if( !mSourceNode->IsFullyVisible( updateBufferIndex ) )
260   {
261     TASK_LOG_FMT(Debug::General, " =F  No visible source  FC:%d\n", mFrameCounter );
262     return false;
263   }
264
265   if ( NULL == mCameraNode ||
266        NULL == mCameraNode->GetParent() ||
267        !mCameraNode->HasAttachment() )
268   {
269     // Camera node is missing or disconnected
270     TASK_LOG_FMT(Debug::General, " =F  No Camera  FC:%d\n", mFrameCounter );
271
272     return false;
273   }
274
275   TASK_LOG_FMT(Debug::General, " =T (FBO ID:%d) FC:%d\n", mFrameBufferResourceId , mFrameCounter );
276   return true;
277 }
278
279 bool RenderTask::IsRenderRequired()
280 {
281   bool required = false;
282
283   switch( mState )
284   {
285     case RENDER_CONTINUOUSLY:
286       required = (mFrameCounter == 0);
287       break;
288
289     case RENDER_ONCE_WAITING_FOR_RESOURCES:
290       required = true;
291       break;
292
293     default:
294       required = false;
295       break;
296   }
297
298   TASK_LOG_FMT( Debug::General, " State:%s = %s\n", STATE_STRING(mState), required?"T":"F" );
299
300   return required;
301 }
302
303 // Called every frame regardless of whether render was required.
304 // If render was not required, ignore resourcesFinished.
305 void RenderTask::UpdateState(bool resourcesFinished)
306 {
307   TASK_LOG_FMT( Debug::General, "(resourcesFinished:%s)  FC:%d State:%s RR:%d\n", resourcesFinished?"T":"F", mFrameCounter, STATE_STRING(mState), mRefreshRate );
308
309   switch( mState )
310   {
311     case RENDER_CONTINUOUSLY:
312     {
313       if( mRefreshRate != Dali::RenderTask::REFRESH_ALWAYS )
314       {
315         if( mFrameCounter == 0 )
316         {
317           if( resourcesFinished )
318           {
319             ++mFrameCounter; // Only start missing frames when resources are loaded
320           }
321         }
322         else // Continue counting to miss frames
323         {
324           ++mFrameCounter;
325           if( mFrameCounter >= mRefreshRate )
326           {
327             mFrameCounter = 0;
328           }
329         }
330       }
331       // else do nothing
332     }
333     break;
334
335     case RENDER_ONCE_WAITING_FOR_RESOURCES:
336     {
337       if( resourcesFinished )
338       {
339         mState = RENDERED_ONCE;
340       }
341     }
342     break;
343
344     case RENDERED_ONCE:
345     {
346       if( mFrameBufferResourceId > 0 )
347       {
348         // Query if the framebuffer is complete:
349         DALI_ASSERT_DEBUG(mCompleteStatusManager && "Complete status tracker is null");
350         if( mCompleteStatusManager != NULL &&
351             CompleteStatusManager::COMPLETE == mCompleteStatusManager->GetStatus( mFrameBufferResourceId ) )
352         {
353           mWaitingToRender = false;
354           mNotifyTrigger = true;
355         }
356         else
357         {
358           mWaitingToRender = true;
359         }
360       }
361       else
362       {
363         mWaitingToRender = false;
364         mNotifyTrigger = true;
365       }
366     }
367     break;
368
369     default:
370       break;
371   }
372
373   TASK_LOG_FMT( Debug::General, " EXIT FC:%d State:%s Notify:%s\n", mFrameCounter, STATE_STRING(mState), mNotifyTrigger?"T":"F");
374 }
375
376 bool RenderTask::IsWaitingToRender()
377 {
378   TASK_LOG_FMT(Debug::Verbose, " State:%s waiting:%s \n", STATE_STRING(mState), mWaitingToRender?"T":"F");
379   return mWaitingToRender;
380 }
381
382 bool RenderTask::HasRendered()
383 {
384   bool notify = false;
385   if( mNotifyTrigger == true )
386   {
387     ++mRenderedOnceCounter;
388     mState = RENDERED_ONCE_AND_NOTIFIED;
389     mNotifyTrigger = false;
390     notify = true;
391   }
392
393   TASK_LOG_FMT(Debug::Verbose, " State:%s hasRendered:%s \n", STATE_STRING(mState), notify?"T":"F");
394   return notify;
395 }
396
397 unsigned int RenderTask::GetRenderedOnceCounter() const
398 {
399   return mRenderedOnceCounter;
400 }
401
402
403 const Matrix& RenderTask::GetViewMatrix( BufferIndex bufferIndex ) const
404 {
405   DALI_ASSERT_DEBUG( NULL != mCameraAttachment );
406
407   return mCameraAttachment->GetViewMatrix( bufferIndex );
408 }
409
410 const Matrix& RenderTask::GetProjectionMatrix( BufferIndex bufferIndex ) const
411 {
412   DALI_ASSERT_DEBUG( NULL != mCameraAttachment );
413
414   return mCameraAttachment->GetProjectionMatrix( bufferIndex );
415 }
416
417 void RenderTask::PrepareRenderInstruction( RenderInstruction& instruction, BufferIndex updateBufferIndex )
418 {
419   DALI_ASSERT_DEBUG( NULL != mCameraAttachment );
420
421   TASK_LOG(Debug::General);
422
423   Viewport viewport;
424   bool viewportSet = QueryViewport( updateBufferIndex, viewport );
425
426   instruction.Reset( mCameraAttachment,
427                      GetFrameBufferId(),
428                      viewportSet ? &viewport : NULL,
429                      mClearEnabled ? &GetClearColor( updateBufferIndex ) : NULL );
430 }
431
432 bool RenderTask::ViewMatrixUpdated()
433 {
434   bool retval = false;
435   if( mCameraAttachment )
436   {
437     retval = mCameraAttachment->ViewMatrixUpdated();
438   }
439   return retval;
440 }
441
442 void RenderTask::SetCompleteStatusManager(CompleteStatusManager* completeStatusManager)
443 {
444   mCompleteStatusManager = completeStatusManager;
445 }
446
447 void RenderTask::SetViewportPosition( BufferIndex updateBufferIndex, const Vector2& value )
448 {
449   mViewportPosition.Set( updateBufferIndex, value );
450 }
451
452 const Vector2& RenderTask::GetViewportPosition( BufferIndex bufferIndex ) const
453 {
454   return mViewportPosition[bufferIndex];
455 }
456
457 void RenderTask::BakeViewportPosition( BufferIndex updateBufferIndex, const Vector2& value )
458 {
459   mViewportPosition.Bake( updateBufferIndex, value );
460 }
461
462 void RenderTask::SetViewportSize( BufferIndex updateBufferIndex, const Vector2& value )
463 {
464   mViewportSize.Set( updateBufferIndex, value );
465 }
466
467 const Vector2& RenderTask::GetViewportSize( BufferIndex bufferIndex ) const
468 {
469   return mViewportSize[bufferIndex];
470 }
471
472 void RenderTask::BakeViewportSize( BufferIndex updateBufferIndex, const Vector2& value )
473 {
474   mViewportSize.Bake( updateBufferIndex, value );
475 }
476
477 bool RenderTask::GetViewportEnabled( BufferIndex bufferIndex ) const
478 {
479   if(fabsf(mViewportPosition[bufferIndex].x) > Math::MACHINE_EPSILON_1 ||
480      fabsf(mViewportPosition[bufferIndex].y) > Math::MACHINE_EPSILON_1 ||
481      fabsf(mViewportSize[bufferIndex].width) > Math::MACHINE_EPSILON_1 ||
482      fabsf(mViewportSize[bufferIndex].height) > Math::MACHINE_EPSILON_1)
483   {
484     return true;
485   }
486
487   return false;
488 }
489
490 void RenderTask::ResetDefaultProperties( BufferIndex updateBufferIndex )
491 {
492   // Reset default properties
493   mViewportPosition.ResetToBaseValue( updateBufferIndex );
494   mViewportSize.ResetToBaseValue( updateBufferIndex );
495   mClearColor.ResetToBaseValue( updateBufferIndex );
496 }
497
498 RenderTask::RenderTask()
499 : mViewportPosition( Vector2::ZERO),
500   mViewportSize( Vector2::ZERO),
501   mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
502   mCompleteStatusManager( NULL ),
503   mSourceNode( NULL ),
504   mCameraNode( NULL ),
505   mCameraAttachment( NULL ),
506   mFrameBufferResourceId( 0 ),
507   mWaitingToRender( false ),
508   mNotifyTrigger( false ),
509   mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
510   mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
511   mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE ),
512   mRenderTarget( NULL ),
513   mState( (Dali::RenderTask::DEFAULT_REFRESH_RATE == Dali::RenderTask::REFRESH_ALWAYS)
514           ? RENDER_CONTINUOUSLY
515           : RENDER_ONCE_WAITING_FOR_RESOURCES ),
516   mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
517   mFrameCounter( 0u ),
518   mRenderedOnceCounter( 0u )
519 {
520 }
521
522 } // namespace SceneGraph
523
524 } // namespace Internal
525
526 } // namespace Dali