Fix MSVC warning.
[platform/core/uifw/dali-core.git] / dali / internal / update / render-tasks / scene-graph-render-task.cpp
1 /*
2  * Copyright (c) 2018 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   if ( mSourceNode )
46   {
47     mSourceNode->RemoveObserver( *this );
48     if( mExclusive )
49     {
50       mSourceNode->SetExclusiveRenderTask( nullptr );
51     }
52   }
53   if ( mCameraNode )
54   {
55     mCameraNode->RemoveObserver( *this );
56   }
57   if( mRenderSyncTracker )
58   {
59     mRenderMessageDispatcher->RemoveRenderTracker( *mRenderSyncTracker );
60   }
61 }
62
63 void RenderTask::Initialize( RenderMessageDispatcher& renderMessageDispatcher )
64 {
65   mRenderMessageDispatcher = &renderMessageDispatcher;
66 }
67
68 void RenderTask::SetSourceNode( Node* node )
69 {
70   // Stop observing the old node (if we were)
71   if ( mSourceNode )
72   {
73     mSourceNode->RemoveObserver( *this );
74     if( this == mSourceNode->GetExclusiveRenderTask() )
75     {
76       mSourceNode->SetExclusiveRenderTask( nullptr );
77     }
78   }
79
80   mSourceNode = node;
81
82   if ( mSourceNode )
83   {
84     mSourceNode->AddObserver( *this );
85     if( mExclusive )
86     {
87       mSourceNode->SetExclusiveRenderTask( this );
88     }
89   }
90   SetActiveStatus();
91 }
92
93 Node* RenderTask::GetSourceNode() const
94 {
95   return mSourceNode;
96 }
97
98 void RenderTask::SetExclusive( bool exclusive )
99 {
100   mExclusive = exclusive;
101
102   if ( mSourceNode )
103   {
104     if ( mExclusive )
105     {
106       mSourceNode->SetExclusiveRenderTask( this );
107     }
108     else if ( this == mSourceNode->GetExclusiveRenderTask() )
109     {
110       mSourceNode->SetExclusiveRenderTask( nullptr );
111     }
112   }
113 }
114
115 bool RenderTask::IsExclusive() const
116 {
117   return mExclusive;
118 }
119
120 void RenderTask::SetCamera( Node* cameraNode, Camera* camera )
121 {
122   if ( mCameraNode )
123   {
124     mCameraNode->RemoveObserver( *this );
125   }
126
127   mCameraNode = cameraNode;
128   mCamera = camera;
129
130   if ( mCameraNode )
131   {
132     mCameraNode->AddObserver( *this );
133   }
134   SetActiveStatus();
135 }
136
137 void RenderTask::SetFrameBuffer( Render::FrameBuffer* frameBuffer )
138 {
139   mFrameBuffer = frameBuffer;
140 }
141
142 Render::FrameBuffer* RenderTask::GetFrameBuffer()
143 {
144   return mFrameBuffer;
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 = static_cast<int>( mViewportPosition[bufferIndex].x ); // truncated
155   viewport.y = static_cast<int>( mViewportPosition[bufferIndex].y ); // truncated
156   viewport.width = static_cast<int>( mViewportSize[bufferIndex].width ); // truncated
157   viewport.height = static_cast<int>( mViewportSize[bufferIndex].height ); // truncated
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( uint32_t 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   else
208   {
209     mState = RENDER_ONCE_WAITING_FOR_RESOURCES;
210     mWaitingToRender = true;
211     mNotifyTrigger = false;
212   }
213
214   mFrameCounter = 0u;
215 }
216
217 uint32_t RenderTask::GetRefreshRate() const
218 {
219   return mRefreshRate;
220 }
221
222 bool RenderTask::ReadyToRender( BufferIndex updateBufferIndex )
223 {
224   return mActive;
225 }
226
227 bool RenderTask::IsRenderRequired()
228 {
229   bool required = false;
230
231   switch( mState )
232   {
233     case RENDER_CONTINUOUSLY:
234     {
235       required = (mFrameCounter == 0);
236       break;
237     }
238     case RENDER_ONCE_WAITING_FOR_RESOURCES:
239     {
240       required = true;
241       break;
242     }
243     default:
244     {
245       required = false;
246       break;
247     }
248   }
249
250   TASK_LOG_FMT( Debug::General, " State:%s = %s\n", STATE_STRING(mState), required?"T":"F" );
251
252   return required;
253 }
254
255 // Called every frame regardless of whether render was required.
256 // If render was not required, ignore resourcesFinished.
257 void RenderTask::UpdateState()
258 {
259   TASK_LOG_FMT( Debug::General, "FC:%d State:%s RR:%d\n", mFrameCounter, STATE_STRING(mState), mRefreshRate );
260
261   switch( mState )
262   {
263     case RENDER_CONTINUOUSLY:
264     {
265       if( mRefreshRate != Dali::RenderTask::REFRESH_ALWAYS )
266       {
267         if( mFrameCounter == 0 )
268         {
269           ++mFrameCounter; // Only start skipping frames when resources are loaded
270         }
271         else // Continue counting to skip frames
272         {
273           ++mFrameCounter;
274           if( mFrameCounter >= mRefreshRate )
275           {
276             mFrameCounter = 0;
277           }
278         }
279       }
280       // else do nothing
281     }
282     break;
283
284     case RENDER_ONCE_WAITING_FOR_RESOURCES:
285     {
286       mState = RENDERED_ONCE;
287     }
288     break;
289
290     case RENDERED_ONCE:
291     {
292       mWaitingToRender = true;
293       mNotifyTrigger = false;
294       if( mFrameBuffer )
295       {
296         if( !mRenderSyncTracker || (mRenderSyncTracker && mRenderSyncTracker->IsSynced() ))
297         {
298           mWaitingToRender = false;
299           mNotifyTrigger = true;
300         }
301       }
302       else
303       {
304         mWaitingToRender = false;
305         mNotifyTrigger = true;
306       }
307     }
308
309     break;
310
311     default:
312       break;
313   }
314
315   TASK_LOG_FMT( Debug::General, " EXIT FC:%d State:%s Notify:%s\n", mFrameCounter, STATE_STRING(mState), mNotifyTrigger?"T":"F");
316 }
317
318 bool RenderTask::IsWaitingToRender()
319 {
320   TASK_LOG_FMT(Debug::Verbose, " State:%s waiting:%s \n", STATE_STRING(mState), mWaitingToRender?"T":"F");
321   return mWaitingToRender;
322 }
323
324 bool RenderTask::HasRendered()
325 {
326   bool notify = false;
327   if( mNotifyTrigger == true )
328   {
329     ++mRenderedOnceCounter;
330     mState = RENDERED_ONCE_AND_NOTIFIED;
331     mNotifyTrigger = false;
332     notify = true;
333   }
334
335   TASK_LOG_FMT(Debug::Verbose, " State:%s hasRendered:%s \n", STATE_STRING(mState), notify?"T":"F");
336   return notify;
337 }
338
339 uint32_t RenderTask::GetRenderedOnceCounter() const
340 {
341   return mRenderedOnceCounter;
342 }
343
344 const Matrix& RenderTask::GetViewMatrix( BufferIndex bufferIndex ) const
345 {
346   DALI_ASSERT_DEBUG( nullptr != mCamera );
347
348   return mCamera->GetViewMatrix( bufferIndex );
349 }
350
351 SceneGraph::Camera& RenderTask::GetCamera() const
352 {
353   DALI_ASSERT_DEBUG( nullptr != mCamera );
354   return *mCamera;
355 }
356
357 const Matrix& RenderTask::GetProjectionMatrix( BufferIndex bufferIndex ) const
358 {
359   DALI_ASSERT_DEBUG( nullptr != mCamera );
360
361   return mCamera->GetProjectionMatrix( bufferIndex );
362 }
363
364 void RenderTask::PrepareRenderInstruction( RenderInstruction& instruction, BufferIndex updateBufferIndex )
365 {
366   DALI_ASSERT_DEBUG( nullptr != mCamera );
367
368   TASK_LOG(Debug::General);
369
370   Viewport viewport;
371   bool viewportSet = QueryViewport( updateBufferIndex, viewport );
372
373   instruction.Reset( mCamera,
374                      GetFrameBuffer(),
375                      viewportSet ? &viewport : nullptr,
376                      mClearEnabled ? &GetClearColor( updateBufferIndex ) : nullptr );
377
378   if( mRequiresSync &&
379       mRefreshRate == Dali::RenderTask::REFRESH_ONCE )
380   {
381     // create tracker if one doesn't yet exist.
382     if( !mRenderSyncTracker )
383     {
384       mRenderSyncTracker = new Render::RenderTracker();
385       mRenderMessageDispatcher->AddRenderTracker( *mRenderSyncTracker );
386     }
387     instruction.mRenderTracker = mRenderSyncTracker;
388   }
389   else
390   {
391     // no sync needed, texture FBOs are "ready" the same frame they are rendered to
392     instruction.mRenderTracker = nullptr;
393   }
394 }
395
396 bool RenderTask::ViewMatrixUpdated()
397 {
398   bool retval = false;
399   if( mCamera )
400   {
401     retval = mCamera->ViewMatrixUpdated();
402   }
403   return retval;
404 }
405
406 void RenderTask::SetViewportPosition( BufferIndex updateBufferIndex, const Vector2& value )
407 {
408   mViewportPosition.Set( updateBufferIndex, value );
409 }
410
411 const Vector2& RenderTask::GetViewportPosition( BufferIndex bufferIndex ) const
412 {
413   return mViewportPosition[bufferIndex];
414 }
415
416 void RenderTask::BakeViewportPosition( BufferIndex updateBufferIndex, const Vector2& value )
417 {
418   mViewportPosition.Bake( updateBufferIndex, value );
419 }
420
421 void RenderTask::SetViewportSize( BufferIndex updateBufferIndex, const Vector2& value )
422 {
423   mViewportSize.Set( updateBufferIndex, value );
424 }
425
426 const Vector2& RenderTask::GetViewportSize( BufferIndex bufferIndex ) const
427 {
428   return mViewportSize[bufferIndex];
429 }
430
431 void RenderTask::BakeViewportSize( BufferIndex updateBufferIndex, const Vector2& value )
432 {
433   mViewportSize.Bake( updateBufferIndex, value );
434 }
435
436 bool RenderTask::GetViewportEnabled( BufferIndex bufferIndex ) const
437 {
438   if(fabsf(mViewportPosition[bufferIndex].x) > Math::MACHINE_EPSILON_1 ||
439      fabsf(mViewportPosition[bufferIndex].y) > Math::MACHINE_EPSILON_1 ||
440      fabsf(mViewportSize[bufferIndex].width) > Math::MACHINE_EPSILON_1 ||
441      fabsf(mViewportSize[bufferIndex].height) > Math::MACHINE_EPSILON_1)
442   {
443     return true;
444   }
445
446   return false;
447 }
448
449 void RenderTask::SetSyncRequired( bool requiresSync )
450 {
451   mRequiresSync = requiresSync;
452 }
453
454 void RenderTask::PropertyOwnerConnected( PropertyOwner& owner )
455 {
456   // check if we've gone from inactive to active
457   SetActiveStatus();
458 }
459
460 void RenderTask::PropertyOwnerDisconnected( BufferIndex /*updateBufferIndex*/, PropertyOwner& owner )
461 {
462   mActive = false; // if either source or camera disconnected, we're no longer active
463 }
464
465 void RenderTask::PropertyOwnerDestroyed( PropertyOwner& owner )
466 {
467   if( static_cast<PropertyOwner*>( mSourceNode ) == &owner )
468   {
469     mSourceNode = nullptr;
470   }
471   else if( static_cast<PropertyOwner*>( mCameraNode ) == &owner )
472   {
473     mCameraNode = nullptr;
474   }
475 }
476
477 RenderTask::RenderTask()
478 : mViewportPosition( Vector2::ZERO),
479   mViewportSize( Vector2::ZERO),
480   mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
481   mRenderMessageDispatcher( nullptr ),
482   mRenderSyncTracker( nullptr ),
483   mSourceNode( nullptr ),
484   mCameraNode( nullptr ),
485   mCamera( nullptr ),
486   mFrameBuffer(0),
487   mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
488   mFrameCounter( 0u ),
489   mRenderedOnceCounter( 0u ),
490   mState( (Dali::RenderTask::DEFAULT_REFRESH_RATE == Dali::RenderTask::REFRESH_ALWAYS)
491           ? RENDER_CONTINUOUSLY
492           : RENDER_ONCE_WAITING_FOR_RESOURCES ),
493   mRequiresSync( false ),
494   mActive( false ),
495   mWaitingToRender( false ),
496   mNotifyTrigger( false ),
497   mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
498   mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
499   mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE )
500 {
501 }
502
503 void RenderTask::SetActiveStatus()
504 {
505   // must have a source and camera both connected to scene
506   mActive = ( mSourceNode && mSourceNode->ConnectedToScene() &&
507               mCameraNode && mCameraNode->ConnectedToScene() && mCamera );
508   TASK_LOG_FMT( Debug::General, " Source node(%x) active %d.  Frame counter: %d\n", mSourceNode, mSourceNode && mSourceNode->ConnectedToScene(), mFrameCounter );
509   TASK_LOG_FMT( Debug::General, " Camera node(%x) active %d\n", mCameraNode, mCameraNode && mCameraNode->ConnectedToScene() );
510 }
511
512 } // namespace SceneGraph
513
514 } // namespace Internal
515
516 } // namespace Dali