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