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