2 * Copyright (c) 2019 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/scene-impl.h>
33 #include <dali/internal/event/common/projection.h>
34 #include <dali/internal/event/images/frame-buffer-image-impl.h>
35 #include <dali/internal/update/nodes/node.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, RenderTaskDefaultProperties )
66 const char* const SIGNAL_FINISHED = "finished";
68 TypeRegistration mType( typeid( Dali::RenderTask ), typeid( Dali::BaseHandle ), NULL, RenderTaskDefaultProperties );
70 SignalConnectorType signalConnector1( mType, SIGNAL_FINISHED, &RenderTask::DoConnectSignal );
72 } // Unnamed namespace
74 RenderTaskPtr RenderTask::New( Actor* sourceActor, CameraActor* cameraActor, RenderTaskList& renderTaskList )
76 // create scene object first so it's guaranteed to exist for the event side
77 auto sceneObject = SceneGraph::RenderTask::New();
79 // pass the pointer to base for message passing
80 RenderTaskPtr task( new RenderTask( sceneObject, renderTaskList ) );
82 // transfer scene object ownership to update manager
83 const SceneGraph::RenderTaskList& parentSceneObject = renderTaskList.GetSceneObject();
84 OwnerPointer< SceneGraph::RenderTask > transferOwnership( sceneObject );
85 AddTaskMessage( task->GetEventThreadServices(), parentSceneObject, transferOwnership );
87 // Set the default source & camera actors
88 task->SetSourceActor( sourceActor );
89 task->SetCameraActor( cameraActor );
91 // no need for additional messages as scene objects defaults match ours
95 void RenderTask::SetSourceActor( Actor* actor )
97 mSourceActor.SetActor( actor );
100 SetSourceNodeMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), &actor->GetNode() );
104 SetSourceNodeMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), nullptr );
107 // set the actor on exclusive container for hit testing
108 mRenderTaskList.SetExclusive( this, mExclusive );
111 Actor* RenderTask::GetSourceActor() const
113 return mSourceActor.GetActor();
116 void RenderTask::SetExclusive( bool exclusive )
118 if ( mExclusive != exclusive )
120 mExclusive = exclusive;
122 mRenderTaskList.SetExclusive( this, exclusive );
124 // scene object is being used in a separate thread; queue a message to set the value
125 SetExclusiveMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), mExclusive );
129 bool RenderTask::IsExclusive() const
134 void RenderTask::SetInputEnabled( bool enabled )
136 mInputEnabled = enabled;
139 bool RenderTask::GetInputEnabled() const
141 return mInputEnabled;
144 void RenderTask::SetCameraActor( CameraActor* cameraActor )
146 mCameraActor.SetActor( cameraActor );
149 SetCameraMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), &cameraActor->GetNode(), cameraActor->GetCamera() );
153 SetCameraMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), nullptr, nullptr );
156 // set the actor on exclusive container for hit testing
157 mRenderTaskList.SetExclusive( this, mExclusive );
160 CameraActor* RenderTask::GetCameraActor() const
162 if( mCameraActor.GetActor() )
164 return static_cast< CameraActor* >( mCameraActor.GetActor() );
169 void RenderTask::SetTargetFrameBuffer( FrameBufferImagePtr image )
171 mFrameBufferImage = image;
172 FrameBuffer* frameBufferPtr( NULL );
175 frameBufferPtr = image->GetFrameBuffer();
178 SetFrameBuffer( frameBufferPtr );
181 void RenderTask::SetFrameBuffer( FrameBufferPtr frameBuffer )
183 mFrameBuffer = frameBuffer;
184 Render::FrameBuffer* renderFrameBufferPtr( NULL );
187 renderFrameBufferPtr = mFrameBuffer->GetRenderObject();
190 SetFrameBufferMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), renderFrameBufferPtr );
193 FrameBuffer* RenderTask::GetFrameBuffer() const
195 return mFrameBuffer.Get();
198 FrameBufferImage* RenderTask::GetTargetFrameBuffer() const
200 return mFrameBufferImage.Get();
203 void RenderTask::SetScreenToFrameBufferFunction( ScreenToFrameBufferFunction conversionFunction )
205 mScreenToFrameBufferFunction = conversionFunction;
208 RenderTask::ScreenToFrameBufferFunction RenderTask::GetScreenToFrameBufferFunction() const
210 return mScreenToFrameBufferFunction;
213 void RenderTask::SetScreenToFrameBufferMappingActor( Dali::Actor& mappingActor )
215 mInputMappingActor = WeakHandle<Dali::Actor>( mappingActor );
218 Dali::Actor RenderTask::GetScreenToFrameBufferMappingActor() const
220 return mInputMappingActor.GetHandle();
223 void RenderTask::SetViewportPosition(const Vector2& value)
225 mViewportPosition = value;
227 BakeViewportPositionMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), value );
230 Vector2 RenderTask::GetCurrentViewportPosition() const
232 return GetRenderTaskSceneObject().GetViewportPosition( GetEventThreadServices().GetEventBufferIndex() );
235 void RenderTask::SetViewportSize(const Vector2& value)
237 mViewportSize = value;
239 BakeViewportSizeMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), value );
242 Vector2 RenderTask::GetCurrentViewportSize() const
244 return GetRenderTaskSceneObject().GetViewportSize( GetEventThreadServices().GetEventBufferIndex() );
247 void RenderTask::SetViewport( const Viewport& viewport )
249 SetViewportPosition( Vector2( static_cast<float>( viewport.x ), static_cast<float>( viewport.y ) ) );
250 SetViewportSize( Vector2( static_cast<float>( viewport.width ), static_cast<float>( viewport.height ) ) );
253 void RenderTask::GetViewport( Viewport& viewPort ) const
255 BufferIndex bufferIndex = GetEventThreadServices().GetEventBufferIndex();
257 if( !GetRenderTaskSceneObject().GetViewportEnabled( bufferIndex ) )
259 if ( mFrameBufferImage )
261 viewPort.x = viewPort.y = 0;
262 viewPort.width = mFrameBufferImage->GetWidth();
263 viewPort.height = mFrameBufferImage->GetHeight();
267 Internal::Stage* stage = Internal::Stage::GetCurrent();
270 Vector2 size( stage->GetSize() );
271 Actor* sourceActor = mSourceActor.GetActor();
272 if ( sourceActor && sourceActor->OnStage() )
274 Scene& scene = sourceActor->GetScene();
275 size = scene.GetSize();
278 viewPort.x = viewPort.y = 0;
279 viewPort.width = static_cast<int32_t>( size.width ); // truncated
280 viewPort.height = static_cast<int32_t>( size.height ); // truncated
286 const Vector2& position = GetRenderTaskSceneObject().GetViewportPosition(bufferIndex);
287 const Vector2& size = GetRenderTaskSceneObject().GetViewportSize(bufferIndex);
288 viewPort.x = static_cast<int32_t>( position.x ); // truncated
289 viewPort.y = static_cast<int32_t>( position.y ); // truncated
290 viewPort.width = static_cast<int32_t>( size.width ); // truncated
291 viewPort.height = static_cast<int32_t>( size.height ); // truncated
295 void RenderTask::SetClearColor( const Vector4& color )
297 if ( mClearColor != color )
301 // scene object is being used in a separate thread; queue a message to set the value
302 BakeClearColorMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), color );
306 const Vector4& RenderTask::GetClearColor() const
308 return GetRenderTaskSceneObject().GetClearColor( GetEventThreadServices().GetEventBufferIndex() );
311 void RenderTask::SetSyncRequired( bool requiresSync )
313 if( mRequiresSync != requiresSync )
315 mRequiresSync = requiresSync;
317 // scene object is being used in a separate thread; queue a message to set the value
318 SetSyncRequiredMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), requiresSync );
322 bool RenderTask::IsSyncRequired() const
324 return mRequiresSync;
327 void RenderTask::SetClearEnabled( bool enabled )
329 if ( mClearEnabled != enabled )
331 mClearEnabled = enabled;
333 // scene object is being used in a separate thread; queue a message to set the value
334 SetClearEnabledMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), mClearEnabled );
338 bool RenderTask::GetClearEnabled() const
340 return mClearEnabled;
343 void RenderTask::SetCullMode( bool mode )
345 if ( mCullMode != mode )
349 // scene object is being used in a separate thread; queue a message to set the value
350 SetCullModeMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), mCullMode );
354 bool RenderTask::GetCullMode() const
359 void RenderTask::SetRefreshRate( uint32_t refreshRate )
361 DALI_LOG_TRACE_METHOD_FMT(gLogRender, "this:%p rate:%d\n", this, refreshRate);
362 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::SetRefreshRate(this:%p, %d)\n", this, refreshRate);
364 mRefreshRate = refreshRate; // cached for GetRefreshRate()
366 // Note - even when refreshRate is the same as mRefreshRate, a message should be sent
368 // sceneObject is being used in a separate thread; queue a message to set the value
369 SetRefreshRateMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), refreshRate );
372 uint32_t RenderTask::GetRefreshRate() const
377 bool RenderTask::IsHittable( Vector2& screenCoords ) const
379 // True when input is enabled, source & camera actor are valid
380 bool inputEnabled( false );
382 Actor* sourceActor = GetSourceActor();
383 CameraActor* cameraActor = GetCameraActor();
385 if ( mInputEnabled &&
386 nullptr != sourceActor &&
387 sourceActor->OnStage() &&
388 nullptr != cameraActor &&
389 cameraActor->OnStage() )
391 // If the actors are rendered off-screen, then the screen coordinates must be converted
392 // and the conversion function will tell us if they are inside or outside
393 if ( TranslateCoordinates( screenCoords ) )
395 // This is a suitable render-task for input handling
403 bool RenderTask::TranslateCoordinates( Vector2& screenCoords ) const
405 // return true for on-screen tasks
407 // If the actors are rendered off-screen, then the screen coordinates must be converted
408 // the function should only be called for offscreen tasks
409 Dali::Actor mappingActor = GetScreenToFrameBufferMappingActor();
411 if( mFrameBufferImage && mappingActor )
413 Internal::Actor* inputMappingActor = &GetImplementation( mappingActor );
414 CameraActor* localCamera = GetCameraActor();
415 StagePtr stage = Stage::GetCurrent();
418 Vector2 size( stage->GetSize() );
419 CameraActor* defaultCamera( &stage->GetDefaultCameraActor() );
420 Actor* sourceActor = mSourceActor.GetActor();
421 if ( sourceActor && sourceActor->OnStage() )
423 Scene& scene = sourceActor->GetScene();
424 size = scene.GetSize();
425 defaultCamera = &scene.GetDefaultCameraActor();
431 viewport.x = viewport.y = 0;
432 viewport.width = static_cast<int32_t>( size.width ); // truncated
433 viewport.height = static_cast<int32_t>( size.height ); // truncated
435 float localX, localY;
436 inside = inputMappingActor->ScreenToLocal(defaultCamera->GetViewMatrix(), defaultCamera->GetProjectionMatrix(), viewport, localX, localY, screenCoords.x, screenCoords.y);
437 Vector3 actorSize = inputMappingActor->GetCurrentSize();
438 if( inside && localX >= 0.f && localX <= actorSize.x && localY >= 0.f && localY <= actorSize.y)
440 screenCoords.x = localX;
441 screenCoords.y = localY;
454 else if ( mFrameBufferImage && mScreenToFrameBufferFunction )
456 inside = mScreenToFrameBufferFunction( screenCoords );
461 bool RenderTask::WorldToViewport(const Vector3 &position, float& viewportX, float& viewportY) const
463 CameraActor* cam = GetCameraActor();
465 Vector4 pos(position);
468 Vector4 viewportPosition;
471 GetViewport( viewport );
473 bool ok = ProjectFull(pos,
474 cam->GetViewMatrix(),
475 cam->GetProjectionMatrix(),
476 static_cast<float>( viewport.x ), // truncated
477 static_cast<float>( viewport.y ), // truncated
478 static_cast<float>( viewport.width ), // truncated
479 static_cast<float>( viewport.height ), // truncated
483 viewportX = viewportPosition.x;
484 viewportY = viewportPosition.y;
490 bool RenderTask::ViewportToLocal(Actor* actor, float viewportX, float viewportY, float &localX, float &localY) const
492 return actor->ScreenToLocal( *this, localX, localY, viewportX, viewportY );
495 const SceneGraph::RenderTask& RenderTask::GetRenderTaskSceneObject() const
497 return *static_cast<const SceneGraph::RenderTask*>( mUpdateObject );
500 RenderTaskList& RenderTask::GetRenderTaskList() const
502 return mRenderTaskList;
505 /********************************************************************************
506 ******************************** PROPERTY METHODS **************************
507 ********************************************************************************/
509 void RenderTask::SetDefaultProperty( Property::Index index, const Property::Value& property )
513 case Dali::RenderTask::Property::VIEWPORT_POSITION:
515 SetViewportPosition( property.Get<Vector2>() );
518 case Dali::RenderTask::Property::VIEWPORT_SIZE:
520 SetViewportSize( property.Get<Vector2>() );
523 case Dali::RenderTask::Property::CLEAR_COLOR:
525 SetClearColor( property.Get<Vector4>() );
528 case Dali::RenderTask::Property::REQUIRES_SYNC:
530 SetSyncRequired( property.Get<bool>() );
541 Property::Value RenderTask::GetDefaultProperty(Property::Index index) const
543 Property::Value value;
547 case Dali::RenderTask::Property::VIEWPORT_POSITION:
549 value = mViewportPosition;
552 case Dali::RenderTask::Property::VIEWPORT_SIZE:
554 value = mViewportSize;
557 case Dali::RenderTask::Property::CLEAR_COLOR:
562 case Dali::RenderTask::Property::REQUIRES_SYNC:
564 value = IsSyncRequired();
570 DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
578 Property::Value RenderTask::GetDefaultPropertyCurrentValue( Property::Index index ) const
580 Property::Value value;
584 case Dali::RenderTask::Property::VIEWPORT_POSITION:
586 value = GetCurrentViewportPosition();
589 case Dali::RenderTask::Property::VIEWPORT_SIZE:
591 value = GetCurrentViewportSize();
594 case Dali::RenderTask::Property::CLEAR_COLOR:
596 value = GetClearColor();
599 case Dali::RenderTask::Property::REQUIRES_SYNC:
601 value = IsSyncRequired();
607 DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
615 void RenderTask::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
617 switch( animationType )
620 case Animation::BETWEEN:
624 case Dali::RenderTask::Property::VIEWPORT_POSITION:
626 value.Get( mViewportPosition );
629 case Dali::RenderTask::Property::VIEWPORT_SIZE:
631 value.Get( mViewportSize );
634 case Dali::RenderTask::Property::CLEAR_COLOR:
636 value.Get( mClearColor );
639 case Dali::RenderTask::Property::REQUIRES_SYNC:
642 // Nothing to do as not animatable
653 case Dali::RenderTask::Property::VIEWPORT_POSITION:
655 AdjustValue< Vector2 >( mViewportPosition, value );
658 case Dali::RenderTask::Property::VIEWPORT_SIZE:
660 AdjustValue< Vector2 >( mViewportSize, value );
663 case Dali::RenderTask::Property::CLEAR_COLOR:
665 AdjustValue< Vector4 >( mClearColor, value );
668 case Dali::RenderTask::Property::REQUIRES_SYNC:
671 // Nothing to do as not animatable
680 const SceneGraph::PropertyBase* RenderTask::GetSceneObjectAnimatableProperty( Property::Index index ) const
682 const SceneGraph::PropertyBase* property( NULL );
686 case Dali::RenderTask::Property::VIEWPORT_POSITION:
688 property = &GetRenderTaskSceneObject().mViewportPosition;
691 case Dali::RenderTask::Property::VIEWPORT_SIZE:
693 property = &GetRenderTaskSceneObject().mViewportSize;
696 case Dali::RenderTask::Property::CLEAR_COLOR:
698 property = &GetRenderTaskSceneObject().mClearColor;
708 // not our property, ask base
709 property = Object::GetSceneObjectAnimatableProperty( index );
715 const PropertyInputImpl* RenderTask::GetSceneObjectInputProperty( Property::Index index ) const
717 // animatable properties are input as well, Object::GetSceneObjectInputProperty does the same so no need to call it
718 return GetSceneObjectAnimatableProperty( index );
721 bool RenderTask::HasFinished()
723 bool finished = false;
724 const uint32_t counter = GetRenderTaskSceneObject().GetRenderedOnceCounter();
726 if( mRefreshOnceCounter < counter )
729 mRefreshOnceCounter = counter;
732 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::HasFinished()=%s SCRT:%p SC\n", finished?"T":"F", &GetRenderTaskSceneObject());
737 void RenderTask::EmitSignalFinish()
739 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::EmitSignalFinish(this:%p)\n", this);
741 if( !mSignalFinished.Empty() )
743 Dali::RenderTask handle( this );
744 mSignalFinished.Emit(handle );
748 Dali::RenderTask::RenderTaskSignalType& RenderTask::FinishedSignal()
750 return mSignalFinished;
753 bool RenderTask::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
755 bool connected( true );
756 RenderTask* renderTask = static_cast< RenderTask* >(object); // TypeRegistry guarantees that this is the correct type.
758 if ( 0 == strcmp( signalName.c_str(), SIGNAL_FINISHED ) )
760 renderTask->FinishedSignal().Connect( tracker, functor );
764 // signalName does not match any signal
771 RenderTask::RenderTask( const SceneGraph::RenderTask* sceneObject, RenderTaskList& renderTaskList )
772 : Object( sceneObject ),
775 mInputMappingActor(),
776 mRenderTaskList( renderTaskList ),
777 mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
778 mViewportPosition( Vector2::ZERO ),
779 mViewportSize( Vector2::ZERO ),
780 mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
781 mRefreshOnceCounter( 0u ),
782 mScreenToFrameBufferFunction( Dali::RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION ),
783 mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
784 mInputEnabled( Dali::RenderTask::DEFAULT_INPUT_ENABLED ),
785 mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
786 mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE ),
787 mRequiresSync( false )
789 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::RenderTask(this:%p)\n", this);
790 // scene object handles observation of source and camera
793 RenderTask::~RenderTask()
795 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::~RenderTask(this:%p)\n", this);
796 // scene object deletion is handled by our parent
797 // scene object handles observation of source and camera
800 } // namespace Internal