2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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
8 // http://floralicense.org/license/
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.
18 #include <dali/internal/event/render-tasks/render-task-impl.h>
21 #include <dali/public-api/common/dali-common.h>
22 #include <dali/internal/common/event-to-update.h>
23 #include <dali/internal/event/actors/actor-impl.h>
24 #include <dali/internal/event/actors/camera-actor-impl.h>
25 #include <dali/internal/event/common/stage-impl.h>
26 #include <dali/internal/event/common/thread-local-storage.h>
27 #include <dali/internal/event/images/frame-buffer-image-impl.h>
28 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
29 #include <dali/internal/update/nodes/node.h>
31 #if defined(DEBUG_ENABLED)
34 Debug::Filter* gLogRender = Debug::Filter::New(Debug::Concise, false, "LOG_RENDER_TASK");
41 const Property::Index RenderTask::VIEWPORT_POSITION = 0;
42 const Property::Index RenderTask::VIEWPORT_SIZE = 1;
43 const Property::Index RenderTask::CLEAR_COLOR = 2;
48 namespace // For internal properties
51 const std::string DEFAULT_PROPERTY_NAMES[] =
57 const int DEFAULT_PROPERTY_COUNT = sizeof( DEFAULT_PROPERTY_NAMES ) / sizeof( std::string );
59 const Property::Type DEFAULT_PROPERTY_TYPES[DEFAULT_PROPERTY_COUNT] =
61 Property::VECTOR2, // viewport-position
62 Property::VECTOR2, // viewport-size
63 Property::VECTOR4, // clear-color
68 RenderTask::DefaultPropertyLookup* RenderTask::sDefaultPropertyLookup = NULL;
70 RenderTask* RenderTask::New( bool isSystemLevel )
72 RenderTask* task( new RenderTask( ThreadLocalStorage::Get().GetEventToUpdate(), isSystemLevel ) );
77 void RenderTask::SetSourceActor( Actor* actor )
79 mSourceConnector.SetActor( actor );
82 Actor* RenderTask::GetSourceActor() const
84 return mSourceConnector.mActor;
87 void RenderTask::SetExclusive( bool exclusive )
89 if ( mExclusive != exclusive )
91 mExclusive = exclusive;
95 // mSceneObject is being used in a separate thread; queue a message to set the value
96 SetExclusiveMessage( mEventToUpdate, *mSceneObject, mExclusive );
101 bool RenderTask::IsExclusive() const
106 void RenderTask::SetInputEnabled( bool enabled )
108 mInputEnabled = enabled;
111 bool RenderTask::GetInputEnabled() const
113 return mInputEnabled;
116 void RenderTask::SetCameraActor( CameraActor* cameraActor )
118 mCameraConnector.SetActor( cameraActor );
121 CameraActor* RenderTask::GetCameraActor() const
123 // camera connector can only point to camera actor
124 return static_cast< CameraActor* >( mCameraConnector.mActor );
127 void RenderTask::SetTargetFrameBuffer( Dali::FrameBufferImage image )
129 if ( mFrameBufferImage != image )
131 // if we have a scene object we need to track connection status and set frame buffer id as well as updating target frame buffer
134 if(mFrameBufferImage)
136 GetImplementation(mFrameBufferImage).Disconnect();
139 // update target frame buffer
140 mFrameBufferImage = image;
142 unsigned int resourceId = 0;
143 if(mFrameBufferImage)
145 GetImplementation(mFrameBufferImage).Connect();
147 resourceId = GetImplementation( mFrameBufferImage ).GetResourceId();
150 // mSceneObject is being used in a separate thread; queue a message to set the value
151 SetFrameBufferIdMessage( mEventToUpdate, *mSceneObject, resourceId );
155 // update target frame buffer
156 mFrameBufferImage = image;
161 Dali::FrameBufferImage RenderTask::GetTargetFrameBuffer() const
163 return mFrameBufferImage;
166 void RenderTask::SetScreenToFrameBufferFunction( ScreenToFrameBufferFunction conversionFunction )
168 mScreenToFrameBufferFunction = conversionFunction;
171 RenderTask::ScreenToFrameBufferFunction RenderTask::GetScreenToFrameBufferFunction() const
173 return mScreenToFrameBufferFunction;
176 void RenderTask::SetScreenToFrameBufferMappingActor( Actor* mappingActor )
178 mMappingConnector.SetActor( mappingActor );
181 Actor* RenderTask::GetScreenToFrameBufferMappingActor() const
183 return mMappingConnector.mActor;
186 void RenderTask::SetViewportPosition(const Vector2& value)
188 StagePtr stage = Stage::GetCurrent();
189 BakeViewportPositionMessage( stage->GetUpdateInterface(), *mSceneObject, value );
192 Vector2 RenderTask::GetCurrentViewportPosition() const
194 StagePtr stage = Stage::GetCurrent();
195 return mSceneObject->GetViewportPosition(stage->GetEventBufferIndex());
198 void RenderTask::SetViewportSize(const Vector2& value)
200 StagePtr stage = Stage::GetCurrent();
201 BakeViewportSizeMessage( stage->GetUpdateInterface(), *mSceneObject, value );
204 Vector2 RenderTask::GetCurrentViewportSize() const
206 StagePtr stage = Stage::GetCurrent();
207 return mSceneObject->GetViewportSize(stage->GetEventBufferIndex());
210 void RenderTask::SetViewport( const Viewport& viewport )
212 SetViewportPosition(Vector2(viewport.x, viewport.y));
213 SetViewportSize(Vector2(viewport.width, viewport.height));
216 void RenderTask::GetViewport( Viewport& viewPort ) const
218 BufferIndex bufferIndex = Stage::GetCurrent()->GetEventBufferIndex();
220 if(!mSceneObject->GetViewportEnabled( bufferIndex ))
222 if ( mFrameBufferImage )
224 viewPort.x = viewPort.y = 0;
225 viewPort.width = mFrameBufferImage.GetWidth();
226 viewPort.height = mFrameBufferImage.GetHeight();
230 Vector2 size( Stage::GetCurrent()->GetSize() );
231 viewPort.x = viewPort.y = 0;
232 viewPort.width = size.width;
233 viewPort.height = size.height;
238 const Vector2& position = mSceneObject->GetViewportPosition(bufferIndex);
239 const Vector2& size = mSceneObject->GetViewportSize(bufferIndex);
240 viewPort.x = position.x;
241 viewPort.y = position.y;
242 viewPort.width = size.width;
243 viewPort.height = size.height;
247 void RenderTask::SetClearColor( const Vector4& color )
249 if ( mClearColor != color )
255 // mSceneObject is being used in a separate thread; queue a message to set the value
256 StagePtr stage = Stage::GetCurrent();
257 BakeClearColorMessage( stage->GetUpdateInterface(), *mSceneObject, color );
262 const Vector4& RenderTask::GetClearColor() const
264 StagePtr stage = Stage::GetCurrent();
265 return mSceneObject->GetClearColor(stage->GetEventBufferIndex());
268 void RenderTask::SetClearEnabled( bool enabled )
270 if ( mClearEnabled != enabled )
272 mClearEnabled = enabled;
276 // mSceneObject is being used in a separate thread; queue a message to set the value
277 SetClearEnabledMessage( mEventToUpdate, *mSceneObject, mClearEnabled );
282 bool RenderTask::GetClearEnabled() const
284 return mClearEnabled;
287 void RenderTask::SetRefreshRate( unsigned int refreshRate )
289 DALI_LOG_TRACE_METHOD_FMT(gLogRender, "this:%p rate:%d\n", this, refreshRate);
290 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::SetRefreshRate(this:%p, %d)\n", this, refreshRate);
292 mRefreshRate = refreshRate; // cached for GetRefreshRate()
294 // Note - even when refreshRate is the same as mRefreshRate, a message should be sent
298 // mSceneObject is being used in a separate thread; queue a message to set the value
299 SetRefreshRateMessage( mEventToUpdate, *mSceneObject, refreshRate );
303 unsigned int RenderTask::GetRefreshRate() const
308 bool RenderTask::IsHittable( Vector2& screenCoords ) const
310 // True when input is enabled, source & camera actor are valid
311 bool inputEnabled( false );
313 Actor* sourceActor = GetSourceActor();
314 CameraActor* cameraActor = GetCameraActor();
316 if ( mInputEnabled &&
317 NULL != sourceActor &&
318 sourceActor->OnStage() &&
319 NULL != cameraActor &&
320 cameraActor->OnStage() )
322 // If the actors are rendered off-screen, then the screen coordinates must be converted
323 // and the conversion function will tell us if they are inside or outside
324 if ( TranslateCoordinates( screenCoords ) )
326 // This is a suitable render-task for input handling
334 bool RenderTask::TranslateCoordinates( Vector2& screenCoords ) const
336 // return true for on-screen tasks
338 // If the actors are rendered off-screen, then the screen coordinates must be converted
339 // the function should only be called for offscreen tasks
340 if( mFrameBufferImage && mMappingConnector.mActor )
342 CameraActor* localCamera = GetCameraActor();
343 StagePtr stage = Stage::GetCurrent();
344 CameraActor& defaultCamera = stage->GetDefaultCameraActor();
348 Vector2 size( stage->GetSize() );
349 viewport.x = viewport.y = 0;
350 viewport.width = size.width;
351 viewport.height = size.height;
353 float localX, localY;
354 inside = mMappingConnector.mActor->ScreenToLocal(defaultCamera.GetViewMatrix(), defaultCamera.GetProjectionMatrix(), viewport, localX, localY, screenCoords.x, screenCoords.y);
355 Vector3 actorSize = mMappingConnector.mActor->GetCurrentSize();
356 if( inside && localX >= 0.f && localX <= actorSize.x && localY >= 0.f && localY <= actorSize.y)
358 screenCoords.x = localX;
359 screenCoords.y = localY;
371 else if ( mFrameBufferImage && mScreenToFrameBufferFunction )
373 inside = mScreenToFrameBufferFunction( screenCoords );
378 bool RenderTask::IsSystemLevel() const
380 return mIsSystemLevel;
383 SceneGraph::RenderTask* RenderTask::CreateSceneObject()
385 // This should only be called once, with no existing scene-object
386 DALI_ASSERT_DEBUG( NULL == mSceneObject );
388 // Keep the raw-pointer until DiscardSceneObject is called
389 mSceneObject = SceneGraph::RenderTask::New();
391 // 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
392 unsigned int resourceId = 0;
393 if(mFrameBufferImage)
395 GetImplementation(mFrameBufferImage).Connect();
397 resourceId = GetImplementation( mFrameBufferImage ).GetResourceId();
400 // mSceneObject is being used in a separate thread; queue a message to set the value
401 SetFrameBufferIdMessage( mEventToUpdate, *mSceneObject, resourceId );
403 // Send messages to set other properties that may have changed since last time we were on stage
404 SetExclusiveMessage( mEventToUpdate, *mSceneObject, mExclusive );
405 SetClearColorMessage( mEventToUpdate, *mSceneObject, mClearColor );
406 SetClearEnabledMessage( mEventToUpdate, *mSceneObject, mClearEnabled );
407 SetRefreshRateMessage( mEventToUpdate, *mSceneObject, mRefreshRate );
409 // Caller takes ownership
413 SceneGraph::RenderTask* RenderTask::GetRenderTaskSceneObject()
418 void RenderTask::DiscardSceneObject()
420 // mSceneObject is not owned; throw away the raw-pointer
423 // if we have a frame buffer we need to track connection status
424 if(mFrameBufferImage)
426 GetImplementation(mFrameBufferImage).Disconnect();
430 /********************************************************************************
431 ********************************************************************************
432 ******************************** PROPERTY METHODS **************************
433 ********************************************************************************
434 ********************************************************************************/
436 bool RenderTask::IsSceneObjectRemovable() const
438 return false; // The scene object is permanently "on stage" whilst this object is alive
441 unsigned int RenderTask::GetDefaultPropertyCount() const
443 return DEFAULT_PROPERTY_COUNT;
446 void RenderTask::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
448 indices.reserve( DEFAULT_PROPERTY_COUNT );
450 for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
452 indices.push_back( i );
456 const std::string& RenderTask::GetDefaultPropertyName( Property::Index index ) const
458 if( index < DEFAULT_PROPERTY_COUNT )
460 return DEFAULT_PROPERTY_NAMES[index];
464 // index out of range..return empty string
465 static const std::string INVALID_PROPERTY_NAME;
466 return INVALID_PROPERTY_NAME;
470 Property::Index RenderTask::GetDefaultPropertyIndex(const std::string& name) const
472 Property::Index index = Property::INVALID_INDEX;
474 // Lazy initialization of static sDefaultPropertyLookup
475 if (!sDefaultPropertyLookup)
477 sDefaultPropertyLookup = new DefaultPropertyLookup();
479 for (int i=0; i<DEFAULT_PROPERTY_COUNT; ++i)
481 (*sDefaultPropertyLookup)[DEFAULT_PROPERTY_NAMES[i]] = i;
484 DALI_ASSERT_DEBUG( NULL != sDefaultPropertyLookup );
486 // Look for name in default properties
487 DefaultPropertyLookup::const_iterator result = sDefaultPropertyLookup->find( name );
488 if ( sDefaultPropertyLookup->end() != result )
490 index = result->second;
496 bool RenderTask::IsDefaultPropertyWritable(Property::Index index) const
501 bool RenderTask::IsDefaultPropertyAnimatable(Property::Index index) const
506 bool RenderTask::IsDefaultPropertyAConstraintInput( Property::Index index ) const
511 Property::Type RenderTask::GetDefaultPropertyType(Property::Index index) const
513 if( index < DEFAULT_PROPERTY_COUNT )
515 return DEFAULT_PROPERTY_TYPES[index];
519 // index out of range...return Property::NONE
520 return Property::NONE;
524 void RenderTask::SetDefaultProperty( Property::Index index, const Property::Value& property )
528 case Dali::RenderTask::VIEWPORT_POSITION:
530 SetViewportPosition( property.Get<Vector2>() );
533 case Dali::RenderTask::VIEWPORT_SIZE:
535 SetViewportSize( property.Get<Vector2>() );
538 case Dali::RenderTask::CLEAR_COLOR:
540 SetClearColor( property.Get<Vector4>() );
546 DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
552 void RenderTask::SetCustomProperty( Property::Index /*index*/, const CustomProperty& /*entry*/, const Property::Value& /*value*/ )
554 // TODO: support them, it doesn't hurt.
555 DALI_ASSERT_ALWAYS( 0 && "RenderTask does not support custom properties");
558 Property::Value RenderTask::GetDefaultProperty(Property::Index index) const
560 Property::Value value;
565 case Dali::RenderTask::VIEWPORT_POSITION:
567 value = GetCurrentViewportPosition();
570 case Dali::RenderTask::VIEWPORT_SIZE:
572 value = GetCurrentViewportSize();
575 case Dali::RenderTask::CLEAR_COLOR:
577 value = GetClearColor();
583 DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
591 void RenderTask::InstallSceneObjectProperty( SceneGraph::PropertyBase& newProperty, const std::string& name, unsigned int index )
593 // TODO: support them, it doesn't hurt.
594 DALI_ASSERT_ALWAYS( 0 && "RenderTask does not support custom properties" );
597 const SceneGraph::PropertyOwner* RenderTask::GetSceneObject() const
602 const SceneGraph::PropertyBase* RenderTask::GetSceneObjectAnimatableProperty( Property::Index index ) const
604 DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" );
606 const SceneGraph::PropertyBase* property( NULL );
608 // This method should only return a property which is part of the scene-graph
609 if( mSceneObject != NULL )
613 case Dali::RenderTask::VIEWPORT_POSITION:
614 property = &mSceneObject->mViewportPosition;
617 case Dali::RenderTask::VIEWPORT_SIZE:
618 property = &mSceneObject->mViewportSize;
621 case Dali::RenderTask::CLEAR_COLOR:
622 property = &mSceneObject->mClearColor;
633 const PropertyInputImpl* RenderTask::GetSceneObjectInputProperty( Property::Index index ) const
635 const PropertyInputImpl* property( NULL );
636 if( mSceneObject != NULL )
640 case Dali::RenderTask::VIEWPORT_POSITION:
641 property = &mSceneObject->mViewportPosition;
644 case Dali::RenderTask::VIEWPORT_SIZE:
645 property = &mSceneObject->mViewportSize;
648 case Dali::RenderTask::CLEAR_COLOR:
649 property = &mSceneObject->mViewportSize;
660 bool RenderTask::HasFinished()
662 bool finished = false;
663 const unsigned int counter = mSceneObject->GetRenderedOnceCounter();
665 if( mRefreshOnceCounter < counter )
668 mRefreshOnceCounter = counter;
671 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::HasFinished()=%s SCRT:%p SC\n", finished?"T":"F", mSceneObject);
676 void RenderTask::EmitSignalFinish()
678 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::EmitSignalFinish(this:%p)\n", this);
680 if( !mSignalFinishedV2.Empty() )
682 Dali::RenderTask handle( this );
683 mSignalFinishedV2.Emit(handle );
687 Dali::RenderTask::RenderTaskSignalV2& RenderTask::FinishedSignal()
689 return mSignalFinishedV2;
692 bool RenderTask::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
694 bool connected( true );
695 RenderTask* renderTask = dynamic_cast<RenderTask*>(object);
697 if ( Dali::RenderTask::SIGNAL_FINISHED == signalName )
699 renderTask->FinishedSignal().Connect( tracker, functor );
703 // signalName does not match any signal
710 RenderTask::RenderTask( EventToUpdate& eventToUpdate, bool isSystemLevel )
711 : mEventToUpdate( eventToUpdate ),
712 mSceneObject( NULL ),
713 mSourceConnector( Connector::SOURCE_CONNECTOR, *this ),
714 mCameraConnector( Connector::CAMERA_CONNECTOR, *this ),
715 mMappingConnector( Connector::MAPPING_CONNECTOR, *this ),
716 mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
717 mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
718 mRefreshOnceCounter( 0u ),
719 mScreenToFrameBufferFunction( Dali::RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION ),
720 mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
721 mInputEnabled( Dali::RenderTask::DEFAULT_INPUT_ENABLED ),
722 mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
723 mIsSystemLevel( isSystemLevel )
725 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::RenderTask(this:%p)\n", this);
728 RenderTask::~RenderTask()
730 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::~RenderTask(this:%p)\n", this);
733 // Helper class for connecting Nodes to the scene-graph RenderTask
735 RenderTask::Connector::Connector( Type type, RenderTask& renderTask )
737 mRenderTask( renderTask ),
742 RenderTask::Connector::~Connector()
747 void RenderTask::Connector::SetActor( Actor* actor )
749 if ( mActor != actor )
753 mActor->RemoveObserver( *this );
760 mActor->AddObserver( *this );
767 void RenderTask::Connector::SceneObjectAdded( ProxyObject& proxy )
772 void RenderTask::Connector::SceneObjectRemoved( ProxyObject& proxy )
777 void RenderTask::Connector::ProxyDestroyed( ProxyObject& proxy )
784 void RenderTask::Connector::UpdateRenderTask()
786 // Guard to allow handle destruction after Core has been destroyed
787 if( Internal::Stage::IsInstalled() &&
788 mRenderTask.mSceneObject )
790 const SceneGraph::Node* node( NULL );
792 // Check whether a Node exists in the scene-graph
793 if ( NULL != mActor )
795 const SceneGraph::PropertyOwner* object = mActor->GetSceneObject();
796 if ( NULL != object )
798 // actors only point to nodes as their scene objects
799 node = static_cast< const SceneGraph::Node* >( object );
803 //the mapping node is not used in the scene graph
804 if ( SOURCE_CONNECTOR == mType )
806 SetSourceNodeMessage( mRenderTask.mEventToUpdate, *(mRenderTask.mSceneObject), node );
808 else if( CAMERA_CONNECTOR == mType )
810 SetCameraNodeMessage( mRenderTask.mEventToUpdate, *(mRenderTask.mSceneObject), node );
815 } // namespace Internal