Converted GPU buffers for geometry to new API
[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   commandBuffer.BindTextures(textureBindings);
401
402   return result;
403 }
404
405 void Renderer::SetFaceCullingMode(FaceCullingMode::Type mode)
406 {
407   mFaceCullingMode = mode;
408   mUpdated         = true;
409 }
410
411 void Renderer::SetBlendingBitMask(uint32_t bitmask)
412 {
413   mBlendingOptions.SetBitmask(bitmask);
414   mUpdated = true;
415 }
416
417 void Renderer::SetBlendColor(const Vector4& color)
418 {
419   mBlendingOptions.SetBlendColor(color);
420   mUpdated = true;
421 }
422
423 void Renderer::SetIndexedDrawFirstElement(uint32_t firstElement)
424 {
425   mIndexedDrawFirstElement = firstElement;
426   mUpdated                 = true;
427 }
428
429 void Renderer::SetIndexedDrawElementsCount(uint32_t elementsCount)
430 {
431   mIndexedDrawElementsCount = elementsCount;
432   mUpdated                  = true;
433 }
434
435 void Renderer::EnablePreMultipliedAlpha(bool enable)
436 {
437   mPremultipledAlphaEnabled = enable;
438   mUpdated                  = true;
439 }
440
441 void Renderer::SetDepthWriteMode(DepthWriteMode::Type depthWriteMode)
442 {
443   mDepthWriteMode = depthWriteMode;
444   mUpdated        = true;
445 }
446
447 void Renderer::SetDepthTestMode(DepthTestMode::Type depthTestMode)
448 {
449   mDepthTestMode = depthTestMode;
450   mUpdated       = true;
451 }
452
453 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
454 {
455   return mDepthWriteMode;
456 }
457
458 DepthTestMode::Type Renderer::GetDepthTestMode() const
459 {
460   return mDepthTestMode;
461 }
462
463 void Renderer::SetDepthFunction(DepthFunction::Type depthFunction)
464 {
465   mDepthFunction = depthFunction;
466   mUpdated       = true;
467 }
468
469 DepthFunction::Type Renderer::GetDepthFunction() const
470 {
471   return mDepthFunction;
472 }
473
474 void Renderer::SetRenderMode(RenderMode::Type renderMode)
475 {
476   mStencilParameters.renderMode = renderMode;
477   mUpdated                      = true;
478 }
479
480 RenderMode::Type Renderer::GetRenderMode() const
481 {
482   return mStencilParameters.renderMode;
483 }
484
485 void Renderer::SetStencilFunction(StencilFunction::Type stencilFunction)
486 {
487   mStencilParameters.stencilFunction = stencilFunction;
488   mUpdated                           = true;
489 }
490
491 StencilFunction::Type Renderer::GetStencilFunction() const
492 {
493   return mStencilParameters.stencilFunction;
494 }
495
496 void Renderer::SetStencilFunctionMask(int stencilFunctionMask)
497 {
498   mStencilParameters.stencilFunctionMask = stencilFunctionMask;
499   mUpdated                               = true;
500 }
501
502 int Renderer::GetStencilFunctionMask() const
503 {
504   return mStencilParameters.stencilFunctionMask;
505 }
506
507 void Renderer::SetStencilFunctionReference(int stencilFunctionReference)
508 {
509   mStencilParameters.stencilFunctionReference = stencilFunctionReference;
510   mUpdated                                    = true;
511 }
512
513 int Renderer::GetStencilFunctionReference() const
514 {
515   return mStencilParameters.stencilFunctionReference;
516 }
517
518 void Renderer::SetStencilMask(int stencilMask)
519 {
520   mStencilParameters.stencilMask = stencilMask;
521   mUpdated                       = true;
522 }
523
524 int Renderer::GetStencilMask() const
525 {
526   return mStencilParameters.stencilMask;
527 }
528
529 void Renderer::SetStencilOperationOnFail(StencilOperation::Type stencilOperationOnFail)
530 {
531   mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
532   mUpdated                                  = true;
533 }
534
535 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
536 {
537   return mStencilParameters.stencilOperationOnFail;
538 }
539
540 void Renderer::SetStencilOperationOnZFail(StencilOperation::Type stencilOperationOnZFail)
541 {
542   mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
543   mUpdated                                   = true;
544 }
545
546 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
547 {
548   return mStencilParameters.stencilOperationOnZFail;
549 }
550
551 void Renderer::SetStencilOperationOnZPass(StencilOperation::Type stencilOperationOnZPass)
552 {
553   mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
554   mUpdated                                   = true;
555 }
556
557 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
558 {
559   return mStencilParameters.stencilOperationOnZPass;
560 }
561
562 void Renderer::Upload()
563 {
564   mGeometry->Upload(*mGraphicsController);
565 }
566
567 void Renderer::Render(Context&                                             context,
568                       BufferIndex                                          bufferIndex,
569                       const SceneGraph::NodeDataProvider&                  node,
570                       const Matrix&                                        modelMatrix,
571                       const Matrix&                                        modelViewMatrix,
572                       const Matrix&                                        viewMatrix,
573                       const Matrix&                                        projectionMatrix,
574                       const Vector3&                                       size,
575                       bool                                                 blend,
576                       Vector<Graphics::Texture*>&                          boundTextures,
577                       const Dali::Internal::SceneGraph::RenderInstruction& instruction,
578                       uint32_t                                             queueIndex)
579 {
580   // Before doing anything test if the call happens in the right queue
581   if(mDrawCommands.empty() && queueIndex > 0)
582   {
583     return;
584   }
585
586   // Prepare commands
587   std::vector<DevelRenderer::DrawCommand*> commands;
588   for(auto& cmd : mDrawCommands)
589   {
590     if(cmd.queue == queueIndex)
591     {
592       commands.emplace_back(&cmd);
593     }
594   }
595
596   // Have commands but nothing to be drawn - abort
597   if(!mDrawCommands.empty() && commands.empty())
598   {
599     return;
600   }
601
602   // Get the program to use:
603   Program* program = mRenderDataProvider->GetShader().GetProgram();
604   if(!program)
605   {
606     DALI_LOG_ERROR("Failed to get program for shader at address %p.\n", reinterpret_cast<void*>(&mRenderDataProvider->GetShader()));
607     return;
608   }
609
610   // For now, create command buffer to perform only the texture / sample binding
611   // and submit it.
612   // Expect this call to glBindTextureForUnit, and glTexParameteri() for the sampler
613   Graphics::UniquePtr<Graphics::CommandBuffer> commandBuffer = mGraphicsController->CreateCommandBuffer(
614     Graphics::CommandBufferCreateInfo()
615       .SetLevel(Graphics::CommandBufferLevel::SECONDARY),
616     nullptr);
617
618   //Set cull face  mode
619   const Dali::Internal::SceneGraph::Camera* cam = instruction.GetCamera();
620   if(cam->GetReflectionUsed())
621   {
622     auto adjFaceCullingMode = mFaceCullingMode;
623     switch(mFaceCullingMode)
624     {
625       case FaceCullingMode::Type::FRONT:
626       {
627         adjFaceCullingMode = FaceCullingMode::Type::BACK;
628         break;
629       }
630       case FaceCullingMode::Type::BACK:
631       {
632         adjFaceCullingMode = FaceCullingMode::Type::FRONT;
633         break;
634       }
635       default:
636       {
637         // nothing to do, leave culling as it is
638       }
639     }
640     context.CullFace(adjFaceCullingMode);
641   }
642   else
643   {
644     context.CullFace(mFaceCullingMode);
645   }
646
647   // Take the program into use so we can send uniforms to it
648   program->Use();
649
650   if(DALI_LIKELY(BindTextures(context, *program, *commandBuffer.get(), boundTextures)))
651   {
652     // Only set up and draw if we have textures and they are all valid
653
654     // set projection and view matrix if program has not yet received them yet this frame
655     SetMatrices(*program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix);
656
657     // set color uniform
658     GLint loc = program->GetUniformLocation(Program::UNIFORM_COLOR);
659     if(Program::UNIFORM_UNKNOWN != loc)
660     {
661       const Vector4& color = node.GetRenderColor(bufferIndex);
662       if(mPremultipledAlphaEnabled)
663       {
664         float alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex);
665         program->SetUniform4f(loc, color.r * alpha, color.g * alpha, color.b * alpha, alpha);
666       }
667       else
668       {
669         program->SetUniform4f(loc, color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex));
670       }
671     }
672
673     SetUniforms(bufferIndex, node, size, *program);
674
675     if(mUpdateAttributesLocation || mGeometry->AttributesChanged())
676     {
677       mGeometry->GetAttributeLocationFromProgram(mAttributesLocation, *program, bufferIndex);
678       mUpdateAttributesLocation = false;
679     }
680
681     if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled)
682     {
683       context.BlendBarrier();
684     }
685
686     if(mDrawCommands.empty())
687     {
688       SetBlending(context, blend);
689
690       mGeometry->Draw(context,
691                       *mGraphicsController,
692                       *commandBuffer.get(),
693                       bufferIndex,
694                       mAttributesLocation,
695                       mIndexedDrawFirstElement,
696                       mIndexedDrawElementsCount);
697     }
698     else
699     {
700       for(auto& cmd : commands)
701       {
702         if(cmd->queue == queueIndex)
703         {
704           //Set blending mode
705           SetBlending(context, cmd->queue == DevelRenderer::RENDER_QUEUE_OPAQUE ? false : blend);
706           mGeometry->Draw(context, *mGraphicsController, *commandBuffer.get(), bufferIndex, mAttributesLocation, cmd->firstIndex, cmd->elementCount);
707         }
708       }
709     }
710     mUpdated = false;
711   }
712 }
713
714 void Renderer::SetSortAttributes(BufferIndex                                             bufferIndex,
715                                  SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes) const
716 {
717   sortAttributes.shader   = &(mRenderDataProvider->GetShader());
718   sortAttributes.geometry = mGeometry;
719 }
720
721 void Renderer::SetShaderChanged(bool value)
722 {
723   mShaderChanged = value;
724 }
725
726 bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
727 {
728   if(mUpdated)
729   {
730     mUpdated = false;
731     return true;
732   }
733
734   if(mShaderChanged || mUpdateAttributesLocation || mGeometry->AttributesChanged())
735   {
736     return true;
737   }
738
739   for(const auto& texture : mRenderDataProvider->GetTextures())
740   {
741     if(texture && texture->IsNativeImage())
742     {
743       return true;
744     }
745   }
746
747   uint64_t                               hash           = 0xc70f6907UL;
748   const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap(bufferIndex);
749   for(const auto& uniformProperty : uniformMapNode)
750   {
751     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
752   }
753
754   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
755   const SceneGraph::CollectedUniformMap&    uniformMap             = uniformMapDataProvider.GetUniformMap(bufferIndex);
756   for(const auto& uniformProperty : uniformMap)
757   {
758     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
759   }
760
761   if(mUniformsHash != hash)
762   {
763     mUniformsHash = hash;
764     return true;
765   }
766
767   return false;
768 }
769
770 } // namespace Render
771
772 } // namespace Internal
773
774 } // namespace Dali