Merge branch 'devel/master' into tizen
[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   else
525   {
526     DALI_LOG_RELEASE_INFO( "RenderManager::Render: Skip rendering [%d, %d, %d]\n", haveInstructions, mImpl->lastFrameWasRendered, forceClear );
527   }
528
529   mImpl->UpdateTrackers();
530
531   // If this frame was rendered due to instructions existing, we mark this so we know to clear the next frame.
532   mImpl->lastFrameWasRendered = haveInstructions;
533
534   /**
535    * The rendering has finished; swap to the next buffer.
536    * Ideally the update has just finished using this buffer; otherwise the render thread
537    * should block until the update has finished.
538    */
539   mImpl->renderBufferIndex = (0 != mImpl->renderBufferIndex) ? 0 : 1;
540
541   DALI_PRINT_RENDER_END();
542 }
543
544 void RenderManager::DoRender( RenderInstruction& instruction )
545 {
546   Rect<int32_t> viewportRect;
547   Vector4   clearColor;
548
549   if ( instruction.mIsClearColorSet )
550   {
551     clearColor = instruction.mClearColor;
552   }
553   else
554   {
555     clearColor = Dali::RenderTask::DEFAULT_CLEAR_COLOR;
556   }
557
558   Rect<int32_t> surfaceRect = mImpl->defaultSurfaceRect;
559   Vector4 backgroundColor = mImpl->backgroundColor;
560   Integration::DepthBufferAvailable depthBufferAvailable = mImpl->depthBufferAvailable;
561   Integration::StencilBufferAvailable stencilBufferAvailable = mImpl->stencilBufferAvailable;
562
563   Render::SurfaceFrameBuffer* surfaceFrameBuffer = nullptr;
564   if ( ( instruction.mFrameBuffer != 0 ) && instruction.mFrameBuffer->IsSurfaceBacked() )
565   {
566     surfaceFrameBuffer = static_cast<Render::SurfaceFrameBuffer*>( instruction.mFrameBuffer );
567
568     if ( mImpl->currentContext->IsSurfacelessContextSupported() )
569     {
570       Context* surfaceContext = surfaceFrameBuffer->GetContext();
571       if ( mImpl->currentContext != surfaceContext )
572       {
573         // Switch the correct context if rendering to a surface
574         mImpl->currentContext = surfaceContext;
575         // Clear the current cached program when the context is switched
576         mImpl->programController.ClearCurrentProgram();
577       }
578     }
579
580     surfaceRect = Rect<int32_t>( 0, 0, static_cast<int32_t>( surfaceFrameBuffer->GetWidth() ), static_cast<int32_t>( surfaceFrameBuffer->GetHeight() ) );
581     backgroundColor = surfaceFrameBuffer->GetBackgroundColor();
582   }
583
584   DALI_ASSERT_DEBUG( mImpl->currentContext->IsGlContextCreated() );
585
586   // reset the program matrices for all programs once per frame
587   // this ensures we will set view and projection matrix once per program per camera
588   mImpl->programController.ResetProgramMatrices();
589
590   if( instruction.mFrameBuffer )
591   {
592     instruction.mFrameBuffer->Bind( *mImpl->currentContext );
593   }
594   else
595   {
596     mImpl->currentContext->BindFramebuffer( GL_FRAMEBUFFER, 0u );
597   }
598
599   if ( surfaceFrameBuffer )
600   {
601     mImpl->currentContext->Viewport( surfaceRect.x,
602                               surfaceRect.y,
603                               surfaceRect.width,
604                               surfaceRect.height );
605
606     mImpl->currentContext->ClearColor( backgroundColor.r,
607                                 backgroundColor.g,
608                                 backgroundColor.b,
609                                 backgroundColor.a );
610   }
611
612   // Clear the entire color, depth and stencil buffers for the default framebuffer, if required.
613   // It is important to clear all 3 buffers when they are being used, for performance on deferred renderers
614   // e.g. previously when the depth & stencil buffers were NOT cleared, it caused the DDK to exceed a "vertex count limit",
615   // and then stall. That problem is only noticeable when rendering a large number of vertices per frame.
616
617   mImpl->currentContext->SetScissorTest( false );
618
619   GLbitfield clearMask = GL_COLOR_BUFFER_BIT;
620
621   mImpl->currentContext->ColorMask( true );
622
623   if( depthBufferAvailable == Integration::DepthBufferAvailable::TRUE )
624   {
625     mImpl->currentContext->DepthMask( true );
626     clearMask |= GL_DEPTH_BUFFER_BIT;
627   }
628
629   if( stencilBufferAvailable == Integration::StencilBufferAvailable::TRUE)
630   {
631     mImpl->currentContext->ClearStencil( 0 );
632     mImpl->currentContext->StencilMask( 0xFF ); // 8 bit stencil mask, all 1's
633     clearMask |= GL_STENCIL_BUFFER_BIT;
634   }
635
636   mImpl->currentContext->Clear( clearMask, Context::FORCE_CLEAR );
637
638   if( !instruction.mIgnoreRenderToFbo && ( instruction.mFrameBuffer != 0 ) )
639   {
640     if ( instruction.mFrameBuffer->IsSurfaceBacked() ) // Surface rendering
641     {
642       if ( instruction.mIsViewportSet )
643       {
644         // For glViewport the lower-left corner is (0,0)
645         // For glViewport the lower-left corner is (0,0)
646         const int32_t y = ( surfaceRect.height - 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 = surfaceRect;
652       }
653     }
654     else // Offscreen buffer rendering
655     {
656       if ( instruction.mIsViewportSet )
657       {
658         // For glViewport the lower-left corner is (0,0)
659         const int32_t y = ( instruction.mFrameBuffer->GetHeight() - instruction.mViewport.height ) - instruction.mViewport.y;
660         viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
661       }
662       else
663       {
664         viewportRect.Set( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
665       }
666     }
667   }
668   else // No Offscreen frame buffer rendering
669   {
670     // Check whether a viewport is specified, otherwise the full surface size is used
671     if ( instruction.mFrameBuffer != 0 )
672     {
673       if ( instruction.mIsViewportSet )
674       {
675         // For glViewport the lower-left corner is (0,0)
676         const int32_t y = ( instruction.mFrameBuffer->GetHeight() - instruction.mViewport.height ) - instruction.mViewport.y;
677         viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
678       }
679       else
680       {
681         viewportRect.Set( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
682       }
683     }
684     else
685     {
686       viewportRect = surfaceRect;
687     }
688   }
689
690   mImpl->currentContext->Viewport(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height);
691
692   if ( instruction.mIsClearColorSet )
693   {
694     mImpl->currentContext->ClearColor( clearColor.r,
695                                        clearColor.g,
696                                        clearColor.b,
697                                        clearColor.a );
698
699     // Clear the viewport area only
700     mImpl->currentContext->SetScissorTest( true );
701     mImpl->currentContext->Scissor( viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height );
702     mImpl->currentContext->ColorMask( true );
703     mImpl->currentContext->Clear( GL_COLOR_BUFFER_BIT , Context::CHECK_CACHED_VALUES );
704     mImpl->currentContext->SetScissorTest( false );
705   }
706
707   mImpl->renderAlgorithms.ProcessRenderInstruction(
708       instruction,
709       *mImpl->currentContext,
710       mImpl->renderBufferIndex,
711       depthBufferAvailable,
712       stencilBufferAvailable );
713
714   if( instruction.mRenderTracker && ( instruction.mFrameBuffer != 0 ) )
715   {
716     // This will create a sync object every frame this render tracker
717     // is alive (though it should be now be created only for
718     // render-once render tasks)
719     instruction.mRenderTracker->CreateSyncObject( mImpl->glSyncAbstraction );
720     instruction.mRenderTracker = NULL; // Only create once.
721   }
722
723   if ( surfaceFrameBuffer )
724   {
725     surfaceFrameBuffer->PostRender();
726   }
727 }
728
729 } // namespace SceneGraph
730
731 } // namespace Internal
732
733 } // namespace Dali