2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
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>
28 #include <dali/internal/update/render-tasks/scene-graph-render-task-debug.h>
36 RenderTask* RenderTask::New()
38 return new RenderTask();
41 RenderTask::~RenderTask()
45 mSourceNode->RemoveObserver(*this);
48 mSourceNode->SetExclusiveRenderTask(nullptr);
53 mCameraNode->RemoveObserver(*this);
55 if(mRenderSyncTracker)
57 mRenderMessageDispatcher->RemoveRenderTracker(*mRenderSyncTracker);
61 void RenderTask::Initialize(RenderMessageDispatcher& renderMessageDispatcher)
63 mRenderMessageDispatcher = &renderMessageDispatcher;
66 void RenderTask::SetSourceNode(Node* node)
68 // Stop observing the old node (if we were)
71 mSourceNode->RemoveObserver(*this);
72 if(this == mSourceNode->GetExclusiveRenderTask())
74 mSourceNode->SetExclusiveRenderTask(nullptr);
82 mSourceNode->AddObserver(*this);
85 mSourceNode->SetExclusiveRenderTask(this);
91 Node* RenderTask::GetSourceNode() const
96 void RenderTask::SetViewportGuideNode(Node* node)
98 mViewportGuideNode = node;
101 Node* RenderTask::GetViewportGuideNode() const
103 return mViewportGuideNode;
106 void RenderTask::SetExclusive(bool exclusive)
108 mExclusive = exclusive;
114 mSourceNode->SetExclusiveRenderTask(this);
116 else if(this == mSourceNode->GetExclusiveRenderTask())
118 mSourceNode->SetExclusiveRenderTask(nullptr);
123 bool RenderTask::IsExclusive() const
128 void RenderTask::SetCamera(Node* cameraNode, Camera* camera)
132 mCameraNode->RemoveObserver(*this);
135 mCameraNode = cameraNode;
140 mCameraNode->AddObserver(*this);
145 void RenderTask::SetFrameBuffer(Render::FrameBuffer* frameBuffer)
147 mFrameBuffer = frameBuffer;
150 Render::FrameBuffer* RenderTask::GetFrameBuffer()
155 bool RenderTask::QueryViewport(BufferIndex bufferIndex, Viewport& viewport) const
157 if(!GetViewportEnabled(bufferIndex))
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
170 const Vector4& RenderTask::GetClearColor(BufferIndex bufferIndex) const
172 return mClearColor[bufferIndex];
175 void RenderTask::SetClearEnabled(bool enabled)
177 mClearEnabled = enabled;
180 bool RenderTask::GetClearEnabled() const
182 return mClearEnabled;
185 void RenderTask::SetCullMode(bool mode)
190 bool RenderTask::GetCullMode() const
195 void RenderTask::SetRefreshRate(uint32_t refreshRate)
197 DALI_LOG_TRACE_METHOD_FMT(gRenderTaskLogFilter, "this:%p RefreshRate:%d\n", this, refreshRate);
199 mRefreshRate = refreshRate;
203 mState = RENDER_CONTINUOUSLY;
207 mState = RENDER_ONCE_WAITING_FOR_RESOURCES;
208 mWaitingToRender = true;
209 mNotifyTrigger = false;
215 uint32_t RenderTask::GetRefreshRate() const
220 bool RenderTask::ReadyToRender(BufferIndex updateBufferIndex)
225 bool RenderTask::IsRenderRequired()
227 bool required = false;
231 case RENDER_CONTINUOUSLY:
233 required = (mFrameCounter == 0);
236 case RENDER_ONCE_WAITING_FOR_RESOURCES:
248 TASK_LOG_FMT(Debug::General, " State:%s = %s\n", STATE_STRING(mState), required ? "T" : "F");
253 // Called every frame regardless of whether render was required.
254 // If render was not required, ignore resourcesFinished.
255 void RenderTask::UpdateState()
257 TASK_LOG_FMT(Debug::General, "FC:%d State:%s RR:%d\n", mFrameCounter, STATE_STRING(mState), mRefreshRate);
261 case RENDER_CONTINUOUSLY:
263 if(mRefreshRate != Dali::RenderTask::REFRESH_ALWAYS)
265 if(mFrameCounter == 0)
267 ++mFrameCounter; // Only start skipping frames when resources are loaded
269 else // Continue counting to skip frames
272 if(mFrameCounter >= mRefreshRate)
282 case RENDER_ONCE_WAITING_FOR_RESOURCES:
284 mState = RENDERED_ONCE;
290 mWaitingToRender = true;
291 mNotifyTrigger = false;
294 if(!mRenderSyncTracker || (mRenderSyncTracker && mRenderSyncTracker->IsSynced()))
296 mWaitingToRender = false;
297 mNotifyTrigger = true;
302 mWaitingToRender = false;
303 mNotifyTrigger = true;
313 TASK_LOG_FMT(Debug::General, " EXIT FC:%d State:%s Notify:%s\n", mFrameCounter, STATE_STRING(mState), mNotifyTrigger ? "T" : "F");
316 bool RenderTask::IsWaitingToRender()
318 TASK_LOG_FMT(Debug::Verbose, " State:%s waiting:%s \n", STATE_STRING(mState), mWaitingToRender ? "T" : "F");
319 return mWaitingToRender;
322 bool RenderTask::HasRendered()
325 if(mNotifyTrigger == true)
327 ++mRenderedOnceCounter;
328 mState = RENDERED_ONCE_AND_NOTIFIED;
329 mNotifyTrigger = false;
333 TASK_LOG_FMT(Debug::Verbose, " State:%s hasRendered:%s \n", STATE_STRING(mState), notify ? "T" : "F");
337 uint32_t RenderTask::GetRenderedOnceCounter() const
339 return mRenderedOnceCounter;
342 const Matrix& RenderTask::GetViewMatrix(BufferIndex bufferIndex) const
344 DALI_ASSERT_DEBUG(nullptr != mCamera);
346 return mCamera->GetViewMatrix(bufferIndex);
349 const SceneGraph::Camera& RenderTask::GetCamera() const
351 DALI_ASSERT_DEBUG(nullptr != mCamera);
355 const Matrix& RenderTask::GetProjectionMatrix(BufferIndex bufferIndex) const
357 DALI_ASSERT_DEBUG(nullptr != mCamera);
359 return mCamera->GetProjectionMatrix(bufferIndex);
362 RenderInstruction& RenderTask::PrepareRenderInstruction(BufferIndex updateBufferIndex)
364 DALI_ASSERT_DEBUG(nullptr != mCamera);
366 TASK_LOG(Debug::General);
369 bool viewportSet = QueryViewport(updateBufferIndex, viewport);
371 mRenderInstruction[updateBufferIndex].Reset(mCamera,
373 viewportSet ? &viewport : nullptr,
374 mClearEnabled ? &GetClearColor(updateBufferIndex) : nullptr);
377 mRefreshRate == Dali::RenderTask::REFRESH_ONCE)
379 // create tracker if one doesn't yet exist.
380 if(!mRenderSyncTracker)
382 mRenderSyncTracker = new Render::RenderTracker();
383 mRenderMessageDispatcher->AddRenderTracker(*mRenderSyncTracker);
385 mRenderInstruction[updateBufferIndex].mRenderTracker = mRenderSyncTracker;
389 // no sync needed, texture FBOs are "ready" the same frame they are rendered to
390 mRenderInstruction[updateBufferIndex].mRenderTracker = nullptr;
393 return mRenderInstruction[updateBufferIndex];
396 bool RenderTask::ViewMatrixUpdated()
401 retval = mCamera->ViewMatrixUpdated();
406 void RenderTask::UpdateViewport(BufferIndex updateBufferIndex, Vector2 sceneSize, Vector3 cameraPosition)
408 if(GetViewportGuideNode() && GetViewportGuideNode()->ConnectedToScene())
410 Vector3 worldPosition = GetViewportGuideNode()->GetWorldPosition(updateBufferIndex);
411 worldPosition -= cameraPosition;
413 Vector3 nodeSize = GetViewportGuideNode()->GetSize(updateBufferIndex) * GetViewportGuideNode()->GetWorldScale(updateBufferIndex);
414 Vector2 halfSceneSize(sceneSize.width * 0.5f, sceneSize.height * 0.5f); // World position origin is center of scene
415 Vector3 halfNodeSize(nodeSize * 0.5f);
416 Vector2 screenPosition(halfSceneSize.width + worldPosition.x - halfNodeSize.x,
417 halfSceneSize.height + worldPosition.y - halfNodeSize.y);
419 /* This is an implicit constraint - the properties will be dirty until the node
420 * is removed. (RenderTask::Impl manages this)
422 mViewportPosition.Set(updateBufferIndex, screenPosition);
423 mViewportSize.Set(updateBufferIndex, Vector2(nodeSize));
427 const Vector2& RenderTask::GetViewportPosition(BufferIndex bufferIndex) const
429 return mViewportPosition[bufferIndex];
432 const Vector2& RenderTask::GetViewportSize(BufferIndex bufferIndex) const
434 return mViewportSize[bufferIndex];
437 bool RenderTask::GetViewportEnabled(BufferIndex bufferIndex) const
439 if(fabsf(mViewportPosition[bufferIndex].x) > Math::MACHINE_EPSILON_1 ||
440 fabsf(mViewportPosition[bufferIndex].y) > Math::MACHINE_EPSILON_1 ||
441 fabsf(mViewportSize[bufferIndex].width) > Math::MACHINE_EPSILON_1 ||
442 fabsf(mViewportSize[bufferIndex].height) > Math::MACHINE_EPSILON_1)
450 void RenderTask::SetSyncRequired(bool requiresSync)
452 mRequiresSync = requiresSync;
455 void RenderTask::PropertyOwnerConnected(PropertyOwner& owner)
457 // check if we've gone from inactive to active
461 void RenderTask::PropertyOwnerDisconnected(BufferIndex /*updateBufferIndex*/, PropertyOwner& owner)
463 mActive = false; // if either source or camera disconnected, we're no longer active
466 void RenderTask::PropertyOwnerDestroyed(PropertyOwner& owner)
468 if(static_cast<PropertyOwner*>(mSourceNode) == &owner)
470 mSourceNode = nullptr;
472 else if(static_cast<PropertyOwner*>(mCameraNode) == &owner)
474 mCameraNode = nullptr;
478 RenderTask::RenderTask()
479 : mViewportPosition(Vector2::ZERO),
480 mViewportSize(Vector2::ZERO),
481 mClearColor(Dali::RenderTask::DEFAULT_CLEAR_COLOR),
482 mRenderMessageDispatcher(nullptr),
483 mRenderSyncTracker(nullptr),
484 mSourceNode(nullptr),
485 mCameraNode(nullptr),
486 mViewportGuideNode(nullptr),
488 mFrameBuffer(nullptr),
489 mRefreshRate(Dali::RenderTask::DEFAULT_REFRESH_RATE),
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),
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)
505 void RenderTask::SetActiveStatus()
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());
514 } // namespace SceneGraph
516 } // namespace Internal