Merge "Added travis.yml for auto-building patches" into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / render / common / render-manager.cpp
1 /*
2  * Copyright (c) 2016 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/gl-resources/frame-buffer-texture.h>
36 #include <dali/internal/render/gl-resources/texture-cache.h>
37 #include <dali/internal/render/queue/render-queue.h>
38 #include <dali/internal/render/renderers/render-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 typedef OwnerContainer< Render::Renderer* >    RendererOwnerContainer;
54 typedef RendererOwnerContainer::Iterator       RendererOwnerIter;
55
56 typedef OwnerContainer< Render::Geometry* >    GeometryOwnerContainer;
57 typedef GeometryOwnerContainer::Iterator       GeometryOwnerIter;
58
59 typedef OwnerContainer< Render::Sampler* >    SamplerOwnerContainer;
60 typedef SamplerOwnerContainer::Iterator       SamplerOwnerIter;
61
62 typedef OwnerContainer< Render::NewTexture* >   TextureOwnerContainer;
63 typedef TextureOwnerContainer::Iterator         TextureOwnerIter;
64
65 typedef OwnerContainer< Render::FrameBuffer* >  FrameBufferOwnerContainer;
66 typedef FrameBufferOwnerContainer::Iterator     FrameBufferOwnerIter;
67
68 typedef OwnerContainer< Render::PropertyBuffer* > PropertyBufferOwnerContainer;
69 typedef PropertyBufferOwnerContainer::Iterator    PropertyBufferOwnerIter;
70
71 typedef OwnerContainer< Render::RenderTracker* > RenderTrackerContainer;
72 typedef RenderTrackerContainer::Iterator         RenderTrackerIter;
73 typedef RenderTrackerContainer::ConstIterator    RenderTrackerConstIter;
74
75 /**
76  * Structure to contain internal data
77  */
78 struct RenderManager::Impl
79 {
80   Impl( Integration::GlAbstraction& glAbstraction,
81         Integration::GlSyncAbstraction& glSyncAbstraction,
82         LockedResourceQueue& textureUploadedQ,
83         TextureUploadedDispatcher& postProcessDispatcher,
84         GeometryBatcher& geometryBatcher )
85   : context( glAbstraction ),
86     glSyncAbstraction( glSyncAbstraction ),
87     renderQueue(),
88     textureCache( renderQueue, postProcessDispatcher, context ),
89     textureUploadedQueue( textureUploadedQ ),
90     instructions(),
91     backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
92     frameCount( 0 ),
93     renderBufferIndex( SceneGraphBuffers::INITIAL_UPDATE_BUFFER_INDEX ),
94     defaultSurfaceRect(),
95     rendererContainer(),
96     samplerContainer(),
97     textureContainer(),
98     frameBufferContainer(),
99     renderersAdded( false ),
100     firstRenderCompleted( false ),
101     defaultShader( NULL ),
102     programController( glAbstraction ),
103     geometryBatcher( geometryBatcher )
104   {
105   }
106
107   ~Impl()
108   {
109   }
110
111   void AddRenderTracker( Render::RenderTracker* renderTracker )
112   {
113     DALI_ASSERT_DEBUG( renderTracker != NULL );
114     mRenderTrackers.PushBack( renderTracker );
115   }
116
117   void RemoveRenderTracker( Render::RenderTracker* renderTracker )
118   {
119     DALI_ASSERT_DEBUG( renderTracker != NULL );
120     for(RenderTrackerIter iter = mRenderTrackers.Begin(), end = mRenderTrackers.End(); iter != end; ++iter)
121     {
122       if( *iter == renderTracker )
123       {
124         mRenderTrackers.Erase( iter );
125         break;
126       }
127     }
128   }
129
130   void UpdateTrackers()
131   {
132     for(RenderTrackerIter iter = mRenderTrackers.Begin(), end = mRenderTrackers.End(); iter != end; ++iter)
133     {
134       (*iter)->PollSyncObject();
135     }
136   }
137
138   // the order is important for destruction,
139   // programs are owned by context at the moment.
140   Context                       context;                  ///< holds the GL state
141   Integration::GlSyncAbstraction& glSyncAbstraction;      ///< GL sync abstraction
142   RenderQueue                   renderQueue;              ///< A message queue for receiving messages from the update-thread.
143   TextureCache                  textureCache;             ///< Cache for all GL textures
144   LockedResourceQueue&          textureUploadedQueue;     ///< A queue for requesting resource post processing in update thread
145
146   // Render instructions describe what should be rendered during RenderManager::Render()
147   // Owned by RenderManager. Update manager updates instructions for the next frame while we render the current one
148   RenderInstructionContainer    instructions;
149
150   Vector4                       backgroundColor;          ///< The glClear color used at the beginning of each frame.
151
152   unsigned int                  frameCount;               ///< The current frame count
153   BufferIndex                   renderBufferIndex;        ///< The index of the buffer to read from; this is opposite of the "update" buffer
154
155   Rect<int>                     defaultSurfaceRect;       ///< Rectangle for the default surface we are rendering to
156
157   RendererOwnerContainer        rendererContainer;        ///< List of owned renderers
158   SamplerOwnerContainer         samplerContainer;         ///< List of owned samplers
159   TextureOwnerContainer         textureContainer;         ///< List of owned textures
160   FrameBufferOwnerContainer     frameBufferContainer;     ///< List of owned framebuffers
161   PropertyBufferOwnerContainer  propertyBufferContainer;  ///< List of owned property buffers
162   GeometryOwnerContainer        geometryContainer;        ///< List of owned Geometries
163
164   bool                          renderersAdded;
165
166   RenderTrackerContainer        mRenderTrackers;          ///< List of render trackers
167
168   bool                          firstRenderCompleted;     ///< False until the first render is done
169   Shader*                       defaultShader;            ///< Default shader to use
170   ProgramController             programController;        ///< Owner of the GL programs
171
172   SceneGraph::GeometryBatcher&  geometryBatcher;          ///< Instance of geometry batcher
173 };
174
175 RenderManager* RenderManager::New( Integration::GlAbstraction& glAbstraction,
176                                    Integration::GlSyncAbstraction& glSyncAbstraction,
177                                    SceneGraph::GeometryBatcher& geometryBatcher,
178                                    LockedResourceQueue& textureUploadedQ )
179 {
180   RenderManager* manager = new RenderManager;
181   manager->mImpl = new Impl( glAbstraction, glSyncAbstraction, textureUploadedQ, *manager, geometryBatcher );
182   return manager;
183 }
184
185 RenderManager::RenderManager()
186 : mImpl(NULL)
187 {
188 }
189
190 RenderManager::~RenderManager()
191 {
192   delete mImpl;
193 }
194
195 RenderQueue& RenderManager::GetRenderQueue()
196 {
197   return mImpl->renderQueue;
198 }
199
200 TextureCache& RenderManager::GetTextureCache()
201 {
202   return mImpl->textureCache;
203 }
204
205 void RenderManager::ContextCreated()
206 {
207   mImpl->context.GlContextCreated();
208   mImpl->programController.GlContextCreated();
209
210   // renderers, textures and gpu buffers cannot reinitialize themselves
211   // so they rely on someone reloading the data for them
212 }
213
214 void RenderManager::ContextDestroyed()
215 {
216   mImpl->context.GlContextDestroyed();
217   mImpl->programController.GlContextDestroyed();
218
219   // inform texture cache
220   mImpl->textureCache.GlContextDestroyed(); // Clears gl texture ids
221
222   //Inform textures
223   for( TextureOwnerIter iter = mImpl->textureContainer.Begin(); iter != mImpl->textureContainer.End(); ++iter )
224   {
225     (*iter)->GlContextDestroyed();
226   }
227
228   //Inform framebuffers
229   for( FrameBufferOwnerIter iter = mImpl->frameBufferContainer.Begin(); iter != mImpl->frameBufferContainer.End(); ++iter )
230   {
231     (*iter)->GlContextDestroyed();
232   }
233
234   // inform renderers
235   RendererOwnerContainer::Iterator end = mImpl->rendererContainer.End();
236   RendererOwnerContainer::Iterator iter = mImpl->rendererContainer.Begin();
237   for( ; iter != end; ++iter )
238   {
239     GlResourceOwner* renderer = *iter;
240     renderer->GlContextDestroyed(); // Clear up vertex buffers
241   }
242 }
243
244 void RenderManager::DispatchTextureUploaded(ResourceId request)
245 {
246   mImpl->textureUploadedQueue.PushBack( request );
247 }
248
249 void RenderManager::SetShaderSaver( ShaderSaver& upstream )
250 {
251   mImpl->programController.SetShaderSaver( upstream );
252 }
253
254 RenderInstructionContainer& RenderManager::GetRenderInstructionContainer()
255 {
256   return mImpl->instructions;
257 }
258
259 void RenderManager::SetBackgroundColor( const Vector4& color )
260 {
261   mImpl->backgroundColor = color;
262 }
263
264 void RenderManager::SetDefaultSurfaceRect(const Rect<int>& rect)
265 {
266   mImpl->defaultSurfaceRect = rect;
267 }
268
269 void RenderManager::AddRenderer( Render::Renderer* renderer )
270 {
271   // Initialize the renderer as we are now in render thread
272   renderer->Initialize( mImpl->context, mImpl->textureCache );
273
274   mImpl->rendererContainer.PushBack( renderer );
275
276   if( !mImpl->renderersAdded )
277   {
278     mImpl->renderersAdded = true;
279   }
280 }
281
282 void RenderManager::RemoveRenderer( Render::Renderer* renderer )
283 {
284   DALI_ASSERT_DEBUG( NULL != renderer );
285
286   RendererOwnerContainer& renderers = mImpl->rendererContainer;
287
288   // Find the renderer
289   for ( RendererOwnerIter iter = renderers.Begin(); iter != renderers.End(); ++iter )
290   {
291     if ( *iter == renderer )
292     {
293       renderers.Erase( iter ); // Renderer found; now destroy it
294       break;
295     }
296   }
297 }
298
299 void RenderManager::AddSampler( Render::Sampler* sampler )
300 {
301   mImpl->samplerContainer.PushBack( sampler );
302 }
303
304 void RenderManager::RemoveSampler( Render::Sampler* sampler )
305 {
306   DALI_ASSERT_DEBUG( NULL != sampler );
307
308   SamplerOwnerContainer& samplers = mImpl->samplerContainer;
309
310   // Find the sampler
311   for ( SamplerOwnerIter iter = samplers.Begin(); iter != samplers.End(); ++iter )
312   {
313     if ( *iter == sampler )
314     {
315       samplers.Erase( iter ); // Sampler found; now destroy it
316       break;
317     }
318   }
319 }
320
321 void RenderManager::AddTexture( Render::NewTexture* texture )
322 {
323   mImpl->textureContainer.PushBack( texture );
324   texture->Initialize(mImpl->context);
325 }
326
327 void RenderManager::RemoveTexture( Render::NewTexture* texture )
328 {
329   DALI_ASSERT_DEBUG( NULL != texture );
330
331   TextureOwnerContainer& textures = mImpl->textureContainer;
332
333   // Find the texture
334   for ( TextureOwnerIter iter = textures.Begin(); iter != textures.End(); ++iter )
335   {
336     if ( *iter == texture )
337     {
338       texture->Destroy( mImpl->context );
339       textures.Erase( iter ); // Texture found; now destroy it
340       break;
341     }
342   }
343 }
344
345 void RenderManager::UploadTexture( Render::NewTexture* texture, PixelDataPtr pixelData, const NewTexture::UploadParams& params )
346 {
347   texture->Upload( mImpl->context, pixelData, params );
348 }
349
350 void RenderManager::GenerateMipmaps( Render::NewTexture* texture )
351 {
352   texture->GenerateMipmaps( mImpl->context );
353 }
354
355 void RenderManager::SetFilterMode( Render::Sampler* sampler, unsigned int minFilterMode, unsigned int magFilterMode )
356 {
357   sampler->mMinificationFilter = static_cast<Dali::FilterMode::Type>(minFilterMode);
358   sampler->mMagnificationFilter = static_cast<Dali::FilterMode::Type>(magFilterMode );
359 }
360
361 void RenderManager::SetWrapMode( Render::Sampler* sampler, unsigned int rWrapMode, unsigned int sWrapMode, unsigned int tWrapMode )
362 {
363   sampler->mRWrapMode = static_cast<Dali::WrapMode::Type>(rWrapMode);
364   sampler->mSWrapMode = static_cast<Dali::WrapMode::Type>(sWrapMode);
365   sampler->mTWrapMode = static_cast<Dali::WrapMode::Type>(tWrapMode);
366 }
367
368 void RenderManager::AddFrameBuffer( Render::FrameBuffer* frameBuffer )
369 {
370   mImpl->frameBufferContainer.PushBack( frameBuffer );
371   frameBuffer->Initialize(mImpl->context);
372 }
373
374 void RenderManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer )
375 {
376   DALI_ASSERT_DEBUG( NULL != frameBuffer );
377
378   FrameBufferOwnerContainer& framebuffers = mImpl->frameBufferContainer;
379
380   // Find the sampler
381   for ( FrameBufferOwnerIter iter = framebuffers.Begin(); iter != framebuffers.End(); ++iter )
382   {
383     if ( *iter == frameBuffer )
384     {
385       frameBuffer->Destroy( mImpl->context );
386       framebuffers.Erase( iter ); // frameBuffer found; now destroy it
387       break;
388     }
389   }
390 }
391
392 void RenderManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::NewTexture* texture, unsigned int mipmapLevel, unsigned int layer )
393 {
394   frameBuffer->AttachColorTexture( mImpl->context, texture, mipmapLevel, layer );
395 }
396
397 void RenderManager::AddPropertyBuffer( Render::PropertyBuffer* propertyBuffer )
398 {
399   mImpl->propertyBufferContainer.PushBack( propertyBuffer );
400 }
401
402 void RenderManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
403 {
404   DALI_ASSERT_DEBUG( NULL != propertyBuffer );
405
406   PropertyBufferOwnerContainer& propertyBuffers = mImpl->propertyBufferContainer;
407
408   // Find the sampler
409   for ( PropertyBufferOwnerIter iter = propertyBuffers.Begin(); iter != propertyBuffers.End(); ++iter )
410   {
411     if ( *iter == propertyBuffer )
412     {
413       propertyBuffers.Erase( iter ); // Property buffer found; now destroy it
414       break;
415     }
416   }
417 }
418
419 void RenderManager::SetPropertyBufferFormat(Render::PropertyBuffer* propertyBuffer, Render::PropertyBuffer::Format* format )
420 {
421   propertyBuffer->SetFormat( format );
422 }
423
424 void RenderManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, Dali::Vector<char>* data, size_t size )
425 {
426   propertyBuffer->SetData( data, size );
427 }
428
429 void RenderManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<unsigned short>& indices )
430 {
431   geometry->SetIndexBuffer( indices );
432 }
433
434 void RenderManager::AddGeometry( Render::Geometry* geometry )
435 {
436   mImpl->geometryContainer.PushBack( geometry );
437 }
438
439 void RenderManager::RemoveGeometry( Render::Geometry* geometry )
440 {
441   DALI_ASSERT_DEBUG( NULL != geometry );
442
443   GeometryOwnerContainer& geometries = mImpl->geometryContainer;
444
445   // Find the geometry
446   for ( GeometryOwnerIter iter = geometries.Begin(); iter != geometries.End(); ++iter )
447   {
448     if ( *iter == geometry )
449     {
450       geometries.Erase( iter ); // Geometry found; now destroy it
451       break;
452     }
453   }
454 }
455
456 void RenderManager::AddVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
457 {
458   DALI_ASSERT_DEBUG( NULL != geometry );
459
460   GeometryOwnerContainer& geometries = mImpl->geometryContainer;
461
462   // Find the renderer
463   for ( GeometryOwnerIter iter = geometries.Begin(); iter != geometries.End(); ++iter )
464   {
465     if ( *iter == geometry )
466     {
467       (*iter)->AddPropertyBuffer( propertyBuffer );
468       break;
469     }
470   }
471 }
472
473 void RenderManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
474 {
475   DALI_ASSERT_DEBUG( NULL != geometry );
476
477   GeometryOwnerContainer& geometries = mImpl->geometryContainer;
478
479   // Find the renderer
480   for ( GeometryOwnerIter iter = geometries.Begin(); iter != geometries.End(); ++iter )
481   {
482     if ( *iter == geometry )
483     {
484       (*iter)->RemovePropertyBuffer( propertyBuffer );
485       break;
486     }
487   }
488 }
489
490 void RenderManager::SetGeometryType( Render::Geometry* geometry, unsigned int geometryType )
491 {
492   geometry->SetType( Render::Geometry::Type(geometryType) );
493 }
494
495 void RenderManager::AddRenderTracker( Render::RenderTracker* renderTracker )
496 {
497   mImpl->AddRenderTracker(renderTracker);
498 }
499
500 void RenderManager::RemoveRenderTracker( Render::RenderTracker* renderTracker )
501 {
502   mImpl->RemoveRenderTracker(renderTracker);
503 }
504
505 void RenderManager::SetDefaultShader( Shader* shader )
506 {
507   mImpl->defaultShader = shader;
508 }
509
510 ProgramCache* RenderManager::GetProgramCache()
511 {
512   return &(mImpl->programController);
513 }
514
515 bool RenderManager::Render( Integration::RenderStatus& status )
516 {
517   DALI_PRINT_RENDER_START( mImpl->renderBufferIndex );
518
519   // Core::Render documents that GL context must be current before calling Render
520   DALI_ASSERT_DEBUG( mImpl->context.IsGlContextCreated() );
521
522   // Increment the frame count at the beginning of each frame
523   ++(mImpl->frameCount);
524
525   // Process messages queued during previous update
526   mImpl->renderQueue.ProcessMessages( mImpl->renderBufferIndex );
527
528   // No need to make any gl calls if we've done 1st glClear & don't have any renderers to render during startup.
529   if( !mImpl->firstRenderCompleted || mImpl->renderersAdded )
530   {
531     // switch rendering to adaptor provided (default) buffer
532     mImpl->context.BindFramebuffer( GL_FRAMEBUFFER, 0 );
533
534     mImpl->context.Viewport( mImpl->defaultSurfaceRect.x,
535                              mImpl->defaultSurfaceRect.y,
536                              mImpl->defaultSurfaceRect.width,
537                              mImpl->defaultSurfaceRect.height );
538
539     mImpl->context.ClearColor( mImpl->backgroundColor.r,
540                                mImpl->backgroundColor.g,
541                                mImpl->backgroundColor.b,
542                                mImpl->backgroundColor.a );
543
544     mImpl->context.ClearStencil( 0 );
545
546     // Clear the entire color, depth and stencil buffers for the default framebuffer.
547     // It is important to clear all 3 buffers, for performance on deferred renderers like Mali
548     // e.g. previously when the depth & stencil buffers were NOT cleared, it caused the DDK to exceed a "vertex count limit",
549     // and then stall. That problem is only noticeable when rendering a large number of vertices per frame.
550     mImpl->context.SetScissorTest( false );
551     mImpl->context.ColorMask( true );
552     mImpl->context.DepthMask( true );
553     mImpl->context.StencilMask( 0xFF ); // 8 bit stencil mask, all 1's
554     mImpl->context.Clear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,  Context::FORCE_CLEAR );
555
556     // reset the program matrices for all programs once per frame
557     // this ensures we will set view and projection matrix once per program per camera
558     mImpl->programController.ResetProgramMatrices();
559
560     // if we don't have default shader, no point doing the render calls
561     if( mImpl->defaultShader )
562     {
563       size_t count = mImpl->instructions.Count( mImpl->renderBufferIndex );
564       for ( size_t i = 0; i < count; ++i )
565       {
566         RenderInstruction& instruction = mImpl->instructions.At( mImpl->renderBufferIndex, i );
567
568         DoRender( instruction, *mImpl->defaultShader );
569       }
570       GLenum attachments[] = { GL_DEPTH, GL_STENCIL };
571       mImpl->context.InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
572
573       mImpl->UpdateTrackers();
574
575       mImpl->firstRenderCompleted = true;
576     }
577   }
578
579   //Notify RenderGeometries that rendering has finished
580   for ( GeometryOwnerIter iter = mImpl->geometryContainer.Begin(); iter != mImpl->geometryContainer.End(); ++iter )
581   {
582     (*iter)->OnRenderFinished();
583   }
584
585   /**
586    * The rendering has finished; swap to the next buffer.
587    * Ideally the update has just finished using this buffer; otherwise the render thread
588    * should block until the update has finished.
589    */
590   mImpl->renderBufferIndex = (0 != mImpl->renderBufferIndex) ? 0 : 1;
591
592   DALI_PRINT_RENDER_END();
593
594   // check if anything has been posted to the update thread, if IsEmpty then no update required.
595   return !mImpl->textureUploadedQueue.IsEmpty();
596 }
597
598 void RenderManager::DoRender( RenderInstruction& instruction, Shader& defaultShader )
599 {
600   Rect<int> viewportRect;
601   Vector4   clearColor;
602
603   if ( instruction.mIsClearColorSet )
604   {
605     clearColor = instruction.mClearColor;
606   }
607   else
608   {
609     clearColor = Dali::RenderTask::DEFAULT_CLEAR_COLOR;
610   }
611
612   FrameBufferTexture* offscreen = NULL;
613
614   if( instruction.mFrameBuffer != 0 )
615   {
616     instruction.mFrameBuffer->Bind( mImpl->context );
617     if ( instruction.mIsViewportSet )
618     {
619       // For glViewport the lower-left corner is (0,0)
620       const int y = ( instruction.mFrameBuffer->GetHeight() - instruction.mViewport.height ) - instruction.mViewport.y;
621       viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
622     }
623     else
624     {
625       viewportRect.Set( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
626     }
627   }
628   else // !(instruction.mOffscreenTexture)
629   {
630     // switch rendering to adaptor provided (default) buffer
631     mImpl->context.BindFramebuffer( GL_FRAMEBUFFER, 0 );
632
633     // Check whether a viewport is specified, otherwise the full surface size is used
634     if ( instruction.mIsViewportSet )
635     {
636       // For glViewport the lower-left corner is (0,0)
637       const int y = ( mImpl->defaultSurfaceRect.height - instruction.mViewport.height ) - instruction.mViewport.y;
638       viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
639     }
640     else
641     {
642       viewportRect = mImpl->defaultSurfaceRect;
643     }
644   }
645
646   mImpl->context.Viewport(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height);
647
648   if ( instruction.mIsClearColorSet )
649   {
650     mImpl->context.ClearColor( clearColor.r,
651                                clearColor.g,
652                                clearColor.b,
653                                clearColor.a );
654
655     // Clear the viewport area only
656     mImpl->context.SetScissorTest( true );
657     mImpl->context.Scissor( viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height );
658     mImpl->context.ColorMask( true );
659     mImpl->context.Clear( GL_COLOR_BUFFER_BIT , Context::CHECK_CACHED_VALUES );
660     mImpl->context.SetScissorTest( false );
661   }
662
663   Render::ProcessRenderInstruction( instruction,
664                                     mImpl->context,
665                                     mImpl->textureCache,
666                                     defaultShader,
667                                     mImpl->geometryBatcher,
668                                     mImpl->renderBufferIndex );
669
670   if( instruction.mRenderTracker && ( offscreen != NULL || instruction.mFrameBuffer != NULL ) )
671   {
672     // This will create a sync object every frame this render tracker
673     // is alive (though it should be now be created only for
674     // render-once render tasks)
675     instruction.mRenderTracker->CreateSyncObject( mImpl->glSyncAbstraction );
676     instruction.mRenderTracker = NULL; // Only create once.
677   }
678 }
679
680 } // namespace SceneGraph
681
682 } // namespace Internal
683
684 } // namespace Dali