[Tizen] Make possible to capture on the old driver devices.
[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::CaptureRenderingResult(Render::FrameBuffer* frameBuffer)
390 {
391   frameBuffer->CaptureRenderingResult();
392 }
393
394 void RenderManager::AddVertexBuffer( OwnerPointer< Render::VertexBuffer >& vertexBuffer )
395 {
396   mImpl->vertexBufferContainer.PushBack( vertexBuffer.Release() );
397 }
398
399 void RenderManager::RemoveVertexBuffer( Render::VertexBuffer* vertexBuffer )
400 {
401   mImpl->vertexBufferContainer.EraseObject( vertexBuffer );
402 }
403
404 void RenderManager::SetVertexBufferFormat( Render::VertexBuffer* vertexBuffer, OwnerPointer< Render::VertexBuffer::Format>& format )
405 {
406   vertexBuffer->SetFormat( format.Release() );
407 }
408
409 void RenderManager::SetVertexBufferData( Render::VertexBuffer* vertexBuffer, OwnerPointer< Vector<uint8_t> >& data, uint32_t size )
410 {
411   vertexBuffer->SetData( data.Release(), size );
412 }
413
414 void RenderManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<uint16_t>& indices )
415 {
416   geometry->SetIndexBuffer( indices );
417 }
418
419 void RenderManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
420 {
421   mImpl->geometryContainer.PushBack( geometry.Release() );
422 }
423
424 void RenderManager::RemoveGeometry( Render::Geometry* geometry )
425 {
426   mImpl->geometryContainer.EraseObject( geometry );
427 }
428
429 void RenderManager::AttachVertexBuffer( Render::Geometry* geometry, Render::VertexBuffer* vertexBuffer )
430 {
431   DALI_ASSERT_DEBUG( NULL != geometry );
432
433   // Find the geometry
434   for ( auto&& iter : mImpl->geometryContainer )
435   {
436     if ( iter == geometry )
437     {
438       iter->AddVertexBuffer( vertexBuffer );
439       break;
440     }
441   }
442 }
443
444 void RenderManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::VertexBuffer* vertexBuffer )
445 {
446   DALI_ASSERT_DEBUG( NULL != geometry );
447
448   // Find the geometry
449   for ( auto&& iter : mImpl->geometryContainer )
450   {
451     if ( iter == geometry )
452     {
453       iter->RemoveVertexBuffer( vertexBuffer );
454       break;
455     }
456   }
457 }
458
459 void RenderManager::SetGeometryType( Render::Geometry* geometry, uint32_t geometryType )
460 {
461   geometry->SetType( Render::Geometry::Type(geometryType) );
462 }
463
464 void RenderManager::AddRenderTracker( Render::RenderTracker* renderTracker )
465 {
466   mImpl->AddRenderTracker(renderTracker);
467 }
468
469 void RenderManager::RemoveRenderTracker( Render::RenderTracker* renderTracker )
470 {
471   mImpl->RemoveRenderTracker(renderTracker);
472 }
473
474 ProgramCache* RenderManager::GetProgramCache()
475 {
476   return &(mImpl->programController);
477 }
478
479 void RenderManager::PreRender( Integration::RenderStatus& status, bool forceClear, bool uploadOnly )
480 {
481   DALI_PRINT_RENDER_START( mImpl->renderBufferIndex );
482
483   // Core::Render documents that GL context must be current before calling Render
484   DALI_ASSERT_DEBUG( mImpl->context.IsGlContextCreated() );
485
486   // Increment the frame count at the beginning of each frame
487   ++mImpl->frameCount;
488
489   // Process messages queued during previous update
490   mImpl->renderQueue.ProcessMessages( mImpl->renderBufferIndex );
491
492   uint32_t count = 0u;
493   for( uint32_t i = 0; i < mImpl->sceneContainer.size(); ++i )
494   {
495     count += mImpl->sceneContainer[i]->GetRenderInstructions().Count( mImpl->renderBufferIndex );
496   }
497
498   const bool haveInstructions = count > 0u;
499
500   DALI_LOG_INFO( gLogFilter, Debug::General,
501                  "Render: haveInstructions(%s) || mImpl->lastFrameWasRendered(%s) || forceClear(%s)\n",
502                  haveInstructions ? "true" : "false",
503                  mImpl->lastFrameWasRendered ? "true" : "false",
504                  forceClear ? "true" : "false" );
505
506   // Only render if we have instructions to render, or the last frame was rendered (and therefore a clear is required).
507   if( haveInstructions || mImpl->lastFrameWasRendered || forceClear )
508   {
509     DALI_LOG_INFO( gLogFilter, Debug::General, "Render: Processing\n" );
510
511     // Switch to the shared context
512     if ( mImpl->currentContext != &mImpl->context )
513     {
514       mImpl->currentContext = &mImpl->context;
515
516       if ( mImpl->currentContext->IsSurfacelessContextSupported() )
517       {
518         mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent();
519       }
520
521       // Clear the current cached program when the context is switched
522       mImpl->programController.ClearCurrentProgram();
523     }
524
525     // Upload the geometries
526     for( uint32_t i = 0; i < mImpl->sceneContainer.size(); ++i )
527     {
528       RenderInstructionContainer& instructions = mImpl->sceneContainer[i]->GetRenderInstructions();
529       for ( uint32_t j = 0; j < instructions.Count( mImpl->renderBufferIndex ); ++j )
530       {
531         RenderInstruction& instruction = instructions.At( mImpl->renderBufferIndex, j );
532
533         const Matrix* viewMatrix       = instruction.GetViewMatrix( mImpl->renderBufferIndex );
534         const Matrix* projectionMatrix = instruction.GetProjectionMatrix( mImpl->renderBufferIndex );
535
536         DALI_ASSERT_DEBUG( viewMatrix );
537         DALI_ASSERT_DEBUG( projectionMatrix );
538
539         if( viewMatrix && projectionMatrix )
540         {
541           const RenderListContainer::SizeType renderListCount = instruction.RenderListCount();
542
543           // Iterate through each render list.
544           for( RenderListContainer::SizeType index = 0; index < renderListCount; ++index )
545           {
546             const RenderList* renderList = instruction.GetRenderList( index );
547
548             if( renderList && !renderList->IsEmpty() )
549             {
550               const std::size_t itemCount = renderList->Count();
551               for( uint32_t itemIndex = 0u; itemIndex < itemCount; ++itemIndex )
552               {
553                 const RenderItem& item = renderList->GetItem( itemIndex );
554                 if( DALI_LIKELY( item.mRenderer ) )
555                 {
556                   item.mRenderer->Upload( *mImpl->currentContext );
557                 }
558               }
559             }
560           }
561         }
562       }
563     }
564   }
565 }
566
567 void RenderManager::PreRender( Integration::Scene& scene, std::vector<Rect<int>>& damagedRects )
568 {
569   if (mImpl->partialUpdateAvailable != Integration::PartialUpdateAvailable::TRUE)
570   {
571     return;
572   }
573
574   Internal::Scene& sceneInternal = GetImplementation(scene);
575   SceneGraph::Scene* sceneObject = sceneInternal.GetSceneObject();
576
577   // @TODO We need to do partial rendering rotation.
578   if( sceneObject && sceneObject->GetSurfaceOrientation() != 0 )
579   {
580     return;
581   }
582
583   class DamagedRectsCleaner
584   {
585   public:
586     DamagedRectsCleaner(std::vector<Rect<int>>& damagedRects)
587     : mDamagedRects(damagedRects),
588       mCleanOnReturn(true)
589     {
590     }
591
592     void SetCleanOnReturn(bool cleanOnReturn)
593     {
594       mCleanOnReturn = cleanOnReturn;
595     }
596
597     ~DamagedRectsCleaner()
598     {
599       if (mCleanOnReturn)
600       {
601         mDamagedRects.clear();
602       }
603     }
604
605   private:
606     std::vector<Rect<int>>& mDamagedRects;
607     bool mCleanOnReturn;
608   };
609
610   Rect<int32_t> surfaceRect = Rect<int32_t>(0, 0, static_cast<int32_t>( scene.GetSize().width ), static_cast<int32_t>( scene.GetSize().height ));
611
612   // Clean collected dirty/damaged rects on exit if 3d layer or 3d node or other conditions.
613   DamagedRectsCleaner damagedRectCleaner(damagedRects);
614
615   // Mark previous dirty rects in the sorted array. The array is already sorted by node and renderer, frame number.
616   // so you don't need to sort: std::stable_sort(itemsDirtyRects.begin(), itemsDirtyRects.end());
617   std::vector<DirtyRect>& itemsDirtyRects = sceneInternal.GetItemsDirtyRects();
618   for (DirtyRect& dirtyRect : itemsDirtyRects)
619   {
620     dirtyRect.visited = false;
621   }
622
623   uint32_t count = sceneObject->GetRenderInstructions().Count( mImpl->renderBufferIndex );
624   for (uint32_t i = 0; i < count; ++i)
625   {
626     RenderInstruction& instruction = sceneObject->GetRenderInstructions().At( mImpl->renderBufferIndex, i );
627
628     if (instruction.mFrameBuffer)
629     {
630       return; // TODO: reset, we don't deal with render tasks with framebuffers (for now)
631     }
632
633     const Camera* camera = instruction.GetCamera();
634     if (camera->mType == Camera::DEFAULT_TYPE && camera->mTargetPosition == Camera::DEFAULT_TARGET_POSITION)
635     {
636       const Node* node = instruction.GetCamera()->GetNode();
637       if (node)
638       {
639         Vector3 position;
640         Vector3 scale;
641         Quaternion orientation;
642         node->GetWorldMatrix(mImpl->renderBufferIndex).GetTransformComponents(position, orientation, scale);
643
644         Vector3 orientationAxis;
645         Radian orientationAngle;
646         orientation.ToAxisAngle( orientationAxis, orientationAngle );
647
648         if (position.x > Math::MACHINE_EPSILON_10000 ||
649             position.y > Math::MACHINE_EPSILON_10000 ||
650             orientationAxis != Vector3(0.0f, 1.0f, 0.0f) ||
651             orientationAngle != ANGLE_180 ||
652             scale != Vector3(1.0f, 1.0f, 1.0f))
653         {
654           return;
655         }
656       }
657     }
658     else
659     {
660       return;
661     }
662
663     Rect<int32_t> viewportRect;
664     if (instruction.mIsViewportSet)
665     {
666       const int32_t y = (surfaceRect.height - instruction.mViewport.height) - instruction.mViewport.y;
667       viewportRect.Set(instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height);
668       if (viewportRect.IsEmpty() || !viewportRect.IsValid())
669       {
670         return; // just skip funny use cases for now, empty viewport means it is set somewhere else
671       }
672     }
673     else
674     {
675       viewportRect = surfaceRect;
676     }
677
678     const Matrix* viewMatrix       = instruction.GetViewMatrix(mImpl->renderBufferIndex);
679     const Matrix* projectionMatrix = instruction.GetProjectionMatrix(mImpl->renderBufferIndex);
680     if (viewMatrix && projectionMatrix)
681     {
682       const RenderListContainer::SizeType count = instruction.RenderListCount();
683       for (RenderListContainer::SizeType index = 0u; index < count; ++index)
684       {
685         const RenderList* renderList = instruction.GetRenderList( index );
686         if (renderList && !renderList->IsEmpty())
687         {
688           const std::size_t count = renderList->Count();
689           for (uint32_t index = 0u; index < count; ++index)
690           {
691             RenderItem& item = renderList->GetItem( index );
692             // If the item does 3D transformation, do early exit and clean the damaged rect array
693             if (item.mUpdateSize == Vector3::ZERO)
694             {
695               return;
696             }
697
698             Rect<int> rect;
699             DirtyRect dirtyRect(item.mNode, item.mRenderer, mImpl->frameCount, rect);
700             // If the item refers to updated node or renderer.
701             if (item.mIsUpdated ||
702                 (item.mNode &&
703                 (item.mNode->Updated() || (item.mRenderer && item.mRenderer->Updated(mImpl->renderBufferIndex, item.mNode)))))
704             {
705               item.mIsUpdated = false;
706               item.mNode->SetUpdated(false);
707
708               rect = item.CalculateViewportSpaceAABB(item.mUpdateSize, viewportRect.width, viewportRect.height);
709               if (rect.IsValid() && rect.Intersect(viewportRect) && !rect.IsEmpty())
710               {
711                 const int left = rect.x;
712                 const int top = rect.y;
713                 const int right = rect.x + rect.width;
714                 const int bottom = rect.y + rect.height;
715                 rect.x = (left / 16) * 16;
716                 rect.y = (top / 16) * 16;
717                 rect.width = ((right + 16) / 16) * 16 - rect.x;
718                 rect.height = ((bottom + 16) / 16) * 16 - rect.y;
719
720                 // Found valid dirty rect.
721                 // 1. Insert it in the sorted array of the dirty rects.
722                 // 2. Mark the related dirty rects as visited so they will not be removed below.
723                 // 3. Keep only last 3 dirty rects for the same node and renderer (Tizen uses 3 back buffers, Ubuntu 1).
724                 dirtyRect.rect = rect;
725                 auto dirtyRectPos = std::lower_bound(itemsDirtyRects.begin(), itemsDirtyRects.end(), dirtyRect);
726                 dirtyRectPos = itemsDirtyRects.insert(dirtyRectPos, dirtyRect);
727
728                 int c = 1;
729                 while (++dirtyRectPos != itemsDirtyRects.end())
730                 {
731                   if (dirtyRectPos->node != item.mNode || dirtyRectPos->renderer != item.mRenderer)
732                   {
733                     break;
734                   }
735
736                   dirtyRectPos->visited = true;
737                   Rect<int>& dirtRect = dirtyRectPos->rect;
738                   rect.Merge(dirtRect);
739
740                   c++;
741                   if (c > 3) // no more then 3 previous rects
742                   {
743                     itemsDirtyRects.erase(dirtyRectPos);
744                     break;
745                   }
746                 }
747
748                 damagedRects.push_back(rect);
749               }
750             }
751             else
752             {
753               // 1. The item is not dirty, the node and renderer referenced by the item are still exist.
754               // 2. Mark the related dirty rects as visited so they will not be removed below.
755               auto dirtyRectPos = std::lower_bound(itemsDirtyRects.begin(), itemsDirtyRects.end(), dirtyRect);
756               while (dirtyRectPos != itemsDirtyRects.end())
757               {
758                 if (dirtyRectPos->node != item.mNode || dirtyRectPos->renderer != item.mRenderer)
759                 {
760                   break;
761                 }
762
763                 dirtyRectPos->visited = true;
764                 dirtyRectPos++;
765               }
766             }
767           }
768         }
769       }
770     }
771   }
772
773   // Check removed nodes or removed renderers dirty rects
774   auto i = itemsDirtyRects.begin();
775   auto j = itemsDirtyRects.begin();
776   while (i != itemsDirtyRects.end())
777   {
778     if (i->visited)
779     {
780       *j++ = *i;
781     }
782     else
783     {
784       Rect<int>& dirtRect = i->rect;
785       damagedRects.push_back(dirtRect);
786     }
787     i++;
788   }
789
790   itemsDirtyRects.resize(j - itemsDirtyRects.begin());
791   damagedRectCleaner.SetCleanOnReturn(false);
792 }
793
794 void RenderManager::RenderScene( Integration::RenderStatus& status, Integration::Scene& scene, bool renderToFbo )
795 {
796   Rect<int> clippingRect;
797   RenderScene( status, scene, renderToFbo, clippingRect);
798 }
799
800 void RenderManager::RenderScene( Integration::RenderStatus& status, Integration::Scene& scene, bool renderToFbo, Rect<int>& clippingRect )
801 {
802   Internal::Scene& sceneInternal = GetImplementation( scene );
803   SceneGraph::Scene* sceneObject = sceneInternal.GetSceneObject();
804
805   uint32_t count = sceneObject->GetRenderInstructions().Count( mImpl->renderBufferIndex );
806
807   for( uint32_t i = 0; i < count; ++i )
808   {
809     RenderInstruction& instruction = sceneObject->GetRenderInstructions().At( mImpl->renderBufferIndex, i );
810
811     if ( ( renderToFbo && !instruction.mFrameBuffer ) || ( !renderToFbo && instruction.mFrameBuffer ) )
812     {
813       continue; // skip
814     }
815
816     // Mark that we will require a post-render step to be performed (includes swap-buffers).
817     status.SetNeedsPostRender( true );
818
819     Rect<int32_t> viewportRect;
820     Vector4   clearColor;
821
822     if ( instruction.mIsClearColorSet )
823     {
824       clearColor = instruction.mClearColor;
825     }
826     else
827     {
828       clearColor = Dali::RenderTask::DEFAULT_CLEAR_COLOR;
829     }
830
831     Rect<int32_t> surfaceRect = mImpl->defaultSurfaceRect;
832     Integration::DepthBufferAvailable depthBufferAvailable = mImpl->depthBufferAvailable;
833     Integration::StencilBufferAvailable stencilBufferAvailable = mImpl->stencilBufferAvailable;
834     int surfaceOrientation = sceneObject->GetSurfaceOrientation();
835
836     if ( instruction.mFrameBuffer )
837     {
838       // offscreen buffer
839       if ( mImpl->currentContext != &mImpl->context )
840       {
841         // Switch to shared context for off-screen buffer
842         mImpl->currentContext = &mImpl->context;
843
844         if ( mImpl->currentContext->IsSurfacelessContextSupported() )
845         {
846           mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent();
847         }
848
849         // Clear the current cached program when the context is switched
850         mImpl->programController.ClearCurrentProgram();
851       }
852     }
853     else
854     {
855       if ( mImpl->currentContext->IsSurfacelessContextSupported() )
856       {
857         if ( mImpl->currentContext != sceneObject->GetContext() )
858         {
859           // Switch the correct context if rendering to a surface
860           mImpl->currentContext = sceneObject->GetContext();
861
862           // Clear the current cached program when the context is switched
863           mImpl->programController.ClearCurrentProgram();
864         }
865       }
866
867       surfaceRect = Rect<int32_t>( 0, 0, static_cast<int32_t>( scene.GetSize().width ), static_cast<int32_t>( scene.GetSize().height ) );
868     }
869
870     // Make sure that GL context must be created
871      mImpl->currentContext->GlContextCreated();
872
873     // reset the program matrices for all programs once per frame
874     // this ensures we will set view and projection matrix once per program per camera
875     mImpl->programController.ResetProgramMatrices();
876
877     if( instruction.mFrameBuffer )
878     {
879       instruction.mFrameBuffer->Bind( *mImpl->currentContext );
880
881       // For each offscreen buffer, update the dependency list with the new texture id used by this frame buffer.
882       for (unsigned int i0 = 0, i1 = instruction.mFrameBuffer->GetColorAttachmentCount(); i0 < i1; ++i0)
883       {
884         mImpl->textureDependencyList.PushBack( instruction.mFrameBuffer->GetTextureId(i0) );
885       }
886     }
887     else
888     {
889       mImpl->currentContext->BindFramebuffer( GL_FRAMEBUFFER, 0u );
890     }
891
892     if ( !instruction.mFrameBuffer )
893     {
894       mImpl->currentContext->Viewport( surfaceRect.x,
895                                        surfaceRect.y,
896                                        surfaceRect.width,
897                                        surfaceRect.height );
898     }
899
900     // Clear the entire color, depth and stencil buffers for the default framebuffer, if required.
901     // It is important to clear all 3 buffers when they are being used, for performance on deferred renderers
902     // e.g. previously when the depth & stencil buffers were NOT cleared, it caused the DDK to exceed a "vertex count limit",
903     // and then stall. That problem is only noticeable when rendering a large number of vertices per frame.
904     GLbitfield clearMask = GL_COLOR_BUFFER_BIT;
905
906     mImpl->currentContext->ColorMask( true );
907
908     if( depthBufferAvailable == Integration::DepthBufferAvailable::TRUE )
909     {
910       mImpl->currentContext->DepthMask( true );
911       clearMask |= GL_DEPTH_BUFFER_BIT;
912     }
913
914     if( stencilBufferAvailable == Integration::StencilBufferAvailable::TRUE)
915     {
916       mImpl->currentContext->ClearStencil( 0 );
917       mImpl->currentContext->StencilMask( 0xFF ); // 8 bit stencil mask, all 1's
918       clearMask |= GL_STENCIL_BUFFER_BIT;
919     }
920
921     if( !instruction.mIgnoreRenderToFbo && ( instruction.mFrameBuffer != nullptr ) )
922     {
923       // Offscreen buffer rendering
924       if ( instruction.mIsViewportSet )
925       {
926         // For glViewport the lower-left corner is (0,0)
927         const int32_t y = ( instruction.mFrameBuffer->GetHeight() - instruction.mViewport.height ) - instruction.mViewport.y;
928         viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
929       }
930       else
931       {
932         viewportRect.Set( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
933       }
934       surfaceOrientation = 0;
935     }
936     else // No Offscreen frame buffer rendering
937     {
938       // Check whether a viewport is specified, otherwise the full surface size is used
939       if ( instruction.mIsViewportSet )
940       {
941         // For glViewport the lower-left corner is (0,0)
942         const int32_t y = ( surfaceRect.height - instruction.mViewport.height ) - instruction.mViewport.y;
943         viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
944       }
945       else
946       {
947         viewportRect = surfaceRect;
948       }
949     }
950
951     if( surfaceOrientation == 90 || surfaceOrientation == 270 )
952     {
953       int temp = viewportRect.width;
954       viewportRect.width = viewportRect.height;
955       viewportRect.height = temp;
956     }
957
958     bool clearFullFrameRect = true;
959     if( instruction.mFrameBuffer != nullptr )
960     {
961       Viewport frameRect( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
962       clearFullFrameRect = ( frameRect == viewportRect );
963     }
964     else
965     {
966       clearFullFrameRect = ( surfaceRect == viewportRect );
967     }
968
969     if (!clippingRect.IsEmpty())
970     {
971       if (!clippingRect.Intersect(viewportRect))
972       {
973         DALI_LOG_ERROR("Invalid clipping rect %d %d %d %d\n", clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height);
974         clippingRect = Rect<int>();
975       }
976       clearFullFrameRect = false;
977     }
978
979     mImpl->currentContext->Viewport(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height);
980
981     if (instruction.mIsClearColorSet)
982     {
983       mImpl->currentContext->ClearColor(clearColor.r,
984                                         clearColor.g,
985                                         clearColor.b,
986                                         clearColor.a);
987       if (!clearFullFrameRect)
988       {
989         if (!clippingRect.IsEmpty())
990         {
991           mImpl->currentContext->SetScissorTest(true);
992           mImpl->currentContext->Scissor(clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height);
993           mImpl->currentContext->Clear(clearMask, Context::FORCE_CLEAR);
994           mImpl->currentContext->SetScissorTest(false);
995         }
996         else
997         {
998           mImpl->currentContext->SetScissorTest(true);
999           mImpl->currentContext->Scissor(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height);
1000           mImpl->currentContext->Clear(clearMask, Context::FORCE_CLEAR);
1001           mImpl->currentContext->SetScissorTest(false);
1002         }
1003       }
1004       else
1005       {
1006         mImpl->currentContext->SetScissorTest(false);
1007         mImpl->currentContext->Clear(clearMask, Context::FORCE_CLEAR);
1008       }
1009     }
1010
1011     // Clear the list of bound textures
1012     mImpl->boundTextures.Clear();
1013
1014     mImpl->renderAlgorithms.ProcessRenderInstruction(
1015         instruction,
1016         *mImpl->currentContext,
1017         mImpl->renderBufferIndex,
1018         depthBufferAvailable,
1019         stencilBufferAvailable,
1020         mImpl->boundTextures,
1021         clippingRect,
1022         surfaceOrientation );
1023
1024     // Synchronise the FBO/Texture access when there are multiple contexts
1025     if ( mImpl->currentContext->IsSurfacelessContextSupported() )
1026     {
1027       // Check whether any binded texture is in the dependency list
1028       bool textureFound = false;
1029
1030       if ( mImpl->boundTextures.Count() > 0u && mImpl->textureDependencyList.Count() > 0u )
1031       {
1032         for ( auto textureId : mImpl->textureDependencyList )
1033         {
1034
1035           textureFound = std::find_if( mImpl->boundTextures.Begin(), mImpl->boundTextures.End(),
1036                                        [textureId]( GLuint id )
1037                                        {
1038                                          return textureId == id;
1039                                        } ) != mImpl->boundTextures.End();
1040         }
1041       }
1042
1043       if ( textureFound )
1044       {
1045         if ( instruction.mFrameBuffer )
1046         {
1047           // For off-screen buffer
1048
1049           // Wait until all rendering calls for the currently context are executed
1050           mImpl->glContextHelperAbstraction.WaitClient();
1051
1052           // Clear the dependency list
1053           mImpl->textureDependencyList.Clear();
1054         }
1055         else
1056         {
1057           // Worker thread lambda function
1058           auto& glContextHelperAbstraction = mImpl->glContextHelperAbstraction;
1059           auto workerFunction = [&glContextHelperAbstraction]( int workerThread )
1060           {
1061             // Switch to the shared context in the worker thread
1062             glContextHelperAbstraction.MakeSurfacelessContextCurrent();
1063
1064             // Wait until all rendering calls for the shared context are executed
1065             glContextHelperAbstraction.WaitClient();
1066
1067             // Must clear the context in the worker thread
1068             // Otherwise the shared context cannot be switched to from the render thread
1069             glContextHelperAbstraction.MakeContextNull();
1070           };
1071
1072           auto future = mImpl->threadPool->SubmitTask( 0u, workerFunction );
1073           if ( future )
1074           {
1075             mImpl->threadPool->Wait();
1076
1077             // Clear the dependency list
1078             mImpl->textureDependencyList.Clear();
1079           }
1080         }
1081       }
1082     }
1083
1084     if( instruction.mRenderTracker && instruction.mFrameBuffer )
1085     {
1086       // This will create a sync object every frame this render tracker
1087       // is alive (though it should be now be created only for
1088       // render-once render tasks)
1089       instruction.mRenderTracker->CreateSyncObject( mImpl->glSyncAbstraction );
1090       instruction.mRenderTracker = nullptr; // Only create once.
1091     }
1092
1093     if ( renderToFbo )
1094     {
1095       mImpl->currentContext->Flush();
1096       instruction.mFrameBuffer->DrawRenderedBuffer(*mImpl->currentContext);
1097     }
1098   }
1099
1100   GLenum attachments[] = { GL_DEPTH, GL_STENCIL };
1101   mImpl->currentContext->InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
1102 }
1103
1104 void RenderManager::PostRender( bool uploadOnly )
1105 {
1106   if ( !uploadOnly )
1107   {
1108     if ( mImpl->currentContext->IsSurfacelessContextSupported() )
1109     {
1110       mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent();
1111     }
1112
1113     GLenum attachments[] = { GL_DEPTH, GL_STENCIL };
1114     mImpl->context.InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
1115   }
1116
1117   //Notify RenderGeometries that rendering has finished
1118   for ( auto&& iter : mImpl->geometryContainer )
1119   {
1120     iter->OnRenderFinished();
1121   }
1122
1123   mImpl->UpdateTrackers();
1124
1125
1126   uint32_t count = 0u;
1127   for( uint32_t i = 0; i < mImpl->sceneContainer.size(); ++i )
1128   {
1129     count += mImpl->sceneContainer[i]->GetRenderInstructions().Count( mImpl->renderBufferIndex );
1130   }
1131
1132   const bool haveInstructions = count > 0u;
1133
1134   // If this frame was rendered due to instructions existing, we mark this so we know to clear the next frame.
1135   mImpl->lastFrameWasRendered = haveInstructions;
1136
1137   /**
1138    * The rendering has finished; swap to the next buffer.
1139    * Ideally the update has just finished using this buffer; otherwise the render thread
1140    * should block until the update has finished.
1141    */
1142   mImpl->renderBufferIndex = (0 != mImpl->renderBufferIndex) ? 0 : 1;
1143
1144   DALI_PRINT_RENDER_END();
1145 }
1146
1147 } // namespace SceneGraph
1148
1149 } // namespace Internal
1150
1151 } // namespace Dali