fb71907ccd8f5cd5fe4572fdb6b03ce24d6c0f6d
[platform/core/uifw/dali-core.git] / dali / internal / render / common / render-manager.cpp
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/render/common/render-manager.h>
20
21 // EXTERNAL INCLUDES
22 #include <memory.h>
23
24 // INTERNAL INCLUDES
25 #include <dali/devel-api/threading/thread-pool.h>
26 #include <dali/integration-api/core.h>
27 #include <dali/integration-api/gl-context-helper-abstraction.h>
28 #include <dali/internal/event/common/scene-impl.h>
29 #include <dali/internal/render/common/render-algorithms.h>
30 #include <dali/internal/render/common/render-debug.h>
31 #include <dali/internal/render/common/render-tracker.h>
32 #include <dali/internal/render/queue/render-queue.h>
33 #include <dali/internal/render/shaders/program-controller.h>
34
35 namespace Dali
36 {
37
38 namespace Internal
39 {
40
41 namespace SceneGraph
42 {
43
44 #if defined(DEBUG_ENABLED)
45 namespace
46 {
47 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RENDER_MANAGER" );
48 } // unnamed namespace
49 #endif
50
51 struct DirtyRect
52 {
53   DirtyRect(Node* node, Render::Renderer* renderer, int frame, Rect<int>& rect)
54   : node(node),
55     renderer(renderer),
56     frame(frame),
57     rect(rect),
58     visited(true)
59   {
60   }
61
62   DirtyRect()
63   : node(nullptr),
64     renderer(nullptr),
65     frame(0),
66     rect(),
67     visited(true)
68   {
69   }
70
71   bool operator<(const DirtyRect& rhs) const
72   {
73     if (node == rhs.node)
74     {
75       if (renderer == rhs.renderer)
76       {
77         return frame > rhs.frame; // Most recent rects come first
78       }
79       else
80       {
81         return renderer < rhs.renderer;
82       }
83     }
84     else
85     {
86       return node < rhs.node;
87     }
88   }
89
90   Node* node;
91   Render::Renderer* renderer;
92   int frame;
93
94   Rect<int> rect;
95   bool visited;
96 };
97
98 /**
99  * Structure to contain internal data
100  */
101 struct RenderManager::Impl
102 {
103   Impl( Integration::GlAbstraction& glAbstraction,
104         Integration::GlSyncAbstraction& glSyncAbstraction,
105         Integration::GlContextHelperAbstraction& glContextHelperAbstraction,
106         Integration::DepthBufferAvailable depthBufferAvailableParam,
107         Integration::StencilBufferAvailable stencilBufferAvailableParam,
108         Integration::PartialUpdateAvailable partialUpdateAvailableParam )
109   : context( glAbstraction, &sceneContextContainer ),
110     currentContext( &context ),
111     glAbstraction( glAbstraction ),
112     glSyncAbstraction( glSyncAbstraction ),
113     glContextHelperAbstraction( glContextHelperAbstraction ),
114     renderQueue(),
115     renderAlgorithms(),
116     frameCount( 0u ),
117     renderBufferIndex( SceneGraphBuffers::INITIAL_UPDATE_BUFFER_INDEX ),
118     defaultSurfaceRect(),
119     rendererContainer(),
120     samplerContainer(),
121     textureContainer(),
122     frameBufferContainer(),
123     lastFrameWasRendered( false ),
124     programController( glAbstraction ),
125     depthBufferAvailable( depthBufferAvailableParam ),
126     stencilBufferAvailable( stencilBufferAvailableParam ),
127     partialUpdateAvailable( partialUpdateAvailableParam ),
128     itemsCheckSum(0),
129     defaultSurfaceOrientation( 0 )
130   {
131      // Create thread pool with just one thread ( there may be a need to create more threads in the future ).
132     threadPool = std::unique_ptr<Dali::ThreadPool>( new Dali::ThreadPool() );
133     threadPool->Initialize( 1u );
134   }
135
136   ~Impl()
137   {
138     threadPool.reset( nullptr ); // reset now to maintain correct destruction order
139   }
140
141   void AddRenderTracker( Render::RenderTracker* renderTracker )
142   {
143     DALI_ASSERT_DEBUG( renderTracker != NULL );
144     mRenderTrackers.PushBack( renderTracker );
145   }
146
147   void RemoveRenderTracker( Render::RenderTracker* renderTracker )
148   {
149     mRenderTrackers.EraseObject( renderTracker );
150   }
151
152   Context* CreateSceneContext()
153   {
154     Context* context = new Context( glAbstraction );
155     sceneContextContainer.PushBack( context );
156     return context;
157   }
158
159   void DestroySceneContext( Context* sceneContext )
160   {
161     auto iter = std::find( sceneContextContainer.Begin(), sceneContextContainer.End(), sceneContext );
162     if( iter != sceneContextContainer.End() )
163     {
164       ( *iter )->GlContextDestroyed();
165       sceneContextContainer.Erase( iter );
166     }
167   }
168
169   Context* ReplaceSceneContext( Context* oldSceneContext )
170   {
171     Context* newContext = new Context( glAbstraction );
172
173     oldSceneContext->GlContextDestroyed();
174
175     std::replace( sceneContextContainer.begin(), sceneContextContainer.end(), oldSceneContext, newContext );
176     return newContext;
177   }
178
179   void UpdateTrackers()
180   {
181     for( auto&& iter : mRenderTrackers )
182     {
183       iter->PollSyncObject();
184     }
185   }
186
187   // the order is important for destruction,
188   // programs are owned by context at the moment.
189   Context                                   context;                 ///< Holds the GL state of the share resource context
190   Context*                                  currentContext;          ///< Holds the GL state of the current context for rendering
191   OwnerContainer< Context* >                sceneContextContainer;   ///< List of owned contexts holding the GL state per scene
192   Integration::GlAbstraction&               glAbstraction;           ///< GL abstraction
193   Integration::GlSyncAbstraction&           glSyncAbstraction;       ///< GL sync abstraction
194   Integration::GlContextHelperAbstraction&  glContextHelperAbstraction; ///< GL context helper abstraction
195   RenderQueue                               renderQueue;             ///< A message queue for receiving messages from the update-thread.
196
197   std::vector< SceneGraph::Scene* >         sceneContainer;          ///< List of pointers to the scene graph objects of the scenes
198
199   Render::RenderAlgorithms                  renderAlgorithms;        ///< The RenderAlgorithms object is used to action the renders required by a RenderInstruction
200
201   uint32_t                                  frameCount;              ///< The current frame count
202   BufferIndex                               renderBufferIndex;       ///< The index of the buffer to read from; this is opposite of the "update" buffer
203
204   Rect<int32_t>                             defaultSurfaceRect;      ///< Rectangle for the default surface we are rendering to
205
206   OwnerContainer< Render::Renderer* >       rendererContainer;       ///< List of owned renderers
207   OwnerContainer< Render::Sampler* >        samplerContainer;        ///< List of owned samplers
208   OwnerContainer< Render::Texture* >        textureContainer;        ///< List of owned textures
209   OwnerContainer< Render::FrameBuffer* >    frameBufferContainer;    ///< List of owned framebuffers
210   OwnerContainer< Render::PropertyBuffer* > propertyBufferContainer; ///< List of owned property buffers
211   OwnerContainer< Render::Geometry* >       geometryContainer;       ///< List of owned Geometries
212
213   bool                                      lastFrameWasRendered;    ///< Keeps track of the last frame being rendered due to having render instructions
214
215   OwnerContainer< Render::RenderTracker* >  mRenderTrackers;         ///< List of render trackers
216
217   ProgramController                         programController;        ///< Owner of the GL programs
218
219   Integration::DepthBufferAvailable         depthBufferAvailable;     ///< Whether the depth buffer is available
220   Integration::StencilBufferAvailable       stencilBufferAvailable;   ///< Whether the stencil buffer is available
221   Integration::PartialUpdateAvailable       partialUpdateAvailable;   ///< Whether the partial update is available
222
223   std::unique_ptr<Dali::ThreadPool>         threadPool;               ///< The thread pool
224   Vector<GLuint>                            boundTextures;            ///< The textures bound for rendering
225   Vector<GLuint>                            textureDependencyList;    ///< The dependency list of binded textures
226   std::size_t                               itemsCheckSum;            ///< The damaged render items checksum from previous prerender phase.
227   std::vector<DirtyRect>                    itemsDirtyRects;
228   int                                       defaultSurfaceOrientation; ///< defaultSurfaceOrientation for the default surface we are rendering to
229 };
230
231 RenderManager* RenderManager::New( Integration::GlAbstraction& glAbstraction,
232                                    Integration::GlSyncAbstraction& glSyncAbstraction,
233                                    Integration::GlContextHelperAbstraction& glContextHelperAbstraction,
234                                    Integration::DepthBufferAvailable depthBufferAvailable,
235                                    Integration::StencilBufferAvailable stencilBufferAvailable,
236                                    Integration::PartialUpdateAvailable partialUpdateAvailable )
237 {
238   RenderManager* manager = new RenderManager;
239   manager->mImpl = new Impl( glAbstraction,
240                              glSyncAbstraction,
241                              glContextHelperAbstraction,
242                              depthBufferAvailable,
243                              stencilBufferAvailable,
244                              partialUpdateAvailable );
245   return manager;
246 }
247
248 RenderManager::RenderManager()
249 : mImpl(NULL)
250 {
251 }
252
253 RenderManager::~RenderManager()
254 {
255   delete mImpl;
256 }
257
258 RenderQueue& RenderManager::GetRenderQueue()
259 {
260   return mImpl->renderQueue;
261 }
262
263 void RenderManager::ContextCreated()
264 {
265   mImpl->context.GlContextCreated();
266   mImpl->programController.GlContextCreated();
267
268   // renderers, textures and gpu buffers cannot reinitialize themselves
269   // so they rely on someone reloading the data for them
270 }
271
272 void RenderManager::ContextDestroyed()
273 {
274   mImpl->context.GlContextDestroyed();
275   mImpl->programController.GlContextDestroyed();
276
277   //Inform textures
278   for( auto&& texture : mImpl->textureContainer )
279   {
280     texture->GlContextDestroyed();
281   }
282
283   //Inform framebuffers
284   for( auto&& framebuffer : mImpl->frameBufferContainer )
285   {
286     framebuffer->GlContextDestroyed();
287   }
288
289   // inform renderers
290   for( auto&& renderer : mImpl->rendererContainer )
291   {
292     renderer->GlContextDestroyed();
293   }
294
295   // inform context
296   for( auto&& context : mImpl->sceneContextContainer )
297   {
298     context->GlContextDestroyed();
299   }
300 }
301
302 void RenderManager::SetShaderSaver( ShaderSaver& upstream )
303 {
304   mImpl->programController.SetShaderSaver( upstream );
305 }
306
307 void RenderManager::SetDefaultSurfaceRect(const Rect<int32_t>& rect)
308 {
309   mImpl->defaultSurfaceRect = rect;
310 }
311
312 void RenderManager::SetDefaultSurfaceOrientation( int orientation )
313 {
314   mImpl->defaultSurfaceOrientation = orientation;
315 }
316
317 void RenderManager::AddRenderer( OwnerPointer< Render::Renderer >& renderer )
318 {
319   // Initialize the renderer as we are now in render thread
320   renderer->Initialize( mImpl->context );
321
322   mImpl->rendererContainer.PushBack( renderer.Release() );
323 }
324
325 void RenderManager::RemoveRenderer( Render::Renderer* renderer )
326 {
327   mImpl->rendererContainer.EraseObject( renderer );
328 }
329
330 void RenderManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
331 {
332   mImpl->samplerContainer.PushBack( sampler.Release() );
333 }
334
335 void RenderManager::RemoveSampler( Render::Sampler* sampler )
336 {
337   mImpl->samplerContainer.EraseObject( sampler );
338 }
339
340 void RenderManager::AddTexture( OwnerPointer< Render::Texture >& texture )
341 {
342   texture->Initialize( mImpl->context );
343   mImpl->textureContainer.PushBack( texture.Release() );
344 }
345
346 void RenderManager::RemoveTexture( Render::Texture* texture )
347 {
348   DALI_ASSERT_DEBUG( NULL != texture );
349
350   // Find the texture, use reference to pointer so we can do the erase safely
351   for ( auto&& iter : mImpl->textureContainer )
352   {
353     if ( iter == texture )
354     {
355       texture->Destroy( mImpl->context );
356       mImpl->textureContainer.Erase( &iter ); // Texture found; now destroy it
357       return;
358     }
359   }
360 }
361
362 void RenderManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
363 {
364   texture->Upload( mImpl->context, pixelData, params );
365 }
366
367 void RenderManager::GenerateMipmaps( Render::Texture* texture )
368 {
369   texture->GenerateMipmaps( mImpl->context );
370 }
371
372 void RenderManager::SetFilterMode( Render::Sampler* sampler, uint32_t minFilterMode, uint32_t magFilterMode )
373 {
374   sampler->mMinificationFilter = static_cast<Dali::FilterMode::Type>(minFilterMode);
375   sampler->mMagnificationFilter = static_cast<Dali::FilterMode::Type>(magFilterMode );
376 }
377
378 void RenderManager::SetWrapMode( Render::Sampler* sampler, uint32_t rWrapMode, uint32_t sWrapMode, uint32_t tWrapMode )
379 {
380   sampler->mRWrapMode = static_cast<Dali::WrapMode::Type>(rWrapMode);
381   sampler->mSWrapMode = static_cast<Dali::WrapMode::Type>(sWrapMode);
382   sampler->mTWrapMode = static_cast<Dali::WrapMode::Type>(tWrapMode);
383 }
384
385 void RenderManager::AddFrameBuffer( OwnerPointer< Render::FrameBuffer >& frameBuffer )
386 {
387   Render::FrameBuffer* frameBufferPtr = frameBuffer.Release();
388   mImpl->frameBufferContainer.PushBack( frameBufferPtr );
389   frameBufferPtr->Initialize( mImpl->context );
390 }
391
392 void RenderManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer )
393 {
394   DALI_ASSERT_DEBUG( NULL != frameBuffer );
395
396   // Find the sampler, use reference so we can safely do the erase
397   for ( auto&& iter : mImpl->frameBufferContainer )
398   {
399     if ( iter == frameBuffer )
400     {
401       frameBuffer->Destroy( mImpl->context );
402       mImpl->frameBufferContainer.Erase( &iter ); // frameBuffer found; now destroy it
403
404       break;
405     }
406   }
407 }
408 void RenderManager::InitializeScene( SceneGraph::Scene* scene )
409 {
410   scene->Initialize( *mImpl->CreateSceneContext() );
411   mImpl->sceneContainer.push_back( scene );
412 }
413
414 void RenderManager::UninitializeScene( SceneGraph::Scene* scene )
415 {
416   mImpl->DestroySceneContext( scene->GetContext() );
417
418   auto iter = std::find( mImpl->sceneContainer.begin(), mImpl->sceneContainer.end(), scene );
419   if( iter != mImpl->sceneContainer.end() )
420   {
421     mImpl->sceneContainer.erase( iter );
422   }
423 }
424
425 void RenderManager::SurfaceReplaced( SceneGraph::Scene* scene )
426 {
427   Context* newContext = mImpl->ReplaceSceneContext( scene->GetContext() );
428   scene->Initialize( *newContext );
429 }
430
431 void RenderManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer )
432 {
433   frameBuffer->AttachColorTexture( mImpl->context, texture, mipmapLevel, layer );
434 }
435
436 void RenderManager::AttachDepthTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel )
437 {
438   frameBuffer->AttachDepthTexture( mImpl->context, texture, mipmapLevel );
439 }
440
441 void RenderManager::AttachDepthStencilTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel )
442 {
443   frameBuffer->AttachDepthStencilTexture( mImpl->context, texture, mipmapLevel );
444 }
445
446 void RenderManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer )
447 {
448   mImpl->propertyBufferContainer.PushBack( propertyBuffer.Release() );
449 }
450
451 void RenderManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
452 {
453   mImpl->propertyBufferContainer.EraseObject( propertyBuffer );
454 }
455
456 void RenderManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
457 {
458   propertyBuffer->SetFormat( format.Release() );
459 }
460
461 void RenderManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<uint8_t> >& data, uint32_t size )
462 {
463   propertyBuffer->SetData( data.Release(), size );
464 }
465
466 void RenderManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<uint16_t>& indices )
467 {
468   geometry->SetIndexBuffer( indices );
469 }
470
471 void RenderManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
472 {
473   mImpl->geometryContainer.PushBack( geometry.Release() );
474 }
475
476 void RenderManager::RemoveGeometry( Render::Geometry* geometry )
477 {
478   mImpl->geometryContainer.EraseObject( geometry );
479 }
480
481 void RenderManager::AttachVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
482 {
483   DALI_ASSERT_DEBUG( NULL != geometry );
484
485   // Find the geometry
486   for ( auto&& iter : mImpl->geometryContainer )
487   {
488     if ( iter == geometry )
489     {
490       iter->AddPropertyBuffer( propertyBuffer );
491       break;
492     }
493   }
494 }
495
496 void RenderManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
497 {
498   DALI_ASSERT_DEBUG( NULL != geometry );
499
500   // Find the geometry
501   for ( auto&& iter : mImpl->geometryContainer )
502   {
503     if ( iter == geometry )
504     {
505       iter->RemovePropertyBuffer( propertyBuffer );
506       break;
507     }
508   }
509 }
510
511 void RenderManager::SetGeometryType( Render::Geometry* geometry, uint32_t geometryType )
512 {
513   geometry->SetType( Render::Geometry::Type(geometryType) );
514 }
515
516 void RenderManager::AddRenderTracker( Render::RenderTracker* renderTracker )
517 {
518   mImpl->AddRenderTracker(renderTracker);
519 }
520
521 void RenderManager::RemoveRenderTracker( Render::RenderTracker* renderTracker )
522 {
523   mImpl->RemoveRenderTracker(renderTracker);
524 }
525
526 ProgramCache* RenderManager::GetProgramCache()
527 {
528   return &(mImpl->programController);
529 }
530
531 void RenderManager::PreRender( Integration::RenderStatus& status, bool forceClear, bool uploadOnly )
532 {
533   DALI_PRINT_RENDER_START( mImpl->renderBufferIndex );
534
535   // Core::Render documents that GL context must be current before calling Render
536   DALI_ASSERT_DEBUG( mImpl->context.IsGlContextCreated() );
537
538   // Increment the frame count at the beginning of each frame
539   ++mImpl->frameCount;
540
541   // Process messages queued during previous update
542   mImpl->renderQueue.ProcessMessages( mImpl->renderBufferIndex );
543
544   uint32_t count = 0u;
545   for( uint32_t i = 0; i < mImpl->sceneContainer.size(); ++i )
546   {
547     count += mImpl->sceneContainer[i]->GetRenderInstructions().Count( mImpl->renderBufferIndex );
548   }
549
550   const bool haveInstructions = count > 0u;
551
552   DALI_LOG_INFO( gLogFilter, Debug::General,
553                  "Render: haveInstructions(%s) || mImpl->lastFrameWasRendered(%s) || forceClear(%s)\n",
554                  haveInstructions ? "true" : "false",
555                  mImpl->lastFrameWasRendered ? "true" : "false",
556                  forceClear ? "true" : "false" );
557
558   // Only render if we have instructions to render, or the last frame was rendered (and therefore a clear is required).
559   if( haveInstructions || mImpl->lastFrameWasRendered || forceClear )
560   {
561     DALI_LOG_INFO( gLogFilter, Debug::General, "Render: Processing\n" );
562
563     // Switch to the shared context
564     if ( mImpl->currentContext != &mImpl->context )
565     {
566       mImpl->currentContext = &mImpl->context;
567
568       if ( mImpl->currentContext->IsSurfacelessContextSupported() )
569       {
570         mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent();
571       }
572
573       // Clear the current cached program when the context is switched
574       mImpl->programController.ClearCurrentProgram();
575     }
576
577     // Upload the geometries
578     for( uint32_t i = 0; i < mImpl->sceneContainer.size(); ++i )
579     {
580       RenderInstructionContainer& instructions = mImpl->sceneContainer[i]->GetRenderInstructions();
581       for ( uint32_t j = 0; j < instructions.Count( mImpl->renderBufferIndex ); ++j )
582       {
583         RenderInstruction& instruction = instructions.At( mImpl->renderBufferIndex, j );
584
585         const Matrix* viewMatrix       = instruction.GetViewMatrix( mImpl->renderBufferIndex );
586         const Matrix* projectionMatrix = instruction.GetProjectionMatrix( mImpl->renderBufferIndex );
587
588         DALI_ASSERT_DEBUG( viewMatrix );
589         DALI_ASSERT_DEBUG( projectionMatrix );
590
591         if( viewMatrix && projectionMatrix )
592         {
593           const RenderListContainer::SizeType renderListCount = instruction.RenderListCount();
594
595           // Iterate through each render list.
596           for( RenderListContainer::SizeType index = 0; index < renderListCount; ++index )
597           {
598             const RenderList* renderList = instruction.GetRenderList( index );
599
600             if( renderList && !renderList->IsEmpty() )
601             {
602               const std::size_t itemCount = renderList->Count();
603               for( uint32_t itemIndex = 0u; itemIndex < itemCount; ++itemIndex )
604               {
605                 const RenderItem& item = renderList->GetItem( itemIndex );
606                 if( DALI_LIKELY( item.mRenderer ) )
607                 {
608                   item.mRenderer->Upload( *mImpl->currentContext );
609                 }
610               }
611             }
612           }
613         }
614       }
615     }
616   }
617 }
618
619 void RenderManager::PreRender( Integration::Scene& scene, std::vector<Rect<int>>& damagedRects )
620 {
621   if (mImpl->partialUpdateAvailable != Integration::PartialUpdateAvailable::TRUE)
622   {
623     return;
624   }
625
626   // @TODO We need to do partial rendering rotation.
627   if( mImpl->defaultSurfaceOrientation != 0 )
628   {
629     return;
630   }
631
632   class DamagedRectsCleaner
633   {
634   public:
635     DamagedRectsCleaner(std::vector<Rect<int>>& damagedRects)
636     : mDamagedRects(damagedRects),
637       mCleanOnReturn(true)
638     {
639     }
640
641     void SetCleanOnReturn(bool cleanOnReturn)
642     {
643       mCleanOnReturn = cleanOnReturn;
644     }
645
646     ~DamagedRectsCleaner()
647     {
648       if (mCleanOnReturn)
649       {
650         mDamagedRects.clear();
651       }
652     }
653
654   private:
655     std::vector<Rect<int>>& mDamagedRects;
656     bool mCleanOnReturn;
657   };
658
659   Rect<int32_t> surfaceRect = Rect<int32_t>(0, 0, static_cast<int32_t>( scene.GetSize().width ), static_cast<int32_t>( scene.GetSize().height ));
660
661   // Clean collected dirty/damaged rects on exit if 3d layer or 3d node or other conditions.
662   DamagedRectsCleaner damagedRectCleaner(damagedRects);
663
664   // Mark previous dirty rects in the sorted array. The array is already sorted by node and renderer, frame number.
665   // so you don't need to sort: std::stable_sort(mImpl->itemsDirtyRects.begin(), mImpl->itemsDirtyRects.end());
666   for (DirtyRect& dirtyRect : mImpl->itemsDirtyRects)
667   {
668     dirtyRect.visited = false;
669   }
670
671   Internal::Scene& sceneInternal = GetImplementation(scene);
672   SceneGraph::Scene* sceneObject = sceneInternal.GetSceneObject();
673   uint32_t count = sceneObject->GetRenderInstructions().Count( mImpl->renderBufferIndex );
674   for (uint32_t i = 0; i < count; ++i)
675   {
676     RenderInstruction& instruction = sceneObject->GetRenderInstructions().At( mImpl->renderBufferIndex, i );
677
678     if (instruction.mFrameBuffer)
679     {
680       return; // TODO: reset, we don't deal with render tasks with framebuffers (for now)
681     }
682
683     const Camera* camera = instruction.GetCamera();
684     if (camera->mType == Camera::DEFAULT_TYPE && camera->mTargetPosition == Camera::DEFAULT_TARGET_POSITION)
685     {
686       const Node* node = instruction.GetCamera()->GetNode();
687       if (node)
688       {
689         Vector3 position;
690         Vector3 scale;
691         Quaternion orientation;
692         node->GetWorldMatrix(mImpl->renderBufferIndex).GetTransformComponents(position, orientation, scale);
693
694         Vector3 orientationAxis;
695         Radian orientationAngle;
696         orientation.ToAxisAngle( orientationAxis, orientationAngle );
697
698         if (position.x > Math::MACHINE_EPSILON_10000 ||
699             position.y > Math::MACHINE_EPSILON_10000 ||
700             orientationAxis != Vector3(0.0f, 1.0f, 0.0f) ||
701             orientationAngle != ANGLE_180 ||
702             scale != Vector3(1.0f, 1.0f, 1.0f))
703         {
704           return;
705         }
706       }
707     }
708     else
709     {
710       return;
711     }
712
713     Rect<int32_t> viewportRect;
714     if (instruction.mIsViewportSet)
715     {
716       const int32_t y = (surfaceRect.height - instruction.mViewport.height) - instruction.mViewport.y;
717       viewportRect.Set(instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height);
718       if (viewportRect.IsEmpty() || !viewportRect.IsValid())
719       {
720         return; // just skip funny use cases for now, empty viewport means it is set somewhere else
721       }
722     }
723     else
724     {
725       viewportRect = surfaceRect;
726     }
727
728     const Matrix* viewMatrix       = instruction.GetViewMatrix(mImpl->renderBufferIndex);
729     const Matrix* projectionMatrix = instruction.GetProjectionMatrix(mImpl->renderBufferIndex);
730     if (viewMatrix && projectionMatrix)
731     {
732       const RenderListContainer::SizeType count = instruction.RenderListCount();
733       for (RenderListContainer::SizeType index = 0u; index < count; ++index)
734       {
735         const RenderList* renderList = instruction.GetRenderList( index );
736         if (renderList && !renderList->IsEmpty())
737         {
738           const std::size_t count = renderList->Count();
739           for (uint32_t index = 0u; index < count; ++index)
740           {
741             RenderItem& item = renderList->GetItem( index );
742             // If the item does 3D transformation, do early exit and clean the damaged rect array
743             if (item.mUpdateSize == Vector3::ZERO)
744             {
745               return;
746             }
747
748             Rect<int> rect;
749             DirtyRect dirtyRect(item.mNode, item.mRenderer, mImpl->frameCount, rect);
750             // If the item refers to updated node or renderer.
751             if (item.mIsUpdated ||
752                 (item.mNode &&
753                 (item.mNode->Updated() || (item.mRenderer && item.mRenderer->Updated(mImpl->renderBufferIndex, item.mNode)))))
754             {
755               item.mIsUpdated = false;
756               item.mNode->SetUpdated(false);
757
758               rect = item.CalculateViewportSpaceAABB(item.mUpdateSize, viewportRect.width, viewportRect.height);
759               if (rect.IsValid() && rect.Intersect(viewportRect) && !rect.IsEmpty())
760               {
761                 const int left = rect.x;
762                 const int top = rect.y;
763                 const int right = rect.x + rect.width;
764                 const int bottom = rect.y + rect.height;
765                 rect.x = (left / 16) * 16;
766                 rect.y = (top / 16) * 16;
767                 rect.width = ((right + 16) / 16) * 16 - rect.x;
768                 rect.height = ((bottom + 16) / 16) * 16 - rect.y;
769
770                 // Found valid dirty rect.
771                 // 1. Insert it in the sorted array of the dirty rects.
772                 // 2. Mark the related dirty rects as visited so they will not be removed below.
773                 // 3. Keep only last 3 dirty rects for the same node and renderer (Tizen uses 3 back buffers, Ubuntu 1).
774                 dirtyRect.rect = rect;
775                 auto dirtyRectPos = std::lower_bound(mImpl->itemsDirtyRects.begin(), mImpl->itemsDirtyRects.end(), dirtyRect);
776                 dirtyRectPos = mImpl->itemsDirtyRects.insert(dirtyRectPos, dirtyRect);
777
778                 int c = 1;
779                 while (++dirtyRectPos != mImpl->itemsDirtyRects.end())
780                 {
781                   if (dirtyRectPos->node != item.mNode || dirtyRectPos->renderer != item.mRenderer)
782                   {
783                     break;
784                   }
785
786                   dirtyRectPos->visited = true;
787                   Rect<int>& dirtRect = dirtyRectPos->rect;
788                   rect.Merge(dirtRect);
789
790                   c++;
791                   if (c > 3) // no more then 3 previous rects
792                   {
793                     mImpl->itemsDirtyRects.erase(dirtyRectPos);
794                     break;
795                   }
796                 }
797
798                 damagedRects.push_back(rect);
799               }
800             }
801             else
802             {
803               // 1. The item is not dirty, the node and renderer referenced by the item are still exist.
804               // 2. Mark the related dirty rects as visited so they will not be removed below.
805               auto dirtyRectPos = std::lower_bound(mImpl->itemsDirtyRects.begin(), mImpl->itemsDirtyRects.end(), dirtyRect);
806               while (dirtyRectPos != mImpl->itemsDirtyRects.end())
807               {
808                 if (dirtyRectPos->node != item.mNode || dirtyRectPos->renderer != item.mRenderer)
809                 {
810                   break;
811                 }
812
813                 dirtyRectPos->visited = true;
814                 dirtyRectPos++;
815               }
816             }
817           }
818         }
819       }
820     }
821   }
822
823   // Check removed nodes or removed renderers dirty rects
824   auto i = mImpl->itemsDirtyRects.begin();
825   auto j = mImpl->itemsDirtyRects.begin();
826   while (i != mImpl->itemsDirtyRects.end())
827   {
828     if (i->visited)
829     {
830       *j++ = *i;
831     }
832     else
833     {
834       Rect<int>& dirtRect = i->rect;
835       damagedRects.push_back(dirtRect);
836     }
837     i++;
838   }
839
840   if( j != mImpl->itemsDirtyRects.begin() )
841   {
842     mImpl->itemsDirtyRects.resize(j - mImpl->itemsDirtyRects.begin());
843   }
844   damagedRectCleaner.SetCleanOnReturn(false);
845 }
846
847 void RenderManager::RenderScene( Integration::RenderStatus& status, Integration::Scene& scene, bool renderToFbo )
848 {
849   Rect<int> clippingRect;
850   RenderScene( status, scene, renderToFbo, clippingRect);
851 }
852
853 void RenderManager::RenderScene( Integration::RenderStatus& status, Integration::Scene& scene, bool renderToFbo, Rect<int>& clippingRect )
854 {
855   Internal::Scene& sceneInternal = GetImplementation( scene );
856   SceneGraph::Scene* sceneObject = sceneInternal.GetSceneObject();
857
858   uint32_t count = sceneObject->GetRenderInstructions().Count( mImpl->renderBufferIndex );
859
860   for( uint32_t i = 0; i < count; ++i )
861   {
862     RenderInstruction& instruction = sceneObject->GetRenderInstructions().At( mImpl->renderBufferIndex, i );
863
864     if ( ( renderToFbo && !instruction.mFrameBuffer ) || ( !renderToFbo && instruction.mFrameBuffer ) )
865     {
866       continue; // skip
867     }
868
869     // Mark that we will require a post-render step to be performed (includes swap-buffers).
870     status.SetNeedsPostRender( true );
871
872     Rect<int32_t> viewportRect;
873     Vector4   clearColor;
874
875     if ( instruction.mIsClearColorSet )
876     {
877       clearColor = instruction.mClearColor;
878     }
879     else
880     {
881       clearColor = Dali::RenderTask::DEFAULT_CLEAR_COLOR;
882     }
883
884     Rect<int32_t> surfaceRect = mImpl->defaultSurfaceRect;
885     Integration::DepthBufferAvailable depthBufferAvailable = mImpl->depthBufferAvailable;
886     Integration::StencilBufferAvailable stencilBufferAvailable = mImpl->stencilBufferAvailable;
887     int surfaceOrientation = mImpl->defaultSurfaceOrientation;
888
889     if ( instruction.mFrameBuffer )
890     {
891       // offscreen buffer
892       if ( mImpl->currentContext != &mImpl->context )
893       {
894         // Switch to shared context for off-screen buffer
895         mImpl->currentContext = &mImpl->context;
896
897         if ( mImpl->currentContext->IsSurfacelessContextSupported() )
898         {
899           mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent();
900         }
901
902         // Clear the current cached program when the context is switched
903         mImpl->programController.ClearCurrentProgram();
904       }
905     }
906     else
907     {
908       if ( mImpl->currentContext->IsSurfacelessContextSupported() )
909       {
910         if ( mImpl->currentContext != sceneObject->GetContext() )
911         {
912           // Switch the correct context if rendering to a surface
913           mImpl->currentContext = sceneObject->GetContext();
914
915           // Clear the current cached program when the context is switched
916           mImpl->programController.ClearCurrentProgram();
917         }
918       }
919
920       surfaceRect = Rect<int32_t>( 0, 0, static_cast<int32_t>( scene.GetSize().width ), static_cast<int32_t>( scene.GetSize().height ) );
921     }
922
923     // Make sure that GL context must be created
924      mImpl->currentContext->GlContextCreated();
925
926     // reset the program matrices for all programs once per frame
927     // this ensures we will set view and projection matrix once per program per camera
928     mImpl->programController.ResetProgramMatrices();
929
930     if( instruction.mFrameBuffer )
931     {
932       instruction.mFrameBuffer->Bind( *mImpl->currentContext );
933
934       // For each offscreen buffer, update the dependency list with the new texture id used by this frame buffer.
935       for (unsigned int i0 = 0, i1 = instruction.mFrameBuffer->GetColorAttachmentCount(); i0 < i1; ++i0)
936       {
937         mImpl->textureDependencyList.PushBack( instruction.mFrameBuffer->GetTextureId(i0) );
938       }
939     }
940     else
941     {
942       mImpl->currentContext->BindFramebuffer( GL_FRAMEBUFFER, 0u );
943     }
944
945     if ( !instruction.mFrameBuffer )
946     {
947       mImpl->currentContext->Viewport( surfaceRect.x,
948                                        surfaceRect.y,
949                                        surfaceRect.width,
950                                        surfaceRect.height );
951     }
952
953     // Clear the entire color, depth and stencil buffers for the default framebuffer, if required.
954     // It is important to clear all 3 buffers when they are being used, for performance on deferred renderers
955     // e.g. previously when the depth & stencil buffers were NOT cleared, it caused the DDK to exceed a "vertex count limit",
956     // and then stall. That problem is only noticeable when rendering a large number of vertices per frame.
957     GLbitfield clearMask = GL_COLOR_BUFFER_BIT;
958
959     mImpl->currentContext->ColorMask( true );
960
961     if( depthBufferAvailable == Integration::DepthBufferAvailable::TRUE )
962     {
963       mImpl->currentContext->DepthMask( true );
964       clearMask |= GL_DEPTH_BUFFER_BIT;
965     }
966
967     if( stencilBufferAvailable == Integration::StencilBufferAvailable::TRUE)
968     {
969       mImpl->currentContext->ClearStencil( 0 );
970       mImpl->currentContext->StencilMask( 0xFF ); // 8 bit stencil mask, all 1's
971       clearMask |= GL_STENCIL_BUFFER_BIT;
972     }
973
974     if( !instruction.mIgnoreRenderToFbo && ( instruction.mFrameBuffer != 0 ) )
975     {
976       // Offscreen buffer rendering
977       if ( instruction.mIsViewportSet )
978       {
979         // For glViewport the lower-left corner is (0,0)
980         const int32_t y = ( instruction.mFrameBuffer->GetHeight() - instruction.mViewport.height ) - instruction.mViewport.y;
981         viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
982       }
983       else
984       {
985         viewportRect.Set( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
986       }
987       surfaceOrientation = 0;
988     }
989     else // No Offscreen frame buffer rendering
990     {
991       // Check whether a viewport is specified, otherwise the full surface size is used
992       if ( instruction.mIsViewportSet )
993       {
994         // For glViewport the lower-left corner is (0,0)
995         const int32_t y = ( surfaceRect.height - instruction.mViewport.height ) - instruction.mViewport.y;
996         viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
997       }
998       else
999       {
1000         viewportRect = surfaceRect;
1001       }
1002     }
1003
1004     if( surfaceOrientation == 90 || surfaceOrientation == 270 )
1005     {
1006       int temp = viewportRect.width;
1007       viewportRect.width = viewportRect.height;
1008       viewportRect.height = temp;
1009     }
1010
1011     bool clearFullFrameRect = true;
1012     if( instruction.mFrameBuffer != 0 )
1013     {
1014       Viewport frameRect( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
1015       clearFullFrameRect = ( frameRect == viewportRect );
1016     }
1017     else
1018     {
1019       clearFullFrameRect = ( surfaceRect == viewportRect );
1020     }
1021
1022     if (!clippingRect.IsEmpty())
1023     {
1024       if (!clippingRect.Intersect(viewportRect))
1025       {
1026         DALI_LOG_ERROR("Invalid clipping rect %d %d %d %d\n", clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height);
1027         clippingRect = Rect<int>();
1028       }
1029       clearFullFrameRect = false;
1030     }
1031
1032     mImpl->currentContext->Viewport(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height);
1033
1034     if (instruction.mIsClearColorSet)
1035     {
1036       mImpl->currentContext->ClearColor(clearColor.r,
1037                                         clearColor.g,
1038                                         clearColor.b,
1039                                         clearColor.a);
1040       if (!clearFullFrameRect)
1041       {
1042         if (!clippingRect.IsEmpty())
1043         {
1044           mImpl->currentContext->SetScissorTest(true);
1045           mImpl->currentContext->Scissor(clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height);
1046           mImpl->currentContext->Clear(clearMask, Context::FORCE_CLEAR);
1047           mImpl->currentContext->SetScissorTest(false);
1048         }
1049         else
1050         {
1051           mImpl->currentContext->SetScissorTest(true);
1052           mImpl->currentContext->Scissor(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height);
1053           mImpl->currentContext->Clear(clearMask, Context::FORCE_CLEAR);
1054           mImpl->currentContext->SetScissorTest(false);
1055         }
1056       }
1057       else
1058       {
1059         mImpl->currentContext->SetScissorTest(false);
1060         mImpl->currentContext->Clear(clearMask, Context::FORCE_CLEAR);
1061       }
1062     }
1063
1064     // Clear the list of bound textures
1065     mImpl->boundTextures.Clear();
1066
1067     mImpl->renderAlgorithms.ProcessRenderInstruction(
1068         instruction,
1069         *mImpl->currentContext,
1070         mImpl->renderBufferIndex,
1071         depthBufferAvailable,
1072         stencilBufferAvailable,
1073         mImpl->boundTextures,
1074         clippingRect,
1075         surfaceOrientation );
1076
1077     // Synchronise the FBO/Texture access when there are multiple contexts
1078     if ( mImpl->currentContext->IsSurfacelessContextSupported() )
1079     {
1080       // Check whether any binded texture is in the dependency list
1081       bool textureFound = false;
1082
1083       if ( mImpl->boundTextures.Count() > 0u && mImpl->textureDependencyList.Count() > 0u )
1084       {
1085         for ( auto textureId : mImpl->textureDependencyList )
1086         {
1087
1088           textureFound = std::find_if( mImpl->boundTextures.Begin(), mImpl->boundTextures.End(),
1089                                        [textureId]( GLuint id )
1090                                        {
1091                                          return textureId == id;
1092                                        } ) != mImpl->boundTextures.End();
1093         }
1094       }
1095
1096       if ( textureFound )
1097       {
1098         if ( instruction.mFrameBuffer )
1099         {
1100           // For off-screen buffer
1101
1102           // Wait until all rendering calls for the currently context are executed
1103           mImpl->glContextHelperAbstraction.WaitClient();
1104
1105           // Clear the dependency list
1106           mImpl->textureDependencyList.Clear();
1107         }
1108         else
1109         {
1110           // Worker thread lambda function
1111           auto& glContextHelperAbstraction = mImpl->glContextHelperAbstraction;
1112           auto workerFunction = [&glContextHelperAbstraction]( int workerThread )
1113           {
1114             // Switch to the shared context in the worker thread
1115             glContextHelperAbstraction.MakeSurfacelessContextCurrent();
1116
1117             // Wait until all rendering calls for the shared context are executed
1118             glContextHelperAbstraction.WaitClient();
1119
1120             // Must clear the context in the worker thread
1121             // Otherwise the shared context cannot be switched to from the render thread
1122             glContextHelperAbstraction.MakeContextNull();
1123           };
1124
1125           auto future = mImpl->threadPool->SubmitTask( 0u, workerFunction );
1126           if ( future )
1127           {
1128             mImpl->threadPool->Wait();
1129
1130             // Clear the dependency list
1131             mImpl->textureDependencyList.Clear();
1132           }
1133         }
1134       }
1135     }
1136
1137     if( instruction.mRenderTracker && instruction.mFrameBuffer )
1138     {
1139       // This will create a sync object every frame this render tracker
1140       // is alive (though it should be now be created only for
1141       // render-once render tasks)
1142       instruction.mRenderTracker->CreateSyncObject( mImpl->glSyncAbstraction );
1143       instruction.mRenderTracker = nullptr; // Only create once.
1144     }
1145
1146     if ( renderToFbo )
1147     {
1148       mImpl->currentContext->Flush();
1149     }
1150   }
1151
1152   GLenum attachments[] = { GL_DEPTH, GL_STENCIL };
1153   mImpl->currentContext->InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
1154 }
1155
1156 void RenderManager::PostRender( bool uploadOnly )
1157 {
1158   if ( !uploadOnly )
1159   {
1160     if ( mImpl->currentContext->IsSurfacelessContextSupported() )
1161     {
1162       mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent();
1163     }
1164
1165     GLenum attachments[] = { GL_DEPTH, GL_STENCIL };
1166     mImpl->context.InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
1167   }
1168
1169   //Notify RenderGeometries that rendering has finished
1170   for ( auto&& iter : mImpl->geometryContainer )
1171   {
1172     iter->OnRenderFinished();
1173   }
1174
1175   mImpl->UpdateTrackers();
1176
1177
1178   uint32_t count = 0u;
1179   for( uint32_t i = 0; i < mImpl->sceneContainer.size(); ++i )
1180   {
1181     count += mImpl->sceneContainer[i]->GetRenderInstructions().Count( mImpl->renderBufferIndex );
1182   }
1183
1184   const bool haveInstructions = count > 0u;
1185
1186   // If this frame was rendered due to instructions existing, we mark this so we know to clear the next frame.
1187   mImpl->lastFrameWasRendered = haveInstructions;
1188
1189   /**
1190    * The rendering has finished; swap to the next buffer.
1191    * Ideally the update has just finished using this buffer; otherwise the render thread
1192    * should block until the update has finished.
1193    */
1194   mImpl->renderBufferIndex = (0 != mImpl->renderBufferIndex) ? 0 : 1;
1195
1196   DALI_PRINT_RENDER_END();
1197 }
1198
1199 } // namespace SceneGraph
1200
1201 } // namespace Internal
1202
1203 } // namespace Dali