[Tizen] Partial rendering rotation does not work
[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   // @TODO We need to do partial rendering rotation.
577   if( mImpl->defaultSurfaceOrientation != 0 )
578   {
579     return;
580   }
581
582   class DamagedRectsCleaner
583   {
584   public:
585     DamagedRectsCleaner(std::vector<Rect<int>>& damagedRects)
586     : mDamagedRects(damagedRects),
587       mCleanOnReturn(true)
588     {
589     }
590
591     void SetCleanOnReturn(bool cleanOnReturn)
592     {
593       mCleanOnReturn = cleanOnReturn;
594     }
595
596     ~DamagedRectsCleaner()
597     {
598       if (mCleanOnReturn)
599       {
600         mDamagedRects.clear();
601       }
602     }
603
604   private:
605     std::vector<Rect<int>>& mDamagedRects;
606     bool mCleanOnReturn;
607   };
608
609   Rect<int32_t> surfaceRect = Rect<int32_t>(0, 0, static_cast<int32_t>( scene.GetSize().width ), static_cast<int32_t>( scene.GetSize().height ));
610
611   // Clean collected dirty/damaged rects on exit if 3d layer or 3d node or other conditions.
612   DamagedRectsCleaner damagedRectCleaner(damagedRects);
613
614
615
616   Internal::Scene& sceneInternal = GetImplementation(scene);
617   SceneGraph::Scene* sceneObject = sceneInternal.GetSceneObject();
618
619   // Mark previous dirty rects in the sorted array. The array is already sorted by node and renderer, frame number.
620   // so you don't need to sort: std::stable_sort(itemsDirtyRects.begin(), itemsDirtyRects.end());
621   std::vector<DirtyRect>& itemsDirtyRects = sceneInternal.GetItemsDirtyRects();
622   for (DirtyRect& dirtyRect : itemsDirtyRects)
623   {
624     dirtyRect.visited = false;
625   }
626
627   uint32_t count = sceneObject->GetRenderInstructions().Count( mImpl->renderBufferIndex );
628   for (uint32_t i = 0; i < count; ++i)
629   {
630     RenderInstruction& instruction = sceneObject->GetRenderInstructions().At( mImpl->renderBufferIndex, i );
631
632     if (instruction.mFrameBuffer)
633     {
634       return; // TODO: reset, we don't deal with render tasks with framebuffers (for now)
635     }
636
637     const Camera* camera = instruction.GetCamera();
638     if (camera->mType == Camera::DEFAULT_TYPE && camera->mTargetPosition == Camera::DEFAULT_TARGET_POSITION)
639     {
640       const Node* node = instruction.GetCamera()->GetNode();
641       if (node)
642       {
643         Vector3 position;
644         Vector3 scale;
645         Quaternion orientation;
646         node->GetWorldMatrix(mImpl->renderBufferIndex).GetTransformComponents(position, orientation, scale);
647
648         Vector3 orientationAxis;
649         Radian orientationAngle;
650         orientation.ToAxisAngle( orientationAxis, orientationAngle );
651
652         if (position.x > Math::MACHINE_EPSILON_10000 ||
653             position.y > Math::MACHINE_EPSILON_10000 ||
654             orientationAxis != Vector3(0.0f, 1.0f, 0.0f) ||
655             orientationAngle != ANGLE_180 ||
656             scale != Vector3(1.0f, 1.0f, 1.0f))
657         {
658           return;
659         }
660       }
661     }
662     else
663     {
664       return;
665     }
666
667     Rect<int32_t> viewportRect;
668     if (instruction.mIsViewportSet)
669     {
670       const int32_t y = (surfaceRect.height - instruction.mViewport.height) - instruction.mViewport.y;
671       viewportRect.Set(instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height);
672       if (viewportRect.IsEmpty() || !viewportRect.IsValid())
673       {
674         return; // just skip funny use cases for now, empty viewport means it is set somewhere else
675       }
676     }
677     else
678     {
679       viewportRect = surfaceRect;
680     }
681
682     const Matrix* viewMatrix       = instruction.GetViewMatrix(mImpl->renderBufferIndex);
683     const Matrix* projectionMatrix = instruction.GetProjectionMatrix(mImpl->renderBufferIndex);
684     if (viewMatrix && projectionMatrix)
685     {
686       const RenderListContainer::SizeType count = instruction.RenderListCount();
687       for (RenderListContainer::SizeType index = 0u; index < count; ++index)
688       {
689         const RenderList* renderList = instruction.GetRenderList( index );
690         if (renderList && !renderList->IsEmpty())
691         {
692           const std::size_t count = renderList->Count();
693           for (uint32_t index = 0u; index < count; ++index)
694           {
695             RenderItem& item = renderList->GetItem( index );
696             // If the item does 3D transformation, do early exit and clean the damaged rect array
697             if (item.mUpdateSize == Vector3::ZERO)
698             {
699               return;
700             }
701
702             Rect<int> rect;
703             DirtyRect dirtyRect(item.mNode, item.mRenderer, mImpl->frameCount, rect);
704             // If the item refers to updated node or renderer.
705             if (item.mIsUpdated ||
706                 (item.mNode &&
707                 (item.mNode->Updated() || (item.mRenderer && item.mRenderer->Updated(mImpl->renderBufferIndex, item.mNode)))))
708             {
709               item.mIsUpdated = false;
710               item.mNode->SetUpdated(false);
711
712               rect = item.CalculateViewportSpaceAABB(item.mUpdateSize, viewportRect.width, viewportRect.height);
713               if (rect.IsValid() && rect.Intersect(viewportRect) && !rect.IsEmpty())
714               {
715                 const int left = rect.x;
716                 const int top = rect.y;
717                 const int right = rect.x + rect.width;
718                 const int bottom = rect.y + rect.height;
719                 rect.x = (left / 16) * 16;
720                 rect.y = (top / 16) * 16;
721                 rect.width = ((right + 16) / 16) * 16 - rect.x;
722                 rect.height = ((bottom + 16) / 16) * 16 - rect.y;
723
724                 // Found valid dirty rect.
725                 // 1. Insert it in the sorted array of the dirty rects.
726                 // 2. Mark the related dirty rects as visited so they will not be removed below.
727                 // 3. Keep only last 3 dirty rects for the same node and renderer (Tizen uses 3 back buffers, Ubuntu 1).
728                 dirtyRect.rect = rect;
729                 auto dirtyRectPos = std::lower_bound(itemsDirtyRects.begin(), itemsDirtyRects.end(), dirtyRect);
730                 dirtyRectPos = itemsDirtyRects.insert(dirtyRectPos, dirtyRect);
731
732                 int c = 1;
733                 while (++dirtyRectPos != itemsDirtyRects.end())
734                 {
735                   if (dirtyRectPos->node != item.mNode || dirtyRectPos->renderer != item.mRenderer)
736                   {
737                     break;
738                   }
739
740                   dirtyRectPos->visited = true;
741                   Rect<int>& dirtRect = dirtyRectPos->rect;
742                   rect.Merge(dirtRect);
743
744                   c++;
745                   if (c > 3) // no more then 3 previous rects
746                   {
747                     itemsDirtyRects.erase(dirtyRectPos);
748                     break;
749                   }
750                 }
751
752                 damagedRects.push_back(rect);
753               }
754             }
755             else
756             {
757               // 1. The item is not dirty, the node and renderer referenced by the item are still exist.
758               // 2. Mark the related dirty rects as visited so they will not be removed below.
759               auto dirtyRectPos = std::lower_bound(itemsDirtyRects.begin(), itemsDirtyRects.end(), dirtyRect);
760               while (dirtyRectPos != itemsDirtyRects.end())
761               {
762                 if (dirtyRectPos->node != item.mNode || dirtyRectPos->renderer != item.mRenderer)
763                 {
764                   break;
765                 }
766
767                 dirtyRectPos->visited = true;
768                 dirtyRectPos++;
769               }
770             }
771           }
772         }
773       }
774     }
775   }
776
777   // Check removed nodes or removed renderers dirty rects
778   auto i = itemsDirtyRects.begin();
779   auto j = itemsDirtyRects.begin();
780   while (i != itemsDirtyRects.end())
781   {
782     if (i->visited)
783     {
784       *j++ = *i;
785     }
786     else
787     {
788       Rect<int>& dirtRect = i->rect;
789       damagedRects.push_back(dirtRect);
790     }
791     i++;
792   }
793
794   itemsDirtyRects.resize(j - itemsDirtyRects.begin());
795   damagedRectCleaner.SetCleanOnReturn(false);
796 }
797
798 void RenderManager::RenderScene( Integration::RenderStatus& status, Integration::Scene& scene, bool renderToFbo )
799 {
800   Rect<int> clippingRect;
801   RenderScene( status, scene, renderToFbo, clippingRect);
802 }
803
804 void RenderManager::RenderScene( Integration::RenderStatus& status, Integration::Scene& scene, bool renderToFbo, Rect<int>& clippingRect )
805 {
806   Internal::Scene& sceneInternal = GetImplementation( scene );
807   SceneGraph::Scene* sceneObject = sceneInternal.GetSceneObject();
808
809   uint32_t count = sceneObject->GetRenderInstructions().Count( mImpl->renderBufferIndex );
810
811   for( uint32_t i = 0; i < count; ++i )
812   {
813     RenderInstruction& instruction = sceneObject->GetRenderInstructions().At( mImpl->renderBufferIndex, i );
814
815     if ( ( renderToFbo && !instruction.mFrameBuffer ) || ( !renderToFbo && instruction.mFrameBuffer ) )
816     {
817       continue; // skip
818     }
819
820     // Mark that we will require a post-render step to be performed (includes swap-buffers).
821     status.SetNeedsPostRender( true );
822
823     Rect<int32_t> viewportRect;
824     Vector4   clearColor;
825
826     if ( instruction.mIsClearColorSet )
827     {
828       clearColor = instruction.mClearColor;
829     }
830     else
831     {
832       clearColor = Dali::RenderTask::DEFAULT_CLEAR_COLOR;
833     }
834
835     Rect<int32_t> surfaceRect = mImpl->defaultSurfaceRect;
836     Integration::DepthBufferAvailable depthBufferAvailable = mImpl->depthBufferAvailable;
837     Integration::StencilBufferAvailable stencilBufferAvailable = mImpl->stencilBufferAvailable;
838     int surfaceOrientation = mImpl->defaultSurfaceOrientation;
839
840     if ( instruction.mFrameBuffer )
841     {
842       // offscreen buffer
843       if ( mImpl->currentContext != &mImpl->context )
844       {
845         // Switch to shared context for off-screen buffer
846         mImpl->currentContext = &mImpl->context;
847
848         if ( mImpl->currentContext->IsSurfacelessContextSupported() )
849         {
850           mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent();
851         }
852
853         // Clear the current cached program when the context is switched
854         mImpl->programController.ClearCurrentProgram();
855       }
856     }
857     else
858     {
859       if ( mImpl->currentContext->IsSurfacelessContextSupported() )
860       {
861         if ( mImpl->currentContext != sceneObject->GetContext() )
862         {
863           // Switch the correct context if rendering to a surface
864           mImpl->currentContext = sceneObject->GetContext();
865
866           // Clear the current cached program when the context is switched
867           mImpl->programController.ClearCurrentProgram();
868         }
869       }
870
871       surfaceRect = Rect<int32_t>( 0, 0, static_cast<int32_t>( scene.GetSize().width ), static_cast<int32_t>( scene.GetSize().height ) );
872     }
873
874     // Make sure that GL context must be created
875      mImpl->currentContext->GlContextCreated();
876
877     // reset the program matrices for all programs once per frame
878     // this ensures we will set view and projection matrix once per program per camera
879     mImpl->programController.ResetProgramMatrices();
880
881     if( instruction.mFrameBuffer )
882     {
883       instruction.mFrameBuffer->Bind( *mImpl->currentContext );
884
885       // For each offscreen buffer, update the dependency list with the new texture id used by this frame buffer.
886       for (unsigned int i0 = 0, i1 = instruction.mFrameBuffer->GetColorAttachmentCount(); i0 < i1; ++i0)
887       {
888         mImpl->textureDependencyList.PushBack( instruction.mFrameBuffer->GetTextureId(i0) );
889       }
890     }
891     else
892     {
893       mImpl->currentContext->BindFramebuffer( GL_FRAMEBUFFER, 0u );
894     }
895
896     if ( !instruction.mFrameBuffer )
897     {
898       mImpl->currentContext->Viewport( surfaceRect.x,
899                                        surfaceRect.y,
900                                        surfaceRect.width,
901                                        surfaceRect.height );
902     }
903
904     // Clear the entire color, depth and stencil buffers for the default framebuffer, if required.
905     // It is important to clear all 3 buffers when they are being used, for performance on deferred renderers
906     // e.g. previously when the depth & stencil buffers were NOT cleared, it caused the DDK to exceed a "vertex count limit",
907     // and then stall. That problem is only noticeable when rendering a large number of vertices per frame.
908     GLbitfield clearMask = GL_COLOR_BUFFER_BIT;
909
910     mImpl->currentContext->ColorMask( true );
911
912     if( depthBufferAvailable == Integration::DepthBufferAvailable::TRUE )
913     {
914       mImpl->currentContext->DepthMask( true );
915       clearMask |= GL_DEPTH_BUFFER_BIT;
916     }
917
918     if( stencilBufferAvailable == Integration::StencilBufferAvailable::TRUE)
919     {
920       mImpl->currentContext->ClearStencil( 0 );
921       mImpl->currentContext->StencilMask( 0xFF ); // 8 bit stencil mask, all 1's
922       clearMask |= GL_STENCIL_BUFFER_BIT;
923     }
924
925     if( !instruction.mIgnoreRenderToFbo && ( instruction.mFrameBuffer != nullptr ) )
926     {
927       // Offscreen buffer rendering
928       if ( instruction.mIsViewportSet )
929       {
930         // For glViewport the lower-left corner is (0,0)
931         const int32_t y = ( instruction.mFrameBuffer->GetHeight() - instruction.mViewport.height ) - instruction.mViewport.y;
932         viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
933       }
934       else
935       {
936         viewportRect.Set( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
937       }
938       surfaceOrientation = 0;
939     }
940     else // No Offscreen frame buffer rendering
941     {
942       // Check whether a viewport is specified, otherwise the full surface size is used
943       if ( instruction.mIsViewportSet )
944       {
945         // For glViewport the lower-left corner is (0,0)
946         const int32_t y = ( surfaceRect.height - instruction.mViewport.height ) - instruction.mViewport.y;
947         viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
948       }
949       else
950       {
951         viewportRect = surfaceRect;
952       }
953     }
954
955     if( surfaceOrientation == 90 || surfaceOrientation == 270 )
956     {
957       int temp = viewportRect.width;
958       viewportRect.width = viewportRect.height;
959       viewportRect.height = temp;
960     }
961
962     bool clearFullFrameRect = true;
963     if( instruction.mFrameBuffer != nullptr )
964     {
965       Viewport frameRect( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
966       clearFullFrameRect = ( frameRect == viewportRect );
967     }
968     else
969     {
970       clearFullFrameRect = ( surfaceRect == viewportRect );
971     }
972
973     if (!clippingRect.IsEmpty())
974     {
975       if (!clippingRect.Intersect(viewportRect))
976       {
977         DALI_LOG_ERROR("Invalid clipping rect %d %d %d %d\n", clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height);
978         clippingRect = Rect<int>();
979       }
980       clearFullFrameRect = false;
981     }
982
983     mImpl->currentContext->Viewport(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height);
984
985     if (instruction.mIsClearColorSet)
986     {
987       mImpl->currentContext->ClearColor(clearColor.r,
988                                         clearColor.g,
989                                         clearColor.b,
990                                         clearColor.a);
991       if (!clearFullFrameRect)
992       {
993         if (!clippingRect.IsEmpty())
994         {
995           mImpl->currentContext->SetScissorTest(true);
996           mImpl->currentContext->Scissor(clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height);
997           mImpl->currentContext->Clear(clearMask, Context::FORCE_CLEAR);
998           mImpl->currentContext->SetScissorTest(false);
999         }
1000         else
1001         {
1002           mImpl->currentContext->SetScissorTest(true);
1003           mImpl->currentContext->Scissor(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height);
1004           mImpl->currentContext->Clear(clearMask, Context::FORCE_CLEAR);
1005           mImpl->currentContext->SetScissorTest(false);
1006         }
1007       }
1008       else
1009       {
1010         mImpl->currentContext->SetScissorTest(false);
1011         mImpl->currentContext->Clear(clearMask, Context::FORCE_CLEAR);
1012       }
1013     }
1014
1015     // Clear the list of bound textures
1016     mImpl->boundTextures.Clear();
1017
1018     mImpl->renderAlgorithms.ProcessRenderInstruction(
1019         instruction,
1020         *mImpl->currentContext,
1021         mImpl->renderBufferIndex,
1022         depthBufferAvailable,
1023         stencilBufferAvailable,
1024         mImpl->boundTextures,
1025         clippingRect,
1026         surfaceOrientation );
1027
1028     // Synchronise the FBO/Texture access when there are multiple contexts
1029     if ( mImpl->currentContext->IsSurfacelessContextSupported() )
1030     {
1031       // Check whether any binded texture is in the dependency list
1032       bool textureFound = false;
1033
1034       if ( mImpl->boundTextures.Count() > 0u && mImpl->textureDependencyList.Count() > 0u )
1035       {
1036         for ( auto textureId : mImpl->textureDependencyList )
1037         {
1038
1039           textureFound = std::find_if( mImpl->boundTextures.Begin(), mImpl->boundTextures.End(),
1040                                        [textureId]( GLuint id )
1041                                        {
1042                                          return textureId == id;
1043                                        } ) != mImpl->boundTextures.End();
1044         }
1045       }
1046
1047       if ( textureFound )
1048       {
1049         if ( instruction.mFrameBuffer )
1050         {
1051           // For off-screen buffer
1052
1053           // Wait until all rendering calls for the currently context are executed
1054           mImpl->glContextHelperAbstraction.WaitClient();
1055
1056           // Clear the dependency list
1057           mImpl->textureDependencyList.Clear();
1058         }
1059         else
1060         {
1061           // Worker thread lambda function
1062           auto& glContextHelperAbstraction = mImpl->glContextHelperAbstraction;
1063           auto workerFunction = [&glContextHelperAbstraction]( int workerThread )
1064           {
1065             // Switch to the shared context in the worker thread
1066             glContextHelperAbstraction.MakeSurfacelessContextCurrent();
1067
1068             // Wait until all rendering calls for the shared context are executed
1069             glContextHelperAbstraction.WaitClient();
1070
1071             // Must clear the context in the worker thread
1072             // Otherwise the shared context cannot be switched to from the render thread
1073             glContextHelperAbstraction.MakeContextNull();
1074           };
1075
1076           auto future = mImpl->threadPool->SubmitTask( 0u, workerFunction );
1077           if ( future )
1078           {
1079             mImpl->threadPool->Wait();
1080
1081             // Clear the dependency list
1082             mImpl->textureDependencyList.Clear();
1083           }
1084         }
1085       }
1086     }
1087
1088     if( instruction.mRenderTracker && instruction.mFrameBuffer )
1089     {
1090       // This will create a sync object every frame this render tracker
1091       // is alive (though it should be now be created only for
1092       // render-once render tasks)
1093       instruction.mRenderTracker->CreateSyncObject( mImpl->glSyncAbstraction );
1094       instruction.mRenderTracker = nullptr; // Only create once.
1095     }
1096
1097     if ( renderToFbo )
1098     {
1099       mImpl->currentContext->Flush();
1100     }
1101   }
1102
1103   GLenum attachments[] = { GL_DEPTH, GL_STENCIL };
1104   mImpl->currentContext->InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
1105 }
1106
1107 void RenderManager::PostRender( bool uploadOnly )
1108 {
1109   if ( !uploadOnly )
1110   {
1111     if ( mImpl->currentContext->IsSurfacelessContextSupported() )
1112     {
1113       mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent();
1114     }
1115
1116     GLenum attachments[] = { GL_DEPTH, GL_STENCIL };
1117     mImpl->context.InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
1118   }
1119
1120   //Notify RenderGeometries that rendering has finished
1121   for ( auto&& iter : mImpl->geometryContainer )
1122   {
1123     iter->OnRenderFinished();
1124   }
1125
1126   mImpl->UpdateTrackers();
1127
1128
1129   uint32_t count = 0u;
1130   for( uint32_t i = 0; i < mImpl->sceneContainer.size(); ++i )
1131   {
1132     count += mImpl->sceneContainer[i]->GetRenderInstructions().Count( mImpl->renderBufferIndex );
1133   }
1134
1135   const bool haveInstructions = count > 0u;
1136
1137   // If this frame was rendered due to instructions existing, we mark this so we know to clear the next frame.
1138   mImpl->lastFrameWasRendered = haveInstructions;
1139
1140   /**
1141    * The rendering has finished; swap to the next buffer.
1142    * Ideally the update has just finished using this buffer; otherwise the render thread
1143    * should block until the update has finished.
1144    */
1145   mImpl->renderBufferIndex = (0 != mImpl->renderBufferIndex) ? 0 : 1;
1146
1147   DALI_PRINT_RENDER_END();
1148 }
1149
1150 } // namespace SceneGraph
1151
1152 } // namespace Internal
1153
1154 } // namespace Dali