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