Merge "Removal of the Scene graph node attachment" into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / event / render-tasks / render-task-impl.cpp
1 /*
2  * Copyright (c) 2016 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/projection.h>
33 #include <dali/internal/event/images/frame-buffer-image-impl.h>
34 #include <dali/internal/update/nodes/node.h>
35 #include <dali/internal/event/render-tasks/render-task-list-impl.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 )
63
64 // Signals
65
66 const char* const SIGNAL_FINISHED = "finished";
67
68 TypeRegistration mType( typeid( Dali::RenderTask ), typeid( Dali::BaseHandle ), NULL );
69
70 SignalConnectorType signalConnector1( mType, SIGNAL_FINISHED, &RenderTask::DoConnectSignal );
71
72 } // Unnamed namespace
73
74 RenderTask* RenderTask::New( bool isSystemLevel )
75 {
76   RenderTask* task( new RenderTask( isSystemLevel ) );
77
78   return task;
79 }
80
81 void RenderTask::SetSourceActor( Actor* actor )
82 {
83   const Stage* stage = Stage::GetCurrent();
84   if ( stage )
85   {
86     stage->GetRenderTaskList().SetExclusive( this, mExclusive );
87   }
88   mSourceConnector.SetActor( actor );
89 }
90
91 Actor* RenderTask::GetSourceActor() const
92 {
93   return mSourceConnector.mActor;
94 }
95
96 void RenderTask::SetExclusive( bool exclusive )
97 {
98   if ( mExclusive != exclusive )
99   {
100     mExclusive = exclusive;
101
102     const Stage* stage = Stage::GetCurrent();
103     if ( stage )
104     {
105       stage->GetRenderTaskList().SetExclusive( this, exclusive );
106     }
107
108     if ( mSceneObject )
109     {
110       // mSceneObject is being used in a separate thread; queue a message to set the value
111       SetExclusiveMessage( GetEventThreadServices(), *mSceneObject, mExclusive );
112     }
113   }
114 }
115
116 bool RenderTask::IsExclusive() const
117 {
118   return mExclusive;
119 }
120
121 void RenderTask::SetInputEnabled( bool enabled )
122 {
123   mInputEnabled = enabled;
124 }
125
126 bool RenderTask::GetInputEnabled() const
127 {
128   return mInputEnabled;
129 }
130
131 void RenderTask::SetCameraActor( CameraActor* cameraActor )
132 {
133   if( cameraActor )
134   {
135     mCameraConnector.mCamera = cameraActor->GetCamera();
136   }
137   else
138   {
139     mCameraConnector.mCamera = NULL;
140   }
141   mCameraConnector.SetActor( cameraActor );
142 }
143
144 CameraActor* RenderTask::GetCameraActor() const
145 {
146   // camera connector can only point to camera actor
147   return static_cast< CameraActor* >( mCameraConnector.mActor );
148 }
149
150 void RenderTask::SetTargetFrameBuffer( Dali::FrameBufferImage image )
151 {
152   if ( mFrameBufferImage != image )
153   {
154     // if we have a scene object we need to track connection status and set frame buffer id as well as updating target frame buffer
155     if ( mSceneObject )
156     {
157       if(mFrameBufferImage)
158       {
159         GetImplementation(mFrameBufferImage).Disconnect();
160       }
161
162       // update target frame buffer
163       mFrameBufferImage = image;
164
165       unsigned int resourceId = 0;
166       bool isNativeFBO = false;
167       if( mFrameBufferImage )
168       {
169         Dali::Internal::FrameBufferImage& impl = GetImplementation( mFrameBufferImage );
170         impl.Connect();
171         resourceId = impl.GetResourceId();
172         isNativeFBO = impl.IsNativeFbo();
173       }
174
175       // mSceneObject is being used in a separate thread; queue a message to set the value
176       SetFrameBufferIdMessage( GetEventThreadServices(), *mSceneObject, resourceId, isNativeFBO );
177     }
178     else
179     {
180       // update target frame buffer
181       mFrameBufferImage = image;
182     }
183   }
184 }
185
186 Dali::FrameBufferImage RenderTask::GetTargetFrameBuffer() const
187 {
188   return mFrameBufferImage;
189 }
190
191 void RenderTask::SetScreenToFrameBufferFunction( ScreenToFrameBufferFunction conversionFunction )
192 {
193   mScreenToFrameBufferFunction = conversionFunction;
194 }
195
196 RenderTask::ScreenToFrameBufferFunction RenderTask::GetScreenToFrameBufferFunction() const
197 {
198   return mScreenToFrameBufferFunction;
199 }
200
201 void RenderTask::SetScreenToFrameBufferMappingActor( Actor* mappingActor )
202 {
203   mMappingConnector.SetActor( mappingActor );
204 }
205
206 Actor* RenderTask::GetScreenToFrameBufferMappingActor() const
207 {
208   return mMappingConnector.mActor;
209 }
210
211 void RenderTask::SetViewportPosition(const Vector2& value)
212 {
213   BakeViewportPositionMessage( GetEventThreadServices(), *mSceneObject, value );
214 }
215
216 Vector2 RenderTask::GetCurrentViewportPosition() const
217 {
218   return mSceneObject->GetViewportPosition( GetEventThreadServices().GetEventBufferIndex() );
219 }
220
221 void RenderTask::SetViewportSize(const Vector2& value)
222 {
223   BakeViewportSizeMessage( GetEventThreadServices(), *mSceneObject, value );
224 }
225
226 Vector2 RenderTask::GetCurrentViewportSize() const
227 {
228   return mSceneObject->GetViewportSize( GetEventThreadServices().GetEventBufferIndex() );
229 }
230
231 void RenderTask::SetViewport( const Viewport& viewport )
232 {
233   SetViewportPosition(Vector2(viewport.x, viewport.y));
234   SetViewportSize(Vector2(viewport.width, viewport.height));
235 }
236
237 void RenderTask::GetViewport( Viewport& viewPort ) const
238 {
239   BufferIndex bufferIndex = GetEventThreadServices().GetEventBufferIndex();
240
241   if(!mSceneObject->GetViewportEnabled( bufferIndex ))
242   {
243     if ( mFrameBufferImage )
244     {
245       viewPort.x = viewPort.y = 0;
246       viewPort.width = mFrameBufferImage.GetWidth();
247       viewPort.height = mFrameBufferImage.GetHeight();
248     }
249     else
250     {
251       Internal::Stage* stage = Internal::Stage::GetCurrent();
252       if ( stage )
253       {
254         Vector2 size( stage->GetSize() );
255         viewPort.x = viewPort.y = 0;
256         viewPort.width = size.width;
257         viewPort.height = size.height;
258       }
259     }
260   }
261   else
262   {
263     const Vector2& position = mSceneObject->GetViewportPosition(bufferIndex);
264     const Vector2& size = mSceneObject->GetViewportSize(bufferIndex);
265     viewPort.x = position.x;
266     viewPort.y = position.y;
267     viewPort.width = size.width;
268     viewPort.height = size.height;
269   }
270 }
271
272 void RenderTask::SetClearColor( const Vector4& color )
273 {
274   if ( mClearColor != color )
275   {
276     mClearColor = color;
277
278     if ( mSceneObject )
279     {
280       // mSceneObject is being used in a separate thread; queue a message to set the value
281       BakeClearColorMessage( GetEventThreadServices(), *mSceneObject, color );
282     }
283   }
284 }
285
286 const Vector4& RenderTask::GetClearColor() const
287 {
288   return mSceneObject->GetClearColor( GetEventThreadServices().GetEventBufferIndex() );
289 }
290
291 void RenderTask::SetSyncRequired( bool requiresSync )
292 {
293   if( mRequiresSync != requiresSync )
294   {
295     mRequiresSync = requiresSync;
296
297     if( mSceneObject )
298     {
299       // mSceneObject is being used in a separate thread; queue a message to set the value
300       SetSyncRequiredMessage( GetEventThreadServices(), *mSceneObject, requiresSync );
301     }
302   }
303 }
304
305 bool RenderTask::IsSyncRequired() const
306 {
307   return mRequiresSync;
308 }
309
310 void RenderTask::SetClearEnabled( bool enabled )
311 {
312   if ( mClearEnabled != enabled )
313   {
314     mClearEnabled = enabled;
315
316     if ( mSceneObject )
317     {
318       // mSceneObject is being used in a separate thread; queue a message to set the value
319       SetClearEnabledMessage( GetEventThreadServices(), *mSceneObject, mClearEnabled );
320     }
321   }
322 }
323
324 bool RenderTask::GetClearEnabled() const
325 {
326   return mClearEnabled;
327 }
328
329 void RenderTask::SetCullMode( bool mode )
330 {
331   if ( mCullMode != mode )
332   {
333     mCullMode = mode;
334
335     if ( mSceneObject )
336     {
337       // mSceneObject is being used in a separate thread; queue a message to set the value
338       SetCullModeMessage( GetEventThreadServices(), *mSceneObject, mCullMode );
339     }
340   }
341 }
342
343 bool RenderTask::GetCullMode() const
344 {
345   return mCullMode;
346 }
347
348 void RenderTask::SetRefreshRate( unsigned int refreshRate )
349 {
350   DALI_LOG_TRACE_METHOD_FMT(gLogRender, "this:%p  rate:%d\n", this, refreshRate);
351   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::SetRefreshRate(this:%p, %d)\n", this, refreshRate);
352
353   mRefreshRate = refreshRate; // cached for GetRefreshRate()
354
355   // Note - even when refreshRate is the same as mRefreshRate, a message should be sent
356
357   if ( mSceneObject )
358   {
359     // mSceneObject is being used in a separate thread; queue a message to set the value
360     SetRefreshRateMessage( GetEventThreadServices(), *mSceneObject, refreshRate );
361   }
362 }
363
364 unsigned int RenderTask::GetRefreshRate() const
365 {
366   return mRefreshRate;
367 }
368
369 bool RenderTask::IsHittable( Vector2& screenCoords ) const
370 {
371   // True when input is enabled, source & camera actor are valid
372   bool inputEnabled( false );
373
374   Actor* sourceActor = GetSourceActor();
375   CameraActor* cameraActor = GetCameraActor();
376
377   if ( mInputEnabled  &&
378        NULL != sourceActor    &&
379        sourceActor->OnStage() &&
380        NULL != cameraActor    &&
381        cameraActor->OnStage() )
382   {
383     // If the actors are rendered off-screen, then the screen coordinates must be converted
384     // and the conversion function will tell us if they are inside or outside
385     if ( TranslateCoordinates( screenCoords ) )
386     {
387       // This is a suitable render-task for input handling
388       inputEnabled = true;
389     }
390   }
391
392   return inputEnabled;
393 }
394
395 bool RenderTask::TranslateCoordinates( Vector2& screenCoords ) const
396 {
397   // return true for on-screen tasks
398   bool inside( true );
399   // If the actors are rendered off-screen, then the screen coordinates must be converted
400   // the function should only be called for offscreen tasks
401   if( mFrameBufferImage && mMappingConnector.mActor )
402   {
403     CameraActor* localCamera = GetCameraActor();
404     StagePtr stage = Stage::GetCurrent();
405     if( stage )
406     {
407       CameraActor& defaultCamera = stage->GetDefaultCameraActor();
408       if( localCamera )
409       {
410         Viewport viewport;
411         Vector2 size( stage->GetSize() );
412         viewport.x = viewport.y = 0;
413         viewport.width = size.width;
414         viewport.height = size.height;
415
416         float localX, localY;
417         inside = mMappingConnector.mActor->ScreenToLocal(defaultCamera.GetViewMatrix(), defaultCamera.GetProjectionMatrix(), viewport, localX, localY, screenCoords.x, screenCoords.y);
418         Vector3 actorSize = mMappingConnector.mActor->GetCurrentSize();
419         if( inside && localX >= 0.f && localX <= actorSize.x && localY >= 0.f && localY <= actorSize.y)
420         {
421           screenCoords.x = localX;
422           screenCoords.y = localY;
423         }
424         else
425         {
426           inside = false;
427         }
428       }
429       else
430       {
431         inside = false;
432       }
433     }
434   }
435   else if ( mFrameBufferImage && mScreenToFrameBufferFunction )
436   {
437     inside = mScreenToFrameBufferFunction( screenCoords );
438   }
439   return inside;
440 }
441
442 bool RenderTask::IsSystemLevel() const
443 {
444   return mIsSystemLevel;
445 }
446
447 bool RenderTask::WorldToViewport(const Vector3 &position, float& viewportX, float& viewportY) const
448 {
449   CameraActor* cam = GetCameraActor();
450
451   Vector4 pos(position);
452   pos.w = 1.0;
453
454   Vector4 viewportPosition;
455
456   Viewport viewport;
457   GetViewport( viewport );
458
459   bool ok = ProjectFull(pos,
460                         cam->GetViewMatrix(),
461                         cam->GetProjectionMatrix(),
462                         viewport.x,
463                         viewport.y,
464                         viewport.width,
465                         viewport.height,
466                         viewportPosition);
467   if(ok)
468   {
469     viewportX = viewportPosition.x;
470     viewportY = viewportPosition.y;
471   }
472
473   return ok;
474 }
475
476 bool RenderTask::ViewportToLocal(Actor* actor, float viewportX, float viewportY, float &localX, float &localY) const
477 {
478   return actor->ScreenToLocal( *this, localX, localY, viewportX, viewportY );
479 }
480
481 SceneGraph::RenderTask* RenderTask::CreateSceneObject()
482 {
483   // This should only be called once, with no existing scene-object
484   DALI_ASSERT_DEBUG( NULL == mSceneObject );
485
486   // Keep the raw-pointer until DiscardSceneObject is called
487   mSceneObject = SceneGraph::RenderTask::New();
488
489   // if we have a frame buffer we need to track connection status then send a message to set the frame buffer id in case it has changed since last time we were on stage
490   unsigned int resourceId = 0;
491   bool isNativeFBO = false;
492   if( mFrameBufferImage )
493   {
494     Dali::Internal::FrameBufferImage& impl = GetImplementation( mFrameBufferImage );
495     impl.Connect();
496     resourceId = impl.GetResourceId();
497     isNativeFBO = impl.IsNativeFbo();
498   }
499
500   // mSceneObject is being used in a separate thread; queue a message to set the value
501   SetFrameBufferIdMessage( GetEventThreadServices(), *mSceneObject, resourceId, isNativeFBO );
502
503   // Send messages to set other properties that may have changed since last time we were on stage
504   SetExclusiveMessage( GetEventThreadServices(), *mSceneObject, mExclusive );
505   SetClearColorMessage(  GetEventThreadServices(), *mSceneObject, mClearColor );
506   SetClearEnabledMessage(  GetEventThreadServices(), *mSceneObject, mClearEnabled );
507   SetCullModeMessage(  GetEventThreadServices(), *mSceneObject, mCullMode );
508   SetRefreshRateMessage(  GetEventThreadServices(), *mSceneObject, mRefreshRate );
509
510   // Caller takes ownership
511   return mSceneObject;
512 }
513
514 SceneGraph::RenderTask* RenderTask::GetRenderTaskSceneObject()
515 {
516   return mSceneObject;
517 }
518
519 void RenderTask::DiscardSceneObject()
520 {
521   // mSceneObject is not owned; throw away the raw-pointer
522   mSceneObject = NULL;
523
524   // if we have a frame buffer we need to track connection status
525   if(mFrameBufferImage)
526   {
527     GetImplementation(mFrameBufferImage).Disconnect();
528   }
529 }
530
531 /********************************************************************************
532  ********************************   PROPERTY METHODS   **************************
533  ********************************************************************************/
534
535 unsigned int RenderTask::GetDefaultPropertyCount() const
536 {
537   return DEFAULT_PROPERTY_COUNT;
538 }
539
540 void RenderTask::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
541 {
542   indices.Reserve( DEFAULT_PROPERTY_COUNT );
543
544   for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
545   {
546     indices.PushBack( i );
547   }
548 }
549
550 const char* RenderTask::GetDefaultPropertyName( Property::Index index ) const
551 {
552   if( index < DEFAULT_PROPERTY_COUNT )
553   {
554     return DEFAULT_PROPERTY_DETAILS[index].name;
555   }
556   else
557   {
558     return NULL;
559   }
560 }
561
562 Property::Index RenderTask::GetDefaultPropertyIndex(const std::string& name) const
563 {
564   Property::Index index = Property::INVALID_INDEX;
565
566   // Look for name in default properties
567   for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
568   {
569     if( 0 == strcmp( name.c_str(), DEFAULT_PROPERTY_DETAILS[i].name ) ) // dont want to convert rhs to string
570     {
571       index = i;
572       break;
573     }
574   }
575
576   return index;
577 }
578
579 bool RenderTask::IsDefaultPropertyWritable(Property::Index index) const
580 {
581   return DEFAULT_PROPERTY_DETAILS[ index ].writable;
582 }
583
584 bool RenderTask::IsDefaultPropertyAnimatable(Property::Index index) const
585 {
586   return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
587 }
588
589 bool RenderTask::IsDefaultPropertyAConstraintInput( Property::Index index ) const
590 {
591   return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
592 }
593
594 Property::Type RenderTask::GetDefaultPropertyType(Property::Index index) const
595 {
596   if( index < DEFAULT_PROPERTY_COUNT )
597   {
598     return DEFAULT_PROPERTY_DETAILS[index].type;
599   }
600
601   // index out of range...return Property::NONE
602   return Property::NONE;
603 }
604
605 void RenderTask::SetDefaultProperty( Property::Index index, const Property::Value& property )
606 {
607   switch ( index )
608   {
609     case Dali::RenderTask::Property::VIEWPORT_POSITION:
610     {
611       SetViewportPosition( property.Get<Vector2>() );
612       break;
613     }
614     case Dali::RenderTask::Property::VIEWPORT_SIZE:
615     {
616       SetViewportSize( property.Get<Vector2>() );
617       break;
618     }
619     case Dali::RenderTask::Property::CLEAR_COLOR:
620     {
621       SetClearColor( property.Get<Vector4>() );
622       break;
623     }
624     case Dali::RenderTask::Property::REQUIRES_SYNC:
625     {
626       SetSyncRequired( property.Get<bool>() );
627       break;
628     }
629     default:
630     {
631       // nothing to do
632       break;
633     }
634   }
635 }
636
637 Property::Value RenderTask::GetDefaultProperty(Property::Index index) const
638 {
639   Property::Value value;
640
641   switch ( index )
642   {
643
644     case Dali::RenderTask::Property::VIEWPORT_POSITION:
645     {
646       value = GetCurrentViewportPosition();
647       break;
648     }
649     case Dali::RenderTask::Property::VIEWPORT_SIZE:
650     {
651       value = GetCurrentViewportSize();
652       break;
653     }
654     case Dali::RenderTask::Property::CLEAR_COLOR:
655     {
656       value = GetClearColor();
657       break;
658     }
659     case Dali::RenderTask::Property::REQUIRES_SYNC:
660     {
661       value = IsSyncRequired();
662       break;
663     }
664
665     default:
666     {
667       DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
668       break;
669     }
670   }
671
672   return value;
673 }
674
675 const SceneGraph::PropertyOwner* RenderTask::GetSceneObject() const
676 {
677   return mSceneObject;
678 }
679
680 const SceneGraph::PropertyBase* RenderTask::GetSceneObjectAnimatableProperty( Property::Index index ) const
681 {
682   DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" );
683
684   const SceneGraph::PropertyBase* property( NULL );
685
686   // This method should only return a property which is part of the scene-graph
687   if( mSceneObject != NULL )
688   {
689     switch ( index )
690     {
691       case Dali::RenderTask::Property::VIEWPORT_POSITION:
692         property = &mSceneObject->mViewportPosition;
693         break;
694
695       case Dali::RenderTask::Property::VIEWPORT_SIZE:
696         property = &mSceneObject->mViewportSize;
697         break;
698
699       case Dali::RenderTask::Property::CLEAR_COLOR:
700         property = &mSceneObject->mClearColor;
701         break;
702
703       default:
704         break;
705     }
706   }
707
708   return property;
709 }
710
711 const PropertyInputImpl* RenderTask::GetSceneObjectInputProperty( Property::Index index ) const
712 {
713   const PropertyInputImpl* property( NULL );
714   if( mSceneObject != NULL )
715   {
716     switch ( index )
717     {
718       case Dali::RenderTask::Property::VIEWPORT_POSITION:
719         property = &mSceneObject->mViewportPosition;
720         break;
721
722       case Dali::RenderTask::Property::VIEWPORT_SIZE:
723         property = &mSceneObject->mViewportSize;
724         break;
725
726       case Dali::RenderTask::Property::CLEAR_COLOR:
727         property = &mSceneObject->mClearColor;
728         break;
729
730       default:
731         break;
732     }
733   }
734
735   return property;
736 }
737
738 bool RenderTask::HasFinished()
739 {
740   bool finished = false;
741   const unsigned int counter = mSceneObject->GetRenderedOnceCounter();
742
743   if( mRefreshOnceCounter < counter )
744   {
745     finished = true;
746     mRefreshOnceCounter = counter;
747   }
748
749   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::HasFinished()=%s SCRT:%p  SC\n", finished?"T":"F", mSceneObject);
750
751   return finished;
752 }
753
754 void RenderTask::EmitSignalFinish()
755 {
756   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::EmitSignalFinish(this:%p)\n", this);
757
758   if( !mSignalFinished.Empty() )
759   {
760     Dali::RenderTask handle( this );
761     mSignalFinished.Emit(handle );
762   }
763 }
764
765 Dali::RenderTask::RenderTaskSignalType& RenderTask::FinishedSignal()
766 {
767   return mSignalFinished;
768 }
769
770 bool RenderTask::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
771 {
772   bool connected( true );
773   RenderTask* renderTask = dynamic_cast<RenderTask*>(object);
774
775   if ( 0 == strcmp( signalName.c_str(), SIGNAL_FINISHED ) )
776   {
777     renderTask->FinishedSignal().Connect( tracker, functor );
778   }
779   else
780   {
781     // signalName does not match any signal
782     connected = false;
783   }
784
785   return connected;
786 }
787
788 RenderTask::RenderTask( bool isSystemLevel )
789 : mSceneObject( NULL ),
790   mSourceConnector( Connector::SOURCE_CONNECTOR, *this ),
791   mCameraConnector( Connector::CAMERA_CONNECTOR, *this ),
792   mMappingConnector( Connector::MAPPING_CONNECTOR, *this  ),
793   mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
794   mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
795   mRefreshOnceCounter( 0u ),
796   mScreenToFrameBufferFunction( Dali::RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION ),
797   mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
798   mInputEnabled( Dali::RenderTask::DEFAULT_INPUT_ENABLED ),
799   mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
800   mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE ),
801   mIsSystemLevel( isSystemLevel ),
802   mRequiresSync( false )
803 {
804   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::RenderTask(this:%p)\n", this);
805 }
806
807 RenderTask::~RenderTask()
808 {
809   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::~RenderTask(this:%p)\n", this);
810 }
811
812 // Helper class for connecting Nodes to the scene-graph RenderTask
813
814 RenderTask::Connector::Connector( Type type, RenderTask& renderTask )
815 : mType( type ),
816   mRenderTask( renderTask ),
817   mActor( NULL ),
818   mCamera( NULL )
819 {
820 }
821
822 RenderTask::Connector::~Connector()
823 {
824   SetActor( NULL );
825 }
826
827 void RenderTask::Connector::SetActor( Actor* actor )
828 {
829   if ( mActor != actor )
830   {
831     if ( mActor )
832     {
833       mActor->RemoveObserver( *this );
834     }
835
836     mActor = actor;
837
838     if ( mActor )
839     {
840       mActor->AddObserver( *this );
841     }
842
843     UpdateRenderTask();
844   }
845 }
846
847 void RenderTask::Connector::SceneObjectAdded( Object& object )
848 {
849   UpdateRenderTask();
850 }
851
852 void RenderTask::Connector::SceneObjectRemoved( Object& object )
853 {
854   UpdateRenderTask();
855 }
856
857 void RenderTask::Connector::ObjectDestroyed( Object& object )
858 {
859   if ( SOURCE_CONNECTOR == mType )
860   {
861     const Stage* stage = Stage::GetCurrent();
862     if ( stage )
863     {
864       stage->GetRenderTaskList().SetExclusive( &mRenderTask, false );
865     }
866   }
867
868   mActor = NULL;
869   mCamera = NULL; // only meaningful for the camera connector but no simple way to distinguish
870
871   UpdateRenderTask();
872 }
873
874 void RenderTask::Connector::UpdateRenderTask()
875 {
876   // Guard to allow handle destruction after Core has been destroyed
877   if( Internal::Stage::IsInstalled() &&
878       mRenderTask.mSceneObject )
879   {
880     const SceneGraph::Node* node( NULL );
881
882     // Check whether a Node exists in the scene-graph
883     if ( NULL != mActor )
884     {
885       const SceneGraph::PropertyOwner* object = mActor->GetSceneObject();
886       if ( NULL != object )
887       {
888         // actors only point to nodes as their scene objects
889         node = static_cast< const SceneGraph::Node* >( object );
890       }
891     }
892
893     //the mapping node is not used in the scene graph
894     if ( SOURCE_CONNECTOR == mType )
895     {
896       SetSourceNodeMessage( mRenderTask.GetEventThreadServices(), *(mRenderTask.mSceneObject), node );
897     }
898     else if( CAMERA_CONNECTOR == mType )
899     {
900       SetCameraMessage( mRenderTask.GetEventThreadServices(), *(mRenderTask.mSceneObject), node, mCamera );
901     }
902   }
903 }
904
905 } // namespace Internal
906
907 } // namespace Dali