Fix a crash of the RenderTask
[platform/core/uifw/dali-core.git] / dali / internal / event / render-tasks / render-task-impl.cpp
1 /*
2  * Copyright (c) 2019 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
24 // INTERNAL INCLUDES
25 #include <dali/public-api/common/dali-common.h>
26 #include <dali/public-api/object/type-registry.h>
27 #include <dali/internal/event/common/event-thread-services.h>
28 #include <dali/internal/event/actors/actor-impl.h>
29 #include <dali/internal/event/actors/camera-actor-impl.h>
30 #include <dali/internal/event/common/property-helper.h>
31 #include <dali/internal/event/common/stage-impl.h>
32 #include <dali/internal/event/common/scene-impl.h>
33 #include <dali/internal/event/common/projection.h>
34 #include <dali/internal/event/images/frame-buffer-image-impl.h>
35 #include <dali/internal/update/nodes/node.h>
36 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
37
38 #if defined(DEBUG_ENABLED)
39 namespace
40 {
41 Debug::Filter* gLogRender = Debug::Filter::New(Debug::Concise, false, "LOG_RENDER_TASK");
42 }
43 #endif
44
45 namespace Dali
46 {
47
48 namespace Internal
49 {
50
51 namespace // For internal properties
52 {
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 ), NULL, 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 )
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   if ( actor )
99   {
100     SetSourceNodeMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), &actor->GetNode() );
101   }
102   else
103   {
104     SetSourceNodeMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), nullptr );
105   }
106
107   // set the actor on exclusive container for hit testing
108   mRenderTaskList.SetExclusive( this, mExclusive );
109 }
110
111 Actor* RenderTask::GetSourceActor() const
112 {
113   return mSourceActor.GetActor();
114 }
115
116 void RenderTask::SetExclusive( bool exclusive )
117 {
118   if ( mExclusive != exclusive )
119   {
120     mExclusive = exclusive;
121
122     mRenderTaskList.SetExclusive( this, exclusive );
123
124     // scene object is being used in a separate thread; queue a message to set the value
125     SetExclusiveMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), mExclusive );
126   }
127 }
128
129 bool RenderTask::IsExclusive() const
130 {
131   return mExclusive;
132 }
133
134 void RenderTask::SetInputEnabled( bool enabled )
135 {
136   mInputEnabled = enabled;
137 }
138
139 bool RenderTask::GetInputEnabled() const
140 {
141   return mInputEnabled;
142 }
143
144 void RenderTask::SetCameraActor( CameraActor* cameraActor )
145 {
146   mCameraActor.SetActor( cameraActor );
147   if( cameraActor )
148   {
149     SetCameraMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), &cameraActor->GetNode(), cameraActor->GetCamera() );
150   }
151   else
152   {
153     SetCameraMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), nullptr, nullptr );
154   }
155
156   // set the actor on exclusive container for hit testing
157   mRenderTaskList.SetExclusive( this, mExclusive );
158 }
159
160 CameraActor* RenderTask::GetCameraActor() const
161 {
162   if( mCameraActor.GetActor() )
163   {
164     return static_cast< CameraActor* >( mCameraActor.GetActor() );
165   }
166   return nullptr;
167 }
168
169 void RenderTask::SetTargetFrameBuffer( FrameBufferImagePtr image )
170 {
171   mFrameBufferImage = image;
172   FrameBuffer* frameBufferPtr( NULL );
173   if( image )
174   {
175     frameBufferPtr = image->GetFrameBuffer();
176   }
177
178   SetFrameBuffer( frameBufferPtr );
179 }
180
181 void RenderTask::SetFrameBuffer( FrameBufferPtr frameBuffer )
182 {
183   mFrameBuffer = frameBuffer;
184   Render::FrameBuffer* renderFrameBufferPtr( NULL );
185   if( frameBuffer )
186   {
187     renderFrameBufferPtr = mFrameBuffer->GetRenderObject();
188   }
189
190   SetFrameBufferMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), renderFrameBufferPtr );
191 }
192
193 FrameBuffer* RenderTask::GetFrameBuffer() const
194 {
195   return mFrameBuffer.Get();
196 }
197
198 FrameBufferImage* RenderTask::GetTargetFrameBuffer() const
199 {
200   return mFrameBufferImage.Get();
201 }
202
203 void RenderTask::SetScreenToFrameBufferFunction( ScreenToFrameBufferFunction conversionFunction )
204 {
205   mScreenToFrameBufferFunction = conversionFunction;
206 }
207
208 RenderTask::ScreenToFrameBufferFunction RenderTask::GetScreenToFrameBufferFunction() const
209 {
210   return mScreenToFrameBufferFunction;
211 }
212
213 void RenderTask::SetScreenToFrameBufferMappingActor( Dali::Actor& mappingActor )
214 {
215   mInputMappingActor = WeakHandle<Dali::Actor>( mappingActor );
216 }
217
218 Dali::Actor RenderTask::GetScreenToFrameBufferMappingActor() const
219 {
220   return mInputMappingActor.GetHandle();
221 }
222
223 void RenderTask::SetViewportPosition(const Vector2& value)
224 {
225   mViewportPosition = value;
226
227   BakeViewportPositionMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), value );
228 }
229
230 Vector2 RenderTask::GetCurrentViewportPosition() const
231 {
232   return GetRenderTaskSceneObject().GetViewportPosition( GetEventThreadServices().GetEventBufferIndex() );
233 }
234
235 void RenderTask::SetViewportSize(const Vector2& value)
236 {
237   mViewportSize = value;
238
239   BakeViewportSizeMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), value );
240 }
241
242 Vector2 RenderTask::GetCurrentViewportSize() const
243 {
244   return GetRenderTaskSceneObject().GetViewportSize( GetEventThreadServices().GetEventBufferIndex() );
245 }
246
247 void RenderTask::SetViewport( const Viewport& viewport )
248 {
249   SetViewportPosition( Vector2( static_cast<float>( viewport.x ), static_cast<float>( viewport.y ) ) );
250   SetViewportSize( Vector2( static_cast<float>( viewport.width ), static_cast<float>( viewport.height ) ) );
251 }
252
253 void RenderTask::GetViewport( Viewport& viewPort ) const
254 {
255   BufferIndex bufferIndex = GetEventThreadServices().GetEventBufferIndex();
256
257   if( !GetRenderTaskSceneObject().GetViewportEnabled( bufferIndex ) )
258   {
259     if ( mFrameBufferImage )
260     {
261       viewPort.x = viewPort.y = 0;
262       viewPort.width = mFrameBufferImage->GetWidth();
263       viewPort.height = mFrameBufferImage->GetHeight();
264     }
265     else
266     {
267       Internal::Stage* stage = Internal::Stage::GetCurrent();
268       if ( stage )
269       {
270         Vector2 size( stage->GetSize() );
271         Actor* sourceActor = mSourceActor.GetActor();
272         if ( sourceActor && sourceActor->OnStage() )
273         {
274           Scene& scene = sourceActor->GetScene();
275           size = scene.GetSize();
276         }
277
278         viewPort.x = viewPort.y = 0;
279         viewPort.width = static_cast<int32_t>( size.width ); // truncated
280         viewPort.height = static_cast<int32_t>( size.height ); // truncated
281       }
282     }
283   }
284   else
285   {
286     const Vector2& position = GetRenderTaskSceneObject().GetViewportPosition(bufferIndex);
287     const Vector2& size = GetRenderTaskSceneObject().GetViewportSize(bufferIndex);
288     viewPort.x = static_cast<int32_t>( position.x ); // truncated
289     viewPort.y = static_cast<int32_t>( position.y ); // truncated
290     viewPort.width = static_cast<int32_t>( size.width ); // truncated
291     viewPort.height = static_cast<int32_t>( size.height ); // truncated
292   }
293 }
294
295 void RenderTask::SetClearColor( const Vector4& color )
296 {
297   if ( mClearColor != color )
298   {
299     mClearColor = color;
300
301     // scene object is being used in a separate thread; queue a message to set the value
302     BakeClearColorMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), color );
303   }
304 }
305
306 const Vector4& RenderTask::GetClearColor() const
307 {
308   return GetRenderTaskSceneObject().GetClearColor( GetEventThreadServices().GetEventBufferIndex() );
309 }
310
311 void RenderTask::SetSyncRequired( bool requiresSync )
312 {
313   if( mRequiresSync != requiresSync )
314   {
315     mRequiresSync = requiresSync;
316
317     // scene object is being used in a separate thread; queue a message to set the value
318     SetSyncRequiredMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), requiresSync );
319   }
320 }
321
322 bool RenderTask::IsSyncRequired() const
323 {
324   return mRequiresSync;
325 }
326
327 void RenderTask::SetClearEnabled( bool enabled )
328 {
329   if ( mClearEnabled != enabled )
330   {
331     mClearEnabled = enabled;
332
333     // scene object is being used in a separate thread; queue a message to set the value
334     SetClearEnabledMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), mClearEnabled );
335   }
336 }
337
338 bool RenderTask::GetClearEnabled() const
339 {
340   return mClearEnabled;
341 }
342
343 void RenderTask::SetCullMode( bool mode )
344 {
345   if ( mCullMode != mode )
346   {
347     mCullMode = mode;
348
349     // scene object is being used in a separate thread; queue a message to set the value
350     SetCullModeMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), mCullMode );
351   }
352 }
353
354 bool RenderTask::GetCullMode() const
355 {
356   return mCullMode;
357 }
358
359 void RenderTask::SetRefreshRate( uint32_t refreshRate )
360 {
361   DALI_LOG_TRACE_METHOD_FMT(gLogRender, "this:%p  rate:%d\n", this, refreshRate);
362   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::SetRefreshRate(this:%p, %d)\n", this, refreshRate);
363
364   mRefreshRate = refreshRate; // cached for GetRefreshRate()
365
366   // Note - even when refreshRate is the same as mRefreshRate, a message should be sent
367
368   // sceneObject is being used in a separate thread; queue a message to set the value
369   SetRefreshRateMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), refreshRate );
370 }
371
372 uint32_t RenderTask::GetRefreshRate() const
373 {
374   return mRefreshRate;
375 }
376
377 bool RenderTask::IsHittable( Vector2& screenCoords ) const
378 {
379   // True when input is enabled, source & camera actor are valid
380   bool inputEnabled( false );
381
382   Actor* sourceActor = GetSourceActor();
383   CameraActor* cameraActor = GetCameraActor();
384
385   if ( mInputEnabled  &&
386        nullptr != sourceActor &&
387        sourceActor->OnStage() &&
388        nullptr != cameraActor &&
389        cameraActor->OnStage() )
390   {
391     // If the actors are rendered off-screen, then the screen coordinates must be converted
392     // and the conversion function will tell us if they are inside or outside
393     if ( TranslateCoordinates( screenCoords ) )
394     {
395       // This is a suitable render-task for input handling
396       inputEnabled = true;
397     }
398   }
399
400   return inputEnabled;
401 }
402
403 bool RenderTask::TranslateCoordinates( Vector2& screenCoords ) const
404 {
405   // return true for on-screen tasks
406   bool inside( true );
407   // If the actors are rendered off-screen, then the screen coordinates must be converted
408   // the function should only be called for offscreen tasks
409   Dali::Actor mappingActor = GetScreenToFrameBufferMappingActor();
410
411   if( mFrameBufferImage && mappingActor )
412   {
413     Internal::Actor* inputMappingActor = &GetImplementation( mappingActor );
414     CameraActor* localCamera = GetCameraActor();
415     StagePtr stage = Stage::GetCurrent();
416     if ( stage )
417     {
418       Vector2 size( stage->GetSize() );
419       CameraActor* defaultCamera( &stage->GetDefaultCameraActor() );
420       Actor* sourceActor = mSourceActor.GetActor();
421       if ( sourceActor && sourceActor->OnStage() )
422       {
423         Scene& scene = sourceActor->GetScene();
424         size = scene.GetSize();
425         defaultCamera = &scene.GetDefaultCameraActor();
426       }
427
428       if( localCamera )
429       {
430         Viewport viewport;
431         viewport.x = viewport.y = 0;
432         viewport.width = static_cast<int32_t>( size.width ); // truncated
433         viewport.height = static_cast<int32_t>( size.height ); // truncated
434
435         float localX, localY;
436         inside = inputMappingActor->ScreenToLocal(defaultCamera->GetViewMatrix(), defaultCamera->GetProjectionMatrix(), viewport, localX, localY, screenCoords.x, screenCoords.y);
437         Vector3 actorSize = inputMappingActor->GetCurrentSize();
438         if( inside && localX >= 0.f && localX <= actorSize.x && localY >= 0.f && localY <= actorSize.y)
439         {
440           screenCoords.x = localX;
441           screenCoords.y = localY;
442         }
443         else
444         {
445           inside = false;
446         }
447       }
448       else
449       {
450         inside = false;
451       }
452     }
453   }
454   else if ( mFrameBufferImage && mScreenToFrameBufferFunction )
455   {
456     inside = mScreenToFrameBufferFunction( screenCoords );
457   }
458   return inside;
459 }
460
461 bool RenderTask::WorldToViewport(const Vector3 &position, float& viewportX, float& viewportY) const
462 {
463   CameraActor* cam = GetCameraActor();
464
465   Vector4 pos(position);
466   pos.w = 1.0;
467
468   Vector4 viewportPosition;
469
470   Viewport viewport;
471   GetViewport( viewport );
472
473   bool ok = ProjectFull(pos,
474                         cam->GetViewMatrix(),
475                         cam->GetProjectionMatrix(),
476                         static_cast<float>( viewport.x ), // truncated
477                         static_cast<float>( viewport.y ), // truncated
478                         static_cast<float>( viewport.width ), // truncated
479                         static_cast<float>( viewport.height ), // truncated
480                         viewportPosition);
481   if(ok)
482   {
483     viewportX = viewportPosition.x;
484     viewportY = viewportPosition.y;
485   }
486
487   return ok;
488 }
489
490 bool RenderTask::ViewportToLocal(Actor* actor, float viewportX, float viewportY, float &localX, float &localY) const
491 {
492   return actor->ScreenToLocal( *this, localX, localY, viewportX, viewportY );
493 }
494
495 const SceneGraph::RenderTask& RenderTask::GetRenderTaskSceneObject() const
496 {
497   return *static_cast<const SceneGraph::RenderTask*>( mUpdateObject );
498 }
499
500 RenderTaskList& RenderTask::GetRenderTaskList() const
501 {
502   return mRenderTaskList;
503 }
504
505 /********************************************************************************
506  ********************************   PROPERTY METHODS   **************************
507  ********************************************************************************/
508
509 void RenderTask::SetDefaultProperty( Property::Index index, const Property::Value& property )
510 {
511   switch ( index )
512   {
513     case Dali::RenderTask::Property::VIEWPORT_POSITION:
514     {
515       SetViewportPosition( property.Get<Vector2>() );
516       break;
517     }
518     case Dali::RenderTask::Property::VIEWPORT_SIZE:
519     {
520       SetViewportSize( property.Get<Vector2>() );
521       break;
522     }
523     case Dali::RenderTask::Property::CLEAR_COLOR:
524     {
525       SetClearColor( property.Get<Vector4>() );
526       break;
527     }
528     case Dali::RenderTask::Property::REQUIRES_SYNC:
529     {
530       SetSyncRequired( property.Get<bool>() );
531       break;
532     }
533     default:
534     {
535       // nothing to do
536       break;
537     }
538   }
539 }
540
541 Property::Value RenderTask::GetDefaultProperty(Property::Index index) const
542 {
543   Property::Value value;
544
545   switch ( index )
546   {
547     case Dali::RenderTask::Property::VIEWPORT_POSITION:
548     {
549       value = mViewportPosition;
550       break;
551     }
552     case Dali::RenderTask::Property::VIEWPORT_SIZE:
553     {
554       value = mViewportSize;
555       break;
556     }
557     case Dali::RenderTask::Property::CLEAR_COLOR:
558     {
559       value = mClearColor;
560       break;
561     }
562     case Dali::RenderTask::Property::REQUIRES_SYNC:
563     {
564       value = IsSyncRequired();
565       break;
566     }
567
568     default:
569     {
570       DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
571       break;
572     }
573   }
574
575   return value;
576 }
577
578 Property::Value RenderTask::GetDefaultPropertyCurrentValue( Property::Index index ) const
579 {
580   Property::Value value;
581
582   switch ( index )
583   {
584     case Dali::RenderTask::Property::VIEWPORT_POSITION:
585     {
586       value = GetCurrentViewportPosition();
587       break;
588     }
589     case Dali::RenderTask::Property::VIEWPORT_SIZE:
590     {
591       value = GetCurrentViewportSize();
592       break;
593     }
594     case Dali::RenderTask::Property::CLEAR_COLOR:
595     {
596       value = GetClearColor();
597       break;
598     }
599     case Dali::RenderTask::Property::REQUIRES_SYNC:
600     {
601       value = IsSyncRequired();
602       break;
603     }
604
605     default:
606     {
607       DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
608       break;
609     }
610   }
611
612   return value;
613 }
614
615 void RenderTask::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
616 {
617   switch( animationType )
618   {
619     case Animation::TO:
620     case Animation::BETWEEN:
621     {
622       switch ( index )
623       {
624         case Dali::RenderTask::Property::VIEWPORT_POSITION:
625         {
626           value.Get( mViewportPosition );
627           break;
628         }
629         case Dali::RenderTask::Property::VIEWPORT_SIZE:
630         {
631           value.Get( mViewportSize );
632           break;
633         }
634         case Dali::RenderTask::Property::CLEAR_COLOR:
635         {
636           value.Get( mClearColor );
637           break;
638         }
639         case Dali::RenderTask::Property::REQUIRES_SYNC:
640         default:
641         {
642           // Nothing to do as not animatable
643           break;
644         }
645       }
646       break;
647     }
648
649     case Animation::BY:
650     {
651       switch ( index )
652       {
653         case Dali::RenderTask::Property::VIEWPORT_POSITION:
654         {
655           AdjustValue< Vector2 >( mViewportPosition, value );
656           break;
657         }
658         case Dali::RenderTask::Property::VIEWPORT_SIZE:
659         {
660           AdjustValue< Vector2 >( mViewportSize, value );
661           break;
662         }
663         case Dali::RenderTask::Property::CLEAR_COLOR:
664         {
665           AdjustValue< Vector4 >( mClearColor, value );
666           break;
667         }
668         case Dali::RenderTask::Property::REQUIRES_SYNC:
669         default:
670         {
671           // Nothing to do as not animatable
672           break;
673         }
674       }
675       break;
676     }
677   }
678 }
679
680 const SceneGraph::PropertyBase* RenderTask::GetSceneObjectAnimatableProperty( Property::Index index ) const
681 {
682   const SceneGraph::PropertyBase* property( NULL );
683
684   switch ( index )
685   {
686     case Dali::RenderTask::Property::VIEWPORT_POSITION:
687     {
688       property = &GetRenderTaskSceneObject().mViewportPosition;
689       break;
690     }
691     case Dali::RenderTask::Property::VIEWPORT_SIZE:
692     {
693       property = &GetRenderTaskSceneObject().mViewportSize;
694       break;
695     }
696     case Dali::RenderTask::Property::CLEAR_COLOR:
697     {
698       property = &GetRenderTaskSceneObject().mClearColor;
699       break;
700     }
701     default:
702     {
703       break;
704     }
705   }
706   if( !property )
707   {
708     // not our property, ask base
709     property = Object::GetSceneObjectAnimatableProperty( index );
710   }
711
712   return property;
713 }
714
715 const PropertyInputImpl* RenderTask::GetSceneObjectInputProperty( Property::Index index ) const
716 {
717   // animatable properties are input as well, Object::GetSceneObjectInputProperty does the same so no need to call it
718   return GetSceneObjectAnimatableProperty( index );
719 }
720
721 bool RenderTask::HasFinished()
722 {
723   bool finished = false;
724   const uint32_t counter = GetRenderTaskSceneObject().GetRenderedOnceCounter();
725
726   if( mRefreshOnceCounter < counter )
727   {
728     finished = true;
729     mRefreshOnceCounter = counter;
730   }
731
732   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::HasFinished()=%s SCRT:%p  SC\n", finished?"T":"F", &GetRenderTaskSceneObject());
733
734   return finished;
735 }
736
737 void RenderTask::EmitSignalFinish()
738 {
739   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::EmitSignalFinish(this:%p)\n", this);
740
741   if( !mSignalFinished.Empty() )
742   {
743     Dali::RenderTask handle( this );
744     mSignalFinished.Emit(handle );
745   }
746 }
747
748 Dali::RenderTask::RenderTaskSignalType& RenderTask::FinishedSignal()
749 {
750   return mSignalFinished;
751 }
752
753 bool RenderTask::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
754 {
755   bool connected( true );
756   RenderTask* renderTask = static_cast< RenderTask* >(object); // TypeRegistry guarantees that this is the correct type.
757
758   if ( 0 == strcmp( signalName.c_str(), SIGNAL_FINISHED ) )
759   {
760     renderTask->FinishedSignal().Connect( tracker, functor );
761   }
762   else
763   {
764     // signalName does not match any signal
765     connected = false;
766   }
767
768   return connected;
769 }
770
771 RenderTask::RenderTask( const SceneGraph::RenderTask* sceneObject, RenderTaskList& renderTaskList )
772 : Object( sceneObject ),
773   mSourceActor(),
774   mCameraActor(),
775   mInputMappingActor(),
776   mRenderTaskList( renderTaskList ),
777   mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
778   mViewportPosition( Vector2::ZERO ),
779   mViewportSize( Vector2::ZERO ),
780   mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
781   mRefreshOnceCounter( 0u ),
782   mScreenToFrameBufferFunction( Dali::RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION ),
783   mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
784   mInputEnabled( Dali::RenderTask::DEFAULT_INPUT_ENABLED ),
785   mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
786   mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE ),
787   mRequiresSync( false )
788 {
789   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::RenderTask(this:%p)\n", this);
790   // scene object handles observation of source and camera
791 }
792
793 RenderTask::~RenderTask()
794 {
795   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::~RenderTask(this:%p)\n", this);
796   // scene object deletion is handled by our parent
797   // scene object handles observation of source and camera
798 }
799
800 } // namespace Internal
801
802 } // namespace Dali