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 <cstring> // for strcmp
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/update/render-tasks/scene-graph-render-task.h>
36 #if defined(DEBUG_ENABLED)
39 Debug::Filter* gLogRender = Debug::Filter::New(Debug::Concise, false, "LOG_RENDER_TASK");
49 namespace // For internal properties
54 // Name Type writable animatable constraint-input enum for index-checking
55 DALI_PROPERTY_TABLE_BEGIN
56 DALI_PROPERTY( "viewport-position", VECTOR2, true, true, true, Dali::RenderTask::Property::VIEWPORT_POSITION )
57 DALI_PROPERTY( "viewport-size", VECTOR2, true, true, true, Dali::RenderTask::Property::VIEWPORT_SIZE )
58 DALI_PROPERTY( "clear-color", VECTOR4, true, true, true, Dali::RenderTask::Property::CLEAR_COLOR )
59 DALI_PROPERTY_TABLE_END( DEFAULT_OBJECT_PROPERTY_START_INDEX )
63 const char* const SIGNAL_FINISHED = "finished";
65 TypeRegistration mType( typeid( Dali::RenderTask ), typeid( Dali::BaseHandle ), NULL );
67 SignalConnectorType signalConnector1( mType, SIGNAL_FINISHED, &RenderTask::DoConnectSignal );
69 } // Unnamed namespace
71 RenderTask* RenderTask::New( bool isSystemLevel )
73 RenderTask* task( new RenderTask( isSystemLevel ) );
78 void RenderTask::SetSourceActor( Actor* actor )
80 mSourceConnector.SetActor( actor );
83 Actor* RenderTask::GetSourceActor() const
85 return mSourceConnector.mActor;
88 void RenderTask::SetExclusive( bool exclusive )
90 if ( mExclusive != exclusive )
92 mExclusive = exclusive;
96 // mSceneObject is being used in a separate thread; queue a message to set the value
97 SetExclusiveMessage( GetEventThreadServices(), *mSceneObject, mExclusive );
102 bool RenderTask::IsExclusive() const
107 void RenderTask::SetInputEnabled( bool enabled )
109 mInputEnabled = enabled;
112 bool RenderTask::GetInputEnabled() const
114 return mInputEnabled;
117 void RenderTask::SetCameraActor( CameraActor* cameraActor )
119 mCameraConnector.SetActor( cameraActor );
122 CameraActor* RenderTask::GetCameraActor() const
124 // camera connector can only point to camera actor
125 return static_cast< CameraActor* >( mCameraConnector.mActor );
128 void RenderTask::SetTargetFrameBuffer( Dali::FrameBufferImage image )
130 if ( mFrameBufferImage != image )
132 // if we have a scene object we need to track connection status and set frame buffer id as well as updating target frame buffer
135 if(mFrameBufferImage)
137 GetImplementation(mFrameBufferImage).Disconnect();
140 // update target frame buffer
141 mFrameBufferImage = image;
143 unsigned int resourceId = 0;
144 if(mFrameBufferImage)
146 GetImplementation(mFrameBufferImage).Connect();
148 resourceId = GetImplementation( mFrameBufferImage ).GetResourceId();
151 // mSceneObject is being used in a separate thread; queue a message to set the value
152 SetFrameBufferIdMessage( GetEventThreadServices(), *mSceneObject, resourceId );
156 // update target frame buffer
157 mFrameBufferImage = image;
162 Dali::FrameBufferImage RenderTask::GetTargetFrameBuffer() const
164 return mFrameBufferImage;
167 void RenderTask::SetScreenToFrameBufferFunction( ScreenToFrameBufferFunction conversionFunction )
169 mScreenToFrameBufferFunction = conversionFunction;
172 RenderTask::ScreenToFrameBufferFunction RenderTask::GetScreenToFrameBufferFunction() const
174 return mScreenToFrameBufferFunction;
177 void RenderTask::SetScreenToFrameBufferMappingActor( Actor* mappingActor )
179 mMappingConnector.SetActor( mappingActor );
182 Actor* RenderTask::GetScreenToFrameBufferMappingActor() const
184 return mMappingConnector.mActor;
187 void RenderTask::SetViewportPosition(const Vector2& value)
189 BakeViewportPositionMessage( GetEventThreadServices(), *mSceneObject, value );
192 Vector2 RenderTask::GetCurrentViewportPosition() const
194 return mSceneObject->GetViewportPosition( GetEventThreadServices().GetEventBufferIndex() );
197 void RenderTask::SetViewportSize(const Vector2& value)
199 BakeViewportSizeMessage( GetEventThreadServices(), *mSceneObject, value );
202 Vector2 RenderTask::GetCurrentViewportSize() const
204 return mSceneObject->GetViewportSize( GetEventThreadServices().GetEventBufferIndex() );
207 void RenderTask::SetViewport( const Viewport& viewport )
209 SetViewportPosition(Vector2(viewport.x, viewport.y));
210 SetViewportSize(Vector2(viewport.width, viewport.height));
213 void RenderTask::GetViewport( Viewport& viewPort ) const
215 BufferIndex bufferIndex = GetEventThreadServices().GetEventBufferIndex();
217 if(!mSceneObject->GetViewportEnabled( bufferIndex ))
219 if ( mFrameBufferImage )
221 viewPort.x = viewPort.y = 0;
222 viewPort.width = mFrameBufferImage.GetWidth();
223 viewPort.height = mFrameBufferImage.GetHeight();
227 Vector2 size( Stage::GetCurrent()->GetSize() );
228 viewPort.x = viewPort.y = 0;
229 viewPort.width = size.width;
230 viewPort.height = size.height;
235 const Vector2& position = mSceneObject->GetViewportPosition(bufferIndex);
236 const Vector2& size = mSceneObject->GetViewportSize(bufferIndex);
237 viewPort.x = position.x;
238 viewPort.y = position.y;
239 viewPort.width = size.width;
240 viewPort.height = size.height;
244 void RenderTask::SetClearColor( const Vector4& color )
246 if ( mClearColor != color )
252 // mSceneObject is being used in a separate thread; queue a message to set the value
253 BakeClearColorMessage( GetEventThreadServices(), *mSceneObject, color );
258 const Vector4& RenderTask::GetClearColor() const
260 return mSceneObject->GetClearColor( GetEventThreadServices().GetEventBufferIndex() );
263 void RenderTask::SetClearEnabled( bool enabled )
265 if ( mClearEnabled != enabled )
267 mClearEnabled = enabled;
271 // mSceneObject is being used in a separate thread; queue a message to set the value
272 SetClearEnabledMessage( GetEventThreadServices(), *mSceneObject, mClearEnabled );
277 bool RenderTask::GetClearEnabled() const
279 return mClearEnabled;
282 void RenderTask::SetCullMode( bool mode )
284 if ( mCullMode != mode )
290 // mSceneObject is being used in a separate thread; queue a message to set the value
291 SetCullModeMessage( GetEventThreadServices(), *mSceneObject, mCullMode );
296 bool RenderTask::GetCullMode() const
301 void RenderTask::SetRefreshRate( unsigned int refreshRate )
303 DALI_LOG_TRACE_METHOD_FMT(gLogRender, "this:%p rate:%d\n", this, refreshRate);
304 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::SetRefreshRate(this:%p, %d)\n", this, refreshRate);
306 mRefreshRate = refreshRate; // cached for GetRefreshRate()
308 // Note - even when refreshRate is the same as mRefreshRate, a message should be sent
312 // mSceneObject is being used in a separate thread; queue a message to set the value
313 SetRefreshRateMessage( GetEventThreadServices(), *mSceneObject, refreshRate );
317 unsigned int RenderTask::GetRefreshRate() const
322 bool RenderTask::IsHittable( Vector2& screenCoords ) const
324 // True when input is enabled, source & camera actor are valid
325 bool inputEnabled( false );
327 Actor* sourceActor = GetSourceActor();
328 CameraActor* cameraActor = GetCameraActor();
330 if ( mInputEnabled &&
331 NULL != sourceActor &&
332 sourceActor->OnStage() &&
333 NULL != cameraActor &&
334 cameraActor->OnStage() )
336 // If the actors are rendered off-screen, then the screen coordinates must be converted
337 // and the conversion function will tell us if they are inside or outside
338 if ( TranslateCoordinates( screenCoords ) )
340 // This is a suitable render-task for input handling
348 bool RenderTask::TranslateCoordinates( Vector2& screenCoords ) const
350 // return true for on-screen tasks
352 // If the actors are rendered off-screen, then the screen coordinates must be converted
353 // the function should only be called for offscreen tasks
354 if( mFrameBufferImage && mMappingConnector.mActor )
356 CameraActor* localCamera = GetCameraActor();
357 StagePtr stage = Stage::GetCurrent();
358 CameraActor& defaultCamera = stage->GetDefaultCameraActor();
362 Vector2 size( stage->GetSize() );
363 viewport.x = viewport.y = 0;
364 viewport.width = size.width;
365 viewport.height = size.height;
367 float localX, localY;
368 inside = mMappingConnector.mActor->ScreenToLocal(defaultCamera.GetViewMatrix(), defaultCamera.GetProjectionMatrix(), viewport, localX, localY, screenCoords.x, screenCoords.y);
369 Vector3 actorSize = mMappingConnector.mActor->GetCurrentSize();
370 if( inside && localX >= 0.f && localX <= actorSize.x && localY >= 0.f && localY <= actorSize.y)
372 screenCoords.x = localX;
373 screenCoords.y = localY;
385 else if ( mFrameBufferImage && mScreenToFrameBufferFunction )
387 inside = mScreenToFrameBufferFunction( screenCoords );
392 bool RenderTask::IsSystemLevel() const
394 return mIsSystemLevel;
397 SceneGraph::RenderTask* RenderTask::CreateSceneObject()
399 // This should only be called once, with no existing scene-object
400 DALI_ASSERT_DEBUG( NULL == mSceneObject );
402 // Keep the raw-pointer until DiscardSceneObject is called
403 mSceneObject = SceneGraph::RenderTask::New();
405 // 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
406 unsigned int resourceId = 0;
407 if(mFrameBufferImage)
409 GetImplementation(mFrameBufferImage).Connect();
411 resourceId = GetImplementation( mFrameBufferImage ).GetResourceId();
414 // mSceneObject is being used in a separate thread; queue a message to set the value
415 SetFrameBufferIdMessage( GetEventThreadServices(), *mSceneObject, resourceId );
417 // Send messages to set other properties that may have changed since last time we were on stage
418 SetExclusiveMessage( GetEventThreadServices(), *mSceneObject, mExclusive );
419 SetClearColorMessage( GetEventThreadServices(), *mSceneObject, mClearColor );
420 SetClearEnabledMessage( GetEventThreadServices(), *mSceneObject, mClearEnabled );
421 SetCullModeMessage( GetEventThreadServices(), *mSceneObject, mCullMode );
422 SetRefreshRateMessage( GetEventThreadServices(), *mSceneObject, mRefreshRate );
424 // Caller takes ownership
428 SceneGraph::RenderTask* RenderTask::GetRenderTaskSceneObject()
433 void RenderTask::DiscardSceneObject()
435 // mSceneObject is not owned; throw away the raw-pointer
438 // if we have a frame buffer we need to track connection status
439 if(mFrameBufferImage)
441 GetImplementation(mFrameBufferImage).Disconnect();
445 /********************************************************************************
446 ******************************** PROPERTY METHODS **************************
447 ********************************************************************************/
449 unsigned int RenderTask::GetDefaultPropertyCount() const
451 return DEFAULT_PROPERTY_COUNT;
454 void RenderTask::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
456 indices.reserve( DEFAULT_PROPERTY_COUNT );
458 for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
460 indices.push_back( i );
464 const char* RenderTask::GetDefaultPropertyName( Property::Index index ) const
466 if( index < DEFAULT_PROPERTY_COUNT )
468 return DEFAULT_PROPERTY_DETAILS[index].name;
476 Property::Index RenderTask::GetDefaultPropertyIndex(const std::string& name) const
478 Property::Index index = Property::INVALID_INDEX;
480 // Look for name in default properties
481 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
483 if( 0 == strcmp( name.c_str(), DEFAULT_PROPERTY_DETAILS[i].name ) ) // dont want to convert rhs to string
493 bool RenderTask::IsDefaultPropertyWritable(Property::Index index) const
495 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
498 bool RenderTask::IsDefaultPropertyAnimatable(Property::Index index) const
500 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
503 bool RenderTask::IsDefaultPropertyAConstraintInput( Property::Index index ) const
505 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
508 Property::Type RenderTask::GetDefaultPropertyType(Property::Index index) const
510 if( index < DEFAULT_PROPERTY_COUNT )
512 return DEFAULT_PROPERTY_DETAILS[index].type;
515 // index out of range...return Property::NONE
516 return Property::NONE;
519 void RenderTask::SetDefaultProperty( Property::Index index, const Property::Value& property )
523 case Dali::RenderTask::Property::VIEWPORT_POSITION:
525 SetViewportPosition( property.Get<Vector2>() );
528 case Dali::RenderTask::Property::VIEWPORT_SIZE:
530 SetViewportSize( property.Get<Vector2>() );
533 case Dali::RenderTask::Property::CLEAR_COLOR:
535 SetClearColor( property.Get<Vector4>() );
546 Property::Value RenderTask::GetDefaultProperty(Property::Index index) const
548 Property::Value value;
553 case Dali::RenderTask::Property::VIEWPORT_POSITION:
555 value = GetCurrentViewportPosition();
558 case Dali::RenderTask::Property::VIEWPORT_SIZE:
560 value = GetCurrentViewportSize();
563 case Dali::RenderTask::Property::CLEAR_COLOR:
565 value = GetClearColor();
571 DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
579 const SceneGraph::PropertyOwner* RenderTask::GetSceneObject() const
584 const SceneGraph::PropertyBase* RenderTask::GetSceneObjectAnimatableProperty( Property::Index index ) const
586 DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" );
588 const SceneGraph::PropertyBase* property( NULL );
590 // This method should only return a property which is part of the scene-graph
591 if( mSceneObject != NULL )
595 case Dali::RenderTask::Property::VIEWPORT_POSITION:
596 property = &mSceneObject->mViewportPosition;
599 case Dali::RenderTask::Property::VIEWPORT_SIZE:
600 property = &mSceneObject->mViewportSize;
603 case Dali::RenderTask::Property::CLEAR_COLOR:
604 property = &mSceneObject->mClearColor;
615 const PropertyInputImpl* RenderTask::GetSceneObjectInputProperty( Property::Index index ) const
617 const PropertyInputImpl* property( NULL );
618 if( mSceneObject != NULL )
622 case Dali::RenderTask::Property::VIEWPORT_POSITION:
623 property = &mSceneObject->mViewportPosition;
626 case Dali::RenderTask::Property::VIEWPORT_SIZE:
627 property = &mSceneObject->mViewportSize;
630 case Dali::RenderTask::Property::CLEAR_COLOR:
631 property = &mSceneObject->mViewportSize;
642 bool RenderTask::HasFinished()
644 bool finished = false;
645 const unsigned int counter = mSceneObject->GetRenderedOnceCounter();
647 if( mRefreshOnceCounter < counter )
650 mRefreshOnceCounter = counter;
653 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::HasFinished()=%s SCRT:%p SC\n", finished?"T":"F", mSceneObject);
658 void RenderTask::EmitSignalFinish()
660 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::EmitSignalFinish(this:%p)\n", this);
662 if( !mSignalFinished.Empty() )
664 Dali::RenderTask handle( this );
665 mSignalFinished.Emit(handle );
669 Dali::RenderTask::RenderTaskSignalType& RenderTask::FinishedSignal()
671 return mSignalFinished;
674 bool RenderTask::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
676 bool connected( true );
677 RenderTask* renderTask = dynamic_cast<RenderTask*>(object);
679 if ( 0 == strcmp( signalName.c_str(), SIGNAL_FINISHED ) )
681 renderTask->FinishedSignal().Connect( tracker, functor );
685 // signalName does not match any signal
692 RenderTask::RenderTask( bool isSystemLevel )
693 : mSceneObject( NULL ),
694 mSourceConnector( Connector::SOURCE_CONNECTOR, *this ),
695 mCameraConnector( Connector::CAMERA_CONNECTOR, *this ),
696 mMappingConnector( Connector::MAPPING_CONNECTOR, *this ),
697 mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
698 mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
699 mRefreshOnceCounter( 0u ),
700 mScreenToFrameBufferFunction( Dali::RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION ),
701 mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
702 mInputEnabled( Dali::RenderTask::DEFAULT_INPUT_ENABLED ),
703 mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
704 mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE ),
705 mIsSystemLevel( isSystemLevel )
707 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::RenderTask(this:%p)\n", this);
710 RenderTask::~RenderTask()
712 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::~RenderTask(this:%p)\n", this);
715 // Helper class for connecting Nodes to the scene-graph RenderTask
717 RenderTask::Connector::Connector( Type type, RenderTask& renderTask )
719 mRenderTask( renderTask ),
724 RenderTask::Connector::~Connector()
729 void RenderTask::Connector::SetActor( Actor* actor )
731 if ( mActor != actor )
735 mActor->RemoveObserver( *this );
742 mActor->AddObserver( *this );
749 void RenderTask::Connector::SceneObjectAdded( Object& object )
754 void RenderTask::Connector::SceneObjectRemoved( Object& object )
759 void RenderTask::Connector::ObjectDestroyed( Object& object )
766 void RenderTask::Connector::UpdateRenderTask()
768 // Guard to allow handle destruction after Core has been destroyed
769 if( Internal::Stage::IsInstalled() &&
770 mRenderTask.mSceneObject )
772 const SceneGraph::Node* node( NULL );
774 // Check whether a Node exists in the scene-graph
775 if ( NULL != mActor )
777 const SceneGraph::PropertyOwner* object = mActor->GetSceneObject();
778 if ( NULL != object )
780 // actors only point to nodes as their scene objects
781 node = static_cast< const SceneGraph::Node* >( object );
785 //the mapping node is not used in the scene graph
786 if ( SOURCE_CONNECTOR == mType )
788 SetSourceNodeMessage( mRenderTask.GetEventThreadServices(), *(mRenderTask.mSceneObject), node );
790 else if( CAMERA_CONNECTOR == mType )
792 SetCameraNodeMessage( mRenderTask.GetEventThreadServices(), *(mRenderTask.mSceneObject), node );
797 } // namespace Internal