Ensure cached values of properties animated using AnimateTo are updated
[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 } // 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( 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(viewport.x, viewport.y));
231   SetViewportSize(Vector2(viewport.width, 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 = size.width;
254         viewPort.height = size.height;
255       }
256     }
257   }
258   else
259   {
260     const Vector2& position = mSceneObject->GetViewportPosition(bufferIndex);
261     const Vector2& size = mSceneObject->GetViewportSize(bufferIndex);
262     viewPort.x = position.x;
263     viewPort.y = position.y;
264     viewPort.width = size.width;
265     viewPort.height = size.height;
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( unsigned int 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 unsigned int 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 = size.width;
411         viewport.height = size.height;
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::IsSystemLevel() const
440 {
441   return mIsSystemLevel;
442 }
443
444 bool RenderTask::WorldToViewport(const Vector3 &position, float& viewportX, float& viewportY) const
445 {
446   CameraActor* cam = GetCameraActor();
447
448   Vector4 pos(position);
449   pos.w = 1.0;
450
451   Vector4 viewportPosition;
452
453   Viewport viewport;
454   GetViewport( viewport );
455
456   bool ok = ProjectFull(pos,
457                         cam->GetViewMatrix(),
458                         cam->GetProjectionMatrix(),
459                         viewport.x,
460                         viewport.y,
461                         viewport.width,
462                         viewport.height,
463                         viewportPosition);
464   if(ok)
465   {
466     viewportX = viewportPosition.x;
467     viewportY = viewportPosition.y;
468   }
469
470   return ok;
471 }
472
473 bool RenderTask::ViewportToLocal(Actor* actor, float viewportX, float viewportY, float &localX, float &localY) const
474 {
475   return actor->ScreenToLocal( *this, localX, localY, viewportX, viewportY );
476 }
477
478 SceneGraph::RenderTask* RenderTask::CreateSceneObject()
479 {
480   // This should only be called once, with no existing scene-object
481   DALI_ASSERT_DEBUG( NULL == mSceneObject );
482
483   // Keep the raw-pointer until DiscardSceneObject is called
484   mSceneObject = SceneGraph::RenderTask::New();
485
486   // Send messages to set other properties that may have changed since last time we were on stage
487   SetExclusiveMessage( GetEventThreadServices(), *mSceneObject, mExclusive );
488   SetClearColorMessage(  GetEventThreadServices(), *mSceneObject, mClearColor );
489   SetClearEnabledMessage(  GetEventThreadServices(), *mSceneObject, mClearEnabled );
490   SetCullModeMessage(  GetEventThreadServices(), *mSceneObject, mCullMode );
491   SetRefreshRateMessage(  GetEventThreadServices(), *mSceneObject, mRefreshRate );
492   SetSyncRequiredMessage( GetEventThreadServices(), *mSceneObject, mRequiresSync );
493   SetFrameBuffer( mFrameBuffer );
494
495   // Caller takes ownership
496   return mSceneObject;
497 }
498
499 SceneGraph::RenderTask* RenderTask::GetRenderTaskSceneObject()
500 {
501   return mSceneObject;
502 }
503
504 void RenderTask::DiscardSceneObject()
505 {
506   // mSceneObject is not owned; throw away the raw-pointer
507   mSceneObject = NULL;
508 }
509
510 /********************************************************************************
511  ********************************   PROPERTY METHODS   **************************
512  ********************************************************************************/
513
514 unsigned int RenderTask::GetDefaultPropertyCount() const
515 {
516   return DEFAULT_PROPERTY_COUNT;
517 }
518
519 void RenderTask::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
520 {
521   indices.Reserve( DEFAULT_PROPERTY_COUNT );
522
523   for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
524   {
525     indices.PushBack( i );
526   }
527 }
528
529 const char* RenderTask::GetDefaultPropertyName( Property::Index index ) const
530 {
531   if( index < DEFAULT_PROPERTY_COUNT )
532   {
533     return DEFAULT_PROPERTY_DETAILS[index].name;
534   }
535   else
536   {
537     return NULL;
538   }
539 }
540
541 Property::Index RenderTask::GetDefaultPropertyIndex(const std::string& name) const
542 {
543   Property::Index index = Property::INVALID_INDEX;
544
545   // Look for name in default properties
546   for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
547   {
548     if( 0 == strcmp( name.c_str(), DEFAULT_PROPERTY_DETAILS[i].name ) ) // dont want to convert rhs to string
549     {
550       index = i;
551       break;
552     }
553   }
554
555   return index;
556 }
557
558 bool RenderTask::IsDefaultPropertyWritable(Property::Index index) const
559 {
560   return DEFAULT_PROPERTY_DETAILS[ index ].writable;
561 }
562
563 bool RenderTask::IsDefaultPropertyAnimatable(Property::Index index) const
564 {
565   return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
566 }
567
568 bool RenderTask::IsDefaultPropertyAConstraintInput( Property::Index index ) const
569 {
570   return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
571 }
572
573 Property::Type RenderTask::GetDefaultPropertyType(Property::Index index) const
574 {
575   if( index < DEFAULT_PROPERTY_COUNT )
576   {
577     return DEFAULT_PROPERTY_DETAILS[index].type;
578   }
579
580   // index out of range...return Property::NONE
581   return Property::NONE;
582 }
583
584 void RenderTask::SetDefaultProperty( Property::Index index, const Property::Value& property )
585 {
586   switch ( index )
587   {
588     case Dali::RenderTask::Property::VIEWPORT_POSITION:
589     {
590       SetViewportPosition( property.Get<Vector2>() );
591       break;
592     }
593     case Dali::RenderTask::Property::VIEWPORT_SIZE:
594     {
595       SetViewportSize( property.Get<Vector2>() );
596       break;
597     }
598     case Dali::RenderTask::Property::CLEAR_COLOR:
599     {
600       SetClearColor( property.Get<Vector4>() );
601       break;
602     }
603     case Dali::RenderTask::Property::REQUIRES_SYNC:
604     {
605       SetSyncRequired( property.Get<bool>() );
606       break;
607     }
608     default:
609     {
610       // nothing to do
611       break;
612     }
613   }
614 }
615
616 Property::Value RenderTask::GetDefaultProperty(Property::Index index) const
617 {
618   Property::Value value;
619
620   switch ( index )
621   {
622
623     case Dali::RenderTask::Property::VIEWPORT_POSITION:
624     {
625       value = mViewportPosition;
626       break;
627     }
628     case Dali::RenderTask::Property::VIEWPORT_SIZE:
629     {
630       value = mViewportSize;
631       break;
632     }
633     case Dali::RenderTask::Property::CLEAR_COLOR:
634     {
635       value = mClearColor;
636       break;
637     }
638     case Dali::RenderTask::Property::REQUIRES_SYNC:
639     {
640       value = IsSyncRequired();
641       break;
642     }
643
644     default:
645     {
646       DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
647       break;
648     }
649   }
650
651   return value;
652 }
653
654 Property::Value RenderTask::GetDefaultPropertyCurrentValue( Property::Index index ) const
655 {
656   Property::Value value;
657
658   switch ( index )
659   {
660
661     case Dali::RenderTask::Property::VIEWPORT_POSITION:
662     {
663       value = GetCurrentViewportPosition();
664       break;
665     }
666     case Dali::RenderTask::Property::VIEWPORT_SIZE:
667     {
668       value = GetCurrentViewportSize();
669       break;
670     }
671     case Dali::RenderTask::Property::CLEAR_COLOR:
672     {
673       value = GetClearColor();
674       break;
675     }
676     case Dali::RenderTask::Property::REQUIRES_SYNC:
677     {
678       value = IsSyncRequired();
679       break;
680     }
681
682     default:
683     {
684       DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
685       break;
686     }
687   }
688
689   return value;
690 }
691
692 void RenderTask::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value )
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 }
719
720 const SceneGraph::PropertyOwner* RenderTask::GetSceneObject() const
721 {
722   return mSceneObject;
723 }
724
725 const SceneGraph::PropertyBase* RenderTask::GetSceneObjectAnimatableProperty( Property::Index index ) const
726 {
727   DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" );
728
729   const SceneGraph::PropertyBase* property( NULL );
730
731   // This method should only return a property which is part of the scene-graph
732   if( mSceneObject != NULL )
733   {
734     switch ( index )
735     {
736       case Dali::RenderTask::Property::VIEWPORT_POSITION:
737         property = &mSceneObject->mViewportPosition;
738         break;
739
740       case Dali::RenderTask::Property::VIEWPORT_SIZE:
741         property = &mSceneObject->mViewportSize;
742         break;
743
744       case Dali::RenderTask::Property::CLEAR_COLOR:
745         property = &mSceneObject->mClearColor;
746         break;
747
748       default:
749         break;
750     }
751   }
752
753   return property;
754 }
755
756 const PropertyInputImpl* RenderTask::GetSceneObjectInputProperty( Property::Index index ) const
757 {
758   const PropertyInputImpl* property( NULL );
759   if( mSceneObject != NULL )
760   {
761     switch ( index )
762     {
763       case Dali::RenderTask::Property::VIEWPORT_POSITION:
764         property = &mSceneObject->mViewportPosition;
765         break;
766
767       case Dali::RenderTask::Property::VIEWPORT_SIZE:
768         property = &mSceneObject->mViewportSize;
769         break;
770
771       case Dali::RenderTask::Property::CLEAR_COLOR:
772         property = &mSceneObject->mClearColor;
773         break;
774
775       default:
776         break;
777     }
778   }
779
780   return property;
781 }
782
783 bool RenderTask::HasFinished()
784 {
785   bool finished = false;
786   const unsigned int counter = mSceneObject->GetRenderedOnceCounter();
787
788   if( mRefreshOnceCounter < counter )
789   {
790     finished = true;
791     mRefreshOnceCounter = counter;
792   }
793
794   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::HasFinished()=%s SCRT:%p  SC\n", finished?"T":"F", mSceneObject);
795
796   return finished;
797 }
798
799 void RenderTask::EmitSignalFinish()
800 {
801   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::EmitSignalFinish(this:%p)\n", this);
802
803   if( !mSignalFinished.Empty() )
804   {
805     Dali::RenderTask handle( this );
806     mSignalFinished.Emit(handle );
807   }
808 }
809
810 Dali::RenderTask::RenderTaskSignalType& RenderTask::FinishedSignal()
811 {
812   return mSignalFinished;
813 }
814
815 bool RenderTask::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
816 {
817   bool connected( true );
818   RenderTask* renderTask = static_cast< RenderTask* >(object); // TypeRegistry guarantees that this is the correct type.
819
820   if ( 0 == strcmp( signalName.c_str(), SIGNAL_FINISHED ) )
821   {
822     renderTask->FinishedSignal().Connect( tracker, functor );
823   }
824   else
825   {
826     // signalName does not match any signal
827     connected = false;
828   }
829
830   return connected;
831 }
832
833 RenderTask::RenderTask( bool isSystemLevel )
834 : mSceneObject( NULL ),
835   mSourceConnector( Connector::SOURCE_CONNECTOR, *this ),
836   mCameraConnector( Connector::CAMERA_CONNECTOR, *this ),
837   mMappingConnector( Connector::MAPPING_CONNECTOR, *this  ),
838   mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
839   mViewportPosition( Vector2::ZERO ),
840   mViewportSize( Vector2::ZERO ),
841   mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
842   mRefreshOnceCounter( 0u ),
843   mScreenToFrameBufferFunction( Dali::RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION ),
844   mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
845   mInputEnabled( Dali::RenderTask::DEFAULT_INPUT_ENABLED ),
846   mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
847   mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE ),
848   mIsSystemLevel( isSystemLevel ),
849   mRequiresSync( false )
850 {
851   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::RenderTask(this:%p)\n", this);
852 }
853
854 RenderTask::~RenderTask()
855 {
856   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::~RenderTask(this:%p)\n", this);
857 }
858
859 // Helper class for connecting Nodes to the scene-graph RenderTask
860
861 RenderTask::Connector::Connector( Type type, RenderTask& renderTask )
862 : mType( type ),
863   mRenderTask( renderTask ),
864   mActor( NULL ),
865   mCamera( NULL )
866 {
867 }
868
869 RenderTask::Connector::~Connector()
870 {
871   SetActor( NULL );
872 }
873
874 void RenderTask::Connector::SetActor( Actor* actor )
875 {
876   if ( mActor != actor )
877   {
878     if ( mActor )
879     {
880       mActor->RemoveObserver( *this );
881     }
882
883     mActor = actor;
884
885     if ( mActor )
886     {
887       mActor->AddObserver( *this );
888     }
889
890     UpdateRenderTask();
891   }
892 }
893
894 void RenderTask::Connector::SceneObjectAdded( Object& object )
895 {
896   UpdateRenderTask();
897 }
898
899 void RenderTask::Connector::SceneObjectRemoved( Object& object )
900 {
901   UpdateRenderTask();
902 }
903
904 void RenderTask::Connector::ObjectDestroyed( Object& object )
905 {
906   if ( SOURCE_CONNECTOR == mType )
907   {
908     const Stage* stage = Stage::GetCurrent();
909     if ( stage )
910     {
911       stage->GetRenderTaskList().SetExclusive( &mRenderTask, false );
912     }
913   }
914
915   mActor = NULL;
916   mCamera = NULL; // only meaningful for the camera connector but no simple way to distinguish
917
918   UpdateRenderTask();
919 }
920
921 void RenderTask::Connector::UpdateRenderTask()
922 {
923   // Guard to allow handle destruction after Core has been destroyed
924   if( Internal::Stage::IsInstalled() &&
925       mRenderTask.mSceneObject )
926   {
927     const SceneGraph::Node* node( NULL );
928
929     // Check whether a Node exists in the scene-graph
930     if ( NULL != mActor )
931     {
932       const SceneGraph::PropertyOwner* object = mActor->GetSceneObject();
933       if ( NULL != object )
934       {
935         // actors only point to nodes as their scene objects
936         node = static_cast< const SceneGraph::Node* >( object );
937       }
938     }
939
940     //the mapping node is not used in the scene graph
941     if ( SOURCE_CONNECTOR == mType )
942     {
943       SetSourceNodeMessage( mRenderTask.GetEventThreadServices(), *(mRenderTask.mSceneObject), node );
944     }
945     else if( CAMERA_CONNECTOR == mType )
946     {
947       SetCameraMessage( mRenderTask.GetEventThreadServices(), *(mRenderTask.mSceneObject), node, mCamera );
948     }
949   }
950 }
951
952 } // namespace Internal
953
954 } // namespace Dali