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