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