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