Implemented Draw and basic pipeline for vertex format and topology
[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/renderers/render-vertex-buffer.h>
30 #include <dali/internal/render/shaders/program.h>
31 #include <dali/internal/render/shaders/scene-graph-shader.h>
32
33 namespace Dali
34 {
35 namespace Internal
36 {
37 namespace
38 {
39 /**
40  * Helper to set view and projection matrices once per program
41  * @param program to set the matrices to
42  * @param modelMatrix to set
43  * @param viewMatrix to set
44  * @param projectionMatrix to set
45  * @param modelViewMatrix to set
46  * @param modelViewProjectionMatrix to set
47  */
48 inline void SetMatrices(Program&      program,
49                         const Matrix& modelMatrix,
50                         const Matrix& viewMatrix,
51                         const Matrix& projectionMatrix,
52                         const Matrix& modelViewMatrix)
53 {
54   GLint loc = program.GetUniformLocation(Program::UNIFORM_MODEL_MATRIX);
55   if(Program::UNIFORM_UNKNOWN != loc)
56   {
57     program.SetUniformMatrix4fv(loc, 1, modelMatrix.AsFloat());
58   }
59   loc = program.GetUniformLocation(Program::UNIFORM_VIEW_MATRIX);
60   if(Program::UNIFORM_UNKNOWN != loc)
61   {
62     if(program.GetViewMatrix() != &viewMatrix)
63     {
64       program.SetViewMatrix(&viewMatrix);
65       program.SetUniformMatrix4fv(loc, 1, viewMatrix.AsFloat());
66     }
67   }
68   // set projection matrix if program has not yet received it this frame or if it is dirty
69   loc = program.GetUniformLocation(Program::UNIFORM_PROJECTION_MATRIX);
70   if(Program::UNIFORM_UNKNOWN != loc)
71   {
72     if(program.GetProjectionMatrix() != &projectionMatrix)
73     {
74       program.SetProjectionMatrix(&projectionMatrix);
75       program.SetUniformMatrix4fv(loc, 1, projectionMatrix.AsFloat());
76     }
77   }
78   loc = program.GetUniformLocation(Program::UNIFORM_MODELVIEW_MATRIX);
79   if(Program::UNIFORM_UNKNOWN != loc)
80   {
81     program.SetUniformMatrix4fv(loc, 1, modelViewMatrix.AsFloat());
82   }
83
84   loc = program.GetUniformLocation(Program::UNIFORM_MVP_MATRIX);
85   if(Program::UNIFORM_UNKNOWN != loc)
86   {
87     Matrix modelViewProjectionMatrix(false);
88     Matrix::Multiply(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix);
89     program.SetUniformMatrix4fv(loc, 1, modelViewProjectionMatrix.AsFloat());
90   }
91
92   loc = program.GetUniformLocation(Program::UNIFORM_NORMAL_MATRIX);
93   if(Program::UNIFORM_UNKNOWN != loc)
94   {
95     Matrix3 normalMatrix;
96     normalMatrix = modelViewMatrix;
97     normalMatrix.Invert();
98     normalMatrix.Transpose();
99     program.SetUniformMatrix3fv(loc, 1, normalMatrix.AsFloat());
100   }
101 }
102
103 // Helper to get the vertex input format
104 Dali::Graphics::VertexInputFormat GetPropertyVertexFormat(Property::Type propertyType)
105 {
106   Dali::Graphics::VertexInputFormat type{};
107
108   switch(propertyType)
109   {
110     case Property::NONE:
111     case Property::STRING:
112     case Property::ARRAY:
113     case Property::MAP:
114     case Property::EXTENTS:   // i4?
115     case Property::RECTANGLE: // i4/f4?
116     case Property::ROTATION:
117     {
118       type = Dali::Graphics::VertexInputFormat::UNDEFINED;
119       break;
120     }
121     case Property::BOOLEAN:
122     {
123       type = Dali::Graphics::VertexInputFormat::UNDEFINED; // type = GL_BYTE; @todo new type for this?
124       break;
125     }
126     case Property::INTEGER:
127     {
128       type = Dali::Graphics::VertexInputFormat::INTEGER; // (short)
129       break;
130     }
131     case Property::FLOAT:
132     {
133       type = Dali::Graphics::VertexInputFormat::FLOAT;
134       break;
135     }
136     case Property::VECTOR2:
137     {
138       type = Dali::Graphics::VertexInputFormat::FVECTOR2;
139       break;
140     }
141     case Property::VECTOR3:
142     {
143       type = Dali::Graphics::VertexInputFormat::FVECTOR3;
144       break;
145     }
146     case Property::VECTOR4:
147     {
148       type = Dali::Graphics::VertexInputFormat::FVECTOR4;
149       break;
150     }
151     case Property::MATRIX3:
152     {
153       type = Dali::Graphics::VertexInputFormat::FLOAT;
154       break;
155     }
156     case Property::MATRIX:
157     {
158       type = Dali::Graphics::VertexInputFormat::FLOAT;
159       break;
160     }
161   }
162
163   return type;
164 }
165
166 } // namespace
167
168 namespace Render
169 {
170 Renderer* Renderer::New(SceneGraph::RenderDataProvider* dataProvider,
171                         Render::Geometry*               geometry,
172                         uint32_t                        blendingBitmask,
173                         const Vector4&                  blendColor,
174                         FaceCullingMode::Type           faceCullingMode,
175                         bool                            preMultipliedAlphaEnabled,
176                         DepthWriteMode::Type            depthWriteMode,
177                         DepthTestMode::Type             depthTestMode,
178                         DepthFunction::Type             depthFunction,
179                         StencilParameters&              stencilParameters)
180 {
181   return new Renderer(dataProvider, geometry, blendingBitmask, blendColor, faceCullingMode, preMultipliedAlphaEnabled, depthWriteMode, depthTestMode, depthFunction, stencilParameters);
182 }
183
184 Renderer::Renderer(SceneGraph::RenderDataProvider* dataProvider,
185                    Render::Geometry*               geometry,
186                    uint32_t                        blendingBitmask,
187                    const Vector4&                  blendColor,
188                    FaceCullingMode::Type           faceCullingMode,
189                    bool                            preMultipliedAlphaEnabled,
190                    DepthWriteMode::Type            depthWriteMode,
191                    DepthTestMode::Type             depthTestMode,
192                    DepthFunction::Type             depthFunction,
193                    StencilParameters&              stencilParameters)
194 : mRenderDataProvider(dataProvider),
195   mContext(nullptr),
196   mGeometry(geometry),
197   mUniformIndexMap(),
198   mAttributeLocations(),
199   mUniformsHash(),
200   mStencilParameters(stencilParameters),
201   mBlendingOptions(),
202   mIndexedDrawFirstElement(0),
203   mIndexedDrawElementsCount(0),
204   mDepthFunction(depthFunction),
205   mFaceCullingMode(faceCullingMode),
206   mDepthWriteMode(depthWriteMode),
207   mDepthTestMode(depthTestMode),
208   mUpdateAttributeLocations(true),
209   mPremultipledAlphaEnabled(preMultipliedAlphaEnabled),
210   mShaderChanged(false),
211   mUpdated(true)
212 {
213   if(blendingBitmask != 0u)
214   {
215     mBlendingOptions.SetBitmask(blendingBitmask);
216   }
217
218   mBlendingOptions.SetBlendColor(blendColor);
219 }
220
221 void Renderer::Initialize(Context& context, Graphics::Controller& graphicsController)
222 {
223   mContext            = &context;
224   mGraphicsController = &graphicsController;
225 }
226
227 Renderer::~Renderer() = default;
228
229 void Renderer::SetGeometry(Render::Geometry* geometry)
230 {
231   mGeometry                 = geometry;
232   mUpdateAttributeLocations = true;
233 }
234 void Renderer::SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size)
235 {
236   mDrawCommands.clear();
237   mDrawCommands.insert(mDrawCommands.end(), pDrawCommands, pDrawCommands + size);
238 }
239
240 void Renderer::SetBlending(Context& context, bool blend)
241 {
242   context.SetBlend(blend);
243   if(blend)
244   {
245     // Blend color is optional and rarely used
246     const Vector4* blendColor = mBlendingOptions.GetBlendColor();
247     if(blendColor)
248     {
249       context.SetCustomBlendColor(*blendColor);
250     }
251     else
252     {
253       context.SetDefaultBlendColor();
254     }
255
256     // Set blend source & destination factors
257     context.BlendFuncSeparate(mBlendingOptions.GetBlendSrcFactorRgb(),
258                               mBlendingOptions.GetBlendDestFactorRgb(),
259                               mBlendingOptions.GetBlendSrcFactorAlpha(),
260                               mBlendingOptions.GetBlendDestFactorAlpha());
261
262     // Set blend equations
263     Dali::DevelBlendEquation::Type rgbEquation   = mBlendingOptions.GetBlendEquationRgb();
264     Dali::DevelBlendEquation::Type alphaEquation = mBlendingOptions.GetBlendEquationAlpha();
265
266     if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled)
267     {
268       if(rgbEquation != alphaEquation)
269       {
270         DALI_LOG_ERROR("Advanced Blend Equation have to be appried by using BlendEquation.\n");
271       }
272       context.BlendEquation(rgbEquation);
273     }
274     else
275     {
276       context.BlendEquationSeparate(rgbEquation, alphaEquation);
277     }
278   }
279
280   mUpdated = true;
281 }
282
283 void Renderer::GlContextDestroyed()
284 {
285   mGeometry->GlContextDestroyed();
286 }
287
288 void Renderer::GlCleanup()
289 {
290 }
291
292 void Renderer::SetUniforms(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program)
293 {
294   // Check if the map has changed
295   DALI_ASSERT_DEBUG(mRenderDataProvider && "No Uniform map data provider available");
296
297   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
298
299   if(uniformMapDataProvider.GetUniformMapChanged(bufferIndex) ||
300      node.GetUniformMapChanged(bufferIndex) ||
301      mUniformIndexMap.Count() == 0 ||
302      mShaderChanged)
303   {
304     // Reset shader pointer
305     mShaderChanged = false;
306
307     const SceneGraph::CollectedUniformMap& uniformMap     = uniformMapDataProvider.GetUniformMap(bufferIndex);
308     const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap(bufferIndex);
309
310     uint32_t maxMaps = static_cast<uint32_t>(uniformMap.Count() + uniformMapNode.Count()); // 4,294,967,295 maps should be enough
311     mUniformIndexMap.Clear();                                                              // Clear contents, but keep memory if we don't change size
312     mUniformIndexMap.Resize(maxMaps);
313
314     uint32_t mapIndex = 0;
315     for(; mapIndex < uniformMap.Count(); ++mapIndex)
316     {
317       mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex].propertyPtr;
318       mUniformIndexMap[mapIndex].uniformIndex  = program.RegisterUniform(uniformMap[mapIndex].uniformName);
319     }
320
321     for(uint32_t nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count(); ++nodeMapIndex)
322     {
323       uint32_t uniformIndex = program.RegisterUniform(uniformMapNode[nodeMapIndex].uniformName);
324       bool     found(false);
325       for(uint32_t i = 0; i < uniformMap.Count(); ++i)
326       {
327         if(mUniformIndexMap[i].uniformIndex == uniformIndex)
328         {
329           mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr;
330           found                             = true;
331           break;
332         }
333       }
334
335       if(!found)
336       {
337         mUniformIndexMap[mapIndex].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr;
338         mUniformIndexMap[mapIndex].uniformIndex  = uniformIndex;
339         ++mapIndex;
340       }
341     }
342
343     mUniformIndexMap.Resize(mapIndex);
344   }
345
346   // Set uniforms in local map
347   for(UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
348                                      end  = mUniformIndexMap.End();
349       iter != end;
350       ++iter)
351   {
352     SetUniformFromProperty(bufferIndex, program, *iter);
353   }
354
355   GLint sizeLoc = program.GetUniformLocation(Program::UNIFORM_SIZE);
356   if(-1 != sizeLoc)
357   {
358     program.SetSizeUniform3f(sizeLoc, size.x, size.y, size.z);
359   }
360 }
361
362 void Renderer::SetUniformFromProperty(BufferIndex bufferIndex, Program& program, UniformIndexMap& map)
363 {
364   GLint location = program.GetUniformLocation(map.uniformIndex);
365   if(Program::UNIFORM_UNKNOWN != location)
366   {
367     // switch based on property type to use correct GL uniform setter
368     switch(map.propertyValue->GetType())
369     {
370       case Property::INTEGER:
371       {
372         program.SetUniform1i(location, map.propertyValue->GetInteger(bufferIndex));
373         break;
374       }
375       case Property::FLOAT:
376       {
377         program.SetUniform1f(location, map.propertyValue->GetFloat(bufferIndex));
378         break;
379       }
380       case Property::VECTOR2:
381       {
382         Vector2 value(map.propertyValue->GetVector2(bufferIndex));
383         program.SetUniform2f(location, value.x, value.y);
384         break;
385       }
386
387       case Property::VECTOR3:
388       {
389         Vector3 value(map.propertyValue->GetVector3(bufferIndex));
390         program.SetUniform3f(location, value.x, value.y, value.z);
391         break;
392       }
393
394       case Property::VECTOR4:
395       {
396         Vector4 value(map.propertyValue->GetVector4(bufferIndex));
397         program.SetUniform4f(location, value.x, value.y, value.z, value.w);
398         break;
399       }
400
401       case Property::ROTATION:
402       {
403         Quaternion value(map.propertyValue->GetQuaternion(bufferIndex));
404         program.SetUniform4f(location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w);
405         break;
406       }
407
408       case Property::MATRIX:
409       {
410         const Matrix& value = map.propertyValue->GetMatrix(bufferIndex);
411         program.SetUniformMatrix4fv(location, 1, value.AsFloat());
412         break;
413       }
414
415       case Property::MATRIX3:
416       {
417         const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex);
418         program.SetUniformMatrix3fv(location, 1, value.AsFloat());
419         break;
420       }
421
422       default:
423       {
424         // Other property types are ignored
425         break;
426       }
427     }
428   }
429 }
430
431 bool Renderer::BindTextures(Context& context, Program& program, Graphics::CommandBuffer& commandBuffer, Vector<Graphics::Texture*>& boundTextures)
432 {
433   uint32_t textureUnit = 0;
434   bool     result      = true;
435
436   GLint                          uniformLocation(-1);
437   std::vector<Render::Sampler*>& samplers(mRenderDataProvider->GetSamplers());
438   std::vector<Render::Texture*>& textures(mRenderDataProvider->GetTextures());
439
440   std::vector<Graphics::TextureBinding> textureBindings;
441   for(uint32_t i = 0; i < static_cast<uint32_t>(textures.size()) && result; ++i) // not expecting more than uint32_t of textures
442   {
443     if(textures[i])
444     {
445       if(program.GetSamplerUniformLocation(i, uniformLocation))
446       {
447         // if the sampler exists,
448         //   if it's default, delete the graphics object
449         //   otherwise re-initialize it if dirty
450
451         const Graphics::Sampler* graphicsSampler = (samplers[i] ? samplers[i]->GetGraphicsObject()
452                                                                 : nullptr);
453
454         boundTextures.PushBack(textures[i]->GetGraphicsObject());
455         const Graphics::TextureBinding textureBinding{textures[i]->GetGraphicsObject(), graphicsSampler, textureUnit};
456         textureBindings.push_back(textureBinding);
457
458         program.SetUniform1i(uniformLocation, textureUnit); // Get through shader reflection
459         ++textureUnit;
460       }
461     }
462   }
463
464   if(textureBindings.size() > 0)
465   {
466     commandBuffer.BindTextures(textureBindings);
467   }
468
469   return result;
470 }
471
472 void Renderer::SetFaceCullingMode(FaceCullingMode::Type mode)
473 {
474   mFaceCullingMode = mode;
475   mUpdated         = true;
476 }
477
478 void Renderer::SetBlendingBitMask(uint32_t bitmask)
479 {
480   mBlendingOptions.SetBitmask(bitmask);
481   mUpdated = true;
482 }
483
484 void Renderer::SetBlendColor(const Vector4& color)
485 {
486   mBlendingOptions.SetBlendColor(color);
487   mUpdated = true;
488 }
489
490 void Renderer::SetIndexedDrawFirstElement(uint32_t firstElement)
491 {
492   mIndexedDrawFirstElement = firstElement;
493   mUpdated                 = true;
494 }
495
496 void Renderer::SetIndexedDrawElementsCount(uint32_t elementsCount)
497 {
498   mIndexedDrawElementsCount = elementsCount;
499   mUpdated                  = true;
500 }
501
502 void Renderer::EnablePreMultipliedAlpha(bool enable)
503 {
504   mPremultipledAlphaEnabled = enable;
505   mUpdated                  = true;
506 }
507
508 void Renderer::SetDepthWriteMode(DepthWriteMode::Type depthWriteMode)
509 {
510   mDepthWriteMode = depthWriteMode;
511   mUpdated        = true;
512 }
513
514 void Renderer::SetDepthTestMode(DepthTestMode::Type depthTestMode)
515 {
516   mDepthTestMode = depthTestMode;
517   mUpdated       = true;
518 }
519
520 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
521 {
522   return mDepthWriteMode;
523 }
524
525 DepthTestMode::Type Renderer::GetDepthTestMode() const
526 {
527   return mDepthTestMode;
528 }
529
530 void Renderer::SetDepthFunction(DepthFunction::Type depthFunction)
531 {
532   mDepthFunction = depthFunction;
533   mUpdated       = true;
534 }
535
536 DepthFunction::Type Renderer::GetDepthFunction() const
537 {
538   return mDepthFunction;
539 }
540
541 void Renderer::SetRenderMode(RenderMode::Type renderMode)
542 {
543   mStencilParameters.renderMode = renderMode;
544   mUpdated                      = true;
545 }
546
547 RenderMode::Type Renderer::GetRenderMode() const
548 {
549   return mStencilParameters.renderMode;
550 }
551
552 void Renderer::SetStencilFunction(StencilFunction::Type stencilFunction)
553 {
554   mStencilParameters.stencilFunction = stencilFunction;
555   mUpdated                           = true;
556 }
557
558 StencilFunction::Type Renderer::GetStencilFunction() const
559 {
560   return mStencilParameters.stencilFunction;
561 }
562
563 void Renderer::SetStencilFunctionMask(int stencilFunctionMask)
564 {
565   mStencilParameters.stencilFunctionMask = stencilFunctionMask;
566   mUpdated                               = true;
567 }
568
569 int Renderer::GetStencilFunctionMask() const
570 {
571   return mStencilParameters.stencilFunctionMask;
572 }
573
574 void Renderer::SetStencilFunctionReference(int stencilFunctionReference)
575 {
576   mStencilParameters.stencilFunctionReference = stencilFunctionReference;
577   mUpdated                                    = true;
578 }
579
580 int Renderer::GetStencilFunctionReference() const
581 {
582   return mStencilParameters.stencilFunctionReference;
583 }
584
585 void Renderer::SetStencilMask(int stencilMask)
586 {
587   mStencilParameters.stencilMask = stencilMask;
588   mUpdated                       = true;
589 }
590
591 int Renderer::GetStencilMask() const
592 {
593   return mStencilParameters.stencilMask;
594 }
595
596 void Renderer::SetStencilOperationOnFail(StencilOperation::Type stencilOperationOnFail)
597 {
598   mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
599   mUpdated                                  = true;
600 }
601
602 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
603 {
604   return mStencilParameters.stencilOperationOnFail;
605 }
606
607 void Renderer::SetStencilOperationOnZFail(StencilOperation::Type stencilOperationOnZFail)
608 {
609   mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
610   mUpdated                                   = true;
611 }
612
613 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
614 {
615   return mStencilParameters.stencilOperationOnZFail;
616 }
617
618 void Renderer::SetStencilOperationOnZPass(StencilOperation::Type stencilOperationOnZPass)
619 {
620   mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
621   mUpdated                                   = true;
622 }
623
624 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
625 {
626   return mStencilParameters.stencilOperationOnZPass;
627 }
628
629 void Renderer::Upload()
630 {
631   mGeometry->Upload(*mGraphicsController);
632 }
633
634 void Renderer::Render(Context&                                             context,
635                       BufferIndex                                          bufferIndex,
636                       const SceneGraph::NodeDataProvider&                  node,
637                       const Matrix&                                        modelMatrix,
638                       const Matrix&                                        modelViewMatrix,
639                       const Matrix&                                        viewMatrix,
640                       const Matrix&                                        projectionMatrix,
641                       const Vector3&                                       size,
642                       bool                                                 blend,
643                       Vector<Graphics::Texture*>&                          boundTextures,
644                       const Dali::Internal::SceneGraph::RenderInstruction& instruction,
645                       uint32_t                                             queueIndex)
646 {
647   // Before doing anything test if the call happens in the right queue
648   if(mDrawCommands.empty() && queueIndex > 0)
649   {
650     return;
651   }
652
653   // Prepare commands
654   std::vector<DevelRenderer::DrawCommand*> commands;
655   for(auto& cmd : mDrawCommands)
656   {
657     if(cmd.queue == queueIndex)
658     {
659       commands.emplace_back(&cmd);
660     }
661   }
662
663   // Have commands but nothing to be drawn - abort
664   if(!mDrawCommands.empty() && commands.empty())
665   {
666     return;
667   }
668
669   // Get the program to use:
670   Program* program = mRenderDataProvider->GetShader().GetProgram();
671   if(!program)
672   {
673     DALI_LOG_ERROR("Failed to get program for shader at address %p.\n", reinterpret_cast<void*>(&mRenderDataProvider->GetShader()));
674     return;
675   }
676
677   Graphics::UniquePtr<Graphics::CommandBuffer> commandBuffer = mGraphicsController->CreateCommandBuffer(
678     Graphics::CommandBufferCreateInfo()
679       .SetLevel(Graphics::CommandBufferLevel::SECONDARY),
680     nullptr);
681
682   //Set cull face  mode
683   const Dali::Internal::SceneGraph::Camera* cam = instruction.GetCamera();
684   if(cam->GetReflectionUsed())
685   {
686     auto adjFaceCullingMode = mFaceCullingMode;
687     switch(mFaceCullingMode)
688     {
689       case FaceCullingMode::Type::FRONT:
690       {
691         adjFaceCullingMode = FaceCullingMode::Type::BACK;
692         break;
693       }
694       case FaceCullingMode::Type::BACK:
695       {
696         adjFaceCullingMode = FaceCullingMode::Type::FRONT;
697         break;
698       }
699       default:
700       {
701         // nothing to do, leave culling as it is
702       }
703     }
704     context.CullFace(adjFaceCullingMode);
705   }
706   else
707   {
708     context.CullFace(mFaceCullingMode);
709   }
710
711   // Temporarily create a pipeline here - this will be used for transporting
712   // topology and vertex format for now.
713   Graphics::UniquePtr<Graphics::Pipeline> pipeline = PrepareGraphicsPipeline(*program);
714   commandBuffer->BindPipeline(*pipeline.get());
715
716   // Take the program into use so we can send uniforms to it
717   program->Use();
718
719   if(DALI_LIKELY(BindTextures(context, *program, *commandBuffer.get(), boundTextures)))
720   {
721     // Only set up and draw if we have textures and they are all valid
722
723     // set projection and view matrix if program has not yet received them yet this frame
724     SetMatrices(*program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix);
725
726     // set color uniform
727     GLint loc = program->GetUniformLocation(Program::UNIFORM_COLOR);
728     if(Program::UNIFORM_UNKNOWN != loc)
729     {
730       const Vector4& color = node.GetRenderColor(bufferIndex);
731       if(mPremultipledAlphaEnabled)
732       {
733         float alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex);
734         program->SetUniform4f(loc, color.r * alpha, color.g * alpha, color.b * alpha, alpha);
735       }
736       else
737       {
738         program->SetUniform4f(loc, color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex));
739       }
740     }
741
742     SetUniforms(bufferIndex, node, size, *program);
743
744     if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled)
745     {
746       context.BlendBarrier();
747     }
748
749     //@todo manage mDrawCommands in the same way as above command buffer?!
750     if(mDrawCommands.empty())
751     {
752       SetBlending(context, blend);
753
754       mGeometry->Draw(*mGraphicsController, *commandBuffer.get(), mIndexedDrawFirstElement, mIndexedDrawElementsCount);
755     }
756     else
757     {
758       for(auto& cmd : commands)
759       {
760         if(cmd->queue == queueIndex)
761         {
762           //Set blending mode
763           SetBlending(context, cmd->queue == DevelRenderer::RENDER_QUEUE_OPAQUE ? false : blend);
764
765           // @todo This should generate a command buffer per cmd
766           // Tests WILL fail.
767           mGeometry->Draw(*mGraphicsController, *commandBuffer.get(), cmd->firstIndex, cmd->elementCount);
768         }
769       }
770     }
771
772     // Command buffer contains Texture bindings, vertex bindings, index buffer binding, pipeline(vertex format)
773     Graphics::SubmitInfo submitInfo{{}, 0 | Graphics::SubmitFlagBits::FLUSH};
774     submitInfo.cmdBuffer.push_back(commandBuffer.get());
775     mGraphicsController->SubmitCommandBuffers(submitInfo);
776
777     mUpdated = false;
778   }
779 }
780
781 void Renderer::SetSortAttributes(BufferIndex                                             bufferIndex,
782                                  SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes) const
783 {
784   sortAttributes.shader   = &(mRenderDataProvider->GetShader());
785   sortAttributes.geometry = mGeometry;
786 }
787
788 void Renderer::SetShaderChanged(bool value)
789 {
790   mShaderChanged = value;
791 }
792
793 bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
794 {
795   if(mUpdated)
796   {
797     mUpdated = false;
798     return true;
799   }
800
801   if(mShaderChanged || mUpdateAttributeLocations || mGeometry->AttributesChanged())
802   {
803     return true;
804   }
805
806   for(const auto& texture : mRenderDataProvider->GetTextures())
807   {
808     if(texture && texture->IsNativeImage())
809     {
810       return true;
811     }
812   }
813
814   uint64_t                               hash           = 0xc70f6907UL;
815   const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap(bufferIndex);
816   for(const auto& uniformProperty : uniformMapNode)
817   {
818     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
819   }
820
821   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
822   const SceneGraph::CollectedUniformMap&    uniformMap             = uniformMapDataProvider.GetUniformMap(bufferIndex);
823   for(const auto& uniformProperty : uniformMap)
824   {
825     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
826   }
827
828   if(mUniformsHash != hash)
829   {
830     mUniformsHash = hash;
831     return true;
832   }
833
834   return false;
835 }
836
837 Graphics::UniquePtr<Graphics::Pipeline> Renderer::PrepareGraphicsPipeline(Program& program)
838 {
839   Graphics::InputAssemblyState inputAssemblyState{};
840   Graphics::VertexInputState   vertexInputState{};
841   uint32_t                     bindingIndex{0u};
842
843   if(mUpdateAttributeLocations || mGeometry->AttributesChanged())
844   {
845     mAttributeLocations.Clear();
846     mUpdateAttributeLocations = true;
847   }
848
849   uint32_t base = 0;
850   for(auto&& vertexBuffer : mGeometry->GetVertexBuffers())
851   {
852     const VertexBuffer::Format& vertexFormat = *vertexBuffer->GetFormat();
853
854     vertexInputState.bufferBindings.emplace_back(vertexFormat.size, // stride
855                                                  Graphics::VertexInputRate::PER_VERTEX);
856
857     const uint32_t attributeCount = vertexBuffer->GetAttributeCount();
858     for(uint32_t i = 0; i < attributeCount; ++i)
859     {
860       if(mUpdateAttributeLocations)
861       {
862         auto     attributeName = vertexBuffer->GetAttributeName(i);
863         uint32_t index         = program.RegisterCustomAttribute(attributeName);
864         int32_t  pLocation     = program.GetCustomAttributeLocation(index);
865         if(-1 == pLocation)
866         {
867           DALI_LOG_WARNING("Attribute not found in the shader: %s\n", attributeName.GetCString());
868         }
869         mAttributeLocations.PushBack(pLocation);
870       }
871
872       uint32_t location = static_cast<uint32_t>(mAttributeLocations[base + i]);
873
874       vertexInputState.attributes.emplace_back(location,
875                                                bindingIndex,
876                                                vertexFormat.components[i].offset,
877                                                GetPropertyVertexFormat(vertexFormat.components[i].type));
878     }
879     base += attributeCount;
880     ++bindingIndex;
881   }
882   mUpdateAttributeLocations = false;
883
884   // Get the topology
885   inputAssemblyState.SetTopology(mGeometry->GetTopology());
886
887   // Create a new pipeline
888   return mGraphicsController->CreatePipeline(
889     Graphics::PipelineCreateInfo()
890       .SetInputAssemblyState(&inputAssemblyState) // Passed as pointers - shallow copy will break. TOO C LIKE
891       .SetVertexInputState(&vertexInputState),
892     nullptr);
893 }
894
895 } // namespace Render
896
897 } // namespace Internal
898
899 } // namespace Dali