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