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