fix deep copy of the vector.
[platform/core/uifw/dali-core.git] / dali / internal / render / renderers / render-renderer.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/renderers/render-renderer.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/internal/common/image-sampler.h>
23 #include <dali/internal/render/gl-resources/context.h>
24 #include <dali/internal/render/renderers/render-sampler.h>
25 #include <dali/internal/render/shaders/scene-graph-shader.h>
26 #include <dali/internal/render/shaders/program.h>
27 #include <dali/internal/render/data-providers/node-data-provider.h>
28 #include <dali/internal/render/data-providers/uniform-map-data-provider.h>
29 #include <dali/internal/render/common/render-instruction.h>
30
31 namespace Dali
32 {
33
34 namespace Internal
35 {
36
37 namespace
38 {
39
40
41 /**
42  * Helper to set view and projection matrices once per program
43  * @param program to set the matrices to
44  * @param modelMatrix to set
45  * @param viewMatrix to set
46  * @param projectionMatrix to set
47  * @param modelViewMatrix to set
48  * @param modelViewProjectionMatrix to set
49  */
50 inline void SetMatrices( Program& program,
51                          const Matrix& modelMatrix,
52                          const Matrix& viewMatrix,
53                          const Matrix& projectionMatrix,
54                          const Matrix& modelViewMatrix )
55 {
56   GLint loc = program.GetUniformLocation( Program::UNIFORM_MODEL_MATRIX );
57   if( Program::UNIFORM_UNKNOWN != loc )
58   {
59     program.SetUniformMatrix4fv( loc, 1, modelMatrix.AsFloat() );
60   }
61   loc = program.GetUniformLocation( Program::UNIFORM_VIEW_MATRIX );
62   if( Program::UNIFORM_UNKNOWN != loc )
63   {
64     if( program.GetViewMatrix() != &viewMatrix )
65     {
66       program.SetViewMatrix( &viewMatrix );
67       program.SetUniformMatrix4fv( loc, 1, viewMatrix.AsFloat() );
68     }
69   }
70   // set projection matrix if program has not yet received it this frame or if it is dirty
71   loc = program.GetUniformLocation( Program::UNIFORM_PROJECTION_MATRIX );
72   if( Program::UNIFORM_UNKNOWN != loc )
73   {
74     if( program.GetProjectionMatrix() != &projectionMatrix )
75     {
76       program.SetProjectionMatrix( &projectionMatrix );
77       program.SetUniformMatrix4fv( loc, 1, projectionMatrix.AsFloat() );
78     }
79   }
80   loc = program.GetUniformLocation(Program::UNIFORM_MODELVIEW_MATRIX);
81   if( Program::UNIFORM_UNKNOWN != loc )
82   {
83     program.SetUniformMatrix4fv( loc, 1, modelViewMatrix.AsFloat() );
84   }
85
86   loc = program.GetUniformLocation( Program::UNIFORM_MVP_MATRIX );
87   if( Program::UNIFORM_UNKNOWN != loc )
88   {
89     Matrix modelViewProjectionMatrix(false);
90     Matrix::Multiply( modelViewProjectionMatrix, modelViewMatrix, projectionMatrix );
91     program.SetUniformMatrix4fv( loc, 1, modelViewProjectionMatrix.AsFloat() );
92   }
93
94   loc = program.GetUniformLocation( Program::UNIFORM_NORMAL_MATRIX );
95   if( Program::UNIFORM_UNKNOWN != loc )
96   {
97     Matrix3 normalMatrix;
98     normalMatrix = modelViewMatrix;
99     normalMatrix.Invert();
100     normalMatrix.Transpose();
101     program.SetUniformMatrix3fv( loc, 1, normalMatrix.AsFloat() );
102   }
103 }
104
105 }
106
107 namespace Render
108 {
109
110 Renderer* Renderer::New( SceneGraph::RenderDataProvider* dataProvider,
111                          Render::Geometry* geometry,
112                          uint32_t blendingBitmask,
113                          const Vector4& blendColor,
114                          FaceCullingMode::Type faceCullingMode,
115                          bool preMultipliedAlphaEnabled,
116                          DepthWriteMode::Type depthWriteMode,
117                          DepthTestMode::Type depthTestMode,
118                          DepthFunction::Type depthFunction,
119                          StencilParameters& stencilParameters )
120 {
121   return new Renderer( dataProvider, geometry, blendingBitmask, blendColor,
122                        faceCullingMode, preMultipliedAlphaEnabled, depthWriteMode, depthTestMode,
123                        depthFunction, stencilParameters );
124 }
125
126 Renderer::Renderer( SceneGraph::RenderDataProvider* dataProvider,
127                     Render::Geometry* geometry,
128                     uint32_t blendingBitmask,
129                     const Vector4& blendColor,
130                     FaceCullingMode::Type faceCullingMode,
131                     bool preMultipliedAlphaEnabled,
132                     DepthWriteMode::Type depthWriteMode,
133                     DepthTestMode::Type depthTestMode,
134                     DepthFunction::Type depthFunction,
135                     StencilParameters& stencilParameters )
136 : mRenderDataProvider( dataProvider ),
137   mContext( NULL),
138   mGeometry( geometry ),
139   mUniformIndexMap(),
140   mAttributesLocation(),
141   mUniformsHash(),
142   mStencilParameters( stencilParameters ),
143   mBlendingOptions(),
144   mIndexedDrawFirstElement( 0 ),
145   mIndexedDrawElementsCount( 0 ),
146   mDepthFunction( depthFunction ),
147   mFaceCullingMode( faceCullingMode ),
148   mDepthWriteMode( depthWriteMode ),
149   mDepthTestMode( depthTestMode ),
150   mUpdateAttributesLocation( true ),
151   mPremultipledAlphaEnabled( preMultipliedAlphaEnabled ),
152   mShaderChanged( false ),
153   mUpdated( true )
154 {
155   if( blendingBitmask != 0u )
156   {
157     mBlendingOptions.SetBitmask( blendingBitmask );
158   }
159
160   mBlendingOptions.SetBlendColor( blendColor );
161 }
162
163 void Renderer::Initialize( Context& context )
164 {
165   mContext = &context;
166 }
167
168 Renderer::~Renderer()
169 {
170 }
171
172 void Renderer::SetGeometry( Render::Geometry* geometry )
173 {
174   mGeometry = geometry;
175   mUpdateAttributesLocation = true;
176 }
177 void Renderer::SetDrawCommands( Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size )
178 {
179   mDrawCommands.clear();
180   mDrawCommands.insert( mDrawCommands.end(), pDrawCommands, pDrawCommands+size );
181 }
182
183 void Renderer::SetBlending( Context& context, bool blend )
184 {
185   context.SetBlend( blend );
186   if( blend )
187   {
188     // Blend color is optional and rarely used
189     const Vector4* blendColor = mBlendingOptions.GetBlendColor();
190     if( blendColor )
191     {
192       context.SetCustomBlendColor( *blendColor );
193     }
194     else
195     {
196       context.SetDefaultBlendColor();
197     }
198
199     // Set blend source & destination factors
200     context.BlendFuncSeparate( mBlendingOptions.GetBlendSrcFactorRgb(),
201                                mBlendingOptions.GetBlendDestFactorRgb(),
202                                mBlendingOptions.GetBlendSrcFactorAlpha(),
203                                mBlendingOptions.GetBlendDestFactorAlpha() );
204
205     // Set blend equations
206     context.BlendEquationSeparate( mBlendingOptions.GetBlendEquationRgb(),
207                                    mBlendingOptions.GetBlendEquationAlpha() );
208   }
209
210   mUpdated = true;
211 }
212
213 void Renderer::GlContextDestroyed()
214 {
215   mGeometry->GlContextDestroyed();
216 }
217
218 void Renderer::GlCleanup()
219 {
220 }
221
222 void Renderer::SetUniforms( BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program )
223 {
224   // Check if the map has changed
225   DALI_ASSERT_DEBUG( mRenderDataProvider && "No Uniform map data provider available" );
226
227   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
228
229   if( uniformMapDataProvider.GetUniformMapChanged( bufferIndex ) ||
230       node.GetUniformMapChanged(bufferIndex) ||
231       mUniformIndexMap.Count() == 0 ||
232       mShaderChanged )
233   {
234     // Reset shader pointer
235     mShaderChanged = false;
236
237     const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap( bufferIndex );
238     const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap( bufferIndex );
239
240     uint32_t maxMaps = static_cast<uint32_t>( uniformMap.Count() + uniformMapNode.Count() ); // 4,294,967,295 maps should be enough
241     mUniformIndexMap.Clear(); // Clear contents, but keep memory if we don't change size
242     mUniformIndexMap.Resize( maxMaps );
243
244     uint32_t mapIndex = 0;
245     for(; mapIndex < uniformMap.Count() ; ++mapIndex )
246     {
247       mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex]->propertyPtr;
248       mUniformIndexMap[mapIndex].uniformIndex = program.RegisterUniform( uniformMap[mapIndex]->uniformName );
249     }
250
251     for( uint32_t nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count() ; ++nodeMapIndex )
252     {
253       uint32_t uniformIndex = program.RegisterUniform( uniformMapNode[nodeMapIndex]->uniformName );
254       bool found(false);
255       for( uint32_t i = 0; i<uniformMap.Count(); ++i )
256       {
257         if( mUniformIndexMap[i].uniformIndex == uniformIndex )
258         {
259           mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
260           found = true;
261           break;
262         }
263       }
264
265       if( !found )
266       {
267         mUniformIndexMap[mapIndex].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
268         mUniformIndexMap[mapIndex].uniformIndex = uniformIndex;
269         ++mapIndex;
270       }
271     }
272
273     mUniformIndexMap.Resize( mapIndex );
274   }
275
276   // Set uniforms in local map
277   for( UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
278          end = mUniformIndexMap.End() ;
279        iter != end ;
280        ++iter )
281   {
282     SetUniformFromProperty( bufferIndex, program, *iter );
283   }
284
285   GLint sizeLoc = program.GetUniformLocation( Program::UNIFORM_SIZE );
286   if( -1 != sizeLoc )
287   {
288     program.SetSizeUniform3f( sizeLoc, size.x, size.y, size.z );
289   }
290 }
291
292 void Renderer::SetUniformFromProperty( BufferIndex bufferIndex, Program& program, UniformIndexMap& map )
293 {
294   GLint location = program.GetUniformLocation(map.uniformIndex);
295   if( Program::UNIFORM_UNKNOWN != location )
296   {
297     // switch based on property type to use correct GL uniform setter
298     switch ( map.propertyValue->GetType() )
299     {
300       case Property::INTEGER:
301       {
302         program.SetUniform1i( location, map.propertyValue->GetInteger( bufferIndex ) );
303         break;
304       }
305       case Property::FLOAT:
306       {
307         program.SetUniform1f( location, map.propertyValue->GetFloat( bufferIndex ) );
308         break;
309       }
310       case Property::VECTOR2:
311       {
312         Vector2 value( map.propertyValue->GetVector2( bufferIndex ) );
313         program.SetUniform2f( location, value.x, value.y );
314         break;
315       }
316
317       case Property::VECTOR3:
318       {
319         Vector3 value( map.propertyValue->GetVector3( bufferIndex ) );
320         program.SetUniform3f( location, value.x, value.y, value.z );
321         break;
322       }
323
324       case Property::VECTOR4:
325       {
326         Vector4 value( map.propertyValue->GetVector4( bufferIndex ) );
327         program.SetUniform4f( location, value.x, value.y, value.z, value.w );
328         break;
329       }
330
331       case Property::ROTATION:
332       {
333         Quaternion value( map.propertyValue->GetQuaternion( bufferIndex ) );
334         program.SetUniform4f( location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w );
335         break;
336       }
337
338       case Property::MATRIX:
339       {
340         const Matrix& value = map.propertyValue->GetMatrix(bufferIndex);
341         program.SetUniformMatrix4fv(location, 1, value.AsFloat() );
342         break;
343       }
344
345       case Property::MATRIX3:
346       {
347         const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex);
348         program.SetUniformMatrix3fv(location, 1, value.AsFloat() );
349         break;
350       }
351
352       default:
353       {
354         // Other property types are ignored
355         break;
356       }
357     }
358   }
359 }
360
361 bool Renderer::BindTextures( Context& context, Program& program, Vector<GLuint>& boundTextures )
362 {
363   uint32_t textureUnit = 0;
364   bool result = true;
365
366   GLint uniformLocation(-1);
367   std::vector<Render::Sampler*>& samplers( mRenderDataProvider->GetSamplers() );
368   std::vector<Render::Texture*>& textures( mRenderDataProvider->GetTextures() );
369   for( uint32_t i = 0; i < static_cast<uint32_t>( textures.size() ) && result; ++i ) // not expecting more than uint32_t of textures
370   {
371     if( textures[i] )
372     {
373       result = textures[i]->Bind(context, textureUnit, samplers[i] );
374       boundTextures.PushBack( textures[i]->GetId() );
375       if( result && program.GetSamplerUniformLocation( i, uniformLocation ) )
376       {
377         program.SetUniform1i( uniformLocation, textureUnit );
378         ++textureUnit;
379       }
380     }
381   }
382
383   return result;
384 }
385
386 void Renderer::SetFaceCullingMode( FaceCullingMode::Type mode )
387 {
388   mFaceCullingMode =  mode;
389   mUpdated = true;
390 }
391
392 void Renderer::SetBlendingBitMask( uint32_t bitmask )
393 {
394   mBlendingOptions.SetBitmask( bitmask );
395   mUpdated = true;
396 }
397
398 void Renderer::SetBlendColor( const Vector4& color )
399 {
400   mBlendingOptions.SetBlendColor( color );
401   mUpdated = true;
402 }
403
404 void Renderer::SetIndexedDrawFirstElement( uint32_t firstElement )
405 {
406   mIndexedDrawFirstElement = firstElement;
407   mUpdated = true;
408 }
409
410 void Renderer::SetIndexedDrawElementsCount( uint32_t elementsCount )
411 {
412   mIndexedDrawElementsCount = elementsCount;
413   mUpdated = true;
414 }
415
416 void Renderer::EnablePreMultipliedAlpha( bool enable )
417 {
418   mPremultipledAlphaEnabled = enable;
419   mUpdated = true;
420 }
421
422 void Renderer::SetDepthWriteMode( DepthWriteMode::Type depthWriteMode )
423 {
424   mDepthWriteMode = depthWriteMode;
425   mUpdated = true;
426 }
427
428 void Renderer::SetDepthTestMode( DepthTestMode::Type depthTestMode )
429 {
430   mDepthTestMode = depthTestMode;
431   mUpdated = true;
432 }
433
434 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
435 {
436   return mDepthWriteMode;
437 }
438
439 DepthTestMode::Type Renderer::GetDepthTestMode() const
440 {
441   return mDepthTestMode;
442 }
443
444 void Renderer::SetDepthFunction( DepthFunction::Type depthFunction )
445 {
446   mDepthFunction = depthFunction;
447   mUpdated = true;
448 }
449
450 DepthFunction::Type Renderer::GetDepthFunction() const
451 {
452   return mDepthFunction;
453 }
454
455 void Renderer::SetRenderMode( RenderMode::Type renderMode )
456 {
457   mStencilParameters.renderMode = renderMode;
458   mUpdated = true;
459 }
460
461 RenderMode::Type Renderer::GetRenderMode() const
462 {
463   return mStencilParameters.renderMode;
464 }
465
466 void Renderer::SetStencilFunction( StencilFunction::Type stencilFunction )
467 {
468   mStencilParameters.stencilFunction = stencilFunction;
469   mUpdated = true;
470 }
471
472 StencilFunction::Type Renderer::GetStencilFunction() const
473 {
474   return mStencilParameters.stencilFunction;
475 }
476
477 void Renderer::SetStencilFunctionMask( int stencilFunctionMask )
478 {
479   mStencilParameters.stencilFunctionMask = stencilFunctionMask;
480   mUpdated = true;
481 }
482
483 int Renderer::GetStencilFunctionMask() const
484 {
485   return mStencilParameters.stencilFunctionMask;
486 }
487
488 void Renderer::SetStencilFunctionReference( int stencilFunctionReference )
489 {
490   mStencilParameters.stencilFunctionReference = stencilFunctionReference;
491   mUpdated = true;
492 }
493
494 int Renderer::GetStencilFunctionReference() const
495 {
496   return mStencilParameters.stencilFunctionReference;
497 }
498
499 void Renderer::SetStencilMask( int stencilMask )
500 {
501   mStencilParameters.stencilMask = stencilMask;
502   mUpdated = true;
503 }
504
505 int Renderer::GetStencilMask() const
506 {
507   return mStencilParameters.stencilMask;
508 }
509
510 void Renderer::SetStencilOperationOnFail( StencilOperation::Type stencilOperationOnFail )
511 {
512   mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
513   mUpdated = true;
514 }
515
516 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
517 {
518   return mStencilParameters.stencilOperationOnFail;
519 }
520
521 void Renderer::SetStencilOperationOnZFail( StencilOperation::Type stencilOperationOnZFail )
522 {
523   mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
524   mUpdated = true;
525 }
526
527 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
528 {
529   return mStencilParameters.stencilOperationOnZFail;
530 }
531
532 void Renderer::SetStencilOperationOnZPass( StencilOperation::Type stencilOperationOnZPass )
533 {
534   mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
535   mUpdated = true;
536 }
537
538 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
539 {
540   return mStencilParameters.stencilOperationOnZPass;
541 }
542
543 void Renderer::Upload( Context& context )
544 {
545   mGeometry->Upload( context );
546 }
547
548 void Renderer::Render( Context& context,
549                        BufferIndex bufferIndex,
550                        const SceneGraph::NodeDataProvider& node,
551                        const Matrix& modelMatrix,
552                        const Matrix& modelViewMatrix,
553                        const Matrix& viewMatrix,
554                        const Matrix& projectionMatrix,
555                        const Vector3& size,
556                        bool blend,
557                        Vector<GLuint>& boundTextures,
558                        const Dali::Internal::SceneGraph::RenderInstruction& instruction,
559                        uint32_t queueIndex )
560 {
561   // Before doing anything test if the call happens in the right queue
562   if( mDrawCommands.empty() && queueIndex > 0 )
563   {
564     return;
565   }
566
567   // Prepare commands
568   std::vector<DevelRenderer::DrawCommand*> commands;
569   for( auto& cmd : mDrawCommands )
570   {
571     if(cmd.queue == queueIndex)
572     {
573       commands.emplace_back( &cmd );
574     }
575   }
576
577   // Have commands but nothing to be drawn - abort
578   if(!mDrawCommands.empty() && commands.empty())
579   {
580     return;
581   }
582
583   // Get the program to use:
584   Program* program = mRenderDataProvider->GetShader().GetProgram();
585   if( !program )
586   {
587     DALI_LOG_ERROR( "Failed to get program for shader at address %p.\n", reinterpret_cast< void* >( &mRenderDataProvider->GetShader() ) );
588     return;
589   }
590
591   //Set cull face  mode
592   const Dali::Internal::SceneGraph::Camera* cam = instruction.GetCamera();
593   if (cam->GetReflectionUsed())
594   {
595     auto adjFaceCullingMode = mFaceCullingMode;
596     switch( mFaceCullingMode )
597     {
598       case FaceCullingMode::Type::FRONT:
599       {
600         adjFaceCullingMode = FaceCullingMode::Type::BACK;
601         break;
602       }
603       case FaceCullingMode::Type::BACK:
604       {
605         adjFaceCullingMode = FaceCullingMode::Type::FRONT;
606         break;
607       }
608       default:
609       {
610         // nothing to do, leave culling as it is
611       }
612     }
613     context.CullFace( adjFaceCullingMode );
614   }
615   else
616   {
617     context.CullFace( mFaceCullingMode );
618   }
619
620   // Take the program into use so we can send uniforms to it
621   program->Use();
622
623   if( DALI_LIKELY( BindTextures( context, *program, boundTextures ) ) )
624   {
625     // Only set up and draw if we have textures and they are all valid
626
627     // set projection and view matrix if program has not yet received them yet this frame
628     SetMatrices( *program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix );
629
630     // set color uniform
631     GLint loc = program->GetUniformLocation( Program::UNIFORM_COLOR );
632     if( Program::UNIFORM_UNKNOWN != loc )
633     {
634       const Vector4& color = node.GetRenderColor( bufferIndex );
635       if( mPremultipledAlphaEnabled )
636       {
637         float alpha = color.a * mRenderDataProvider->GetOpacity( bufferIndex );
638         program->SetUniform4f( loc, color.r * alpha, color.g * alpha, color.b * alpha, alpha );
639       }
640       else
641       {
642         program->SetUniform4f( loc, color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity( bufferIndex ) );
643       }
644     }
645
646     SetUniforms( bufferIndex, node, size, *program );
647
648     if( mUpdateAttributesLocation || mGeometry->AttributesChanged() )
649     {
650       mGeometry->GetAttributeLocationFromProgram( mAttributesLocation, *program, bufferIndex );
651       mUpdateAttributesLocation = false;
652     }
653
654     if(mDrawCommands.empty())
655     {
656       SetBlending( context, blend );
657
658       mGeometry->Draw( context,
659                        bufferIndex,
660                        mAttributesLocation,
661                        mIndexedDrawFirstElement,
662                        mIndexedDrawElementsCount );
663     }
664     else
665     {
666       for(auto& cmd : commands )
667       {
668         if(cmd->queue == queueIndex )
669         {
670           //Set blending mode
671           SetBlending(context, cmd->queue == DevelRenderer::RENDER_QUEUE_OPAQUE ? false : blend);
672           mGeometry->Draw(context, bufferIndex, mAttributesLocation,
673                           cmd->firstIndex, cmd->elementCount);
674         }
675       }
676     }
677     mUpdated = false;
678   }
679 }
680
681 void Renderer::SetSortAttributes( BufferIndex bufferIndex,
682                                   SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes ) const
683 {
684   sortAttributes.shader = &( mRenderDataProvider->GetShader() );
685   sortAttributes.geometry = mGeometry;
686 }
687
688 void Renderer::SetShaderChanged( bool value )
689 {
690   mShaderChanged = value;
691 }
692
693 bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
694 {
695   if (mUpdated)
696   {
697     mUpdated = false;
698     return true;
699   }
700
701   if (mShaderChanged || mUpdateAttributesLocation || mGeometry->AttributesChanged())
702   {
703     return true;
704   }
705
706   for( const auto& texture : mRenderDataProvider->GetTextures() )
707   {
708     if (texture && texture->IsNativeImage())
709     {
710       return true;
711     }
712   }
713
714   uint64_t hash = 0xc70f6907UL;
715   const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap( bufferIndex );
716   for (const auto* uniformProperty : uniformMapNode)
717   {
718     hash = uniformProperty->propertyPtr->Hash(bufferIndex, hash);
719   }
720
721   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
722   const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap( bufferIndex );
723   for (const auto* uniformProperty : uniformMap)
724   {
725     hash = uniformProperty->propertyPtr->Hash(bufferIndex, hash);
726   }
727
728   if (mUniformsHash != hash)
729   {
730     mUniformsHash = hash;
731     return true;
732   }
733
734   return false;
735 }
736
737 } // namespace SceneGraph
738
739 } // namespace Internal
740
741 } // namespace Dali