2 * Copyright (c) 2018 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, 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, SceneGraph::RenderTaskList& parentSceneObject )
76 // create scene object first so it's guaranteed to exist for the event side
77 auto sceneObject = SceneGraph::RenderTask::New();
78 OwnerPointer< SceneGraph::RenderTask > transferOwnership( sceneObject );
79 // pass the pointer to base for message passing
80 RenderTaskPtr task( new RenderTask( sceneObject ) );
81 // transfer scene object ownership to update manager
82 AddTaskMessage( task->GetEventThreadServices(), parentSceneObject, transferOwnership );
84 // Set the default source & camera actors
85 task->SetSourceActor( sourceActor );
86 task->SetCameraActor( cameraActor );
88 // no need for additional messages as scene objects defaults match ours
92 void RenderTask::SetSourceActor( Actor* actor )
97 SetSourceNodeMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), &mSourceActor->GetNode() );
101 SetSourceNodeMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), nullptr );
103 // set the actor on exclusive container for hit testing
104 const Stage* stage = Stage::GetCurrent();
107 stage->GetRenderTaskList().SetExclusive( this, mExclusive );
111 Actor* RenderTask::GetSourceActor() const
116 void RenderTask::SetExclusive( bool exclusive )
118 if ( mExclusive != exclusive )
120 mExclusive = exclusive;
122 const Stage* stage = Stage::GetCurrent();
125 stage->GetRenderTaskList().SetExclusive( this, exclusive );
128 // scene object is being used in a separate thread; queue a message to set the value
129 SetExclusiveMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), mExclusive );
133 bool RenderTask::IsExclusive() const
138 void RenderTask::SetInputEnabled( bool enabled )
140 mInputEnabled = enabled;
143 bool RenderTask::GetInputEnabled() const
145 return mInputEnabled;
148 void RenderTask::SetCameraActor( CameraActor* cameraActor )
150 mCameraActor = cameraActor;
153 SetCameraMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), &mCameraActor->GetNode(), mCameraActor->GetCamera() );
157 SetCameraMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), nullptr, nullptr );
161 CameraActor* RenderTask::GetCameraActor() const
166 void RenderTask::SetTargetFrameBuffer( FrameBufferImagePtr image )
168 mFrameBufferImage = image;
169 FrameBuffer* frameBufferPtr( NULL );
172 frameBufferPtr = image->GetFrameBuffer();
175 SetFrameBuffer( frameBufferPtr );
178 void RenderTask::SetFrameBuffer( FrameBufferPtr frameBuffer )
180 mFrameBuffer = frameBuffer;
181 Render::FrameBuffer* renderFrameBufferPtr( NULL );
184 renderFrameBufferPtr = mFrameBuffer->GetRenderObject();
187 SetFrameBufferMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), renderFrameBufferPtr );
190 FrameBuffer* RenderTask::GetFrameBuffer() const
192 return mFrameBuffer.Get();
195 FrameBufferImage* RenderTask::GetTargetFrameBuffer() const
197 return mFrameBufferImage.Get();
200 void RenderTask::SetScreenToFrameBufferFunction( ScreenToFrameBufferFunction conversionFunction )
202 mScreenToFrameBufferFunction = conversionFunction;
205 RenderTask::ScreenToFrameBufferFunction RenderTask::GetScreenToFrameBufferFunction() const
207 return mScreenToFrameBufferFunction;
210 void RenderTask::SetScreenToFrameBufferMappingActor( Dali::Actor& mappingActor )
212 mInputMappingActor = WeakHandle<Dali::Actor>( mappingActor );
215 Dali::Actor RenderTask::GetScreenToFrameBufferMappingActor() const
217 return mInputMappingActor.GetHandle();
220 void RenderTask::SetViewportPosition(const Vector2& value)
222 mViewportPosition = value;
224 BakeViewportPositionMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), value );
227 Vector2 RenderTask::GetCurrentViewportPosition() const
229 return GetRenderTaskSceneObject().GetViewportPosition( GetEventThreadServices().GetEventBufferIndex() );
232 void RenderTask::SetViewportSize(const Vector2& value)
234 mViewportSize = value;
236 BakeViewportSizeMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), value );
239 Vector2 RenderTask::GetCurrentViewportSize() const
241 return GetRenderTaskSceneObject().GetViewportSize( GetEventThreadServices().GetEventBufferIndex() );
244 void RenderTask::SetViewport( const Viewport& viewport )
246 SetViewportPosition( Vector2( static_cast<float>( viewport.x ), static_cast<float>( viewport.y ) ) );
247 SetViewportSize( Vector2( static_cast<float>( viewport.width ), static_cast<float>( viewport.height ) ) );
250 void RenderTask::GetViewport( Viewport& viewPort ) const
252 BufferIndex bufferIndex = GetEventThreadServices().GetEventBufferIndex();
254 if( !GetRenderTaskSceneObject().GetViewportEnabled( bufferIndex ) )
256 if ( mFrameBufferImage )
258 viewPort.x = viewPort.y = 0;
259 viewPort.width = mFrameBufferImage->GetWidth();
260 viewPort.height = mFrameBufferImage->GetHeight();
264 Internal::Stage* stage = Internal::Stage::GetCurrent();
267 Vector2 size( stage->GetSize() );
268 viewPort.x = viewPort.y = 0;
269 viewPort.width = static_cast<int32_t>( size.width ); // truncated
270 viewPort.height = static_cast<int32_t>( size.height ); // truncated
276 const Vector2& position = GetRenderTaskSceneObject().GetViewportPosition(bufferIndex);
277 const Vector2& size = GetRenderTaskSceneObject().GetViewportSize(bufferIndex);
278 viewPort.x = static_cast<int32_t>( position.x ); // truncated
279 viewPort.y = static_cast<int32_t>( position.y ); // truncated
280 viewPort.width = static_cast<int32_t>( size.width ); // truncated
281 viewPort.height = static_cast<int32_t>( size.height ); // truncated
285 void RenderTask::SetClearColor( const Vector4& color )
287 if ( mClearColor != color )
291 // scene object is being used in a separate thread; queue a message to set the value
292 BakeClearColorMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), color );
296 const Vector4& RenderTask::GetClearColor() const
298 return GetRenderTaskSceneObject().GetClearColor( GetEventThreadServices().GetEventBufferIndex() );
301 void RenderTask::SetSyncRequired( bool requiresSync )
303 if( mRequiresSync != requiresSync )
305 mRequiresSync = requiresSync;
307 // scene object is being used in a separate thread; queue a message to set the value
308 SetSyncRequiredMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), requiresSync );
312 bool RenderTask::IsSyncRequired() const
314 return mRequiresSync;
317 void RenderTask::SetClearEnabled( bool enabled )
319 if ( mClearEnabled != enabled )
321 mClearEnabled = enabled;
323 // scene object is being used in a separate thread; queue a message to set the value
324 SetClearEnabledMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), mClearEnabled );
328 bool RenderTask::GetClearEnabled() const
330 return mClearEnabled;
333 void RenderTask::SetCullMode( bool mode )
335 if ( mCullMode != mode )
339 // scene object is being used in a separate thread; queue a message to set the value
340 SetCullModeMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), mCullMode );
344 bool RenderTask::GetCullMode() const
349 void RenderTask::SetRefreshRate( uint32_t refreshRate )
351 DALI_LOG_TRACE_METHOD_FMT(gLogRender, "this:%p rate:%d\n", this, refreshRate);
352 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::SetRefreshRate(this:%p, %d)\n", this, refreshRate);
354 mRefreshRate = refreshRate; // cached for GetRefreshRate()
356 // Note - even when refreshRate is the same as mRefreshRate, a message should be sent
358 // sceneObject is being used in a separate thread; queue a message to set the value
359 SetRefreshRateMessage( GetEventThreadServices(), GetRenderTaskSceneObject(), refreshRate );
362 uint32_t RenderTask::GetRefreshRate() const
367 bool RenderTask::IsHittable( Vector2& screenCoords ) const
369 // True when input is enabled, source & camera actor are valid
370 bool inputEnabled( false );
372 Actor* sourceActor = GetSourceActor();
373 CameraActor* cameraActor = GetCameraActor();
375 if ( mInputEnabled &&
376 nullptr != sourceActor &&
377 sourceActor->OnStage() &&
378 nullptr != cameraActor &&
379 cameraActor->OnStage() )
381 // If the actors are rendered off-screen, then the screen coordinates must be converted
382 // and the conversion function will tell us if they are inside or outside
383 if ( TranslateCoordinates( screenCoords ) )
385 // This is a suitable render-task for input handling
393 bool RenderTask::TranslateCoordinates( Vector2& screenCoords ) const
395 // return true for on-screen tasks
397 // If the actors are rendered off-screen, then the screen coordinates must be converted
398 // the function should only be called for offscreen tasks
399 Dali::Actor mappingActor = GetScreenToFrameBufferMappingActor();
401 if( mFrameBufferImage && mappingActor )
403 Internal::Actor* inputMappingActor = &GetImplementation( mappingActor );
404 CameraActor* localCamera = GetCameraActor();
405 StagePtr stage = Stage::GetCurrent();
408 CameraActor& defaultCamera = stage->GetDefaultCameraActor();
412 Vector2 size( stage->GetSize() );
413 viewport.x = viewport.y = 0;
414 viewport.width = static_cast<int32_t>( size.width ); // truncated
415 viewport.height = static_cast<int32_t>( size.height ); // truncated
417 float localX, localY;
418 inside = inputMappingActor->ScreenToLocal(defaultCamera.GetViewMatrix(), defaultCamera.GetProjectionMatrix(), viewport, localX, localY, screenCoords.x, screenCoords.y);
419 Vector3 actorSize = inputMappingActor->GetCurrentSize();
420 if( inside && localX >= 0.f && localX <= actorSize.x && localY >= 0.f && localY <= actorSize.y)
422 screenCoords.x = localX;
423 screenCoords.y = localY;
436 else if ( mFrameBufferImage && mScreenToFrameBufferFunction )
438 inside = mScreenToFrameBufferFunction( screenCoords );
443 bool RenderTask::WorldToViewport(const Vector3 &position, float& viewportX, float& viewportY) const
445 CameraActor* cam = GetCameraActor();
447 Vector4 pos(position);
450 Vector4 viewportPosition;
453 GetViewport( viewport );
455 bool ok = ProjectFull(pos,
456 cam->GetViewMatrix(),
457 cam->GetProjectionMatrix(),
458 static_cast<float>( viewport.x ), // truncated
459 static_cast<float>( viewport.y ), // truncated
460 static_cast<float>( viewport.width ), // truncated
461 static_cast<float>( viewport.height ), // truncated
465 viewportX = viewportPosition.x;
466 viewportY = viewportPosition.y;
472 bool RenderTask::ViewportToLocal(Actor* actor, float viewportX, float viewportY, float &localX, float &localY) const
474 return actor->ScreenToLocal( *this, localX, localY, viewportX, viewportY );
477 const SceneGraph::RenderTask& RenderTask::GetRenderTaskSceneObject() const
479 return *static_cast<const SceneGraph::RenderTask*>( mUpdateObject );
482 /********************************************************************************
483 ******************************** PROPERTY METHODS **************************
484 ********************************************************************************/
486 void RenderTask::SetDefaultProperty( Property::Index index, const Property::Value& property )
490 case Dali::RenderTask::Property::VIEWPORT_POSITION:
492 SetViewportPosition( property.Get<Vector2>() );
495 case Dali::RenderTask::Property::VIEWPORT_SIZE:
497 SetViewportSize( property.Get<Vector2>() );
500 case Dali::RenderTask::Property::CLEAR_COLOR:
502 SetClearColor( property.Get<Vector4>() );
505 case Dali::RenderTask::Property::REQUIRES_SYNC:
507 SetSyncRequired( property.Get<bool>() );
518 Property::Value RenderTask::GetDefaultProperty(Property::Index index) const
520 Property::Value value;
525 case Dali::RenderTask::Property::VIEWPORT_POSITION:
527 value = mViewportPosition;
530 case Dali::RenderTask::Property::VIEWPORT_SIZE:
532 value = mViewportSize;
535 case Dali::RenderTask::Property::CLEAR_COLOR:
540 case Dali::RenderTask::Property::REQUIRES_SYNC:
542 value = IsSyncRequired();
548 DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
556 Property::Value RenderTask::GetDefaultPropertyCurrentValue( Property::Index index ) const
558 Property::Value value;
563 case Dali::RenderTask::Property::VIEWPORT_POSITION:
565 value = GetCurrentViewportPosition();
568 case Dali::RenderTask::Property::VIEWPORT_SIZE:
570 value = GetCurrentViewportSize();
573 case Dali::RenderTask::Property::CLEAR_COLOR:
575 value = GetClearColor();
578 case Dali::RenderTask::Property::REQUIRES_SYNC:
580 value = IsSyncRequired();
586 DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
594 void RenderTask::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
596 switch( animationType )
599 case Animation::BETWEEN:
603 case Dali::RenderTask::Property::VIEWPORT_POSITION:
605 value.Get( mViewportPosition );
608 case Dali::RenderTask::Property::VIEWPORT_SIZE:
610 value.Get( mViewportSize );
613 case Dali::RenderTask::Property::CLEAR_COLOR:
615 value.Get( mClearColor );
618 case Dali::RenderTask::Property::REQUIRES_SYNC:
621 // Nothing to do as not animatable
632 case Dali::RenderTask::Property::VIEWPORT_POSITION:
634 AdjustValue< Vector2 >( mViewportPosition, value );
637 case Dali::RenderTask::Property::VIEWPORT_SIZE:
639 AdjustValue< Vector2 >( mViewportSize, value );
642 case Dali::RenderTask::Property::CLEAR_COLOR:
644 AdjustValue< Vector4 >( mClearColor, value );
647 case Dali::RenderTask::Property::REQUIRES_SYNC:
650 // Nothing to do as not animatable
659 const SceneGraph::PropertyBase* RenderTask::GetSceneObjectAnimatableProperty( Property::Index index ) const
661 const SceneGraph::PropertyBase* property( NULL );
665 case Dali::RenderTask::Property::VIEWPORT_POSITION:
667 property = &GetRenderTaskSceneObject().mViewportPosition;
670 case Dali::RenderTask::Property::VIEWPORT_SIZE:
672 property = &GetRenderTaskSceneObject().mViewportSize;
675 case Dali::RenderTask::Property::CLEAR_COLOR:
677 property = &GetRenderTaskSceneObject().mClearColor;
687 // not our property, ask base
688 property = Object::GetSceneObjectAnimatableProperty( index );
694 const PropertyInputImpl* RenderTask::GetSceneObjectInputProperty( Property::Index index ) const
696 // animatable properties are input as well, Object::GetSceneObjectInputProperty does the same so no need to call it
697 return GetSceneObjectAnimatableProperty( index );
700 bool RenderTask::HasFinished()
702 bool finished = false;
703 const uint32_t counter = GetRenderTaskSceneObject().GetRenderedOnceCounter();
705 if( mRefreshOnceCounter < counter )
708 mRefreshOnceCounter = counter;
711 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::HasFinished()=%s SCRT:%p SC\n", finished?"T":"F", &GetRenderTaskSceneObject());
716 void RenderTask::EmitSignalFinish()
718 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::EmitSignalFinish(this:%p)\n", this);
720 if( !mSignalFinished.Empty() )
722 Dali::RenderTask handle( this );
723 mSignalFinished.Emit(handle );
727 Dali::RenderTask::RenderTaskSignalType& RenderTask::FinishedSignal()
729 return mSignalFinished;
732 bool RenderTask::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
734 bool connected( true );
735 RenderTask* renderTask = static_cast< RenderTask* >(object); // TypeRegistry guarantees that this is the correct type.
737 if ( 0 == strcmp( signalName.c_str(), SIGNAL_FINISHED ) )
739 renderTask->FinishedSignal().Connect( tracker, functor );
743 // signalName does not match any signal
750 RenderTask::RenderTask( const SceneGraph::RenderTask* sceneObject )
751 : Object( sceneObject ),
752 mSourceActor( nullptr ),
753 mCameraActor( nullptr ),
754 mInputMappingActor(),
755 mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
756 mViewportPosition( Vector2::ZERO ),
757 mViewportSize( Vector2::ZERO ),
758 mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
759 mRefreshOnceCounter( 0u ),
760 mScreenToFrameBufferFunction( Dali::RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION ),
761 mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
762 mInputEnabled( Dali::RenderTask::DEFAULT_INPUT_ENABLED ),
763 mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
764 mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE ),
765 mRequiresSync( false )
767 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::RenderTask(this:%p)\n", this);
768 // scene object handles observation of source and camera
771 RenderTask::~RenderTask()
773 DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::~RenderTask(this:%p)\n", this);
774 // scene object deletion is handled by our parent
775 // scene object handles observation of source and camera
778 } // namespace Internal