Revert "[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(NULL)
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   class DamagedRectsCleaner
627   {
628   public:
629     DamagedRectsCleaner(std::vector<Rect<int>>& damagedRects)
630     : mDamagedRects(damagedRects),
631       mCleanOnReturn(true)
632     {
633     }
634
635     void SetCleanOnReturn(bool cleanOnReturn)
636     {
637       mCleanOnReturn = cleanOnReturn;
638     }
639
640     ~DamagedRectsCleaner()
641     {
642       if (mCleanOnReturn)
643       {
644         mDamagedRects.clear();
645       }
646     }
647
648   private:
649     std::vector<Rect<int>>& mDamagedRects;
650     bool mCleanOnReturn;
651   };
652
653   Rect<int32_t> surfaceRect = Rect<int32_t>(0, 0, static_cast<int32_t>( scene.GetSize().width ), static_cast<int32_t>( scene.GetSize().height ));
654
655   // Clean collected dirty/damaged rects on exit if 3d layer or 3d node or other conditions.
656   DamagedRectsCleaner damagedRectCleaner(damagedRects);
657
658   // Mark previous dirty rects in the sorted array. The array is already sorted by node and renderer, frame number.
659   // so you don't need to sort: std::stable_sort(mImpl->itemsDirtyRects.begin(), mImpl->itemsDirtyRects.end());
660   for (DirtyRect& dirtyRect : mImpl->itemsDirtyRects)
661   {
662     dirtyRect.visited = false;
663   }
664
665   Internal::Scene& sceneInternal = GetImplementation(scene);
666   SceneGraph::Scene* sceneObject = sceneInternal.GetSceneObject();
667   uint32_t count = sceneObject->GetRenderInstructions().Count( mImpl->renderBufferIndex );
668   for (uint32_t i = 0; i < count; ++i)
669   {
670     RenderInstruction& instruction = sceneObject->GetRenderInstructions().At( mImpl->renderBufferIndex, i );
671
672     if (instruction.mFrameBuffer)
673     {
674       return; // TODO: reset, we don't deal with render tasks with framebuffers (for now)
675     }
676
677     const Camera* camera = instruction.GetCamera();
678     if (camera->mType == Camera::DEFAULT_TYPE && camera->mTargetPosition == Camera::DEFAULT_TARGET_POSITION)
679     {
680       const Node* node = instruction.GetCamera()->GetNode();
681       if (node)
682       {
683         Vector3 position;
684         Vector3 scale;
685         Quaternion orientation;
686         node->GetWorldMatrix(mImpl->renderBufferIndex).GetTransformComponents(position, orientation, scale);
687
688         Vector3 orientationAxis;
689         Radian orientationAngle;
690         orientation.ToAxisAngle( orientationAxis, orientationAngle );
691
692         if (position.x > Math::MACHINE_EPSILON_10000 ||
693             position.y > Math::MACHINE_EPSILON_10000 ||
694             orientationAxis != Vector3(0.0f, 1.0f, 0.0f) ||
695             orientationAngle != ANGLE_180 ||
696             scale != Vector3(1.0f, 1.0f, 1.0f))
697         {
698           return;
699         }
700       }
701     }
702     else
703     {
704       return;
705     }
706
707     Rect<int32_t> viewportRect;
708     if (instruction.mIsViewportSet)
709     {
710       const int32_t y = (surfaceRect.height - instruction.mViewport.height) - instruction.mViewport.y;
711       viewportRect.Set(instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height);
712       if (viewportRect.IsEmpty() || !viewportRect.IsValid())
713       {
714         return; // just skip funny use cases for now, empty viewport means it is set somewhere else
715       }
716     }
717     else
718     {
719       viewportRect = surfaceRect;
720     }
721
722     const Matrix* viewMatrix       = instruction.GetViewMatrix(mImpl->renderBufferIndex);
723     const Matrix* projectionMatrix = instruction.GetProjectionMatrix(mImpl->renderBufferIndex);
724     if (viewMatrix && projectionMatrix)
725     {
726       const RenderListContainer::SizeType count = instruction.RenderListCount();
727       for (RenderListContainer::SizeType index = 0u; index < count; ++index)
728       {
729         const RenderList* renderList = instruction.GetRenderList( index );
730         if (renderList && !renderList->IsEmpty())
731         {
732           const std::size_t count = renderList->Count();
733           for (uint32_t index = 0u; index < count; ++index)
734           {
735             RenderItem& item = renderList->GetItem( index );
736             // If the item does 3D transformation, do early exit and clean the damaged rect array
737             if (item.mUpdateSize == Vector3::ZERO)
738             {
739               return;
740             }
741
742             Rect<int> rect;
743             DirtyRect dirtyRect(item.mNode, item.mRenderer, mImpl->frameCount, rect);
744             // If the item refers to updated node or renderer.
745             if (item.mIsUpdated ||
746                 (item.mNode &&
747                 (item.mNode->Updated() || (item.mRenderer && item.mRenderer->Updated(mImpl->renderBufferIndex, item.mNode)))))
748             {
749               item.mIsUpdated = false;
750               item.mNode->SetUpdated(false);
751
752               rect = item.CalculateViewportSpaceAABB(item.mUpdateSize, viewportRect.width, viewportRect.height);
753               if (rect.IsValid() && rect.Intersect(viewportRect) && !rect.IsEmpty())
754               {
755                 const int left = rect.x;
756                 const int top = rect.y;
757                 const int right = rect.x + rect.width;
758                 const int bottom = rect.y + rect.height;
759                 rect.x = (left / 16) * 16;
760                 rect.y = (top / 16) * 16;
761                 rect.width = ((right + 16) / 16) * 16 - rect.x;
762                 rect.height = ((bottom + 16) / 16) * 16 - rect.y;
763
764                 // Found valid dirty rect.
765                 // 1. Insert it in the sorted array of the dirty rects.
766                 // 2. Mark the related dirty rects as visited so they will not be removed below.
767                 // 3. Keep only last 3 dirty rects for the same node and renderer (Tizen uses 3 back buffers, Ubuntu 1).
768                 dirtyRect.rect = rect;
769                 auto dirtyRectPos = std::lower_bound(mImpl->itemsDirtyRects.begin(), mImpl->itemsDirtyRects.end(), dirtyRect);
770                 dirtyRectPos = mImpl->itemsDirtyRects.insert(dirtyRectPos, dirtyRect);
771
772                 int c = 1;
773                 while (++dirtyRectPos != mImpl->itemsDirtyRects.end())
774                 {
775                   if (dirtyRectPos->node != item.mNode || dirtyRectPos->renderer != item.mRenderer)
776                   {
777                     break;
778                   }
779
780                   dirtyRectPos->visited = true;
781                   Rect<int>& dirtRect = dirtyRectPos->rect;
782                   rect.Merge(dirtRect);
783
784                   c++;
785                   if (c > 3) // no more then 3 previous rects
786                   {
787                     mImpl->itemsDirtyRects.erase(dirtyRectPos);
788                     break;
789                   }
790                 }
791
792                 damagedRects.push_back(rect);
793               }
794             }
795             else
796             {
797               // 1. The item is not dirty, the node and renderer referenced by the item are still exist.
798               // 2. Mark the related dirty rects as visited so they will not be removed below.
799               auto dirtyRectPos = std::lower_bound(mImpl->itemsDirtyRects.begin(), mImpl->itemsDirtyRects.end(), dirtyRect);
800               while (dirtyRectPos != mImpl->itemsDirtyRects.end())
801               {
802                 if (dirtyRectPos->node != item.mNode || dirtyRectPos->renderer != item.mRenderer)
803                 {
804                   break;
805                 }
806
807                 dirtyRectPos->visited = true;
808                 dirtyRectPos++;
809               }
810             }
811           }
812         }
813       }
814     }
815   }
816
817   // Check removed nodes or removed renderers dirty rects
818   auto i = mImpl->itemsDirtyRects.begin();
819   auto j = mImpl->itemsDirtyRects.begin();
820   while (i != mImpl->itemsDirtyRects.end())
821   {
822     if (i->visited)
823     {
824       *j++ = *i;
825     }
826     else
827     {
828       Rect<int>& dirtRect = i->rect;
829       damagedRects.push_back(dirtRect);
830     }
831     i++;
832   }
833
834   mImpl->itemsDirtyRects.resize(j - mImpl->itemsDirtyRects.begin());
835   damagedRectCleaner.SetCleanOnReturn(false);
836 }
837
838 void RenderManager::RenderScene( Integration::RenderStatus& status, Integration::Scene& scene, bool renderToFbo )
839 {
840   Rect<int> clippingRect;
841   RenderScene( status, scene, renderToFbo, clippingRect);
842 }
843
844 void RenderManager::RenderScene( Integration::RenderStatus& status, Integration::Scene& scene, bool renderToFbo, Rect<int>& clippingRect )
845 {
846   Internal::Scene& sceneInternal = GetImplementation( scene );
847   SceneGraph::Scene* sceneObject = sceneInternal.GetSceneObject();
848
849   uint32_t count = sceneObject->GetRenderInstructions().Count( mImpl->renderBufferIndex );
850
851   for( uint32_t i = 0; i < count; ++i )
852   {
853     RenderInstruction& instruction = sceneObject->GetRenderInstructions().At( mImpl->renderBufferIndex, i );
854
855     if ( ( renderToFbo && !instruction.mFrameBuffer ) || ( !renderToFbo && instruction.mFrameBuffer ) )
856     {
857       continue; // skip
858     }
859
860     // Mark that we will require a post-render step to be performed (includes swap-buffers).
861     status.SetNeedsPostRender( true );
862
863     Rect<int32_t> viewportRect;
864     Vector4   clearColor;
865
866     if ( instruction.mIsClearColorSet )
867     {
868       clearColor = instruction.mClearColor;
869     }
870     else
871     {
872       clearColor = Dali::RenderTask::DEFAULT_CLEAR_COLOR;
873     }
874
875     Rect<int32_t> surfaceRect = mImpl->defaultSurfaceRect;
876     Integration::DepthBufferAvailable depthBufferAvailable = mImpl->depthBufferAvailable;
877     Integration::StencilBufferAvailable stencilBufferAvailable = mImpl->stencilBufferAvailable;
878     int surfaceOrientation = mImpl->defaultSurfaceOrientation;
879
880     if ( instruction.mFrameBuffer )
881     {
882       // offscreen buffer
883       if ( mImpl->currentContext != &mImpl->context )
884       {
885         // Switch to shared context for off-screen buffer
886         mImpl->currentContext = &mImpl->context;
887
888         if ( mImpl->currentContext->IsSurfacelessContextSupported() )
889         {
890           mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent();
891         }
892
893         // Clear the current cached program when the context is switched
894         mImpl->programController.ClearCurrentProgram();
895       }
896     }
897     else
898     {
899       if ( mImpl->currentContext->IsSurfacelessContextSupported() )
900       {
901         if ( mImpl->currentContext != sceneObject->GetContext() )
902         {
903           // Switch the correct context if rendering to a surface
904           mImpl->currentContext = sceneObject->GetContext();
905
906           // Clear the current cached program when the context is switched
907           mImpl->programController.ClearCurrentProgram();
908         }
909       }
910
911       surfaceRect = Rect<int32_t>( 0, 0, static_cast<int32_t>( scene.GetSize().width ), static_cast<int32_t>( scene.GetSize().height ) );
912     }
913
914     // Make sure that GL context must be created
915      mImpl->currentContext->GlContextCreated();
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       surfaceOrientation = 0;
979     }
980     else // No Offscreen frame buffer rendering
981     {
982       // Check whether a viewport is specified, otherwise the full surface size is used
983       if ( instruction.mIsViewportSet )
984       {
985         // For glViewport the lower-left corner is (0,0)
986         const int32_t y = ( surfaceRect.height - instruction.mViewport.height ) - instruction.mViewport.y;
987         viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
988       }
989       else
990       {
991         viewportRect = surfaceRect;
992       }
993     }
994
995     if( surfaceOrientation == 90 || surfaceOrientation == 270 )
996     {
997       int temp = viewportRect.width;
998       viewportRect.width = viewportRect.height;
999       viewportRect.height = temp;
1000     }
1001
1002     bool clearFullFrameRect = true;
1003     if( instruction.mFrameBuffer != 0 )
1004     {
1005       Viewport frameRect( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
1006       clearFullFrameRect = ( frameRect == viewportRect );
1007     }
1008     else
1009     {
1010       clearFullFrameRect = ( surfaceRect == viewportRect );
1011     }
1012
1013     if (!clippingRect.IsEmpty())
1014     {
1015       if (!clippingRect.Intersect(viewportRect))
1016       {
1017         DALI_LOG_ERROR("Invalid clipping rect %d %d %d %d\n", clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height);
1018         clippingRect = Rect<int>();
1019       }
1020       clearFullFrameRect = false;
1021     }
1022
1023     mImpl->currentContext->Viewport(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height);
1024
1025     if (instruction.mIsClearColorSet)
1026     {
1027       mImpl->currentContext->ClearColor(clearColor.r,
1028                                         clearColor.g,
1029                                         clearColor.b,
1030                                         clearColor.a);
1031       if (!clearFullFrameRect)
1032       {
1033         if (!clippingRect.IsEmpty())
1034         {
1035           mImpl->currentContext->SetScissorTest(true);
1036           mImpl->currentContext->Scissor(clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height);
1037           mImpl->currentContext->Clear(clearMask, Context::FORCE_CLEAR);
1038           mImpl->currentContext->SetScissorTest(false);
1039         }
1040         else
1041         {
1042           mImpl->currentContext->SetScissorTest(true);
1043           mImpl->currentContext->Scissor(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height);
1044           mImpl->currentContext->Clear(clearMask, Context::FORCE_CLEAR);
1045           mImpl->currentContext->SetScissorTest(false);
1046         }
1047       }
1048       else
1049       {
1050         mImpl->currentContext->SetScissorTest(false);
1051         mImpl->currentContext->Clear(clearMask, Context::FORCE_CLEAR);
1052       }
1053     }
1054
1055     // Clear the list of bound textures
1056     mImpl->boundTextures.Clear();
1057
1058     mImpl->renderAlgorithms.ProcessRenderInstruction(
1059         instruction,
1060         *mImpl->currentContext,
1061         mImpl->renderBufferIndex,
1062         depthBufferAvailable,
1063         stencilBufferAvailable,
1064         mImpl->boundTextures,
1065         clippingRect,
1066         surfaceOrientation );
1067
1068     // Synchronise the FBO/Texture access when there are multiple contexts
1069     if ( mImpl->currentContext->IsSurfacelessContextSupported() )
1070     {
1071       // Check whether any binded texture is in the dependency list
1072       bool textureFound = false;
1073
1074       if ( mImpl->boundTextures.Count() > 0u && mImpl->textureDependencyList.Count() > 0u )
1075       {
1076         for ( auto textureId : mImpl->textureDependencyList )
1077         {
1078
1079           textureFound = std::find_if( mImpl->boundTextures.Begin(), mImpl->boundTextures.End(),
1080                                        [textureId]( GLuint id )
1081                                        {
1082                                          return textureId == id;
1083                                        } ) != mImpl->boundTextures.End();
1084         }
1085       }
1086
1087       if ( textureFound )
1088       {
1089         if ( instruction.mFrameBuffer )
1090         {
1091           // For off-screen buffer
1092
1093           // Wait until all rendering calls for the currently context are executed
1094           mImpl->glContextHelperAbstraction.WaitClient();
1095
1096           // Clear the dependency list
1097           mImpl->textureDependencyList.Clear();
1098         }
1099         else
1100         {
1101           // Worker thread lambda function
1102           auto& glContextHelperAbstraction = mImpl->glContextHelperAbstraction;
1103           auto workerFunction = [&glContextHelperAbstraction]( int workerThread )
1104           {
1105             // Switch to the shared context in the worker thread
1106             glContextHelperAbstraction.MakeSurfacelessContextCurrent();
1107
1108             // Wait until all rendering calls for the shared context are executed
1109             glContextHelperAbstraction.WaitClient();
1110
1111             // Must clear the context in the worker thread
1112             // Otherwise the shared context cannot be switched to from the render thread
1113             glContextHelperAbstraction.MakeContextNull();
1114           };
1115
1116           auto future = mImpl->threadPool->SubmitTask( 0u, workerFunction );
1117           if ( future )
1118           {
1119             mImpl->threadPool->Wait();
1120
1121             // Clear the dependency list
1122             mImpl->textureDependencyList.Clear();
1123           }
1124         }
1125       }
1126     }
1127
1128     if( instruction.mRenderTracker && instruction.mFrameBuffer )
1129     {
1130       // This will create a sync object every frame this render tracker
1131       // is alive (though it should be now be created only for
1132       // render-once render tasks)
1133       instruction.mRenderTracker->CreateSyncObject( mImpl->glSyncAbstraction );
1134       instruction.mRenderTracker = nullptr; // Only create once.
1135     }
1136
1137     if ( renderToFbo )
1138     {
1139       mImpl->currentContext->Flush();
1140     }
1141   }
1142
1143   GLenum attachments[] = { GL_DEPTH, GL_STENCIL };
1144   mImpl->currentContext->InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
1145 }
1146
1147 void RenderManager::PostRender( bool uploadOnly )
1148 {
1149   if ( !uploadOnly )
1150   {
1151     if ( mImpl->currentContext->IsSurfacelessContextSupported() )
1152     {
1153       mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent();
1154     }
1155
1156     GLenum attachments[] = { GL_DEPTH, GL_STENCIL };
1157     mImpl->context.InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
1158   }
1159
1160   //Notify RenderGeometries that rendering has finished
1161   for ( auto&& iter : mImpl->geometryContainer )
1162   {
1163     iter->OnRenderFinished();
1164   }
1165
1166   mImpl->UpdateTrackers();
1167
1168
1169   uint32_t count = 0u;
1170   for( uint32_t i = 0; i < mImpl->sceneContainer.size(); ++i )
1171   {
1172     count += mImpl->sceneContainer[i]->GetRenderInstructions().Count( mImpl->renderBufferIndex );
1173   }
1174
1175   const bool haveInstructions = count > 0u;
1176
1177   // If this frame was rendered due to instructions existing, we mark this so we know to clear the next frame.
1178   mImpl->lastFrameWasRendered = haveInstructions;
1179
1180   /**
1181    * The rendering has finished; swap to the next buffer.
1182    * Ideally the update has just finished using this buffer; otherwise the render thread
1183    * should block until the update has finished.
1184    */
1185   mImpl->renderBufferIndex = (0 != mImpl->renderBufferIndex) ? 0 : 1;
1186
1187   DALI_PRINT_RENDER_END();
1188 }
1189
1190 } // namespace SceneGraph
1191
1192 } // namespace Internal
1193
1194 } // namespace Dali