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