2 * Copyright (c) 2017 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/common/projection.h>
33 #include <dali/internal/event/images/frame-buffer-image-impl.h>
34 #include <dali/internal/update/nodes/node.h>
35 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
36 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
38 #if defined(DEBUG_ENABLED)
41 Debug::Filter* gLogRender = Debug::Filter::New(Debug::Concise, false, "LOG_RENDER_TASK");
51 namespace // For internal properties
56 // Name Type writable animatable constraint-input enum for index-checking
57 DALI_PROPERTY_TABLE_BEGIN
58 DALI_PROPERTY( "viewportPosition", VECTOR2, true, true, true, Dali::RenderTask::Property::VIEWPORT_POSITION )
59 DALI_PROPERTY( "viewportSize", VECTOR2, true, true, true, Dali::RenderTask::Property::VIEWPORT_SIZE )
60 DALI_PROPERTY( "clearColor", VECTOR4, true, true, true, Dali::RenderTask::Property::CLEAR_COLOR )
61 DALI_PROPERTY( "requiresSync", BOOLEAN, true, false, false, Dali::RenderTask::Property::REQUIRES_SYNC )
62 DALI_PROPERTY_TABLE_END( DEFAULT_OBJECT_PROPERTY_START_INDEX )
66 const char* const SIGNAL_FINISHED = "finished";
68 TypeRegistration mType( typeid( Dali::RenderTask ), typeid( Dali::BaseHandle ), NULL );
70 SignalConnectorType signalConnector1( mType, SIGNAL_FINISHED, &RenderTask::DoConnectSignal );
72 } // Unnamed namespace
74 RenderTask* RenderTask::New( bool isSystemLevel )
76 RenderTask* task( new RenderTask( isSystemLevel ) );
81 void RenderTask::SetSourceActor( Actor* actor )
83 const Stage* stage = Stage::GetCurrent();
86 stage->GetRenderTaskList().SetExclusive( this, mExclusive );
88 mSourceConnector.SetActor( actor );
91 Actor* RenderTask::GetSourceActor() const
93 return mSourceConnector.mActor;
96 void RenderTask::SetExclusive( bool exclusive )
98 if ( mExclusive != exclusive )
100 mExclusive = exclusive;
102 const Stage* stage = Stage::GetCurrent();
105 stage->GetRenderTaskList().SetExclusive( this, exclusive );
110 // mSceneObject is being used in a separate thread; queue a message to set the value
111 SetExclusiveMessage( GetEventThreadServices(), *mSceneObject, mExclusive );
116 bool RenderTask::IsExclusive() const
121 void RenderTask::SetInputEnabled( bool enabled )
123 mInputEnabled = enabled;
126 bool RenderTask::GetInputEnabled() const
128 return mInputEnabled;
131 void RenderTask::SetCameraActor( CameraActor* cameraActor )
135 mCameraConnector.mCamera = cameraActor->GetCamera();
139 mCameraConnector.mCamera = NULL;
141 mCameraConnector.SetActor( cameraActor );
144 CameraActor* RenderTask::GetCameraActor() const
146 // camera connector can only point to camera actor
147 return static_cast< CameraActor* >( mCameraConnector.mActor );
150 void RenderTask::SetTargetFrameBuffer( FrameBufferImagePtr image )
152 mFrameBufferImage = image;
153 FrameBuffer* frameBufferPtr( NULL );
156 frameBufferPtr = image->GetFrameBuffer();
159 SetFrameBuffer( frameBufferPtr );
162 void RenderTask::SetFrameBuffer( FrameBufferPtr frameBuffer )
164 mFrameBuffer = frameBuffer;
165 Render::FrameBuffer* renderFrameBufferPtr( NULL );
168 renderFrameBufferPtr = mFrameBuffer->GetRenderObject();
171 SetFrameBufferMessage( GetEventThreadServices(), *mSceneObject, renderFrameBufferPtr );
174 FrameBuffer* RenderTask::GetFrameBuffer() const
176 return mFrameBuffer.Get();
179 FrameBufferImage* RenderTask::GetTargetFrameBuffer() const
181 return mFrameBufferImage.Get();
184 void RenderTask::SetScreenToFrameBufferFunction( ScreenToFrameBufferFunction conversionFunction )
186 mScreenToFrameBufferFunction = conversionFunction;
189 RenderTask::ScreenToFrameBufferFunction RenderTask::GetScreenToFrameBufferFunction() const
191 return mScreenToFrameBufferFunction;
194 void RenderTask::SetScreenToFrameBufferMappingActor( Actor* mappingActor )
196 mMappingConnector.SetActor( mappingActor );
199 Actor* RenderTask::GetScreenToFrameBufferMappingActor() const
201 return mMappingConnector.mActor;
204 void RenderTask::SetViewportPosition(const Vector2& value)
206 mViewportPosition = value;
208 BakeViewportPositionMessage( GetEventThreadServices(), *mSceneObject, value );
211 Vector2 RenderTask::GetCurrentViewportPosition() const
213 return mSceneObject->GetViewportPosition( GetEventThreadServices().GetEventBufferIndex() );
216 void RenderTask::SetViewportSize(const Vector2& value)
218 mViewportSize = value;
220 BakeViewportSizeMessage( GetEventThreadServices(), *mSceneObject, value );
223 Vector2 RenderTask::GetCurrentViewportSize() const
225 return mSceneObject->GetViewportSize( GetEventThreadServices().GetEventBufferIndex() );
228 void RenderTask::SetViewport( const Viewport& viewport )
230 SetViewportPosition(Vector2(viewport.x, viewport.y));
231 SetViewportSize(Vector2(viewport.width, viewport.height));
234 void RenderTask::GetViewport( Viewport& viewPort ) const
236 BufferIndex bufferIndex = GetEventThreadServices().GetEventBufferIndex();
238 if(!mSceneObject->GetViewportEnabled( bufferIndex ))
240 if ( mFrameBufferImage )
242 viewPort.x = viewPort.y = 0;
243 viewPort.width = mFrameBufferImage->GetWidth();
244 viewPort.height = mFrameBufferImage->GetHeight();
248 Internal::Stage* stage = Internal::Stage::GetCurrent();
251 Vector2 size( stage->GetSize() );
252 viewPort.x = viewPort.y = 0;
253 viewPort.width = size.width;
254 viewPort.height = size.height;
260 const Vector2& position = mSceneObject->GetViewportPosition(bufferIndex);
261 const Vector2& size = mSceneObject->GetViewportSize(bufferIndex);
262 viewPort.x = position.x;
263 viewPort.y = position.y;
264 viewPort.width = size.width;
265 viewPort.height = size.height;
269 void RenderTask::SetClearColor( const Vector4& color )
271 if ( mClearColor != color )
277 // mSceneObject is being used in a separate thread; queue a message to set the value
278 BakeClearColorMessage( GetEventThreadServices(), *mSceneObject, color );
283 const Vector4& RenderTask::GetClearColor() const
285 return mSceneObject->GetClearColor( GetEventThreadServices().GetEventBufferIndex() );
288 void RenderTask::SetSyncRequired( bool requiresSync )
290 if( mRequiresSync != requiresSync )
292 mRequiresSync = requiresSync;
296 // mSceneObject is being used in a separate thread; queue a message to set the value
297 SetSyncRequiredMessage( GetEventThreadServices(), *mSceneObject, requiresSync );
302 bool RenderTask::IsSyncRequired() const
304 return mRequiresSync;
307 void RenderTask::SetClearEnabled( bool enabled )
309 if ( mClearEnabled != enabled )
311 mClearEnabled = enabled;
315 // mSceneObject is being used in a separate thread; queue a message to set the value
316 SetClearEnabledMessage( GetEventThreadServices(), *mSceneObject, mClearEnabled );
321 bool RenderTask::GetClearEnabled() const
323 return mClearEnabled;
326 void RenderTask::SetCullMode( bool mode )
328 if ( mCullMode != mode )
334 // mSceneObject is being used in a separate thread; queue a message to set the value
335 SetCullModeMessage( GetEventThreadServices(), *mSceneObject, mCullMode );
340 bool RenderTask::GetCullMode() const
345 void RenderTask::SetRefreshRate( unsigned int refreshRate )
347 DALI_LOG_TRACE_METHOD_FMT(gLogRender, "this:%p rate:%d\n", this, refreshRate);
348 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::SetRefreshRate(this:%p, %d)\n", this, refreshRate);
350 mRefreshRate = refreshRate; // cached for GetRefreshRate()
352 // Note - even when refreshRate is the same as mRefreshRate, a message should be sent
356 // mSceneObject is being used in a separate thread; queue a message to set the value
357 SetRefreshRateMessage( GetEventThreadServices(), *mSceneObject, refreshRate );
361 unsigned int RenderTask::GetRefreshRate() const
366 bool RenderTask::IsHittable( Vector2& screenCoords ) const
368 // True when input is enabled, source & camera actor are valid
369 bool inputEnabled( false );
371 Actor* sourceActor = GetSourceActor();
372 CameraActor* cameraActor = GetCameraActor();
374 if ( mInputEnabled &&
375 NULL != sourceActor &&
376 sourceActor->OnStage() &&
377 NULL != cameraActor &&
378 cameraActor->OnStage() )
380 // If the actors are rendered off-screen, then the screen coordinates must be converted
381 // and the conversion function will tell us if they are inside or outside
382 if ( TranslateCoordinates( screenCoords ) )
384 // This is a suitable render-task for input handling
392 bool RenderTask::TranslateCoordinates( Vector2& screenCoords ) const
394 // return true for on-screen tasks
396 // If the actors are rendered off-screen, then the screen coordinates must be converted
397 // the function should only be called for offscreen tasks
398 if( mFrameBufferImage && mMappingConnector.mActor )
400 CameraActor* localCamera = GetCameraActor();
401 StagePtr stage = Stage::GetCurrent();
404 CameraActor& defaultCamera = stage->GetDefaultCameraActor();
408 Vector2 size( stage->GetSize() );
409 viewport.x = viewport.y = 0;
410 viewport.width = size.width;
411 viewport.height = size.height;
413 float localX, localY;
414 inside = mMappingConnector.mActor->ScreenToLocal(defaultCamera.GetViewMatrix(), defaultCamera.GetProjectionMatrix(), viewport, localX, localY, screenCoords.x, screenCoords.y);
415 Vector3 actorSize = mMappingConnector.mActor->GetCurrentSize();
416 if( inside && localX >= 0.f && localX <= actorSize.x && localY >= 0.f && localY <= actorSize.y)
418 screenCoords.x = localX;
419 screenCoords.y = localY;
432 else if ( mFrameBufferImage && mScreenToFrameBufferFunction )
434 inside = mScreenToFrameBufferFunction( screenCoords );
439 bool RenderTask::IsSystemLevel() const
441 return mIsSystemLevel;
444 bool RenderTask::WorldToViewport(const Vector3 &position, float& viewportX, float& viewportY) const
446 CameraActor* cam = GetCameraActor();
448 Vector4 pos(position);
451 Vector4 viewportPosition;
454 GetViewport( viewport );
456 bool ok = ProjectFull(pos,
457 cam->GetViewMatrix(),
458 cam->GetProjectionMatrix(),
466 viewportX = viewportPosition.x;
467 viewportY = viewportPosition.y;
473 bool RenderTask::ViewportToLocal(Actor* actor, float viewportX, float viewportY, float &localX, float &localY) const
475 return actor->ScreenToLocal( *this, localX, localY, viewportX, viewportY );
478 SceneGraph::RenderTask* RenderTask::CreateSceneObject()
480 // This should only be called once, with no existing scene-object
481 DALI_ASSERT_DEBUG( NULL == mSceneObject );
483 // Keep the raw-pointer until DiscardSceneObject is called
484 mSceneObject = SceneGraph::RenderTask::New();
486 // Send messages to set other properties that may have changed since last time we were on stage
487 SetExclusiveMessage( GetEventThreadServices(), *mSceneObject, mExclusive );
488 SetClearColorMessage( GetEventThreadServices(), *mSceneObject, mClearColor );
489 SetClearEnabledMessage( GetEventThreadServices(), *mSceneObject, mClearEnabled );
490 SetCullModeMessage( GetEventThreadServices(), *mSceneObject, mCullMode );
491 SetRefreshRateMessage( GetEventThreadServices(), *mSceneObject, mRefreshRate );
492 SetSyncRequiredMessage( GetEventThreadServices(), *mSceneObject, mRequiresSync );
493 SetFrameBuffer( mFrameBuffer );
495 // Caller takes ownership
499 SceneGraph::RenderTask* RenderTask::GetRenderTaskSceneObject()
504 void RenderTask::DiscardSceneObject()
506 // mSceneObject is not owned; throw away the raw-pointer
510 /********************************************************************************
511 ******************************** PROPERTY METHODS **************************
512 ********************************************************************************/
514 unsigned int RenderTask::GetDefaultPropertyCount() const
516 return DEFAULT_PROPERTY_COUNT;
519 void RenderTask::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
521 indices.Reserve( DEFAULT_PROPERTY_COUNT );
523 for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
525 indices.PushBack( i );
529 const char* RenderTask::GetDefaultPropertyName( Property::Index index ) const
531 if( index < DEFAULT_PROPERTY_COUNT )
533 return DEFAULT_PROPERTY_DETAILS[index].name;
541 Property::Index RenderTask::GetDefaultPropertyIndex(const std::string& name) const
543 Property::Index index = Property::INVALID_INDEX;
545 // Look for name in default properties
546 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
548 if( 0 == strcmp( name.c_str(), DEFAULT_PROPERTY_DETAILS[i].name ) ) // dont want to convert rhs to string
558 bool RenderTask::IsDefaultPropertyWritable(Property::Index index) const
560 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
563 bool RenderTask::IsDefaultPropertyAnimatable(Property::Index index) const
565 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
568 bool RenderTask::IsDefaultPropertyAConstraintInput( Property::Index index ) const
570 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
573 Property::Type RenderTask::GetDefaultPropertyType(Property::Index index) const
575 if( index < DEFAULT_PROPERTY_COUNT )
577 return DEFAULT_PROPERTY_DETAILS[index].type;
580 // index out of range...return Property::NONE
581 return Property::NONE;
584 void RenderTask::SetDefaultProperty( Property::Index index, const Property::Value& property )
588 case Dali::RenderTask::Property::VIEWPORT_POSITION:
590 SetViewportPosition( property.Get<Vector2>() );
593 case Dali::RenderTask::Property::VIEWPORT_SIZE:
595 SetViewportSize( property.Get<Vector2>() );
598 case Dali::RenderTask::Property::CLEAR_COLOR:
600 SetClearColor( property.Get<Vector4>() );
603 case Dali::RenderTask::Property::REQUIRES_SYNC:
605 SetSyncRequired( property.Get<bool>() );
616 Property::Value RenderTask::GetDefaultProperty(Property::Index index) const
618 Property::Value value;
623 case Dali::RenderTask::Property::VIEWPORT_POSITION:
625 value = mViewportPosition;
628 case Dali::RenderTask::Property::VIEWPORT_SIZE:
630 value = mViewportSize;
633 case Dali::RenderTask::Property::CLEAR_COLOR:
638 case Dali::RenderTask::Property::REQUIRES_SYNC:
640 value = IsSyncRequired();
646 DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
654 Property::Value RenderTask::GetDefaultPropertyCurrentValue( Property::Index index ) const
656 Property::Value value;
661 case Dali::RenderTask::Property::VIEWPORT_POSITION:
663 value = GetCurrentViewportPosition();
666 case Dali::RenderTask::Property::VIEWPORT_SIZE:
668 value = GetCurrentViewportSize();
671 case Dali::RenderTask::Property::CLEAR_COLOR:
673 value = GetClearColor();
676 case Dali::RenderTask::Property::REQUIRES_SYNC:
678 value = IsSyncRequired();
684 DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
692 void RenderTask::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value )
696 case Dali::RenderTask::Property::VIEWPORT_POSITION:
698 value.Get( mViewportPosition );
701 case Dali::RenderTask::Property::VIEWPORT_SIZE:
703 value.Get( mViewportSize );
706 case Dali::RenderTask::Property::CLEAR_COLOR:
708 value.Get( mClearColor );
711 case Dali::RenderTask::Property::REQUIRES_SYNC:
714 // Nothing to do as not animatable
720 const SceneGraph::PropertyOwner* RenderTask::GetSceneObject() const
725 const SceneGraph::PropertyBase* RenderTask::GetSceneObjectAnimatableProperty( Property::Index index ) const
727 DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" );
729 const SceneGraph::PropertyBase* property( NULL );
731 // This method should only return a property which is part of the scene-graph
732 if( mSceneObject != NULL )
736 case Dali::RenderTask::Property::VIEWPORT_POSITION:
737 property = &mSceneObject->mViewportPosition;
740 case Dali::RenderTask::Property::VIEWPORT_SIZE:
741 property = &mSceneObject->mViewportSize;
744 case Dali::RenderTask::Property::CLEAR_COLOR:
745 property = &mSceneObject->mClearColor;
756 const PropertyInputImpl* RenderTask::GetSceneObjectInputProperty( Property::Index index ) const
758 const PropertyInputImpl* property( NULL );
759 if( mSceneObject != NULL )
763 case Dali::RenderTask::Property::VIEWPORT_POSITION:
764 property = &mSceneObject->mViewportPosition;
767 case Dali::RenderTask::Property::VIEWPORT_SIZE:
768 property = &mSceneObject->mViewportSize;
771 case Dali::RenderTask::Property::CLEAR_COLOR:
772 property = &mSceneObject->mClearColor;
783 bool RenderTask::HasFinished()
785 bool finished = false;
786 const unsigned int counter = mSceneObject->GetRenderedOnceCounter();
788 if( mRefreshOnceCounter < counter )
791 mRefreshOnceCounter = counter;
794 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::HasFinished()=%s SCRT:%p SC\n", finished?"T":"F", mSceneObject);
799 void RenderTask::EmitSignalFinish()
801 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::EmitSignalFinish(this:%p)\n", this);
803 if( !mSignalFinished.Empty() )
805 Dali::RenderTask handle( this );
806 mSignalFinished.Emit(handle );
810 Dali::RenderTask::RenderTaskSignalType& RenderTask::FinishedSignal()
812 return mSignalFinished;
815 bool RenderTask::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
817 bool connected( true );
818 RenderTask* renderTask = static_cast< RenderTask* >(object); // TypeRegistry guarantees that this is the correct type.
820 if ( 0 == strcmp( signalName.c_str(), SIGNAL_FINISHED ) )
822 renderTask->FinishedSignal().Connect( tracker, functor );
826 // signalName does not match any signal
833 RenderTask::RenderTask( bool isSystemLevel )
834 : mSceneObject( NULL ),
835 mSourceConnector( Connector::SOURCE_CONNECTOR, *this ),
836 mCameraConnector( Connector::CAMERA_CONNECTOR, *this ),
837 mMappingConnector( Connector::MAPPING_CONNECTOR, *this ),
838 mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
839 mViewportPosition( Vector2::ZERO ),
840 mViewportSize( Vector2::ZERO ),
841 mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
842 mRefreshOnceCounter( 0u ),
843 mScreenToFrameBufferFunction( Dali::RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION ),
844 mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
845 mInputEnabled( Dali::RenderTask::DEFAULT_INPUT_ENABLED ),
846 mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
847 mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE ),
848 mIsSystemLevel( isSystemLevel ),
849 mRequiresSync( false )
851 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::RenderTask(this:%p)\n", this);
854 RenderTask::~RenderTask()
856 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::~RenderTask(this:%p)\n", this);
859 // Helper class for connecting Nodes to the scene-graph RenderTask
861 RenderTask::Connector::Connector( Type type, RenderTask& renderTask )
863 mRenderTask( renderTask ),
869 RenderTask::Connector::~Connector()
874 void RenderTask::Connector::SetActor( Actor* actor )
876 if ( mActor != actor )
880 mActor->RemoveObserver( *this );
887 mActor->AddObserver( *this );
894 void RenderTask::Connector::SceneObjectAdded( Object& object )
899 void RenderTask::Connector::SceneObjectRemoved( Object& object )
904 void RenderTask::Connector::ObjectDestroyed( Object& object )
906 if ( SOURCE_CONNECTOR == mType )
908 const Stage* stage = Stage::GetCurrent();
911 stage->GetRenderTaskList().SetExclusive( &mRenderTask, false );
916 mCamera = NULL; // only meaningful for the camera connector but no simple way to distinguish
921 void RenderTask::Connector::UpdateRenderTask()
923 // Guard to allow handle destruction after Core has been destroyed
924 if( Internal::Stage::IsInstalled() &&
925 mRenderTask.mSceneObject )
927 const SceneGraph::Node* node( NULL );
929 // Check whether a Node exists in the scene-graph
930 if ( NULL != mActor )
932 const SceneGraph::PropertyOwner* object = mActor->GetSceneObject();
933 if ( NULL != object )
935 // actors only point to nodes as their scene objects
936 node = static_cast< const SceneGraph::Node* >( object );
940 //the mapping node is not used in the scene graph
941 if ( SOURCE_CONNECTOR == mType )
943 SetSourceNodeMessage( mRenderTask.GetEventThreadServices(), *(mRenderTask.mSceneObject), node );
945 else if( CAMERA_CONNECTOR == mType )
947 SetCameraMessage( mRenderTask.GetEventThreadServices(), *(mRenderTask.mSceneObject), node, mCamera );
952 } // namespace Internal