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