2 * Copyright (c) 2024 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/common/property-resetter.h>
29 #include <dali/internal/update/common/resetter-manager.h> ///< For AddInitializeResetter
31 #include <dali/internal/update/render-tasks/scene-graph-render-task-debug.h>
39 RenderTask* RenderTask::New()
41 return new RenderTask();
44 RenderTask::~RenderTask()
48 mSourceNode->RemoveObserver(*this);
51 mSourceNode->RemoveExclusiveRenderTask(this);
56 mCameraNode->RemoveObserver(*this);
58 if(mRenderSyncTracker)
60 mRenderMessageDispatcher->RemoveRenderTracker(*mRenderSyncTracker);
64 void RenderTask::Initialize(ResetterManager& resetterManager, RenderMessageDispatcher& renderMessageDispatcher)
66 mResetterManager = &resetterManager;
67 mRenderMessageDispatcher = &renderMessageDispatcher;
70 void RenderTask::SetSourceNode(Node* node)
72 // Stop observing the old node (if we were)
75 mSourceNode->RemoveObserver(*this);
76 mSourceNode->RemoveExclusiveRenderTask(this);
83 mSourceNode->AddObserver(*this);
86 mSourceNode->AddExclusiveRenderTask(this);
92 Node* RenderTask::GetSourceNode() const
97 void RenderTask::SetStopperNode(Node* node)
102 Node* RenderTask::GetStopperNode() const
107 void RenderTask::SetViewportGuideNode(Node* node)
109 mViewportGuideNode = node;
112 Node* RenderTask::GetViewportGuideNode() const
114 return mViewportGuideNode;
117 void RenderTask::SetExclusive(bool exclusive)
119 mExclusive = exclusive;
125 mSourceNode->AddExclusiveRenderTask(this);
129 mSourceNode->RemoveExclusiveRenderTask(this);
134 bool RenderTask::IsExclusive() const
139 void RenderTask::SetCamera(Camera* cameraNode)
143 mCameraNode->RemoveObserver(*this);
146 mCameraNode = cameraNode;
150 mCameraNode->AddObserver(*this);
155 void RenderTask::SetFrameBuffer(Render::FrameBuffer* frameBuffer)
157 mFrameBuffer = frameBuffer;
160 Render::FrameBuffer* RenderTask::GetFrameBuffer()
165 bool RenderTask::QueryViewport(BufferIndex bufferIndex, Viewport& viewport) const
167 if(!GetViewportEnabled(bufferIndex))
172 viewport.x = static_cast<int>(mViewportPosition[bufferIndex].x); // truncated
173 viewport.y = static_cast<int>(mViewportPosition[bufferIndex].y); // truncated
174 viewport.width = static_cast<int>(mViewportSize[bufferIndex].width); // truncated
175 viewport.height = static_cast<int>(mViewportSize[bufferIndex].height); // truncated
180 const Vector4& RenderTask::GetClearColor(BufferIndex bufferIndex) const
182 return mClearColor[bufferIndex];
185 void RenderTask::SetClearEnabled(bool enabled)
187 mClearEnabled = enabled;
190 bool RenderTask::GetClearEnabled() const
192 return mClearEnabled;
195 void RenderTask::SetCullMode(bool mode)
200 bool RenderTask::GetCullMode() const
205 void RenderTask::SetRefreshRate(uint32_t refreshRate)
207 DALI_LOG_TRACE_METHOD_FMT(gRenderTaskLogFilter, "this:%p RefreshRate:%d\n", this, refreshRate);
209 mRefreshRate = refreshRate;
213 mState = RENDER_CONTINUOUSLY;
217 mState = RENDER_ONCE_WAITING_FOR_RESOURCES;
218 mWaitingToRender = true;
219 mNotifyTrigger = false;
225 uint32_t RenderTask::GetRefreshRate() const
230 bool RenderTask::ReadyToRender(BufferIndex updateBufferIndex)
235 bool RenderTask::IsRenderRequired()
237 bool required = false;
241 case RENDER_CONTINUOUSLY:
243 required = (mFrameCounter == 0);
246 case RENDER_ONCE_WAITING_FOR_RESOURCES:
258 TASK_LOG_FMT(Debug::General, " State:%s = %s\n", STATE_STRING(mState), required ? "T" : "F");
263 // Called every frame regardless of whether render was required.
264 // If render was not required, ignore resourcesFinished.
265 void RenderTask::UpdateState()
267 TASK_LOG_FMT(Debug::General, "FC:%d State:%s RR:%d\n", mFrameCounter, STATE_STRING(mState), mRefreshRate);
271 case RENDER_CONTINUOUSLY:
273 if(mRefreshRate != Dali::RenderTask::REFRESH_ALWAYS)
275 if(mFrameCounter == 0)
277 ++mFrameCounter; // Only start skipping frames when resources are loaded
279 else // Continue counting to skip frames
282 if(mFrameCounter >= mRefreshRate)
292 case RENDER_ONCE_WAITING_FOR_RESOURCES:
294 mState = RENDERED_ONCE;
300 mWaitingToRender = true;
301 mNotifyTrigger = false;
304 if(!mRenderSyncTracker || (mRenderSyncTracker && mRenderSyncTracker->IsSynced()))
306 mWaitingToRender = false;
307 mNotifyTrigger = true;
312 mWaitingToRender = false;
313 mNotifyTrigger = true;
323 TASK_LOG_FMT(Debug::General, " EXIT FC:%d State:%s Notify:%s\n", mFrameCounter, STATE_STRING(mState), mNotifyTrigger ? "T" : "F");
326 bool RenderTask::IsWaitingToRender()
328 TASK_LOG_FMT(Debug::Verbose, " State:%s waiting:%s \n", STATE_STRING(mState), mWaitingToRender ? "T" : "F");
329 return mWaitingToRender;
332 bool RenderTask::HasRendered()
335 if(mNotifyTrigger == true)
337 ++mRenderedOnceCounter;
338 mState = RENDERED_ONCE_AND_NOTIFIED;
339 mNotifyTrigger = false;
343 TASK_LOG_FMT(Debug::Verbose, " State:%s hasRendered:%s \n", STATE_STRING(mState), notify ? "T" : "F");
347 uint32_t RenderTask::GetRenderedOnceCounter() const
349 return mRenderedOnceCounter;
352 const Matrix& RenderTask::GetViewMatrix(BufferIndex bufferIndex) const
354 DALI_ASSERT_DEBUG(nullptr != mCameraNode);
356 return mCameraNode->GetViewMatrix(bufferIndex);
359 const SceneGraph::Camera& RenderTask::GetCamera() const
361 DALI_ASSERT_DEBUG(nullptr != mCameraNode);
365 const Matrix& RenderTask::GetProjectionMatrix(BufferIndex bufferIndex) const
367 DALI_ASSERT_DEBUG(nullptr != mCameraNode);
369 return mCameraNode->GetProjectionMatrix(bufferIndex);
372 RenderInstruction& RenderTask::PrepareRenderInstruction(BufferIndex updateBufferIndex)
374 DALI_ASSERT_DEBUG(nullptr != mCameraNode);
376 TASK_LOG(Debug::General);
379 bool viewportSet = QueryViewport(updateBufferIndex, viewport);
381 mRenderInstruction[updateBufferIndex].Reset(mCameraNode,
383 viewportSet ? &viewport : nullptr,
384 mClearEnabled ? &GetClearColor(updateBufferIndex) : nullptr);
387 mRefreshRate == Dali::RenderTask::REFRESH_ONCE)
389 // create tracker if one doesn't yet exist.
390 if(!mRenderSyncTracker)
392 mRenderSyncTracker = new Render::RenderTracker();
393 mRenderMessageDispatcher->AddRenderTracker(*mRenderSyncTracker);
395 mRenderInstruction[updateBufferIndex].mRenderTracker = mRenderSyncTracker;
399 // no sync needed, texture FBOs are "ready" the same frame they are rendered to
400 mRenderInstruction[updateBufferIndex].mRenderTracker = nullptr;
403 mRenderInstruction[updateBufferIndex].mRenderPassTag = mRenderPassTag;
404 return mRenderInstruction[updateBufferIndex];
407 bool RenderTask::ViewMatrixUpdated()
412 retval = mCameraNode->ViewMatrixUpdated();
417 void RenderTask::UpdateViewport(BufferIndex updateBufferIndex, Vector2 sceneSize, Vector3 cameraPosition)
419 if(GetViewportGuideNode() && GetViewportGuideNode()->ConnectedToScene())
421 Vector3 worldPosition = GetViewportGuideNode()->GetWorldPosition(updateBufferIndex);
422 worldPosition -= cameraPosition;
424 Vector3 nodeSize = GetViewportGuideNode()->GetSize(updateBufferIndex) * GetViewportGuideNode()->GetWorldScale(updateBufferIndex);
425 Vector2 halfSceneSize(sceneSize.width * 0.5f, sceneSize.height * 0.5f); // World position origin is center of scene
426 Vector3 halfNodeSize(nodeSize * 0.5f);
427 Vector2 screenPosition(halfSceneSize.width + worldPosition.x - halfNodeSize.x,
428 halfSceneSize.height + worldPosition.y - halfNodeSize.y);
430 /* This is an implicit constraint - the properties will be dirty until the node
431 * is removed. (RenderTask::Impl manages this)
433 mViewportPosition.Set(updateBufferIndex, screenPosition);
434 mViewportSize.Set(updateBufferIndex, Vector2(nodeSize));
438 const Vector2& RenderTask::GetViewportPosition(BufferIndex bufferIndex) const
440 return mViewportPosition[bufferIndex];
443 const Vector2& RenderTask::GetViewportSize(BufferIndex bufferIndex) const
445 return mViewportSize[bufferIndex];
448 bool RenderTask::GetViewportEnabled(BufferIndex bufferIndex) const
450 if(fabsf(mViewportPosition[bufferIndex].x) > Math::MACHINE_EPSILON_1 ||
451 fabsf(mViewportPosition[bufferIndex].y) > Math::MACHINE_EPSILON_1 ||
452 fabsf(mViewportSize[bufferIndex].width) > Math::MACHINE_EPSILON_1 ||
453 fabsf(mViewportSize[bufferIndex].height) > Math::MACHINE_EPSILON_1)
461 void RenderTask::SetSyncRequired(bool requiresSync)
463 mRequiresSync = requiresSync;
466 void RenderTask::SetRenderPassTag(uint32_t renderPassTag)
468 mRenderPassTag = renderPassTag;
471 void RenderTask::PropertyOwnerConnected(PropertyOwner& owner)
473 // check if we've gone from inactive to active
477 PropertyOwner::Observer::NotifyReturnType RenderTask::PropertyOwnerDisconnected(BufferIndex /*updateBufferIndex*/, PropertyOwner& owner)
479 mActive = false; // if either source or camera disconnected, we're no longer active
480 return PropertyOwner::Observer::NotifyReturnType::KEEP_OBSERVING;
483 void RenderTask::PropertyOwnerDestroyed(PropertyOwner& owner)
485 if(static_cast<PropertyOwner*>(mSourceNode) == &owner)
487 mSourceNode = nullptr;
489 else if(static_cast<PropertyOwner*>(mCameraNode) == &owner)
491 mCameraNode = nullptr;
494 mActive = false; // if either source or camera destroyed, we're no longer active
497 void RenderTask::AddInitializeResetter(ResetterManager& manager) const
499 OwnerPointer<SceneGraph::PropertyResetterBase> resetterViewportPosition = SceneGraph::BakerResetter::New(*this, mViewportPosition, SceneGraph::BakerResetter::Lifetime::BAKE);
500 OwnerPointer<SceneGraph::PropertyResetterBase> resetterViewportSize = SceneGraph::BakerResetter::New(*this, mViewportSize, SceneGraph::BakerResetter::Lifetime::BAKE);
501 OwnerPointer<SceneGraph::PropertyResetterBase> resetterClearColor = SceneGraph::BakerResetter::New(*this, mClearColor, SceneGraph::BakerResetter::Lifetime::BAKE);
502 manager.AddPropertyResetter(resetterViewportPosition);
503 manager.AddPropertyResetter(resetterViewportSize);
504 manager.AddPropertyResetter(resetterClearColor);
507 RenderTask::RenderTask()
508 : mViewportPosition(Vector2::ZERO),
509 mViewportSize(Vector2::ZERO),
510 mClearColor(Dali::RenderTask::DEFAULT_CLEAR_COLOR),
511 mResetterManager(nullptr),
512 mRenderMessageDispatcher(nullptr),
513 mRenderSyncTracker(nullptr),
514 mSourceNode(nullptr),
515 mStopperNode(nullptr),
516 mCameraNode(nullptr),
517 mViewportGuideNode(nullptr),
518 mFrameBuffer(nullptr),
519 mRefreshRate(Dali::RenderTask::DEFAULT_REFRESH_RATE),
521 mRenderedOnceCounter(0u),
522 mState((Dali::RenderTask::DEFAULT_REFRESH_RATE == Dali::RenderTask::REFRESH_ALWAYS)
523 ? RENDER_CONTINUOUSLY
524 : RENDER_ONCE_WAITING_FOR_RESOURCES),
525 mRequiresSync(false),
527 mWaitingToRender(false),
528 mNotifyTrigger(false),
529 mExclusive(Dali::RenderTask::DEFAULT_EXCLUSIVE),
530 mClearEnabled(Dali::RenderTask::DEFAULT_CLEAR_ENABLED),
531 mCullMode(Dali::RenderTask::DEFAULT_CULL_MODE)
535 void RenderTask::SetActiveStatus()
537 bool oldActive = mActive;
539 // must have a source and camera both connected to scene
540 mActive = (mSourceNode && mSourceNode->ConnectedToScene() &&
541 mCameraNode && mCameraNode->ConnectedToScene());
542 TASK_LOG_FMT(Debug::General, " Source node(%x) active %d. Frame counter: %d\n", mSourceNode, mSourceNode && mSourceNode->ConnectedToScene(), mFrameCounter);
543 TASK_LOG_FMT(Debug::General, " Camera node(%x) active %d\n", mCameraNode, mCameraNode && mCameraNode->ConnectedToScene());
545 if(!oldActive && mActive)
547 // Send resetter only if newly activated
548 AddInitializeResetter(*mResetterManager);
552 } // namespace SceneGraph
554 } // namespace Internal