Merge "fix buffer GpuBuffer" into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / event / render-tasks / render-task-impl.cpp
1 /*
2  * Copyright (c) 2015 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/images/frame-buffer-image-impl.h>
33 #include <dali/internal/update/nodes/node.h>
34 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
35 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
36
37 #if defined(DEBUG_ENABLED)
38 namespace
39 {
40 Debug::Filter* gLogRender = Debug::Filter::New(Debug::Concise, false, "LOG_RENDER_TASK");
41 }
42 #endif
43
44 namespace Dali
45 {
46
47 namespace Internal
48 {
49
50 namespace // For internal properties
51 {
52
53 // Properties
54
55 //              Name                 Type     writable animatable constraint-input  enum for index-checking
56 DALI_PROPERTY_TABLE_BEGIN
57 DALI_PROPERTY( "viewportPosition",   VECTOR2,    true,    true,    true,    Dali::RenderTask::Property::VIEWPORT_POSITION )
58 DALI_PROPERTY( "viewportSize",       VECTOR2,    true,    true,    true,    Dali::RenderTask::Property::VIEWPORT_SIZE     )
59 DALI_PROPERTY( "clearColor",         VECTOR4,    true,    true,    true,    Dali::RenderTask::Property::CLEAR_COLOR       )
60 DALI_PROPERTY_TABLE_END( DEFAULT_OBJECT_PROPERTY_START_INDEX )
61
62 // Signals
63
64 const char* const SIGNAL_FINISHED = "finished";
65
66 TypeRegistration mType( typeid( Dali::RenderTask ), typeid( Dali::BaseHandle ), NULL );
67
68 SignalConnectorType signalConnector1( mType, SIGNAL_FINISHED, &RenderTask::DoConnectSignal );
69
70 } // Unnamed namespace
71
72 RenderTask* RenderTask::New( bool isSystemLevel )
73 {
74   RenderTask* task( new RenderTask( isSystemLevel ) );
75
76   return task;
77 }
78
79 void RenderTask::SetSourceActor( Actor* actor )
80 {
81   const Stage* stage = Stage::GetCurrent();
82   if ( stage )
83   {
84     stage->GetRenderTaskList().SetExclusive( this, mExclusive );
85   }
86   mSourceConnector.SetActor( actor );
87 }
88
89 Actor* RenderTask::GetSourceActor() const
90 {
91   return mSourceConnector.mActor;
92 }
93
94 void RenderTask::SetExclusive( bool exclusive )
95 {
96   if ( mExclusive != exclusive )
97   {
98     mExclusive = exclusive;
99
100     const Stage* stage = Stage::GetCurrent();
101     if ( stage )
102     {
103       stage->GetRenderTaskList().SetExclusive( this, exclusive );
104     }
105
106     if ( mSceneObject )
107     {
108       // mSceneObject is being used in a separate thread; queue a message to set the value
109       SetExclusiveMessage( GetEventThreadServices(), *mSceneObject, mExclusive );
110     }
111   }
112 }
113
114 bool RenderTask::IsExclusive() const
115 {
116   return mExclusive;
117 }
118
119 void RenderTask::SetInputEnabled( bool enabled )
120 {
121   mInputEnabled = enabled;
122 }
123
124 bool RenderTask::GetInputEnabled() const
125 {
126   return mInputEnabled;
127 }
128
129 void RenderTask::SetCameraActor( CameraActor* cameraActor )
130 {
131   mCameraConnector.SetActor( cameraActor );
132 }
133
134 CameraActor* RenderTask::GetCameraActor() const
135 {
136   // camera connector can only point to camera actor
137   return static_cast< CameraActor* >( mCameraConnector.mActor );
138 }
139
140 void RenderTask::SetTargetFrameBuffer( Dali::FrameBufferImage image )
141 {
142   if ( mFrameBufferImage != image )
143   {
144     // if we have a scene object we need to track connection status and set frame buffer id as well as updating target frame buffer
145     if ( mSceneObject )
146     {
147       if(mFrameBufferImage)
148       {
149         GetImplementation(mFrameBufferImage).Disconnect();
150       }
151
152       // update target frame buffer
153       mFrameBufferImage = image;
154
155       unsigned int resourceId = 0;
156       bool isNativeFBO = false;
157       if( mFrameBufferImage )
158       {
159         Dali::Internal::FrameBufferImage& impl = GetImplementation( mFrameBufferImage );
160         impl.Connect();
161         resourceId = impl.GetResourceId();
162         isNativeFBO = impl.IsNativeFbo();
163       }
164
165       // mSceneObject is being used in a separate thread; queue a message to set the value
166       SetFrameBufferIdMessage( GetEventThreadServices(), *mSceneObject, resourceId, isNativeFBO );
167     }
168     else
169     {
170       // update target frame buffer
171       mFrameBufferImage = image;
172     }
173   }
174 }
175
176 Dali::FrameBufferImage RenderTask::GetTargetFrameBuffer() const
177 {
178   return mFrameBufferImage;
179 }
180
181 void RenderTask::SetScreenToFrameBufferFunction( ScreenToFrameBufferFunction conversionFunction )
182 {
183   mScreenToFrameBufferFunction = conversionFunction;
184 }
185
186 RenderTask::ScreenToFrameBufferFunction RenderTask::GetScreenToFrameBufferFunction() const
187 {
188   return mScreenToFrameBufferFunction;
189 }
190
191 void RenderTask::SetScreenToFrameBufferMappingActor( Actor* mappingActor )
192 {
193   mMappingConnector.SetActor( mappingActor );
194 }
195
196 Actor* RenderTask::GetScreenToFrameBufferMappingActor() const
197 {
198   return mMappingConnector.mActor;
199 }
200
201 void RenderTask::SetViewportPosition(const Vector2& value)
202 {
203   BakeViewportPositionMessage( GetEventThreadServices(), *mSceneObject, value );
204 }
205
206 Vector2 RenderTask::GetCurrentViewportPosition() const
207 {
208   return mSceneObject->GetViewportPosition( GetEventThreadServices().GetEventBufferIndex() );
209 }
210
211 void RenderTask::SetViewportSize(const Vector2& value)
212 {
213   BakeViewportSizeMessage( GetEventThreadServices(), *mSceneObject, value );
214 }
215
216 Vector2 RenderTask::GetCurrentViewportSize() const
217 {
218   return mSceneObject->GetViewportSize( GetEventThreadServices().GetEventBufferIndex() );
219 }
220
221 void RenderTask::SetViewport( const Viewport& viewport )
222 {
223   SetViewportPosition(Vector2(viewport.x, viewport.y));
224   SetViewportSize(Vector2(viewport.width, viewport.height));
225 }
226
227 void RenderTask::GetViewport( Viewport& viewPort ) const
228 {
229   BufferIndex bufferIndex = GetEventThreadServices().GetEventBufferIndex();
230
231   if(!mSceneObject->GetViewportEnabled( bufferIndex ))
232   {
233     if ( mFrameBufferImage )
234     {
235       viewPort.x = viewPort.y = 0;
236       viewPort.width = mFrameBufferImage.GetWidth();
237       viewPort.height = mFrameBufferImage.GetHeight();
238     }
239     else
240     {
241       Internal::Stage* stage = Internal::Stage::GetCurrent();
242       if ( stage )
243       {
244         Vector2 size( stage->GetSize() );
245         viewPort.x = viewPort.y = 0;
246         viewPort.width = size.width;
247         viewPort.height = size.height;
248       }
249     }
250   }
251   else
252   {
253     const Vector2& position = mSceneObject->GetViewportPosition(bufferIndex);
254     const Vector2& size = mSceneObject->GetViewportSize(bufferIndex);
255     viewPort.x = position.x;
256     viewPort.y = position.y;
257     viewPort.width = size.width;
258     viewPort.height = size.height;
259   }
260 }
261
262 void RenderTask::SetClearColor( const Vector4& color )
263 {
264   if ( mClearColor != color )
265   {
266     mClearColor = color;
267
268     if ( mSceneObject )
269     {
270       // mSceneObject is being used in a separate thread; queue a message to set the value
271       BakeClearColorMessage( GetEventThreadServices(), *mSceneObject, color );
272     }
273   }
274 }
275
276 const Vector4& RenderTask::GetClearColor() const
277 {
278   return mSceneObject->GetClearColor( GetEventThreadServices().GetEventBufferIndex() );
279 }
280
281 void RenderTask::SetClearEnabled( bool enabled )
282 {
283   if ( mClearEnabled != enabled )
284   {
285     mClearEnabled = enabled;
286
287     if ( mSceneObject )
288     {
289       // mSceneObject is being used in a separate thread; queue a message to set the value
290       SetClearEnabledMessage( GetEventThreadServices(), *mSceneObject, mClearEnabled );
291     }
292   }
293 }
294
295 bool RenderTask::GetClearEnabled() const
296 {
297   return mClearEnabled;
298 }
299
300 void RenderTask::SetCullMode( bool mode )
301 {
302   if ( mCullMode != mode )
303   {
304     mCullMode = mode;
305
306     if ( mSceneObject )
307     {
308       // mSceneObject is being used in a separate thread; queue a message to set the value
309       SetCullModeMessage( GetEventThreadServices(), *mSceneObject, mCullMode );
310     }
311   }
312 }
313
314 bool RenderTask::GetCullMode() const
315 {
316   return mCullMode;
317 }
318
319 void RenderTask::SetRefreshRate( unsigned int refreshRate )
320 {
321   DALI_LOG_TRACE_METHOD_FMT(gLogRender, "this:%p  rate:%d\n", this, refreshRate);
322   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::SetRefreshRate(this:%p, %d)\n", this, refreshRate);
323
324   mRefreshRate = refreshRate; // cached for GetRefreshRate()
325
326   // Note - even when refreshRate is the same as mRefreshRate, a message should be sent
327
328   if ( mSceneObject )
329   {
330     // mSceneObject is being used in a separate thread; queue a message to set the value
331     SetRefreshRateMessage( GetEventThreadServices(), *mSceneObject, refreshRate );
332   }
333 }
334
335 unsigned int RenderTask::GetRefreshRate() const
336 {
337   return mRefreshRate;
338 }
339
340 bool RenderTask::IsHittable( Vector2& screenCoords ) const
341 {
342   // True when input is enabled, source & camera actor are valid
343   bool inputEnabled( false );
344
345   Actor* sourceActor = GetSourceActor();
346   CameraActor* cameraActor = GetCameraActor();
347
348   if ( mInputEnabled  &&
349        NULL != sourceActor    &&
350        sourceActor->OnStage() &&
351        NULL != cameraActor    &&
352        cameraActor->OnStage() )
353   {
354     // If the actors are rendered off-screen, then the screen coordinates must be converted
355     // and the conversion function will tell us if they are inside or outside
356     if ( TranslateCoordinates( screenCoords ) )
357     {
358       // This is a suitable render-task for input handling
359       inputEnabled = true;
360     }
361   }
362
363   return inputEnabled;
364 }
365
366 bool RenderTask::TranslateCoordinates( Vector2& screenCoords ) const
367 {
368   // return true for on-screen tasks
369   bool inside( true );
370   // If the actors are rendered off-screen, then the screen coordinates must be converted
371   // the function should only be called for offscreen tasks
372   if( mFrameBufferImage && mMappingConnector.mActor )
373   {
374     CameraActor* localCamera = GetCameraActor();
375     StagePtr stage = Stage::GetCurrent();
376     if( stage )
377     {
378       CameraActor& defaultCamera = stage->GetDefaultCameraActor();
379       if( localCamera )
380       {
381         Viewport viewport;
382         Vector2 size( stage->GetSize() );
383         viewport.x = viewport.y = 0;
384         viewport.width = size.width;
385         viewport.height = size.height;
386
387         float localX, localY;
388         inside = mMappingConnector.mActor->ScreenToLocal(defaultCamera.GetViewMatrix(), defaultCamera.GetProjectionMatrix(), viewport, localX, localY, screenCoords.x, screenCoords.y);
389         Vector3 actorSize = mMappingConnector.mActor->GetCurrentSize();
390         if( inside && localX >= 0.f && localX <= actorSize.x && localY >= 0.f && localY <= actorSize.y)
391         {
392           screenCoords.x = localX;
393           screenCoords.y = localY;
394         }
395         else
396         {
397           inside = false;
398         }
399       }
400       else
401       {
402         inside = false;
403       }
404     }
405   }
406   else if ( mFrameBufferImage && mScreenToFrameBufferFunction )
407   {
408     inside = mScreenToFrameBufferFunction( screenCoords );
409   }
410   return inside;
411 }
412
413 bool RenderTask::IsSystemLevel() const
414 {
415   return mIsSystemLevel;
416 }
417
418 SceneGraph::RenderTask* RenderTask::CreateSceneObject()
419 {
420   // This should only be called once, with no existing scene-object
421   DALI_ASSERT_DEBUG( NULL == mSceneObject );
422
423   // Keep the raw-pointer until DiscardSceneObject is called
424   mSceneObject = SceneGraph::RenderTask::New();
425
426   // 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
427   unsigned int resourceId = 0;
428   bool isNativeFBO = false;
429   if( mFrameBufferImage )
430   {
431     Dali::Internal::FrameBufferImage& impl = GetImplementation( mFrameBufferImage );
432     impl.Connect();
433     resourceId = impl.GetResourceId();
434     isNativeFBO = impl.IsNativeFbo();
435   }
436
437   // mSceneObject is being used in a separate thread; queue a message to set the value
438   SetFrameBufferIdMessage( GetEventThreadServices(), *mSceneObject, resourceId, isNativeFBO );
439
440   // Send messages to set other properties that may have changed since last time we were on stage
441   SetExclusiveMessage( GetEventThreadServices(), *mSceneObject, mExclusive );
442   SetClearColorMessage(  GetEventThreadServices(), *mSceneObject, mClearColor );
443   SetClearEnabledMessage(  GetEventThreadServices(), *mSceneObject, mClearEnabled );
444   SetCullModeMessage(  GetEventThreadServices(), *mSceneObject, mCullMode );
445   SetRefreshRateMessage(  GetEventThreadServices(), *mSceneObject, mRefreshRate );
446
447   // Caller takes ownership
448   return mSceneObject;
449 }
450
451 SceneGraph::RenderTask* RenderTask::GetRenderTaskSceneObject()
452 {
453   return mSceneObject;
454 }
455
456 void RenderTask::DiscardSceneObject()
457 {
458   // mSceneObject is not owned; throw away the raw-pointer
459   mSceneObject = NULL;
460
461   // if we have a frame buffer we need to track connection status
462   if(mFrameBufferImage)
463   {
464     GetImplementation(mFrameBufferImage).Disconnect();
465   }
466 }
467
468 /********************************************************************************
469  ********************************   PROPERTY METHODS   **************************
470  ********************************************************************************/
471
472 unsigned int RenderTask::GetDefaultPropertyCount() const
473 {
474   return DEFAULT_PROPERTY_COUNT;
475 }
476
477 void RenderTask::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
478 {
479   indices.Reserve( DEFAULT_PROPERTY_COUNT );
480
481   for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
482   {
483     indices.PushBack( i );
484   }
485 }
486
487 const char* RenderTask::GetDefaultPropertyName( Property::Index index ) const
488 {
489   if( index < DEFAULT_PROPERTY_COUNT )
490   {
491     return DEFAULT_PROPERTY_DETAILS[index].name;
492   }
493   else
494   {
495     return NULL;
496   }
497 }
498
499 Property::Index RenderTask::GetDefaultPropertyIndex(const std::string& name) const
500 {
501   Property::Index index = Property::INVALID_INDEX;
502
503   // Look for name in default properties
504   for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
505   {
506     if( 0 == strcmp( name.c_str(), DEFAULT_PROPERTY_DETAILS[i].name ) ) // dont want to convert rhs to string
507     {
508       index = i;
509       break;
510     }
511   }
512
513   return index;
514 }
515
516 bool RenderTask::IsDefaultPropertyWritable(Property::Index index) const
517 {
518   return DEFAULT_PROPERTY_DETAILS[ index ].writable;
519 }
520
521 bool RenderTask::IsDefaultPropertyAnimatable(Property::Index index) const
522 {
523   return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
524 }
525
526 bool RenderTask::IsDefaultPropertyAConstraintInput( Property::Index index ) const
527 {
528   return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
529 }
530
531 Property::Type RenderTask::GetDefaultPropertyType(Property::Index index) const
532 {
533   if( index < DEFAULT_PROPERTY_COUNT )
534   {
535     return DEFAULT_PROPERTY_DETAILS[index].type;
536   }
537
538   // index out of range...return Property::NONE
539   return Property::NONE;
540 }
541
542 void RenderTask::SetDefaultProperty( Property::Index index, const Property::Value& property )
543 {
544   switch ( index )
545   {
546     case Dali::RenderTask::Property::VIEWPORT_POSITION:
547     {
548       SetViewportPosition( property.Get<Vector2>() );
549       break;
550     }
551     case Dali::RenderTask::Property::VIEWPORT_SIZE:
552     {
553       SetViewportSize( property.Get<Vector2>() );
554       break;
555     }
556     case Dali::RenderTask::Property::CLEAR_COLOR:
557     {
558       SetClearColor( property.Get<Vector4>() );
559       break;
560     }
561     default:
562     {
563       // nothing to do
564       break;
565     }
566   }
567 }
568
569 Property::Value RenderTask::GetDefaultProperty(Property::Index index) const
570 {
571   Property::Value value;
572
573   switch ( index )
574   {
575
576     case Dali::RenderTask::Property::VIEWPORT_POSITION:
577     {
578       value = GetCurrentViewportPosition();
579       break;
580     }
581     case Dali::RenderTask::Property::VIEWPORT_SIZE:
582     {
583       value = GetCurrentViewportSize();
584       break;
585     }
586     case Dali::RenderTask::Property::CLEAR_COLOR:
587     {
588       value = GetClearColor();
589       break;
590     }
591
592     default:
593     {
594       DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
595       break;
596     }
597   }
598
599   return value;
600 }
601
602 const SceneGraph::PropertyOwner* RenderTask::GetSceneObject() const
603 {
604   return mSceneObject;
605 }
606
607 const SceneGraph::PropertyBase* RenderTask::GetSceneObjectAnimatableProperty( Property::Index index ) const
608 {
609   DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" );
610
611   const SceneGraph::PropertyBase* property( NULL );
612
613   // This method should only return a property which is part of the scene-graph
614   if( mSceneObject != NULL )
615   {
616     switch ( index )
617     {
618       case Dali::RenderTask::Property::VIEWPORT_POSITION:
619         property = &mSceneObject->mViewportPosition;
620         break;
621
622       case Dali::RenderTask::Property::VIEWPORT_SIZE:
623         property = &mSceneObject->mViewportSize;
624         break;
625
626       case Dali::RenderTask::Property::CLEAR_COLOR:
627         property = &mSceneObject->mClearColor;
628         break;
629
630       default:
631         break;
632     }
633   }
634
635   return property;
636 }
637
638 const PropertyInputImpl* RenderTask::GetSceneObjectInputProperty( Property::Index index ) const
639 {
640   const PropertyInputImpl* property( NULL );
641   if( mSceneObject != NULL )
642   {
643     switch ( index )
644     {
645       case Dali::RenderTask::Property::VIEWPORT_POSITION:
646         property = &mSceneObject->mViewportPosition;
647         break;
648
649       case Dali::RenderTask::Property::VIEWPORT_SIZE:
650         property = &mSceneObject->mViewportSize;
651         break;
652
653       case Dali::RenderTask::Property::CLEAR_COLOR:
654         property = &mSceneObject->mViewportSize;
655         break;
656
657       default:
658         break;
659     }
660   }
661
662   return property;
663 }
664
665 bool RenderTask::HasFinished()
666 {
667   bool finished = false;
668   const unsigned int counter = mSceneObject->GetRenderedOnceCounter();
669
670   if( mRefreshOnceCounter < counter )
671   {
672     finished = true;
673     mRefreshOnceCounter = counter;
674   }
675
676   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::HasFinished()=%s SCRT:%p  SC\n", finished?"T":"F", mSceneObject);
677
678   return finished;
679 }
680
681 void RenderTask::EmitSignalFinish()
682 {
683   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::EmitSignalFinish(this:%p)\n", this);
684
685   if( !mSignalFinished.Empty() )
686   {
687     Dali::RenderTask handle( this );
688     mSignalFinished.Emit(handle );
689   }
690 }
691
692 Dali::RenderTask::RenderTaskSignalType& RenderTask::FinishedSignal()
693 {
694   return mSignalFinished;
695 }
696
697 bool RenderTask::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
698 {
699   bool connected( true );
700   RenderTask* renderTask = dynamic_cast<RenderTask*>(object);
701
702   if ( 0 == strcmp( signalName.c_str(), SIGNAL_FINISHED ) )
703   {
704     renderTask->FinishedSignal().Connect( tracker, functor );
705   }
706   else
707   {
708     // signalName does not match any signal
709     connected = false;
710   }
711
712   return connected;
713 }
714
715 RenderTask::RenderTask( bool isSystemLevel )
716 : mSceneObject( NULL ),
717   mSourceConnector( Connector::SOURCE_CONNECTOR, *this ),
718   mCameraConnector( Connector::CAMERA_CONNECTOR, *this ),
719   mMappingConnector( Connector::MAPPING_CONNECTOR, *this  ),
720   mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
721   mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
722   mRefreshOnceCounter( 0u ),
723   mScreenToFrameBufferFunction( Dali::RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION ),
724   mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
725   mInputEnabled( Dali::RenderTask::DEFAULT_INPUT_ENABLED ),
726   mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
727   mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE ),
728   mIsSystemLevel( isSystemLevel )
729 {
730   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::RenderTask(this:%p)\n", this);
731 }
732
733 RenderTask::~RenderTask()
734 {
735   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::~RenderTask(this:%p)\n", this);
736 }
737
738 // Helper class for connecting Nodes to the scene-graph RenderTask
739
740 RenderTask::Connector::Connector( Type type, RenderTask& renderTask )
741 : mType( type ),
742   mRenderTask( renderTask ),
743   mActor( NULL )
744 {
745 }
746
747 RenderTask::Connector::~Connector()
748 {
749   SetActor( NULL );
750 }
751
752 void RenderTask::Connector::SetActor( Actor* actor )
753 {
754   if ( mActor != actor )
755   {
756     if ( mActor )
757     {
758       mActor->RemoveObserver( *this );
759     }
760
761     mActor = actor;
762
763     if ( mActor )
764     {
765       mActor->AddObserver( *this );
766     }
767
768     UpdateRenderTask();
769   }
770 }
771
772 void RenderTask::Connector::SceneObjectAdded( Object& object )
773 {
774   UpdateRenderTask();
775 }
776
777 void RenderTask::Connector::SceneObjectRemoved( Object& object )
778 {
779   UpdateRenderTask();
780 }
781
782 void RenderTask::Connector::ObjectDestroyed( Object& object )
783 {
784   if ( SOURCE_CONNECTOR == mType )
785   {
786     const Stage* stage = Stage::GetCurrent();
787     if ( stage )
788     {
789       stage->GetRenderTaskList().SetExclusive( &mRenderTask, false );
790     }
791   }
792
793   mActor = NULL;
794
795   UpdateRenderTask();
796 }
797
798 void RenderTask::Connector::UpdateRenderTask()
799 {
800   // Guard to allow handle destruction after Core has been destroyed
801   if( Internal::Stage::IsInstalled() &&
802       mRenderTask.mSceneObject )
803   {
804     const SceneGraph::Node* node( NULL );
805
806     // Check whether a Node exists in the scene-graph
807     if ( NULL != mActor )
808     {
809       const SceneGraph::PropertyOwner* object = mActor->GetSceneObject();
810       if ( NULL != object )
811       {
812         // actors only point to nodes as their scene objects
813         node = static_cast< const SceneGraph::Node* >( object );
814       }
815     }
816
817     //the mapping node is not used in the scene graph
818     if ( SOURCE_CONNECTOR == mType )
819     {
820       SetSourceNodeMessage( mRenderTask.GetEventThreadServices(), *(mRenderTask.mSceneObject), node );
821     }
822     else if( CAMERA_CONNECTOR == mType )
823     {
824       SetCameraNodeMessage( mRenderTask.GetEventThreadServices(), *(mRenderTask.mSceneObject), node );
825     }
826   }
827 }
828
829 } // namespace Internal
830
831 } // namespace Dali