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