2 * Copyright (c) 2021 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 void RenderTask::SetClearColor(BufferIndex updateBufferIndex, const Vector4& value)
172 mClearColor.Set(updateBufferIndex, value);
175 const Vector4& RenderTask::GetClearColor(BufferIndex bufferIndex) const
177 return mClearColor[bufferIndex];
180 void RenderTask::BakeClearColor(BufferIndex updateBufferIndex, const Vector4& value)
182 mClearColor.Bake(updateBufferIndex, value);
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 != mCamera);
356 return mCamera->GetViewMatrix(bufferIndex);
359 SceneGraph::Camera& RenderTask::GetCamera() const
361 DALI_ASSERT_DEBUG(nullptr != mCamera);
365 const Matrix& RenderTask::GetProjectionMatrix(BufferIndex bufferIndex) const
367 DALI_ASSERT_DEBUG(nullptr != mCamera);
369 return mCamera->GetProjectionMatrix(bufferIndex);
372 RenderInstruction& RenderTask::PrepareRenderInstruction(BufferIndex updateBufferIndex)
374 DALI_ASSERT_DEBUG(nullptr != mCamera);
376 TASK_LOG(Debug::General);
379 bool viewportSet = QueryViewport(updateBufferIndex, viewport);
381 mRenderInstruction[updateBufferIndex].Reset(mCamera,
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 return mRenderInstruction[updateBufferIndex];
406 bool RenderTask::ViewMatrixUpdated()
411 retval = mCamera->ViewMatrixUpdated();
416 void RenderTask::UpdateViewport(BufferIndex updateBufferIndex, Vector2 sceneSize, Vector3 cameraPosition)
418 if(GetViewportGuideNode() && GetViewportGuideNode()->ConnectedToScene())
420 Vector3 worldPosition = GetViewportGuideNode()->GetWorldPosition(updateBufferIndex);
421 worldPosition -= cameraPosition;
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));
433 void RenderTask::SetViewportPosition(BufferIndex updateBufferIndex, const Vector2& value)
435 mViewportPosition.Set(updateBufferIndex, value);
438 const Vector2& RenderTask::GetViewportPosition(BufferIndex bufferIndex) const
440 return mViewportPosition[bufferIndex];
443 void RenderTask::BakeViewportPosition(BufferIndex updateBufferIndex, const Vector2& value)
445 mViewportPosition.Bake(updateBufferIndex, value);
448 void RenderTask::SetViewportSize(BufferIndex updateBufferIndex, const Vector2& value)
450 mViewportSize.Set(updateBufferIndex, value);
453 const Vector2& RenderTask::GetViewportSize(BufferIndex bufferIndex) const
455 return mViewportSize[bufferIndex];
458 void RenderTask::BakeViewportSize(BufferIndex updateBufferIndex, const Vector2& value)
460 mViewportSize.Bake(updateBufferIndex, value);
463 bool RenderTask::GetViewportEnabled(BufferIndex bufferIndex) const
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)
476 void RenderTask::SetSyncRequired(bool requiresSync)
478 mRequiresSync = requiresSync;
481 void RenderTask::PropertyOwnerConnected(PropertyOwner& owner)
483 // check if we've gone from inactive to active
487 void RenderTask::PropertyOwnerDisconnected(BufferIndex /*updateBufferIndex*/, PropertyOwner& owner)
489 mActive = false; // if either source or camera disconnected, we're no longer active
492 void RenderTask::PropertyOwnerDestroyed(PropertyOwner& owner)
494 if(static_cast<PropertyOwner*>(mSourceNode) == &owner)
496 mSourceNode = nullptr;
498 else if(static_cast<PropertyOwner*>(mCameraNode) == &owner)
500 mCameraNode = nullptr;
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),
514 mFrameBuffer(nullptr),
515 mRefreshRate(Dali::RenderTask::DEFAULT_REFRESH_RATE),
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),
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)
531 void RenderTask::SetActiveStatus()
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());
540 } // namespace SceneGraph
542 } // namespace Internal