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