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