2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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.
18 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
21 #include <dali/public-api/math/matrix.h>
22 #include <dali/internal/update/resources/resource-manager.h>
23 #include <dali/internal/update/resources/complete-status-manager.h>
24 #include <dali/internal/update/nodes/node.h>
25 #include <dali/internal/update/node-attachments/scene-graph-camera-attachment.h>
26 #include <dali/internal/render/common/render-instruction.h>
28 #include <dali/internal/update/render-tasks/scene-graph-render-task-debug.h>
32 const unsigned int NUM_FRAMES_BEFORE_NOTIFY_FINISHED(3);
33 const unsigned int COUNTDOWN_COMPLETE(-1);
34 } // anonymous namespace
44 RenderTask* RenderTask::New()
46 return new RenderTask();
49 RenderTask::~RenderTask()
51 // Remove exclusive flag from source node
54 if( mSourceNode && (this == mSourceNode->GetExclusiveRenderTask() ) )
56 mSourceNode->SetExclusiveRenderTask( NULL );
59 if( mFrameBufferResourceId )
61 mCompleteStatusManager->StopTrackingResource( mFrameBufferResourceId );
65 void RenderTask::SetSourceNode( Node* node )
67 // Remove exclusive flag from the old node, if necessary
69 this == mSourceNode->GetExclusiveRenderTask() )
71 mSourceNode->SetExclusiveRenderTask( NULL );
76 if ( mSourceNode && mExclusive )
78 mSourceNode->SetExclusiveRenderTask( this );
82 Node* RenderTask::GetSourceNode() const
87 void RenderTask::SetExclusive( bool exclusive )
89 mExclusive = exclusive;
95 mSourceNode->SetExclusiveRenderTask( this );
97 else if ( this == mSourceNode->GetExclusiveRenderTask() )
99 mSourceNode->SetExclusiveRenderTask( NULL );
104 bool RenderTask::IsExclusive() const
109 void RenderTask::SetCameraNode( Node* cameraNode )
112 if( cameraNode != mCameraNode )
116 // get attachment. when camera node is changed we will get a message from event thread object
117 // so no need to observe the node here
118 mCameraAttachment = dynamic_cast< CameraAttachment* >( &cameraNode->GetAttachment() );
119 DALI_ASSERT_DEBUG( mCameraAttachment && "Camera without attachment" );
121 mCameraNode = cameraNode;
125 Node* RenderTask::GetCameraNode() const
130 void RenderTask::SetFrameBufferId( unsigned int resourceId )
132 if ( mFrameBufferResourceId != resourceId )
134 DALI_ASSERT_DEBUG(mCompleteStatusManager && "Complete status tracker is null");
135 if( mCompleteStatusManager )
137 if( resourceId && mState == RENDER_ONCE_WAITING_FOR_RESOURCES )
139 mCompleteStatusManager->TrackResource( resourceId );
142 if( mFrameBufferResourceId )
144 mCompleteStatusManager->StopTrackingResource( mFrameBufferResourceId );
148 mFrameBufferResourceId = resourceId;
152 unsigned int RenderTask::GetFrameBufferId() const
154 return mFrameBufferResourceId;
157 bool RenderTask::QueryViewport( BufferIndex bufferIndex, Viewport& viewport ) const
159 if( ! GetViewportEnabled( bufferIndex ) )
164 viewport.x = mViewportPosition[bufferIndex].x;
165 viewport.y = mViewportPosition[bufferIndex].y;
166 viewport.width = mViewportSize[bufferIndex].width;
167 viewport.height = mViewportSize[bufferIndex].height;
172 void RenderTask::SetClearColor( BufferIndex updateBufferIndex, const Vector4& value )
174 mClearColor.Set( updateBufferIndex, value );
177 const Vector4& RenderTask::GetClearColor( BufferIndex bufferIndex ) const
179 return mClearColor[bufferIndex];
182 void RenderTask::BakeClearColor( BufferIndex updateBufferIndex, const Vector4& value )
184 mClearColor.Bake( updateBufferIndex, value );
187 void RenderTask::SetClearEnabled( bool enabled )
189 mClearEnabled = enabled;
192 bool RenderTask::GetClearEnabled() const
194 return mClearEnabled;
197 void RenderTask::SetRefreshRate( unsigned int refreshRate )
199 DALI_LOG_TRACE_METHOD_FMT(gRenderTaskLogFilter, "this:%p RefreshRate:%d\n", this, refreshRate);
201 mRefreshRate = refreshRate;
203 if( mRefreshRate > 0 )
205 mState = RENDER_CONTINUOUSLY;
207 if( mFrameBufferResourceId )
209 // Don't need tracking
210 DALI_ASSERT_DEBUG(mCompleteStatusManager && "Ready state tracker is null");
211 if( mCompleteStatusManager != NULL )
213 mCompleteStatusManager->StopTrackingResource( mFrameBufferResourceId );
219 mState = RENDER_ONCE_WAITING_FOR_RESOURCES;
220 mWaitingToRender = true;
221 mNotifyTrigger = false;
223 if( mFrameBufferResourceId )
225 DALI_ASSERT_DEBUG(mCompleteStatusManager && "Ready state tracker is null");
226 if( mCompleteStatusManager != NULL )
228 mCompleteStatusManager->TrackResource( mFrameBufferResourceId );
236 unsigned int RenderTask::GetRefreshRate() const
241 bool RenderTask::ReadyToRender( BufferIndex updateBufferIndex )
243 if ( NULL == mSourceNode ||
244 ( !mSourceNode->IsRoot() && NULL == mSourceNode->GetParent() ) )
246 TASK_LOG_FMT(Debug::General, " =F No source actor FC:%d\n", mFrameCounter );
248 // Source node is missing or disconnected
252 // Check if the source node (root actor) and all its ancestors are visible.
253 if( !mSourceNode->IsFullyVisible( updateBufferIndex ) )
255 TASK_LOG_FMT(Debug::General, " =F No visible source FC:%d\n", mFrameCounter );
259 if ( NULL == mCameraNode ||
260 NULL == mCameraNode->GetParent() ||
261 !mCameraNode->HasAttachment() )
263 // Camera node is missing or disconnected
264 TASK_LOG_FMT(Debug::General, " =F No Camera FC:%d\n", mFrameCounter );
269 TASK_LOG_FMT(Debug::General, " =T (FBO ID:%d) FC:%d\n", mFrameBufferResourceId , mFrameCounter );
273 bool RenderTask::IsRenderRequired()
275 bool required = false;
279 case RENDER_CONTINUOUSLY:
280 required = (mFrameCounter == 0);
283 case RENDER_ONCE_WAITING_FOR_RESOURCES:
292 TASK_LOG_FMT( Debug::General, " State:%s = %s\n", STATE_STRING(mState), required?"T":"F" );
297 // Called every frame regardless of whether render was required.
298 // If render was not required, ignore resourcesFinished.
299 void RenderTask::UpdateState(bool resourcesFinished)
301 TASK_LOG_FMT( Debug::General, "(resourcesFinished:%s) FC:%d State:%s RR:%d\n", resourcesFinished?"T":"F", mFrameCounter, STATE_STRING(mState), mRefreshRate );
305 case RENDER_CONTINUOUSLY:
307 if( mRefreshRate != Dali::RenderTask::REFRESH_ALWAYS )
309 if( mFrameCounter == 0 )
311 if( resourcesFinished )
313 ++mFrameCounter; // Only start missing frames when resources are loaded
316 else // Continue counting to miss frames
319 if( mFrameCounter >= mRefreshRate )
329 case RENDER_ONCE_WAITING_FOR_RESOURCES:
331 if( resourcesFinished )
333 mState = RENDERED_ONCE;
340 if( mFrameBufferResourceId > 0 )
342 // Query if the framebuffer is complete:
343 DALI_ASSERT_DEBUG(mCompleteStatusManager && "Complete status tracker is null");
344 if( mCompleteStatusManager != NULL &&
345 CompleteStatusManager::COMPLETE == mCompleteStatusManager->GetStatus( mFrameBufferResourceId ) )
347 mWaitingToRender = false;
348 mNotifyTrigger = true;
352 mWaitingToRender = true;
357 mWaitingToRender = false;
358 mNotifyTrigger = true;
367 TASK_LOG_FMT( Debug::General, " EXIT FC:%d State:%s Notify:%s\n", mFrameCounter, STATE_STRING(mState), mNotifyTrigger?"T":"F");
370 bool RenderTask::IsWaitingToRender()
372 TASK_LOG_FMT(Debug::Verbose, " State:%s waiting:%s \n", STATE_STRING(mState), mWaitingToRender?"T":"F");
373 return mWaitingToRender;
376 bool RenderTask::HasRendered()
379 if( mNotifyTrigger == true )
381 ++mRenderedOnceCounter;
382 mState = RENDERED_ONCE_AND_NOTIFIED;
383 mNotifyTrigger = false;
387 TASK_LOG_FMT(Debug::Verbose, " State:%s hasRendered:%s \n", STATE_STRING(mState), notify?"T":"F");
391 unsigned int RenderTask::GetRenderedOnceCounter() const
393 return mRenderedOnceCounter;
397 const Matrix& RenderTask::GetViewMatrix( BufferIndex bufferIndex ) const
399 DALI_ASSERT_DEBUG( NULL != mCameraAttachment );
401 return mCameraAttachment->GetViewMatrix( bufferIndex );
404 const Matrix& RenderTask::GetProjectionMatrix( BufferIndex bufferIndex ) const
406 DALI_ASSERT_DEBUG( NULL != mCameraAttachment );
408 return mCameraAttachment->GetProjectionMatrix( bufferIndex );
411 void RenderTask::PrepareRenderInstruction( RenderInstruction& instruction, BufferIndex updateBufferIndex )
413 TASK_LOG(Debug::General);
416 bool viewportSet = QueryViewport( updateBufferIndex, viewport );
418 instruction.Reset( &GetViewMatrix( updateBufferIndex ),
419 &GetProjectionMatrix( updateBufferIndex ),
421 viewportSet ? &viewport : NULL,
422 mClearEnabled ? &GetClearColor( updateBufferIndex ) : NULL );
425 bool RenderTask::ViewMatrixUpdated()
428 if( mCameraAttachment )
430 retval = mCameraAttachment->ViewMatrixUpdated();
435 void RenderTask::SetCompleteStatusManager(CompleteStatusManager* completeStatusManager)
437 mCompleteStatusManager = completeStatusManager;
440 void RenderTask::SetViewportPosition( BufferIndex updateBufferIndex, const Vector2& value )
442 mViewportPosition.Set( updateBufferIndex, value );
445 const Vector2& RenderTask::GetViewportPosition( BufferIndex bufferIndex ) const
447 return mViewportPosition[bufferIndex];
450 void RenderTask::BakeViewportPosition( BufferIndex updateBufferIndex, const Vector2& value )
452 mViewportPosition.Bake( updateBufferIndex, value );
455 void RenderTask::SetViewportSize( BufferIndex updateBufferIndex, const Vector2& value )
457 mViewportSize.Set( updateBufferIndex, value );
460 const Vector2& RenderTask::GetViewportSize( BufferIndex bufferIndex ) const
462 return mViewportSize[bufferIndex];
465 void RenderTask::BakeViewportSize( BufferIndex updateBufferIndex, const Vector2& value )
467 mViewportSize.Bake( updateBufferIndex, value );
470 bool RenderTask::GetViewportEnabled( BufferIndex bufferIndex ) const
472 if(fabsf(mViewportPosition[bufferIndex].x) > Math::MACHINE_EPSILON_1 ||
473 fabsf(mViewportPosition[bufferIndex].y) > Math::MACHINE_EPSILON_1 ||
474 fabsf(mViewportSize[bufferIndex].width) > Math::MACHINE_EPSILON_1 ||
475 fabsf(mViewportSize[bufferIndex].height) > Math::MACHINE_EPSILON_1)
483 void RenderTask::ResetDefaultProperties( BufferIndex updateBufferIndex )
485 // Reset default properties
486 mViewportPosition.ResetToBaseValue( updateBufferIndex );
487 mViewportSize.ResetToBaseValue( updateBufferIndex );
488 mClearColor.ResetToBaseValue( updateBufferIndex );
491 RenderTask::RenderTask()
492 : mViewportPosition( Vector2::ZERO),
493 mViewportSize( Vector2::ZERO),
494 mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
495 mCompleteStatusManager( NULL ),
498 mCameraAttachment( NULL ),
499 mFrameBufferResourceId( 0 ),
500 mWaitingToRender( false ),
501 mNotifyTrigger( false ),
502 mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
503 mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
504 mRenderTarget( NULL ),
505 mState( (Dali::RenderTask::DEFAULT_REFRESH_RATE == Dali::RenderTask::REFRESH_ALWAYS)
506 ? RENDER_CONTINUOUSLY
507 : RENDER_ONCE_WAITING_FOR_RESOURCES ),
508 mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
510 mRenderedOnceCounter( 0u )
514 } // namespace SceneGraph
516 } // namespace Internal