2 * Copyright (c) 2022 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->RemoveExclusiveRenderTask(this);
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 mSourceNode->RemoveExclusiveRenderTask(this);
79 mSourceNode->AddObserver(*this);
82 mSourceNode->AddExclusiveRenderTask(this);
88 Node* RenderTask::GetSourceNode() const
93 void RenderTask::SetViewportGuideNode(Node* node)
95 mViewportGuideNode = node;
98 Node* RenderTask::GetViewportGuideNode() const
100 return mViewportGuideNode;
103 void RenderTask::SetExclusive(bool exclusive)
105 mExclusive = exclusive;
111 mSourceNode->AddExclusiveRenderTask(this);
115 mSourceNode->RemoveExclusiveRenderTask(this);
120 bool RenderTask::IsExclusive() const
125 void RenderTask::SetCamera(Node* cameraNode, Camera* camera)
129 mCameraNode->RemoveObserver(*this);
132 mCameraNode = cameraNode;
137 mCameraNode->AddObserver(*this);
142 void RenderTask::SetFrameBuffer(Render::FrameBuffer* frameBuffer)
144 mFrameBuffer = frameBuffer;
147 Render::FrameBuffer* RenderTask::GetFrameBuffer()
152 bool RenderTask::QueryViewport(BufferIndex bufferIndex, Viewport& viewport) const
154 if(!GetViewportEnabled(bufferIndex))
159 viewport.x = static_cast<int>(mViewportPosition[bufferIndex].x); // truncated
160 viewport.y = static_cast<int>(mViewportPosition[bufferIndex].y); // truncated
161 viewport.width = static_cast<int>(mViewportSize[bufferIndex].width); // truncated
162 viewport.height = static_cast<int>(mViewportSize[bufferIndex].height); // truncated
167 void RenderTask::SetClearColor(BufferIndex updateBufferIndex, const Vector4& value)
169 mClearColor.Set(updateBufferIndex, value);
172 const Vector4& RenderTask::GetClearColor(BufferIndex bufferIndex) const
174 return mClearColor[bufferIndex];
177 void RenderTask::BakeClearColor(BufferIndex updateBufferIndex, const Vector4& value)
179 mClearColor.Bake(updateBufferIndex, value);
182 void RenderTask::SetClearEnabled(bool enabled)
184 mClearEnabled = enabled;
187 bool RenderTask::GetClearEnabled() const
189 return mClearEnabled;
192 void RenderTask::SetCullMode(bool mode)
197 bool RenderTask::GetCullMode() const
202 void RenderTask::SetRefreshRate(uint32_t refreshRate)
204 DALI_LOG_TRACE_METHOD_FMT(gRenderTaskLogFilter, "this:%p RefreshRate:%d\n", this, refreshRate);
206 mRefreshRate = refreshRate;
210 mState = RENDER_CONTINUOUSLY;
214 mState = RENDER_ONCE_WAITING_FOR_RESOURCES;
215 mWaitingToRender = true;
216 mNotifyTrigger = false;
222 uint32_t RenderTask::GetRefreshRate() const
227 bool RenderTask::ReadyToRender(BufferIndex updateBufferIndex)
232 bool RenderTask::IsRenderRequired()
234 bool required = false;
238 case RENDER_CONTINUOUSLY:
240 required = (mFrameCounter == 0);
243 case RENDER_ONCE_WAITING_FOR_RESOURCES:
255 TASK_LOG_FMT(Debug::General, " State:%s = %s\n", STATE_STRING(mState), required ? "T" : "F");
260 // Called every frame regardless of whether render was required.
261 // If render was not required, ignore resourcesFinished.
262 void RenderTask::UpdateState()
264 TASK_LOG_FMT(Debug::General, "FC:%d State:%s RR:%d\n", mFrameCounter, STATE_STRING(mState), mRefreshRate);
268 case RENDER_CONTINUOUSLY:
270 if(mRefreshRate != Dali::RenderTask::REFRESH_ALWAYS)
272 if(mFrameCounter == 0)
274 ++mFrameCounter; // Only start skipping frames when resources are loaded
276 else // Continue counting to skip frames
279 if(mFrameCounter >= mRefreshRate)
289 case RENDER_ONCE_WAITING_FOR_RESOURCES:
291 mState = RENDERED_ONCE;
297 mWaitingToRender = true;
298 mNotifyTrigger = false;
301 if(!mRenderSyncTracker || (mRenderSyncTracker && mRenderSyncTracker->IsSynced()))
303 mWaitingToRender = false;
304 mNotifyTrigger = true;
309 mWaitingToRender = false;
310 mNotifyTrigger = true;
320 TASK_LOG_FMT(Debug::General, " EXIT FC:%d State:%s Notify:%s\n", mFrameCounter, STATE_STRING(mState), mNotifyTrigger ? "T" : "F");
323 bool RenderTask::IsWaitingToRender()
325 TASK_LOG_FMT(Debug::Verbose, " State:%s waiting:%s \n", STATE_STRING(mState), mWaitingToRender ? "T" : "F");
326 return mWaitingToRender;
329 bool RenderTask::HasRendered()
332 if(mNotifyTrigger == true)
334 ++mRenderedOnceCounter;
335 mState = RENDERED_ONCE_AND_NOTIFIED;
336 mNotifyTrigger = false;
340 TASK_LOG_FMT(Debug::Verbose, " State:%s hasRendered:%s \n", STATE_STRING(mState), notify ? "T" : "F");
344 uint32_t RenderTask::GetRenderedOnceCounter() const
346 return mRenderedOnceCounter;
349 const Matrix& RenderTask::GetViewMatrix(BufferIndex bufferIndex) const
351 DALI_ASSERT_DEBUG(nullptr != mCamera);
353 return mCamera->GetViewMatrix(bufferIndex);
356 const SceneGraph::Camera& RenderTask::GetCamera() const
358 DALI_ASSERT_DEBUG(nullptr != mCamera);
362 const Matrix& RenderTask::GetProjectionMatrix(BufferIndex bufferIndex) const
364 DALI_ASSERT_DEBUG(nullptr != mCamera);
366 return mCamera->GetProjectionMatrix(bufferIndex);
369 RenderInstruction& RenderTask::PrepareRenderInstruction(BufferIndex updateBufferIndex)
371 DALI_ASSERT_DEBUG(nullptr != mCamera);
373 TASK_LOG(Debug::General);
376 bool viewportSet = QueryViewport(updateBufferIndex, viewport);
378 mRenderInstruction[updateBufferIndex].Reset(mCamera,
380 viewportSet ? &viewport : nullptr,
381 mClearEnabled ? &GetClearColor(updateBufferIndex) : nullptr);
384 mRefreshRate == Dali::RenderTask::REFRESH_ONCE)
386 // create tracker if one doesn't yet exist.
387 if(!mRenderSyncTracker)
389 mRenderSyncTracker = new Render::RenderTracker();
390 mRenderMessageDispatcher->AddRenderTracker(*mRenderSyncTracker);
392 mRenderInstruction[updateBufferIndex].mRenderTracker = mRenderSyncTracker;
396 // no sync needed, texture FBOs are "ready" the same frame they are rendered to
397 mRenderInstruction[updateBufferIndex].mRenderTracker = nullptr;
400 mRenderInstruction[updateBufferIndex].mRenderPassTag = mRenderPassTag;
401 return mRenderInstruction[updateBufferIndex];
404 bool RenderTask::ViewMatrixUpdated()
409 retval = mCamera->ViewMatrixUpdated();
414 void RenderTask::UpdateViewport(BufferIndex updateBufferIndex, Vector2 sceneSize, Vector3 cameraPosition)
416 if(GetViewportGuideNode() && GetViewportGuideNode()->ConnectedToScene())
418 Vector3 worldPosition = GetViewportGuideNode()->GetWorldPosition(updateBufferIndex);
419 worldPosition -= cameraPosition;
421 Vector3 nodeSize = GetViewportGuideNode()->GetSize(updateBufferIndex) * GetViewportGuideNode()->GetWorldScale(updateBufferIndex);
422 Vector2 halfSceneSize(sceneSize.width * 0.5f, sceneSize.height * 0.5f); // World position origin is center of scene
423 Vector3 halfNodeSize(nodeSize * 0.5f);
424 Vector2 screenPosition(halfSceneSize.width + worldPosition.x - halfNodeSize.x,
425 halfSceneSize.height + worldPosition.y - halfNodeSize.y);
426 SetViewportPosition(updateBufferIndex, screenPosition);
427 SetViewportSize(updateBufferIndex, Vector2(nodeSize));
431 void RenderTask::SetViewportPosition(BufferIndex updateBufferIndex, const Vector2& value)
433 mViewportPosition.Set(updateBufferIndex, value);
436 const Vector2& RenderTask::GetViewportPosition(BufferIndex bufferIndex) const
438 return mViewportPosition[bufferIndex];
441 void RenderTask::BakeViewportPosition(BufferIndex updateBufferIndex, const Vector2& value)
443 mViewportPosition.Bake(updateBufferIndex, value);
446 void RenderTask::SetViewportSize(BufferIndex updateBufferIndex, const Vector2& value)
448 mViewportSize.Set(updateBufferIndex, value);
451 const Vector2& RenderTask::GetViewportSize(BufferIndex bufferIndex) const
453 return mViewportSize[bufferIndex];
456 void RenderTask::BakeViewportSize(BufferIndex updateBufferIndex, const Vector2& value)
458 mViewportSize.Bake(updateBufferIndex, value);
461 bool RenderTask::GetViewportEnabled(BufferIndex bufferIndex) const
463 if(fabsf(mViewportPosition[bufferIndex].x) > Math::MACHINE_EPSILON_1 ||
464 fabsf(mViewportPosition[bufferIndex].y) > Math::MACHINE_EPSILON_1 ||
465 fabsf(mViewportSize[bufferIndex].width) > Math::MACHINE_EPSILON_1 ||
466 fabsf(mViewportSize[bufferIndex].height) > Math::MACHINE_EPSILON_1)
474 void RenderTask::SetSyncRequired(bool requiresSync)
476 mRequiresSync = requiresSync;
479 void RenderTask::SetRenderPassTag(uint32_t renderPassTag)
481 mRenderPassTag = renderPassTag;
484 void RenderTask::PropertyOwnerConnected(PropertyOwner& owner)
486 // check if we've gone from inactive to active
490 void RenderTask::PropertyOwnerDisconnected(BufferIndex /*updateBufferIndex*/, PropertyOwner& owner)
492 mActive = false; // if either source or camera disconnected, we're no longer active
495 void RenderTask::PropertyOwnerDestroyed(PropertyOwner& owner)
497 if(static_cast<PropertyOwner*>(mSourceNode) == &owner)
499 mSourceNode = nullptr;
501 else if(static_cast<PropertyOwner*>(mCameraNode) == &owner)
503 mCameraNode = nullptr;
507 RenderTask::RenderTask()
508 : mViewportPosition(Vector2::ZERO),
509 mViewportSize(Vector2::ZERO),
510 mClearColor(Dali::RenderTask::DEFAULT_CLEAR_COLOR),
511 mRenderMessageDispatcher(nullptr),
512 mRenderSyncTracker(nullptr),
513 mSourceNode(nullptr),
514 mCameraNode(nullptr),
515 mViewportGuideNode(nullptr),
517 mFrameBuffer(nullptr),
518 mRefreshRate(Dali::RenderTask::DEFAULT_REFRESH_RATE),
520 mRenderedOnceCounter(0u),
521 mState((Dali::RenderTask::DEFAULT_REFRESH_RATE == Dali::RenderTask::REFRESH_ALWAYS)
522 ? RENDER_CONTINUOUSLY
523 : RENDER_ONCE_WAITING_FOR_RESOURCES),
524 mRequiresSync(false),
526 mWaitingToRender(false),
527 mNotifyTrigger(false),
528 mExclusive(Dali::RenderTask::DEFAULT_EXCLUSIVE),
529 mClearEnabled(Dali::RenderTask::DEFAULT_CLEAR_ENABLED),
530 mCullMode(Dali::RenderTask::DEFAULT_CULL_MODE)
534 void RenderTask::SetActiveStatus()
536 // must have a source and camera both connected to scene
537 mActive = (mSourceNode && mSourceNode->ConnectedToScene() &&
538 mCameraNode && mCameraNode->ConnectedToScene() && mCamera);
539 TASK_LOG_FMT(Debug::General, " Source node(%x) active %d. Frame counter: %d\n", mSourceNode, mSourceNode && mSourceNode->ConnectedToScene(), mFrameCounter);
540 TASK_LOG_FMT(Debug::General, " Camera node(%x) active %d\n", mCameraNode, mCameraNode && mCameraNode->ConnectedToScene());
543 } // namespace SceneGraph
545 } // namespace Internal