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 std::string DEFAULT_PROPERTY_NAMES[] =
58 const int DEFAULT_PROPERTY_COUNT = sizeof( DEFAULT_PROPERTY_NAMES ) / sizeof( std::string );
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::DefaultPropertyLookup* RenderTask::sDefaultPropertyLookup = NULL;
71 RenderTask* RenderTask::New( bool isSystemLevel )
73 RenderTask* task( new RenderTask( ThreadLocalStorage::Get().GetEventToUpdate(), 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( mEventToUpdate, *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( mEventToUpdate, *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 StagePtr stage = Stage::GetCurrent();
190 BakeViewportPositionMessage( stage->GetUpdateInterface(), *mSceneObject, value );
193 Vector2 RenderTask::GetCurrentViewportPosition() const
195 StagePtr stage = Stage::GetCurrent();
196 return mSceneObject->GetViewportPosition(stage->GetEventBufferIndex());
199 void RenderTask::SetViewportSize(const Vector2& value)
201 StagePtr stage = Stage::GetCurrent();
202 BakeViewportSizeMessage( stage->GetUpdateInterface(), *mSceneObject, value );
205 Vector2 RenderTask::GetCurrentViewportSize() const
207 StagePtr stage = Stage::GetCurrent();
208 return mSceneObject->GetViewportSize(stage->GetEventBufferIndex());
211 void RenderTask::SetViewport( const Viewport& viewport )
213 SetViewportPosition(Vector2(viewport.x, viewport.y));
214 SetViewportSize(Vector2(viewport.width, viewport.height));
217 void RenderTask::GetViewport( Viewport& viewPort ) const
219 BufferIndex bufferIndex = Stage::GetCurrent()->GetEventBufferIndex();
221 if(!mSceneObject->GetViewportEnabled( bufferIndex ))
223 if ( mFrameBufferImage )
225 viewPort.x = viewPort.y = 0;
226 viewPort.width = mFrameBufferImage.GetWidth();
227 viewPort.height = mFrameBufferImage.GetHeight();
231 Vector2 size( Stage::GetCurrent()->GetSize() );
232 viewPort.x = viewPort.y = 0;
233 viewPort.width = size.width;
234 viewPort.height = size.height;
239 const Vector2& position = mSceneObject->GetViewportPosition(bufferIndex);
240 const Vector2& size = mSceneObject->GetViewportSize(bufferIndex);
241 viewPort.x = position.x;
242 viewPort.y = position.y;
243 viewPort.width = size.width;
244 viewPort.height = size.height;
248 void RenderTask::SetClearColor( const Vector4& color )
250 if ( mClearColor != color )
256 // mSceneObject is being used in a separate thread; queue a message to set the value
257 StagePtr stage = Stage::GetCurrent();
258 BakeClearColorMessage( stage->GetUpdateInterface(), *mSceneObject, color );
263 const Vector4& RenderTask::GetClearColor() const
265 StagePtr stage = Stage::GetCurrent();
266 return mSceneObject->GetClearColor(stage->GetEventBufferIndex());
269 void RenderTask::SetClearEnabled( bool enabled )
271 if ( mClearEnabled != enabled )
273 mClearEnabled = enabled;
277 // mSceneObject is being used in a separate thread; queue a message to set the value
278 SetClearEnabledMessage( mEventToUpdate, *mSceneObject, mClearEnabled );
283 bool RenderTask::GetClearEnabled() const
285 return mClearEnabled;
288 void RenderTask::SetCullMode( bool mode )
290 if ( mCullMode != mode )
296 // mSceneObject is being used in a separate thread; queue a message to set the value
297 SetCullModeMessage( mEventToUpdate, *mSceneObject, mCullMode );
302 bool RenderTask::GetCullMode() const
307 void RenderTask::SetRefreshRate( unsigned int refreshRate )
309 DALI_LOG_TRACE_METHOD_FMT(gLogRender, "this:%p rate:%d\n", this, refreshRate);
310 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::SetRefreshRate(this:%p, %d)\n", this, refreshRate);
312 mRefreshRate = refreshRate; // cached for GetRefreshRate()
314 // Note - even when refreshRate is the same as mRefreshRate, a message should be sent
318 // mSceneObject is being used in a separate thread; queue a message to set the value
319 SetRefreshRateMessage( mEventToUpdate, *mSceneObject, refreshRate );
323 unsigned int RenderTask::GetRefreshRate() const
328 bool RenderTask::IsHittable( Vector2& screenCoords ) const
330 // True when input is enabled, source & camera actor are valid
331 bool inputEnabled( false );
333 Actor* sourceActor = GetSourceActor();
334 CameraActor* cameraActor = GetCameraActor();
336 if ( mInputEnabled &&
337 NULL != sourceActor &&
338 sourceActor->OnStage() &&
339 NULL != cameraActor &&
340 cameraActor->OnStage() )
342 // If the actors are rendered off-screen, then the screen coordinates must be converted
343 // and the conversion function will tell us if they are inside or outside
344 if ( TranslateCoordinates( screenCoords ) )
346 // This is a suitable render-task for input handling
354 bool RenderTask::TranslateCoordinates( Vector2& screenCoords ) const
356 // return true for on-screen tasks
358 // If the actors are rendered off-screen, then the screen coordinates must be converted
359 // the function should only be called for offscreen tasks
360 if( mFrameBufferImage && mMappingConnector.mActor )
362 CameraActor* localCamera = GetCameraActor();
363 StagePtr stage = Stage::GetCurrent();
364 CameraActor& defaultCamera = stage->GetDefaultCameraActor();
368 Vector2 size( stage->GetSize() );
369 viewport.x = viewport.y = 0;
370 viewport.width = size.width;
371 viewport.height = size.height;
373 float localX, localY;
374 inside = mMappingConnector.mActor->ScreenToLocal(defaultCamera.GetViewMatrix(), defaultCamera.GetProjectionMatrix(), viewport, localX, localY, screenCoords.x, screenCoords.y);
375 Vector3 actorSize = mMappingConnector.mActor->GetCurrentSize();
376 if( inside && localX >= 0.f && localX <= actorSize.x && localY >= 0.f && localY <= actorSize.y)
378 screenCoords.x = localX;
379 screenCoords.y = localY;
391 else if ( mFrameBufferImage && mScreenToFrameBufferFunction )
393 inside = mScreenToFrameBufferFunction( screenCoords );
398 bool RenderTask::IsSystemLevel() const
400 return mIsSystemLevel;
403 SceneGraph::RenderTask* RenderTask::CreateSceneObject()
405 // This should only be called once, with no existing scene-object
406 DALI_ASSERT_DEBUG( NULL == mSceneObject );
408 // Keep the raw-pointer until DiscardSceneObject is called
409 mSceneObject = SceneGraph::RenderTask::New();
411 // 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
412 unsigned int resourceId = 0;
413 if(mFrameBufferImage)
415 GetImplementation(mFrameBufferImage).Connect();
417 resourceId = GetImplementation( mFrameBufferImage ).GetResourceId();
420 // mSceneObject is being used in a separate thread; queue a message to set the value
421 SetFrameBufferIdMessage( mEventToUpdate, *mSceneObject, resourceId );
423 // Send messages to set other properties that may have changed since last time we were on stage
424 SetExclusiveMessage( mEventToUpdate, *mSceneObject, mExclusive );
425 SetClearColorMessage( mEventToUpdate, *mSceneObject, mClearColor );
426 SetClearEnabledMessage( mEventToUpdate, *mSceneObject, mClearEnabled );
427 SetCullModeMessage( mEventToUpdate, *mSceneObject, mCullMode );
428 SetRefreshRateMessage( mEventToUpdate, *mSceneObject, mRefreshRate );
430 // Caller takes ownership
434 SceneGraph::RenderTask* RenderTask::GetRenderTaskSceneObject()
439 void RenderTask::DiscardSceneObject()
441 // mSceneObject is not owned; throw away the raw-pointer
444 // if we have a frame buffer we need to track connection status
445 if(mFrameBufferImage)
447 GetImplementation(mFrameBufferImage).Disconnect();
451 /********************************************************************************
452 ********************************************************************************
453 ******************************** PROPERTY METHODS **************************
454 ********************************************************************************
455 ********************************************************************************/
457 bool RenderTask::IsSceneObjectRemovable() const
459 return false; // The scene object is permanently "on stage" whilst this object is alive
462 unsigned int RenderTask::GetDefaultPropertyCount() const
464 return DEFAULT_PROPERTY_COUNT;
467 void RenderTask::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
469 indices.reserve( DEFAULT_PROPERTY_COUNT );
471 for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
473 indices.push_back( i );
477 const std::string& RenderTask::GetDefaultPropertyName( Property::Index index ) const
479 if( index < DEFAULT_PROPERTY_COUNT )
481 return DEFAULT_PROPERTY_NAMES[index];
485 // index out of range..return empty string
486 static const std::string INVALID_PROPERTY_NAME;
487 return INVALID_PROPERTY_NAME;
491 Property::Index RenderTask::GetDefaultPropertyIndex(const std::string& name) const
493 Property::Index index = Property::INVALID_INDEX;
495 // Lazy initialization of static sDefaultPropertyLookup
496 if (!sDefaultPropertyLookup)
498 sDefaultPropertyLookup = new DefaultPropertyLookup();
500 for (int i=0; i<DEFAULT_PROPERTY_COUNT; ++i)
502 (*sDefaultPropertyLookup)[DEFAULT_PROPERTY_NAMES[i]] = i;
505 DALI_ASSERT_DEBUG( NULL != sDefaultPropertyLookup );
507 // Look for name in default properties
508 DefaultPropertyLookup::const_iterator result = sDefaultPropertyLookup->find( name );
509 if ( sDefaultPropertyLookup->end() != result )
511 index = result->second;
517 bool RenderTask::IsDefaultPropertyWritable(Property::Index index) const
522 bool RenderTask::IsDefaultPropertyAnimatable(Property::Index index) const
527 bool RenderTask::IsDefaultPropertyAConstraintInput( Property::Index index ) const
532 Property::Type RenderTask::GetDefaultPropertyType(Property::Index index) const
534 if( index < DEFAULT_PROPERTY_COUNT )
536 return DEFAULT_PROPERTY_TYPES[index];
540 // index out of range...return Property::NONE
541 return Property::NONE;
545 void RenderTask::SetDefaultProperty( Property::Index index, const Property::Value& property )
549 case Dali::RenderTask::VIEWPORT_POSITION:
551 SetViewportPosition( property.Get<Vector2>() );
554 case Dali::RenderTask::VIEWPORT_SIZE:
556 SetViewportSize( property.Get<Vector2>() );
559 case Dali::RenderTask::CLEAR_COLOR:
561 SetClearColor( property.Get<Vector4>() );
567 DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
573 void RenderTask::SetCustomProperty( Property::Index /*index*/, const CustomProperty& /*entry*/, const Property::Value& /*value*/ )
575 // TODO: support them, it doesn't hurt.
576 DALI_ASSERT_ALWAYS( 0 && "RenderTask does not support custom properties");
579 Property::Value RenderTask::GetDefaultProperty(Property::Index index) const
581 Property::Value value;
586 case Dali::RenderTask::VIEWPORT_POSITION:
588 value = GetCurrentViewportPosition();
591 case Dali::RenderTask::VIEWPORT_SIZE:
593 value = GetCurrentViewportSize();
596 case Dali::RenderTask::CLEAR_COLOR:
598 value = GetClearColor();
604 DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
612 void RenderTask::InstallSceneObjectProperty( SceneGraph::PropertyBase& newProperty, const std::string& name, unsigned int index )
614 // TODO: support them, it doesn't hurt.
615 DALI_ASSERT_ALWAYS( 0 && "RenderTask does not support custom properties" );
618 const SceneGraph::PropertyOwner* RenderTask::GetSceneObject() const
623 const SceneGraph::PropertyBase* RenderTask::GetSceneObjectAnimatableProperty( Property::Index index ) const
625 DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" );
627 const SceneGraph::PropertyBase* property( NULL );
629 // This method should only return a property which is part of the scene-graph
630 if( mSceneObject != NULL )
634 case Dali::RenderTask::VIEWPORT_POSITION:
635 property = &mSceneObject->mViewportPosition;
638 case Dali::RenderTask::VIEWPORT_SIZE:
639 property = &mSceneObject->mViewportSize;
642 case Dali::RenderTask::CLEAR_COLOR:
643 property = &mSceneObject->mClearColor;
654 const PropertyInputImpl* RenderTask::GetSceneObjectInputProperty( Property::Index index ) const
656 const PropertyInputImpl* property( NULL );
657 if( mSceneObject != NULL )
661 case Dali::RenderTask::VIEWPORT_POSITION:
662 property = &mSceneObject->mViewportPosition;
665 case Dali::RenderTask::VIEWPORT_SIZE:
666 property = &mSceneObject->mViewportSize;
669 case Dali::RenderTask::CLEAR_COLOR:
670 property = &mSceneObject->mViewportSize;
681 bool RenderTask::HasFinished()
683 bool finished = false;
684 const unsigned int counter = mSceneObject->GetRenderedOnceCounter();
686 if( mRefreshOnceCounter < counter )
689 mRefreshOnceCounter = counter;
692 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::HasFinished()=%s SCRT:%p SC\n", finished?"T":"F", mSceneObject);
697 void RenderTask::EmitSignalFinish()
699 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::EmitSignalFinish(this:%p)\n", this);
701 if( !mSignalFinishedV2.Empty() )
703 Dali::RenderTask handle( this );
704 mSignalFinishedV2.Emit(handle );
708 Dali::RenderTask::RenderTaskSignalV2& RenderTask::FinishedSignal()
710 return mSignalFinishedV2;
713 bool RenderTask::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
715 bool connected( true );
716 RenderTask* renderTask = dynamic_cast<RenderTask*>(object);
718 if ( Dali::RenderTask::SIGNAL_FINISHED == signalName )
720 renderTask->FinishedSignal().Connect( tracker, functor );
724 // signalName does not match any signal
731 RenderTask::RenderTask( EventToUpdate& eventToUpdate, bool isSystemLevel )
732 : mEventToUpdate( eventToUpdate ),
733 mSceneObject( NULL ),
734 mSourceConnector( Connector::SOURCE_CONNECTOR, *this ),
735 mCameraConnector( Connector::CAMERA_CONNECTOR, *this ),
736 mMappingConnector( Connector::MAPPING_CONNECTOR, *this ),
737 mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
738 mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
739 mRefreshOnceCounter( 0u ),
740 mScreenToFrameBufferFunction( Dali::RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION ),
741 mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
742 mInputEnabled( Dali::RenderTask::DEFAULT_INPUT_ENABLED ),
743 mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
744 mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE ),
745 mIsSystemLevel( isSystemLevel )
747 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::RenderTask(this:%p)\n", this);
750 RenderTask::~RenderTask()
752 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::~RenderTask(this:%p)\n", this);
755 // Helper class for connecting Nodes to the scene-graph RenderTask
757 RenderTask::Connector::Connector( Type type, RenderTask& renderTask )
759 mRenderTask( renderTask ),
764 RenderTask::Connector::~Connector()
769 void RenderTask::Connector::SetActor( Actor* actor )
771 if ( mActor != actor )
775 mActor->RemoveObserver( *this );
782 mActor->AddObserver( *this );
789 void RenderTask::Connector::SceneObjectAdded( ProxyObject& proxy )
794 void RenderTask::Connector::SceneObjectRemoved( ProxyObject& proxy )
799 void RenderTask::Connector::ProxyDestroyed( ProxyObject& proxy )
806 void RenderTask::Connector::UpdateRenderTask()
808 // Guard to allow handle destruction after Core has been destroyed
809 if( Internal::Stage::IsInstalled() &&
810 mRenderTask.mSceneObject )
812 const SceneGraph::Node* node( NULL );
814 // Check whether a Node exists in the scene-graph
815 if ( NULL != mActor )
817 const SceneGraph::PropertyOwner* object = mActor->GetSceneObject();
818 if ( NULL != object )
820 // actors only point to nodes as their scene objects
821 node = static_cast< const SceneGraph::Node* >( object );
825 //the mapping node is not used in the scene graph
826 if ( SOURCE_CONNECTOR == mType )
828 SetSourceNodeMessage( mRenderTask.mEventToUpdate, *(mRenderTask.mSceneObject), node );
830 else if( CAMERA_CONNECTOR == mType )
832 SetCameraNodeMessage( mRenderTask.mEventToUpdate, *(mRenderTask.mSceneObject), node );
837 } // namespace Internal