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