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/internal/common/event-to-update.h>
24 #include <dali/internal/event/actors/actor-impl.h>
25 #include <dali/internal/event/actors/camera-actor-impl.h>
26 #include <dali/internal/event/common/stage-impl.h>
27 #include <dali/internal/event/common/thread-local-storage.h>
28 #include <dali/internal/event/images/frame-buffer-image-impl.h>
29 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
30 #include <dali/internal/update/nodes/node.h>
32 #if defined(DEBUG_ENABLED)
35 Debug::Filter* gLogRender = Debug::Filter::New(Debug::Concise, false, "LOG_RENDER_TASK");
42 const Property::Index RenderTask::VIEWPORT_POSITION = 0;
43 const Property::Index RenderTask::VIEWPORT_SIZE = 1;
44 const Property::Index RenderTask::CLEAR_COLOR = 2;
49 namespace // For internal properties
52 const char* DEFAULT_PROPERTY_NAMES[] =
58 const int DEFAULT_PROPERTY_COUNT = sizeof( DEFAULT_PROPERTY_NAMES ) / sizeof( DEFAULT_PROPERTY_NAMES[0]);
60 const Property::Type DEFAULT_PROPERTY_TYPES[DEFAULT_PROPERTY_COUNT] =
62 Property::VECTOR2, // viewport-position
63 Property::VECTOR2, // viewport-size
64 Property::VECTOR4, // clear-color
69 RenderTask* RenderTask::New( bool isSystemLevel )
71 RenderTask* task( new RenderTask( ThreadLocalStorage::Get().GetEventToUpdate(), isSystemLevel ) );
76 void RenderTask::SetSourceActor( Actor* actor )
78 mSourceConnector.SetActor( actor );
81 Actor* RenderTask::GetSourceActor() const
83 return mSourceConnector.mActor;
86 void RenderTask::SetExclusive( bool exclusive )
88 if ( mExclusive != exclusive )
90 mExclusive = exclusive;
94 // mSceneObject is being used in a separate thread; queue a message to set the value
95 SetExclusiveMessage( mEventToUpdate, *mSceneObject, mExclusive );
100 bool RenderTask::IsExclusive() const
105 void RenderTask::SetInputEnabled( bool enabled )
107 mInputEnabled = enabled;
110 bool RenderTask::GetInputEnabled() const
112 return mInputEnabled;
115 void RenderTask::SetCameraActor( CameraActor* cameraActor )
117 mCameraConnector.SetActor( cameraActor );
120 CameraActor* RenderTask::GetCameraActor() const
122 // camera connector can only point to camera actor
123 return static_cast< CameraActor* >( mCameraConnector.mActor );
126 void RenderTask::SetTargetFrameBuffer( Dali::FrameBufferImage image )
128 if ( mFrameBufferImage != image )
130 // if we have a scene object we need to track connection status and set frame buffer id as well as updating target frame buffer
133 if(mFrameBufferImage)
135 GetImplementation(mFrameBufferImage).Disconnect();
138 // update target frame buffer
139 mFrameBufferImage = image;
141 unsigned int resourceId = 0;
142 if(mFrameBufferImage)
144 GetImplementation(mFrameBufferImage).Connect();
146 resourceId = GetImplementation( mFrameBufferImage ).GetResourceId();
149 // mSceneObject is being used in a separate thread; queue a message to set the value
150 SetFrameBufferIdMessage( mEventToUpdate, *mSceneObject, resourceId );
154 // update target frame buffer
155 mFrameBufferImage = image;
160 Dali::FrameBufferImage RenderTask::GetTargetFrameBuffer() const
162 return mFrameBufferImage;
165 void RenderTask::SetScreenToFrameBufferFunction( ScreenToFrameBufferFunction conversionFunction )
167 mScreenToFrameBufferFunction = conversionFunction;
170 RenderTask::ScreenToFrameBufferFunction RenderTask::GetScreenToFrameBufferFunction() const
172 return mScreenToFrameBufferFunction;
175 void RenderTask::SetScreenToFrameBufferMappingActor( Actor* mappingActor )
177 mMappingConnector.SetActor( mappingActor );
180 Actor* RenderTask::GetScreenToFrameBufferMappingActor() const
182 return mMappingConnector.mActor;
185 void RenderTask::SetViewportPosition(const Vector2& value)
187 StagePtr stage = Stage::GetCurrent();
188 BakeViewportPositionMessage( stage->GetUpdateInterface(), *mSceneObject, value );
191 Vector2 RenderTask::GetCurrentViewportPosition() const
193 StagePtr stage = Stage::GetCurrent();
194 return mSceneObject->GetViewportPosition(stage->GetEventBufferIndex());
197 void RenderTask::SetViewportSize(const Vector2& value)
199 StagePtr stage = Stage::GetCurrent();
200 BakeViewportSizeMessage( stage->GetUpdateInterface(), *mSceneObject, value );
203 Vector2 RenderTask::GetCurrentViewportSize() const
205 StagePtr stage = Stage::GetCurrent();
206 return mSceneObject->GetViewportSize(stage->GetEventBufferIndex());
209 void RenderTask::SetViewport( const Viewport& viewport )
211 SetViewportPosition(Vector2(viewport.x, viewport.y));
212 SetViewportSize(Vector2(viewport.width, viewport.height));
215 void RenderTask::GetViewport( Viewport& viewPort ) const
217 BufferIndex bufferIndex = Stage::GetCurrent()->GetEventBufferIndex();
219 if(!mSceneObject->GetViewportEnabled( bufferIndex ))
221 if ( mFrameBufferImage )
223 viewPort.x = viewPort.y = 0;
224 viewPort.width = mFrameBufferImage.GetWidth();
225 viewPort.height = mFrameBufferImage.GetHeight();
229 Vector2 size( Stage::GetCurrent()->GetSize() );
230 viewPort.x = viewPort.y = 0;
231 viewPort.width = size.width;
232 viewPort.height = size.height;
237 const Vector2& position = mSceneObject->GetViewportPosition(bufferIndex);
238 const Vector2& size = mSceneObject->GetViewportSize(bufferIndex);
239 viewPort.x = position.x;
240 viewPort.y = position.y;
241 viewPort.width = size.width;
242 viewPort.height = size.height;
246 void RenderTask::SetClearColor( const Vector4& color )
248 if ( mClearColor != color )
254 // mSceneObject is being used in a separate thread; queue a message to set the value
255 StagePtr stage = Stage::GetCurrent();
256 BakeClearColorMessage( stage->GetUpdateInterface(), *mSceneObject, color );
261 const Vector4& RenderTask::GetClearColor() const
263 StagePtr stage = Stage::GetCurrent();
264 return mSceneObject->GetClearColor(stage->GetEventBufferIndex());
267 void RenderTask::SetClearEnabled( bool enabled )
269 if ( mClearEnabled != enabled )
271 mClearEnabled = enabled;
275 // mSceneObject is being used in a separate thread; queue a message to set the value
276 SetClearEnabledMessage( mEventToUpdate, *mSceneObject, mClearEnabled );
281 bool RenderTask::GetClearEnabled() const
283 return mClearEnabled;
286 void RenderTask::SetCullMode( bool mode )
288 if ( mCullMode != mode )
294 // mSceneObject is being used in a separate thread; queue a message to set the value
295 SetCullModeMessage( mEventToUpdate, *mSceneObject, mCullMode );
300 bool RenderTask::GetCullMode() const
305 void RenderTask::SetRefreshRate( unsigned int refreshRate )
307 DALI_LOG_TRACE_METHOD_FMT(gLogRender, "this:%p rate:%d\n", this, refreshRate);
308 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::SetRefreshRate(this:%p, %d)\n", this, refreshRate);
310 mRefreshRate = refreshRate; // cached for GetRefreshRate()
312 // Note - even when refreshRate is the same as mRefreshRate, a message should be sent
316 // mSceneObject is being used in a separate thread; queue a message to set the value
317 SetRefreshRateMessage( mEventToUpdate, *mSceneObject, refreshRate );
321 unsigned int RenderTask::GetRefreshRate() const
326 bool RenderTask::IsHittable( Vector2& screenCoords ) const
328 // True when input is enabled, source & camera actor are valid
329 bool inputEnabled( false );
331 Actor* sourceActor = GetSourceActor();
332 CameraActor* cameraActor = GetCameraActor();
334 if ( mInputEnabled &&
335 NULL != sourceActor &&
336 sourceActor->OnStage() &&
337 NULL != cameraActor &&
338 cameraActor->OnStage() )
340 // If the actors are rendered off-screen, then the screen coordinates must be converted
341 // and the conversion function will tell us if they are inside or outside
342 if ( TranslateCoordinates( screenCoords ) )
344 // This is a suitable render-task for input handling
352 bool RenderTask::TranslateCoordinates( Vector2& screenCoords ) const
354 // return true for on-screen tasks
356 // If the actors are rendered off-screen, then the screen coordinates must be converted
357 // the function should only be called for offscreen tasks
358 if( mFrameBufferImage && mMappingConnector.mActor )
360 CameraActor* localCamera = GetCameraActor();
361 StagePtr stage = Stage::GetCurrent();
362 CameraActor& defaultCamera = stage->GetDefaultCameraActor();
366 Vector2 size( stage->GetSize() );
367 viewport.x = viewport.y = 0;
368 viewport.width = size.width;
369 viewport.height = size.height;
371 float localX, localY;
372 inside = mMappingConnector.mActor->ScreenToLocal(defaultCamera.GetViewMatrix(), defaultCamera.GetProjectionMatrix(), viewport, localX, localY, screenCoords.x, screenCoords.y);
373 Vector3 actorSize = mMappingConnector.mActor->GetCurrentSize();
374 if( inside && localX >= 0.f && localX <= actorSize.x && localY >= 0.f && localY <= actorSize.y)
376 screenCoords.x = localX;
377 screenCoords.y = localY;
389 else if ( mFrameBufferImage && mScreenToFrameBufferFunction )
391 inside = mScreenToFrameBufferFunction( screenCoords );
396 bool RenderTask::IsSystemLevel() const
398 return mIsSystemLevel;
401 SceneGraph::RenderTask* RenderTask::CreateSceneObject()
403 // This should only be called once, with no existing scene-object
404 DALI_ASSERT_DEBUG( NULL == mSceneObject );
406 // Keep the raw-pointer until DiscardSceneObject is called
407 mSceneObject = SceneGraph::RenderTask::New();
409 // 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
410 unsigned int resourceId = 0;
411 if(mFrameBufferImage)
413 GetImplementation(mFrameBufferImage).Connect();
415 resourceId = GetImplementation( mFrameBufferImage ).GetResourceId();
418 // mSceneObject is being used in a separate thread; queue a message to set the value
419 SetFrameBufferIdMessage( mEventToUpdate, *mSceneObject, resourceId );
421 // Send messages to set other properties that may have changed since last time we were on stage
422 SetExclusiveMessage( mEventToUpdate, *mSceneObject, mExclusive );
423 SetClearColorMessage( mEventToUpdate, *mSceneObject, mClearColor );
424 SetClearEnabledMessage( mEventToUpdate, *mSceneObject, mClearEnabled );
425 SetCullModeMessage( mEventToUpdate, *mSceneObject, mCullMode );
426 SetRefreshRateMessage( mEventToUpdate, *mSceneObject, mRefreshRate );
428 // Caller takes ownership
432 SceneGraph::RenderTask* RenderTask::GetRenderTaskSceneObject()
437 void RenderTask::DiscardSceneObject()
439 // mSceneObject is not owned; throw away the raw-pointer
442 // if we have a frame buffer we need to track connection status
443 if(mFrameBufferImage)
445 GetImplementation(mFrameBufferImage).Disconnect();
449 /********************************************************************************
450 ********************************************************************************
451 ******************************** PROPERTY METHODS **************************
452 ********************************************************************************
453 ********************************************************************************/
455 unsigned int RenderTask::GetDefaultPropertyCount() const
457 return DEFAULT_PROPERTY_COUNT;
460 void RenderTask::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
462 indices.reserve( DEFAULT_PROPERTY_COUNT );
464 for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
466 indices.push_back( i );
470 const char* RenderTask::GetDefaultPropertyName( Property::Index index ) const
472 if( index < DEFAULT_PROPERTY_COUNT )
474 return DEFAULT_PROPERTY_NAMES[index];
482 Property::Index RenderTask::GetDefaultPropertyIndex(const std::string& name) const
484 Property::Index index = Property::INVALID_INDEX;
486 // Look for name in default properties
487 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
489 if( 0 == strcmp( name.c_str(), DEFAULT_PROPERTY_NAMES[ i ] ) ) // dont want to convert rhs to string
499 bool RenderTask::IsDefaultPropertyWritable(Property::Index index) const
501 return true; // all properties writable
504 bool RenderTask::IsDefaultPropertyAnimatable(Property::Index index) const
506 return true; // all properties animatable
509 bool RenderTask::IsDefaultPropertyAConstraintInput( Property::Index index ) const
511 return true; // all properties can be used as constraint input
514 Property::Type RenderTask::GetDefaultPropertyType(Property::Index index) const
516 if( index < DEFAULT_PROPERTY_COUNT )
518 return DEFAULT_PROPERTY_TYPES[index];
522 // index out of range...return Property::NONE
523 return Property::NONE;
527 void RenderTask::SetDefaultProperty( Property::Index index, const Property::Value& property )
531 case Dali::RenderTask::VIEWPORT_POSITION:
533 SetViewportPosition( property.Get<Vector2>() );
536 case Dali::RenderTask::VIEWPORT_SIZE:
538 SetViewportSize( property.Get<Vector2>() );
541 case Dali::RenderTask::CLEAR_COLOR:
543 SetClearColor( property.Get<Vector4>() );
554 Property::Value RenderTask::GetDefaultProperty(Property::Index index) const
556 Property::Value value;
561 case Dali::RenderTask::VIEWPORT_POSITION:
563 value = GetCurrentViewportPosition();
566 case Dali::RenderTask::VIEWPORT_SIZE:
568 value = GetCurrentViewportSize();
571 case Dali::RenderTask::CLEAR_COLOR:
573 value = GetClearColor();
579 DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
587 const SceneGraph::PropertyOwner* RenderTask::GetSceneObject() const
592 const SceneGraph::PropertyBase* RenderTask::GetSceneObjectAnimatableProperty( Property::Index index ) const
594 DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" );
596 const SceneGraph::PropertyBase* property( NULL );
598 // This method should only return a property which is part of the scene-graph
599 if( mSceneObject != NULL )
603 case Dali::RenderTask::VIEWPORT_POSITION:
604 property = &mSceneObject->mViewportPosition;
607 case Dali::RenderTask::VIEWPORT_SIZE:
608 property = &mSceneObject->mViewportSize;
611 case Dali::RenderTask::CLEAR_COLOR:
612 property = &mSceneObject->mClearColor;
623 const PropertyInputImpl* RenderTask::GetSceneObjectInputProperty( Property::Index index ) const
625 const PropertyInputImpl* property( NULL );
626 if( mSceneObject != NULL )
630 case Dali::RenderTask::VIEWPORT_POSITION:
631 property = &mSceneObject->mViewportPosition;
634 case Dali::RenderTask::VIEWPORT_SIZE:
635 property = &mSceneObject->mViewportSize;
638 case Dali::RenderTask::CLEAR_COLOR:
639 property = &mSceneObject->mViewportSize;
650 bool RenderTask::HasFinished()
652 bool finished = false;
653 const unsigned int counter = mSceneObject->GetRenderedOnceCounter();
655 if( mRefreshOnceCounter < counter )
658 mRefreshOnceCounter = counter;
661 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::HasFinished()=%s SCRT:%p SC\n", finished?"T":"F", mSceneObject);
666 void RenderTask::EmitSignalFinish()
668 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::EmitSignalFinish(this:%p)\n", this);
670 if( !mSignalFinished.Empty() )
672 Dali::RenderTask handle( this );
673 mSignalFinished.Emit(handle );
677 Dali::RenderTask::RenderTaskSignalType& RenderTask::FinishedSignal()
679 return mSignalFinished;
682 bool RenderTask::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
684 bool connected( true );
685 RenderTask* renderTask = dynamic_cast<RenderTask*>(object);
687 if ( Dali::RenderTask::SIGNAL_FINISHED == signalName )
689 renderTask->FinishedSignal().Connect( tracker, functor );
693 // signalName does not match any signal
700 RenderTask::RenderTask( EventToUpdate& eventToUpdate, bool isSystemLevel )
701 : mEventToUpdate( eventToUpdate ),
702 mSceneObject( NULL ),
703 mSourceConnector( Connector::SOURCE_CONNECTOR, *this ),
704 mCameraConnector( Connector::CAMERA_CONNECTOR, *this ),
705 mMappingConnector( Connector::MAPPING_CONNECTOR, *this ),
706 mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
707 mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
708 mRefreshOnceCounter( 0u ),
709 mScreenToFrameBufferFunction( Dali::RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION ),
710 mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
711 mInputEnabled( Dali::RenderTask::DEFAULT_INPUT_ENABLED ),
712 mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
713 mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE ),
714 mIsSystemLevel( isSystemLevel )
716 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::RenderTask(this:%p)\n", this);
719 RenderTask::~RenderTask()
721 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::~RenderTask(this:%p)\n", this);
724 // Helper class for connecting Nodes to the scene-graph RenderTask
726 RenderTask::Connector::Connector( Type type, RenderTask& renderTask )
728 mRenderTask( renderTask ),
733 RenderTask::Connector::~Connector()
738 void RenderTask::Connector::SetActor( Actor* actor )
740 if ( mActor != actor )
744 mActor->RemoveObserver( *this );
751 mActor->AddObserver( *this );
758 void RenderTask::Connector::SceneObjectAdded( ProxyObject& proxy )
763 void RenderTask::Connector::SceneObjectRemoved( ProxyObject& proxy )
768 void RenderTask::Connector::ProxyDestroyed( ProxyObject& proxy )
775 void RenderTask::Connector::UpdateRenderTask()
777 // Guard to allow handle destruction after Core has been destroyed
778 if( Internal::Stage::IsInstalled() &&
779 mRenderTask.mSceneObject )
781 const SceneGraph::Node* node( NULL );
783 // Check whether a Node exists in the scene-graph
784 if ( NULL != mActor )
786 const SceneGraph::PropertyOwner* object = mActor->GetSceneObject();
787 if ( NULL != object )
789 // actors only point to nodes as their scene objects
790 node = static_cast< const SceneGraph::Node* >( object );
794 //the mapping node is not used in the scene graph
795 if ( SOURCE_CONNECTOR == mType )
797 SetSourceNodeMessage( mRenderTask.mEventToUpdate, *(mRenderTask.mSceneObject), node );
799 else if( CAMERA_CONNECTOR == mType )
801 SetCameraNodeMessage( mRenderTask.mEventToUpdate, *(mRenderTask.mSceneObject), node );
806 } // namespace Internal