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