2 * Copyright (c) 2020 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/render/common/render-manager.h>
25 #include <dali/public-api/actors/sampling.h>
26 #include <dali/public-api/common/dali-common.h>
27 #include <dali/public-api/common/stage.h>
28 #include <dali/public-api/render-tasks/render-task.h>
29 #include <dali/devel-api/threading/thread-pool.h>
30 #include <dali/integration-api/debug.h>
31 #include <dali/integration-api/core.h>
32 #include <dali/integration-api/gl-context-helper-abstraction.h>
33 #include <dali/internal/common/owner-pointer.h>
34 #include <dali/internal/event/common/scene-impl.h>
35 #include <dali/internal/render/common/render-algorithms.h>
36 #include <dali/internal/render/common/render-debug.h>
37 #include <dali/internal/render/common/render-tracker.h>
38 #include <dali/internal/render/common/render-instruction-container.h>
39 #include <dali/internal/render/common/render-instruction.h>
40 #include <dali/internal/render/gl-resources/context.h>
41 #include <dali/internal/render/queue/render-queue.h>
42 #include <dali/internal/render/renderers/render-frame-buffer.h>
43 #include <dali/internal/render/renderers/render-geometry.h>
44 #include <dali/internal/render/renderers/render-renderer.h>
45 #include <dali/internal/render/renderers/render-sampler.h>
46 #include <dali/internal/render/shaders/program-controller.h>
47 #include <dali/internal/update/common/scene-graph-scene.h>
58 #if defined(DEBUG_ENABLED)
61 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RENDER_MANAGER" );
62 } // unnamed namespace
67 DirtyRect(Node* node, Render::Renderer* renderer, int frame, Rect<int>& rect)
85 bool operator<(const DirtyRect& rhs) const
89 if (renderer == rhs.renderer)
91 return frame > rhs.frame; // Most recent rects come first
95 return renderer < rhs.renderer;
100 return node < rhs.node;
105 Render::Renderer* renderer;
113 * Structure to contain internal data
115 struct RenderManager::Impl
117 Impl( Integration::GlAbstraction& glAbstraction,
118 Integration::GlSyncAbstraction& glSyncAbstraction,
119 Integration::GlContextHelperAbstraction& glContextHelperAbstraction,
120 Integration::DepthBufferAvailable depthBufferAvailableParam,
121 Integration::StencilBufferAvailable stencilBufferAvailableParam,
122 Integration::PartialUpdateAvailable partialUpdateAvailableParam )
123 : context( glAbstraction, &sceneContextContainer ),
124 currentContext( &context ),
125 glAbstraction( glAbstraction ),
126 glSyncAbstraction( glSyncAbstraction ),
127 glContextHelperAbstraction( glContextHelperAbstraction ),
131 renderBufferIndex( SceneGraphBuffers::INITIAL_UPDATE_BUFFER_INDEX ),
132 defaultSurfaceRect(),
136 frameBufferContainer(),
137 lastFrameWasRendered( false ),
138 programController( glAbstraction ),
139 depthBufferAvailable( depthBufferAvailableParam ),
140 stencilBufferAvailable( stencilBufferAvailableParam ),
141 partialUpdateAvailable( partialUpdateAvailableParam ),
144 // Create thread pool with just one thread ( there may be a need to create more threads in the future ).
145 threadPool = std::unique_ptr<Dali::ThreadPool>( new Dali::ThreadPool() );
146 threadPool->Initialize( 1u );
151 threadPool.reset( nullptr ); // reset now to maintain correct destruction order
154 void AddRenderTracker( Render::RenderTracker* renderTracker )
156 DALI_ASSERT_DEBUG( renderTracker != NULL );
157 mRenderTrackers.PushBack( renderTracker );
160 void RemoveRenderTracker( Render::RenderTracker* renderTracker )
162 mRenderTrackers.EraseObject( renderTracker );
165 Context* CreateSceneContext()
167 sceneContextContainer.push_back( new Context( glAbstraction ) );
168 return sceneContextContainer[ sceneContextContainer.size() - 1 ];
171 void DestroySceneContext( Context* sceneContext )
173 auto iter = std::find( sceneContextContainer.begin(), sceneContextContainer.end(), sceneContext );
174 if( iter != sceneContextContainer.end() )
176 sceneContextContainer.erase( iter );
180 Context* ReplaceSceneContext( Context* oldSceneContext )
182 Context* newContext = new Context( glAbstraction );
183 std::replace( sceneContextContainer.begin(), sceneContextContainer.end(), oldSceneContext, newContext );
187 void UpdateTrackers()
189 for( auto&& iter : mRenderTrackers )
191 iter->PollSyncObject();
195 // the order is important for destruction,
196 // programs are owned by context at the moment.
197 Context context; ///< Holds the GL state of the share resource context
198 Context* currentContext; ///< Holds the GL state of the current context for rendering
199 std::vector< Context* > sceneContextContainer; ///< List of owned contexts holding the GL state per scene
200 Integration::GlAbstraction& glAbstraction; ///< GL abstraction
201 Integration::GlSyncAbstraction& glSyncAbstraction; ///< GL sync abstraction
202 Integration::GlContextHelperAbstraction& glContextHelperAbstraction; ///< GL context helper abstraction
203 RenderQueue renderQueue; ///< A message queue for receiving messages from the update-thread.
205 std::vector< SceneGraph::Scene* > sceneContainer; ///< List of pointers to the scene graph objects of the scenes
207 Render::RenderAlgorithms renderAlgorithms; ///< The RenderAlgorithms object is used to action the renders required by a RenderInstruction
209 uint32_t frameCount; ///< The current frame count
210 BufferIndex renderBufferIndex; ///< The index of the buffer to read from; this is opposite of the "update" buffer
212 Rect<int32_t> defaultSurfaceRect; ///< Rectangle for the default surface we are rendering to
214 OwnerContainer< Render::Renderer* > rendererContainer; ///< List of owned renderers
215 OwnerContainer< Render::Sampler* > samplerContainer; ///< List of owned samplers
216 OwnerContainer< Render::Texture* > textureContainer; ///< List of owned textures
217 OwnerContainer< Render::FrameBuffer* > frameBufferContainer; ///< List of owned framebuffers
218 OwnerContainer< Render::PropertyBuffer* > propertyBufferContainer; ///< List of owned property buffers
219 OwnerContainer< Render::Geometry* > geometryContainer; ///< List of owned Geometries
221 bool lastFrameWasRendered; ///< Keeps track of the last frame being rendered due to having render instructions
223 OwnerContainer< Render::RenderTracker* > mRenderTrackers; ///< List of render trackers
225 ProgramController programController; ///< Owner of the GL programs
227 Integration::DepthBufferAvailable depthBufferAvailable; ///< Whether the depth buffer is available
228 Integration::StencilBufferAvailable stencilBufferAvailable; ///< Whether the stencil buffer is available
229 Integration::PartialUpdateAvailable partialUpdateAvailable; ///< Whether the partial update is available
231 std::unique_ptr<Dali::ThreadPool> threadPool; ///< The thread pool
232 Vector<GLuint> boundTextures; ///< The textures bound for rendering
233 Vector<GLuint> textureDependencyList; ///< The dependency list of binded textures
234 std::size_t itemsCheckSum; ///< The damaged render items checksum from previous prerender phase.
235 std::vector<DirtyRect> itemsDirtyRects;
238 RenderManager* RenderManager::New( Integration::GlAbstraction& glAbstraction,
239 Integration::GlSyncAbstraction& glSyncAbstraction,
240 Integration::GlContextHelperAbstraction& glContextHelperAbstraction,
241 Integration::DepthBufferAvailable depthBufferAvailable,
242 Integration::StencilBufferAvailable stencilBufferAvailable,
243 Integration::PartialUpdateAvailable partialUpdateAvailable )
245 RenderManager* manager = new RenderManager;
246 manager->mImpl = new Impl( glAbstraction,
248 glContextHelperAbstraction,
249 depthBufferAvailable,
250 stencilBufferAvailable,
251 partialUpdateAvailable );
255 RenderManager::RenderManager()
260 RenderManager::~RenderManager()
265 RenderQueue& RenderManager::GetRenderQueue()
267 return mImpl->renderQueue;
270 void RenderManager::ContextCreated()
272 mImpl->context.GlContextCreated();
273 mImpl->programController.GlContextCreated();
275 // renderers, textures and gpu buffers cannot reinitialize themselves
276 // so they rely on someone reloading the data for them
279 void RenderManager::ContextDestroyed()
281 mImpl->context.GlContextDestroyed();
282 mImpl->programController.GlContextDestroyed();
285 for( auto&& texture : mImpl->textureContainer )
287 texture->GlContextDestroyed();
290 //Inform framebuffers
291 for( auto&& framebuffer : mImpl->frameBufferContainer )
293 framebuffer->GlContextDestroyed();
297 for( auto&& renderer : mImpl->rendererContainer )
299 renderer->GlContextDestroyed();
303 for( auto&& scene : mImpl->sceneContainer )
305 scene->GlContextDestroyed();
309 void RenderManager::SetShaderSaver( ShaderSaver& upstream )
311 mImpl->programController.SetShaderSaver( upstream );
314 void RenderManager::SetDefaultSurfaceRect(const Rect<int32_t>& rect)
316 mImpl->defaultSurfaceRect = rect;
319 void RenderManager::AddRenderer( OwnerPointer< Render::Renderer >& renderer )
321 // Initialize the renderer as we are now in render thread
322 renderer->Initialize( mImpl->context );
324 mImpl->rendererContainer.PushBack( renderer.Release() );
327 void RenderManager::RemoveRenderer( Render::Renderer* renderer )
329 mImpl->rendererContainer.EraseObject( renderer );
332 void RenderManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
334 mImpl->samplerContainer.PushBack( sampler.Release() );
337 void RenderManager::RemoveSampler( Render::Sampler* sampler )
339 mImpl->samplerContainer.EraseObject( sampler );
342 void RenderManager::AddTexture( OwnerPointer< Render::Texture >& texture )
344 texture->Initialize( mImpl->context );
345 mImpl->textureContainer.PushBack( texture.Release() );
348 void RenderManager::RemoveTexture( Render::Texture* texture )
350 DALI_ASSERT_DEBUG( NULL != texture );
352 // Find the texture, use reference to pointer so we can do the erase safely
353 for ( auto&& iter : mImpl->textureContainer )
355 if ( iter == texture )
357 texture->Destroy( mImpl->context );
358 mImpl->textureContainer.Erase( &iter ); // Texture found; now destroy it
364 void RenderManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
366 texture->Upload( mImpl->context, pixelData, params );
369 void RenderManager::GenerateMipmaps( Render::Texture* texture )
371 texture->GenerateMipmaps( mImpl->context );
374 void RenderManager::SetFilterMode( Render::Sampler* sampler, uint32_t minFilterMode, uint32_t magFilterMode )
376 sampler->mMinificationFilter = static_cast<Dali::FilterMode::Type>(minFilterMode);
377 sampler->mMagnificationFilter = static_cast<Dali::FilterMode::Type>(magFilterMode );
380 void RenderManager::SetWrapMode( Render::Sampler* sampler, uint32_t rWrapMode, uint32_t sWrapMode, uint32_t tWrapMode )
382 sampler->mRWrapMode = static_cast<Dali::WrapMode::Type>(rWrapMode);
383 sampler->mSWrapMode = static_cast<Dali::WrapMode::Type>(sWrapMode);
384 sampler->mTWrapMode = static_cast<Dali::WrapMode::Type>(tWrapMode);
387 void RenderManager::AddFrameBuffer( OwnerPointer< Render::FrameBuffer >& frameBuffer )
389 Render::FrameBuffer* frameBufferPtr = frameBuffer.Release();
390 mImpl->frameBufferContainer.PushBack( frameBufferPtr );
391 frameBufferPtr->Initialize( mImpl->context );
394 void RenderManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer )
396 DALI_ASSERT_DEBUG( NULL != frameBuffer );
398 // Find the sampler, use reference so we can safely do the erase
399 for ( auto&& iter : mImpl->frameBufferContainer )
401 if ( iter == frameBuffer )
403 frameBuffer->Destroy( mImpl->context );
404 mImpl->frameBufferContainer.Erase( &iter ); // frameBuffer found; now destroy it
410 void RenderManager::InitializeScene( SceneGraph::Scene* scene )
412 scene->Initialize( *mImpl->CreateSceneContext() );
413 mImpl->sceneContainer.push_back( scene );
416 void RenderManager::UninitializeScene( SceneGraph::Scene* scene )
418 mImpl->DestroySceneContext( scene->GetContext() );
420 auto iter = std::find( mImpl->sceneContainer.begin(), mImpl->sceneContainer.end(), scene );
421 if( iter != mImpl->sceneContainer.end() )
423 mImpl->sceneContainer.erase( iter );
427 void RenderManager::SurfaceReplaced( SceneGraph::Scene* scene )
429 Context* newContext = mImpl->ReplaceSceneContext( scene->GetContext() );
430 scene->Initialize( *newContext );
433 void RenderManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer )
435 frameBuffer->AttachColorTexture( mImpl->context, texture, mipmapLevel, layer );
438 void RenderManager::AttachDepthTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel )
440 frameBuffer->AttachDepthTexture( mImpl->context, texture, mipmapLevel );
443 void RenderManager::AttachDepthStencilTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel )
445 frameBuffer->AttachDepthStencilTexture( mImpl->context, texture, mipmapLevel );
448 void RenderManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer )
450 mImpl->propertyBufferContainer.PushBack( propertyBuffer.Release() );
453 void RenderManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
455 mImpl->propertyBufferContainer.EraseObject( propertyBuffer );
458 void RenderManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
460 propertyBuffer->SetFormat( format.Release() );
463 void RenderManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<uint8_t> >& data, uint32_t size )
465 propertyBuffer->SetData( data.Release(), size );
468 void RenderManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<uint16_t>& indices )
470 geometry->SetIndexBuffer( indices );
473 void RenderManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
475 mImpl->geometryContainer.PushBack( geometry.Release() );
478 void RenderManager::RemoveGeometry( Render::Geometry* geometry )
480 mImpl->geometryContainer.EraseObject( geometry );
483 void RenderManager::AttachVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
485 DALI_ASSERT_DEBUG( NULL != geometry );
488 for ( auto&& iter : mImpl->geometryContainer )
490 if ( iter == geometry )
492 iter->AddPropertyBuffer( propertyBuffer );
498 void RenderManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
500 DALI_ASSERT_DEBUG( NULL != geometry );
503 for ( auto&& iter : mImpl->geometryContainer )
505 if ( iter == geometry )
507 iter->RemovePropertyBuffer( propertyBuffer );
513 void RenderManager::SetGeometryType( Render::Geometry* geometry, uint32_t geometryType )
515 geometry->SetType( Render::Geometry::Type(geometryType) );
518 void RenderManager::AddRenderTracker( Render::RenderTracker* renderTracker )
520 mImpl->AddRenderTracker(renderTracker);
523 void RenderManager::RemoveRenderTracker( Render::RenderTracker* renderTracker )
525 mImpl->RemoveRenderTracker(renderTracker);
528 ProgramCache* RenderManager::GetProgramCache()
530 return &(mImpl->programController);
533 void RenderManager::PreRender( Integration::RenderStatus& status, bool forceClear, bool uploadOnly )
535 DALI_PRINT_RENDER_START( mImpl->renderBufferIndex );
537 // Core::Render documents that GL context must be current before calling Render
538 DALI_ASSERT_DEBUG( mImpl->context.IsGlContextCreated() );
540 // Increment the frame count at the beginning of each frame
543 // Process messages queued during previous update
544 mImpl->renderQueue.ProcessMessages( mImpl->renderBufferIndex );
547 for( uint32_t i = 0; i < mImpl->sceneContainer.size(); ++i )
549 count += mImpl->sceneContainer[i]->GetRenderInstructions().Count( mImpl->renderBufferIndex );
552 const bool haveInstructions = count > 0u;
554 DALI_LOG_INFO( gLogFilter, Debug::General,
555 "Render: haveInstructions(%s) || mImpl->lastFrameWasRendered(%s) || forceClear(%s)\n",
556 haveInstructions ? "true" : "false",
557 mImpl->lastFrameWasRendered ? "true" : "false",
558 forceClear ? "true" : "false" );
560 // Only render if we have instructions to render, or the last frame was rendered (and therefore a clear is required).
561 if( haveInstructions || mImpl->lastFrameWasRendered || forceClear )
563 DALI_LOG_INFO( gLogFilter, Debug::General, "Render: Processing\n" );
565 // Switch to the shared context
566 if ( mImpl->currentContext != &mImpl->context )
568 mImpl->currentContext = &mImpl->context;
570 if ( mImpl->currentContext->IsSurfacelessContextSupported() )
572 mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent();
575 // Clear the current cached program when the context is switched
576 mImpl->programController.ClearCurrentProgram();
579 // Upload the geometries
580 for( uint32_t i = 0; i < mImpl->sceneContainer.size(); ++i )
582 RenderInstructionContainer& instructions = mImpl->sceneContainer[i]->GetRenderInstructions();
583 for ( uint32_t j = 0; j < instructions.Count( mImpl->renderBufferIndex ); ++j )
585 RenderInstruction& instruction = instructions.At( mImpl->renderBufferIndex, j );
587 const Matrix* viewMatrix = instruction.GetViewMatrix( mImpl->renderBufferIndex );
588 const Matrix* projectionMatrix = instruction.GetProjectionMatrix( mImpl->renderBufferIndex );
590 DALI_ASSERT_DEBUG( viewMatrix );
591 DALI_ASSERT_DEBUG( projectionMatrix );
593 if( viewMatrix && projectionMatrix )
595 const RenderListContainer::SizeType renderListCount = instruction.RenderListCount();
597 // Iterate through each render list.
598 for( RenderListContainer::SizeType index = 0; index < renderListCount; ++index )
600 const RenderList* renderList = instruction.GetRenderList( index );
602 if( renderList && !renderList->IsEmpty() )
604 const std::size_t itemCount = renderList->Count();
605 for( uint32_t itemIndex = 0u; itemIndex < itemCount; ++itemIndex )
607 const RenderItem& item = renderList->GetItem( itemIndex );
608 if( DALI_LIKELY( item.mRenderer ) )
610 item.mRenderer->Upload( *mImpl->currentContext );
621 void RenderManager::PreRender( Integration::Scene& scene, std::vector<Rect<int>>& damagedRects )
623 if (mImpl->partialUpdateAvailable != Integration::PartialUpdateAvailable::TRUE)
628 class DamagedRectsCleaner
631 DamagedRectsCleaner(std::vector<Rect<int>>& damagedRects)
632 : mDamagedRects(damagedRects),
637 void SetCleanOnReturn(bool cleanOnReturn)
639 mCleanOnReturn = cleanOnReturn;
642 ~DamagedRectsCleaner()
646 mDamagedRects.clear();
651 std::vector<Rect<int>>& mDamagedRects;
655 Rect<int32_t> surfaceRect = Rect<int32_t>(0, 0, static_cast<int32_t>( scene.GetSize().width ), static_cast<int32_t>( scene.GetSize().height ));
657 // Clean collected dirty/damaged rects on exit if 3d layer or 3d node or other conditions.
658 DamagedRectsCleaner damagedRectCleaner(damagedRects);
660 // Mark previous dirty rects in the sorted array. The array is already sorted by node and renderer, frame number.
661 // so you don't need to sort: std::stable_sort(mImpl->itemsDirtyRects.begin(), mImpl->itemsDirtyRects.end());
662 for (DirtyRect& dirtyRect : mImpl->itemsDirtyRects)
664 dirtyRect.visited = false;
667 Internal::Scene& sceneInternal = GetImplementation(scene);
668 SceneGraph::Scene* sceneObject = sceneInternal.GetSceneObject();
669 uint32_t count = sceneObject->GetRenderInstructions().Count( mImpl->renderBufferIndex );
670 for (uint32_t i = 0; i < count; ++i)
672 RenderInstruction& instruction = sceneObject->GetRenderInstructions().At( mImpl->renderBufferIndex, i );
674 if (instruction.mFrameBuffer)
676 return; // TODO: reset, we don't deal with render tasks with framebuffers (for now)
679 const Camera* camera = instruction.GetCamera();
680 if (camera->mType == Camera::DEFAULT_TYPE && camera->mTargetPosition == Camera::DEFAULT_TARGET_POSITION)
682 const Node* node = instruction.GetCamera()->GetNode();
687 Quaternion orientation;
688 node->GetWorldMatrix(mImpl->renderBufferIndex).GetTransformComponents(position, orientation, scale);
690 Vector3 orientationAxis;
691 Radian orientationAngle;
692 orientation.ToAxisAngle( orientationAxis, orientationAngle );
694 if (position.x > Math::MACHINE_EPSILON_10000 ||
695 position.y > Math::MACHINE_EPSILON_10000 ||
696 orientationAxis != Vector3(0.0f, 1.0f, 0.0f) ||
697 orientationAngle != ANGLE_180 ||
698 scale != Vector3(1.0f, 1.0f, 1.0f))
709 Rect<int32_t> viewportRect;
710 if (instruction.mIsViewportSet)
712 const int32_t y = (surfaceRect.height - instruction.mViewport.height) - instruction.mViewport.y;
713 viewportRect.Set(instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height);
714 if (viewportRect.IsEmpty() || !viewportRect.IsValid())
716 return; // just skip funny use cases for now, empty viewport means it is set somewhere else
721 viewportRect = surfaceRect;
724 const Matrix* viewMatrix = instruction.GetViewMatrix(mImpl->renderBufferIndex);
725 const Matrix* projectionMatrix = instruction.GetProjectionMatrix(mImpl->renderBufferIndex);
726 if (viewMatrix && projectionMatrix)
728 const RenderListContainer::SizeType count = instruction.RenderListCount();
729 for (RenderListContainer::SizeType index = 0u; index < count; ++index)
731 const RenderList* renderList = instruction.GetRenderList( index );
732 if (renderList && !renderList->IsEmpty())
734 const std::size_t count = renderList->Count();
735 for (uint32_t index = 0u; index < count; ++index)
737 RenderItem& item = renderList->GetItem( index );
738 // If the item does 3D transformation, do early exit and clean the damaged rect array
739 if (item.mUpdateSize == Vector3::ZERO)
745 DirtyRect dirtyRect(item.mNode, item.mRenderer, mImpl->frameCount, rect);
746 // If the item refers to updated node or renderer.
747 if (item.mIsUpdated ||
749 (item.mNode->Updated() || (item.mRenderer && item.mRenderer->Updated(mImpl->renderBufferIndex, item.mNode)))))
751 item.mIsUpdated = false;
752 item.mNode->SetUpdated(false);
754 rect = item.CalculateViewportSpaceAABB(item.mUpdateSize, viewportRect.width, viewportRect.height);
755 if (rect.IsValid() && rect.Intersect(viewportRect) && !rect.IsEmpty())
757 const int left = rect.x;
758 const int top = rect.y;
759 const int right = rect.x + rect.width;
760 const int bottom = rect.y + rect.height;
761 rect.x = (left / 16) * 16;
762 rect.y = (top / 16) * 16;
763 rect.width = ((right + 16) / 16) * 16 - rect.x;
764 rect.height = ((bottom + 16) / 16) * 16 - rect.y;
766 // Found valid dirty rect.
767 // 1. Insert it in the sorted array of the dirty rects.
768 // 2. Mark the related dirty rects as visited so they will not be removed below.
769 // 3. Keep only last 3 dirty rects for the same node and renderer (Tizen uses 3 back buffers, Ubuntu 1).
770 dirtyRect.rect = rect;
771 auto dirtyRectPos = std::lower_bound(mImpl->itemsDirtyRects.begin(), mImpl->itemsDirtyRects.end(), dirtyRect);
772 dirtyRectPos = mImpl->itemsDirtyRects.insert(dirtyRectPos, dirtyRect);
775 while (++dirtyRectPos != mImpl->itemsDirtyRects.end())
777 if (dirtyRectPos->node != item.mNode || dirtyRectPos->renderer != item.mRenderer)
782 dirtyRectPos->visited = true;
783 Rect<int>& dirtRect = dirtyRectPos->rect;
784 rect.Merge(dirtRect);
787 if (c > 3) // no more then 3 previous rects
789 mImpl->itemsDirtyRects.erase(dirtyRectPos);
794 damagedRects.push_back(rect);
799 // 1. The item is not dirty, the node and renderer referenced by the item are still exist.
800 // 2. Mark the related dirty rects as visited so they will not be removed below.
801 auto dirtyRectPos = std::lower_bound(mImpl->itemsDirtyRects.begin(), mImpl->itemsDirtyRects.end(), dirtyRect);
802 while (dirtyRectPos != mImpl->itemsDirtyRects.end())
804 if (dirtyRectPos->node != item.mNode || dirtyRectPos->renderer != item.mRenderer)
809 dirtyRectPos->visited = true;
819 // Check removed nodes or removed renderers dirty rects
820 auto i = mImpl->itemsDirtyRects.begin();
821 auto j = mImpl->itemsDirtyRects.begin();
822 while (i != mImpl->itemsDirtyRects.end())
830 Rect<int>& dirtRect = i->rect;
831 damagedRects.push_back(dirtRect);
836 mImpl->itemsDirtyRects.resize(j - mImpl->itemsDirtyRects.begin());
837 damagedRectCleaner.SetCleanOnReturn(false);
840 void RenderManager::RenderScene( Integration::RenderStatus& status, Integration::Scene& scene, bool renderToFbo )
842 Rect<int> clippingRect;
843 RenderScene( status, scene, renderToFbo, clippingRect);
846 void RenderManager::RenderScene( Integration::RenderStatus& status, Integration::Scene& scene, bool renderToFbo, Rect<int>& clippingRect )
848 Internal::Scene& sceneInternal = GetImplementation( scene );
849 SceneGraph::Scene* sceneObject = sceneInternal.GetSceneObject();
851 uint32_t count = sceneObject->GetRenderInstructions().Count( mImpl->renderBufferIndex );
853 for( uint32_t i = 0; i < count; ++i )
855 RenderInstruction& instruction = sceneObject->GetRenderInstructions().At( mImpl->renderBufferIndex, i );
857 if ( ( renderToFbo && !instruction.mFrameBuffer ) || ( !renderToFbo && instruction.mFrameBuffer ) )
862 // Mark that we will require a post-render step to be performed (includes swap-buffers).
863 status.SetNeedsPostRender( true );
865 Rect<int32_t> viewportRect;
868 if ( instruction.mIsClearColorSet )
870 clearColor = instruction.mClearColor;
874 clearColor = Dali::RenderTask::DEFAULT_CLEAR_COLOR;
877 Rect<int32_t> surfaceRect = mImpl->defaultSurfaceRect;
878 Integration::DepthBufferAvailable depthBufferAvailable = mImpl->depthBufferAvailable;
879 Integration::StencilBufferAvailable stencilBufferAvailable = mImpl->stencilBufferAvailable;
881 if ( instruction.mFrameBuffer )
884 if ( mImpl->currentContext != &mImpl->context )
886 // Switch to shared context for off-screen buffer
887 mImpl->currentContext = &mImpl->context;
889 if ( mImpl->currentContext->IsSurfacelessContextSupported() )
891 mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent();
894 // Clear the current cached program when the context is switched
895 mImpl->programController.ClearCurrentProgram();
900 if ( mImpl->currentContext->IsSurfacelessContextSupported() )
902 if ( mImpl->currentContext != sceneObject->GetContext() )
904 // Switch the correct context if rendering to a surface
905 mImpl->currentContext = sceneObject->GetContext();
907 // Clear the current cached program when the context is switched
908 mImpl->programController.ClearCurrentProgram();
912 surfaceRect = Rect<int32_t>( 0, 0, static_cast<int32_t>( scene.GetSize().width ), static_cast<int32_t>( scene.GetSize().height ) );
915 DALI_ASSERT_DEBUG( mImpl->currentContext->IsGlContextCreated() );
917 // reset the program matrices for all programs once per frame
918 // this ensures we will set view and projection matrix once per program per camera
919 mImpl->programController.ResetProgramMatrices();
921 if( instruction.mFrameBuffer )
923 instruction.mFrameBuffer->Bind( *mImpl->currentContext );
925 // For each offscreen buffer, update the dependency list with the new texture id used by this frame buffer.
926 for (unsigned int i0 = 0, i1 = instruction.mFrameBuffer->GetColorAttachmentCount(); i0 < i1; ++i0)
928 mImpl->textureDependencyList.PushBack( instruction.mFrameBuffer->GetTextureId(i0) );
933 mImpl->currentContext->BindFramebuffer( GL_FRAMEBUFFER, 0u );
936 if ( !instruction.mFrameBuffer )
938 mImpl->currentContext->Viewport( surfaceRect.x,
941 surfaceRect.height );
944 // Clear the entire color, depth and stencil buffers for the default framebuffer, if required.
945 // It is important to clear all 3 buffers when they are being used, for performance on deferred renderers
946 // e.g. previously when the depth & stencil buffers were NOT cleared, it caused the DDK to exceed a "vertex count limit",
947 // and then stall. That problem is only noticeable when rendering a large number of vertices per frame.
948 GLbitfield clearMask = GL_COLOR_BUFFER_BIT;
950 mImpl->currentContext->ColorMask( true );
952 if( depthBufferAvailable == Integration::DepthBufferAvailable::TRUE )
954 mImpl->currentContext->DepthMask( true );
955 clearMask |= GL_DEPTH_BUFFER_BIT;
958 if( stencilBufferAvailable == Integration::StencilBufferAvailable::TRUE)
960 mImpl->currentContext->ClearStencil( 0 );
961 mImpl->currentContext->StencilMask( 0xFF ); // 8 bit stencil mask, all 1's
962 clearMask |= GL_STENCIL_BUFFER_BIT;
965 if( !instruction.mIgnoreRenderToFbo && ( instruction.mFrameBuffer != 0 ) )
967 // Offscreen buffer rendering
968 if ( instruction.mIsViewportSet )
970 // For glViewport the lower-left corner is (0,0)
971 const int32_t y = ( instruction.mFrameBuffer->GetHeight() - instruction.mViewport.height ) - instruction.mViewport.y;
972 viewportRect.Set( instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height );
976 viewportRect.Set( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
979 else // No Offscreen frame buffer rendering
981 // Check whether a viewport is specified, otherwise the full surface size is used
982 if ( instruction.mIsViewportSet )
984 // For glViewport the lower-left corner is (0,0)
985 const int32_t y = ( surfaceRect.height - instruction.mViewport.height ) - instruction.mViewport.y;
986 viewportRect.Set( instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height );
990 viewportRect = surfaceRect;
994 bool clearFullFrameRect = true;
995 if( instruction.mFrameBuffer != 0 )
997 Viewport frameRect( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
998 clearFullFrameRect = ( frameRect == viewportRect );
1002 clearFullFrameRect = ( surfaceRect == viewportRect );
1005 if (!clippingRect.IsEmpty())
1007 if (!clippingRect.Intersect(viewportRect))
1009 DALI_LOG_ERROR("Invalid clipping rect %d %d %d %d\n", clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height);
1010 clippingRect = Rect<int>();
1012 clearFullFrameRect = false;
1015 mImpl->currentContext->Viewport(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height);
1017 if (instruction.mIsClearColorSet)
1019 mImpl->currentContext->ClearColor(clearColor.r,
1023 if (!clearFullFrameRect)
1025 if (!clippingRect.IsEmpty())
1027 mImpl->currentContext->SetScissorTest(true);
1028 mImpl->currentContext->Scissor(clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height);
1029 mImpl->currentContext->Clear(clearMask, Context::FORCE_CLEAR);
1030 mImpl->currentContext->SetScissorTest(false);
1034 mImpl->currentContext->SetScissorTest(true);
1035 mImpl->currentContext->Scissor(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height);
1036 mImpl->currentContext->Clear(clearMask, Context::FORCE_CLEAR);
1037 mImpl->currentContext->SetScissorTest(false);
1042 mImpl->currentContext->SetScissorTest(false);
1043 mImpl->currentContext->Clear(clearMask, Context::FORCE_CLEAR);
1047 // Clear the list of bound textures
1048 mImpl->boundTextures.Clear();
1050 mImpl->renderAlgorithms.ProcessRenderInstruction(
1052 *mImpl->currentContext,
1053 mImpl->renderBufferIndex,
1054 depthBufferAvailable,
1055 stencilBufferAvailable,
1056 mImpl->boundTextures,
1059 // Synchronise the FBO/Texture access when there are multiple contexts
1060 if ( mImpl->currentContext->IsSurfacelessContextSupported() )
1062 // Check whether any binded texture is in the dependency list
1063 bool textureFound = false;
1065 if ( mImpl->boundTextures.Count() > 0u && mImpl->textureDependencyList.Count() > 0u )
1067 for ( auto textureId : mImpl->textureDependencyList )
1070 textureFound = std::find_if( mImpl->boundTextures.Begin(), mImpl->boundTextures.End(),
1071 [textureId]( GLuint id )
1073 return textureId == id;
1074 } ) != mImpl->boundTextures.End();
1080 if ( instruction.mFrameBuffer )
1082 // For off-screen buffer
1084 // Wait until all rendering calls for the currently context are executed
1085 mImpl->glContextHelperAbstraction.WaitClient();
1087 // Clear the dependency list
1088 mImpl->textureDependencyList.Clear();
1092 // Worker thread lambda function
1093 auto& glContextHelperAbstraction = mImpl->glContextHelperAbstraction;
1094 auto workerFunction = [&glContextHelperAbstraction]( int workerThread )
1096 // Switch to the shared context in the worker thread
1097 glContextHelperAbstraction.MakeSurfacelessContextCurrent();
1099 // Wait until all rendering calls for the shared context are executed
1100 glContextHelperAbstraction.WaitClient();
1102 // Must clear the context in the worker thread
1103 // Otherwise the shared context cannot be switched to from the render thread
1104 glContextHelperAbstraction.MakeContextNull();
1107 auto future = mImpl->threadPool->SubmitTask( 0u, workerFunction );
1110 mImpl->threadPool->Wait();
1112 // Clear the dependency list
1113 mImpl->textureDependencyList.Clear();
1119 if( instruction.mRenderTracker && instruction.mFrameBuffer )
1121 // This will create a sync object every frame this render tracker
1122 // is alive (though it should be now be created only for
1123 // render-once render tasks)
1124 instruction.mRenderTracker->CreateSyncObject( mImpl->glSyncAbstraction );
1125 instruction.mRenderTracker = nullptr; // Only create once.
1130 mImpl->currentContext->Flush();
1134 GLenum attachments[] = { GL_DEPTH, GL_STENCIL };
1135 mImpl->currentContext->InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
1138 void RenderManager::PostRender( bool uploadOnly )
1142 if ( mImpl->currentContext->IsSurfacelessContextSupported() )
1144 mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent();
1147 GLenum attachments[] = { GL_DEPTH, GL_STENCIL };
1148 mImpl->context.InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
1151 //Notify RenderGeometries that rendering has finished
1152 for ( auto&& iter : mImpl->geometryContainer )
1154 iter->OnRenderFinished();
1157 mImpl->UpdateTrackers();
1160 uint32_t count = 0u;
1161 for( uint32_t i = 0; i < mImpl->sceneContainer.size(); ++i )
1163 count += mImpl->sceneContainer[i]->GetRenderInstructions().Count( mImpl->renderBufferIndex );
1166 const bool haveInstructions = count > 0u;
1168 // If this frame was rendered due to instructions existing, we mark this so we know to clear the next frame.
1169 mImpl->lastFrameWasRendered = haveInstructions;
1172 * The rendering has finished; swap to the next buffer.
1173 * Ideally the update has just finished using this buffer; otherwise the render thread
1174 * should block until the update has finished.
1176 mImpl->renderBufferIndex = (0 != mImpl->renderBufferIndex) ? 0 : 1;
1178 DALI_PRINT_RENDER_END();
1181 } // namespace SceneGraph
1183 } // namespace Internal