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