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