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 )
100 SetSourceNodeMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), &mSourceActor->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
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 = cameraActor;
149 SetCameraMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), &mCameraActor->GetNode(), mCameraActor->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
165 void RenderTask::SetTargetFrameBuffer( FrameBufferImagePtr image )
167 mFrameBufferImage = image;
168 FrameBuffer* frameBufferPtr( NULL );
171 frameBufferPtr = image->GetFrameBuffer();
174 SetFrameBuffer( frameBufferPtr );
177 void RenderTask::SetFrameBuffer( FrameBufferPtr frameBuffer )
179 mFrameBuffer = frameBuffer;
180 Render::FrameBuffer* renderFrameBufferPtr( NULL );
183 renderFrameBufferPtr = mFrameBuffer->GetRenderObject();
186 SetFrameBufferMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), renderFrameBufferPtr );
189 FrameBuffer* RenderTask::GetFrameBuffer() const
191 return mFrameBuffer.Get();
194 FrameBufferImage* RenderTask::GetTargetFrameBuffer() const
196 return mFrameBufferImage.Get();
199 void RenderTask::SetScreenToFrameBufferFunction( ScreenToFrameBufferFunction conversionFunction )
201 mScreenToFrameBufferFunction = conversionFunction;
204 RenderTask::ScreenToFrameBufferFunction RenderTask::GetScreenToFrameBufferFunction() const
206 return mScreenToFrameBufferFunction;
209 void RenderTask::SetScreenToFrameBufferMappingActor( Dali::Actor& mappingActor )
211 mInputMappingActor = WeakHandle<Dali::Actor>( mappingActor );
214 Dali::Actor RenderTask::GetScreenToFrameBufferMappingActor() const
216 return mInputMappingActor.GetHandle();
219 void RenderTask::SetViewportPosition(const Vector2& value)
221 mViewportPosition = value;
223 BakeViewportPositionMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), value );
226 Vector2 RenderTask::GetCurrentViewportPosition() const
228 return GetRenderTaskSceneObject().GetViewportPosition( GetEventThreadServices().GetEventBufferIndex() );
231 void RenderTask::SetViewportSize(const Vector2& value)
233 mViewportSize = value;
235 BakeViewportSizeMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), value );
238 Vector2 RenderTask::GetCurrentViewportSize() const
240 return GetRenderTaskSceneObject().GetViewportSize( GetEventThreadServices().GetEventBufferIndex() );
243 void RenderTask::SetViewport( const Viewport& viewport )
245 SetViewportPosition( Vector2( static_cast<float>( viewport.x ), static_cast<float>( viewport.y ) ) );
246 SetViewportSize( Vector2( static_cast<float>( viewport.width ), static_cast<float>( viewport.height ) ) );
249 void RenderTask::GetViewport( Viewport& viewPort ) const
251 BufferIndex bufferIndex = GetEventThreadServices().GetEventBufferIndex();
253 if( !GetRenderTaskSceneObject().GetViewportEnabled( bufferIndex ) )
255 if ( mFrameBufferImage )
257 viewPort.x = viewPort.y = 0;
258 viewPort.width = mFrameBufferImage->GetWidth();
259 viewPort.height = mFrameBufferImage->GetHeight();
263 Internal::Stage* stage = Internal::Stage::GetCurrent();
266 Vector2 size( stage->GetSize() );
267 if ( mSourceActor && mSourceActor->OnStage() )
269 Scene& scene = mSourceActor->GetScene();
270 size = scene.GetSize();
273 viewPort.x = viewPort.y = 0;
274 viewPort.width = static_cast<int32_t>( size.width ); // truncated
275 viewPort.height = static_cast<int32_t>( size.height ); // truncated
281 const Vector2& position = GetRenderTaskSceneObject().GetViewportPosition(bufferIndex);
282 const Vector2& size = GetRenderTaskSceneObject().GetViewportSize(bufferIndex);
283 viewPort.x = static_cast<int32_t>( position.x ); // truncated
284 viewPort.y = static_cast<int32_t>( position.y ); // truncated
285 viewPort.width = static_cast<int32_t>( size.width ); // truncated
286 viewPort.height = static_cast<int32_t>( size.height ); // truncated
290 void RenderTask::SetClearColor( const Vector4& color )
292 if ( mClearColor != color )
296 // scene object is being used in a separate thread; queue a message to set the value
297 BakeClearColorMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), color );
301 const Vector4& RenderTask::GetClearColor() const
303 return GetRenderTaskSceneObject().GetClearColor( GetEventThreadServices().GetEventBufferIndex() );
306 void RenderTask::SetSyncRequired( bool requiresSync )
308 if( mRequiresSync != requiresSync )
310 mRequiresSync = requiresSync;
312 // scene object is being used in a separate thread; queue a message to set the value
313 SetSyncRequiredMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), requiresSync );
317 bool RenderTask::IsSyncRequired() const
319 return mRequiresSync;
322 void RenderTask::SetClearEnabled( bool enabled )
324 if ( mClearEnabled != enabled )
326 mClearEnabled = enabled;
328 // scene object is being used in a separate thread; queue a message to set the value
329 SetClearEnabledMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), mClearEnabled );
333 bool RenderTask::GetClearEnabled() const
335 return mClearEnabled;
338 void RenderTask::SetCullMode( bool mode )
340 if ( mCullMode != mode )
344 // scene object is being used in a separate thread; queue a message to set the value
345 SetCullModeMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), mCullMode );
349 bool RenderTask::GetCullMode() const
354 void RenderTask::SetRefreshRate( uint32_t refreshRate )
356 DALI_LOG_TRACE_METHOD_FMT(gLogRender, "this:%p rate:%d\n", this, refreshRate);
357 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::SetRefreshRate(this:%p, %d)\n", this, refreshRate);
359 mRefreshRate = refreshRate; // cached for GetRefreshRate()
361 // Note - even when refreshRate is the same as mRefreshRate, a message should be sent
363 // sceneObject is being used in a separate thread; queue a message to set the value
364 SetRefreshRateMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), refreshRate );
367 uint32_t RenderTask::GetRefreshRate() const
372 bool RenderTask::IsHittable( Vector2& screenCoords ) const
374 // True when input is enabled, source & camera actor are valid
375 bool inputEnabled( false );
377 Actor* sourceActor = GetSourceActor();
378 CameraActor* cameraActor = GetCameraActor();
380 if ( mInputEnabled &&
381 nullptr != sourceActor &&
382 sourceActor->OnStage() &&
383 nullptr != cameraActor &&
384 cameraActor->OnStage() )
386 // If the actors are rendered off-screen, then the screen coordinates must be converted
387 // and the conversion function will tell us if they are inside or outside
388 if ( TranslateCoordinates( screenCoords ) )
390 // This is a suitable render-task for input handling
398 bool RenderTask::TranslateCoordinates( Vector2& screenCoords ) const
400 // return true for on-screen tasks
402 // If the actors are rendered off-screen, then the screen coordinates must be converted
403 // the function should only be called for offscreen tasks
404 Dali::Actor mappingActor = GetScreenToFrameBufferMappingActor();
406 if( mFrameBufferImage && mappingActor )
408 Internal::Actor* inputMappingActor = &GetImplementation( mappingActor );
409 CameraActor* localCamera = GetCameraActor();
410 StagePtr stage = Stage::GetCurrent();
413 Vector2 size( stage->GetSize() );
414 CameraActor* defaultCamera( &stage->GetDefaultCameraActor() );
415 if ( mSourceActor && mSourceActor->OnStage() )
417 Scene& scene = mSourceActor->GetScene();
418 size = scene.GetSize();
419 defaultCamera = &scene.GetDefaultCameraActor();
425 viewport.x = viewport.y = 0;
426 viewport.width = static_cast<int32_t>( size.width ); // truncated
427 viewport.height = static_cast<int32_t>( size.height ); // truncated
429 float localX, localY;
430 inside = inputMappingActor->ScreenToLocal(defaultCamera->GetViewMatrix(), defaultCamera->GetProjectionMatrix(), viewport, localX, localY, screenCoords.x, screenCoords.y);
431 Vector3 actorSize = inputMappingActor->GetCurrentSize();
432 if( inside && localX >= 0.f && localX <= actorSize.x && localY >= 0.f && localY <= actorSize.y)
434 screenCoords.x = localX;
435 screenCoords.y = localY;
448 else if ( mFrameBufferImage && mScreenToFrameBufferFunction )
450 inside = mScreenToFrameBufferFunction( screenCoords );
455 bool RenderTask::WorldToViewport(const Vector3 &position, float& viewportX, float& viewportY) const
457 CameraActor* cam = GetCameraActor();
459 Vector4 pos(position);
462 Vector4 viewportPosition;
465 GetViewport( viewport );
467 bool ok = ProjectFull(pos,
468 cam->GetViewMatrix(),
469 cam->GetProjectionMatrix(),
470 static_cast<float>( viewport.x ), // truncated
471 static_cast<float>( viewport.y ), // truncated
472 static_cast<float>( viewport.width ), // truncated
473 static_cast<float>( viewport.height ), // truncated
477 viewportX = viewportPosition.x;
478 viewportY = viewportPosition.y;
484 bool RenderTask::ViewportToLocal(Actor* actor, float viewportX, float viewportY, float &localX, float &localY) const
486 return actor->ScreenToLocal( *this, localX, localY, viewportX, viewportY );
489 const SceneGraph::RenderTask& RenderTask::GetRenderTaskSceneObject() const
491 return *static_cast<const SceneGraph::RenderTask*>( mUpdateObject );
494 RenderTaskList& RenderTask::GetRenderTaskList() const
496 return mRenderTaskList;
499 /********************************************************************************
500 ******************************** PROPERTY METHODS **************************
501 ********************************************************************************/
503 void RenderTask::SetDefaultProperty( Property::Index index, const Property::Value& property )
507 case Dali::RenderTask::Property::VIEWPORT_POSITION:
509 SetViewportPosition( property.Get<Vector2>() );
512 case Dali::RenderTask::Property::VIEWPORT_SIZE:
514 SetViewportSize( property.Get<Vector2>() );
517 case Dali::RenderTask::Property::CLEAR_COLOR:
519 SetClearColor( property.Get<Vector4>() );
522 case Dali::RenderTask::Property::REQUIRES_SYNC:
524 SetSyncRequired( property.Get<bool>() );
535 Property::Value RenderTask::GetDefaultProperty(Property::Index index) const
537 Property::Value value;
541 case Dali::RenderTask::Property::VIEWPORT_POSITION:
543 value = mViewportPosition;
546 case Dali::RenderTask::Property::VIEWPORT_SIZE:
548 value = mViewportSize;
551 case Dali::RenderTask::Property::CLEAR_COLOR:
556 case Dali::RenderTask::Property::REQUIRES_SYNC:
558 value = IsSyncRequired();
564 DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
572 Property::Value RenderTask::GetDefaultPropertyCurrentValue( Property::Index index ) const
574 Property::Value value;
578 case Dali::RenderTask::Property::VIEWPORT_POSITION:
580 value = GetCurrentViewportPosition();
583 case Dali::RenderTask::Property::VIEWPORT_SIZE:
585 value = GetCurrentViewportSize();
588 case Dali::RenderTask::Property::CLEAR_COLOR:
590 value = GetClearColor();
593 case Dali::RenderTask::Property::REQUIRES_SYNC:
595 value = IsSyncRequired();
601 DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
609 void RenderTask::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
611 switch( animationType )
614 case Animation::BETWEEN:
618 case Dali::RenderTask::Property::VIEWPORT_POSITION:
620 value.Get( mViewportPosition );
623 case Dali::RenderTask::Property::VIEWPORT_SIZE:
625 value.Get( mViewportSize );
628 case Dali::RenderTask::Property::CLEAR_COLOR:
630 value.Get( mClearColor );
633 case Dali::RenderTask::Property::REQUIRES_SYNC:
636 // Nothing to do as not animatable
647 case Dali::RenderTask::Property::VIEWPORT_POSITION:
649 AdjustValue< Vector2 >( mViewportPosition, value );
652 case Dali::RenderTask::Property::VIEWPORT_SIZE:
654 AdjustValue< Vector2 >( mViewportSize, value );
657 case Dali::RenderTask::Property::CLEAR_COLOR:
659 AdjustValue< Vector4 >( mClearColor, value );
662 case Dali::RenderTask::Property::REQUIRES_SYNC:
665 // Nothing to do as not animatable
674 const SceneGraph::PropertyBase* RenderTask::GetSceneObjectAnimatableProperty( Property::Index index ) const
676 const SceneGraph::PropertyBase* property( NULL );
680 case Dali::RenderTask::Property::VIEWPORT_POSITION:
682 property = &GetRenderTaskSceneObject().mViewportPosition;
685 case Dali::RenderTask::Property::VIEWPORT_SIZE:
687 property = &GetRenderTaskSceneObject().mViewportSize;
690 case Dali::RenderTask::Property::CLEAR_COLOR:
692 property = &GetRenderTaskSceneObject().mClearColor;
702 // not our property, ask base
703 property = Object::GetSceneObjectAnimatableProperty( index );
709 const PropertyInputImpl* RenderTask::GetSceneObjectInputProperty( Property::Index index ) const
711 // animatable properties are input as well, Object::GetSceneObjectInputProperty does the same so no need to call it
712 return GetSceneObjectAnimatableProperty( index );
715 bool RenderTask::HasFinished()
717 bool finished = false;
718 const uint32_t counter = GetRenderTaskSceneObject().GetRenderedOnceCounter();
720 if( mRefreshOnceCounter < counter )
723 mRefreshOnceCounter = counter;
726 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::HasFinished()=%s SCRT:%p SC\n", finished?"T":"F", &GetRenderTaskSceneObject());
731 void RenderTask::EmitSignalFinish()
733 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::EmitSignalFinish(this:%p)\n", this);
735 if( !mSignalFinished.Empty() )
737 Dali::RenderTask handle( this );
738 mSignalFinished.Emit(handle );
742 Dali::RenderTask::RenderTaskSignalType& RenderTask::FinishedSignal()
744 return mSignalFinished;
747 bool RenderTask::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
749 bool connected( true );
750 RenderTask* renderTask = static_cast< RenderTask* >(object); // TypeRegistry guarantees that this is the correct type.
752 if ( 0 == strcmp( signalName.c_str(), SIGNAL_FINISHED ) )
754 renderTask->FinishedSignal().Connect( tracker, functor );
758 // signalName does not match any signal
765 RenderTask::RenderTask( const SceneGraph::RenderTask* sceneObject, RenderTaskList& renderTaskList )
766 : Object( sceneObject ),
767 mSourceActor( nullptr ),
768 mCameraActor( nullptr ),
769 mInputMappingActor(),
770 mRenderTaskList( renderTaskList ),
771 mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
772 mViewportPosition( Vector2::ZERO ),
773 mViewportSize( Vector2::ZERO ),
774 mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
775 mRefreshOnceCounter( 0u ),
776 mScreenToFrameBufferFunction( Dali::RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION ),
777 mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
778 mInputEnabled( Dali::RenderTask::DEFAULT_INPUT_ENABLED ),
779 mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
780 mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE ),
781 mRequiresSync( false )
783 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::RenderTask(this:%p)\n", this);
784 // scene object handles observation of source and camera
787 RenderTask::~RenderTask()
789 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::~RenderTask(this:%p)\n", this);
790 // scene object deletion is handled by our parent
791 // scene object handles observation of source and camera
794 } // namespace Internal