Level up Dali::Internal::FreeList as Dali::FreeList
[platform/core/uifw/dali-core.git] / dali / internal / update / render-tasks / scene-graph-render-task.cpp
1 /*
2  * Copyright (c) 2021 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/internal/render/common/render-instruction.h>
23 #include <dali/internal/render/common/render-tracker.h>
24 #include <dali/internal/update/controllers/render-message-dispatcher.h>
25 #include <dali/internal/update/nodes/node.h>
26 #include <dali/public-api/math/matrix.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 namespace SceneGraph
35 {
36 RenderTask* RenderTask::New()
37 {
38   return new RenderTask();
39 }
40
41 RenderTask::~RenderTask()
42 {
43   if(mSourceNode)
44   {
45     mSourceNode->RemoveObserver(*this);
46     if(mExclusive)
47     {
48       mSourceNode->SetExclusiveRenderTask(nullptr);
49     }
50   }
51   if(mCameraNode)
52   {
53     mCameraNode->RemoveObserver(*this);
54   }
55   if(mRenderSyncTracker)
56   {
57     mRenderMessageDispatcher->RemoveRenderTracker(*mRenderSyncTracker);
58   }
59 }
60
61 void RenderTask::Initialize(RenderMessageDispatcher& renderMessageDispatcher)
62 {
63   mRenderMessageDispatcher = &renderMessageDispatcher;
64 }
65
66 void RenderTask::SetSourceNode(Node* node)
67 {
68   // Stop observing the old node (if we were)
69   if(mSourceNode)
70   {
71     mSourceNode->RemoveObserver(*this);
72     if(this == mSourceNode->GetExclusiveRenderTask())
73     {
74       mSourceNode->SetExclusiveRenderTask(nullptr);
75     }
76   }
77
78   mSourceNode = node;
79
80   if(mSourceNode)
81   {
82     mSourceNode->AddObserver(*this);
83     if(mExclusive)
84     {
85       mSourceNode->SetExclusiveRenderTask(this);
86     }
87   }
88   SetActiveStatus();
89 }
90
91 Node* RenderTask::GetSourceNode() const
92 {
93   return mSourceNode;
94 }
95
96 void RenderTask::SetExclusive(bool exclusive)
97 {
98   mExclusive = exclusive;
99
100   if(mSourceNode)
101   {
102     if(mExclusive)
103     {
104       mSourceNode->SetExclusiveRenderTask(this);
105     }
106     else if(this == mSourceNode->GetExclusiveRenderTask())
107     {
108       mSourceNode->SetExclusiveRenderTask(nullptr);
109     }
110   }
111 }
112
113 bool RenderTask::IsExclusive() const
114 {
115   return mExclusive;
116 }
117
118 void RenderTask::SetCamera(Node* cameraNode, Camera* camera)
119 {
120   if(mCameraNode)
121   {
122     mCameraNode->RemoveObserver(*this);
123   }
124
125   mCameraNode = cameraNode;
126   mCamera     = camera;
127
128   if(mCameraNode)
129   {
130     mCameraNode->AddObserver(*this);
131   }
132   SetActiveStatus();
133 }
134
135 void RenderTask::SetFrameBuffer(Render::FrameBuffer* frameBuffer)
136 {
137   mFrameBuffer = frameBuffer;
138 }
139
140 Render::FrameBuffer* RenderTask::GetFrameBuffer()
141 {
142   return mFrameBuffer;
143 }
144
145 bool RenderTask::QueryViewport(BufferIndex bufferIndex, Viewport& viewport) const
146 {
147   if(!GetViewportEnabled(bufferIndex))
148   {
149     return false;
150   }
151
152   viewport.x      = static_cast<int>(mViewportPosition[bufferIndex].x);  // truncated
153   viewport.y      = static_cast<int>(mViewportPosition[bufferIndex].y);  // truncated
154   viewport.width  = static_cast<int>(mViewportSize[bufferIndex].width);  // truncated
155   viewport.height = static_cast<int>(mViewportSize[bufferIndex].height); // truncated
156
157   return true;
158 }
159
160 void RenderTask::SetClearColor(BufferIndex updateBufferIndex, const Vector4& value)
161 {
162   mClearColor.Set(updateBufferIndex, value);
163 }
164
165 const Vector4& RenderTask::GetClearColor(BufferIndex bufferIndex) const
166 {
167   return mClearColor[bufferIndex];
168 }
169
170 void RenderTask::BakeClearColor(BufferIndex updateBufferIndex, const Vector4& value)
171 {
172   mClearColor.Bake(updateBufferIndex, value);
173 }
174
175 void RenderTask::SetClearEnabled(bool enabled)
176 {
177   mClearEnabled = enabled;
178 }
179
180 bool RenderTask::GetClearEnabled() const
181 {
182   return mClearEnabled;
183 }
184
185 void RenderTask::SetCullMode(bool mode)
186 {
187   mCullMode = mode;
188 }
189
190 bool RenderTask::GetCullMode() const
191 {
192   return mCullMode;
193 }
194
195 void RenderTask::SetRefreshRate(uint32_t refreshRate)
196 {
197   DALI_LOG_TRACE_METHOD_FMT(gRenderTaskLogFilter, "this:%p RefreshRate:%d\n", this, refreshRate);
198
199   mRefreshRate = refreshRate;
200
201   if(mRefreshRate > 0)
202   {
203     mState = RENDER_CONTINUOUSLY;
204   }
205   else
206   {
207     mState           = RENDER_ONCE_WAITING_FOR_RESOURCES;
208     mWaitingToRender = true;
209     mNotifyTrigger   = false;
210   }
211
212   mFrameCounter = 0u;
213 }
214
215 uint32_t RenderTask::GetRefreshRate() const
216 {
217   return mRefreshRate;
218 }
219
220 bool RenderTask::ReadyToRender(BufferIndex updateBufferIndex)
221 {
222   return mActive;
223 }
224
225 bool RenderTask::IsRenderRequired()
226 {
227   bool required = false;
228
229   switch(mState)
230   {
231     case RENDER_CONTINUOUSLY:
232     {
233       required = (mFrameCounter == 0);
234       break;
235     }
236     case RENDER_ONCE_WAITING_FOR_RESOURCES:
237     {
238       required = true;
239       break;
240     }
241     default:
242     {
243       required = false;
244       break;
245     }
246   }
247
248   TASK_LOG_FMT(Debug::General, " State:%s = %s\n", STATE_STRING(mState), required ? "T" : "F");
249
250   return required;
251 }
252
253 // Called every frame regardless of whether render was required.
254 // If render was not required, ignore resourcesFinished.
255 void RenderTask::UpdateState()
256 {
257   TASK_LOG_FMT(Debug::General, "FC:%d State:%s RR:%d\n", mFrameCounter, STATE_STRING(mState), mRefreshRate);
258
259   switch(mState)
260   {
261     case RENDER_CONTINUOUSLY:
262     {
263       if(mRefreshRate != Dali::RenderTask::REFRESH_ALWAYS)
264       {
265         if(mFrameCounter == 0)
266         {
267           ++mFrameCounter; // Only start skipping frames when resources are loaded
268         }
269         else // Continue counting to skip frames
270         {
271           ++mFrameCounter;
272           if(mFrameCounter >= mRefreshRate)
273           {
274             mFrameCounter = 0;
275           }
276         }
277       }
278       // else do nothing
279     }
280     break;
281
282     case RENDER_ONCE_WAITING_FOR_RESOURCES:
283     {
284       mState = RENDERED_ONCE;
285     }
286     break;
287
288     case RENDERED_ONCE:
289     {
290       mWaitingToRender = true;
291       mNotifyTrigger   = false;
292       if(mFrameBuffer)
293       {
294         if(!mRenderSyncTracker || (mRenderSyncTracker && mRenderSyncTracker->IsSynced()))
295         {
296           mWaitingToRender = false;
297           mNotifyTrigger   = true;
298         }
299       }
300       else
301       {
302         mWaitingToRender = false;
303         mNotifyTrigger   = true;
304       }
305     }
306
307     break;
308
309     default:
310       break;
311   }
312
313   TASK_LOG_FMT(Debug::General, " EXIT FC:%d State:%s Notify:%s\n", mFrameCounter, STATE_STRING(mState), mNotifyTrigger ? "T" : "F");
314 }
315
316 bool RenderTask::IsWaitingToRender()
317 {
318   TASK_LOG_FMT(Debug::Verbose, " State:%s waiting:%s \n", STATE_STRING(mState), mWaitingToRender ? "T" : "F");
319   return mWaitingToRender;
320 }
321
322 bool RenderTask::HasRendered()
323 {
324   bool notify = false;
325   if(mNotifyTrigger == true)
326   {
327     ++mRenderedOnceCounter;
328     mState         = RENDERED_ONCE_AND_NOTIFIED;
329     mNotifyTrigger = false;
330     notify         = true;
331   }
332
333   TASK_LOG_FMT(Debug::Verbose, " State:%s hasRendered:%s \n", STATE_STRING(mState), notify ? "T" : "F");
334   return notify;
335 }
336
337 uint32_t RenderTask::GetRenderedOnceCounter() const
338 {
339   return mRenderedOnceCounter;
340 }
341
342 const Matrix& RenderTask::GetViewMatrix(BufferIndex bufferIndex) const
343 {
344   DALI_ASSERT_DEBUG(nullptr != mCamera);
345
346   return mCamera->GetViewMatrix(bufferIndex);
347 }
348
349 SceneGraph::Camera& RenderTask::GetCamera() const
350 {
351   DALI_ASSERT_DEBUG(nullptr != mCamera);
352   return *mCamera;
353 }
354
355 const Matrix& RenderTask::GetProjectionMatrix(BufferIndex bufferIndex) const
356 {
357   DALI_ASSERT_DEBUG(nullptr != mCamera);
358
359   return mCamera->GetProjectionMatrix(bufferIndex);
360 }
361
362 RenderInstruction& RenderTask::PrepareRenderInstruction(BufferIndex updateBufferIndex)
363 {
364   DALI_ASSERT_DEBUG(nullptr != mCamera);
365
366   TASK_LOG(Debug::General);
367
368   Viewport viewport;
369   bool     viewportSet = QueryViewport(updateBufferIndex, viewport);
370
371   mRenderInstruction[updateBufferIndex].Reset(mCamera,
372                                               GetFrameBuffer(),
373                                               viewportSet ? &viewport : nullptr,
374                                               mClearEnabled ? &GetClearColor(updateBufferIndex) : nullptr);
375
376   if(mRequiresSync &&
377      mRefreshRate == Dali::RenderTask::REFRESH_ONCE)
378   {
379     // create tracker if one doesn't yet exist.
380     if(!mRenderSyncTracker)
381     {
382       mRenderSyncTracker = new Render::RenderTracker();
383       mRenderMessageDispatcher->AddRenderTracker(*mRenderSyncTracker);
384     }
385     mRenderInstruction[updateBufferIndex].mRenderTracker = mRenderSyncTracker;
386   }
387   else
388   {
389     // no sync needed, texture FBOs are "ready" the same frame they are rendered to
390     mRenderInstruction[updateBufferIndex].mRenderTracker = nullptr;
391   }
392
393   return mRenderInstruction[updateBufferIndex];
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(nullptr),
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