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