Merge "Removed unused CullFace features for ImageActor" into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / update / render-tasks / scene-graph-render-task.cpp
1 /*
2  * Copyright (c) 2015 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/controllers/render-message-dispatcher.h>
24 #include <dali/internal/update/resources/resource-manager.h>
25 #include <dali/internal/update/nodes/node.h>
26 #include <dali/internal/render/common/render-instruction.h>
27 #include <dali/internal/render/common/render-tracker.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( mRenderSyncTracker )
55   {
56     mRenderMessageDispatcher->RemoveRenderTracker( *mRenderSyncTracker );
57   }
58 }
59
60 void RenderTask::Initialize( RenderMessageDispatcher& renderMessageDispatcher, ResourceManager& resourceManager )
61 {
62   mRenderMessageDispatcher = &renderMessageDispatcher;
63   mResourceManager = &resourceManager;
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, bool isNativeFBO )
127 {
128   // note that we might already have a RenderTracker
129   mTargetIsNativeFramebuffer = isNativeFBO;
130   mFrameBufferResourceId = resourceId;
131 }
132
133 unsigned int RenderTask::GetFrameBufferId() const
134 {
135   return mFrameBufferResourceId;
136 }
137
138 bool RenderTask::QueryViewport( BufferIndex bufferIndex, Viewport& viewport ) const
139 {
140   if( ! GetViewportEnabled( bufferIndex ) )
141   {
142     return false;
143   }
144
145   viewport.x = mViewportPosition[bufferIndex].x;
146   viewport.y = mViewportPosition[bufferIndex].y;
147   viewport.width = mViewportSize[bufferIndex].width;
148   viewport.height = mViewportSize[bufferIndex].height;
149
150   return true;
151 }
152
153 void RenderTask::SetClearColor( BufferIndex updateBufferIndex, const Vector4& value )
154 {
155   mClearColor.Set( updateBufferIndex, value );
156 }
157
158 const Vector4& RenderTask::GetClearColor( BufferIndex bufferIndex ) const
159 {
160   return mClearColor[bufferIndex];
161 }
162
163 void RenderTask::BakeClearColor( BufferIndex updateBufferIndex, const Vector4& value )
164 {
165   mClearColor.Bake( updateBufferIndex, value );
166 }
167
168 void RenderTask::SetClearEnabled( bool enabled )
169 {
170   mClearEnabled = enabled;
171 }
172
173 bool RenderTask::GetClearEnabled() const
174 {
175   return mClearEnabled;
176 }
177
178 void RenderTask::SetCullMode( bool mode )
179 {
180   mCullMode = mode;
181 }
182
183 bool RenderTask::GetCullMode() const
184 {
185   return mCullMode;
186 }
187
188 void RenderTask::SetRefreshRate( unsigned int refreshRate )
189 {
190   DALI_LOG_TRACE_METHOD_FMT(gRenderTaskLogFilter, "this:%p RefreshRate:%d\n", this, refreshRate);
191
192   mRefreshRate = refreshRate;
193
194   if( mRefreshRate > 0 )
195   {
196     mState = RENDER_CONTINUOUSLY;
197   }
198   else
199   {
200     mState = RENDER_ONCE_WAITING_FOR_RESOURCES;
201     mWaitingToRender = true;
202     mNotifyTrigger = false;
203     // need at least on other render on the FBO
204     mResourceManager->SetFrameBufferBeenRenderedTo( mFrameBufferResourceId, false );
205   }
206
207   mFrameCounter = 0u;
208 }
209
210 unsigned int RenderTask::GetRefreshRate() const
211 {
212   return mRefreshRate;
213 }
214
215 bool RenderTask::ReadyToRender( BufferIndex updateBufferIndex )
216 {
217   // If the source node of the render task is invisible we should still render
218   // We want the render task to complete and possible clear colors to happen
219
220   // Check source node
221   if ( NULL == mSourceNode ||
222        ( !mSourceNode->IsRoot() && NULL == mSourceNode->GetParent() ) )
223   {
224     TASK_LOG_FMT(Debug::General, " =F  No source actor  FC:%d\n", mFrameCounter );
225
226     // Source node is missing or disconnected
227     return false;
228   }
229
230   // Check camera node
231   if ( NULL == mCameraNode ||
232        NULL == mCameraNode->GetParent() ||
233        NULL == mCameraAttachment )
234   {
235     // Camera node is missing or disconnected
236     TASK_LOG_FMT(Debug::General, " =F  No Camera  FC:%d\n", mFrameCounter );
237
238     return false;
239   }
240
241   mCameraAttachment->Update( updateBufferIndex, *mCameraNode );
242
243   TASK_LOG_FMT(Debug::General, " =T (FBO ID:%d) FC:%d\n", mFrameBufferResourceId , mFrameCounter );
244   return true;
245 }
246
247 bool RenderTask::IsRenderRequired()
248 {
249   bool required = false;
250
251   switch( mState )
252   {
253     case RENDER_CONTINUOUSLY:
254     {
255       required = (mFrameCounter == 0);
256       break;
257     }
258     case RENDER_ONCE_WAITING_FOR_RESOURCES:
259     {
260       required = true;
261       break;
262     }
263     default:
264     {
265       required = false;
266       break;
267     }
268   }
269
270   TASK_LOG_FMT( Debug::General, " State:%s = %s\n", STATE_STRING(mState), required?"T":"F" );
271
272   return required;
273 }
274
275 void RenderTask::SetResourcesFinished( bool resourcesFinished )
276 {
277   // resourcesFinished tells us that this render task will render to its FBO
278   mResourcesFinished = resourcesFinished;
279   if( mResourcesFinished )
280   {
281     mResourceManager->SetFrameBufferBeenRenderedTo( mFrameBufferResourceId, true );
282   }
283 }
284
285 // Called every frame regardless of whether render was required.
286 // If render was not required, ignore resourcesFinished.
287 void RenderTask::UpdateState()
288 {
289   TASK_LOG_FMT( Debug::General, "(mResourcesFinished:%s)  FC:%d State:%s RR:%d\n", mResourcesFinished?"T":"F", mFrameCounter, STATE_STRING(mState), mRefreshRate );
290
291   switch( mState )
292   {
293     case RENDER_CONTINUOUSLY:
294     {
295       if( mRefreshRate != Dali::RenderTask::REFRESH_ALWAYS )
296       {
297         if( mFrameCounter == 0 )
298         {
299           if( mResourcesFinished )
300           {
301             ++mFrameCounter; // Only start skipping frames when resources are loaded
302           }
303         }
304         else // Continue counting to skip frames
305         {
306           ++mFrameCounter;
307           if( mFrameCounter >= mRefreshRate )
308           {
309             mFrameCounter = 0;
310           }
311         }
312       }
313       // else do nothing
314     }
315     break;
316
317     case RENDER_ONCE_WAITING_FOR_RESOURCES:
318     {
319       if( mResourcesFinished )
320       {
321         mState = RENDERED_ONCE;
322       }
323     }
324     break;
325
326     case RENDERED_ONCE:
327     {
328       mWaitingToRender = true;
329       mNotifyTrigger = false;
330       if( mFrameBufferResourceId > 0 )
331       {
332         if( mTargetIsNativeFramebuffer )
333         {
334           if( mRenderSyncTracker && mRenderSyncTracker->IsSynced() )
335           {
336             mWaitingToRender = false;
337             mNotifyTrigger = true;
338           }
339         }
340         else if( mResourceManager->HasFrameBufferBeenRenderedTo( mFrameBufferResourceId ) )
341         {
342           mWaitingToRender = false;
343           mNotifyTrigger = true;
344         }
345       }
346       else
347       {
348         mNotifyTrigger = true;
349       }
350     }
351
352     break;
353
354     default:
355       break;
356   }
357
358   TASK_LOG_FMT( Debug::General, " EXIT FC:%d State:%s Notify:%s\n", mFrameCounter, STATE_STRING(mState), mNotifyTrigger?"T":"F");
359 }
360
361 bool RenderTask::IsWaitingToRender()
362 {
363   TASK_LOG_FMT(Debug::Verbose, " State:%s waiting:%s \n", STATE_STRING(mState), mWaitingToRender?"T":"F");
364   return mWaitingToRender;
365 }
366
367 bool RenderTask::HasRendered()
368 {
369   bool notify = false;
370   if( mNotifyTrigger == true )
371   {
372     ++mRenderedOnceCounter;
373     mState = RENDERED_ONCE_AND_NOTIFIED;
374     mNotifyTrigger = false;
375     notify = true;
376   }
377
378   TASK_LOG_FMT(Debug::Verbose, " State:%s hasRendered:%s \n", STATE_STRING(mState), notify?"T":"F");
379   return notify;
380 }
381
382 unsigned int RenderTask::GetRenderedOnceCounter() const
383 {
384   return mRenderedOnceCounter;
385 }
386
387
388 const Matrix& RenderTask::GetViewMatrix( BufferIndex bufferIndex ) const
389 {
390   DALI_ASSERT_DEBUG( NULL != mCameraAttachment );
391
392   return mCameraAttachment->GetViewMatrix( bufferIndex );
393 }
394
395 SceneGraph::CameraAttachment& RenderTask::GetCameraAttachment() const
396 {
397   DALI_ASSERT_DEBUG( NULL != mCameraAttachment );
398   return *mCameraAttachment;
399 }
400
401 const Matrix& RenderTask::GetProjectionMatrix( BufferIndex bufferIndex ) const
402 {
403   DALI_ASSERT_DEBUG( NULL != mCameraAttachment );
404
405   return mCameraAttachment->GetProjectionMatrix( bufferIndex );
406 }
407
408 void RenderTask::PrepareRenderInstruction( RenderInstruction& instruction, BufferIndex updateBufferIndex )
409 {
410   DALI_ASSERT_DEBUG( NULL != mCameraAttachment );
411
412   TASK_LOG(Debug::General);
413
414   Viewport viewport;
415   bool viewportSet = QueryViewport( updateBufferIndex, viewport );
416
417   instruction.Reset( mCameraAttachment,
418                      GetFrameBufferId(),
419                      viewportSet ? &viewport : NULL,
420                      mClearEnabled ? &GetClearColor( updateBufferIndex ) : NULL );
421
422   if( mTargetIsNativeFramebuffer && mRequiresSync &&
423       mRefreshRate == Dali::RenderTask::REFRESH_ONCE &&
424       mResourcesFinished )
425   {
426     // create tracker if one doesn't yet exist.
427     if( !mRenderSyncTracker )
428     {
429       mRenderSyncTracker = new Render::RenderTracker();
430       mRenderMessageDispatcher->AddRenderTracker( *mRenderSyncTracker );
431     }
432     instruction.mRenderTracker = mRenderSyncTracker;
433   }
434   else
435   {
436     // no sync needed, texture FBOs are "ready" the same frame they are rendered to
437     instruction.mRenderTracker = NULL;
438   }
439 }
440
441 bool RenderTask::ViewMatrixUpdated()
442 {
443   bool retval = false;
444   if( mCameraAttachment )
445   {
446     retval = mCameraAttachment->ViewMatrixUpdated();
447   }
448   return retval;
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 Node* RenderTask::GetCamera() const
495 {
496   return mCameraNode;
497 }
498
499 void RenderTask::SetSyncRequired( bool requiresSync )
500 {
501   mRequiresSync = requiresSync;
502 }
503
504 void RenderTask::ResetDefaultProperties( BufferIndex updateBufferIndex )
505 {
506   // Reset default properties
507   mViewportPosition.ResetToBaseValue( updateBufferIndex );
508   mViewportSize.ResetToBaseValue( updateBufferIndex );
509   mClearColor.ResetToBaseValue( updateBufferIndex );
510 }
511
512 RenderTask::RenderTask()
513 : mViewportPosition( Vector2::ZERO),
514   mViewportSize( Vector2::ZERO),
515   mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
516   mRenderMessageDispatcher( NULL ),
517   mResourceManager( NULL ),
518   mRenderSyncTracker( NULL ),
519   mSourceNode( NULL ),
520   mCameraNode( NULL ),
521   mCameraAttachment( NULL ),
522   mFrameBufferResourceId( 0 ),
523   mResourcesFinished( false ),
524   mWaitingToRender( false ),
525   mNotifyTrigger( false ),
526   mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
527   mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
528   mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE ),
529   mRenderTarget( NULL ),
530   mState( (Dali::RenderTask::DEFAULT_REFRESH_RATE == Dali::RenderTask::REFRESH_ALWAYS)
531           ? RENDER_CONTINUOUSLY
532           : RENDER_ONCE_WAITING_FOR_RESOURCES ),
533   mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
534   mFrameCounter( 0u ),
535   mRenderedOnceCounter( 0u ),
536   mTargetIsNativeFramebuffer( false ),
537   mRequiresSync( false )
538 {
539 }
540
541 } // namespace SceneGraph
542
543 } // namespace Internal
544
545 } // namespace Dali