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/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/update/nodes/node.h>
33 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
34 #include <dali/public-api/common/dali-common.h>
35 #include <dali/public-api/object/type-registry.h>
37 #if defined(DEBUG_ENABLED)
40 Debug::Filter* gLogRender = Debug::Filter::New(Debug::Concise, false, "LOG_RENDER_TASK");
48 namespace // For internal properties
52 // Name Type writable animatable constraint-input enum for index-checking
53 DALI_PROPERTY_TABLE_BEGIN
54 DALI_PROPERTY("viewportPosition", VECTOR2, true, true, true, Dali::RenderTask::Property::VIEWPORT_POSITION)
55 DALI_PROPERTY("viewportSize", VECTOR2, true, true, true, Dali::RenderTask::Property::VIEWPORT_SIZE)
56 DALI_PROPERTY("clearColor", VECTOR4, true, true, true, Dali::RenderTask::Property::CLEAR_COLOR)
57 DALI_PROPERTY("requiresSync", BOOLEAN, true, false, false, Dali::RenderTask::Property::REQUIRES_SYNC)
58 DALI_PROPERTY_TABLE_END(DEFAULT_OBJECT_PROPERTY_START_INDEX, RenderTaskDefaultProperties)
62 const char* const SIGNAL_FINISHED = "finished";
64 TypeRegistration mType(typeid(Dali::RenderTask), typeid(Dali::BaseHandle), nullptr, RenderTaskDefaultProperties);
66 SignalConnectorType signalConnector1(mType, SIGNAL_FINISHED, &RenderTask::DoConnectSignal);
68 } // Unnamed namespace
70 RenderTaskPtr RenderTask::New(Actor* sourceActor, CameraActor* cameraActor, RenderTaskList& renderTaskList)
72 // create scene object first so it's guaranteed to exist for the event side
73 auto sceneObject = SceneGraph::RenderTask::New();
75 // pass the pointer to base for message passing
76 RenderTaskPtr task(new RenderTask(sceneObject, renderTaskList));
78 // transfer scene object ownership to update manager
79 const SceneGraph::RenderTaskList& parentSceneObject = renderTaskList.GetSceneObject();
80 OwnerPointer<SceneGraph::RenderTask> transferOwnership(sceneObject);
81 AddTaskMessage(task->GetEventThreadServices(), parentSceneObject, transferOwnership);
83 // Set the default source & camera actors
84 task->SetSourceActor(sourceActor);
85 task->SetCameraActor(cameraActor);
87 // no need for additional messages as scene objects defaults match ours
91 void RenderTask::SetSourceActor(Actor* actor)
93 mSourceActor.SetActor(actor);
96 SetSourceNodeMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), &actor->GetNode());
100 SetSourceNodeMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), nullptr);
103 // set the actor on exclusive container for hit testing
104 mRenderTaskList.SetExclusive(this, mExclusive);
107 Actor* RenderTask::GetSourceActor() const
109 return mSourceActor.GetActor();
112 void RenderTask::SetExclusive(bool exclusive)
114 if(mExclusive != exclusive)
116 mExclusive = exclusive;
118 mRenderTaskList.SetExclusive(this, exclusive);
120 // scene object is being used in a separate thread; queue a message to set the value
121 SetExclusiveMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), mExclusive);
125 bool RenderTask::IsExclusive() const
130 void RenderTask::SetInputEnabled(bool enabled)
132 mInputEnabled = enabled;
135 bool RenderTask::GetInputEnabled() const
137 return mInputEnabled;
140 void RenderTask::SetCameraActor(CameraActor* cameraActor)
142 mCameraActor.SetActor(cameraActor);
145 SetCameraMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), &cameraActor->GetNode(), cameraActor->GetCamera());
149 SetCameraMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), nullptr, nullptr);
152 // set the actor on exclusive container for hit testing
153 mRenderTaskList.SetExclusive(this, mExclusive);
156 CameraActor* RenderTask::GetCameraActor() const
158 if(mCameraActor.GetActor())
160 return static_cast<CameraActor*>(mCameraActor.GetActor());
165 void RenderTask::SetFrameBuffer(FrameBufferPtr frameBuffer)
167 mFrameBuffer = frameBuffer;
168 Render::FrameBuffer* renderFrameBufferPtr(nullptr);
171 renderFrameBufferPtr = mFrameBuffer->GetRenderObject();
174 SetFrameBufferMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), renderFrameBufferPtr);
177 FrameBuffer* RenderTask::GetFrameBuffer() const
179 return mFrameBuffer.Get();
182 void RenderTask::SetScreenToFrameBufferFunction(ScreenToFrameBufferFunction conversionFunction)
184 mScreenToFrameBufferFunction = conversionFunction;
187 RenderTask::ScreenToFrameBufferFunction RenderTask::GetScreenToFrameBufferFunction() const
189 return mScreenToFrameBufferFunction;
192 void RenderTask::SetScreenToFrameBufferMappingActor(Dali::Actor& mappingActor)
194 mInputMappingActor = WeakHandle<Dali::Actor>(mappingActor);
197 Dali::Actor RenderTask::GetScreenToFrameBufferMappingActor() const
199 return mInputMappingActor.GetHandle();
202 void RenderTask::SetViewportGuideActor(Actor* actor)
204 mViewportGuideActor.SetActor(actor);
207 SetViewportGuideNodeMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), &actor->GetNode());
211 SetViewportGuideNodeMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), nullptr);
215 Actor* RenderTask::GetViewportGuideActor() const
217 return mViewportGuideActor.GetActor();
220 void RenderTask::ResetViewportGuideActor()
222 SetViewportGuideActor(nullptr);
224 BakeViewportPositionMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), mViewportPosition);
225 BakeViewportSizeMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), mViewportSize);
228 void RenderTask::SetViewportPosition(const Vector2& value)
230 mViewportPosition = value;
232 BakeViewportPositionMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), value);
235 Vector2 RenderTask::GetCurrentViewportPosition() const
237 return GetRenderTaskSceneObject().GetViewportPosition(GetEventThreadServices().GetEventBufferIndex());
240 void RenderTask::SetViewportSize(const Vector2& value)
242 mViewportSize = value;
244 BakeViewportSizeMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), value);
247 Vector2 RenderTask::GetCurrentViewportSize() const
249 return GetRenderTaskSceneObject().GetViewportSize(GetEventThreadServices().GetEventBufferIndex());
252 void RenderTask::SetViewport(const Viewport& viewport)
254 SetViewportPosition(Vector2(static_cast<float>(viewport.x), static_cast<float>(viewport.y)));
255 SetViewportSize(Vector2(static_cast<float>(viewport.width), static_cast<float>(viewport.height)));
258 void RenderTask::GetViewport(Viewport& viewPort) const
260 BufferIndex bufferIndex = GetEventThreadServices().GetEventBufferIndex();
262 if(!GetRenderTaskSceneObject().GetViewportEnabled(bufferIndex))
264 Internal::Stage* stage = Internal::Stage::GetCurrent();
267 Vector2 size(stage->GetSize());
268 Actor* sourceActor = mSourceActor.GetActor();
269 if(sourceActor && sourceActor->OnScene())
271 Scene& scene = sourceActor->GetScene();
272 size = scene.GetSize();
275 viewPort.x = viewPort.y = 0;
276 viewPort.width = static_cast<int32_t>(size.width); // truncated
277 viewPort.height = static_cast<int32_t>(size.height); // truncated
282 const Vector2& position = GetRenderTaskSceneObject().GetViewportPosition(bufferIndex);
283 const Vector2& size = GetRenderTaskSceneObject().GetViewportSize(bufferIndex);
284 viewPort.x = static_cast<int32_t>(position.x); // truncated
285 viewPort.y = static_cast<int32_t>(position.y); // truncated
286 viewPort.width = static_cast<int32_t>(size.width); // truncated
287 viewPort.height = static_cast<int32_t>(size.height); // truncated
291 void RenderTask::SetClearColor(const Vector4& color)
293 if(mClearColor != color)
297 // scene object is being used in a separate thread; queue a message to set the value
298 BakeClearColorMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), color);
302 const Vector4& RenderTask::GetClearColor() const
304 return GetRenderTaskSceneObject().GetClearColor(GetEventThreadServices().GetEventBufferIndex());
307 void RenderTask::SetSyncRequired(bool requiresSync)
309 if(mRequiresSync != requiresSync)
311 mRequiresSync = requiresSync;
313 // scene object is being used in a separate thread; queue a message to set the value
314 SetSyncRequiredMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), requiresSync);
318 bool RenderTask::IsSyncRequired() const
320 return mRequiresSync;
323 void RenderTask::SetClearEnabled(bool enabled)
325 if(mClearEnabled != enabled)
327 mClearEnabled = enabled;
329 // scene object is being used in a separate thread; queue a message to set the value
330 SetClearEnabledMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), mClearEnabled);
334 bool RenderTask::GetClearEnabled() const
336 return mClearEnabled;
339 void RenderTask::SetCullMode(bool mode)
341 if(mCullMode != mode)
345 // scene object is being used in a separate thread; queue a message to set the value
346 SetCullModeMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), mCullMode);
350 bool RenderTask::GetCullMode() const
355 void RenderTask::SetRefreshRate(uint32_t refreshRate)
357 DALI_LOG_TRACE_METHOD_FMT(gLogRender, "this:%p rate:%d\n", this, refreshRate);
358 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::SetRefreshRate(this:%p, %d)\n", this, refreshRate);
360 mRefreshRate = refreshRate; // cached for GetRefreshRate()
362 // Note - even when refreshRate is the same as mRefreshRate, a message should be sent
364 // sceneObject is being used in a separate thread; queue a message to set the value
365 SetRefreshRateMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), refreshRate);
368 uint32_t RenderTask::GetRefreshRate() const
373 bool RenderTask::IsHittable(Vector2& screenCoords) const
375 // True when input is enabled, source & camera actor are valid
376 bool inputEnabled(false);
378 Actor* sourceActor = GetSourceActor();
379 CameraActor* cameraActor = GetCameraActor();
382 nullptr != sourceActor &&
383 sourceActor->OnScene() &&
384 nullptr != cameraActor &&
385 cameraActor->OnScene())
387 // If the actors are rendered off-screen, then the screen coordinates must be converted
388 // and the conversion function will tell us if they are inside or outside
389 if(TranslateCoordinates(screenCoords))
391 // This is a suitable render-task for input handling
399 bool RenderTask::TranslateCoordinates(Vector2& screenCoords) const
401 // return true for on-screen tasks
403 // If the actors are rendered off-screen, then the screen coordinates must be converted
404 // the function should only be called for offscreen tasks
405 Dali::Actor mappingActor = GetScreenToFrameBufferMappingActor();
407 if(mFrameBuffer && mappingActor)
409 Internal::Actor* inputMappingActor = &GetImplementation(mappingActor);
410 CameraActor* localCamera = GetCameraActor();
411 StagePtr stage = Stage::GetCurrent();
414 Vector2 size(stage->GetSize());
415 CameraActor* defaultCamera(&stage->GetDefaultCameraActor());
416 Actor* sourceActor = mSourceActor.GetActor();
417 if(sourceActor && sourceActor->OnScene())
419 Scene& scene = sourceActor->GetScene();
420 size = scene.GetSize();
421 defaultCamera = &scene.GetDefaultCameraActor();
427 viewport.x = viewport.y = 0;
428 viewport.width = static_cast<int32_t>(size.width); // truncated
429 viewport.height = static_cast<int32_t>(size.height); // truncated
431 float localX, localY;
432 inside = inputMappingActor->ScreenToLocal(defaultCamera->GetViewMatrix(), defaultCamera->GetProjectionMatrix(), viewport, localX, localY, screenCoords.x, screenCoords.y);
433 Vector3 actorSize = inputMappingActor->GetCurrentSize();
434 if(inside && localX >= 0.f && localX <= actorSize.x && localY >= 0.f && localY <= actorSize.y)
436 screenCoords.x = localX;
437 screenCoords.y = localY;
450 else if(mFrameBuffer && mScreenToFrameBufferFunction)
452 inside = mScreenToFrameBufferFunction(screenCoords);
457 bool RenderTask::WorldToViewport(const Vector3& position, float& viewportX, float& viewportY) const
459 CameraActor* cam = GetCameraActor();
461 Vector4 pos(position);
464 Vector4 viewportPosition;
467 GetViewport(viewport);
469 bool ok = ProjectFull(pos,
470 cam->GetViewMatrix(),
471 cam->GetProjectionMatrix(),
472 static_cast<float>(viewport.x), // truncated
473 static_cast<float>(viewport.y), // truncated
474 static_cast<float>(viewport.width), // truncated
475 static_cast<float>(viewport.height), // truncated
479 viewportX = viewportPosition.x;
480 viewportY = viewportPosition.y;
486 bool RenderTask::ViewportToLocal(Actor* actor, float viewportX, float viewportY, float& localX, float& localY) const
488 return actor->ScreenToLocal(*this, localX, localY, viewportX, viewportY);
491 const SceneGraph::RenderTask& RenderTask::GetRenderTaskSceneObject() const
493 return *static_cast<const SceneGraph::RenderTask*>(mUpdateObject);
496 RenderTaskList& RenderTask::GetRenderTaskList() const
498 return mRenderTaskList;
501 /********************************************************************************
502 ******************************** PROPERTY METHODS **************************
503 ********************************************************************************/
505 void RenderTask::SetDefaultProperty(Property::Index index, const Property::Value& property)
509 case Dali::RenderTask::Property::VIEWPORT_POSITION:
511 SetViewportPosition(property.Get<Vector2>());
514 case Dali::RenderTask::Property::VIEWPORT_SIZE:
516 SetViewportSize(property.Get<Vector2>());
519 case Dali::RenderTask::Property::CLEAR_COLOR:
521 SetClearColor(property.Get<Vector4>());
524 case Dali::RenderTask::Property::REQUIRES_SYNC:
526 SetSyncRequired(property.Get<bool>());
537 Property::Value RenderTask::GetDefaultProperty(Property::Index index) const
539 Property::Value value;
543 case Dali::RenderTask::Property::VIEWPORT_POSITION:
545 value = mViewportPosition;
548 case Dali::RenderTask::Property::VIEWPORT_SIZE:
550 value = mViewportSize;
553 case Dali::RenderTask::Property::CLEAR_COLOR:
558 case Dali::RenderTask::Property::REQUIRES_SYNC:
560 value = IsSyncRequired();
566 DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
574 Property::Value RenderTask::GetDefaultPropertyCurrentValue(Property::Index index) const
576 Property::Value value;
580 case Dali::RenderTask::Property::VIEWPORT_POSITION:
582 value = GetCurrentViewportPosition();
585 case Dali::RenderTask::Property::VIEWPORT_SIZE:
587 value = GetCurrentViewportSize();
590 case Dali::RenderTask::Property::CLEAR_COLOR:
592 value = GetClearColor();
595 case Dali::RenderTask::Property::REQUIRES_SYNC:
597 value = IsSyncRequired();
603 DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
611 void RenderTask::OnNotifyDefaultPropertyAnimation(Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType)
613 switch(animationType)
616 case Animation::BETWEEN:
620 case Dali::RenderTask::Property::VIEWPORT_POSITION:
622 value.Get(mViewportPosition);
625 case Dali::RenderTask::Property::VIEWPORT_SIZE:
627 value.Get(mViewportSize);
630 case Dali::RenderTask::Property::CLEAR_COLOR:
632 value.Get(mClearColor);
635 case Dali::RenderTask::Property::REQUIRES_SYNC:
638 // Nothing to do as not animatable
649 case Dali::RenderTask::Property::VIEWPORT_POSITION:
651 AdjustValue<Vector2>(mViewportPosition, value);
654 case Dali::RenderTask::Property::VIEWPORT_SIZE:
656 AdjustValue<Vector2>(mViewportSize, value);
659 case Dali::RenderTask::Property::CLEAR_COLOR:
661 AdjustValue<Vector4>(mClearColor, value);
664 case Dali::RenderTask::Property::REQUIRES_SYNC:
667 // Nothing to do as not animatable
676 const SceneGraph::PropertyBase* RenderTask::GetSceneObjectAnimatableProperty(Property::Index index) const
678 const SceneGraph::PropertyBase* property(nullptr);
682 case Dali::RenderTask::Property::VIEWPORT_POSITION:
684 property = &GetRenderTaskSceneObject().mViewportPosition;
687 case Dali::RenderTask::Property::VIEWPORT_SIZE:
689 property = &GetRenderTaskSceneObject().mViewportSize;
692 case Dali::RenderTask::Property::CLEAR_COLOR:
694 property = &GetRenderTaskSceneObject().mClearColor;
704 // not our property, ask base
705 property = Object::GetSceneObjectAnimatableProperty(index);
711 const PropertyInputImpl* RenderTask::GetSceneObjectInputProperty(Property::Index index) const
713 // animatable properties are input as well, Object::GetSceneObjectInputProperty does the same so no need to call it
714 return GetSceneObjectAnimatableProperty(index);
717 bool RenderTask::HasFinished()
719 bool finished = false;
720 const uint32_t counter = GetRenderTaskSceneObject().GetRenderedOnceCounter();
722 if(mRefreshOnceCounter < counter)
725 mRefreshOnceCounter = counter;
728 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::HasFinished()=%s SCRT:%p SC\n", finished ? "T" : "F", &GetRenderTaskSceneObject());
733 void RenderTask::EmitSignalFinish()
735 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::EmitSignalFinish(this:%p)\n", this);
737 if(!mSignalFinished.Empty())
739 Dali::RenderTask handle(this);
740 mSignalFinished.Emit(handle);
744 Dali::RenderTask::RenderTaskSignalType& RenderTask::FinishedSignal()
746 return mSignalFinished;
749 bool RenderTask::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
751 bool connected(true);
752 RenderTask* renderTask = static_cast<RenderTask*>(object); // TypeRegistry guarantees that this is the correct type.
754 if(0 == strcmp(signalName.c_str(), SIGNAL_FINISHED))
756 renderTask->FinishedSignal().Connect(tracker, functor);
760 // signalName does not match any signal
767 RenderTask::RenderTask(const SceneGraph::RenderTask* sceneObject, RenderTaskList& renderTaskList)
768 : Object(sceneObject),
771 mViewportGuideActor(),
772 mInputMappingActor(),
773 mRenderTaskList(renderTaskList),
774 mClearColor(Dali::RenderTask::DEFAULT_CLEAR_COLOR),
775 mViewportPosition(Vector2::ZERO),
776 mViewportSize(Vector2::ZERO),
777 mRefreshRate(Dali::RenderTask::DEFAULT_REFRESH_RATE),
778 mRefreshOnceCounter(0u),
779 mScreenToFrameBufferFunction(Dali::RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION),
780 mExclusive(Dali::RenderTask::DEFAULT_EXCLUSIVE),
781 mInputEnabled(Dali::RenderTask::DEFAULT_INPUT_ENABLED),
782 mClearEnabled(Dali::RenderTask::DEFAULT_CLEAR_ENABLED),
783 mCullMode(Dali::RenderTask::DEFAULT_CULL_MODE),
786 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::RenderTask(this:%p)\n", this);
787 // scene object handles observation of source and camera
790 RenderTask::~RenderTask()
792 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::~RenderTask(this:%p)\n", this);
793 // scene object deletion is handled by our parent
794 // scene object handles observation of source and camera
797 } // namespace Internal