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