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/event/render-tasks/render-task-impl.h>
22 #include <cstring> // for strcmp
25 #include <dali/internal/event/actors/actor-impl.h>
26 #include <dali/internal/event/actors/camera-actor-impl.h>
27 #include <dali/internal/event/common/event-thread-services.h>
28 #include <dali/internal/event/common/projection.h>
29 #include <dali/internal/event/common/property-helper.h>
30 #include <dali/internal/event/common/scene-impl.h>
31 #include <dali/internal/event/common/stage-impl.h>
32 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
33 #include <dali/internal/update/nodes/node.h>
34 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
35 #include <dali/public-api/common/dali-common.h>
36 #include <dali/public-api/object/type-registry.h>
38 #if defined(DEBUG_ENABLED)
41 Debug::Filter* gLogRender = Debug::Filter::New(Debug::Concise, false, "LOG_RENDER_TASK");
49 namespace // For internal properties
53 // Name Type writable animatable constraint-input enum for index-checking
54 DALI_PROPERTY_TABLE_BEGIN
55 DALI_PROPERTY("viewportPosition", VECTOR2, true, true, true, Dali::RenderTask::Property::VIEWPORT_POSITION)
56 DALI_PROPERTY("viewportSize", VECTOR2, true, true, true, Dali::RenderTask::Property::VIEWPORT_SIZE)
57 DALI_PROPERTY("clearColor", VECTOR4, true, true, true, Dali::RenderTask::Property::CLEAR_COLOR)
58 DALI_PROPERTY("requiresSync", BOOLEAN, true, false, false, Dali::RenderTask::Property::REQUIRES_SYNC)
59 DALI_PROPERTY_TABLE_END(DEFAULT_OBJECT_PROPERTY_START_INDEX, RenderTaskDefaultProperties)
63 const char* const SIGNAL_FINISHED = "finished";
65 TypeRegistration mType(typeid(Dali::RenderTask), typeid(Dali::BaseHandle), nullptr, RenderTaskDefaultProperties);
67 SignalConnectorType signalConnector1(mType, SIGNAL_FINISHED, &RenderTask::DoConnectSignal);
69 } // Unnamed namespace
71 RenderTaskPtr RenderTask::New(Actor* sourceActor, CameraActor* cameraActor, RenderTaskList& renderTaskList, bool isOverlayTask)
73 // create scene object first so it's guaranteed to exist for the event side
74 auto sceneObject = SceneGraph::RenderTask::New();
76 // pass the pointer to base for message passing
77 RenderTaskPtr task(new RenderTask(sceneObject, renderTaskList));
79 // transfer scene object ownership to update manager
80 const SceneGraph::RenderTaskList& parentSceneObject = renderTaskList.GetSceneObject();
81 OwnerPointer<SceneGraph::RenderTask> transferOwnership(sceneObject);
84 AddOverlayTaskMessage(task->GetEventThreadServices(), parentSceneObject, transferOwnership);
88 AddTaskMessage(task->GetEventThreadServices(), parentSceneObject, transferOwnership);
91 // Set the default source & camera actors
92 task->SetSourceActor(sourceActor);
93 task->SetCameraActor(cameraActor);
95 // no need for additional messages as scene objects defaults match ours
99 void RenderTask::SetSourceActor(Actor* actor)
101 mSourceActor.SetActor(actor);
104 SetSourceNodeMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), &actor->GetNode());
108 SetSourceNodeMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), nullptr);
111 // set the actor on exclusive container for hit testing
112 mRenderTaskList.SetExclusive(this, mExclusive);
115 Actor* RenderTask::GetSourceActor() const
117 return mSourceActor.GetActor();
120 void RenderTask::SetExclusive(bool exclusive)
122 if(mExclusive != exclusive)
124 mExclusive = exclusive;
126 mRenderTaskList.SetExclusive(this, exclusive);
128 // scene object is being used in a separate thread; queue a message to set the value
129 SetExclusiveMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), mExclusive);
133 bool RenderTask::IsExclusive() const
138 void RenderTask::SetInputEnabled(bool enabled)
140 mInputEnabled = enabled;
143 bool RenderTask::GetInputEnabled() const
145 return mInputEnabled;
148 void RenderTask::SetCameraActor(CameraActor* cameraActor)
150 mCameraActor.SetActor(cameraActor);
153 SetCameraMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), &cameraActor->GetNode(), &cameraActor->GetCameraSceneObject());
157 SetCameraMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), nullptr, nullptr);
160 // set the actor on exclusive container for hit testing
161 mRenderTaskList.SetExclusive(this, mExclusive);
164 CameraActor* RenderTask::GetCameraActor() const
166 if(mCameraActor.GetActor())
168 return static_cast<CameraActor*>(mCameraActor.GetActor());
173 void RenderTask::SetFrameBuffer(FrameBufferPtr frameBuffer)
175 mFrameBuffer = frameBuffer;
176 Render::FrameBuffer* renderFrameBufferPtr(nullptr);
179 renderFrameBufferPtr = mFrameBuffer->GetRenderObject();
182 SetFrameBufferMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), renderFrameBufferPtr);
185 FrameBuffer* RenderTask::GetFrameBuffer() const
187 return mFrameBuffer.Get();
190 void RenderTask::SetScreenToFrameBufferFunction(ScreenToFrameBufferFunction conversionFunction)
192 mScreenToFrameBufferFunction = conversionFunction;
195 RenderTask::ScreenToFrameBufferFunction RenderTask::GetScreenToFrameBufferFunction() const
197 return mScreenToFrameBufferFunction;
200 void RenderTask::SetScreenToFrameBufferMappingActor(Dali::Actor& mappingActor)
202 mInputMappingActor = WeakHandle<Dali::Actor>(mappingActor);
205 Dali::Actor RenderTask::GetScreenToFrameBufferMappingActor() const
207 return mInputMappingActor.GetHandle();
210 void RenderTask::SetViewportGuideActor(Actor* actor)
212 mViewportGuideActor.SetActor(actor);
215 SetViewportGuideNodeMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), &actor->GetNode());
219 SetViewportGuideNodeMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), nullptr);
223 Actor* RenderTask::GetViewportGuideActor() const
225 return mViewportGuideActor.GetActor();
228 void RenderTask::ResetViewportGuideActor()
230 SetViewportGuideActor(nullptr);
232 BakeViewportPositionMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), mViewportPosition);
233 BakeViewportSizeMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), mViewportSize);
236 void RenderTask::SetViewportPosition(const Vector2& value)
238 mViewportPosition = value;
240 BakeViewportPositionMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), value);
243 Vector2 RenderTask::GetCurrentViewportPosition() const
245 return GetRenderTaskSceneObject().GetViewportPosition(GetEventThreadServices().GetEventBufferIndex());
248 void RenderTask::SetViewportSize(const Vector2& value)
250 mViewportSize = value;
252 BakeViewportSizeMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), value);
255 Vector2 RenderTask::GetCurrentViewportSize() const
257 return GetRenderTaskSceneObject().GetViewportSize(GetEventThreadServices().GetEventBufferIndex());
260 void RenderTask::SetViewport(const Viewport& viewport)
262 SetViewportPosition(Vector2(static_cast<float>(viewport.x), static_cast<float>(viewport.y)));
263 SetViewportSize(Vector2(static_cast<float>(viewport.width), static_cast<float>(viewport.height)));
266 void RenderTask::GetViewport(Viewport& viewPort) const
268 BufferIndex bufferIndex = GetEventThreadServices().GetEventBufferIndex();
270 if(!GetRenderTaskSceneObject().GetViewportEnabled(bufferIndex))
272 Internal::Stage* stage = Internal::Stage::GetCurrent();
275 Vector2 size(stage->GetSize());
276 Actor* sourceActor = mSourceActor.GetActor();
277 if(sourceActor && sourceActor->OnScene())
279 Scene& scene = sourceActor->GetScene();
280 size = scene.GetSize();
283 viewPort.x = viewPort.y = 0;
284 viewPort.width = static_cast<int32_t>(size.width); // truncated
285 viewPort.height = static_cast<int32_t>(size.height); // truncated
290 const Vector2& position = GetRenderTaskSceneObject().GetViewportPosition(bufferIndex);
291 const Vector2& size = GetRenderTaskSceneObject().GetViewportSize(bufferIndex);
292 viewPort.x = static_cast<int32_t>(position.x); // truncated
293 viewPort.y = static_cast<int32_t>(position.y); // truncated
294 viewPort.width = static_cast<int32_t>(size.width); // truncated
295 viewPort.height = static_cast<int32_t>(size.height); // truncated
299 void RenderTask::SetClearColor(const Vector4& color)
301 if(mClearColor != color)
305 // scene object is being used in a separate thread; queue a message to set the value
306 BakeClearColorMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), color);
310 const Vector4& RenderTask::GetClearColor() const
312 return GetRenderTaskSceneObject().GetClearColor(GetEventThreadServices().GetEventBufferIndex());
315 void RenderTask::SetSyncRequired(bool requiresSync)
317 if(mRequiresSync != requiresSync)
319 mRequiresSync = requiresSync;
321 // scene object is being used in a separate thread; queue a message to set the value
322 SetSyncRequiredMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), requiresSync);
326 bool RenderTask::IsSyncRequired() const
328 return mRequiresSync;
331 void RenderTask::SetClearEnabled(bool enabled)
333 if(mClearEnabled != enabled)
335 mClearEnabled = enabled;
337 // scene object is being used in a separate thread; queue a message to set the value
338 SetClearEnabledMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), mClearEnabled);
342 bool RenderTask::GetClearEnabled() const
344 return mClearEnabled;
347 void RenderTask::SetCullMode(bool mode)
349 if(mCullMode != mode)
353 // scene object is being used in a separate thread; queue a message to set the value
354 SetCullModeMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), mCullMode);
358 bool RenderTask::GetCullMode() const
363 void RenderTask::SetRefreshRate(uint32_t refreshRate)
365 DALI_LOG_TRACE_METHOD_FMT(gLogRender, "this:%p rate:%d\n", this, refreshRate);
366 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::SetRefreshRate(this:%p, %d)\n", this, refreshRate);
368 mRefreshRate = refreshRate; // cached for GetRefreshRate()
370 // Note - even when refreshRate is the same as mRefreshRate, a message should be sent
372 // sceneObject is being used in a separate thread; queue a message to set the value
373 SetRefreshRateMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), refreshRate);
376 uint32_t RenderTask::GetRefreshRate() const
381 bool RenderTask::IsHittable(Vector2& screenCoords) const
383 // True when input is enabled, source & camera actor are valid
384 bool inputEnabled(false);
386 Actor* sourceActor = GetSourceActor();
387 CameraActor* cameraActor = GetCameraActor();
390 nullptr != sourceActor &&
391 sourceActor->OnScene() &&
392 nullptr != cameraActor &&
393 cameraActor->OnScene())
395 // If the actors are rendered off-screen, then the screen coordinates must be converted
396 // and the conversion function will tell us if they are inside or outside
397 if(TranslateCoordinates(screenCoords))
399 // This is a suitable render-task for input handling
407 bool RenderTask::TranslateCoordinates(Vector2& screenCoords) const
409 // return true for on-screen tasks
411 // If the actors are rendered off-screen, then the screen coordinates must be converted
412 // the function should only be called for offscreen tasks
413 Dali::Actor mappingActor = GetScreenToFrameBufferMappingActor();
415 if(mFrameBuffer && mappingActor)
417 Internal::Actor* inputMappingActor = &GetImplementation(mappingActor);
418 CameraActor* localCamera = GetCameraActor();
419 StagePtr stage = Stage::GetCurrent();
422 Vector2 size(stage->GetSize());
423 CameraActor* defaultCamera(&stage->GetDefaultCameraActor());
424 Actor* sourceActor = mSourceActor.GetActor();
425 if(sourceActor && sourceActor->OnScene())
427 Scene& scene = sourceActor->GetScene();
428 size = scene.GetSize();
429 defaultCamera = &scene.GetDefaultCameraActor();
435 viewport.x = viewport.y = 0;
436 viewport.width = static_cast<int32_t>(size.width); // truncated
437 viewport.height = static_cast<int32_t>(size.height); // truncated
439 float localX, localY;
440 inside = inputMappingActor->ScreenToLocal(defaultCamera->GetViewMatrix(), defaultCamera->GetProjectionMatrix(), viewport, localX, localY, screenCoords.x, screenCoords.y);
441 Vector3 actorSize = inputMappingActor->GetCurrentSize();
442 if(inside && localX >= 0.f && localX <= actorSize.x && localY >= 0.f && localY <= actorSize.y)
444 screenCoords.x = localX;
445 screenCoords.y = localY;
458 else if(mFrameBuffer && mScreenToFrameBufferFunction)
460 inside = mScreenToFrameBufferFunction(screenCoords);
465 bool RenderTask::WorldToViewport(const Vector3& position, float& viewportX, float& viewportY) const
467 CameraActor* cam = GetCameraActor();
469 Vector4 pos(position);
472 Vector4 viewportPosition;
475 GetViewport(viewport);
477 bool ok = ProjectFull(pos,
478 cam->GetViewMatrix(),
479 cam->GetProjectionMatrix(),
480 static_cast<float>(viewport.x), // truncated
481 static_cast<float>(viewport.y), // truncated
482 static_cast<float>(viewport.width), // truncated
483 static_cast<float>(viewport.height), // truncated
487 viewportX = viewportPosition.x;
488 viewportY = viewportPosition.y;
494 bool RenderTask::ViewportToLocal(Actor* actor, float viewportX, float viewportY, float& localX, float& localY) const
496 return actor->ScreenToLocal(*this, localX, localY, viewportX, viewportY);
499 const SceneGraph::RenderTask& RenderTask::GetRenderTaskSceneObject() const
501 return *static_cast<const SceneGraph::RenderTask*>(mUpdateObject);
504 RenderTaskList& RenderTask::GetRenderTaskList() const
506 return mRenderTaskList;
509 /********************************************************************************
510 ******************************** PROPERTY METHODS **************************
511 ********************************************************************************/
513 void RenderTask::SetDefaultProperty(Property::Index index, const Property::Value& property)
517 case Dali::RenderTask::Property::VIEWPORT_POSITION:
519 SetViewportPosition(property.Get<Vector2>());
522 case Dali::RenderTask::Property::VIEWPORT_SIZE:
524 SetViewportSize(property.Get<Vector2>());
527 case Dali::RenderTask::Property::CLEAR_COLOR:
529 SetClearColor(property.Get<Vector4>());
532 case Dali::RenderTask::Property::REQUIRES_SYNC:
534 SetSyncRequired(property.Get<bool>());
545 Property::Value RenderTask::GetDefaultProperty(Property::Index index) const
547 Property::Value value;
551 case Dali::RenderTask::Property::VIEWPORT_POSITION:
553 value = mViewportPosition;
556 case Dali::RenderTask::Property::VIEWPORT_SIZE:
558 value = mViewportSize;
561 case Dali::RenderTask::Property::CLEAR_COLOR:
566 case Dali::RenderTask::Property::REQUIRES_SYNC:
568 value = IsSyncRequired();
574 DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
582 Property::Value RenderTask::GetDefaultPropertyCurrentValue(Property::Index index) const
584 Property::Value value;
588 case Dali::RenderTask::Property::VIEWPORT_POSITION:
590 value = GetCurrentViewportPosition();
593 case Dali::RenderTask::Property::VIEWPORT_SIZE:
595 value = GetCurrentViewportSize();
598 case Dali::RenderTask::Property::CLEAR_COLOR:
600 value = GetClearColor();
603 case Dali::RenderTask::Property::REQUIRES_SYNC:
605 value = IsSyncRequired();
611 DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
619 void RenderTask::OnNotifyDefaultPropertyAnimation(Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType)
621 switch(animationType)
624 case Animation::BETWEEN:
628 case Dali::RenderTask::Property::VIEWPORT_POSITION:
630 value.Get(mViewportPosition);
633 case Dali::RenderTask::Property::VIEWPORT_SIZE:
635 value.Get(mViewportSize);
638 case Dali::RenderTask::Property::CLEAR_COLOR:
640 value.Get(mClearColor);
643 case Dali::RenderTask::Property::REQUIRES_SYNC:
646 // Nothing to do as not animatable
657 case Dali::RenderTask::Property::VIEWPORT_POSITION:
659 AdjustValue<Vector2>(mViewportPosition, value);
662 case Dali::RenderTask::Property::VIEWPORT_SIZE:
664 AdjustValue<Vector2>(mViewportSize, value);
667 case Dali::RenderTask::Property::CLEAR_COLOR:
669 AdjustValue<Vector4>(mClearColor, value);
672 case Dali::RenderTask::Property::REQUIRES_SYNC:
675 // Nothing to do as not animatable
684 const SceneGraph::PropertyBase* RenderTask::GetSceneObjectAnimatableProperty(Property::Index index) const
686 const SceneGraph::PropertyBase* property(nullptr);
690 case Dali::RenderTask::Property::VIEWPORT_POSITION:
692 property = &GetRenderTaskSceneObject().mViewportPosition;
695 case Dali::RenderTask::Property::VIEWPORT_SIZE:
697 property = &GetRenderTaskSceneObject().mViewportSize;
700 case Dali::RenderTask::Property::CLEAR_COLOR:
702 property = &GetRenderTaskSceneObject().mClearColor;
712 // not our property, ask base
713 property = Object::GetSceneObjectAnimatableProperty(index);
719 const PropertyInputImpl* RenderTask::GetSceneObjectInputProperty(Property::Index index) const
721 // animatable properties are input as well, Object::GetSceneObjectInputProperty does the same so no need to call it
722 return GetSceneObjectAnimatableProperty(index);
725 bool RenderTask::HasFinished()
727 bool finished = false;
728 const uint32_t counter = GetRenderTaskSceneObject().GetRenderedOnceCounter();
730 if(mRefreshOnceCounter < counter)
733 mRefreshOnceCounter = counter;
736 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::HasFinished()=%s SCRT:%p SC\n", finished ? "T" : "F", &GetRenderTaskSceneObject());
741 void RenderTask::EmitSignalFinish()
743 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::EmitSignalFinish(this:%p)\n", this);
745 if(!mSignalFinished.Empty())
747 Dali::RenderTask handle(this);
748 mSignalFinished.Emit(handle);
752 Dali::RenderTask::RenderTaskSignalType& RenderTask::FinishedSignal()
754 return mSignalFinished;
757 bool RenderTask::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
759 bool connected(true);
760 RenderTask* renderTask = static_cast<RenderTask*>(object); // TypeRegistry guarantees that this is the correct type.
762 if(0 == strcmp(signalName.c_str(), SIGNAL_FINISHED))
764 renderTask->FinishedSignal().Connect(tracker, functor);
768 // signalName does not match any signal
775 RenderTask::RenderTask(const SceneGraph::RenderTask* sceneObject, RenderTaskList& renderTaskList)
776 : Object(sceneObject),
779 mViewportGuideActor(),
780 mInputMappingActor(),
781 mRenderTaskList(renderTaskList),
782 mClearColor(Dali::RenderTask::DEFAULT_CLEAR_COLOR),
783 mViewportPosition(Vector2::ZERO),
784 mViewportSize(Vector2::ZERO),
785 mRefreshRate(Dali::RenderTask::DEFAULT_REFRESH_RATE),
786 mRefreshOnceCounter(0u),
787 mScreenToFrameBufferFunction(Dali::RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION),
788 mExclusive(Dali::RenderTask::DEFAULT_EXCLUSIVE),
789 mInputEnabled(Dali::RenderTask::DEFAULT_INPUT_ENABLED),
790 mClearEnabled(Dali::RenderTask::DEFAULT_CLEAR_ENABLED),
791 mCullMode(Dali::RenderTask::DEFAULT_CULL_MODE),
794 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::RenderTask(this:%p)\n", this);
795 // scene object handles observation of source and camera
798 RenderTask::~RenderTask()
800 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::~RenderTask(this:%p)\n", this);
801 // scene object deletion is handled by our parent
802 // scene object handles observation of source and camera
805 } // namespace Internal