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