Remove dependency of OpenGL es version.
[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( Render::FrameBuffer* frameBuffer )
307 {
308   mImpl->frameBufferContainer.PushBack( frameBuffer );
309   if ( frameBuffer->IsSurfaceBacked() )
310   {
311     frameBuffer->Initialize( *mImpl->CreateSurfaceContext() );
312   }
313   else
314   {
315     frameBuffer->Initialize( mImpl->context );
316   }
317 }
318
319 void RenderManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer )
320 {
321   DALI_ASSERT_DEBUG( NULL != frameBuffer );
322
323   // Find the sampler, use reference so we can safely do the erase
324   for ( auto&& iter : mImpl->frameBufferContainer )
325   {
326     if ( iter == frameBuffer )
327     {
328       frameBuffer->Destroy( mImpl->context );
329
330       if ( frameBuffer->IsSurfaceBacked() )
331       {
332         auto surfaceFrameBuffer = static_cast<Render::SurfaceFrameBuffer*>( frameBuffer );
333         mImpl->DestroySurfaceContext( surfaceFrameBuffer->GetContext() );
334       }
335
336       mImpl->frameBufferContainer.Erase( &iter ); // frameBuffer found; now destroy it
337
338       break;
339     }
340   }
341 }
342
343 void RenderManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer )
344 {
345   if ( !frameBuffer->IsSurfaceBacked() )
346   {
347     auto textureFrameBuffer = static_cast<Render::TextureFrameBuffer*>( frameBuffer );
348     textureFrameBuffer->AttachColorTexture( mImpl->context, texture, mipmapLevel, layer );
349   }
350 }
351
352 void RenderManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer )
353 {
354   mImpl->propertyBufferContainer.PushBack( propertyBuffer.Release() );
355 }
356
357 void RenderManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
358 {
359   mImpl->propertyBufferContainer.EraseObject( propertyBuffer );
360 }
361
362 void RenderManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
363 {
364   propertyBuffer->SetFormat( format.Release() );
365 }
366
367 void RenderManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<uint8_t> >& data, uint32_t size )
368 {
369   propertyBuffer->SetData( data.Release(), size );
370 }
371
372 void RenderManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<uint16_t>& indices )
373 {
374   geometry->SetIndexBuffer( indices );
375 }
376
377 void RenderManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
378 {
379   mImpl->geometryContainer.PushBack( geometry.Release() );
380 }
381
382 void RenderManager::RemoveGeometry( Render::Geometry* geometry )
383 {
384   mImpl->geometryContainer.EraseObject( geometry );
385 }
386
387 void RenderManager::AttachVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
388 {
389   DALI_ASSERT_DEBUG( NULL != geometry );
390
391   // Find the geometry
392   for ( auto&& iter : mImpl->geometryContainer )
393   {
394     if ( iter == geometry )
395     {
396       iter->AddPropertyBuffer( propertyBuffer );
397       break;
398     }
399   }
400 }
401
402 void RenderManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
403 {
404   DALI_ASSERT_DEBUG( NULL != geometry );
405
406   // Find the geometry
407   for ( auto&& iter : mImpl->geometryContainer )
408   {
409     if ( iter == geometry )
410     {
411       iter->RemovePropertyBuffer( propertyBuffer );
412       break;
413     }
414   }
415 }
416
417 void RenderManager::SetGeometryType( Render::Geometry* geometry, uint32_t geometryType )
418 {
419   geometry->SetType( Render::Geometry::Type(geometryType) );
420 }
421
422 void RenderManager::AddRenderTracker( Render::RenderTracker* renderTracker )
423 {
424   mImpl->AddRenderTracker(renderTracker);
425 }
426
427 void RenderManager::RemoveRenderTracker( Render::RenderTracker* renderTracker )
428 {
429   mImpl->RemoveRenderTracker(renderTracker);
430 }
431
432 ProgramCache* RenderManager::GetProgramCache()
433 {
434   return &(mImpl->programController);
435 }
436
437 void RenderManager::Render( Integration::RenderStatus& status, bool forceClear )
438 {
439   DALI_PRINT_RENDER_START( mImpl->renderBufferIndex );
440
441   // Core::Render documents that GL context must be current before calling Render
442   DALI_ASSERT_DEBUG( mImpl->context.IsGlContextCreated() );
443
444   // Increment the frame count at the beginning of each frame
445   ++mImpl->frameCount;
446
447   // Process messages queued during previous update
448   mImpl->renderQueue.ProcessMessages( mImpl->renderBufferIndex );
449
450   const uint32_t count = mImpl->instructions.Count( mImpl->renderBufferIndex );
451   const bool haveInstructions = count > 0u;
452
453   // Only render if we have instructions to render, or the last frame was rendered (and therefore a clear is required).
454   if( haveInstructions || mImpl->lastFrameWasRendered || forceClear )
455   {
456     // Mark that we will require a post-render step to be performed (includes swap-buffers).
457     status.SetNeedsPostRender( true );
458
459     // Switch to the shared context
460     if ( mImpl->currentContext != &mImpl->context )
461     {
462       mImpl->currentContext = &mImpl->context;
463       // Clear the current cached program when the context is switched
464       mImpl->programController.ClearCurrentProgram();
465     }
466
467
468     // Upload the geometries
469     for( uint32_t i = 0; i < count; ++i )
470     {
471       RenderInstruction& instruction = mImpl->instructions.At( mImpl->renderBufferIndex, i );
472
473       const Matrix* viewMatrix       = instruction.GetViewMatrix( mImpl->renderBufferIndex );
474       const Matrix* projectionMatrix = instruction.GetProjectionMatrix( mImpl->renderBufferIndex );
475
476       DALI_ASSERT_DEBUG( viewMatrix );
477       DALI_ASSERT_DEBUG( projectionMatrix );
478
479       if( viewMatrix && projectionMatrix )
480       {
481         const RenderListContainer::SizeType renderListCount = instruction.RenderListCount();
482
483         // Iterate through each render list.
484         for( RenderListContainer::SizeType index = 0; index < renderListCount; ++index )
485         {
486           const RenderList* renderList = instruction.GetRenderList( index );
487
488           if( renderList && !renderList->IsEmpty() )
489           {
490             const std::size_t itemCount = renderList->Count();
491             for( uint32_t itemIndex = 0u; itemIndex < itemCount; ++itemIndex )
492             {
493               const RenderItem& item = renderList->GetItem( itemIndex );
494               if( DALI_LIKELY( item.mRenderer ) )
495               {
496                 item.mRenderer->Upload( *mImpl->currentContext );
497               }
498             }
499           }
500         }
501       }
502     }
503
504     for( uint32_t i = 0; i < count; ++i )
505     {
506       RenderInstruction& instruction = mImpl->instructions.At( mImpl->renderBufferIndex, i );
507
508       DoRender( instruction );
509     }
510
511     GLenum attachments[] = { GL_DEPTH, GL_STENCIL };
512     mImpl->context.InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
513     for ( auto&& context : mImpl->surfaceContextContainer )
514     {
515       context->InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
516     }
517
518     //Notify RenderGeometries that rendering has finished
519     for ( auto&& iter : mImpl->geometryContainer )
520     {
521       iter->OnRenderFinished();
522     }
523   }
524
525   mImpl->UpdateTrackers();
526
527   // If this frame was rendered due to instructions existing, we mark this so we know to clear the next frame.
528   mImpl->lastFrameWasRendered = haveInstructions;
529
530   /**
531    * The rendering has finished; swap to the next buffer.
532    * Ideally the update has just finished using this buffer; otherwise the render thread
533    * should block until the update has finished.
534    */
535   mImpl->renderBufferIndex = (0 != mImpl->renderBufferIndex) ? 0 : 1;
536
537   DALI_PRINT_RENDER_END();
538 }
539
540 void RenderManager::DoRender( RenderInstruction& instruction )
541 {
542   Rect<int32_t> viewportRect;
543   Vector4   clearColor;
544
545   if ( instruction.mIsClearColorSet )
546   {
547     clearColor = instruction.mClearColor;
548   }
549   else
550   {
551     clearColor = Dali::RenderTask::DEFAULT_CLEAR_COLOR;
552   }
553
554   Rect<int32_t> surfaceRect = mImpl->defaultSurfaceRect;
555   Vector4 backgroundColor = mImpl->backgroundColor;
556   Integration::DepthBufferAvailable depthBufferAvailable = mImpl->depthBufferAvailable;
557   Integration::StencilBufferAvailable stencilBufferAvailable = mImpl->stencilBufferAvailable;
558
559   Render::SurfaceFrameBuffer* surfaceFrameBuffer = nullptr;
560   if ( ( instruction.mFrameBuffer != 0 ) && instruction.mFrameBuffer->IsSurfaceBacked() )
561   {
562     surfaceFrameBuffer = static_cast<Render::SurfaceFrameBuffer*>( instruction.mFrameBuffer );
563
564     // For the Multi-Windows
565     Context* surfaceContext = surfaceFrameBuffer->GetContext();
566     if ( mImpl->currentContext != surfaceContext )
567     {
568       // Switch the correct context if rendering to a surface
569       mImpl->currentContext = surfaceContext;
570       // Clear the current cached program when the context is switched
571       mImpl->programController.ClearCurrentProgram();
572     }
573
574     surfaceRect = Rect<int32_t>( 0, 0, static_cast<int32_t>( surfaceFrameBuffer->GetWidth() ), static_cast<int32_t>( surfaceFrameBuffer->GetHeight() ) );
575     backgroundColor = surfaceFrameBuffer->GetBackgroundColor();
576   }
577
578   DALI_ASSERT_DEBUG( mImpl->currentContext->IsGlContextCreated() );
579
580   // reset the program matrices for all programs once per frame
581   // this ensures we will set view and projection matrix once per program per camera
582   mImpl->programController.ResetProgramMatrices();
583
584   if( instruction.mFrameBuffer )
585   {
586     instruction.mFrameBuffer->Bind( *mImpl->currentContext );
587   }
588
589   mImpl->currentContext->Viewport( surfaceRect.x,
590                             surfaceRect.y,
591                             surfaceRect.width,
592                             surfaceRect.height );
593
594   mImpl->currentContext->ClearColor( backgroundColor.r,
595                               backgroundColor.g,
596                               backgroundColor.b,
597                               backgroundColor.a );
598
599   // Clear the entire color, depth and stencil buffers for the default framebuffer, if required.
600   // It is important to clear all 3 buffers when they are being used, for performance on deferred renderers
601   // e.g. previously when the depth & stencil buffers were NOT cleared, it caused the DDK to exceed a "vertex count limit",
602   // and then stall. That problem is only noticeable when rendering a large number of vertices per frame.
603
604   mImpl->currentContext->SetScissorTest( false );
605
606   GLbitfield clearMask = GL_COLOR_BUFFER_BIT;
607
608   mImpl->currentContext->ColorMask( true );
609
610   if( depthBufferAvailable == Integration::DepthBufferAvailable::TRUE )
611   {
612     mImpl->currentContext->DepthMask( true );
613     clearMask |= GL_DEPTH_BUFFER_BIT;
614   }
615
616   if( stencilBufferAvailable == Integration::StencilBufferAvailable::TRUE)
617   {
618     mImpl->currentContext->ClearStencil( 0 );
619     mImpl->currentContext->StencilMask( 0xFF ); // 8 bit stencil mask, all 1's
620     clearMask |= GL_STENCIL_BUFFER_BIT;
621   }
622
623   mImpl->currentContext->Clear( clearMask, Context::FORCE_CLEAR );
624
625   if( !instruction.mIgnoreRenderToFbo && ( instruction.mFrameBuffer != 0 ) )
626   {
627     if ( instruction.mFrameBuffer->IsSurfaceBacked() ) // Surface rendering
628     {
629       if ( instruction.mIsViewportSet )
630       {
631         // For glViewport the lower-left corner is (0,0)
632         // For glViewport the lower-left corner is (0,0)
633         const int32_t y = ( surfaceRect.height - instruction.mViewport.height ) - instruction.mViewport.y;
634         viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
635       }
636       else
637       {
638         viewportRect = surfaceRect;
639       }
640     }
641     else // Offscreen buffer rendering
642     {
643       if ( instruction.mIsViewportSet )
644       {
645         // For glViewport the lower-left corner is (0,0)
646         const int32_t y = ( instruction.mFrameBuffer->GetHeight() - instruction.mViewport.height ) - instruction.mViewport.y;
647         viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
648       }
649       else
650       {
651         viewportRect.Set( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
652       }
653     }
654   }
655   else // No Offscreen frame buffer rendering
656   {
657     // Check whether a viewport is specified, otherwise the full surface size is used
658     if ( instruction.mFrameBuffer != 0 )
659     {
660       if ( instruction.mIsViewportSet )
661       {
662         // For glViewport the lower-left corner is (0,0)
663         const int32_t y = ( instruction.mFrameBuffer->GetHeight() - instruction.mViewport.height ) - instruction.mViewport.y;
664         viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
665       }
666       else
667       {
668         viewportRect.Set( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
669       }
670     }
671     else
672     {
673       viewportRect = surfaceRect;
674     }
675   }
676
677   mImpl->currentContext->Viewport(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height);
678
679   if ( instruction.mIsClearColorSet )
680   {
681     mImpl->currentContext->ClearColor( clearColor.r,
682                                        clearColor.g,
683                                        clearColor.b,
684                                        clearColor.a );
685
686     // Clear the viewport area only
687     mImpl->currentContext->SetScissorTest( true );
688     mImpl->currentContext->Scissor( viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height );
689     mImpl->currentContext->ColorMask( true );
690     mImpl->currentContext->Clear( GL_COLOR_BUFFER_BIT , Context::CHECK_CACHED_VALUES );
691     mImpl->currentContext->SetScissorTest( false );
692   }
693
694   mImpl->renderAlgorithms.ProcessRenderInstruction(
695       instruction,
696       *mImpl->currentContext,
697       mImpl->renderBufferIndex,
698       depthBufferAvailable,
699       stencilBufferAvailable );
700
701   if( instruction.mRenderTracker && ( instruction.mFrameBuffer != 0 ) )
702   {
703     // This will create a sync object every frame this render tracker
704     // is alive (though it should be now be created only for
705     // render-once render tasks)
706     instruction.mRenderTracker->CreateSyncObject( mImpl->glSyncAbstraction );
707     instruction.mRenderTracker = NULL; // Only create once.
708   }
709
710   if ( surfaceFrameBuffer )
711   {
712     surfaceFrameBuffer->PostRender();
713   }
714 }
715
716 } // namespace SceneGraph
717
718 } // namespace Internal
719
720 } // namespace Dali