Merge "DALi Version 1.0.5" into tizen
[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 void RenderTask::SetResourcesFinished( bool resourcesFinished )
304 {
305   mResourcesFinished = resourcesFinished;
306 }
307
308 // Called every frame regardless of whether render was required.
309 // If render was not required, ignore resourcesFinished.
310 void RenderTask::UpdateState()
311 {
312   TASK_LOG_FMT( Debug::General, "(mResourcesFinished:%s)  FC:%d State:%s RR:%d\n", mResourcesFinished?"T":"F", mFrameCounter, STATE_STRING(mState), mRefreshRate );
313
314   switch( mState )
315   {
316     case RENDER_CONTINUOUSLY:
317     {
318       if( mRefreshRate != Dali::RenderTask::REFRESH_ALWAYS )
319       {
320         if( mFrameCounter == 0 )
321         {
322           if( mResourcesFinished )
323           {
324             ++mFrameCounter; // Only start skipping frames when resources are loaded
325           }
326         }
327         else // Continue counting to skip frames
328         {
329           ++mFrameCounter;
330           if( mFrameCounter >= mRefreshRate )
331           {
332             mFrameCounter = 0;
333           }
334         }
335       }
336       // else do nothing
337     }
338     break;
339
340     case RENDER_ONCE_WAITING_FOR_RESOURCES:
341     {
342       if( mResourcesFinished )
343       {
344         mState = RENDERED_ONCE;
345       }
346     }
347     break;
348
349     case RENDERED_ONCE:
350     {
351       if( mFrameBufferResourceId > 0 )
352       {
353         // Query if the framebuffer is complete:
354         DALI_ASSERT_DEBUG(mCompleteStatusManager && "Complete status tracker is null");
355         if( mCompleteStatusManager != NULL &&
356             CompleteStatusManager::COMPLETE == mCompleteStatusManager->GetStatus( mFrameBufferResourceId ) )
357         {
358           mWaitingToRender = false;
359           mNotifyTrigger = true;
360         }
361         else
362         {
363           mWaitingToRender = true;
364         }
365       }
366       else
367       {
368         mWaitingToRender = false;
369         mNotifyTrigger = true;
370       }
371     }
372     break;
373
374     default:
375       break;
376   }
377
378   TASK_LOG_FMT( Debug::General, " EXIT FC:%d State:%s Notify:%s\n", mFrameCounter, STATE_STRING(mState), mNotifyTrigger?"T":"F");
379 }
380
381 bool RenderTask::IsWaitingToRender()
382 {
383   TASK_LOG_FMT(Debug::Verbose, " State:%s waiting:%s \n", STATE_STRING(mState), mWaitingToRender?"T":"F");
384   return mWaitingToRender;
385 }
386
387 bool RenderTask::HasRendered()
388 {
389   bool notify = false;
390   if( mNotifyTrigger == true )
391   {
392     ++mRenderedOnceCounter;
393     mState = RENDERED_ONCE_AND_NOTIFIED;
394     mNotifyTrigger = false;
395     notify = true;
396   }
397
398   TASK_LOG_FMT(Debug::Verbose, " State:%s hasRendered:%s \n", STATE_STRING(mState), notify?"T":"F");
399   return notify;
400 }
401
402 unsigned int RenderTask::GetRenderedOnceCounter() const
403 {
404   return mRenderedOnceCounter;
405 }
406
407
408 const Matrix& RenderTask::GetViewMatrix( BufferIndex bufferIndex ) const
409 {
410   DALI_ASSERT_DEBUG( NULL != mCameraAttachment );
411
412   return mCameraAttachment->GetViewMatrix( bufferIndex );
413 }
414
415 const Matrix& RenderTask::GetProjectionMatrix( BufferIndex bufferIndex ) const
416 {
417   DALI_ASSERT_DEBUG( NULL != mCameraAttachment );
418
419   return mCameraAttachment->GetProjectionMatrix( bufferIndex );
420 }
421
422 void RenderTask::PrepareRenderInstruction( RenderInstruction& instruction, BufferIndex updateBufferIndex )
423 {
424   DALI_ASSERT_DEBUG( NULL != mCameraAttachment );
425
426   TASK_LOG(Debug::General);
427
428   Viewport viewport;
429   bool viewportSet = QueryViewport( updateBufferIndex, viewport );
430
431   instruction.Reset( mCameraAttachment,
432                      GetFrameBufferId(),
433                      viewportSet ? &viewport : NULL,
434                      mClearEnabled ? &GetClearColor( updateBufferIndex ) : NULL );
435 }
436
437 bool RenderTask::ViewMatrixUpdated()
438 {
439   bool retval = false;
440   if( mCameraAttachment )
441   {
442     retval = mCameraAttachment->ViewMatrixUpdated();
443   }
444   return retval;
445 }
446
447 void RenderTask::SetCompleteStatusManager(CompleteStatusManager* completeStatusManager)
448 {
449   mCompleteStatusManager = completeStatusManager;
450 }
451
452 void RenderTask::SetViewportPosition( BufferIndex updateBufferIndex, const Vector2& value )
453 {
454   mViewportPosition.Set( updateBufferIndex, value );
455 }
456
457 const Vector2& RenderTask::GetViewportPosition( BufferIndex bufferIndex ) const
458 {
459   return mViewportPosition[bufferIndex];
460 }
461
462 void RenderTask::BakeViewportPosition( BufferIndex updateBufferIndex, const Vector2& value )
463 {
464   mViewportPosition.Bake( updateBufferIndex, value );
465 }
466
467 void RenderTask::SetViewportSize( BufferIndex updateBufferIndex, const Vector2& value )
468 {
469   mViewportSize.Set( updateBufferIndex, value );
470 }
471
472 const Vector2& RenderTask::GetViewportSize( BufferIndex bufferIndex ) const
473 {
474   return mViewportSize[bufferIndex];
475 }
476
477 void RenderTask::BakeViewportSize( BufferIndex updateBufferIndex, const Vector2& value )
478 {
479   mViewportSize.Bake( updateBufferIndex, value );
480 }
481
482 bool RenderTask::GetViewportEnabled( BufferIndex bufferIndex ) const
483 {
484   if(fabsf(mViewportPosition[bufferIndex].x) > Math::MACHINE_EPSILON_1 ||
485      fabsf(mViewportPosition[bufferIndex].y) > Math::MACHINE_EPSILON_1 ||
486      fabsf(mViewportSize[bufferIndex].width) > Math::MACHINE_EPSILON_1 ||
487      fabsf(mViewportSize[bufferIndex].height) > Math::MACHINE_EPSILON_1)
488   {
489     return true;
490   }
491
492   return false;
493 }
494
495 Node* RenderTask::GetCamera() const
496 {
497   return mCameraNode;
498 }
499
500 void RenderTask::ResetDefaultProperties( BufferIndex updateBufferIndex )
501 {
502   // Reset default properties
503   mViewportPosition.ResetToBaseValue( updateBufferIndex );
504   mViewportSize.ResetToBaseValue( updateBufferIndex );
505   mClearColor.ResetToBaseValue( updateBufferIndex );
506 }
507
508 RenderTask::RenderTask()
509 : mViewportPosition( Vector2::ZERO),
510   mViewportSize( Vector2::ZERO),
511   mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
512   mCompleteStatusManager( NULL ),
513   mSourceNode( NULL ),
514   mCameraNode( NULL ),
515   mCameraAttachment( NULL ),
516   mFrameBufferResourceId( 0 ),
517   mResourcesFinished( false ),
518   mWaitingToRender( false ),
519   mNotifyTrigger( false ),
520   mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
521   mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
522   mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE ),
523   mRenderTarget( NULL ),
524   mState( (Dali::RenderTask::DEFAULT_REFRESH_RATE == Dali::RenderTask::REFRESH_ALWAYS)
525           ? RENDER_CONTINUOUSLY
526           : RENDER_ONCE_WAITING_FOR_RESOURCES ),
527   mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
528   mFrameCounter( 0u ),
529   mRenderedOnceCounter( 0u )
530 {
531 }
532
533 } // namespace SceneGraph
534
535 } // namespace Internal
536
537 } // namespace Dali