2 * Copyright (c) 2015 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/update/render-tasks/scene-graph-render-task.h>
22 #include <dali/public-api/math/matrix.h>
23 #include <dali/internal/update/controllers/render-message-dispatcher.h>
24 #include <dali/internal/update/resources/resource-manager.h>
25 #include <dali/internal/update/nodes/node.h>
26 #include <dali/internal/render/common/render-instruction.h>
27 #include <dali/internal/render/common/render-tracker.h>
29 #include <dali/internal/update/render-tasks/scene-graph-render-task-debug.h>
39 RenderTask* RenderTask::New()
41 return new RenderTask();
44 RenderTask::~RenderTask()
46 // Remove exclusive flag from source node
49 if( mSourceNode && (this == mSourceNode->GetExclusiveRenderTask() ) )
51 mSourceNode->SetExclusiveRenderTask( NULL );
54 if( mRenderSyncTracker )
56 mRenderMessageDispatcher->RemoveRenderTracker( *mRenderSyncTracker );
60 void RenderTask::Initialize( RenderMessageDispatcher& renderMessageDispatcher, ResourceManager& resourceManager )
62 mRenderMessageDispatcher = &renderMessageDispatcher;
63 mResourceManager = &resourceManager;
66 void RenderTask::SetSourceNode( Node* node )
68 // Remove exclusive flag from the old node, if necessary
70 this == mSourceNode->GetExclusiveRenderTask() )
72 mSourceNode->SetExclusiveRenderTask( NULL );
77 if ( mSourceNode && mExclusive )
79 mSourceNode->SetExclusiveRenderTask( this );
83 Node* RenderTask::GetSourceNode() const
88 void RenderTask::SetExclusive( bool exclusive )
90 mExclusive = exclusive;
96 mSourceNode->SetExclusiveRenderTask( this );
98 else if ( this == mSourceNode->GetExclusiveRenderTask() )
100 mSourceNode->SetExclusiveRenderTask( NULL );
105 bool RenderTask::IsExclusive() const
110 void RenderTask::SetCameraNode( Node* cameraNode )
113 if( cameraNode != mCameraNode )
117 // get attachment. when camera node is changed we will get a message from event thread object
118 // so no need to observe the node here
119 mCameraAttachment = dynamic_cast< CameraAttachment* >( &cameraNode->GetAttachment() );
120 DALI_ASSERT_DEBUG( mCameraAttachment && "Camera without attachment" );
122 mCameraNode = cameraNode;
126 void RenderTask::SetFrameBufferId( unsigned int resourceId, bool isNativeFBO )
128 // note that we might already have a RenderTracker
129 mTargetIsNativeFramebuffer = isNativeFBO;
130 mFrameBufferResourceId = resourceId;
133 unsigned int RenderTask::GetFrameBufferId() const
135 return mFrameBufferResourceId;
138 bool RenderTask::QueryViewport( BufferIndex bufferIndex, Viewport& viewport ) const
140 if( ! GetViewportEnabled( bufferIndex ) )
145 viewport.x = mViewportPosition[bufferIndex].x;
146 viewport.y = mViewportPosition[bufferIndex].y;
147 viewport.width = mViewportSize[bufferIndex].width;
148 viewport.height = mViewportSize[bufferIndex].height;
153 void RenderTask::SetClearColor( BufferIndex updateBufferIndex, const Vector4& value )
155 mClearColor.Set( updateBufferIndex, value );
158 const Vector4& RenderTask::GetClearColor( BufferIndex bufferIndex ) const
160 return mClearColor[bufferIndex];
163 void RenderTask::BakeClearColor( BufferIndex updateBufferIndex, const Vector4& value )
165 mClearColor.Bake( updateBufferIndex, value );
168 void RenderTask::SetClearEnabled( bool enabled )
170 mClearEnabled = enabled;
173 bool RenderTask::GetClearEnabled() const
175 return mClearEnabled;
178 void RenderTask::SetCullMode( bool mode )
183 bool RenderTask::GetCullMode() const
188 void RenderTask::SetRefreshRate( unsigned int refreshRate )
190 DALI_LOG_TRACE_METHOD_FMT(gRenderTaskLogFilter, "this:%p RefreshRate:%d\n", this, refreshRate);
192 mRefreshRate = refreshRate;
194 if( mRefreshRate > 0 )
196 mState = RENDER_CONTINUOUSLY;
200 mState = RENDER_ONCE_WAITING_FOR_RESOURCES;
201 mWaitingToRender = true;
202 mNotifyTrigger = false;
203 // need at least on other render on the FBO
204 mResourceManager->SetFrameBufferBeenRenderedTo( mFrameBufferResourceId, false );
210 unsigned int RenderTask::GetRefreshRate() const
215 bool RenderTask::ReadyToRender( BufferIndex updateBufferIndex )
217 // If the source node of the render task is invisible we should still render
218 // We want the render task to complete and possible clear colors to happen
221 if ( NULL == mSourceNode ||
222 ( !mSourceNode->IsRoot() && NULL == mSourceNode->GetParent() ) )
224 TASK_LOG_FMT(Debug::General, " =F No source actor FC:%d\n", mFrameCounter );
226 // Source node is missing or disconnected
231 if ( NULL == mCameraNode ||
232 NULL == mCameraNode->GetParent() ||
233 NULL == mCameraAttachment )
235 // Camera node is missing or disconnected
236 TASK_LOG_FMT(Debug::General, " =F No Camera FC:%d\n", mFrameCounter );
241 mCameraAttachment->Update( updateBufferIndex, *mCameraNode );
243 TASK_LOG_FMT(Debug::General, " =T (FBO ID:%d) FC:%d\n", mFrameBufferResourceId , mFrameCounter );
247 bool RenderTask::IsRenderRequired()
249 bool required = false;
253 case RENDER_CONTINUOUSLY:
255 required = (mFrameCounter == 0);
258 case RENDER_ONCE_WAITING_FOR_RESOURCES:
270 TASK_LOG_FMT( Debug::General, " State:%s = %s\n", STATE_STRING(mState), required?"T":"F" );
275 void RenderTask::SetResourcesFinished( bool resourcesFinished )
277 // resourcesFinished tells us that this render task will render to its FBO
278 mResourcesFinished = resourcesFinished;
279 if( mResourcesFinished )
281 mResourceManager->SetFrameBufferBeenRenderedTo( mFrameBufferResourceId, true );
285 // Called every frame regardless of whether render was required.
286 // If render was not required, ignore resourcesFinished.
287 void RenderTask::UpdateState()
289 TASK_LOG_FMT( Debug::General, "(mResourcesFinished:%s) FC:%d State:%s RR:%d\n", mResourcesFinished?"T":"F", mFrameCounter, STATE_STRING(mState), mRefreshRate );
293 case RENDER_CONTINUOUSLY:
295 if( mRefreshRate != Dali::RenderTask::REFRESH_ALWAYS )
297 if( mFrameCounter == 0 )
299 if( mResourcesFinished )
301 ++mFrameCounter; // Only start skipping frames when resources are loaded
304 else // Continue counting to skip frames
307 if( mFrameCounter >= mRefreshRate )
317 case RENDER_ONCE_WAITING_FOR_RESOURCES:
319 if( mResourcesFinished )
321 mState = RENDERED_ONCE;
328 mWaitingToRender = true;
329 mNotifyTrigger = false;
330 if( mFrameBufferResourceId > 0 )
332 if( mTargetIsNativeFramebuffer )
334 if( mRenderSyncTracker && mRenderSyncTracker->IsSynced() )
336 mWaitingToRender = false;
337 mNotifyTrigger = true;
340 else if( mResourceManager->HasFrameBufferBeenRenderedTo( mFrameBufferResourceId ) )
342 mWaitingToRender = false;
343 mNotifyTrigger = true;
348 mNotifyTrigger = true;
358 TASK_LOG_FMT( Debug::General, " EXIT FC:%d State:%s Notify:%s\n", mFrameCounter, STATE_STRING(mState), mNotifyTrigger?"T":"F");
361 bool RenderTask::IsWaitingToRender()
363 TASK_LOG_FMT(Debug::Verbose, " State:%s waiting:%s \n", STATE_STRING(mState), mWaitingToRender?"T":"F");
364 return mWaitingToRender;
367 bool RenderTask::HasRendered()
370 if( mNotifyTrigger == true )
372 ++mRenderedOnceCounter;
373 mState = RENDERED_ONCE_AND_NOTIFIED;
374 mNotifyTrigger = false;
378 TASK_LOG_FMT(Debug::Verbose, " State:%s hasRendered:%s \n", STATE_STRING(mState), notify?"T":"F");
382 unsigned int RenderTask::GetRenderedOnceCounter() const
384 return mRenderedOnceCounter;
388 const Matrix& RenderTask::GetViewMatrix( BufferIndex bufferIndex ) const
390 DALI_ASSERT_DEBUG( NULL != mCameraAttachment );
392 return mCameraAttachment->GetViewMatrix( bufferIndex );
395 SceneGraph::CameraAttachment& RenderTask::GetCameraAttachment() const
397 DALI_ASSERT_DEBUG( NULL != mCameraAttachment );
398 return *mCameraAttachment;
401 const Matrix& RenderTask::GetProjectionMatrix( BufferIndex bufferIndex ) const
403 DALI_ASSERT_DEBUG( NULL != mCameraAttachment );
405 return mCameraAttachment->GetProjectionMatrix( bufferIndex );
408 void RenderTask::PrepareRenderInstruction( RenderInstruction& instruction, BufferIndex updateBufferIndex )
410 DALI_ASSERT_DEBUG( NULL != mCameraAttachment );
412 TASK_LOG(Debug::General);
415 bool viewportSet = QueryViewport( updateBufferIndex, viewport );
417 instruction.Reset( mCameraAttachment,
419 viewportSet ? &viewport : NULL,
420 mClearEnabled ? &GetClearColor( updateBufferIndex ) : NULL );
422 if( mTargetIsNativeFramebuffer && mRequiresSync &&
423 mRefreshRate == Dali::RenderTask::REFRESH_ONCE &&
426 // create tracker if one doesn't yet exist.
427 if( !mRenderSyncTracker )
429 mRenderSyncTracker = new Render::RenderTracker();
430 mRenderMessageDispatcher->AddRenderTracker( *mRenderSyncTracker );
432 instruction.mRenderTracker = mRenderSyncTracker;
436 // no sync needed, texture FBOs are "ready" the same frame they are rendered to
437 instruction.mRenderTracker = NULL;
441 bool RenderTask::ViewMatrixUpdated()
444 if( mCameraAttachment )
446 retval = mCameraAttachment->ViewMatrixUpdated();
451 void RenderTask::SetViewportPosition( BufferIndex updateBufferIndex, const Vector2& value )
453 mViewportPosition.Set( updateBufferIndex, value );
456 const Vector2& RenderTask::GetViewportPosition( BufferIndex bufferIndex ) const
458 return mViewportPosition[bufferIndex];
461 void RenderTask::BakeViewportPosition( BufferIndex updateBufferIndex, const Vector2& value )
463 mViewportPosition.Bake( updateBufferIndex, value );
466 void RenderTask::SetViewportSize( BufferIndex updateBufferIndex, const Vector2& value )
468 mViewportSize.Set( updateBufferIndex, value );
471 const Vector2& RenderTask::GetViewportSize( BufferIndex bufferIndex ) const
473 return mViewportSize[bufferIndex];
476 void RenderTask::BakeViewportSize( BufferIndex updateBufferIndex, const Vector2& value )
478 mViewportSize.Bake( updateBufferIndex, value );
481 bool RenderTask::GetViewportEnabled( BufferIndex bufferIndex ) const
483 if(fabsf(mViewportPosition[bufferIndex].x) > Math::MACHINE_EPSILON_1 ||
484 fabsf(mViewportPosition[bufferIndex].y) > Math::MACHINE_EPSILON_1 ||
485 fabsf(mViewportSize[bufferIndex].width) > Math::MACHINE_EPSILON_1 ||
486 fabsf(mViewportSize[bufferIndex].height) > Math::MACHINE_EPSILON_1)
494 Node* RenderTask::GetCamera() const
499 void RenderTask::SetSyncRequired( bool requiresSync )
501 mRequiresSync = requiresSync;
504 void RenderTask::ResetDefaultProperties( BufferIndex updateBufferIndex )
506 // Reset default properties
507 mViewportPosition.ResetToBaseValue( updateBufferIndex );
508 mViewportSize.ResetToBaseValue( updateBufferIndex );
509 mClearColor.ResetToBaseValue( updateBufferIndex );
512 RenderTask::RenderTask()
513 : mViewportPosition( Vector2::ZERO),
514 mViewportSize( Vector2::ZERO),
515 mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
516 mRenderMessageDispatcher( NULL ),
517 mResourceManager( NULL ),
518 mRenderSyncTracker( NULL ),
521 mCameraAttachment( NULL ),
522 mFrameBufferResourceId( 0 ),
523 mResourcesFinished( false ),
524 mWaitingToRender( false ),
525 mNotifyTrigger( false ),
526 mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
527 mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
528 mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE ),
529 mRenderTarget( NULL ),
530 mState( (Dali::RenderTask::DEFAULT_REFRESH_RATE == Dali::RenderTask::REFRESH_ALWAYS)
531 ? RENDER_CONTINUOUSLY
532 : RENDER_ONCE_WAITING_FOR_RESOURCES ),
533 mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
535 mRenderedOnceCounter( 0u ),
536 mTargetIsNativeFramebuffer( false ),
537 mRequiresSync( false )
541 } // namespace SceneGraph
543 } // namespace Internal