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