[Tizen] Add KeyEventGeneratedSignal for Get KeyEvent normally
[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 // INTERNAL INCLUDES
22 #include <dali/public-api/actors/sampling.h>
23 #include <dali/public-api/common/dali-common.h>
24 #include <dali/public-api/common/stage.h>
25 #include <dali/public-api/render-tasks/render-task.h>
26 #include <dali/integration-api/debug.h>
27 #include <dali/integration-api/core.h>
28 #include <dali/internal/common/owner-pointer.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/common/render-instruction-container.h>
33 #include <dali/internal/render/common/render-instruction.h>
34 #include <dali/internal/render/gl-resources/context.h>
35 #include <dali/internal/render/queue/render-queue.h>
36 #include <dali/internal/render/renderers/render-frame-buffer.h>
37 #include <dali/internal/render/renderers/render-texture-frame-buffer.h>
38 #include <dali/internal/render/renderers/render-surface-frame-buffer.h>
39 #include <dali/internal/render/renderers/render-geometry.h>
40 #include <dali/internal/render/renderers/render-renderer.h>
41 #include <dali/internal/render/renderers/render-sampler.h>
42 #include <dali/internal/render/shaders/program-controller.h>
43
44 namespace Dali
45 {
46
47 namespace Internal
48 {
49
50 namespace SceneGraph
51 {
52
53 #if defined(DEBUG_ENABLED)
54 namespace
55 {
56 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RENDER_MANAGER" );
57 } // unnamed namespace
58 #endif
59
60 /**
61  * Structure to contain internal data
62  */
63 struct RenderManager::Impl
64 {
65   Impl( Integration::GlAbstraction& glAbstraction,
66         Integration::GlSyncAbstraction& glSyncAbstraction,
67         Integration::DepthBufferAvailable depthBufferAvailableParam,
68         Integration::StencilBufferAvailable stencilBufferAvailableParam )
69   : context( glAbstraction ),
70     currentContext( &context ),
71     glAbstraction( glAbstraction ),
72     glSyncAbstraction( glSyncAbstraction ),
73     renderQueue(),
74     instructions(),
75     renderAlgorithms(),
76     backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
77     frameCount( 0u ),
78     renderBufferIndex( SceneGraphBuffers::INITIAL_UPDATE_BUFFER_INDEX ),
79     defaultSurfaceRect(),
80     rendererContainer(),
81     samplerContainer(),
82     textureContainer(),
83     frameBufferContainer(),
84     lastFrameWasRendered( false ),
85     programController( glAbstraction ),
86     depthBufferAvailable( depthBufferAvailableParam ),
87     stencilBufferAvailable( stencilBufferAvailableParam )
88   {
89   }
90
91   ~Impl()
92   {
93   }
94
95   void AddRenderTracker( Render::RenderTracker* renderTracker )
96   {
97     DALI_ASSERT_DEBUG( renderTracker != NULL );
98     mRenderTrackers.PushBack( renderTracker );
99   }
100
101   void RemoveRenderTracker( Render::RenderTracker* renderTracker )
102   {
103     mRenderTrackers.EraseObject( renderTracker );
104   }
105
106   Context* CreateSurfaceContext()
107   {
108     surfaceContextContainer.PushBack( new Context( glAbstraction ) );
109     return surfaceContextContainer[ surfaceContextContainer.Count() - 1 ];
110   }
111
112   void DestroySurfaceContext( Context* surfaceContext )
113   {
114     surfaceContextContainer.EraseObject( surfaceContext );
115   }
116
117   void UpdateTrackers()
118   {
119     for( auto&& iter : mRenderTrackers )
120     {
121       iter->PollSyncObject();
122     }
123   }
124
125   // the order is important for destruction,
126   // programs are owned by context at the moment.
127   Context                                   context;                 ///< Holds the GL state of the share resource context
128   Context*                                  currentContext;          ///< Holds the GL state of the current context for rendering
129   OwnerContainer< Context* >                surfaceContextContainer; ///< List of owned contexts holding the GL state per surface
130   Integration::GlAbstraction&               glAbstraction;           ///< GL abstraction
131   Integration::GlSyncAbstraction&           glSyncAbstraction;       ///< GL sync abstraction
132   RenderQueue                               renderQueue;             ///< A message queue for receiving messages from the update-thread.
133
134   // Render instructions describe what should be rendered during RenderManager::Render()
135   // Owned by RenderManager. Update manager updates instructions for the next frame while we render the current one
136   RenderInstructionContainer                instructions;
137   Render::RenderAlgorithms                  renderAlgorithms;        ///< The RenderAlgorithms object is used to action the renders required by a RenderInstruction
138
139   Vector4                                   backgroundColor;         ///< The glClear color used at the beginning of each frame.
140
141   uint32_t                                  frameCount;              ///< The current frame count
142   BufferIndex                               renderBufferIndex;       ///< The index of the buffer to read from; this is opposite of the "update" buffer
143
144   Rect<int32_t>                             defaultSurfaceRect;      ///< Rectangle for the default surface we are rendering to
145
146   OwnerContainer< Render::Renderer* >       rendererContainer;       ///< List of owned renderers
147   OwnerContainer< Render::Sampler* >        samplerContainer;        ///< List of owned samplers
148   OwnerContainer< Render::Texture* >        textureContainer;        ///< List of owned textures
149   OwnerContainer< Render::FrameBuffer* >    frameBufferContainer;    ///< List of owned framebuffers
150   OwnerContainer< Render::PropertyBuffer* > propertyBufferContainer; ///< List of owned property buffers
151   OwnerContainer< Render::Geometry* >       geometryContainer;       ///< List of owned Geometries
152
153   bool                                      lastFrameWasRendered;    ///< Keeps track of the last frame being rendered due to having render instructions
154
155   OwnerContainer< Render::RenderTracker* >  mRenderTrackers;         ///< List of render trackers
156
157   ProgramController                         programController;        ///< Owner of the GL programs
158
159   Integration::DepthBufferAvailable         depthBufferAvailable;     ///< Whether the depth buffer is available
160   Integration::StencilBufferAvailable       stencilBufferAvailable;   ///< Whether the stencil buffer is available
161
162 };
163
164 RenderManager* RenderManager::New( Integration::GlAbstraction& glAbstraction,
165                                    Integration::GlSyncAbstraction& glSyncAbstraction,
166                                    Integration::DepthBufferAvailable depthBufferAvailable,
167                                    Integration::StencilBufferAvailable stencilBufferAvailable )
168 {
169   RenderManager* manager = new RenderManager;
170   manager->mImpl = new Impl( glAbstraction,
171                              glSyncAbstraction,
172                              depthBufferAvailable,
173                              stencilBufferAvailable );
174   return manager;
175 }
176
177 RenderManager::RenderManager()
178 : mImpl(NULL)
179 {
180 }
181
182 RenderManager::~RenderManager()
183 {
184   delete mImpl;
185 }
186
187 RenderQueue& RenderManager::GetRenderQueue()
188 {
189   return mImpl->renderQueue;
190 }
191
192 void RenderManager::ContextCreated()
193 {
194   mImpl->context.GlContextCreated();
195   mImpl->programController.GlContextCreated();
196
197   // renderers, textures and gpu buffers cannot reinitialize themselves
198   // so they rely on someone reloading the data for them
199 }
200
201 void RenderManager::ContextDestroyed()
202 {
203   mImpl->context.GlContextDestroyed();
204   mImpl->programController.GlContextDestroyed();
205
206   //Inform textures
207   for( auto&& texture : mImpl->textureContainer )
208   {
209     texture->GlContextDestroyed();
210   }
211
212   //Inform framebuffers
213   for( auto&& framebuffer : mImpl->frameBufferContainer )
214   {
215     framebuffer->GlContextDestroyed();
216   }
217
218   // inform renderers
219   for( auto&& renderer : mImpl->rendererContainer )
220   {
221     renderer->GlContextDestroyed();
222   }
223 }
224
225 void RenderManager::SetShaderSaver( ShaderSaver& upstream )
226 {
227   mImpl->programController.SetShaderSaver( upstream );
228 }
229
230 RenderInstructionContainer& RenderManager::GetRenderInstructionContainer()
231 {
232   return mImpl->instructions;
233 }
234
235 void RenderManager::SetBackgroundColor( const Vector4& color )
236 {
237   mImpl->backgroundColor = color;
238 }
239
240 void RenderManager::SetDefaultSurfaceRect(const Rect<int32_t>& rect)
241 {
242   mImpl->defaultSurfaceRect = rect;
243 }
244
245 void RenderManager::AddRenderer( OwnerPointer< Render::Renderer >& renderer )
246 {
247   // Initialize the renderer as we are now in render thread
248   renderer->Initialize( mImpl->context );
249
250   mImpl->rendererContainer.PushBack( renderer.Release() );
251 }
252
253 void RenderManager::RemoveRenderer( Render::Renderer* renderer )
254 {
255   mImpl->rendererContainer.EraseObject( renderer );
256 }
257
258 void RenderManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
259 {
260   mImpl->samplerContainer.PushBack( sampler.Release() );
261 }
262
263 void RenderManager::RemoveSampler( Render::Sampler* sampler )
264 {
265   mImpl->samplerContainer.EraseObject( sampler );
266 }
267
268 void RenderManager::AddTexture( OwnerPointer< Render::Texture >& texture )
269 {
270   texture->Initialize( mImpl->context );
271   mImpl->textureContainer.PushBack( texture.Release() );
272 }
273
274 void RenderManager::RemoveTexture( Render::Texture* texture )
275 {
276   DALI_ASSERT_DEBUG( NULL != texture );
277
278   // Find the texture, use reference to pointer so we can do the erase safely
279   for ( auto&& iter : mImpl->textureContainer )
280   {
281     if ( iter == texture )
282     {
283       texture->Destroy( mImpl->context );
284       mImpl->textureContainer.Erase( &iter ); // Texture found; now destroy it
285       return;
286     }
287   }
288 }
289
290 void RenderManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
291 {
292   texture->Upload( mImpl->context, pixelData, params );
293 }
294
295 void RenderManager::GenerateMipmaps( Render::Texture* texture )
296 {
297   texture->GenerateMipmaps( mImpl->context );
298 }
299
300 void RenderManager::SetFilterMode( Render::Sampler* sampler, uint32_t minFilterMode, uint32_t magFilterMode )
301 {
302   sampler->mMinificationFilter = static_cast<Dali::FilterMode::Type>(minFilterMode);
303   sampler->mMagnificationFilter = static_cast<Dali::FilterMode::Type>(magFilterMode );
304 }
305
306 void RenderManager::SetWrapMode( Render::Sampler* sampler, uint32_t rWrapMode, uint32_t sWrapMode, uint32_t tWrapMode )
307 {
308   sampler->mRWrapMode = static_cast<Dali::WrapMode::Type>(rWrapMode);
309   sampler->mSWrapMode = static_cast<Dali::WrapMode::Type>(sWrapMode);
310   sampler->mTWrapMode = static_cast<Dali::WrapMode::Type>(tWrapMode);
311 }
312
313 void RenderManager::AddFrameBuffer( OwnerPointer< Render::FrameBuffer >& frameBuffer )
314 {
315   Render::FrameBuffer* frameBufferPtr = frameBuffer.Release();
316   mImpl->frameBufferContainer.PushBack( frameBufferPtr );
317   if ( frameBufferPtr->IsSurfaceBacked() )
318   {
319     frameBufferPtr->Initialize( *mImpl->CreateSurfaceContext() );
320   }
321   else
322   {
323     frameBufferPtr->Initialize( mImpl->context );
324   }
325 }
326
327 void RenderManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer )
328 {
329   DALI_ASSERT_DEBUG( NULL != frameBuffer );
330
331   // Find the sampler, use reference so we can safely do the erase
332   for ( auto&& iter : mImpl->frameBufferContainer )
333   {
334     if ( iter == frameBuffer )
335     {
336       frameBuffer->Destroy( mImpl->context );
337
338       if ( frameBuffer->IsSurfaceBacked() )
339       {
340         auto surfaceFrameBuffer = static_cast<Render::SurfaceFrameBuffer*>( frameBuffer );
341         mImpl->DestroySurfaceContext( surfaceFrameBuffer->GetContext() );
342       }
343
344       mImpl->frameBufferContainer.Erase( &iter ); // frameBuffer found; now destroy it
345
346       break;
347     }
348   }
349 }
350
351 void RenderManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer )
352 {
353   if ( !frameBuffer->IsSurfaceBacked() )
354   {
355     auto textureFrameBuffer = static_cast<Render::TextureFrameBuffer*>( frameBuffer );
356     textureFrameBuffer->AttachColorTexture( mImpl->context, texture, mipmapLevel, layer );
357   }
358 }
359
360 void RenderManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer )
361 {
362   mImpl->propertyBufferContainer.PushBack( propertyBuffer.Release() );
363 }
364
365 void RenderManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
366 {
367   mImpl->propertyBufferContainer.EraseObject( propertyBuffer );
368 }
369
370 void RenderManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
371 {
372   propertyBuffer->SetFormat( format.Release() );
373 }
374
375 void RenderManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<uint8_t> >& data, uint32_t size )
376 {
377   propertyBuffer->SetData( data.Release(), size );
378 }
379
380 void RenderManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<uint16_t>& indices )
381 {
382   geometry->SetIndexBuffer( indices );
383 }
384
385 void RenderManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
386 {
387   mImpl->geometryContainer.PushBack( geometry.Release() );
388 }
389
390 void RenderManager::RemoveGeometry( Render::Geometry* geometry )
391 {
392   mImpl->geometryContainer.EraseObject( geometry );
393 }
394
395 void RenderManager::AttachVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
396 {
397   DALI_ASSERT_DEBUG( NULL != geometry );
398
399   // Find the geometry
400   for ( auto&& iter : mImpl->geometryContainer )
401   {
402     if ( iter == geometry )
403     {
404       iter->AddPropertyBuffer( propertyBuffer );
405       break;
406     }
407   }
408 }
409
410 void RenderManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
411 {
412   DALI_ASSERT_DEBUG( NULL != geometry );
413
414   // Find the geometry
415   for ( auto&& iter : mImpl->geometryContainer )
416   {
417     if ( iter == geometry )
418     {
419       iter->RemovePropertyBuffer( propertyBuffer );
420       break;
421     }
422   }
423 }
424
425 void RenderManager::SetGeometryType( Render::Geometry* geometry, uint32_t geometryType )
426 {
427   geometry->SetType( Render::Geometry::Type(geometryType) );
428 }
429
430 void RenderManager::AddRenderTracker( Render::RenderTracker* renderTracker )
431 {
432   mImpl->AddRenderTracker(renderTracker);
433 }
434
435 void RenderManager::RemoveRenderTracker( Render::RenderTracker* renderTracker )
436 {
437   mImpl->RemoveRenderTracker(renderTracker);
438 }
439
440 ProgramCache* RenderManager::GetProgramCache()
441 {
442   return &(mImpl->programController);
443 }
444
445 void RenderManager::Render( Integration::RenderStatus& status, bool forceClear )
446 {
447   DALI_PRINT_RENDER_START( mImpl->renderBufferIndex );
448
449   // Core::Render documents that GL context must be current before calling Render
450   DALI_ASSERT_DEBUG( mImpl->context.IsGlContextCreated() );
451
452   // Increment the frame count at the beginning of each frame
453   ++mImpl->frameCount;
454
455   // Process messages queued during previous update
456   mImpl->renderQueue.ProcessMessages( mImpl->renderBufferIndex );
457
458   const uint32_t count = mImpl->instructions.Count( mImpl->renderBufferIndex );
459   const bool haveInstructions = count > 0u;
460
461   DALI_LOG_INFO( gLogFilter, Debug::General,
462                  "Render: haveInstructions(%s) || mImpl->lastFrameWasRendered(%s) || forceClear(%s)\n",
463                  haveInstructions ? "true" : "false",
464                  mImpl->lastFrameWasRendered ? "true" : "false",
465                  forceClear ? "true" : "false" );
466
467   // Only render if we have instructions to render, or the last frame was rendered (and therefore a clear is required).
468   if( haveInstructions || mImpl->lastFrameWasRendered || forceClear )
469   {
470     DALI_LOG_INFO( gLogFilter, Debug::General, "Render: Processing\n" );
471
472     // Mark that we will require a post-render step to be performed (includes swap-buffers).
473     status.SetNeedsPostRender( true );
474
475     // Switch to the shared context
476     if ( mImpl->currentContext != &mImpl->context )
477     {
478       mImpl->currentContext = &mImpl->context;
479       // Clear the current cached program when the context is switched
480       mImpl->programController.ClearCurrentProgram();
481     }
482
483
484     // Upload the geometries
485     for( uint32_t i = 0; i < count; ++i )
486     {
487       RenderInstruction& instruction = mImpl->instructions.At( mImpl->renderBufferIndex, i );
488
489       const Matrix* viewMatrix       = instruction.GetViewMatrix( mImpl->renderBufferIndex );
490       const Matrix* projectionMatrix = instruction.GetProjectionMatrix( mImpl->renderBufferIndex );
491
492       DALI_ASSERT_DEBUG( viewMatrix );
493       DALI_ASSERT_DEBUG( projectionMatrix );
494
495       if( viewMatrix && projectionMatrix )
496       {
497         const RenderListContainer::SizeType renderListCount = instruction.RenderListCount();
498
499         // Iterate through each render list.
500         for( RenderListContainer::SizeType index = 0; index < renderListCount; ++index )
501         {
502           const RenderList* renderList = instruction.GetRenderList( index );
503
504           if( renderList && !renderList->IsEmpty() )
505           {
506             const std::size_t itemCount = renderList->Count();
507             for( uint32_t itemIndex = 0u; itemIndex < itemCount; ++itemIndex )
508             {
509               const RenderItem& item = renderList->GetItem( itemIndex );
510               if( DALI_LIKELY( item.mRenderer ) )
511               {
512                 item.mRenderer->Upload( *mImpl->currentContext );
513               }
514             }
515           }
516         }
517       }
518     }
519
520     for( uint32_t i = 0; i < count; ++i )
521     {
522       RenderInstruction& instruction = mImpl->instructions.At( mImpl->renderBufferIndex, i );
523
524       DoRender( instruction );
525     }
526
527     GLenum attachments[] = { GL_DEPTH, GL_STENCIL };
528     mImpl->context.InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
529     for ( auto&& context : mImpl->surfaceContextContainer )
530     {
531       context->InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
532     }
533
534     //Notify RenderGeometries that rendering has finished
535     for ( auto&& iter : mImpl->geometryContainer )
536     {
537       iter->OnRenderFinished();
538     }
539   }
540   else
541   {
542     DALI_LOG_RELEASE_INFO( "RenderManager::Render: Skip rendering [%d, %d, %d]\n", haveInstructions, mImpl->lastFrameWasRendered, forceClear );
543   }
544
545   mImpl->UpdateTrackers();
546
547   // If this frame was rendered due to instructions existing, we mark this so we know to clear the next frame.
548   mImpl->lastFrameWasRendered = haveInstructions;
549
550   /**
551    * The rendering has finished; swap to the next buffer.
552    * Ideally the update has just finished using this buffer; otherwise the render thread
553    * should block until the update has finished.
554    */
555   mImpl->renderBufferIndex = (0 != mImpl->renderBufferIndex) ? 0 : 1;
556
557   DALI_PRINT_RENDER_END();
558 }
559
560 void RenderManager::DoRender( RenderInstruction& instruction )
561 {
562   Rect<int32_t> viewportRect;
563   Vector4   clearColor;
564
565   if ( instruction.mIsClearColorSet )
566   {
567     clearColor = instruction.mClearColor;
568   }
569   else
570   {
571     clearColor = Dali::RenderTask::DEFAULT_CLEAR_COLOR;
572   }
573
574   Rect<int32_t> surfaceRect = mImpl->defaultSurfaceRect;
575   Vector4 backgroundColor = mImpl->backgroundColor;
576   Integration::DepthBufferAvailable depthBufferAvailable = mImpl->depthBufferAvailable;
577   Integration::StencilBufferAvailable stencilBufferAvailable = mImpl->stencilBufferAvailable;
578
579   Render::SurfaceFrameBuffer* surfaceFrameBuffer = nullptr;
580   if ( instruction.mFrameBuffer != 0 )
581   {
582     if ( instruction.mFrameBuffer->IsSurfaceBacked() )
583     {
584       surfaceFrameBuffer = static_cast<Render::SurfaceFrameBuffer*>( instruction.mFrameBuffer );
585
586       if ( mImpl->currentContext->IsSurfacelessContextSupported() )
587       {
588         Context* surfaceContext = surfaceFrameBuffer->GetContext();
589         if ( mImpl->currentContext != surfaceContext )
590         {
591           // Switch the correct context if rendering to a surface
592           mImpl->currentContext = surfaceContext;
593           // Clear the current cached program when the context is switched
594           mImpl->programController.ClearCurrentProgram();
595         }
596       }
597
598       surfaceRect = Rect<int32_t>( 0, 0, static_cast<int32_t>( surfaceFrameBuffer->GetWidth() ), static_cast<int32_t>( surfaceFrameBuffer->GetHeight() ) );
599       backgroundColor = surfaceFrameBuffer->GetBackgroundColor();
600     }
601     else
602     {
603       // Switch to shared context for off-screen buffer
604       mImpl->currentContext = &mImpl->context;
605     }
606   }
607
608   DALI_ASSERT_DEBUG( mImpl->currentContext->IsGlContextCreated() );
609
610   // reset the program matrices for all programs once per frame
611   // this ensures we will set view and projection matrix once per program per camera
612   mImpl->programController.ResetProgramMatrices();
613
614   if( instruction.mFrameBuffer )
615   {
616     instruction.mFrameBuffer->Bind( *mImpl->currentContext );
617   }
618   else
619   {
620     mImpl->currentContext->BindFramebuffer( GL_FRAMEBUFFER, 0u );
621   }
622
623   if ( surfaceFrameBuffer )
624   {
625     mImpl->currentContext->Viewport( surfaceRect.x,
626                               surfaceRect.y,
627                               surfaceRect.width,
628                               surfaceRect.height );
629
630     mImpl->currentContext->ClearColor( backgroundColor.r,
631                                 backgroundColor.g,
632                                 backgroundColor.b,
633                                 backgroundColor.a );
634   }
635
636   // Clear the entire color, depth and stencil buffers for the default framebuffer, if required.
637   // It is important to clear all 3 buffers when they are being used, for performance on deferred renderers
638   // e.g. previously when the depth & stencil buffers were NOT cleared, it caused the DDK to exceed a "vertex count limit",
639   // and then stall. That problem is only noticeable when rendering a large number of vertices per frame.
640
641   mImpl->currentContext->SetScissorTest( false );
642
643   GLbitfield clearMask = GL_COLOR_BUFFER_BIT;
644
645   mImpl->currentContext->ColorMask( true );
646
647   if( depthBufferAvailable == Integration::DepthBufferAvailable::TRUE )
648   {
649     mImpl->currentContext->DepthMask( true );
650     clearMask |= GL_DEPTH_BUFFER_BIT;
651   }
652
653   if( stencilBufferAvailable == Integration::StencilBufferAvailable::TRUE)
654   {
655     mImpl->currentContext->ClearStencil( 0 );
656     mImpl->currentContext->StencilMask( 0xFF ); // 8 bit stencil mask, all 1's
657     clearMask |= GL_STENCIL_BUFFER_BIT;
658   }
659
660   mImpl->currentContext->Clear( clearMask, Context::FORCE_CLEAR );
661
662   if( !instruction.mIgnoreRenderToFbo && ( instruction.mFrameBuffer != 0 ) )
663   {
664     if ( instruction.mFrameBuffer->IsSurfaceBacked() ) // Surface rendering
665     {
666       if ( instruction.mIsViewportSet )
667       {
668         // For glViewport the lower-left corner is (0,0)
669         // For glViewport the lower-left corner is (0,0)
670         const int32_t y = ( surfaceRect.height - instruction.mViewport.height ) - instruction.mViewport.y;
671         viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
672       }
673       else
674       {
675         viewportRect = surfaceRect;
676       }
677     }
678     else // Offscreen buffer rendering
679     {
680       if ( instruction.mIsViewportSet )
681       {
682         // For glViewport the lower-left corner is (0,0)
683         const int32_t y = ( instruction.mFrameBuffer->GetHeight() - instruction.mViewport.height ) - instruction.mViewport.y;
684         viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
685       }
686       else
687       {
688         viewportRect.Set( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
689       }
690     }
691   }
692   else // No Offscreen frame buffer rendering
693   {
694     // Check whether a viewport is specified, otherwise the full surface size is used
695     if ( instruction.mFrameBuffer != 0 )
696     {
697       if ( instruction.mIsViewportSet )
698       {
699         // For glViewport the lower-left corner is (0,0)
700         const int32_t y = ( instruction.mFrameBuffer->GetHeight() - instruction.mViewport.height ) - instruction.mViewport.y;
701         viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
702       }
703       else
704       {
705         viewportRect.Set( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
706       }
707     }
708     else
709     {
710       viewportRect = surfaceRect;
711     }
712   }
713
714   mImpl->currentContext->Viewport(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height);
715
716   if ( instruction.mIsClearColorSet )
717   {
718     mImpl->currentContext->ClearColor( clearColor.r,
719                                        clearColor.g,
720                                        clearColor.b,
721                                        clearColor.a );
722
723     // Clear the viewport area only
724     mImpl->currentContext->SetScissorTest( true );
725     mImpl->currentContext->Scissor( viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height );
726     mImpl->currentContext->ColorMask( true );
727     mImpl->currentContext->Clear( GL_COLOR_BUFFER_BIT , Context::CHECK_CACHED_VALUES );
728     mImpl->currentContext->SetScissorTest( false );
729   }
730
731   mImpl->renderAlgorithms.ProcessRenderInstruction(
732       instruction,
733       *mImpl->currentContext,
734       mImpl->renderBufferIndex,
735       depthBufferAvailable,
736       stencilBufferAvailable );
737
738   if( instruction.mRenderTracker && ( instruction.mFrameBuffer != 0 ) )
739   {
740     // This will create a sync object every frame this render tracker
741     // is alive (though it should be now be created only for
742     // render-once render tasks)
743     instruction.mRenderTracker->CreateSyncObject( mImpl->glSyncAbstraction );
744     instruction.mRenderTracker = NULL; // Only create once.
745   }
746
747   if ( surfaceFrameBuffer )
748   {
749     surfaceFrameBuffer->PostRender();
750   }
751 }
752
753 } // namespace SceneGraph
754
755 } // namespace Internal
756
757 } // namespace Dali