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