[Tizen] Implement partial update
[platform/core/uifw/dali-core.git] / dali / internal / render / common / render-manager.cpp
1 /*
2  * Copyright (c) 2019 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/public-api/actors/sampling.h>
26 #include <dali/public-api/common/dali-common.h>
27 #include <dali/public-api/common/stage.h>
28 #include <dali/public-api/render-tasks/render-task.h>
29 #include <dali/devel-api/threading/thread-pool.h>
30 #include <dali/integration-api/debug.h>
31 #include <dali/integration-api/core.h>
32 #include <dali/integration-api/gl-context-helper-abstraction.h>
33 #include <dali/internal/common/owner-pointer.h>
34 #include <dali/internal/render/common/render-algorithms.h>
35 #include <dali/internal/render/common/render-debug.h>
36 #include <dali/internal/render/common/render-tracker.h>
37 #include <dali/internal/render/common/render-instruction-container.h>
38 #include <dali/internal/render/common/render-instruction.h>
39 #include <dali/internal/render/gl-resources/context.h>
40 #include <dali/internal/render/queue/render-queue.h>
41 #include <dali/internal/render/renderers/render-frame-buffer.h>
42 #include <dali/internal/render/renderers/render-texture-frame-buffer.h>
43 #include <dali/internal/render/renderers/render-surface-frame-buffer.h>
44 #include <dali/internal/render/renderers/render-geometry.h>
45 #include <dali/internal/render/renderers/render-renderer.h>
46 #include <dali/internal/render/renderers/render-sampler.h>
47 #include <dali/internal/render/shaders/program-controller.h>
48
49 namespace Dali
50 {
51
52 namespace Internal
53 {
54
55 namespace SceneGraph
56 {
57
58 #if defined(DEBUG_ENABLED)
59 namespace
60 {
61 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RENDER_MANAGER" );
62 } // unnamed namespace
63 #endif
64
65 const int partialUpdateMargin = 4u;
66 const float partialUpdateRatio = 0.8f; // If the partial update area exceeds 80%, change to full update.
67
68 /**
69  * Structure to contain internal data
70  */
71 struct RenderManager::Impl
72 {
73   Impl( Integration::GlAbstraction& glAbstraction,
74         Integration::GlSyncAbstraction& glSyncAbstraction,
75         Integration::GlContextHelperAbstraction& glContextHelperAbstraction,
76         Integration::DepthBufferAvailable depthBufferAvailableParam,
77         Integration::StencilBufferAvailable stencilBufferAvailableParam,
78         Integration::PartialUpdateAvailable partialUpdateAvailableParam )
79   : context( glAbstraction, &surfaceContextContainer ),
80     currentContext( &context ),
81     glAbstraction( glAbstraction ),
82     glSyncAbstraction( glSyncAbstraction ),
83     glContextHelperAbstraction( glContextHelperAbstraction ),
84     renderQueue(),
85     instructions(),
86     renderAlgorithms(),
87     backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
88     frameCount( 0u ),
89     renderBufferIndex( SceneGraphBuffers::INITIAL_UPDATE_BUFFER_INDEX ),
90     defaultSurfaceRect(),
91     rendererContainer(),
92     samplerContainer(),
93     textureContainer(),
94     frameBufferContainer(),
95     lastFrameWasRendered( false ),
96     programController( glAbstraction ),
97     depthBufferAvailable( depthBufferAvailableParam ),
98     stencilBufferAvailable( stencilBufferAvailableParam ),
99     partialUpdateAvailable( partialUpdateAvailableParam ),
100     defaultSurfaceOrientation( 0 )
101   {
102      // Create thread pool with just one thread ( there may be a need to create more threads in the future ).
103     threadPool = std::unique_ptr<Dali::ThreadPool>( new Dali::ThreadPool() );
104     threadPool->Initialize( 1u );
105   }
106
107   ~Impl()
108   {
109     threadPool.reset( nullptr ); // reset now to maintain correct destruction order
110   }
111
112   void AddRenderTracker( Render::RenderTracker* renderTracker )
113   {
114     DALI_ASSERT_DEBUG( renderTracker != NULL );
115     mRenderTrackers.PushBack( renderTracker );
116   }
117
118   void RemoveRenderTracker( Render::RenderTracker* renderTracker )
119   {
120     mRenderTrackers.EraseObject( renderTracker );
121   }
122
123   Context* CreateSurfaceContext()
124   {
125     surfaceContextContainer.PushBack( new Context( glAbstraction ) );
126     return surfaceContextContainer[ surfaceContextContainer.Count() - 1 ];
127   }
128
129   void DestroySurfaceContext( Context* surfaceContext )
130   {
131     surfaceContextContainer.EraseObject( surfaceContext );
132   }
133
134   void UpdateTrackers()
135   {
136     for( auto&& iter : mRenderTrackers )
137     {
138       iter->PollSyncObject();
139     }
140   }
141
142   // the order is important for destruction,
143   // programs are owned by context at the moment.
144   Context                                   context;                 ///< Holds the GL state of the share resource context
145   Context*                                  currentContext;          ///< Holds the GL state of the current context for rendering
146   OwnerContainer< Context* >                surfaceContextContainer; ///< List of owned contexts holding the GL state per surface
147   Integration::GlAbstraction&               glAbstraction;           ///< GL abstraction
148   Integration::GlSyncAbstraction&           glSyncAbstraction;       ///< GL sync abstraction
149   Integration::GlContextHelperAbstraction&  glContextHelperAbstraction; ///< GL context helper abstraction
150   RenderQueue                               renderQueue;             ///< A message queue for receiving messages from the update-thread.
151
152   // Render instructions describe what should be rendered during RenderManager::Render()
153   // Owned by RenderManager. Update manager updates instructions for the next frame while we render the current one
154   RenderInstructionContainer                instructions;
155   Render::RenderAlgorithms                  renderAlgorithms;        ///< The RenderAlgorithms object is used to action the renders required by a RenderInstruction
156
157   Vector4                                   backgroundColor;         ///< The glClear color used at the beginning of each frame.
158
159   uint32_t                                  frameCount;              ///< The current frame count
160   BufferIndex                               renderBufferIndex;       ///< The index of the buffer to read from; this is opposite of the "update" buffer
161
162   Rect<int32_t>                             defaultSurfaceRect;      ///< Rectangle for the default surface we are rendering to
163
164   OwnerContainer< Render::Renderer* >       rendererContainer;       ///< List of owned renderers
165   OwnerContainer< Render::Sampler* >        samplerContainer;        ///< List of owned samplers
166   OwnerContainer< Render::Texture* >        textureContainer;        ///< List of owned textures
167   OwnerContainer< Render::FrameBuffer* >    frameBufferContainer;    ///< List of owned framebuffers
168   OwnerContainer< Render::PropertyBuffer* > propertyBufferContainer; ///< List of owned property buffers
169   OwnerContainer< Render::Geometry* >       geometryContainer;       ///< List of owned Geometries
170
171   bool                                      lastFrameWasRendered;    ///< Keeps track of the last frame being rendered due to having render instructions
172
173   OwnerContainer< Render::RenderTracker* >  mRenderTrackers;         ///< List of render trackers
174
175   ProgramController                         programController;        ///< Owner of the GL programs
176
177   Integration::DepthBufferAvailable         depthBufferAvailable;     ///< Whether the depth buffer is available
178   Integration::StencilBufferAvailable       stencilBufferAvailable;   ///< Whether the stencil buffer is available
179   Integration::PartialUpdateAvailable       partialUpdateAvailable;   ///< Whether the partial update is available
180
181   std::unique_ptr<Dali::ThreadPool>         threadPool;               ///< The thread pool
182   Vector<GLuint>                            boundTextures;            ///< The textures bound for rendering
183   Vector<GLuint>                            textureDependencyList;    ///< The dependency list of binded textures
184   int                                       defaultSurfaceOrientation; ///< defaultSurfaceOrientation for the default surface we are rendering to
185
186 };
187
188 RenderManager* RenderManager::New( Integration::GlAbstraction& glAbstraction,
189                                    Integration::GlSyncAbstraction& glSyncAbstraction,
190                                    Integration::GlContextHelperAbstraction& glContextHelperAbstraction,
191                                    Integration::DepthBufferAvailable depthBufferAvailable,
192                                    Integration::StencilBufferAvailable stencilBufferAvailable,
193                                    Integration::PartialUpdateAvailable partialUpdateAvailable )
194 {
195   RenderManager* manager = new RenderManager;
196   manager->mImpl = new Impl( glAbstraction,
197                              glSyncAbstraction,
198                              glContextHelperAbstraction,
199                              depthBufferAvailable,
200                              stencilBufferAvailable,
201                              partialUpdateAvailable );
202   return manager;
203 }
204
205 RenderManager::RenderManager()
206 : mImpl(NULL)
207 {
208 }
209
210 RenderManager::~RenderManager()
211 {
212   delete mImpl;
213 }
214
215 RenderQueue& RenderManager::GetRenderQueue()
216 {
217   return mImpl->renderQueue;
218 }
219
220 void RenderManager::ContextCreated()
221 {
222   mImpl->context.GlContextCreated();
223   mImpl->programController.GlContextCreated();
224
225   // renderers, textures and gpu buffers cannot reinitialize themselves
226   // so they rely on someone reloading the data for them
227 }
228
229 void RenderManager::ContextDestroyed()
230 {
231   mImpl->context.GlContextDestroyed();
232   mImpl->programController.GlContextDestroyed();
233
234   //Inform textures
235   for( auto&& texture : mImpl->textureContainer )
236   {
237     texture->GlContextDestroyed();
238   }
239
240   //Inform framebuffers
241   for( auto&& framebuffer : mImpl->frameBufferContainer )
242   {
243     framebuffer->GlContextDestroyed();
244   }
245
246   // inform renderers
247   for( auto&& renderer : mImpl->rendererContainer )
248   {
249     renderer->GlContextDestroyed();
250   }
251 }
252
253 void RenderManager::SetShaderSaver( ShaderSaver& upstream )
254 {
255   mImpl->programController.SetShaderSaver( upstream );
256 }
257
258 RenderInstructionContainer& RenderManager::GetRenderInstructionContainer()
259 {
260   return mImpl->instructions;
261 }
262
263 void RenderManager::SetBackgroundColor( const Vector4& color )
264 {
265   mImpl->backgroundColor = color;
266 }
267
268 void RenderManager::SetDefaultSurfaceRect(const Rect<int32_t>& rect)
269 {
270   mImpl->defaultSurfaceRect = rect;
271 }
272
273 void RenderManager::SetDefaultSurfaceOrientation( int orientation )
274 {
275   mImpl->defaultSurfaceOrientation = orientation;
276 }
277
278 void RenderManager::AddRenderer( OwnerPointer< Render::Renderer >& renderer )
279 {
280   // Initialize the renderer as we are now in render thread
281   renderer->Initialize( mImpl->context );
282
283   mImpl->rendererContainer.PushBack( renderer.Release() );
284 }
285
286 void RenderManager::RemoveRenderer( Render::Renderer* renderer )
287 {
288   mImpl->rendererContainer.EraseObject( renderer );
289 }
290
291 void RenderManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
292 {
293   mImpl->samplerContainer.PushBack( sampler.Release() );
294 }
295
296 void RenderManager::RemoveSampler( Render::Sampler* sampler )
297 {
298   mImpl->samplerContainer.EraseObject( sampler );
299 }
300
301 void RenderManager::AddTexture( OwnerPointer< Render::Texture >& texture )
302 {
303   texture->Initialize( mImpl->context );
304   mImpl->textureContainer.PushBack( texture.Release() );
305 }
306
307 void RenderManager::RemoveTexture( Render::Texture* texture )
308 {
309   DALI_ASSERT_DEBUG( NULL != texture );
310
311   // Find the texture, use reference to pointer so we can do the erase safely
312   for ( auto&& iter : mImpl->textureContainer )
313   {
314     if ( iter == texture )
315     {
316       texture->Destroy( mImpl->context );
317       mImpl->textureContainer.Erase( &iter ); // Texture found; now destroy it
318       return;
319     }
320   }
321 }
322
323 void RenderManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
324 {
325   texture->Upload( mImpl->context, pixelData, params );
326 }
327
328 void RenderManager::GenerateMipmaps( Render::Texture* texture )
329 {
330   texture->GenerateMipmaps( mImpl->context );
331 }
332
333 void RenderManager::SetFilterMode( Render::Sampler* sampler, uint32_t minFilterMode, uint32_t magFilterMode )
334 {
335   sampler->mMinificationFilter = static_cast<Dali::FilterMode::Type>(minFilterMode);
336   sampler->mMagnificationFilter = static_cast<Dali::FilterMode::Type>(magFilterMode );
337 }
338
339 void RenderManager::SetWrapMode( Render::Sampler* sampler, uint32_t rWrapMode, uint32_t sWrapMode, uint32_t tWrapMode )
340 {
341   sampler->mRWrapMode = static_cast<Dali::WrapMode::Type>(rWrapMode);
342   sampler->mSWrapMode = static_cast<Dali::WrapMode::Type>(sWrapMode);
343   sampler->mTWrapMode = static_cast<Dali::WrapMode::Type>(tWrapMode);
344 }
345
346 void RenderManager::AddFrameBuffer( OwnerPointer< Render::FrameBuffer >& frameBuffer )
347 {
348   Render::FrameBuffer* frameBufferPtr = frameBuffer.Release();
349   mImpl->frameBufferContainer.PushBack( frameBufferPtr );
350   if ( frameBufferPtr->IsSurfaceBacked() )
351   {
352     frameBufferPtr->Initialize( *mImpl->CreateSurfaceContext() );
353   }
354   else
355   {
356     frameBufferPtr->Initialize( mImpl->context );
357   }
358 }
359
360 void RenderManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer )
361 {
362   DALI_ASSERT_DEBUG( NULL != frameBuffer );
363
364   // Find the sampler, use reference so we can safely do the erase
365   for ( auto&& iter : mImpl->frameBufferContainer )
366   {
367     if ( iter == frameBuffer )
368     {
369       frameBuffer->Destroy( mImpl->context );
370
371       if ( frameBuffer->IsSurfaceBacked() )
372       {
373         auto surfaceFrameBuffer = static_cast<Render::SurfaceFrameBuffer*>( frameBuffer );
374         mImpl->DestroySurfaceContext( surfaceFrameBuffer->GetContext() );
375       }
376
377       mImpl->frameBufferContainer.Erase( &iter ); // frameBuffer found; now destroy it
378
379       break;
380     }
381   }
382 }
383
384 void RenderManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer )
385 {
386   if ( !frameBuffer->IsSurfaceBacked() )
387   {
388     auto textureFrameBuffer = static_cast<Render::TextureFrameBuffer*>( frameBuffer );
389     textureFrameBuffer->AttachColorTexture( mImpl->context, texture, mipmapLevel, layer );
390   }
391 }
392
393 void RenderManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer )
394 {
395   mImpl->propertyBufferContainer.PushBack( propertyBuffer.Release() );
396 }
397
398 void RenderManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
399 {
400   mImpl->propertyBufferContainer.EraseObject( propertyBuffer );
401 }
402
403 void RenderManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
404 {
405   propertyBuffer->SetFormat( format.Release() );
406 }
407
408 void RenderManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<uint8_t> >& data, uint32_t size )
409 {
410   propertyBuffer->SetData( data.Release(), size );
411 }
412
413 void RenderManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<uint16_t>& indices )
414 {
415   geometry->SetIndexBuffer( indices );
416 }
417
418 void RenderManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
419 {
420   mImpl->geometryContainer.PushBack( geometry.Release() );
421 }
422
423 void RenderManager::RemoveGeometry( Render::Geometry* geometry )
424 {
425   mImpl->geometryContainer.EraseObject( geometry );
426 }
427
428 void RenderManager::AttachVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
429 {
430   DALI_ASSERT_DEBUG( NULL != geometry );
431
432   // Find the geometry
433   for ( auto&& iter : mImpl->geometryContainer )
434   {
435     if ( iter == geometry )
436     {
437       iter->AddPropertyBuffer( propertyBuffer );
438       break;
439     }
440   }
441 }
442
443 void RenderManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
444 {
445   DALI_ASSERT_DEBUG( NULL != geometry );
446
447   // Find the geometry
448   for ( auto&& iter : mImpl->geometryContainer )
449   {
450     if ( iter == geometry )
451     {
452       iter->RemovePropertyBuffer( propertyBuffer );
453       break;
454     }
455   }
456 }
457
458 void RenderManager::SetGeometryType( Render::Geometry* geometry, uint32_t geometryType )
459 {
460   geometry->SetType( Render::Geometry::Type(geometryType) );
461 }
462
463 void RenderManager::AddRenderTracker( Render::RenderTracker* renderTracker )
464 {
465   mImpl->AddRenderTracker(renderTracker);
466 }
467
468 void RenderManager::RemoveRenderTracker( Render::RenderTracker* renderTracker )
469 {
470   mImpl->RemoveRenderTracker(renderTracker);
471 }
472
473 ProgramCache* RenderManager::GetProgramCache()
474 {
475   return &(mImpl->programController);
476 }
477
478 void RenderManager::Render( Integration::RenderStatus& status, bool forceClear )
479 {
480   DALI_PRINT_RENDER_START( mImpl->renderBufferIndex );
481
482   // Core::Render documents that GL context must be current before calling Render
483   DALI_ASSERT_DEBUG( mImpl->context.IsGlContextCreated() );
484
485   // Increment the frame count at the beginning of each frame
486   ++mImpl->frameCount;
487
488   // Process messages queued during previous update
489   mImpl->renderQueue.ProcessMessages( mImpl->renderBufferIndex );
490
491   const uint32_t count = mImpl->instructions.Count( mImpl->renderBufferIndex );
492   const bool haveInstructions = count > 0u;
493
494   DALI_LOG_INFO( gLogFilter, Debug::General,
495                  "Render: haveInstructions(%s) || mImpl->lastFrameWasRendered(%s) || forceClear(%s)\n",
496                  haveInstructions ? "true" : "false",
497                  mImpl->lastFrameWasRendered ? "true" : "false",
498                  forceClear ? "true" : "false" );
499
500   // Only render if we have instructions to render, or the last frame was rendered (and therefore a clear is required).
501   if( haveInstructions || mImpl->lastFrameWasRendered || forceClear )
502   {
503     DALI_LOG_INFO( gLogFilter, Debug::General, "Render: Processing\n" );
504
505     // Mark that we will require a post-render step to be performed (includes swap-buffers).
506     status.SetNeedsPostRender( true );
507
508     // Switch to the shared context
509     if ( mImpl->currentContext != &mImpl->context )
510     {
511       mImpl->currentContext = &mImpl->context;
512
513       if ( mImpl->currentContext->IsSurfacelessContextSupported() )
514       {
515         mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent();
516       }
517
518       // Clear the current cached program when the context is switched
519       mImpl->programController.ClearCurrentProgram();
520     }
521
522     // Upload the geometries
523     for( uint32_t i = 0; i < count; ++i )
524     {
525       RenderInstruction& instruction = mImpl->instructions.At( mImpl->renderBufferIndex, i );
526
527       const Matrix* viewMatrix       = instruction.GetViewMatrix( mImpl->renderBufferIndex );
528       const Matrix* projectionMatrix = instruction.GetProjectionMatrix( mImpl->renderBufferIndex );
529
530       DALI_ASSERT_DEBUG( viewMatrix );
531       DALI_ASSERT_DEBUG( projectionMatrix );
532
533       if( viewMatrix && projectionMatrix )
534       {
535         const RenderListContainer::SizeType renderListCount = instruction.RenderListCount();
536
537         // Iterate through each render list.
538         for( RenderListContainer::SizeType index = 0; index < renderListCount; ++index )
539         {
540           const RenderList* renderList = instruction.GetRenderList( index );
541
542           if( renderList && !renderList->IsEmpty() )
543           {
544             const std::size_t itemCount = renderList->Count();
545             for( uint32_t itemIndex = 0u; itemIndex < itemCount; ++itemIndex )
546             {
547               const RenderItem& item = renderList->GetItem( itemIndex );
548               if( DALI_LIKELY( item.mRenderer ) )
549               {
550                 item.mRenderer->Upload( *mImpl->currentContext );
551               }
552             }
553           }
554         }
555       }
556     }
557
558     for( uint32_t i = 0; i < count; ++i )
559     {
560       RenderInstruction& instruction = mImpl->instructions.At( mImpl->renderBufferIndex, i );
561
562       DoRender( instruction );
563     }
564
565     if ( mImpl->currentContext->IsSurfacelessContextSupported() )
566     {
567       mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent();
568     }
569
570     GLenum attachments[] = { GL_DEPTH, GL_STENCIL };
571     mImpl->context.InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
572     for ( auto&& context : mImpl->surfaceContextContainer )
573     {
574       context->InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
575     }
576
577     //Notify RenderGeometries that rendering has finished
578     for ( auto&& iter : mImpl->geometryContainer )
579     {
580       iter->OnRenderFinished();
581     }
582   }
583   else
584   {
585     DALI_LOG_RELEASE_INFO( "RenderManager::Render: Skip rendering [%d, %d, %d]\n", haveInstructions, mImpl->lastFrameWasRendered, forceClear );
586   }
587
588   mImpl->UpdateTrackers();
589
590   // If this frame was rendered due to instructions existing, we mark this so we know to clear the next frame.
591   mImpl->lastFrameWasRendered = haveInstructions;
592
593   /**
594    * The rendering has finished; swap to the next buffer.
595    * Ideally the update has just finished using this buffer; otherwise the render thread
596    * should block until the update has finished.
597    */
598   mImpl->renderBufferIndex = (0 != mImpl->renderBufferIndex) ? 0 : 1;
599
600   DALI_PRINT_RENDER_END();
601 }
602
603 bool GetDamagedRect( Rect<int32_t> &viewportRect, RenderInstruction& instruction, Rect<int32_t> &damagedRect )
604 {
605   // merge bounding
606   int dx1 = viewportRect.width, dx2 = 0, dy1 = viewportRect.height, dy2 = 0;
607   int checkWidth = static_cast<int>( static_cast<float>( viewportRect.width ) * partialUpdateRatio );
608   int checkHeight = static_cast<int>( static_cast<float>( viewportRect.height ) * partialUpdateRatio );
609   Rect<int32_t> screenRect;
610
611   bool isPartialUpdate = false;
612
613   const RenderListContainer::SizeType renderListCount = instruction.RenderListCount();
614   // Iterate through each render list.
615
616   for( RenderListContainer::SizeType index = 0; index < renderListCount; ++index )
617   {
618     const RenderList* renderList = instruction.GetRenderList( index );
619
620     if( renderList && !renderList->IsEmpty() && renderList->IsPartialUpdateEnabled() )
621     {
622       const std::size_t itemCount = renderList->Count();
623       for( uint32_t itemIndex = 0u; itemIndex < itemCount; ++itemIndex )
624       {
625         const RenderItem& item = renderList->GetItem( itemIndex );
626
627         if( item.mPartialUpdateEnabled )
628         {
629           isPartialUpdate = true;
630
631           screenRect = item.CalculateViewportSpaceAABB( viewportRect.width, viewportRect.height, true );
632
633           dx1 = std::min( screenRect.x, dx1 );
634           dx2 = std::max( screenRect.x + screenRect.width, dx2);
635           dy1 = std::min( screenRect.y, dy1 );
636           dy2 = std::max( screenRect.y + screenRect.height, dy2 );
637
638           if( ( dx2 - dx1 )  > checkWidth && ( dy2 - dy1 ) > checkHeight )
639           {
640             return false;
641           }
642         }
643       }
644     }
645   }
646
647   if( isPartialUpdate )
648   {
649     damagedRect.x = dx1 - partialUpdateMargin;
650     damagedRect.y = dy1 - partialUpdateMargin;
651     damagedRect.width = dx2 - dx1 + ( 2 * partialUpdateMargin );
652     damagedRect.height = dy2 - dy1 + ( 2 * partialUpdateMargin );
653   }
654
655   return isPartialUpdate;
656 }
657
658 void RenderManager::DoRender( RenderInstruction& instruction )
659 {
660   Rect<int32_t> viewportRect;
661   Vector4   clearColor;
662   bool isPartialUpdate = false;
663   Rect<int32_t> damagedRect;
664   Rect<int32_t> mergedRect;
665   Dali::ClippingBox scissorBox;
666
667   if ( instruction.mIsClearColorSet )
668   {
669     clearColor = instruction.mClearColor;
670   }
671   else
672   {
673     clearColor = Dali::RenderTask::DEFAULT_CLEAR_COLOR;
674   }
675
676   Rect<int32_t> surfaceRect = mImpl->defaultSurfaceRect;
677   int surfaceOrientation = mImpl->defaultSurfaceOrientation;
678   Vector4 backgroundColor = mImpl->backgroundColor;
679   Integration::DepthBufferAvailable depthBufferAvailable = mImpl->depthBufferAvailable;
680   Integration::StencilBufferAvailable stencilBufferAvailable = mImpl->stencilBufferAvailable;
681   Integration::PartialUpdateAvailable partialUpdateAvailable = mImpl->partialUpdateAvailable;
682
683   Render::SurfaceFrameBuffer* surfaceFrameBuffer = nullptr;
684   if ( instruction.mFrameBuffer != 0 )
685   {
686     if ( instruction.mFrameBuffer->IsSurfaceBacked() )
687     {
688       surfaceFrameBuffer = static_cast<Render::SurfaceFrameBuffer*>( instruction.mFrameBuffer );
689
690       if ( !surfaceFrameBuffer->IsSurfaceValid() )
691       {
692         // Skip rendering the frame buffer if the render surface becomes invalid
693         return;
694       }
695
696       if ( mImpl->currentContext->IsSurfacelessContextSupported() )
697       {
698         Context* surfaceContext = surfaceFrameBuffer->GetContext();
699         if ( mImpl->currentContext != surfaceContext )
700         {
701           // Switch the correct context if rendering to a surface
702           mImpl->currentContext = surfaceContext;
703           surfaceFrameBuffer->MakeContextCurrent();
704
705           // Clear the current cached program when the context is switched
706           mImpl->programController.ClearCurrentProgram();
707         }
708       }
709
710       surfaceRect = Rect<int32_t>( 0, 0, static_cast<int32_t>( surfaceFrameBuffer->GetWidth() ), static_cast<int32_t>( surfaceFrameBuffer->GetHeight() ) );
711       backgroundColor = surfaceFrameBuffer->GetBackgroundColor();
712     }
713     else
714     {
715       // Switch to shared context for off-screen buffer
716       mImpl->currentContext = &mImpl->context;
717
718       if ( mImpl->currentContext->IsSurfacelessContextSupported() )
719       {
720         mImpl->glContextHelperAbstraction.MakeSurfacelessContextCurrent();
721       }
722     }
723   }
724
725   DALI_ASSERT_DEBUG( mImpl->currentContext->IsGlContextCreated() );
726
727   // reset the program matrices for all programs once per frame
728   // this ensures we will set view and projection matrix once per program per camera
729   mImpl->programController.ResetProgramMatrices();
730
731   if( instruction.mFrameBuffer )
732   {
733     instruction.mFrameBuffer->Bind( *mImpl->currentContext );
734
735     if ( !instruction.mFrameBuffer->IsSurfaceBacked() )
736     {
737       // For each offscreen buffer, update the dependency list with the new texture id used by this frame buffer.
738       Render::TextureFrameBuffer* textureFrameBuffer = static_cast<Render::TextureFrameBuffer*>( instruction.mFrameBuffer );
739       mImpl->textureDependencyList.PushBack( textureFrameBuffer->GetTextureId() );
740     }
741   }
742   else
743   {
744     mImpl->currentContext->BindFramebuffer( GL_FRAMEBUFFER, 0u );
745   }
746
747
748   if( surfaceFrameBuffer &&
749       partialUpdateAvailable == Integration::PartialUpdateAvailable::TRUE )
750   {
751     const RenderListContainer::SizeType renderListCount = instruction.RenderListCount();
752     // Iterate through each render list.
753     if( surfaceFrameBuffer->IsPartialUpdateEnabled() )
754     {
755       isPartialUpdate = GetDamagedRect( surfaceRect, instruction, damagedRect ) ;
756     }
757
758     if( !isPartialUpdate )
759     {
760       damagedRect = surfaceRect;
761     }
762
763     mergedRect = surfaceFrameBuffer->SetDamagedRect( damagedRect );
764
765     if( mergedRect.IsEmpty() )
766     {
767       isPartialUpdate = false;
768     }
769     else
770     {
771       scissorBox.x = mergedRect.x;
772       scissorBox.y = mergedRect.y;
773       scissorBox.width = mergedRect.width;
774       scissorBox.height = mergedRect.height;
775     }
776   }
777
778   if ( surfaceFrameBuffer )
779   {
780       mImpl->currentContext->Viewport( surfaceRect.x,
781                                 surfaceRect.y,
782                                 surfaceRect.width,
783                                 surfaceRect.height );
784
785
786       mImpl->currentContext->ClearColor( backgroundColor.r,
787                                   backgroundColor.g,
788                                   backgroundColor.b,
789                                   backgroundColor.a );
790   }
791
792   // Clear the entire color, depth and stencil buffers for the default framebuffer, if required.
793   // It is important to clear all 3 buffers when they are being used, for performance on deferred renderers
794   // e.g. previously when the depth & stencil buffers were NOT cleared, it caused the DDK to exceed a "vertex count limit",
795   // and then stall. That problem is only noticeable when rendering a large number of vertices per frame.
796   mImpl->currentContext->SetScissorTest( false );
797
798   if( isPartialUpdate )
799   {
800     mImpl->currentContext->SetScissorTest( true );
801     mImpl->currentContext->Scissor( scissorBox.x, scissorBox.y, scissorBox.width, scissorBox.height );
802   }
803
804   GLbitfield clearMask = GL_COLOR_BUFFER_BIT;
805
806   mImpl->currentContext->ColorMask( true );
807
808   if( depthBufferAvailable == Integration::DepthBufferAvailable::TRUE )
809   {
810     mImpl->currentContext->DepthMask( true );
811     clearMask |= GL_DEPTH_BUFFER_BIT;
812   }
813
814   if( stencilBufferAvailable == Integration::StencilBufferAvailable::TRUE)
815   {
816     mImpl->currentContext->ClearStencil( 0 );
817     mImpl->currentContext->StencilMask( 0xFF ); // 8 bit stencil mask, all 1's
818     clearMask |= GL_STENCIL_BUFFER_BIT;
819   }
820
821   mImpl->currentContext->Clear( clearMask, Context::FORCE_CLEAR );
822
823   if( isPartialUpdate )
824   {
825     mImpl->currentContext->SetScissorTest( false );
826   }
827
828
829   if( !instruction.mIgnoreRenderToFbo && ( instruction.mFrameBuffer != 0 ) )
830   {
831     if ( instruction.mFrameBuffer->IsSurfaceBacked() ) // Surface rendering
832     {
833       if ( instruction.mIsViewportSet )
834       {
835         // For glViewport the lower-left corner is (0,0)
836         // For glViewport the lower-left corner is (0,0)
837         const int32_t y = ( surfaceRect.height - instruction.mViewport.height ) - instruction.mViewport.y;
838         viewportRect.Set( instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height );
839       }
840       else
841       {
842         viewportRect = surfaceRect;
843       }
844     }
845     else // Offscreen buffer rendering
846     {
847       if ( instruction.mIsViewportSet )
848       {
849         // For glViewport the lower-left corner is (0,0)
850         const int32_t y = ( instruction.mFrameBuffer->GetHeight() - instruction.mViewport.height ) - instruction.mViewport.y;
851         viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
852       }
853       else
854       {
855         viewportRect.Set( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
856       }
857       surfaceOrientation = 0;
858     }
859   }
860   else // No Offscreen frame buffer rendering
861   {
862     // Check whether a viewport is specified, otherwise the full surface size is used
863     if ( instruction.mFrameBuffer != 0 )
864     {
865       if ( instruction.mIsViewportSet )
866       {
867         // For glViewport the lower-left corner is (0,0)
868         const int32_t y = ( instruction.mFrameBuffer->GetHeight() - instruction.mViewport.height ) - instruction.mViewport.y;
869         viewportRect.Set( instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height );
870       }
871       else
872       {
873         viewportRect.Set( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
874       }
875     }
876     else
877     {
878       viewportRect = surfaceRect;
879     }
880   }
881
882   if ( surfaceOrientation == 90 || surfaceOrientation == 270 )
883   {
884     int temp = viewportRect.width;
885     viewportRect.width = viewportRect.height;
886     viewportRect.height = temp;
887   }
888
889   mImpl->currentContext->Viewport(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height);
890
891   if ( instruction.mIsClearColorSet )
892   {
893     mImpl->currentContext->ClearColor( clearColor.r,
894                                        clearColor.g,
895                                        clearColor.b,
896                                        clearColor.a );
897
898     // Clear the viewport area only
899     mImpl->currentContext->SetScissorTest( true );
900     if( isPartialUpdate )
901     {
902       mImpl->currentContext->Scissor( scissorBox.x, scissorBox.y, scissorBox.width, scissorBox.height );
903     }
904     else
905     {
906       mImpl->currentContext->Scissor( viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height );
907     }
908     mImpl->currentContext->ColorMask( true );
909     mImpl->currentContext->Clear( GL_COLOR_BUFFER_BIT , Context::CHECK_CACHED_VALUES );
910     mImpl->currentContext->SetScissorTest( false );
911   }
912
913   // Clear the list of bound textures
914   mImpl->boundTextures.Clear();
915
916   mImpl->renderAlgorithms.ProcessRenderInstruction(
917       instruction,
918       *mImpl->currentContext,
919       mImpl->renderBufferIndex,
920       depthBufferAvailable,
921       stencilBufferAvailable,
922       mImpl->boundTextures,
923       surfaceOrientation,
924       scissorBox );
925
926   // Synchronise the FBO/Texture access when there are multiple contexts
927   if ( mImpl->currentContext->IsSurfacelessContextSupported() )
928   {
929     // Check whether any binded texture is in the dependency list
930     bool textureFound = false;
931
932     if ( mImpl->boundTextures.Count() > 0u && mImpl->textureDependencyList.Count() > 0u )
933     {
934       for ( auto textureId : mImpl->textureDependencyList )
935       {
936
937         textureFound = std::find_if( mImpl->boundTextures.Begin(), mImpl->boundTextures.End(),
938                                      [textureId]( GLuint id )
939                                      {
940                                        return textureId == id;
941                                      } ) != mImpl->boundTextures.End();
942       }
943     }
944
945     if ( textureFound )
946     {
947
948       if ( !instruction.mFrameBuffer || !instruction.mFrameBuffer->IsSurfaceBacked() )
949       {
950         // For off-screen buffer
951
952         // Wait until all rendering calls for the currently context are executed
953         mImpl->glContextHelperAbstraction.WaitClient();
954
955         // Clear the dependency list
956         mImpl->textureDependencyList.Clear();
957       }
958       else
959       {
960         // For surface-backed frame buffer
961
962         // Worker thread lambda function
963         auto& glContextHelperAbstraction = mImpl->glContextHelperAbstraction;
964         auto workerFunction = [&glContextHelperAbstraction]( int workerThread )
965         {
966           // Switch to the shared context in the worker thread
967           glContextHelperAbstraction.MakeSurfacelessContextCurrent();
968
969           // Wait until all rendering calls for the shared context are executed
970           glContextHelperAbstraction.WaitClient();
971
972           // Must clear the context in the worker thread
973           // Otherwise the shared context cannot be switched to from the render thread
974           glContextHelperAbstraction.MakeContextNull();
975         };
976
977         auto future = mImpl->threadPool->SubmitTask( 0u, workerFunction );
978         if ( future )
979         {
980           mImpl->threadPool->Wait();
981
982           // Clear the dependency list
983           mImpl->textureDependencyList.Clear();
984         }
985       }
986     }
987   }
988
989   if( instruction.mRenderTracker && ( instruction.mFrameBuffer != 0 ) )
990   {
991     // This will create a sync object every frame this render tracker
992     // is alive (though it should be now be created only for
993     // render-once render tasks)
994     instruction.mRenderTracker->CreateSyncObject( mImpl->glSyncAbstraction );
995     instruction.mRenderTracker = NULL; // Only create once.
996   }
997
998   if ( surfaceFrameBuffer )
999   {
1000     surfaceFrameBuffer->PostRender();
1001   }
1002   else
1003   {
1004     mImpl->currentContext->Flush();
1005   }
1006 }
1007
1008 } // namespace SceneGraph
1009
1010 } // namespace Internal
1011
1012 } // namespace Dali