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