Added image renderer clip space culling
[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::SetCullMode( bool mode )
199 {
200   mCullMode = mode;
201 }
202
203 bool RenderTask::GetCullMode() const
204 {
205   return mCullMode;
206 }
207
208 void RenderTask::SetRefreshRate( unsigned int refreshRate )
209 {
210   DALI_LOG_TRACE_METHOD_FMT(gRenderTaskLogFilter, "this:%p RefreshRate:%d\n", this, refreshRate);
211
212   mRefreshRate = refreshRate;
213
214   if( mRefreshRate > 0 )
215   {
216     mState = RENDER_CONTINUOUSLY;
217
218     if( mFrameBufferResourceId )
219     {
220       // Don't need tracking
221       DALI_ASSERT_DEBUG(mCompleteStatusManager && "Ready state tracker is null");
222       if( mCompleteStatusManager != NULL )
223       {
224         mCompleteStatusManager->StopTrackingResource( mFrameBufferResourceId );
225       }
226     }
227   }
228   else
229   {
230     mState = RENDER_ONCE_WAITING_FOR_RESOURCES;
231     mWaitingToRender = true;
232     mNotifyTrigger = false;
233
234     if( mFrameBufferResourceId )
235     {
236       DALI_ASSERT_DEBUG(mCompleteStatusManager && "Ready state tracker is null");
237       if( mCompleteStatusManager != NULL )
238       {
239         mCompleteStatusManager->TrackResource( mFrameBufferResourceId );
240       }
241     }
242   }
243
244   mFrameCounter = 0u;
245 }
246
247 unsigned int RenderTask::GetRefreshRate() const
248 {
249   return mRefreshRate;
250 }
251
252 bool RenderTask::ReadyToRender( BufferIndex updateBufferIndex )
253 {
254   if ( NULL == mSourceNode ||
255        ( !mSourceNode->IsRoot() && NULL == mSourceNode->GetParent() ) )
256   {
257     TASK_LOG_FMT(Debug::General, " =F  No source actor  FC:%d\n", mFrameCounter );
258
259     // Source node is missing or disconnected
260     return false;
261   }
262
263   // Check if the source node (root actor) and all its ancestors are visible.
264   if( !mSourceNode->IsFullyVisible( updateBufferIndex ) )
265   {
266     TASK_LOG_FMT(Debug::General, " =F  No visible source  FC:%d\n", mFrameCounter );
267     return false;
268   }
269
270   if ( NULL == mCameraNode ||
271        NULL == mCameraNode->GetParent() ||
272        !mCameraNode->HasAttachment() )
273   {
274     // Camera node is missing or disconnected
275     TASK_LOG_FMT(Debug::General, " =F  No Camera  FC:%d\n", mFrameCounter );
276
277     return false;
278   }
279
280   TASK_LOG_FMT(Debug::General, " =T (FBO ID:%d) FC:%d\n", mFrameBufferResourceId , mFrameCounter );
281   return true;
282 }
283
284 bool RenderTask::IsRenderRequired()
285 {
286   bool required = false;
287
288   switch( mState )
289   {
290     case RENDER_CONTINUOUSLY:
291       required = (mFrameCounter == 0);
292       break;
293
294     case RENDER_ONCE_WAITING_FOR_RESOURCES:
295       required = true;
296       break;
297
298     default:
299       required = false;
300       break;
301   }
302
303   TASK_LOG_FMT( Debug::General, " State:%s = %s\n", STATE_STRING(mState), required?"T":"F" );
304
305   return required;
306 }
307
308 // Called every frame regardless of whether render was required.
309 // If render was not required, ignore resourcesFinished.
310 void RenderTask::UpdateState(bool resourcesFinished)
311 {
312   TASK_LOG_FMT( Debug::General, "(resourcesFinished:%s)  FC:%d State:%s RR:%d\n", resourcesFinished?"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( resourcesFinished )
323           {
324             ++mFrameCounter; // Only start missing frames when resources are loaded
325           }
326         }
327         else // Continue counting to miss 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( resourcesFinished )
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   TASK_LOG(Debug::General);
425
426   Viewport viewport;
427   bool viewportSet = QueryViewport( updateBufferIndex, viewport );
428
429   instruction.Reset( &GetViewMatrix( updateBufferIndex ),
430                      &GetProjectionMatrix( updateBufferIndex ),
431                      GetFrameBufferId(),
432                      viewportSet ? &viewport : NULL,
433                      mClearEnabled ? &GetClearColor( updateBufferIndex ) : NULL );
434 }
435
436 bool RenderTask::ViewMatrixUpdated()
437 {
438   bool retval = false;
439   if( mCameraAttachment )
440   {
441     retval = mCameraAttachment->ViewMatrixUpdated();
442   }
443   return retval;
444 }
445
446 void RenderTask::SetCompleteStatusManager(CompleteStatusManager* completeStatusManager)
447 {
448   mCompleteStatusManager = completeStatusManager;
449 }
450
451 void RenderTask::SetViewportPosition( BufferIndex updateBufferIndex, const Vector2& value )
452 {
453   mViewportPosition.Set( updateBufferIndex, value );
454 }
455
456 const Vector2& RenderTask::GetViewportPosition( BufferIndex bufferIndex ) const
457 {
458   return mViewportPosition[bufferIndex];
459 }
460
461 void RenderTask::BakeViewportPosition( BufferIndex updateBufferIndex, const Vector2& value )
462 {
463   mViewportPosition.Bake( updateBufferIndex, value );
464 }
465
466 void RenderTask::SetViewportSize( BufferIndex updateBufferIndex, const Vector2& value )
467 {
468   mViewportSize.Set( updateBufferIndex, value );
469 }
470
471 const Vector2& RenderTask::GetViewportSize( BufferIndex bufferIndex ) const
472 {
473   return mViewportSize[bufferIndex];
474 }
475
476 void RenderTask::BakeViewportSize( BufferIndex updateBufferIndex, const Vector2& value )
477 {
478   mViewportSize.Bake( updateBufferIndex, value );
479 }
480
481 bool RenderTask::GetViewportEnabled( BufferIndex bufferIndex ) const
482 {
483   if(fabsf(mViewportPosition[bufferIndex].x) > Math::MACHINE_EPSILON_1 ||
484      fabsf(mViewportPosition[bufferIndex].y) > Math::MACHINE_EPSILON_1 ||
485      fabsf(mViewportSize[bufferIndex].width) > Math::MACHINE_EPSILON_1 ||
486      fabsf(mViewportSize[bufferIndex].height) > Math::MACHINE_EPSILON_1)
487   {
488     return true;
489   }
490
491   return false;
492 }
493
494 void RenderTask::ResetDefaultProperties( BufferIndex updateBufferIndex )
495 {
496   // Reset default properties
497   mViewportPosition.ResetToBaseValue( updateBufferIndex );
498   mViewportSize.ResetToBaseValue( updateBufferIndex );
499   mClearColor.ResetToBaseValue( updateBufferIndex );
500 }
501
502 RenderTask::RenderTask()
503 : mViewportPosition( Vector2::ZERO),
504   mViewportSize( Vector2::ZERO),
505   mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
506   mCompleteStatusManager( NULL ),
507   mSourceNode( NULL ),
508   mCameraNode( NULL ),
509   mCameraAttachment( NULL ),
510   mFrameBufferResourceId( 0 ),
511   mWaitingToRender( false ),
512   mNotifyTrigger( false ),
513   mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
514   mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
515   mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE ),
516   mRenderTarget( NULL ),
517   mState( (Dali::RenderTask::DEFAULT_REFRESH_RATE == Dali::RenderTask::REFRESH_ALWAYS)
518           ? RENDER_CONTINUOUSLY
519           : RENDER_ONCE_WAITING_FOR_RESOURCES ),
520   mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
521   mFrameCounter( 0u ),
522   mRenderedOnceCounter( 0u )
523 {
524 }
525
526 } // namespace SceneGraph
527
528 } // namespace Internal
529
530 } // namespace Dali