Remove RenderSurface from Core
[platform/core/uifw/dali-core.git] / dali / internal / update / render-tasks / scene-graph-render-task.cpp
1 /*
2  * Copyright (c) 2020 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 RenderInstruction& RenderTask::PrepareRenderInstruction( 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   mRenderInstruction[updateBufferIndex].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     mRenderInstruction[updateBufferIndex].mRenderTracker = mRenderSyncTracker;
388   }
389   else
390   {
391     // no sync needed, texture FBOs are "ready" the same frame they are rendered to
392     mRenderInstruction[updateBufferIndex].mRenderTracker = nullptr;
393   }
394
395   return mRenderInstruction[updateBufferIndex];
396 }
397
398 bool RenderTask::ViewMatrixUpdated()
399 {
400   bool retval = false;
401   if( mCamera )
402   {
403     retval = mCamera->ViewMatrixUpdated();
404   }
405   return retval;
406 }
407
408 void RenderTask::SetViewportPosition( BufferIndex updateBufferIndex, const Vector2& value )
409 {
410   mViewportPosition.Set( updateBufferIndex, value );
411 }
412
413 const Vector2& RenderTask::GetViewportPosition( BufferIndex bufferIndex ) const
414 {
415   return mViewportPosition[bufferIndex];
416 }
417
418 void RenderTask::BakeViewportPosition( BufferIndex updateBufferIndex, const Vector2& value )
419 {
420   mViewportPosition.Bake( updateBufferIndex, value );
421 }
422
423 void RenderTask::SetViewportSize( BufferIndex updateBufferIndex, const Vector2& value )
424 {
425   mViewportSize.Set( updateBufferIndex, value );
426 }
427
428 const Vector2& RenderTask::GetViewportSize( BufferIndex bufferIndex ) const
429 {
430   return mViewportSize[bufferIndex];
431 }
432
433 void RenderTask::BakeViewportSize( BufferIndex updateBufferIndex, const Vector2& value )
434 {
435   mViewportSize.Bake( updateBufferIndex, value );
436 }
437
438 bool RenderTask::GetViewportEnabled( BufferIndex bufferIndex ) const
439 {
440   if(fabsf(mViewportPosition[bufferIndex].x) > Math::MACHINE_EPSILON_1 ||
441      fabsf(mViewportPosition[bufferIndex].y) > Math::MACHINE_EPSILON_1 ||
442      fabsf(mViewportSize[bufferIndex].width) > Math::MACHINE_EPSILON_1 ||
443      fabsf(mViewportSize[bufferIndex].height) > Math::MACHINE_EPSILON_1)
444   {
445     return true;
446   }
447
448   return false;
449 }
450
451 void RenderTask::SetSyncRequired( bool requiresSync )
452 {
453   mRequiresSync = requiresSync;
454 }
455
456 void RenderTask::PropertyOwnerConnected( PropertyOwner& owner )
457 {
458   // check if we've gone from inactive to active
459   SetActiveStatus();
460 }
461
462 void RenderTask::PropertyOwnerDisconnected( BufferIndex /*updateBufferIndex*/, PropertyOwner& owner )
463 {
464   mActive = false; // if either source or camera disconnected, we're no longer active
465 }
466
467 void RenderTask::PropertyOwnerDestroyed( PropertyOwner& owner )
468 {
469   if( static_cast<PropertyOwner*>( mSourceNode ) == &owner )
470   {
471     mSourceNode = nullptr;
472   }
473   else if( static_cast<PropertyOwner*>( mCameraNode ) == &owner )
474   {
475     mCameraNode = nullptr;
476   }
477 }
478
479 RenderTask::RenderTask()
480 : mViewportPosition( Vector2::ZERO),
481   mViewportSize( Vector2::ZERO),
482   mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
483   mRenderMessageDispatcher( nullptr ),
484   mRenderSyncTracker( nullptr ),
485   mSourceNode( nullptr ),
486   mCameraNode( nullptr ),
487   mCamera( nullptr ),
488   mFrameBuffer(0),
489   mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
490   mFrameCounter( 0u ),
491   mRenderedOnceCounter( 0u ),
492   mState( (Dali::RenderTask::DEFAULT_REFRESH_RATE == Dali::RenderTask::REFRESH_ALWAYS)
493           ? RENDER_CONTINUOUSLY
494           : RENDER_ONCE_WAITING_FOR_RESOURCES ),
495   mRequiresSync( false ),
496   mActive( false ),
497   mWaitingToRender( false ),
498   mNotifyTrigger( false ),
499   mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
500   mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
501   mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE )
502 {
503 }
504
505 void RenderTask::SetActiveStatus()
506 {
507   // must have a source and camera both connected to scene
508   mActive = ( mSourceNode && mSourceNode->ConnectedToScene() &&
509               mCameraNode && mCameraNode->ConnectedToScene() && mCamera );
510   TASK_LOG_FMT( Debug::General, " Source node(%x) active %d.  Frame counter: %d\n", mSourceNode, mSourceNode && mSourceNode->ConnectedToScene(), mFrameCounter );
511   TASK_LOG_FMT( Debug::General, " Camera node(%x) active %d\n", mCameraNode, mCameraNode && mCameraNode->ConnectedToScene() );
512 }
513
514 } // namespace SceneGraph
515
516 } // namespace Internal
517
518 } // namespace Dali