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/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/update/render-tasks/scene-graph-render-task.h>
37 #if defined(DEBUG_ENABLED)
40 Debug::Filter* gLogRender = Debug::Filter::New(Debug::Concise, false, "LOG_RENDER_TASK");
50 namespace // For internal properties
55 // Name Type writable animatable constraint-input enum for index-checking
56 DALI_PROPERTY_TABLE_BEGIN
57 DALI_PROPERTY( "viewportPosition", VECTOR2, true, true, true, Dali::RenderTask::Property::VIEWPORT_POSITION )
58 DALI_PROPERTY( "viewportSize", VECTOR2, true, true, true, Dali::RenderTask::Property::VIEWPORT_SIZE )
59 DALI_PROPERTY( "clearColor", VECTOR4, true, true, true, Dali::RenderTask::Property::CLEAR_COLOR )
60 DALI_PROPERTY( "requiresSync", BOOLEAN, true, false, false, Dali::RenderTask::Property::REQUIRES_SYNC )
61 DALI_PROPERTY_TABLE_END( DEFAULT_OBJECT_PROPERTY_START_INDEX, RenderTaskDefaultProperties )
65 const char* const SIGNAL_FINISHED = "finished";
67 TypeRegistration mType( typeid( Dali::RenderTask ), typeid( Dali::BaseHandle ), NULL, RenderTaskDefaultProperties );
69 SignalConnectorType signalConnector1( mType, SIGNAL_FINISHED, &RenderTask::DoConnectSignal );
71 } // Unnamed namespace
73 RenderTaskPtr RenderTask::New( Actor* sourceActor, CameraActor* cameraActor, RenderTaskList& renderTaskList )
75 // create scene object first so it's guaranteed to exist for the event side
76 auto sceneObject = SceneGraph::RenderTask::New();
78 // pass the pointer to base for message passing
79 RenderTaskPtr task( new RenderTask( sceneObject, renderTaskList ) );
81 // transfer scene object ownership to update manager
82 const SceneGraph::RenderTaskList& parentSceneObject = renderTaskList.GetSceneObject();
83 OwnerPointer< SceneGraph::RenderTask > transferOwnership( sceneObject );
84 AddTaskMessage( task->GetEventThreadServices(), parentSceneObject, transferOwnership );
86 // Set the default source & camera actors
87 task->SetSourceActor( sourceActor );
88 task->SetCameraActor( cameraActor );
90 // no need for additional messages as scene objects defaults match ours
94 void RenderTask::SetSourceActor( Actor* actor )
99 SetSourceNodeMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), &mSourceActor->GetNode() );
103 SetSourceNodeMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), nullptr );
106 // set the actor on exclusive container for hit testing
107 mRenderTaskList.SetExclusive( this, mExclusive );
110 Actor* RenderTask::GetSourceActor() const
115 void RenderTask::SetExclusive( bool exclusive )
117 if ( mExclusive != exclusive )
119 mExclusive = exclusive;
121 mRenderTaskList.SetExclusive( this, exclusive );
123 // scene object is being used in a separate thread; queue a message to set the value
124 SetExclusiveMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), mExclusive );
128 bool RenderTask::IsExclusive() const
133 void RenderTask::SetInputEnabled( bool enabled )
135 mInputEnabled = enabled;
138 bool RenderTask::GetInputEnabled() const
140 return mInputEnabled;
143 void RenderTask::SetCameraActor( CameraActor* cameraActor )
145 mCameraActor = cameraActor;
148 SetCameraMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), &mCameraActor->GetNode(), mCameraActor->GetCamera() );
152 SetCameraMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), nullptr, nullptr );
155 // set the actor on exclusive container for hit testing
156 mRenderTaskList.SetExclusive( this, mExclusive );
159 CameraActor* RenderTask::GetCameraActor() const
164 void RenderTask::SetTargetFrameBuffer( FrameBufferImagePtr image )
166 mFrameBufferImage = image;
167 FrameBuffer* frameBufferPtr( NULL );
170 frameBufferPtr = image->GetFrameBuffer();
173 SetFrameBuffer( frameBufferPtr );
176 void RenderTask::SetFrameBuffer( FrameBufferPtr frameBuffer )
178 mFrameBuffer = frameBuffer;
179 Render::FrameBuffer* renderFrameBufferPtr( NULL );
182 renderFrameBufferPtr = mFrameBuffer->GetRenderObject();
185 SetFrameBufferMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), renderFrameBufferPtr );
188 FrameBuffer* RenderTask::GetFrameBuffer() const
190 return mFrameBuffer.Get();
193 FrameBufferImage* RenderTask::GetTargetFrameBuffer() const
195 return mFrameBufferImage.Get();
198 void RenderTask::SetScreenToFrameBufferFunction( ScreenToFrameBufferFunction conversionFunction )
200 mScreenToFrameBufferFunction = conversionFunction;
203 RenderTask::ScreenToFrameBufferFunction RenderTask::GetScreenToFrameBufferFunction() const
205 return mScreenToFrameBufferFunction;
208 void RenderTask::SetScreenToFrameBufferMappingActor( Dali::Actor& mappingActor )
210 mInputMappingActor = WeakHandle<Dali::Actor>( mappingActor );
213 Dali::Actor RenderTask::GetScreenToFrameBufferMappingActor() const
215 return mInputMappingActor.GetHandle();
218 void RenderTask::SetViewportPosition(const Vector2& value)
220 mViewportPosition = value;
222 BakeViewportPositionMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), value );
225 Vector2 RenderTask::GetCurrentViewportPosition() const
227 return GetRenderTaskSceneObject().GetViewportPosition( GetEventThreadServices().GetEventBufferIndex() );
230 void RenderTask::SetViewportSize(const Vector2& value)
232 mViewportSize = value;
234 BakeViewportSizeMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), value );
237 Vector2 RenderTask::GetCurrentViewportSize() const
239 return GetRenderTaskSceneObject().GetViewportSize( GetEventThreadServices().GetEventBufferIndex() );
242 void RenderTask::SetViewport( const Viewport& viewport )
244 SetViewportPosition( Vector2( static_cast<float>( viewport.x ), static_cast<float>( viewport.y ) ) );
245 SetViewportSize( Vector2( static_cast<float>( viewport.width ), static_cast<float>( viewport.height ) ) );
248 void RenderTask::GetViewport( Viewport& viewPort ) const
250 BufferIndex bufferIndex = GetEventThreadServices().GetEventBufferIndex();
252 if( !GetRenderTaskSceneObject().GetViewportEnabled( bufferIndex ) )
254 if ( mFrameBufferImage )
256 viewPort.x = viewPort.y = 0;
257 viewPort.width = mFrameBufferImage->GetWidth();
258 viewPort.height = mFrameBufferImage->GetHeight();
262 Internal::Stage* stage = Internal::Stage::GetCurrent();
265 Vector2 size( stage->GetSize() );
266 viewPort.x = viewPort.y = 0;
267 viewPort.width = static_cast<int32_t>( size.width ); // truncated
268 viewPort.height = static_cast<int32_t>( size.height ); // truncated
274 const Vector2& position = GetRenderTaskSceneObject().GetViewportPosition(bufferIndex);
275 const Vector2& size = GetRenderTaskSceneObject().GetViewportSize(bufferIndex);
276 viewPort.x = static_cast<int32_t>( position.x ); // truncated
277 viewPort.y = static_cast<int32_t>( position.y ); // truncated
278 viewPort.width = static_cast<int32_t>( size.width ); // truncated
279 viewPort.height = static_cast<int32_t>( size.height ); // truncated
283 void RenderTask::SetClearColor( const Vector4& color )
285 if ( mClearColor != color )
289 // scene object is being used in a separate thread; queue a message to set the value
290 BakeClearColorMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), color );
294 const Vector4& RenderTask::GetClearColor() const
296 return GetRenderTaskSceneObject().GetClearColor( GetEventThreadServices().GetEventBufferIndex() );
299 void RenderTask::SetSyncRequired( bool requiresSync )
301 if( mRequiresSync != requiresSync )
303 mRequiresSync = requiresSync;
305 // scene object is being used in a separate thread; queue a message to set the value
306 SetSyncRequiredMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), requiresSync );
310 bool RenderTask::IsSyncRequired() const
312 return mRequiresSync;
315 void RenderTask::SetClearEnabled( bool enabled )
317 if ( mClearEnabled != enabled )
319 mClearEnabled = enabled;
321 // scene object is being used in a separate thread; queue a message to set the value
322 SetClearEnabledMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), mClearEnabled );
326 bool RenderTask::GetClearEnabled() const
328 return mClearEnabled;
331 void RenderTask::SetCullMode( bool mode )
333 if ( mCullMode != mode )
337 // scene object is being used in a separate thread; queue a message to set the value
338 SetCullModeMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), mCullMode );
342 bool RenderTask::GetCullMode() const
347 void RenderTask::SetRefreshRate( uint32_t refreshRate )
349 DALI_LOG_TRACE_METHOD_FMT(gLogRender, "this:%p rate:%d\n", this, refreshRate);
350 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::SetRefreshRate(this:%p, %d)\n", this, refreshRate);
352 mRefreshRate = refreshRate; // cached for GetRefreshRate()
354 // Note - even when refreshRate is the same as mRefreshRate, a message should be sent
356 // sceneObject is being used in a separate thread; queue a message to set the value
357 SetRefreshRateMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), refreshRate );
360 uint32_t RenderTask::GetRefreshRate() const
365 bool RenderTask::IsHittable( Vector2& screenCoords ) const
367 // True when input is enabled, source & camera actor are valid
368 bool inputEnabled( false );
370 Actor* sourceActor = GetSourceActor();
371 CameraActor* cameraActor = GetCameraActor();
373 if ( mInputEnabled &&
374 nullptr != sourceActor &&
375 sourceActor->OnStage() &&
376 nullptr != cameraActor &&
377 cameraActor->OnStage() )
379 // If the actors are rendered off-screen, then the screen coordinates must be converted
380 // and the conversion function will tell us if they are inside or outside
381 if ( TranslateCoordinates( screenCoords ) )
383 // This is a suitable render-task for input handling
391 bool RenderTask::TranslateCoordinates( Vector2& screenCoords ) const
393 // return true for on-screen tasks
395 // If the actors are rendered off-screen, then the screen coordinates must be converted
396 // the function should only be called for offscreen tasks
397 Dali::Actor mappingActor = GetScreenToFrameBufferMappingActor();
399 if( mFrameBufferImage && mappingActor )
401 Internal::Actor* inputMappingActor = &GetImplementation( mappingActor );
402 CameraActor* localCamera = GetCameraActor();
403 StagePtr stage = Stage::GetCurrent();
406 CameraActor& defaultCamera = stage->GetDefaultCameraActor();
410 Vector2 size( stage->GetSize() );
411 viewport.x = viewport.y = 0;
412 viewport.width = static_cast<int32_t>( size.width ); // truncated
413 viewport.height = static_cast<int32_t>( size.height ); // truncated
415 float localX, localY;
416 inside = inputMappingActor->ScreenToLocal(defaultCamera.GetViewMatrix(), defaultCamera.GetProjectionMatrix(), viewport, localX, localY, screenCoords.x, screenCoords.y);
417 Vector3 actorSize = inputMappingActor->GetCurrentSize();
418 if( inside && localX >= 0.f && localX <= actorSize.x && localY >= 0.f && localY <= actorSize.y)
420 screenCoords.x = localX;
421 screenCoords.y = localY;
434 else if ( mFrameBufferImage && mScreenToFrameBufferFunction )
436 inside = mScreenToFrameBufferFunction( screenCoords );
441 bool RenderTask::WorldToViewport(const Vector3 &position, float& viewportX, float& viewportY) const
443 CameraActor* cam = GetCameraActor();
445 Vector4 pos(position);
448 Vector4 viewportPosition;
451 GetViewport( viewport );
453 bool ok = ProjectFull(pos,
454 cam->GetViewMatrix(),
455 cam->GetProjectionMatrix(),
456 static_cast<float>( viewport.x ), // truncated
457 static_cast<float>( viewport.y ), // truncated
458 static_cast<float>( viewport.width ), // truncated
459 static_cast<float>( viewport.height ), // truncated
463 viewportX = viewportPosition.x;
464 viewportY = viewportPosition.y;
470 bool RenderTask::ViewportToLocal(Actor* actor, float viewportX, float viewportY, float &localX, float &localY) const
472 return actor->ScreenToLocal( *this, localX, localY, viewportX, viewportY );
475 const SceneGraph::RenderTask& RenderTask::GetRenderTaskSceneObject() const
477 return *static_cast<const SceneGraph::RenderTask*>( mUpdateObject );
480 /********************************************************************************
481 ******************************** PROPERTY METHODS **************************
482 ********************************************************************************/
484 void RenderTask::SetDefaultProperty( Property::Index index, const Property::Value& property )
488 case Dali::RenderTask::Property::VIEWPORT_POSITION:
490 SetViewportPosition( property.Get<Vector2>() );
493 case Dali::RenderTask::Property::VIEWPORT_SIZE:
495 SetViewportSize( property.Get<Vector2>() );
498 case Dali::RenderTask::Property::CLEAR_COLOR:
500 SetClearColor( property.Get<Vector4>() );
503 case Dali::RenderTask::Property::REQUIRES_SYNC:
505 SetSyncRequired( property.Get<bool>() );
516 Property::Value RenderTask::GetDefaultProperty(Property::Index index) const
518 Property::Value value;
522 case Dali::RenderTask::Property::VIEWPORT_POSITION:
524 value = mViewportPosition;
527 case Dali::RenderTask::Property::VIEWPORT_SIZE:
529 value = mViewportSize;
532 case Dali::RenderTask::Property::CLEAR_COLOR:
537 case Dali::RenderTask::Property::REQUIRES_SYNC:
539 value = IsSyncRequired();
545 DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
553 Property::Value RenderTask::GetDefaultPropertyCurrentValue( Property::Index index ) const
555 Property::Value value;
559 case Dali::RenderTask::Property::VIEWPORT_POSITION:
561 value = GetCurrentViewportPosition();
564 case Dali::RenderTask::Property::VIEWPORT_SIZE:
566 value = GetCurrentViewportSize();
569 case Dali::RenderTask::Property::CLEAR_COLOR:
571 value = GetClearColor();
574 case Dali::RenderTask::Property::REQUIRES_SYNC:
576 value = IsSyncRequired();
582 DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
590 void RenderTask::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
592 switch( animationType )
595 case Animation::BETWEEN:
599 case Dali::RenderTask::Property::VIEWPORT_POSITION:
601 value.Get( mViewportPosition );
604 case Dali::RenderTask::Property::VIEWPORT_SIZE:
606 value.Get( mViewportSize );
609 case Dali::RenderTask::Property::CLEAR_COLOR:
611 value.Get( mClearColor );
614 case Dali::RenderTask::Property::REQUIRES_SYNC:
617 // Nothing to do as not animatable
628 case Dali::RenderTask::Property::VIEWPORT_POSITION:
630 AdjustValue< Vector2 >( mViewportPosition, value );
633 case Dali::RenderTask::Property::VIEWPORT_SIZE:
635 AdjustValue< Vector2 >( mViewportSize, value );
638 case Dali::RenderTask::Property::CLEAR_COLOR:
640 AdjustValue< Vector4 >( mClearColor, value );
643 case Dali::RenderTask::Property::REQUIRES_SYNC:
646 // Nothing to do as not animatable
655 const SceneGraph::PropertyBase* RenderTask::GetSceneObjectAnimatableProperty( Property::Index index ) const
657 const SceneGraph::PropertyBase* property( NULL );
661 case Dali::RenderTask::Property::VIEWPORT_POSITION:
663 property = &GetRenderTaskSceneObject().mViewportPosition;
666 case Dali::RenderTask::Property::VIEWPORT_SIZE:
668 property = &GetRenderTaskSceneObject().mViewportSize;
671 case Dali::RenderTask::Property::CLEAR_COLOR:
673 property = &GetRenderTaskSceneObject().mClearColor;
683 // not our property, ask base
684 property = Object::GetSceneObjectAnimatableProperty( index );
690 const PropertyInputImpl* RenderTask::GetSceneObjectInputProperty( Property::Index index ) const
692 // animatable properties are input as well, Object::GetSceneObjectInputProperty does the same so no need to call it
693 return GetSceneObjectAnimatableProperty( index );
696 bool RenderTask::HasFinished()
698 bool finished = false;
699 const uint32_t counter = GetRenderTaskSceneObject().GetRenderedOnceCounter();
701 if( mRefreshOnceCounter < counter )
704 mRefreshOnceCounter = counter;
707 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::HasFinished()=%s SCRT:%p SC\n", finished?"T":"F", &GetRenderTaskSceneObject());
712 void RenderTask::EmitSignalFinish()
714 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::EmitSignalFinish(this:%p)\n", this);
716 if( !mSignalFinished.Empty() )
718 Dali::RenderTask handle( this );
719 mSignalFinished.Emit(handle );
723 Dali::RenderTask::RenderTaskSignalType& RenderTask::FinishedSignal()
725 return mSignalFinished;
728 bool RenderTask::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
730 bool connected( true );
731 RenderTask* renderTask = static_cast< RenderTask* >(object); // TypeRegistry guarantees that this is the correct type.
733 if ( 0 == strcmp( signalName.c_str(), SIGNAL_FINISHED ) )
735 renderTask->FinishedSignal().Connect( tracker, functor );
739 // signalName does not match any signal
746 RenderTask::RenderTask( const SceneGraph::RenderTask* sceneObject, RenderTaskList& renderTaskList )
747 : Object( sceneObject ),
748 mSourceActor( nullptr ),
749 mCameraActor( nullptr ),
750 mInputMappingActor(),
751 mRenderTaskList( renderTaskList ),
752 mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
753 mViewportPosition( Vector2::ZERO ),
754 mViewportSize( Vector2::ZERO ),
755 mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
756 mRefreshOnceCounter( 0u ),
757 mScreenToFrameBufferFunction( Dali::RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION ),
758 mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
759 mInputEnabled( Dali::RenderTask::DEFAULT_INPUT_ENABLED ),
760 mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
761 mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE ),
762 mRequiresSync( false )
764 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::RenderTask(this:%p)\n", this);
765 // scene object handles observation of source and camera
768 RenderTask::~RenderTask()
770 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::~RenderTask(this:%p)\n", this);
771 // scene object deletion is handled by our parent
772 // scene object handles observation of source and camera
775 } // namespace Internal