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