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