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