Merge "Revert "Implemented basic CPU image masking"" into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / update / render-tasks / scene-graph-render-task.cpp
1 /*
2  * Copyright (c) 2017 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 the source node.
205   if( NULL == mSourceNode ||
206       ( !mSourceNode->IsRoot() && NULL == mSourceNode->GetParent() ) )
207   {
208     TASK_LOG_FMT( Debug::General, " Source actor not on stage.  Frame counter: %d\n", mFrameCounter );
209
210     // The 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     // The camera node is missing or disconnected.
220     TASK_LOG_FMT(Debug::General, " =F  No Camera  FC:%d\n", mFrameCounter );
221     return false;
222   }
223
224   return true;
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         mNotifyTrigger = true;
305       }
306     }
307
308     break;
309
310     default:
311       break;
312   }
313
314   TASK_LOG_FMT( Debug::General, " EXIT FC:%d State:%s Notify:%s\n", mFrameCounter, STATE_STRING(mState), mNotifyTrigger?"T":"F");
315 }
316
317 bool RenderTask::IsWaitingToRender()
318 {
319   TASK_LOG_FMT(Debug::Verbose, " State:%s waiting:%s \n", STATE_STRING(mState), mWaitingToRender?"T":"F");
320   return mWaitingToRender;
321 }
322
323 bool RenderTask::HasRendered()
324 {
325   bool notify = false;
326   if( mNotifyTrigger == true )
327   {
328     ++mRenderedOnceCounter;
329     mState = RENDERED_ONCE_AND_NOTIFIED;
330     mNotifyTrigger = false;
331     notify = true;
332   }
333
334   TASK_LOG_FMT(Debug::Verbose, " State:%s hasRendered:%s \n", STATE_STRING(mState), notify?"T":"F");
335   return notify;
336 }
337
338 unsigned int RenderTask::GetRenderedOnceCounter() const
339 {
340   return mRenderedOnceCounter;
341 }
342
343
344 const Matrix& RenderTask::GetViewMatrix( BufferIndex bufferIndex ) const
345 {
346   DALI_ASSERT_DEBUG( NULL != mCamera );
347
348   return mCamera->GetViewMatrix( bufferIndex );
349 }
350
351 SceneGraph::Camera& RenderTask::GetCamera() const
352 {
353   DALI_ASSERT_DEBUG( NULL != mCamera );
354   return *mCamera;
355 }
356
357 const Matrix& RenderTask::GetProjectionMatrix( BufferIndex bufferIndex ) const
358 {
359   DALI_ASSERT_DEBUG( NULL != mCamera );
360
361   return mCamera->GetProjectionMatrix( bufferIndex );
362 }
363
364 void RenderTask::PrepareRenderInstruction( RenderInstruction& instruction, BufferIndex updateBufferIndex )
365 {
366   DALI_ASSERT_DEBUG( NULL != 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 : NULL,
376                      mClearEnabled ? &GetClearColor( updateBufferIndex ) : NULL );
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 = NULL;
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::ResetDefaultProperties( BufferIndex updateBufferIndex )
455 {
456   // Reset default properties
457   mViewportPosition.ResetToBaseValue( updateBufferIndex );
458   mViewportSize.ResetToBaseValue( updateBufferIndex );
459   mClearColor.ResetToBaseValue( updateBufferIndex );
460 }
461
462 RenderTask::RenderTask()
463 : mViewportPosition( Vector2::ZERO),
464   mViewportSize( Vector2::ZERO),
465   mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
466   mRenderMessageDispatcher( NULL ),
467   mRenderSyncTracker( NULL ),
468   mSourceNode( NULL ),
469   mCameraNode( NULL ),
470   mCamera( NULL ),
471   mFrameBuffer(0),
472   mWaitingToRender( false ),
473   mNotifyTrigger( false ),
474   mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
475   mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
476   mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE ),
477   mState( (Dali::RenderTask::DEFAULT_REFRESH_RATE == Dali::RenderTask::REFRESH_ALWAYS)
478           ? RENDER_CONTINUOUSLY
479           : RENDER_ONCE_WAITING_FOR_RESOURCES ),
480   mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
481   mFrameCounter( 0u ),
482   mRenderedOnceCounter( 0u ),
483   mRequiresSync( false )
484 {
485 }
486
487 } // namespace SceneGraph
488
489 } // namespace Internal
490
491 } // namespace Dali