[dali_2.3.37] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / internal / event / render-tasks / render-task-impl.cpp
1 /*
2  * Copyright (c) 2024 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/event/render-tasks/render-task-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <cstring> // for strcmp
23 #include "render-task-impl.h"
24
25 // INTERNAL INCLUDES
26 #include <dali/internal/event/actors/actor-impl.h>
27 #include <dali/internal/event/actors/camera-actor-impl.h>
28 #include <dali/internal/event/common/event-thread-services.h>
29 #include <dali/internal/event/common/projection.h>
30 #include <dali/internal/event/common/property-helper.h>
31 #include <dali/internal/event/common/scene-impl.h>
32 #include <dali/internal/event/common/stage-impl.h>
33 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
34 #include <dali/internal/update/common/animatable-property-messages.h>
35 #include <dali/internal/update/nodes/node.h>
36 #include <dali/internal/update/render-tasks/scene-graph-render-task-messages.h>
37 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
38 #include <dali/public-api/common/dali-common.h>
39 #include <dali/public-api/object/type-registry.h>
40
41 #if defined(DEBUG_ENABLED)
42 namespace
43 {
44 Debug::Filter* gLogRender = Debug::Filter::New(Debug::Concise, false, "LOG_RENDER_TASK");
45 }
46 #endif
47
48 namespace Dali
49 {
50 namespace Internal
51 {
52 namespace // For internal properties
53 {
54 // Properties
55
56 //              Name                 Type     writable animatable constraint-input  enum for index-checking
57 DALI_PROPERTY_TABLE_BEGIN
58 DALI_PROPERTY("viewportPosition", VECTOR2, true, true, true, Dali::RenderTask::Property::VIEWPORT_POSITION)
59 DALI_PROPERTY("viewportSize", VECTOR2, true, true, true, Dali::RenderTask::Property::VIEWPORT_SIZE)
60 DALI_PROPERTY("clearColor", VECTOR4, true, true, true, Dali::RenderTask::Property::CLEAR_COLOR)
61 DALI_PROPERTY("requiresSync", BOOLEAN, true, false, false, Dali::RenderTask::Property::REQUIRES_SYNC)
62 DALI_PROPERTY_TABLE_END(DEFAULT_OBJECT_PROPERTY_START_INDEX, RenderTaskDefaultProperties)
63
64 // Signals
65
66 const char* const SIGNAL_FINISHED = "finished";
67
68 TypeRegistration mType(typeid(Dali::RenderTask), typeid(Dali::BaseHandle), nullptr, RenderTaskDefaultProperties);
69
70 SignalConnectorType signalConnector1(mType, SIGNAL_FINISHED, &RenderTask::DoConnectSignal);
71
72 } // Unnamed namespace
73
74 RenderTaskPtr RenderTask::New(Actor* sourceActor, CameraActor* cameraActor, RenderTaskList& renderTaskList, bool isOverlayTask)
75 {
76   // create scene object first so it's guaranteed to exist for the event side
77   auto sceneObject = SceneGraph::RenderTask::New();
78
79   // pass the pointer to base for message passing
80   RenderTaskPtr task(new RenderTask(sceneObject, renderTaskList));
81
82   // transfer scene object ownership to update manager
83   const SceneGraph::RenderTaskList&    parentSceneObject = renderTaskList.GetSceneObject();
84   OwnerPointer<SceneGraph::RenderTask> transferOwnership(sceneObject);
85   AddTaskMessage(task->GetEventThreadServices(), parentSceneObject, transferOwnership);
86
87   // Set the default source & camera actors
88   task->SetSourceActor(sourceActor);
89   task->SetCameraActor(cameraActor);
90
91   // no need for additional messages as scene objects defaults match ours
92   return task;
93 }
94
95 void RenderTask::SetSourceActor(Actor* actor)
96 {
97   mSourceActor.SetActor(actor);
98
99   if(GetRenderTaskSceneObject())
100   {
101     if(actor)
102     {
103       SetSourceNodeMessage(GetEventThreadServices(), *GetRenderTaskSceneObject(), &actor->GetNode());
104     }
105     else
106     {
107       SetSourceNodeMessage(GetEventThreadServices(), *GetRenderTaskSceneObject(), nullptr);
108     }
109   }
110
111   // set the actor on exclusive container for hit testing
112   mRenderTaskList.SetExclusive(this, mExclusive);
113 }
114
115 Actor* RenderTask::GetSourceActor() const
116 {
117   return mSourceActor.GetActor();
118 }
119
120 Actor* RenderTask::GetStopperActor() const
121 {
122   return mStopperActor.GetActor();
123 }
124
125 void RenderTask::SetExclusive(bool exclusive)
126 {
127   if(mExclusive != exclusive)
128   {
129     mExclusive = exclusive;
130
131     mRenderTaskList.SetExclusive(this, exclusive);
132
133     if(GetRenderTaskSceneObject())
134     {
135       // scene object is being used in a separate thread; queue a message to set the value
136       SetExclusiveMessage(GetEventThreadServices(), *GetRenderTaskSceneObject(), mExclusive);
137     }
138   }
139 }
140
141 bool RenderTask::IsExclusive() const
142 {
143   return mExclusive;
144 }
145
146 void RenderTask::SetInputEnabled(bool enabled)
147 {
148   mInputEnabled = enabled;
149 }
150
151 bool RenderTask::GetInputEnabled() const
152 {
153   return mInputEnabled;
154 }
155
156 void RenderTask::SetCameraActor(CameraActor* cameraActor)
157 {
158   mCameraActor.SetActor(cameraActor);
159
160   if(GetRenderTaskSceneObject())
161   {
162     if(cameraActor)
163     {
164       SetCameraMessage(GetEventThreadServices(), *GetRenderTaskSceneObject(), &cameraActor->GetCameraSceneObject());
165     }
166     else
167     {
168       SetCameraMessage(GetEventThreadServices(), *GetRenderTaskSceneObject(), nullptr);
169     }
170   }
171
172   // set the actor on exclusive container for hit testing
173   mRenderTaskList.SetExclusive(this, mExclusive);
174 }
175
176 CameraActor* RenderTask::GetCameraActor() const
177 {
178   if(mCameraActor.GetActor())
179   {
180     return static_cast<CameraActor*>(mCameraActor.GetActor());
181   }
182   return nullptr;
183 }
184
185 void RenderTask::SetFrameBuffer(FrameBufferPtr frameBuffer)
186 {
187   mFrameBuffer = frameBuffer;
188   Render::FrameBuffer* renderFrameBufferPtr(nullptr);
189   if(frameBuffer)
190   {
191     renderFrameBufferPtr = mFrameBuffer->GetRenderObject();
192   }
193
194   if(GetRenderTaskSceneObject())
195   {
196     SetFrameBufferMessage(GetEventThreadServices(), *GetRenderTaskSceneObject(), renderFrameBufferPtr);
197   }
198 }
199
200 FrameBuffer* RenderTask::GetFrameBuffer() const
201 {
202   return mFrameBuffer.Get();
203 }
204
205 void RenderTask::SetScreenToFrameBufferFunction(ScreenToFrameBufferFunction conversionFunction)
206 {
207   mScreenToFrameBufferFunction = conversionFunction;
208 }
209
210 RenderTask::ScreenToFrameBufferFunction RenderTask::GetScreenToFrameBufferFunction() const
211 {
212   return mScreenToFrameBufferFunction;
213 }
214
215 void RenderTask::SetScreenToFrameBufferMappingActor(Dali::Actor& mappingActor)
216 {
217   mInputMappingActor = WeakHandle<Dali::Actor>(mappingActor);
218 }
219
220 Dali::Actor RenderTask::GetScreenToFrameBufferMappingActor() const
221 {
222   return mInputMappingActor.GetHandle();
223 }
224
225 void RenderTask::SetViewportGuideActor(Actor* actor)
226 {
227   mViewportGuideActor.SetActor(actor);
228
229   auto sceneObject = GetRenderTaskSceneObject();
230   if(sceneObject)
231   {
232     auto& eventThreadServices = GetEventThreadServices();
233     auto& updateManager       = eventThreadServices.GetUpdateManager();
234
235     if(actor)
236     {
237       SetViewportGuideNodeMessage(eventThreadServices, *sceneObject, &actor->GetNode());
238     }
239     else
240     {
241       // Ensure that if the node is removed through this API, that the
242       // viewport values are set back to their base value and that their dirty
243       // flags are cleared after 1 frame.
244       SetViewportGuideNodeMessage(eventThreadServices, *sceneObject, nullptr);
245
246       auto renderTask               = const_cast<SceneGraph::RenderTask*>(sceneObject);
247       auto viewportPositionProperty = const_cast<SceneGraph::AnimatableProperty<Vector2>*>(&renderTask->mViewportPosition);
248       auto viewportSizeProperty     = const_cast<SceneGraph::AnimatableProperty<Vector2>*>(&renderTask->mViewportSize);
249
250       OwnerPointer<SceneGraph::PropertyResetterBase> resetter1(
251         new SceneGraph::BakerResetter(renderTask, viewportPositionProperty, SceneGraph::BakerResetter::Lifetime::SET));
252       OwnerPointer<SceneGraph::PropertyResetterBase> resetter2(
253         new SceneGraph::BakerResetter(renderTask, viewportSizeProperty, SceneGraph::BakerResetter::Lifetime::SET));
254       AddResetterMessage(updateManager, resetter1);
255       AddResetterMessage(updateManager, resetter2);
256     }
257   }
258 }
259
260 Actor* RenderTask::GetViewportGuideActor() const
261 {
262   return mViewportGuideActor.GetActor();
263 }
264
265 void RenderTask::ResetViewportGuideActor()
266 {
267   // Don't re-use the SetViewportGuideActor method for this task - the bake messages below will create their own resetters.
268   mViewportGuideActor.SetActor(nullptr);
269
270   if(GetRenderTaskSceneObject())
271   {
272     SetViewportGuideNodeMessage(GetEventThreadServices(), *GetRenderTaskSceneObject(), nullptr);
273
274     EventThreadServices& eventThreadServices      = GetEventThreadServices();
275     auto                 renderTask               = const_cast<SceneGraph::RenderTask*>(GetRenderTaskSceneObject());
276     auto                 viewportPositionProperty = const_cast<SceneGraph::AnimatableProperty<Vector2>*>(&renderTask->mViewportPosition);
277     auto                 viewportSizeProperty     = const_cast<SceneGraph::AnimatableProperty<Vector2>*>(&renderTask->mViewportSize);
278     BakeMessage<Vector2>(eventThreadServices, *renderTask, *viewportPositionProperty, mViewportPosition);
279     BakeMessage<Vector2>(eventThreadServices, *renderTask, *viewportSizeProperty, mViewportSize);
280   }
281 }
282
283 void RenderTask::SetViewportPosition(const Vector2& value)
284 {
285   mViewportPosition = value;
286
287   if(GetRenderTaskSceneObject())
288   {
289     EventThreadServices& eventThreadServices      = GetEventThreadServices();
290     auto                 renderTask               = const_cast<SceneGraph::RenderTask*>(GetRenderTaskSceneObject());
291     auto                 viewportPositionProperty = const_cast<SceneGraph::AnimatableProperty<Vector2>*>(&renderTask->mViewportPosition);
292     BakeMessage<Vector2>(eventThreadServices, *renderTask, *viewportPositionProperty, mViewportPosition);
293   }
294 }
295
296 Vector2 RenderTask::GetCurrentViewportPosition() const
297 {
298   return GetRenderTaskSceneObject() ? GetRenderTaskSceneObject()->GetViewportPosition(GetEventThreadServices().GetEventBufferIndex()) : Vector2::ZERO;
299 }
300
301 void RenderTask::SetViewportSize(const Vector2& value)
302 {
303   mViewportSize = value;
304
305   if(GetRenderTaskSceneObject())
306   {
307     EventThreadServices& eventThreadServices  = GetEventThreadServices();
308     auto                 renderTask           = const_cast<SceneGraph::RenderTask*>(GetRenderTaskSceneObject());
309     auto                 viewportSizeProperty = const_cast<SceneGraph::AnimatableProperty<Vector2>*>(&renderTask->mViewportSize);
310     BakeMessage<Vector2>(eventThreadServices, *renderTask, *viewportSizeProperty, mViewportSize);
311   }
312 }
313
314 Vector2 RenderTask::GetCurrentViewportSize() const
315 {
316   return GetRenderTaskSceneObject() ? GetRenderTaskSceneObject()->GetViewportSize(GetEventThreadServices().GetEventBufferIndex()) : Vector2::ZERO;
317 }
318
319 void RenderTask::SetViewport(const Viewport& viewport)
320 {
321   SetViewportPosition(Vector2(static_cast<float>(viewport.x), static_cast<float>(viewport.y)));
322   SetViewportSize(Vector2(static_cast<float>(viewport.width), static_cast<float>(viewport.height)));
323 }
324
325 void RenderTask::GetViewport(Viewport& viewPort) const
326 {
327   if(GetRenderTaskSceneObject())
328   {
329     BufferIndex bufferIndex = GetEventThreadServices().GetEventBufferIndex();
330
331     if(!GetRenderTaskSceneObject()->GetViewportEnabled(bufferIndex))
332     {
333       Internal::Stage* stage = Internal::Stage::GetCurrent();
334       if(stage)
335       {
336         Vector2 size(stage->GetSize());
337         Actor*  sourceActor = mSourceActor.GetActor();
338         if(sourceActor && sourceActor->OnScene())
339         {
340           Scene& scene = sourceActor->GetScene();
341           size         = scene.GetSize();
342         }
343
344         viewPort.x = viewPort.y = 0;
345         viewPort.width          = static_cast<int32_t>(size.width);  // truncated
346         viewPort.height         = static_cast<int32_t>(size.height); // truncated
347       }
348     }
349     else
350     {
351       const Vector2& position = GetRenderTaskSceneObject()->GetViewportPosition(bufferIndex);
352       const Vector2& size     = GetRenderTaskSceneObject()->GetViewportSize(bufferIndex);
353       viewPort.x              = static_cast<int32_t>(position.x);  // truncated
354       viewPort.y              = static_cast<int32_t>(position.y);  // truncated
355       viewPort.width          = static_cast<int32_t>(size.width);  // truncated
356       viewPort.height         = static_cast<int32_t>(size.height); // truncated
357     }
358   }
359 }
360
361 void RenderTask::SetClearColor(const Vector4& color)
362 {
363   if(mClearColor != color)
364   {
365     mClearColor = color;
366
367     if(GetRenderTaskSceneObject())
368     {
369       // scene object is being used in a separate thread; queue a message to set the value
370       EventThreadServices& eventThreadServices = GetEventThreadServices();
371       auto                 renderTask          = const_cast<SceneGraph::RenderTask*>(GetRenderTaskSceneObject());
372       auto                 clearColorProperty  = const_cast<SceneGraph::AnimatableProperty<Vector4>*>(&renderTask->mClearColor);
373       BakeMessage<Vector4>(eventThreadServices, *renderTask, *clearColorProperty, mClearColor);
374     }
375   }
376 }
377
378 const Vector4& RenderTask::GetClearColor() const
379 {
380   return GetRenderTaskSceneObject() ? GetRenderTaskSceneObject()->GetClearColor(GetEventThreadServices().GetEventBufferIndex()) : Vector4::ZERO;
381 }
382
383 void RenderTask::SetSyncRequired(bool requiresSync)
384 {
385   if(mRequiresSync != requiresSync)
386   {
387     mRequiresSync = requiresSync;
388
389     if(GetRenderTaskSceneObject())
390     {
391       // scene object is being used in a separate thread; queue a message to set the value
392       SetSyncRequiredMessage(GetEventThreadServices(), *GetRenderTaskSceneObject(), requiresSync);
393     }
394   }
395 }
396
397 bool RenderTask::IsSyncRequired() const
398 {
399   return mRequiresSync;
400 }
401
402 void RenderTask::SetClearEnabled(bool enabled)
403 {
404   if(mClearEnabled != enabled)
405   {
406     mClearEnabled = enabled;
407
408     if(GetRenderTaskSceneObject())
409     {
410       // scene object is being used in a separate thread; queue a message to set the value
411       SetClearEnabledMessage(GetEventThreadServices(), *GetRenderTaskSceneObject(), mClearEnabled);
412     }
413   }
414 }
415
416 bool RenderTask::GetClearEnabled() const
417 {
418   return mClearEnabled;
419 }
420
421 void RenderTask::SetCullMode(bool mode)
422 {
423   if(mCullMode != mode)
424   {
425     mCullMode = mode;
426
427     if(GetRenderTaskSceneObject())
428     {
429       // scene object is being used in a separate thread; queue a message to set the value
430       SetCullModeMessage(GetEventThreadServices(), *GetRenderTaskSceneObject(), mCullMode);
431     }
432   }
433 }
434
435 bool RenderTask::GetCullMode() const
436 {
437   return mCullMode;
438 }
439
440 void RenderTask::SetRefreshRate(uint32_t refreshRate)
441 {
442   DALI_LOG_TRACE_METHOD_FMT(gLogRender, "this:%p  rate:%d\n", this, refreshRate);
443   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::SetRefreshRate(this:%p, %d)\n", this, refreshRate);
444
445   mRefreshRate = refreshRate; // cached for GetRefreshRate()
446
447   // Note - even when refreshRate is the same as mRefreshRate, a message should be sent
448
449   if(GetRenderTaskSceneObject())
450   {
451     // sceneObject is being used in a separate thread; queue a message to set the value
452     SetRefreshRateMessage(GetEventThreadServices(), *GetRenderTaskSceneObject(), refreshRate);
453   }
454 }
455
456 uint32_t RenderTask::GetRefreshRate() const
457 {
458   return mRefreshRate;
459 }
460
461 bool RenderTask::IsHittable(Vector2& screenCoords) const
462 {
463   // True when input is enabled, source & camera actor are valid
464   bool inputEnabled(false);
465
466   Actor*       sourceActor = GetSourceActor();
467   CameraActor* cameraActor = GetCameraActor();
468
469   if(mInputEnabled &&
470      nullptr != sourceActor &&
471      sourceActor->OnScene() &&
472      nullptr != cameraActor &&
473      cameraActor->OnScene())
474   {
475     // If the actors are rendered off-screen, then the screen coordinates must be converted
476     // and the conversion function will tell us if they are inside or outside
477     if(TranslateCoordinates(screenCoords))
478     {
479       // This is a suitable render-task for input handling
480       inputEnabled = true;
481     }
482   }
483
484   return inputEnabled;
485 }
486
487 bool RenderTask::TranslateCoordinates(Vector2& screenCoords) const
488 {
489   // return true for on-screen tasks
490   bool inside(true);
491   // If the actors are rendered off-screen, then the screen coordinates must be converted
492   // the function should only be called for offscreen tasks
493   Dali::Actor mappingActor = GetScreenToFrameBufferMappingActor();
494
495   if(mFrameBuffer && mappingActor)
496   {
497     Internal::Actor* inputMappingActor = &GetImplementation(mappingActor);
498     if(!inputMappingActor->OnScene())
499     {
500       return false;
501     }
502
503     CameraActor* localCamera = GetCameraActor();
504     StagePtr     stage       = Stage::GetCurrent();
505     if(stage)
506     {
507       Vector2      size(stage->GetSize());
508       CameraActor* defaultCamera(&stage->GetDefaultCameraActor());
509       Actor*       sourceActor = mSourceActor.GetActor();
510       if(sourceActor && sourceActor->OnScene())
511       {
512         Scene& scene  = sourceActor->GetScene();
513         size          = scene.GetSize();
514         defaultCamera = &scene.GetDefaultCameraActor();
515       }
516
517       if(localCamera)
518       {
519         Viewport viewport;
520         viewport.x = viewport.y = 0;
521         viewport.width          = static_cast<int32_t>(size.width);  // truncated
522         viewport.height         = static_cast<int32_t>(size.height); // truncated
523
524         float localX, localY;
525         inside            = inputMappingActor->ScreenToLocal(defaultCamera->GetViewMatrix(), defaultCamera->GetProjectionMatrix(), viewport, localX, localY, screenCoords.x, screenCoords.y);
526         Vector3 actorSize = inputMappingActor->GetCurrentSize() * inputMappingActor->GetCurrentWorldScale();
527         if(inside && localX >= 0.f && localX <= actorSize.x && localY >= 0.f && localY <= actorSize.y)
528         {
529           screenCoords.x = localX;
530           screenCoords.y = localY;
531         }
532         else
533         {
534           inside = false;
535         }
536       }
537       else
538       {
539         inside = false;
540       }
541     }
542   }
543   else if(mFrameBuffer && mScreenToFrameBufferFunction)
544   {
545     inside = mScreenToFrameBufferFunction(screenCoords);
546   }
547   return inside;
548 }
549
550 void RenderTask::GetHittableViewport(Viewport& viewPort) const
551 {
552   if(GetRenderTaskSceneObject())
553   {
554     if(GetInputEnabled())
555     {
556       if(mFrameBuffer)
557       {
558         auto mappingActor = GetScreenToFrameBufferMappingActor();
559         if(mappingActor)
560         {
561           Actor& inputMappingActor = GetImplementation(mappingActor);
562
563           Vector3 actorSize = inputMappingActor.GetCurrentSize() * inputMappingActor.GetCurrentWorldScale();
564
565           viewPort.x = viewPort.y = 0;
566           viewPort.width          = static_cast<int32_t>(actorSize.x + 0.5f); // rounded
567           viewPort.height         = static_cast<int32_t>(actorSize.y + 0.5f); // rounded
568         }
569         else
570         {
571           // For the case to use ScreenToFrameBufferFunction
572           GetViewport(viewPort);
573         }
574       }
575       else
576       {
577         GetViewport(viewPort);
578       }
579     }
580   }
581 }
582
583 bool RenderTask::WorldToViewport(const Vector3& position, float& viewportX, float& viewportY) const
584 {
585   CameraActor* cam = GetCameraActor();
586
587   Vector4 pos(position);
588   pos.w = 1.0;
589
590   Vector4 viewportPosition;
591
592   Viewport viewport;
593   GetViewport(viewport);
594
595   bool ok = ProjectFull(pos,
596                         cam->GetViewMatrix(),
597                         cam->GetProjectionMatrix(),
598                         static_cast<float>(viewport.x),      // truncated
599                         static_cast<float>(viewport.y),      // truncated
600                         static_cast<float>(viewport.width),  // truncated
601                         static_cast<float>(viewport.height), // truncated
602                         viewportPosition);
603   if(ok)
604   {
605     viewportX = viewportPosition.x;
606     viewportY = viewportPosition.y;
607   }
608
609   return ok;
610 }
611
612 bool RenderTask::ViewportToLocal(Actor* actor, float viewportX, float viewportY, float& localX, float& localY) const
613 {
614   return actor->ScreenToLocal(*this, localX, localY, viewportX, viewportY);
615 }
616
617 void RenderTask::SetRenderPassTag(uint32_t renderPassTag)
618 {
619   if(mRenderPassTag != renderPassTag)
620   {
621     mRenderPassTag = renderPassTag;
622     if(GetRenderTaskSceneObject())
623     {
624       SetRenderPassTagMessage(GetEventThreadServices(), *GetRenderTaskSceneObject(), renderPassTag);
625     }
626   }
627 }
628
629 uint32_t RenderTask::GetRenderPassTag() const
630 {
631   return mRenderPassTag;
632 }
633
634 void RenderTask::SetOrderIndex(int32_t orderIndex)
635 {
636   if(mOrderIndex != orderIndex)
637   {
638     mOrderIndex = orderIndex;
639
640     // We only need to sort render task list if it is valid.
641     if(GetRenderTaskSceneObject())
642     {
643       mRenderTaskList.RequestToSort();
644     }
645   }
646 }
647
648 int32_t RenderTask::GetOrderIndex() const
649 {
650   return mOrderIndex;
651 }
652
653 uint32_t RenderTask::GetRenderTaskId() const
654 {
655   return mRenderTaskId;
656 }
657
658 void RenderTask::RenderUntil(Actor* stopperActor)
659 {
660   Actor* target = mSourceActor.GetActor();
661   DALI_ASSERT_ALWAYS((target && stopperActor) && "RenderTask::RenderUntil() has empty actors.");
662   DALI_ASSERT_ALWAYS((target->GetHierarchyDepth() < stopperActor->GetHierarchyDepth()) && "RenderTask::RenderUntil() has reversed hierarchy.");
663
664   Actor* parent = stopperActor;
665   while(parent != target && !(parent->IsLayer()))
666   {
667     parent = parent->GetParent();
668   }
669
670   if(parent == target && GetRenderTaskSceneObject())
671   {
672     mStopperActor.SetActor(stopperActor);
673     SetStopperNodeMessage(GetEventThreadServices(), *GetRenderTaskSceneObject(), &stopperActor->GetNode());
674   }
675 }
676
677 const SceneGraph::RenderTask* RenderTask::GetRenderTaskSceneObject() const
678 {
679   return static_cast<const SceneGraph::RenderTask*>(mUpdateObject);
680 }
681
682 void RenderTask::RemoveRenderTaskSceneObject(RenderTaskList& renderTaskList)
683 {
684   // send a message to remove the scene-graph RenderTask
685   const SceneGraph::RenderTaskList& parentSceneObject = renderTaskList.GetSceneObject();
686   RemoveTaskMessage(GetEventThreadServices(), parentSceneObject, *GetRenderTaskSceneObject());
687
688   mUpdateObject = nullptr;
689 }
690
691 RenderTaskList& RenderTask::GetRenderTaskList() const
692 {
693   return mRenderTaskList;
694 }
695
696 /********************************************************************************
697  ********************************   PROPERTY METHODS   **************************
698  ********************************************************************************/
699
700 void RenderTask::SetDefaultProperty(Property::Index index, const Property::Value& property)
701 {
702   switch(index)
703   {
704     case Dali::RenderTask::Property::VIEWPORT_POSITION:
705     {
706       SetViewportPosition(property.Get<Vector2>());
707       break;
708     }
709     case Dali::RenderTask::Property::VIEWPORT_SIZE:
710     {
711       SetViewportSize(property.Get<Vector2>());
712       break;
713     }
714     case Dali::RenderTask::Property::CLEAR_COLOR:
715     {
716       SetClearColor(property.Get<Vector4>());
717       break;
718     }
719     case Dali::RenderTask::Property::REQUIRES_SYNC:
720     {
721       SetSyncRequired(property.Get<bool>());
722       break;
723     }
724     default:
725     {
726       // nothing to do
727       break;
728     }
729   }
730 }
731
732 Property::Value RenderTask::GetDefaultProperty(Property::Index index) const
733 {
734   Property::Value value;
735
736   switch(index)
737   {
738     case Dali::RenderTask::Property::VIEWPORT_POSITION:
739     {
740       value = mViewportPosition;
741       break;
742     }
743     case Dali::RenderTask::Property::VIEWPORT_SIZE:
744     {
745       value = mViewportSize;
746       break;
747     }
748     case Dali::RenderTask::Property::CLEAR_COLOR:
749     {
750       value = mClearColor;
751       break;
752     }
753     case Dali::RenderTask::Property::REQUIRES_SYNC:
754     {
755       value = IsSyncRequired();
756       break;
757     }
758
759     default:
760     {
761       DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
762       break;
763     }
764   }
765
766   return value;
767 }
768
769 Property::Value RenderTask::GetDefaultPropertyCurrentValue(Property::Index index) const
770 {
771   Property::Value value;
772
773   switch(index)
774   {
775     case Dali::RenderTask::Property::VIEWPORT_POSITION:
776     {
777       value = GetCurrentViewportPosition();
778       break;
779     }
780     case Dali::RenderTask::Property::VIEWPORT_SIZE:
781     {
782       value = GetCurrentViewportSize();
783       break;
784     }
785     case Dali::RenderTask::Property::CLEAR_COLOR:
786     {
787       value = GetClearColor();
788       break;
789     }
790     case Dali::RenderTask::Property::REQUIRES_SYNC:
791     {
792       value = IsSyncRequired();
793       break;
794     }
795
796     default:
797     {
798       DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
799       break;
800     }
801   }
802
803   return value;
804 }
805
806 void RenderTask::OnNotifyDefaultPropertyAnimation(Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType)
807 {
808   switch(animationType)
809   {
810     case Animation::TO:
811     case Animation::BETWEEN:
812     {
813       switch(index)
814       {
815         case Dali::RenderTask::Property::VIEWPORT_POSITION:
816         {
817           value.Get(mViewportPosition);
818           break;
819         }
820         case Dali::RenderTask::Property::VIEWPORT_SIZE:
821         {
822           value.Get(mViewportSize);
823           break;
824         }
825         case Dali::RenderTask::Property::CLEAR_COLOR:
826         {
827           value.Get(mClearColor);
828           break;
829         }
830         case Dali::RenderTask::Property::REQUIRES_SYNC:
831         default:
832         {
833           // Nothing to do as not animatable
834           break;
835         }
836       }
837       break;
838     }
839
840     case Animation::BY:
841     {
842       switch(index)
843       {
844         case Dali::RenderTask::Property::VIEWPORT_POSITION:
845         {
846           AdjustValue<Vector2>(mViewportPosition, value);
847           break;
848         }
849         case Dali::RenderTask::Property::VIEWPORT_SIZE:
850         {
851           AdjustValue<Vector2>(mViewportSize, value);
852           break;
853         }
854         case Dali::RenderTask::Property::CLEAR_COLOR:
855         {
856           AdjustValue<Vector4>(mClearColor, value);
857           break;
858         }
859         case Dali::RenderTask::Property::REQUIRES_SYNC:
860         default:
861         {
862           // Nothing to do as not animatable
863           break;
864         }
865       }
866       break;
867     }
868   }
869 }
870
871 const SceneGraph::PropertyBase* RenderTask::GetSceneObjectAnimatableProperty(Property::Index index) const
872 {
873   if(!GetRenderTaskSceneObject())
874   {
875     return nullptr;
876   }
877
878   const SceneGraph::PropertyBase* property(nullptr);
879
880   switch(index)
881   {
882     case Dali::RenderTask::Property::VIEWPORT_POSITION:
883     {
884       property = &GetRenderTaskSceneObject()->mViewportPosition;
885       break;
886     }
887     case Dali::RenderTask::Property::VIEWPORT_SIZE:
888     {
889       property = &GetRenderTaskSceneObject()->mViewportSize;
890       break;
891     }
892     case Dali::RenderTask::Property::CLEAR_COLOR:
893     {
894       property = &GetRenderTaskSceneObject()->mClearColor;
895       break;
896     }
897     default:
898     {
899       break;
900     }
901   }
902   if(!property)
903   {
904     // not our property, ask base
905     property = Object::GetSceneObjectAnimatableProperty(index);
906   }
907
908   return property;
909 }
910
911 const PropertyInputImpl* RenderTask::GetSceneObjectInputProperty(Property::Index index) const
912 {
913   // animatable properties are input as well, Object::GetSceneObjectInputProperty does the same so no need to call it
914   return GetSceneObjectAnimatableProperty(index);
915 }
916
917 bool RenderTask::HasFinished()
918 {
919   bool finished = false;
920
921   if(GetRenderTaskSceneObject())
922   {
923     const uint32_t counter = GetRenderTaskSceneObject()->GetRenderedOnceCounter();
924
925     if(mRefreshOnceCounter < counter)
926     {
927       finished            = true;
928       mRefreshOnceCounter = counter;
929     }
930   }
931
932   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::HasFinished()=%s SCRT:%p  SC\n", finished ? "T" : "F", GetRenderTaskSceneObject());
933
934   return finished;
935 }
936
937 void RenderTask::EmitSignalFinish()
938 {
939   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::EmitSignalFinish(this:%p)\n", this);
940
941   if(!mSignalFinished.Empty())
942   {
943     Dali::RenderTask handle(this);
944     mSignalFinished.Emit(handle);
945   }
946 }
947
948 Dali::RenderTask::RenderTaskSignalType& RenderTask::FinishedSignal()
949 {
950   return mSignalFinished;
951 }
952
953 bool RenderTask::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
954 {
955   bool        connected(true);
956   RenderTask* renderTask = static_cast<RenderTask*>(object); // TypeRegistry guarantees that this is the correct type.
957
958   if(0 == strcmp(signalName.c_str(), SIGNAL_FINISHED))
959   {
960     renderTask->FinishedSignal().Connect(tracker, functor);
961   }
962   else
963   {
964     // signalName does not match any signal
965     connected = false;
966   }
967
968   return connected;
969 }
970
971 RenderTask::RenderTask(const SceneGraph::RenderTask* sceneObject, RenderTaskList& renderTaskList)
972 : Object(sceneObject),
973   mSourceActor(),
974   mCameraActor(),
975   mViewportGuideActor(),
976   mInputMappingActor(),
977   mRenderTaskList(renderTaskList),
978   mClearColor(Dali::RenderTask::DEFAULT_CLEAR_COLOR),
979   mViewportPosition(Vector2::ZERO),
980   mViewportSize(Vector2::ZERO),
981   mRefreshRate(Dali::RenderTask::DEFAULT_REFRESH_RATE),
982   mRefreshOnceCounter(0u),
983   mScreenToFrameBufferFunction(Dali::RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION),
984   mExclusive(Dali::RenderTask::DEFAULT_EXCLUSIVE),
985   mInputEnabled(Dali::RenderTask::DEFAULT_INPUT_ENABLED),
986   mClearEnabled(Dali::RenderTask::DEFAULT_CLEAR_ENABLED),
987   mCullMode(Dali::RenderTask::DEFAULT_CULL_MODE),
988   mRequiresSync(false)
989 {
990   // Set id of render task
991   mRenderTaskId = sceneObject->GetNotifyId();
992
993   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::RenderTask(this:%p)\n", this);
994   // scene object handles observation of source and camera
995 }
996
997 RenderTask::~RenderTask()
998 {
999   if(DALI_UNLIKELY(!Dali::Stage::IsCoreThread()))
1000   {
1001     DALI_LOG_ERROR("~RenderTask[%p] called from non-UI thread! something unknown issue will be happened!\n", this);
1002   }
1003
1004   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::~RenderTask(this:%p)\n", this);
1005   // scene object deletion is handled by our parent
1006   // scene object handles observation of source and camera
1007 }
1008
1009 } // namespace Internal
1010
1011 } // namespace Dali