Changed remaining image types to use Texture internally
[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 void RenderTask::SetFrameBuffer( Render::FrameBuffer* frameBuffer )
129 {
130   mFrameBuffer = frameBuffer;
131 }
132
133 Render::FrameBuffer* RenderTask::GetFrameBuffer()
134 {
135   return mFrameBuffer;
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 == mCamera )
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   mCamera->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 if( mFrameBuffer )
347       {
348         if( !mRenderSyncTracker || (mRenderSyncTracker && mRenderSyncTracker->IsSynced() ))
349         {
350           mWaitingToRender = false;
351           mNotifyTrigger = true;
352         }
353       }
354       else
355       {
356         mNotifyTrigger = true;
357       }
358     }
359
360     break;
361
362     default:
363       break;
364   }
365
366   TASK_LOG_FMT( Debug::General, " EXIT FC:%d State:%s Notify:%s\n", mFrameCounter, STATE_STRING(mState), mNotifyTrigger?"T":"F");
367 }
368
369 bool RenderTask::IsWaitingToRender()
370 {
371   TASK_LOG_FMT(Debug::Verbose, " State:%s waiting:%s \n", STATE_STRING(mState), mWaitingToRender?"T":"F");
372   return mWaitingToRender;
373 }
374
375 bool RenderTask::HasRendered()
376 {
377   bool notify = false;
378   if( mNotifyTrigger == true )
379   {
380     ++mRenderedOnceCounter;
381     mState = RENDERED_ONCE_AND_NOTIFIED;
382     mNotifyTrigger = false;
383     notify = true;
384   }
385
386   TASK_LOG_FMT(Debug::Verbose, " State:%s hasRendered:%s \n", STATE_STRING(mState), notify?"T":"F");
387   return notify;
388 }
389
390 unsigned int RenderTask::GetRenderedOnceCounter() const
391 {
392   return mRenderedOnceCounter;
393 }
394
395
396 const Matrix& RenderTask::GetViewMatrix( BufferIndex bufferIndex ) const
397 {
398   DALI_ASSERT_DEBUG( NULL != mCamera );
399
400   return mCamera->GetViewMatrix( bufferIndex );
401 }
402
403 SceneGraph::Camera& RenderTask::GetCamera() const
404 {
405   DALI_ASSERT_DEBUG( NULL != mCamera );
406   return *mCamera;
407 }
408
409 const Matrix& RenderTask::GetProjectionMatrix( BufferIndex bufferIndex ) const
410 {
411   DALI_ASSERT_DEBUG( NULL != mCamera );
412
413   return mCamera->GetProjectionMatrix( bufferIndex );
414 }
415
416 void RenderTask::PrepareRenderInstruction( RenderInstruction& instruction, BufferIndex updateBufferIndex )
417 {
418   DALI_ASSERT_DEBUG( NULL != mCamera );
419
420   TASK_LOG(Debug::General);
421
422   Viewport viewport;
423   bool viewportSet = QueryViewport( updateBufferIndex, viewport );
424
425   instruction.Reset( mCamera,
426                      GetFrameBufferId(),
427                      GetFrameBuffer(),
428                      viewportSet ? &viewport : NULL,
429                      mClearEnabled ? &GetClearColor( updateBufferIndex ) : NULL );
430
431   if( mRequiresSync &&
432       mRefreshRate == Dali::RenderTask::REFRESH_ONCE &&
433       mResourcesFinished )
434   {
435     // create tracker if one doesn't yet exist.
436     if( !mRenderSyncTracker )
437     {
438       mRenderSyncTracker = new Render::RenderTracker();
439       mRenderMessageDispatcher->AddRenderTracker( *mRenderSyncTracker );
440     }
441     instruction.mRenderTracker = mRenderSyncTracker;
442   }
443   else
444   {
445     // no sync needed, texture FBOs are "ready" the same frame they are rendered to
446     instruction.mRenderTracker = NULL;
447   }
448 }
449
450 bool RenderTask::ViewMatrixUpdated()
451 {
452   bool retval = false;
453   if( mCamera )
454   {
455     retval = mCamera->ViewMatrixUpdated();
456   }
457   return retval;
458 }
459
460 void RenderTask::SetViewportPosition( BufferIndex updateBufferIndex, const Vector2& value )
461 {
462   mViewportPosition.Set( updateBufferIndex, value );
463 }
464
465 const Vector2& RenderTask::GetViewportPosition( BufferIndex bufferIndex ) const
466 {
467   return mViewportPosition[bufferIndex];
468 }
469
470 void RenderTask::BakeViewportPosition( BufferIndex updateBufferIndex, const Vector2& value )
471 {
472   mViewportPosition.Bake( updateBufferIndex, value );
473 }
474
475 void RenderTask::SetViewportSize( BufferIndex updateBufferIndex, const Vector2& value )
476 {
477   mViewportSize.Set( updateBufferIndex, value );
478 }
479
480 const Vector2& RenderTask::GetViewportSize( BufferIndex bufferIndex ) const
481 {
482   return mViewportSize[bufferIndex];
483 }
484
485 void RenderTask::BakeViewportSize( BufferIndex updateBufferIndex, const Vector2& value )
486 {
487   mViewportSize.Bake( updateBufferIndex, value );
488 }
489
490 bool RenderTask::GetViewportEnabled( BufferIndex bufferIndex ) const
491 {
492   if(fabsf(mViewportPosition[bufferIndex].x) > Math::MACHINE_EPSILON_1 ||
493      fabsf(mViewportPosition[bufferIndex].y) > Math::MACHINE_EPSILON_1 ||
494      fabsf(mViewportSize[bufferIndex].width) > Math::MACHINE_EPSILON_1 ||
495      fabsf(mViewportSize[bufferIndex].height) > Math::MACHINE_EPSILON_1)
496   {
497     return true;
498   }
499
500   return false;
501 }
502
503 void RenderTask::SetSyncRequired( bool requiresSync )
504 {
505   mRequiresSync = requiresSync;
506 }
507
508 void RenderTask::ResetDefaultProperties( BufferIndex updateBufferIndex )
509 {
510   // Reset default properties
511   mViewportPosition.ResetToBaseValue( updateBufferIndex );
512   mViewportSize.ResetToBaseValue( updateBufferIndex );
513   mClearColor.ResetToBaseValue( updateBufferIndex );
514 }
515
516 RenderTask::RenderTask()
517 : mViewportPosition( Vector2::ZERO),
518   mViewportSize( Vector2::ZERO),
519   mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
520   mRenderMessageDispatcher( NULL ),
521   mResourceManager( NULL ),
522   mRenderSyncTracker( NULL ),
523   mSourceNode( NULL ),
524   mCameraNode( NULL ),
525   mCamera( NULL ),
526   mFrameBufferResourceId( 0 ),
527   mFrameBuffer(0),
528   mResourcesFinished( false ),
529   mWaitingToRender( false ),
530   mNotifyTrigger( false ),
531   mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
532   mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
533   mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE ),
534   mRenderTarget( NULL ),
535   mState( (Dali::RenderTask::DEFAULT_REFRESH_RATE == Dali::RenderTask::REFRESH_ALWAYS)
536           ? RENDER_CONTINUOUSLY
537           : RENDER_ONCE_WAITING_FOR_RESOURCES ),
538   mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
539   mFrameCounter( 0u ),
540   mRenderedOnceCounter( 0u ),
541   mTargetIsNativeFramebuffer( false ),
542   mRequiresSync( false )
543 {
544 }
545
546 } // namespace SceneGraph
547
548 } // namespace Internal
549
550 } // namespace Dali