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