2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/event/render-tasks/render-task-impl.h>
22 #include <dali/public-api/common/dali-common.h>
23 #include <dali/public-api/object/type-registry.h>
24 #include <dali/internal/common/event-to-update.h>
25 #include <dali/internal/event/actors/actor-impl.h>
26 #include <dali/internal/event/actors/camera-actor-impl.h>
27 #include <dali/internal/event/common/stage-impl.h>
28 #include <dali/internal/event/common/thread-local-storage.h>
29 #include <dali/internal/event/images/frame-buffer-image-impl.h>
30 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
31 #include <dali/internal/update/nodes/node.h>
33 #if defined(DEBUG_ENABLED)
36 Debug::Filter* gLogRender = Debug::Filter::New(Debug::Concise, false, "LOG_RENDER_TASK");
43 const Property::Index RenderTask::VIEWPORT_POSITION = 0;
44 const Property::Index RenderTask::VIEWPORT_SIZE = 1;
45 const Property::Index RenderTask::CLEAR_COLOR = 2;
50 namespace // For internal properties
55 const char* const SIGNAL_FINISHED = "finished";
57 TypeRegistration mType( typeid( Dali::RenderTask ), typeid( Dali::BaseHandle ), NULL );
59 SignalConnectorType signalConnector1( mType, SIGNAL_FINISHED, &RenderTask::DoConnectSignal );
61 const char* DEFAULT_PROPERTY_NAMES[] =
67 const int DEFAULT_PROPERTY_COUNT = sizeof( DEFAULT_PROPERTY_NAMES ) / sizeof( DEFAULT_PROPERTY_NAMES[0]);
69 const Property::Type DEFAULT_PROPERTY_TYPES[DEFAULT_PROPERTY_COUNT] =
71 Property::VECTOR2, // viewport-position
72 Property::VECTOR2, // viewport-size
73 Property::VECTOR4, // clear-color
78 RenderTask* RenderTask::New( bool isSystemLevel )
80 RenderTask* task( new RenderTask( ThreadLocalStorage::Get().GetEventToUpdate(), isSystemLevel ) );
85 void RenderTask::SetSourceActor( Actor* actor )
87 mSourceConnector.SetActor( actor );
90 Actor* RenderTask::GetSourceActor() const
92 return mSourceConnector.mActor;
95 void RenderTask::SetExclusive( bool exclusive )
97 if ( mExclusive != exclusive )
99 mExclusive = exclusive;
103 // mSceneObject is being used in a separate thread; queue a message to set the value
104 SetExclusiveMessage( mEventToUpdate, *mSceneObject, mExclusive );
109 bool RenderTask::IsExclusive() const
114 void RenderTask::SetInputEnabled( bool enabled )
116 mInputEnabled = enabled;
119 bool RenderTask::GetInputEnabled() const
121 return mInputEnabled;
124 void RenderTask::SetCameraActor( CameraActor* cameraActor )
126 mCameraConnector.SetActor( cameraActor );
129 CameraActor* RenderTask::GetCameraActor() const
131 // camera connector can only point to camera actor
132 return static_cast< CameraActor* >( mCameraConnector.mActor );
135 void RenderTask::SetTargetFrameBuffer( Dali::FrameBufferImage image )
137 if ( mFrameBufferImage != image )
139 // if we have a scene object we need to track connection status and set frame buffer id as well as updating target frame buffer
142 if(mFrameBufferImage)
144 GetImplementation(mFrameBufferImage).Disconnect();
147 // update target frame buffer
148 mFrameBufferImage = image;
150 unsigned int resourceId = 0;
151 if(mFrameBufferImage)
153 GetImplementation(mFrameBufferImage).Connect();
155 resourceId = GetImplementation( mFrameBufferImage ).GetResourceId();
158 // mSceneObject is being used in a separate thread; queue a message to set the value
159 SetFrameBufferIdMessage( mEventToUpdate, *mSceneObject, resourceId );
163 // update target frame buffer
164 mFrameBufferImage = image;
169 Dali::FrameBufferImage RenderTask::GetTargetFrameBuffer() const
171 return mFrameBufferImage;
174 void RenderTask::SetScreenToFrameBufferFunction( ScreenToFrameBufferFunction conversionFunction )
176 mScreenToFrameBufferFunction = conversionFunction;
179 RenderTask::ScreenToFrameBufferFunction RenderTask::GetScreenToFrameBufferFunction() const
181 return mScreenToFrameBufferFunction;
184 void RenderTask::SetScreenToFrameBufferMappingActor( Actor* mappingActor )
186 mMappingConnector.SetActor( mappingActor );
189 Actor* RenderTask::GetScreenToFrameBufferMappingActor() const
191 return mMappingConnector.mActor;
194 void RenderTask::SetViewportPosition(const Vector2& value)
196 StagePtr stage = Stage::GetCurrent();
197 BakeViewportPositionMessage( stage->GetUpdateInterface(), *mSceneObject, value );
200 Vector2 RenderTask::GetCurrentViewportPosition() const
202 StagePtr stage = Stage::GetCurrent();
203 return mSceneObject->GetViewportPosition(stage->GetEventBufferIndex());
206 void RenderTask::SetViewportSize(const Vector2& value)
208 StagePtr stage = Stage::GetCurrent();
209 BakeViewportSizeMessage( stage->GetUpdateInterface(), *mSceneObject, value );
212 Vector2 RenderTask::GetCurrentViewportSize() const
214 StagePtr stage = Stage::GetCurrent();
215 return mSceneObject->GetViewportSize(stage->GetEventBufferIndex());
218 void RenderTask::SetViewport( const Viewport& viewport )
220 SetViewportPosition(Vector2(viewport.x, viewport.y));
221 SetViewportSize(Vector2(viewport.width, viewport.height));
224 void RenderTask::GetViewport( Viewport& viewPort ) const
226 BufferIndex bufferIndex = Stage::GetCurrent()->GetEventBufferIndex();
228 if(!mSceneObject->GetViewportEnabled( bufferIndex ))
230 if ( mFrameBufferImage )
232 viewPort.x = viewPort.y = 0;
233 viewPort.width = mFrameBufferImage.GetWidth();
234 viewPort.height = mFrameBufferImage.GetHeight();
238 Vector2 size( Stage::GetCurrent()->GetSize() );
239 viewPort.x = viewPort.y = 0;
240 viewPort.width = size.width;
241 viewPort.height = size.height;
246 const Vector2& position = mSceneObject->GetViewportPosition(bufferIndex);
247 const Vector2& size = mSceneObject->GetViewportSize(bufferIndex);
248 viewPort.x = position.x;
249 viewPort.y = position.y;
250 viewPort.width = size.width;
251 viewPort.height = size.height;
255 void RenderTask::SetClearColor( const Vector4& color )
257 if ( mClearColor != color )
263 // mSceneObject is being used in a separate thread; queue a message to set the value
264 StagePtr stage = Stage::GetCurrent();
265 BakeClearColorMessage( stage->GetUpdateInterface(), *mSceneObject, color );
270 const Vector4& RenderTask::GetClearColor() const
272 StagePtr stage = Stage::GetCurrent();
273 return mSceneObject->GetClearColor(stage->GetEventBufferIndex());
276 void RenderTask::SetClearEnabled( bool enabled )
278 if ( mClearEnabled != enabled )
280 mClearEnabled = enabled;
284 // mSceneObject is being used in a separate thread; queue a message to set the value
285 SetClearEnabledMessage( mEventToUpdate, *mSceneObject, mClearEnabled );
290 bool RenderTask::GetClearEnabled() const
292 return mClearEnabled;
295 void RenderTask::SetCullMode( bool mode )
297 if ( mCullMode != mode )
303 // mSceneObject is being used in a separate thread; queue a message to set the value
304 SetCullModeMessage( mEventToUpdate, *mSceneObject, mCullMode );
309 bool RenderTask::GetCullMode() const
314 void RenderTask::SetRefreshRate( unsigned int refreshRate )
316 DALI_LOG_TRACE_METHOD_FMT(gLogRender, "this:%p rate:%d\n", this, refreshRate);
317 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::SetRefreshRate(this:%p, %d)\n", this, refreshRate);
319 mRefreshRate = refreshRate; // cached for GetRefreshRate()
321 // Note - even when refreshRate is the same as mRefreshRate, a message should be sent
325 // mSceneObject is being used in a separate thread; queue a message to set the value
326 SetRefreshRateMessage( mEventToUpdate, *mSceneObject, refreshRate );
330 unsigned int RenderTask::GetRefreshRate() const
335 bool RenderTask::IsHittable( Vector2& screenCoords ) const
337 // True when input is enabled, source & camera actor are valid
338 bool inputEnabled( false );
340 Actor* sourceActor = GetSourceActor();
341 CameraActor* cameraActor = GetCameraActor();
343 if ( mInputEnabled &&
344 NULL != sourceActor &&
345 sourceActor->OnStage() &&
346 NULL != cameraActor &&
347 cameraActor->OnStage() )
349 // If the actors are rendered off-screen, then the screen coordinates must be converted
350 // and the conversion function will tell us if they are inside or outside
351 if ( TranslateCoordinates( screenCoords ) )
353 // This is a suitable render-task for input handling
361 bool RenderTask::TranslateCoordinates( Vector2& screenCoords ) const
363 // return true for on-screen tasks
365 // If the actors are rendered off-screen, then the screen coordinates must be converted
366 // the function should only be called for offscreen tasks
367 if( mFrameBufferImage && mMappingConnector.mActor )
369 CameraActor* localCamera = GetCameraActor();
370 StagePtr stage = Stage::GetCurrent();
371 CameraActor& defaultCamera = stage->GetDefaultCameraActor();
375 Vector2 size( stage->GetSize() );
376 viewport.x = viewport.y = 0;
377 viewport.width = size.width;
378 viewport.height = size.height;
380 float localX, localY;
381 inside = mMappingConnector.mActor->ScreenToLocal(defaultCamera.GetViewMatrix(), defaultCamera.GetProjectionMatrix(), viewport, localX, localY, screenCoords.x, screenCoords.y);
382 Vector3 actorSize = mMappingConnector.mActor->GetCurrentSize();
383 if( inside && localX >= 0.f && localX <= actorSize.x && localY >= 0.f && localY <= actorSize.y)
385 screenCoords.x = localX;
386 screenCoords.y = localY;
398 else if ( mFrameBufferImage && mScreenToFrameBufferFunction )
400 inside = mScreenToFrameBufferFunction( screenCoords );
405 bool RenderTask::IsSystemLevel() const
407 return mIsSystemLevel;
410 SceneGraph::RenderTask* RenderTask::CreateSceneObject()
412 // This should only be called once, with no existing scene-object
413 DALI_ASSERT_DEBUG( NULL == mSceneObject );
415 // Keep the raw-pointer until DiscardSceneObject is called
416 mSceneObject = SceneGraph::RenderTask::New();
418 // 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
419 unsigned int resourceId = 0;
420 if(mFrameBufferImage)
422 GetImplementation(mFrameBufferImage).Connect();
424 resourceId = GetImplementation( mFrameBufferImage ).GetResourceId();
427 // mSceneObject is being used in a separate thread; queue a message to set the value
428 SetFrameBufferIdMessage( mEventToUpdate, *mSceneObject, resourceId );
430 // Send messages to set other properties that may have changed since last time we were on stage
431 SetExclusiveMessage( mEventToUpdate, *mSceneObject, mExclusive );
432 SetClearColorMessage( mEventToUpdate, *mSceneObject, mClearColor );
433 SetClearEnabledMessage( mEventToUpdate, *mSceneObject, mClearEnabled );
434 SetCullModeMessage( mEventToUpdate, *mSceneObject, mCullMode );
435 SetRefreshRateMessage( mEventToUpdate, *mSceneObject, mRefreshRate );
437 // Caller takes ownership
441 SceneGraph::RenderTask* RenderTask::GetRenderTaskSceneObject()
446 void RenderTask::DiscardSceneObject()
448 // mSceneObject is not owned; throw away the raw-pointer
451 // if we have a frame buffer we need to track connection status
452 if(mFrameBufferImage)
454 GetImplementation(mFrameBufferImage).Disconnect();
458 /********************************************************************************
459 ********************************************************************************
460 ******************************** PROPERTY METHODS **************************
461 ********************************************************************************
462 ********************************************************************************/
464 unsigned int RenderTask::GetDefaultPropertyCount() const
466 return DEFAULT_PROPERTY_COUNT;
469 void RenderTask::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
471 indices.reserve( DEFAULT_PROPERTY_COUNT );
473 for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
475 indices.push_back( i );
479 const char* RenderTask::GetDefaultPropertyName( Property::Index index ) const
481 if( index < DEFAULT_PROPERTY_COUNT )
483 return DEFAULT_PROPERTY_NAMES[index];
491 Property::Index RenderTask::GetDefaultPropertyIndex(const std::string& name) const
493 Property::Index index = Property::INVALID_INDEX;
495 // Look for name in default properties
496 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
498 if( 0 == strcmp( name.c_str(), DEFAULT_PROPERTY_NAMES[ i ] ) ) // dont want to convert rhs to string
508 bool RenderTask::IsDefaultPropertyWritable(Property::Index index) const
510 return true; // all properties writable
513 bool RenderTask::IsDefaultPropertyAnimatable(Property::Index index) const
515 return true; // all properties animatable
518 bool RenderTask::IsDefaultPropertyAConstraintInput( Property::Index index ) const
520 return true; // all properties can be used as constraint input
523 Property::Type RenderTask::GetDefaultPropertyType(Property::Index index) const
525 if( index < DEFAULT_PROPERTY_COUNT )
527 return DEFAULT_PROPERTY_TYPES[index];
531 // index out of range...return Property::NONE
532 return Property::NONE;
536 void RenderTask::SetDefaultProperty( Property::Index index, const Property::Value& property )
540 case Dali::RenderTask::VIEWPORT_POSITION:
542 SetViewportPosition( property.Get<Vector2>() );
545 case Dali::RenderTask::VIEWPORT_SIZE:
547 SetViewportSize( property.Get<Vector2>() );
550 case Dali::RenderTask::CLEAR_COLOR:
552 SetClearColor( property.Get<Vector4>() );
563 Property::Value RenderTask::GetDefaultProperty(Property::Index index) const
565 Property::Value value;
570 case Dali::RenderTask::VIEWPORT_POSITION:
572 value = GetCurrentViewportPosition();
575 case Dali::RenderTask::VIEWPORT_SIZE:
577 value = GetCurrentViewportSize();
580 case Dali::RenderTask::CLEAR_COLOR:
582 value = GetClearColor();
588 DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
596 const SceneGraph::PropertyOwner* RenderTask::GetSceneObject() const
601 const SceneGraph::PropertyBase* RenderTask::GetSceneObjectAnimatableProperty( Property::Index index ) const
603 DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" );
605 const SceneGraph::PropertyBase* property( NULL );
607 // This method should only return a property which is part of the scene-graph
608 if( mSceneObject != NULL )
612 case Dali::RenderTask::VIEWPORT_POSITION:
613 property = &mSceneObject->mViewportPosition;
616 case Dali::RenderTask::VIEWPORT_SIZE:
617 property = &mSceneObject->mViewportSize;
620 case Dali::RenderTask::CLEAR_COLOR:
621 property = &mSceneObject->mClearColor;
632 const PropertyInputImpl* RenderTask::GetSceneObjectInputProperty( Property::Index index ) const
634 const PropertyInputImpl* property( NULL );
635 if( mSceneObject != NULL )
639 case Dali::RenderTask::VIEWPORT_POSITION:
640 property = &mSceneObject->mViewportPosition;
643 case Dali::RenderTask::VIEWPORT_SIZE:
644 property = &mSceneObject->mViewportSize;
647 case Dali::RenderTask::CLEAR_COLOR:
648 property = &mSceneObject->mViewportSize;
659 bool RenderTask::HasFinished()
661 bool finished = false;
662 const unsigned int counter = mSceneObject->GetRenderedOnceCounter();
664 if( mRefreshOnceCounter < counter )
667 mRefreshOnceCounter = counter;
670 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::HasFinished()=%s SCRT:%p SC\n", finished?"T":"F", mSceneObject);
675 void RenderTask::EmitSignalFinish()
677 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::EmitSignalFinish(this:%p)\n", this);
679 if( !mSignalFinished.Empty() )
681 Dali::RenderTask handle( this );
682 mSignalFinished.Emit(handle );
686 Dali::RenderTask::RenderTaskSignalType& RenderTask::FinishedSignal()
688 return mSignalFinished;
691 bool RenderTask::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
693 bool connected( true );
694 RenderTask* renderTask = dynamic_cast<RenderTask*>(object);
696 if ( 0 == strcmp( signalName.c_str(), SIGNAL_FINISHED ) )
698 renderTask->FinishedSignal().Connect( tracker, functor );
702 // signalName does not match any signal
709 RenderTask::RenderTask( EventToUpdate& eventToUpdate, bool isSystemLevel )
710 : mEventToUpdate( eventToUpdate ),
711 mSceneObject( NULL ),
712 mSourceConnector( Connector::SOURCE_CONNECTOR, *this ),
713 mCameraConnector( Connector::CAMERA_CONNECTOR, *this ),
714 mMappingConnector( Connector::MAPPING_CONNECTOR, *this ),
715 mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
716 mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
717 mRefreshOnceCounter( 0u ),
718 mScreenToFrameBufferFunction( Dali::RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION ),
719 mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
720 mInputEnabled( Dali::RenderTask::DEFAULT_INPUT_ENABLED ),
721 mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
722 mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE ),
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( Object& object )
772 void RenderTask::Connector::SceneObjectRemoved( Object& object )
777 void RenderTask::Connector::ObjectDestroyed( Object& object )
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