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