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;
360 if( !localCamera->GetInvertYAxis() )
362 screenCoords.y = actorSize.y - localY;
375 else if ( mFrameBufferImage && mScreenToFrameBufferFunction )
377 inside = mScreenToFrameBufferFunction( screenCoords );
382 bool RenderTask::IsSystemLevel() const
384 return mIsSystemLevel;
387 SceneGraph::RenderTask* RenderTask::CreateSceneObject()
389 // This should only be called once, with no existing scene-object
390 DALI_ASSERT_DEBUG( NULL == mSceneObject );
392 // Keep the raw-pointer until DiscardSceneObject is called
393 mSceneObject = SceneGraph::RenderTask::New();
395 // 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
396 unsigned int resourceId = 0;
397 if(mFrameBufferImage)
399 GetImplementation(mFrameBufferImage).Connect();
401 resourceId = GetImplementation( mFrameBufferImage ).GetResourceId();
404 // mSceneObject is being used in a separate thread; queue a message to set the value
405 SetFrameBufferIdMessage( mEventToUpdate, *mSceneObject, resourceId );
407 // Send messages to set other properties that may have changed since last time we were on stage
408 SetExclusiveMessage( mEventToUpdate, *mSceneObject, mExclusive );
409 SetClearColorMessage( mEventToUpdate, *mSceneObject, mClearColor );
410 SetClearEnabledMessage( mEventToUpdate, *mSceneObject, mClearEnabled );
411 SetRefreshRateMessage( mEventToUpdate, *mSceneObject, mRefreshRate );
413 // Caller takes ownership
417 SceneGraph::RenderTask* RenderTask::GetRenderTaskSceneObject()
422 void RenderTask::DiscardSceneObject()
424 // mSceneObject is not owned; throw away the raw-pointer
427 // if we have a frame buffer we need to track connection status
428 if(mFrameBufferImage)
430 GetImplementation(mFrameBufferImage).Disconnect();
434 /********************************************************************************
435 ********************************************************************************
436 ******************************** PROPERTY METHODS **************************
437 ********************************************************************************
438 ********************************************************************************/
440 bool RenderTask::IsSceneObjectRemovable() const
442 return false; // The scene object is permanently "on stage" whilst this object is alive
445 unsigned int RenderTask::GetDefaultPropertyCount() const
447 return DEFAULT_PROPERTY_COUNT;
450 const std::string& RenderTask::GetDefaultPropertyName( Property::Index index ) const
452 // ProxyObject guarantees that index is within range
453 return DEFAULT_PROPERTY_NAMES[index];
456 Property::Index RenderTask::GetDefaultPropertyIndex(const std::string& name) const
458 Property::Index index = Property::INVALID_INDEX;
460 // Lazy initialization of static sDefaultPropertyLookup
461 if (!sDefaultPropertyLookup)
463 sDefaultPropertyLookup = new DefaultPropertyLookup();
465 for (int i=0; i<DEFAULT_PROPERTY_COUNT; ++i)
467 (*sDefaultPropertyLookup)[DEFAULT_PROPERTY_NAMES[i]] = i;
470 DALI_ASSERT_DEBUG( NULL != sDefaultPropertyLookup );
472 // Look for name in default properties
473 DefaultPropertyLookup::const_iterator result = sDefaultPropertyLookup->find( name );
474 if ( sDefaultPropertyLookup->end() != result )
476 index = result->second;
482 bool RenderTask::IsDefaultPropertyWritable(Property::Index index) const
487 bool RenderTask::IsDefaultPropertyAnimatable(Property::Index index) const
492 Property::Type RenderTask::GetDefaultPropertyType(Property::Index index) const
494 // ProxyObject guarantees that index is within range
495 return DEFAULT_PROPERTY_TYPES[index];
498 void RenderTask::SetDefaultProperty( Property::Index index, const Property::Value& property )
500 // ProxyObject guarantees the property is writable and index is in range
503 case Dali::RenderTask::VIEWPORT_POSITION:
505 SetViewportPosition( property.Get<Vector2>() );
508 case Dali::RenderTask::VIEWPORT_SIZE:
510 SetViewportSize( property.Get<Vector2>() );
513 case Dali::RenderTask::CLEAR_COLOR:
515 SetClearColor( property.Get<Vector4>() );
521 DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
527 void RenderTask::SetCustomProperty( Property::Index /*index*/, const CustomProperty& /*entry*/, const Property::Value& /*value*/ )
529 // TODO: support them, it doesn't hurt.
530 DALI_ASSERT_ALWAYS( 0 && "RenderTask does not support custom properties");
533 Property::Value RenderTask::GetDefaultProperty(Property::Index index) const
535 Property::Value value;
537 // ProxyObject guarantees that index is within range
541 case Dali::RenderTask::VIEWPORT_POSITION:
543 value = GetCurrentViewportPosition();
546 case Dali::RenderTask::VIEWPORT_SIZE:
548 value = GetCurrentViewportSize();
551 case Dali::RenderTask::CLEAR_COLOR:
553 value = GetClearColor();
559 DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
567 void RenderTask::InstallSceneObjectProperty( SceneGraph::PropertyBase& newProperty, const std::string& name, unsigned int index )
569 // TODO: support them, it doesn't hurt.
570 DALI_ASSERT_ALWAYS( 0 && "RenderTask does not support custom properties" );
573 const SceneGraph::PropertyOwner* RenderTask::GetSceneObject() const
578 const SceneGraph::PropertyBase* RenderTask::GetSceneObjectAnimatableProperty( Property::Index index ) const
580 DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" );
582 const SceneGraph::PropertyBase* property( NULL );
584 // This method should only return a property which is part of the scene-graph
585 if( mSceneObject != NULL )
589 case Dali::RenderTask::VIEWPORT_POSITION:
590 property = &mSceneObject->mViewportPosition;
593 case Dali::RenderTask::VIEWPORT_SIZE:
594 property = &mSceneObject->mViewportSize;
597 case Dali::RenderTask::CLEAR_COLOR:
598 property = &mSceneObject->mClearColor;
609 const PropertyInputImpl* RenderTask::GetSceneObjectInputProperty( Property::Index index ) const
611 const PropertyInputImpl* property( NULL );
612 if( mSceneObject != NULL )
616 case Dali::RenderTask::VIEWPORT_POSITION:
617 property = &mSceneObject->mViewportPosition;
620 case Dali::RenderTask::VIEWPORT_SIZE:
621 property = &mSceneObject->mViewportSize;
624 case Dali::RenderTask::CLEAR_COLOR:
625 property = &mSceneObject->mViewportSize;
636 bool RenderTask::HasFinished()
638 bool finished = false;
639 const unsigned int counter = mSceneObject->GetRenderedOnceCounter();
641 if( mRefreshOnceCounter < counter )
644 mRefreshOnceCounter = counter;
647 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::HasFinished()=%s SCRT:%p SC\n", finished?"T":"F", mSceneObject);
652 void RenderTask::EmitSignalFinish()
654 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::EmitSignalFinish(this:%p)\n", this);
656 if( !mSignalFinishedV2.Empty() )
658 Dali::RenderTask handle( this );
659 mSignalFinishedV2.Emit(handle );
663 Dali::RenderTask::RenderTaskSignalV2& RenderTask::FinishedSignal()
665 return mSignalFinishedV2;
668 bool RenderTask::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
670 bool connected( true );
671 RenderTask* renderTask = dynamic_cast<RenderTask*>(object);
673 if ( Dali::RenderTask::SIGNAL_FINISHED == signalName )
675 renderTask->FinishedSignal().Connect( tracker, functor );
679 // signalName does not match any signal
686 RenderTask::RenderTask( EventToUpdate& eventToUpdate, bool isSystemLevel )
687 : mEventToUpdate( eventToUpdate ),
688 mSceneObject( NULL ),
689 mSourceConnector( Connector::SOURCE_CONNECTOR, *this ),
690 mCameraConnector( Connector::CAMERA_CONNECTOR, *this ),
691 mMappingConnector( Connector::MAPPING_CONNECTOR, *this ),
692 mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
693 mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
694 mRefreshOnceCounter( 0u ),
695 mScreenToFrameBufferFunction( Dali::RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION ),
696 mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
697 mInputEnabled( Dali::RenderTask::DEFAULT_INPUT_ENABLED ),
698 mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
699 mIsSystemLevel( isSystemLevel )
701 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::RenderTask(this:%p)\n", this);
704 RenderTask::~RenderTask()
706 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::~RenderTask(this:%p)\n", this);
709 // Helper class for connecting Nodes to the scene-graph RenderTask
711 RenderTask::Connector::Connector( Type type, RenderTask& renderTask )
713 mRenderTask( renderTask ),
718 RenderTask::Connector::~Connector()
723 void RenderTask::Connector::SetActor( Actor* actor )
725 if ( mActor != actor )
729 mActor->RemoveObserver( *this );
736 mActor->AddObserver( *this );
743 void RenderTask::Connector::SceneObjectAdded( ProxyObject& proxy )
748 void RenderTask::Connector::SceneObjectRemoved( ProxyObject& proxy )
753 void RenderTask::Connector::ProxyDestroyed( ProxyObject& proxy )
760 void RenderTask::Connector::UpdateRenderTask()
762 // Guard to allow handle destruction after Core has been destroyed
763 if( Internal::Stage::IsInstalled() &&
764 mRenderTask.mSceneObject )
766 const SceneGraph::Node* node( NULL );
768 // Check whether a Node exists in the scene-graph
769 if ( NULL != mActor )
771 const SceneGraph::PropertyOwner* object = mActor->GetSceneObject();
772 if ( NULL != object )
774 // actors only point to nodes as their scene objects
775 node = static_cast< const SceneGraph::Node* >( object );
779 //the mapping node is not used in the scene graph
780 if ( SOURCE_CONNECTOR == mType )
782 SetSourceNodeMessage( mRenderTask.mEventToUpdate, *(mRenderTask.mSceneObject), node );
784 else if( CAMERA_CONNECTOR == mType )
786 SetCameraNodeMessage( mRenderTask.mEventToUpdate, *(mRenderTask.mSceneObject), node );
791 } // namespace Internal