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