Merge "Add descriptions and example codes" 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   for ( TextureOwnerIter iter = mImpl->textureContainer.Begin(); iter != mImpl->textureContainer.End(); ++iter )
193   {
194     (*iter)->Destroy( mImpl->context );
195   }
196
197   for ( FrameBufferOwnerIter iter = mImpl->frameBufferContainer.Begin(); iter != mImpl->frameBufferContainer.End(); ++iter )
198   {
199     (*iter)->Destroy( mImpl->context );
200   }
201
202   delete mImpl;
203 }
204
205 RenderQueue& RenderManager::GetRenderQueue()
206 {
207   return mImpl->renderQueue;
208 }
209
210 TextureCache& RenderManager::GetTextureCache()
211 {
212   return mImpl->textureCache;
213 }
214
215 void RenderManager::ContextCreated()
216 {
217   mImpl->context.GlContextCreated();
218   mImpl->programController.GlContextCreated();
219
220   // renderers, textures and gpu buffers cannot reinitialize themselves
221   // so they rely on someone reloading the data for them
222 }
223
224 void RenderManager::ContextDestroyed()
225 {
226   mImpl->context.GlContextDestroyed();
227   mImpl->programController.GlContextDestroyed();
228
229   // inform texture cache
230   mImpl->textureCache.GlContextDestroyed(); // Clears gl texture ids
231
232   // inform renderers
233   RendererOwnerContainer::Iterator end = mImpl->rendererContainer.End();
234   RendererOwnerContainer::Iterator iter = mImpl->rendererContainer.Begin();
235   for( ; iter != end; ++iter )
236   {
237     GlResourceOwner* renderer = *iter;
238     renderer->GlContextDestroyed(); // Clear up vertex buffers
239   }
240 }
241
242 void RenderManager::DispatchTextureUploaded(ResourceId request)
243 {
244   mImpl->textureUploadedQueue.PushBack( request );
245 }
246
247 void RenderManager::SetShaderSaver( ShaderSaver& upstream )
248 {
249   mImpl->programController.SetShaderSaver( upstream );
250 }
251
252 RenderInstructionContainer& RenderManager::GetRenderInstructionContainer()
253 {
254   return mImpl->instructions;
255 }
256
257 void RenderManager::SetBackgroundColor( const Vector4& color )
258 {
259   mImpl->backgroundColor = color;
260 }
261
262 void RenderManager::SetDefaultSurfaceRect(const Rect<int>& rect)
263 {
264   mImpl->defaultSurfaceRect = rect;
265 }
266
267 void RenderManager::AddRenderer( Render::Renderer* renderer )
268 {
269   // Initialize the renderer as we are now in render thread
270   renderer->Initialize( mImpl->context, mImpl->textureCache );
271
272   mImpl->rendererContainer.PushBack( renderer );
273
274   if( !mImpl->renderersAdded )
275   {
276     mImpl->renderersAdded = true;
277   }
278 }
279
280 void RenderManager::RemoveRenderer( Render::Renderer* renderer )
281 {
282   DALI_ASSERT_DEBUG( NULL != renderer );
283
284   RendererOwnerContainer& renderers = mImpl->rendererContainer;
285
286   // Find the renderer
287   for ( RendererOwnerIter iter = renderers.Begin(); iter != renderers.End(); ++iter )
288   {
289     if ( *iter == renderer )
290     {
291       renderers.Erase( iter ); // Renderer found; now destroy it
292       break;
293     }
294   }
295 }
296
297 void RenderManager::AddSampler( Render::Sampler* sampler )
298 {
299   mImpl->samplerContainer.PushBack( sampler );
300 }
301
302 void RenderManager::RemoveSampler( Render::Sampler* sampler )
303 {
304   DALI_ASSERT_DEBUG( NULL != sampler );
305
306   SamplerOwnerContainer& samplers = mImpl->samplerContainer;
307
308   // Find the sampler
309   for ( SamplerOwnerIter iter = samplers.Begin(); iter != samplers.End(); ++iter )
310   {
311     if ( *iter == sampler )
312     {
313       samplers.Erase( iter ); // Sampler found; now destroy it
314       break;
315     }
316   }
317 }
318
319 void RenderManager::AddTexture( Render::NewTexture* texture )
320 {
321   mImpl->textureContainer.PushBack( texture );
322   texture->Initialize(mImpl->context);
323 }
324
325 void RenderManager::RemoveTexture( Render::NewTexture* texture )
326 {
327   DALI_ASSERT_DEBUG( NULL != texture );
328
329   TextureOwnerContainer& textures = mImpl->textureContainer;
330
331   // Find the texture
332   for ( TextureOwnerIter iter = textures.Begin(); iter != textures.End(); ++iter )
333   {
334     if ( *iter == texture )
335     {
336       texture->Destroy( mImpl->context );
337       textures.Erase( iter ); // Texture found; now destroy it
338       break;
339     }
340   }
341 }
342
343 void RenderManager::UploadTexture( Render::NewTexture* texture, PixelDataPtr pixelData, const NewTexture::UploadParams& params )
344 {
345   texture->Upload( mImpl->context, pixelData, params );
346 }
347
348 void RenderManager::GenerateMipmaps( Render::NewTexture* texture )
349 {
350   texture->GenerateMipmaps( mImpl->context );
351 }
352
353 void RenderManager::SetFilterMode( Render::Sampler* sampler, unsigned int minFilterMode, unsigned int magFilterMode )
354 {
355   sampler->mMinificationFilter = static_cast<Dali::FilterMode::Type>(minFilterMode);
356   sampler->mMagnificationFilter = static_cast<Dali::FilterMode::Type>(magFilterMode );
357 }
358
359 void RenderManager::SetWrapMode( Render::Sampler* sampler, unsigned int rWrapMode, unsigned int sWrapMode, unsigned int tWrapMode )
360 {
361   sampler->mRWrapMode = static_cast<Dali::WrapMode::Type>(rWrapMode);
362   sampler->mSWrapMode = static_cast<Dali::WrapMode::Type>(sWrapMode);
363   sampler->mTWrapMode = static_cast<Dali::WrapMode::Type>(tWrapMode);
364 }
365
366 void RenderManager::AddFrameBuffer( Render::FrameBuffer* frameBuffer )
367 {
368   mImpl->frameBufferContainer.PushBack( frameBuffer );
369   frameBuffer->Initialize(mImpl->context);
370 }
371
372 void RenderManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer )
373 {
374   DALI_ASSERT_DEBUG( NULL != frameBuffer );
375
376   FrameBufferOwnerContainer& framebuffers = mImpl->frameBufferContainer;
377
378   // Find the sampler
379   for ( FrameBufferOwnerIter iter = framebuffers.Begin(); iter != framebuffers.End(); ++iter )
380   {
381     if ( *iter == frameBuffer )
382     {
383       frameBuffer->Destroy( mImpl->context );
384       framebuffers.Erase( iter ); // frameBuffer found; now destroy it
385       break;
386     }
387   }
388 }
389
390 void RenderManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::NewTexture* texture, unsigned int mipmapLevel, unsigned int layer )
391 {
392   frameBuffer->AttachColorTexture( mImpl->context, texture, mipmapLevel, layer );
393 }
394
395 void RenderManager::AddPropertyBuffer( Render::PropertyBuffer* propertyBuffer )
396 {
397   mImpl->propertyBufferContainer.PushBack( propertyBuffer );
398 }
399
400 void RenderManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
401 {
402   DALI_ASSERT_DEBUG( NULL != propertyBuffer );
403
404   PropertyBufferOwnerContainer& propertyBuffers = mImpl->propertyBufferContainer;
405
406   // Find the sampler
407   for ( PropertyBufferOwnerIter iter = propertyBuffers.Begin(); iter != propertyBuffers.End(); ++iter )
408   {
409     if ( *iter == propertyBuffer )
410     {
411       propertyBuffers.Erase( iter ); // Property buffer found; now destroy it
412       break;
413     }
414   }
415 }
416
417 void RenderManager::SetPropertyBufferFormat(Render::PropertyBuffer* propertyBuffer, Render::PropertyBuffer::Format* format )
418 {
419   propertyBuffer->SetFormat( format );
420 }
421
422 void RenderManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, Dali::Vector<char>* data, size_t size )
423 {
424   propertyBuffer->SetData( data, size );
425 }
426
427 void RenderManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<unsigned short>& indices )
428 {
429   geometry->SetIndexBuffer( indices );
430 }
431
432 void RenderManager::AddGeometry( Render::Geometry* geometry )
433 {
434   mImpl->geometryContainer.PushBack( geometry );
435 }
436
437 void RenderManager::RemoveGeometry( Render::Geometry* geometry )
438 {
439   DALI_ASSERT_DEBUG( NULL != geometry );
440
441   GeometryOwnerContainer& geometries = mImpl->geometryContainer;
442
443   // Find the geometry
444   for ( GeometryOwnerIter iter = geometries.Begin(); iter != geometries.End(); ++iter )
445   {
446     if ( *iter == geometry )
447     {
448       geometries.Erase( iter ); // Geometry found; now destroy it
449       break;
450     }
451   }
452 }
453
454 void RenderManager::AddVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
455 {
456   DALI_ASSERT_DEBUG( NULL != geometry );
457
458   GeometryOwnerContainer& geometries = mImpl->geometryContainer;
459
460   // Find the renderer
461   for ( GeometryOwnerIter iter = geometries.Begin(); iter != geometries.End(); ++iter )
462   {
463     if ( *iter == geometry )
464     {
465       (*iter)->AddPropertyBuffer( propertyBuffer );
466       break;
467     }
468   }
469 }
470
471 void RenderManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
472 {
473   DALI_ASSERT_DEBUG( NULL != geometry );
474
475   GeometryOwnerContainer& geometries = mImpl->geometryContainer;
476
477   // Find the renderer
478   for ( GeometryOwnerIter iter = geometries.Begin(); iter != geometries.End(); ++iter )
479   {
480     if ( *iter == geometry )
481     {
482       (*iter)->RemovePropertyBuffer( propertyBuffer );
483       break;
484     }
485   }
486 }
487
488 void RenderManager::SetGeometryType( Render::Geometry* geometry, unsigned int geometryType )
489 {
490   geometry->SetType( Render::Geometry::Type(geometryType) );
491 }
492
493 void RenderManager::AddRenderTracker( Render::RenderTracker* renderTracker )
494 {
495   mImpl->AddRenderTracker(renderTracker);
496 }
497
498 void RenderManager::RemoveRenderTracker( Render::RenderTracker* renderTracker )
499 {
500   mImpl->RemoveRenderTracker(renderTracker);
501 }
502
503 void RenderManager::SetDefaultShader( Shader* shader )
504 {
505   mImpl->defaultShader = shader;
506 }
507
508 ProgramCache* RenderManager::GetProgramCache()
509 {
510   return &(mImpl->programController);
511 }
512
513 bool RenderManager::Render( Integration::RenderStatus& status )
514 {
515   DALI_PRINT_RENDER_START( mImpl->renderBufferIndex );
516
517   // Core::Render documents that GL context must be current before calling Render
518   DALI_ASSERT_DEBUG( mImpl->context.IsGlContextCreated() );
519
520   // Increment the frame count at the beginning of each frame
521   ++(mImpl->frameCount);
522
523   // Process messages queued during previous update
524   mImpl->renderQueue.ProcessMessages( mImpl->renderBufferIndex );
525
526   // No need to make any gl calls if we've done 1st glClear & don't have any renderers to render during startup.
527   if( !mImpl->firstRenderCompleted || mImpl->renderersAdded )
528   {
529     // switch rendering to adaptor provided (default) buffer
530     mImpl->context.BindFramebuffer( GL_FRAMEBUFFER, 0 );
531
532     mImpl->context.Viewport( mImpl->defaultSurfaceRect.x,
533                              mImpl->defaultSurfaceRect.y,
534                              mImpl->defaultSurfaceRect.width,
535                              mImpl->defaultSurfaceRect.height );
536
537     mImpl->context.ClearColor( mImpl->backgroundColor.r,
538                                mImpl->backgroundColor.g,
539                                mImpl->backgroundColor.b,
540                                mImpl->backgroundColor.a );
541
542     mImpl->context.ClearStencil( 0 );
543
544     // Clear the entire color, depth and stencil buffers for the default framebuffer.
545     // It is important to clear all 3 buffers, for performance on deferred renderers like Mali
546     // e.g. previously when the depth & stencil buffers were NOT cleared, it caused the DDK to exceed a "vertex count limit",
547     // and then stall. That problem is only noticeable when rendering a large number of vertices per frame.
548     mImpl->context.SetScissorTest( false );
549     mImpl->context.ColorMask( true );
550     mImpl->context.DepthMask( true );
551     mImpl->context.StencilMask( 0xFF ); // 8 bit stencil mask, all 1's
552     mImpl->context.Clear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,  Context::FORCE_CLEAR );
553
554     // reset the program matrices for all programs once per frame
555     // this ensures we will set view and projection matrix once per program per camera
556     mImpl->programController.ResetProgramMatrices();
557
558     // if we don't have default shader, no point doing the render calls
559     if( mImpl->defaultShader )
560     {
561       size_t count = mImpl->instructions.Count( mImpl->renderBufferIndex );
562       for ( size_t i = 0; i < count; ++i )
563       {
564         RenderInstruction& instruction = mImpl->instructions.At( mImpl->renderBufferIndex, i );
565
566         DoRender( instruction, *mImpl->defaultShader );
567       }
568       GLenum attachments[] = { GL_DEPTH, GL_STENCIL };
569       mImpl->context.InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
570
571       mImpl->UpdateTrackers();
572
573       mImpl->firstRenderCompleted = true;
574     }
575   }
576
577   //Notify RenderGeometries that rendering has finished
578   for ( GeometryOwnerIter iter = mImpl->geometryContainer.Begin(); iter != mImpl->geometryContainer.End(); ++iter )
579   {
580     (*iter)->OnRenderFinished();
581   }
582
583   /**
584    * The rendering has finished; swap to the next buffer.
585    * Ideally the update has just finished using this buffer; otherwise the render thread
586    * should block until the update has finished.
587    */
588   mImpl->renderBufferIndex = (0 != mImpl->renderBufferIndex) ? 0 : 1;
589
590   DALI_PRINT_RENDER_END();
591
592   // check if anything has been posted to the update thread, if IsEmpty then no update required.
593   return !mImpl->textureUploadedQueue.IsEmpty();
594 }
595
596 void RenderManager::DoRender( RenderInstruction& instruction, Shader& defaultShader )
597 {
598   Rect<int> viewportRect;
599   Vector4   clearColor;
600
601   if ( instruction.mIsClearColorSet )
602   {
603     clearColor = instruction.mClearColor;
604   }
605   else
606   {
607     clearColor = Dali::RenderTask::DEFAULT_CLEAR_COLOR;
608   }
609
610   FrameBufferTexture* offscreen = NULL;
611
612   if ( instruction.mOffscreenTextureId != 0 )
613   {
614     offscreen = mImpl->textureCache.GetFramebuffer( instruction.mOffscreenTextureId );
615     DALI_ASSERT_DEBUG( NULL != offscreen );
616
617     if( NULL != offscreen &&
618         offscreen->Prepare() )
619     {
620       // Check whether a viewport is specified, otherwise the full surface size is used
621       if ( instruction.mIsViewportSet )
622       {
623         // For glViewport the lower-left corner is (0,0)
624         const int y = ( offscreen->GetHeight() - instruction.mViewport.height ) - instruction.mViewport.y;
625         viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
626       }
627       else
628       {
629         viewportRect.Set( 0, 0, offscreen->GetWidth(), offscreen->GetHeight() );
630       }
631     }
632     else
633     {
634       // Offscreen is NULL or could not be prepared.
635       return;
636     }
637   }
638   else if( instruction.mFrameBuffer != 0 )
639   {
640     instruction.mFrameBuffer->Bind( mImpl->context );
641     if ( instruction.mIsViewportSet )
642     {
643       // For glViewport the lower-left corner is (0,0)
644       const int y = ( instruction.mFrameBuffer->GetHeight() - instruction.mViewport.height ) - instruction.mViewport.y;
645       viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
646     }
647     else
648     {
649       viewportRect.Set( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
650     }
651   }
652   else // !(instruction.mOffscreenTexture)
653   {
654     // switch rendering to adaptor provided (default) buffer
655     mImpl->context.BindFramebuffer( GL_FRAMEBUFFER, 0 );
656
657     // Check whether a viewport is specified, otherwise the full surface size is used
658     if ( instruction.mIsViewportSet )
659     {
660       // For glViewport the lower-left corner is (0,0)
661       const int y = ( mImpl->defaultSurfaceRect.height - instruction.mViewport.height ) - instruction.mViewport.y;
662       viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
663     }
664     else
665     {
666       viewportRect = mImpl->defaultSurfaceRect;
667     }
668   }
669
670   mImpl->context.Viewport(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height);
671
672   if ( instruction.mIsClearColorSet )
673   {
674     mImpl->context.ClearColor( clearColor.r,
675                                clearColor.g,
676                                clearColor.b,
677                                clearColor.a );
678
679     // Clear the viewport area only
680     mImpl->context.SetScissorTest( true );
681     mImpl->context.Scissor( viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height );
682     mImpl->context.ColorMask( true );
683     mImpl->context.Clear( GL_COLOR_BUFFER_BIT , Context::CHECK_CACHED_VALUES );
684     mImpl->context.SetScissorTest( false );
685   }
686
687   Render::ProcessRenderInstruction( instruction,
688                                     mImpl->context,
689                                     mImpl->textureCache,
690                                     defaultShader,
691                                     mImpl->geometryBatcher,
692                                     mImpl->renderBufferIndex );
693
694   if(instruction.mOffscreenTextureId != 0)
695   {
696     GLenum attachments[] = { GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT };
697     mImpl->context.InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
698   }
699
700   if( instruction.mRenderTracker && offscreen != NULL )
701   {
702     // This will create a sync object every frame this render tracker
703     // is alive (though it should be now be created only for
704     // render-once render tasks)
705     instruction.mRenderTracker->CreateSyncObject( mImpl->glSyncAbstraction );
706     instruction.mRenderTracker = NULL; // Only create once.
707   }
708 }
709
710 } // namespace SceneGraph
711
712 } // namespace Internal
713
714 } // namespace Dali