Create UBO for uniform buffer bindings
[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/graphics-api/graphics-program.h>
23 #include <dali/graphics-api/graphics-types.h>
24 #include <dali/internal/common/image-sampler.h>
25 #include <dali/internal/render/common/render-instruction.h>
26 #include <dali/internal/render/data-providers/node-data-provider.h>
27 #include <dali/internal/render/data-providers/uniform-map-data-provider.h>
28 #include <dali/internal/render/gl-resources/context.h>
29 #include <dali/internal/render/renderers/render-sampler.h>
30 #include <dali/internal/render/renderers/render-texture.h>
31 #include <dali/internal/render/renderers/render-vertex-buffer.h>
32 #include <dali/internal/render/renderers/shader-cache.h>
33 #include <dali/internal/render/shaders/program.h>
34 #include <dali/internal/render/shaders/scene-graph-shader.h>
35 #include <dali/internal/update/common/uniform-map.h>
36
37 namespace Dali
38 {
39 namespace Internal
40 {
41 namespace
42 {
43 // Size of uniform buffer page used when resizing
44 constexpr uint32_t UBO_PAGE_SIZE = 8192u;
45
46 // UBO allocation threshold below which the UBO will shrink
47 constexpr auto UBO_SHRINK_THRESHOLD = 0.75f;
48
49 /**
50  * Helper to set view and projection matrices once per program
51  * @param program to set the matrices to
52  * @param modelMatrix to set
53  * @param viewMatrix to set
54  * @param projectionMatrix to set
55  * @param modelViewMatrix to set
56  * @param modelViewProjectionMatrix to set
57  */
58 inline void SetMatrices(Program&      program,
59                         const Matrix& modelMatrix,
60                         const Matrix& viewMatrix,
61                         const Matrix& projectionMatrix,
62                         const Matrix& modelViewMatrix)
63 {
64   GLint loc = program.GetUniformLocation(Program::UNIFORM_MODEL_MATRIX);
65   if(Program::UNIFORM_UNKNOWN != loc)
66   {
67     program.SetUniformMatrix4fv(loc, 1, modelMatrix.AsFloat());
68   }
69   loc = program.GetUniformLocation(Program::UNIFORM_VIEW_MATRIX);
70   if(Program::UNIFORM_UNKNOWN != loc)
71   {
72     if(program.GetViewMatrix() != &viewMatrix)
73     {
74       program.SetViewMatrix(&viewMatrix);
75       program.SetUniformMatrix4fv(loc, 1, viewMatrix.AsFloat());
76     }
77   }
78   // set projection matrix if program has not yet received it this frame or if it is dirty
79   loc = program.GetUniformLocation(Program::UNIFORM_PROJECTION_MATRIX);
80   if(Program::UNIFORM_UNKNOWN != loc)
81   {
82     if(program.GetProjectionMatrix() != &projectionMatrix)
83     {
84       program.SetProjectionMatrix(&projectionMatrix);
85       program.SetUniformMatrix4fv(loc, 1, projectionMatrix.AsFloat());
86     }
87   }
88   loc = program.GetUniformLocation(Program::UNIFORM_MODELVIEW_MATRIX);
89   if(Program::UNIFORM_UNKNOWN != loc)
90   {
91     program.SetUniformMatrix4fv(loc, 1, modelViewMatrix.AsFloat());
92   }
93
94   loc = program.GetUniformLocation(Program::UNIFORM_MVP_MATRIX);
95   if(Program::UNIFORM_UNKNOWN != loc)
96   {
97     Matrix modelViewProjectionMatrix(false);
98     Matrix::Multiply(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix);
99     program.SetUniformMatrix4fv(loc, 1, modelViewProjectionMatrix.AsFloat());
100   }
101
102   loc = program.GetUniformLocation(Program::UNIFORM_NORMAL_MATRIX);
103   if(Program::UNIFORM_UNKNOWN != loc)
104   {
105     Matrix3 normalMatrix;
106     normalMatrix = modelViewMatrix;
107     normalMatrix.Invert();
108     normalMatrix.Transpose();
109     program.SetUniformMatrix3fv(loc, 1, normalMatrix.AsFloat());
110   }
111 }
112
113 // Helper to get the vertex input format
114 Dali::Graphics::VertexInputFormat GetPropertyVertexFormat(Property::Type propertyType)
115 {
116   Dali::Graphics::VertexInputFormat type{};
117
118   switch(propertyType)
119   {
120     case Property::NONE:
121     case Property::STRING:
122     case Property::ARRAY:
123     case Property::MAP:
124     case Property::EXTENTS:   // i4?
125     case Property::RECTANGLE: // i4/f4?
126     case Property::ROTATION:
127     {
128       type = Dali::Graphics::VertexInputFormat::UNDEFINED;
129       break;
130     }
131     case Property::BOOLEAN:
132     {
133       type = Dali::Graphics::VertexInputFormat::UNDEFINED; // type = GL_BYTE; @todo new type for this?
134       break;
135     }
136     case Property::INTEGER:
137     {
138       type = Dali::Graphics::VertexInputFormat::INTEGER; // (short)
139       break;
140     }
141     case Property::FLOAT:
142     {
143       type = Dali::Graphics::VertexInputFormat::FLOAT;
144       break;
145     }
146     case Property::VECTOR2:
147     {
148       type = Dali::Graphics::VertexInputFormat::FVECTOR2;
149       break;
150     }
151     case Property::VECTOR3:
152     {
153       type = Dali::Graphics::VertexInputFormat::FVECTOR3;
154       break;
155     }
156     case Property::VECTOR4:
157     {
158       type = Dali::Graphics::VertexInputFormat::FVECTOR4;
159       break;
160     }
161     case Property::MATRIX3:
162     {
163       type = Dali::Graphics::VertexInputFormat::FLOAT;
164       break;
165     }
166     case Property::MATRIX:
167     {
168       type = Dali::Graphics::VertexInputFormat::FLOAT;
169       break;
170     }
171   }
172
173   return type;
174 }
175
176 constexpr Graphics::CullMode ConvertCullFace(Dali::FaceCullingMode::Type mode)
177 {
178   switch(mode)
179   {
180     case Dali::FaceCullingMode::NONE:
181     {
182       return Graphics::CullMode::NONE;
183     }
184     case Dali::FaceCullingMode::FRONT:
185     {
186       return Graphics::CullMode::FRONT;
187     }
188     case Dali::FaceCullingMode::BACK:
189     {
190       return Graphics::CullMode::BACK;
191     }
192     case Dali::FaceCullingMode::FRONT_AND_BACK:
193     {
194       return Graphics::CullMode::FRONT_AND_BACK;
195     }
196   }
197   return Graphics::CullMode::NONE;
198 }
199
200 constexpr Graphics::BlendFactor ConvertBlendFactor(BlendFactor::Type blendFactor)
201 {
202   switch(blendFactor)
203   {
204     case BlendFactor::ZERO:
205       return Graphics::BlendFactor::ZERO;
206     case BlendFactor::ONE:
207       return Graphics::BlendFactor::ONE;
208     case BlendFactor::SRC_COLOR:
209       return Graphics::BlendFactor::SRC_COLOR;
210     case BlendFactor::ONE_MINUS_SRC_COLOR:
211       return Graphics::BlendFactor::ONE_MINUS_SRC_COLOR;
212     case BlendFactor::SRC_ALPHA:
213       return Graphics::BlendFactor::SRC_ALPHA;
214     case BlendFactor::ONE_MINUS_SRC_ALPHA:
215       return Graphics::BlendFactor::ONE_MINUS_SRC_ALPHA;
216     case BlendFactor::DST_ALPHA:
217       return Graphics::BlendFactor::DST_ALPHA;
218     case BlendFactor::ONE_MINUS_DST_ALPHA:
219       return Graphics::BlendFactor::ONE_MINUS_DST_ALPHA;
220     case BlendFactor::DST_COLOR:
221       return Graphics::BlendFactor::DST_COLOR;
222     case BlendFactor::ONE_MINUS_DST_COLOR:
223       return Graphics::BlendFactor::ONE_MINUS_DST_COLOR;
224     case BlendFactor::SRC_ALPHA_SATURATE:
225       return Graphics::BlendFactor::SRC_ALPHA_SATURATE;
226     case BlendFactor::CONSTANT_COLOR:
227       return Graphics::BlendFactor::CONSTANT_COLOR;
228     case BlendFactor::ONE_MINUS_CONSTANT_COLOR:
229       return Graphics::BlendFactor::ONE_MINUS_CONSTANT_COLOR;
230     case BlendFactor::CONSTANT_ALPHA:
231       return Graphics::BlendFactor::CONSTANT_ALPHA;
232     case BlendFactor::ONE_MINUS_CONSTANT_ALPHA:
233       return Graphics::BlendFactor::ONE_MINUS_CONSTANT_ALPHA;
234   }
235   return Graphics::BlendFactor{};
236 }
237
238 constexpr Graphics::BlendOp ConvertBlendEquation(DevelBlendEquation::Type blendEquation)
239 {
240   switch(blendEquation)
241   {
242     case DevelBlendEquation::ADD:
243       return Graphics::BlendOp::ADD;
244     case DevelBlendEquation::SUBTRACT:
245       return Graphics::BlendOp::SUBTRACT;
246     case DevelBlendEquation::REVERSE_SUBTRACT:
247       return Graphics::BlendOp::REVERSE_SUBTRACT;
248     case DevelBlendEquation::COLOR:
249     case DevelBlendEquation::COLOR_BURN:
250     case DevelBlendEquation::COLOR_DODGE:
251     case DevelBlendEquation::DARKEN:
252     case DevelBlendEquation::DIFFERENCE:
253     case DevelBlendEquation::EXCLUSION:
254     case DevelBlendEquation::HARD_LIGHT:
255     case DevelBlendEquation::HUE:
256     case DevelBlendEquation::LIGHTEN:
257     case DevelBlendEquation::LUMINOSITY:
258     case DevelBlendEquation::MAX:
259     case DevelBlendEquation::MIN:
260     case DevelBlendEquation::MULTIPLY:
261     case DevelBlendEquation::OVERLAY:
262     case DevelBlendEquation::SATURATION:
263     case DevelBlendEquation::SCREEN:
264     case DevelBlendEquation::SOFT_LIGHT:
265       return Graphics::BlendOp{};
266   }
267   return Graphics::BlendOp{};
268 }
269
270 /**
271  * Helper function to calculate the correct alignment of data for uniform buffers
272  * @param dataSize size of uniform buffer
273  * @return aligned offset of data
274  */
275 inline uint32_t GetUniformBufferDataAlignment(uint32_t dataSize)
276 {
277   return ((dataSize / 256u) + ((dataSize % 256u) ? 1u : 0u)) * 256u;
278 }
279
280 } // namespace
281
282 namespace Render
283 {
284 Renderer* Renderer::New(SceneGraph::RenderDataProvider* dataProvider,
285                         Render::Geometry*               geometry,
286                         uint32_t                        blendingBitmask,
287                         const Vector4&                  blendColor,
288                         FaceCullingMode::Type           faceCullingMode,
289                         bool                            preMultipliedAlphaEnabled,
290                         DepthWriteMode::Type            depthWriteMode,
291                         DepthTestMode::Type             depthTestMode,
292                         DepthFunction::Type             depthFunction,
293                         StencilParameters&              stencilParameters)
294 {
295   return new Renderer(dataProvider, geometry, blendingBitmask, blendColor, faceCullingMode, preMultipliedAlphaEnabled, depthWriteMode, depthTestMode, depthFunction, stencilParameters);
296 }
297
298 Renderer::Renderer(SceneGraph::RenderDataProvider* dataProvider,
299                    Render::Geometry*               geometry,
300                    uint32_t                        blendingBitmask,
301                    const Vector4&                  blendColor,
302                    FaceCullingMode::Type           faceCullingMode,
303                    bool                            preMultipliedAlphaEnabled,
304                    DepthWriteMode::Type            depthWriteMode,
305                    DepthTestMode::Type             depthTestMode,
306                    DepthFunction::Type             depthFunction,
307                    StencilParameters&              stencilParameters)
308 : mRenderDataProvider(dataProvider),
309   mContext(nullptr),
310   mGeometry(geometry),
311   mProgramCache(nullptr),
312   mUniformIndexMap(),
313   mAttributeLocations(),
314   mUniformsHash(),
315   mStencilParameters(stencilParameters),
316   mBlendingOptions(),
317   mIndexedDrawFirstElement(0),
318   mIndexedDrawElementsCount(0),
319   mDepthFunction(depthFunction),
320   mFaceCullingMode(faceCullingMode),
321   mDepthWriteMode(depthWriteMode),
322   mDepthTestMode(depthTestMode),
323   mUpdateAttributeLocations(true),
324   mPremultipledAlphaEnabled(preMultipliedAlphaEnabled),
325   mShaderChanged(false),
326   mUpdated(true)
327 {
328   if(blendingBitmask != 0u)
329   {
330     mBlendingOptions.SetBitmask(blendingBitmask);
331   }
332
333   mBlendingOptions.SetBlendColor(blendColor);
334 }
335
336 void Renderer::Initialize(Context& context, Graphics::Controller& graphicsController, ProgramCache& programCache, Render::ShaderCache& shaderCache, Render::UniformBufferManager& uniformBufferManager)
337 {
338   mContext              = &context;
339   mGraphicsController   = &graphicsController;
340   mProgramCache         = &programCache;
341   mShaderCache          = &shaderCache;
342   mUniformBufferManager = &uniformBufferManager;
343 }
344
345 Renderer::~Renderer() = default;
346
347 void Renderer::SetGeometry(Render::Geometry* geometry)
348 {
349   mGeometry                 = geometry;
350   mUpdateAttributeLocations = true;
351 }
352 void Renderer::SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size)
353 {
354   mDrawCommands.clear();
355   mDrawCommands.insert(mDrawCommands.end(), pDrawCommands, pDrawCommands + size);
356 }
357
358 void Renderer::GlContextDestroyed()
359 {
360   mGeometry->GlContextDestroyed();
361 }
362
363 void Renderer::GlCleanup()
364 {
365 }
366
367 void Renderer::BuildUniformIndexMap(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program)
368 {
369   // Check if the map has changed
370   DALI_ASSERT_DEBUG(mRenderDataProvider && "No Uniform map data provider available");
371
372   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
373
374   if(uniformMapDataProvider.GetUniformMapChanged(bufferIndex) ||
375      node.GetUniformMapChanged(bufferIndex) ||
376      mUniformIndexMap.Count() == 0 ||
377      mShaderChanged)
378   {
379     // Reset shader pointer
380     mShaderChanged = false;
381
382     const SceneGraph::CollectedUniformMap& uniformMap     = uniformMapDataProvider.GetUniformMap(bufferIndex);
383     const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap(bufferIndex);
384
385     uint32_t maxMaps = static_cast<uint32_t>(uniformMap.Count() + uniformMapNode.Count()); // 4,294,967,295 maps should be enough
386     mUniformIndexMap.Clear();                                                              // Clear contents, but keep memory if we don't change size
387     mUniformIndexMap.Resize(maxMaps);
388
389     uint32_t mapIndex = 0;
390     for(; mapIndex < uniformMap.Count(); ++mapIndex)
391     {
392       mUniformIndexMap[mapIndex].propertyValue          = uniformMap[mapIndex].propertyPtr;
393       mUniformIndexMap[mapIndex].uniformIndex           = program.RegisterUniform(uniformMap[mapIndex].uniformName);
394       mUniformIndexMap[mapIndex].uniformName            = uniformMap[mapIndex].uniformName;
395       mUniformIndexMap[mapIndex].uniformNameHash        = uniformMap[mapIndex].uniformNameHash;
396       mUniformIndexMap[mapIndex].uniformNameHashNoArray = uniformMap[mapIndex].uniformNameHashNoArray;
397       mUniformIndexMap[mapIndex].arrayIndex             = uniformMap[mapIndex].arrayIndex;
398     }
399
400     for(uint32_t nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count(); ++nodeMapIndex)
401     {
402       uint32_t uniformIndex = program.RegisterUniform(uniformMapNode[nodeMapIndex].uniformName);
403       bool     found(false);
404       for(uint32_t i = 0; i < uniformMap.Count(); ++i)
405       {
406         if(mUniformIndexMap[i].uniformIndex == uniformIndex)
407         {
408           mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr;
409           found                             = true;
410           break;
411         }
412       }
413
414       if(!found)
415       {
416         mUniformIndexMap[mapIndex].propertyValue          = uniformMapNode[nodeMapIndex].propertyPtr;
417         mUniformIndexMap[mapIndex].uniformName            = uniformMapNode[nodeMapIndex].uniformName;
418         mUniformIndexMap[mapIndex].uniformIndex           = uniformIndex;
419         mUniformIndexMap[mapIndex].uniformNameHash        = uniformMapNode[nodeMapIndex].uniformNameHash;
420         mUniformIndexMap[mapIndex].uniformNameHashNoArray = uniformMapNode[nodeMapIndex].uniformNameHashNoArray;
421         mUniformIndexMap[mapIndex].arrayIndex             = uniformMapNode[nodeMapIndex].arrayIndex;
422         ++mapIndex;
423       }
424     }
425
426     mUniformIndexMap.Resize(mapIndex);
427   }
428
429   // The code below is disabled because the uniforms should now be set in the graphics backend.
430
431   /*
432   // Set uniforms in local map
433   for(UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
434                                      end  = mUniformIndexMap.End();
435       iter != end;
436       ++iter)
437   {
438     SetUniformFromProperty(bufferIndex, program, *iter);
439   }
440
441   GLint sizeLoc = program.GetUniformLocation(Program::UNIFORM_SIZE);
442   if(-1 != sizeLoc)
443   {
444     program.SetSizeUniform3f(sizeLoc, size.x, size.y, size.z);
445   }
446 */
447 }
448
449 void Renderer::SetUniformFromProperty(BufferIndex bufferIndex, Program& program, UniformIndexMap& map)
450 {
451   GLint location = program.GetUniformLocation(map.uniformIndex);
452   if(Program::UNIFORM_UNKNOWN != location)
453   {
454     // switch based on property type to use correct GL uniform setter
455     switch(map.propertyValue->GetType())
456     {
457       case Property::INTEGER:
458       {
459         program.SetUniform1i(location, map.propertyValue->GetInteger(bufferIndex));
460         break;
461       }
462       case Property::FLOAT:
463       {
464         program.SetUniform1f(location, map.propertyValue->GetFloat(bufferIndex));
465         break;
466       }
467       case Property::VECTOR2:
468       {
469         Vector2 value(map.propertyValue->GetVector2(bufferIndex));
470         program.SetUniform2f(location, value.x, value.y);
471         break;
472       }
473
474       case Property::VECTOR3:
475       {
476         Vector3 value(map.propertyValue->GetVector3(bufferIndex));
477         program.SetUniform3f(location, value.x, value.y, value.z);
478         break;
479       }
480
481       case Property::VECTOR4:
482       {
483         Vector4 value(map.propertyValue->GetVector4(bufferIndex));
484         program.SetUniform4f(location, value.x, value.y, value.z, value.w);
485         break;
486       }
487
488       case Property::ROTATION:
489       {
490         Quaternion value(map.propertyValue->GetQuaternion(bufferIndex));
491         program.SetUniform4f(location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w);
492         break;
493       }
494
495       case Property::MATRIX:
496       {
497         const Matrix& value = map.propertyValue->GetMatrix(bufferIndex);
498         program.SetUniformMatrix4fv(location, 1, value.AsFloat());
499         break;
500       }
501
502       case Property::MATRIX3:
503       {
504         const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex);
505         program.SetUniformMatrix3fv(location, 1, value.AsFloat());
506         break;
507       }
508
509       default:
510       {
511         // Other property types are ignored
512         break;
513       }
514     }
515   }
516 }
517
518 bool Renderer::BindTextures(Program& program, Graphics::CommandBuffer& commandBuffer, Vector<Graphics::Texture*>& boundTextures)
519 {
520   uint32_t textureUnit = 0;
521
522   GLint                          uniformLocation(-1);
523   std::vector<Render::Sampler*>& samplers(mRenderDataProvider->GetSamplers());
524   std::vector<Render::Texture*>& textures(mRenderDataProvider->GetTextures());
525
526   std::vector<Graphics::TextureBinding> textureBindings;
527   for(uint32_t i = 0; i < static_cast<uint32_t>(textures.size()); ++i) // not expecting more than uint32_t of textures
528   {
529     if(textures[i] && textures[i]->GetGraphicsObject())
530     {
531       if(program.GetSamplerUniformLocation(i, uniformLocation))
532       {
533         // if the sampler exists,
534         //   if it's default, delete the graphics object
535         //   otherwise re-initialize it if dirty
536
537         const Graphics::Sampler* graphicsSampler = (samplers[i] ? samplers[i]->GetGraphicsObject()
538                                                                 : nullptr);
539
540         boundTextures.PushBack(textures[i]->GetGraphicsObject());
541         const Graphics::TextureBinding textureBinding{textures[i]->GetGraphicsObject(), graphicsSampler, textureUnit};
542         textureBindings.push_back(textureBinding);
543
544         program.SetUniform1i(uniformLocation, textureUnit); // Get through shader reflection
545         ++textureUnit;
546       }
547     }
548   }
549
550   if(textureBindings.size() > 0)
551   {
552     commandBuffer.BindTextures(textureBindings);
553   }
554
555   // @todo remove check from caller.
556   return true;
557 }
558
559 void Renderer::SetFaceCullingMode(FaceCullingMode::Type mode)
560 {
561   mFaceCullingMode = mode;
562   mUpdated         = true;
563 }
564
565 void Renderer::SetBlendingBitMask(uint32_t bitmask)
566 {
567   mBlendingOptions.SetBitmask(bitmask);
568   mUpdated = true;
569 }
570
571 void Renderer::SetBlendColor(const Vector4& color)
572 {
573   mBlendingOptions.SetBlendColor(color);
574   mUpdated = true;
575 }
576
577 void Renderer::SetIndexedDrawFirstElement(uint32_t firstElement)
578 {
579   mIndexedDrawFirstElement = firstElement;
580   mUpdated                 = true;
581 }
582
583 void Renderer::SetIndexedDrawElementsCount(uint32_t elementsCount)
584 {
585   mIndexedDrawElementsCount = elementsCount;
586   mUpdated                  = true;
587 }
588
589 void Renderer::EnablePreMultipliedAlpha(bool enable)
590 {
591   mPremultipledAlphaEnabled = enable;
592   mUpdated                  = true;
593 }
594
595 void Renderer::SetDepthWriteMode(DepthWriteMode::Type depthWriteMode)
596 {
597   mDepthWriteMode = depthWriteMode;
598   mUpdated        = true;
599 }
600
601 void Renderer::SetDepthTestMode(DepthTestMode::Type depthTestMode)
602 {
603   mDepthTestMode = depthTestMode;
604   mUpdated       = true;
605 }
606
607 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
608 {
609   return mDepthWriteMode;
610 }
611
612 DepthTestMode::Type Renderer::GetDepthTestMode() const
613 {
614   return mDepthTestMode;
615 }
616
617 void Renderer::SetDepthFunction(DepthFunction::Type depthFunction)
618 {
619   mDepthFunction = depthFunction;
620   mUpdated       = true;
621 }
622
623 DepthFunction::Type Renderer::GetDepthFunction() const
624 {
625   return mDepthFunction;
626 }
627
628 void Renderer::SetRenderMode(RenderMode::Type renderMode)
629 {
630   mStencilParameters.renderMode = renderMode;
631   mUpdated                      = true;
632 }
633
634 RenderMode::Type Renderer::GetRenderMode() const
635 {
636   return mStencilParameters.renderMode;
637 }
638
639 void Renderer::SetStencilFunction(StencilFunction::Type stencilFunction)
640 {
641   mStencilParameters.stencilFunction = stencilFunction;
642   mUpdated                           = true;
643 }
644
645 StencilFunction::Type Renderer::GetStencilFunction() const
646 {
647   return mStencilParameters.stencilFunction;
648 }
649
650 void Renderer::SetStencilFunctionMask(int stencilFunctionMask)
651 {
652   mStencilParameters.stencilFunctionMask = stencilFunctionMask;
653   mUpdated                               = true;
654 }
655
656 int Renderer::GetStencilFunctionMask() const
657 {
658   return mStencilParameters.stencilFunctionMask;
659 }
660
661 void Renderer::SetStencilFunctionReference(int stencilFunctionReference)
662 {
663   mStencilParameters.stencilFunctionReference = stencilFunctionReference;
664   mUpdated                                    = true;
665 }
666
667 int Renderer::GetStencilFunctionReference() const
668 {
669   return mStencilParameters.stencilFunctionReference;
670 }
671
672 void Renderer::SetStencilMask(int stencilMask)
673 {
674   mStencilParameters.stencilMask = stencilMask;
675   mUpdated                       = true;
676 }
677
678 int Renderer::GetStencilMask() const
679 {
680   return mStencilParameters.stencilMask;
681 }
682
683 void Renderer::SetStencilOperationOnFail(StencilOperation::Type stencilOperationOnFail)
684 {
685   mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
686   mUpdated                                  = true;
687 }
688
689 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
690 {
691   return mStencilParameters.stencilOperationOnFail;
692 }
693
694 void Renderer::SetStencilOperationOnZFail(StencilOperation::Type stencilOperationOnZFail)
695 {
696   mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
697   mUpdated                                   = true;
698 }
699
700 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
701 {
702   return mStencilParameters.stencilOperationOnZFail;
703 }
704
705 void Renderer::SetStencilOperationOnZPass(StencilOperation::Type stencilOperationOnZPass)
706 {
707   mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
708   mUpdated                                   = true;
709 }
710
711 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
712 {
713   return mStencilParameters.stencilOperationOnZPass;
714 }
715
716 void Renderer::Upload()
717 {
718   mGeometry->Upload(*mGraphicsController);
719 }
720
721 void Renderer::Render(Context&                                             context,
722                       BufferIndex                                          bufferIndex,
723                       const SceneGraph::NodeDataProvider&                  node,
724                       const Matrix&                                        modelMatrix,
725                       const Matrix&                                        modelViewMatrix,
726                       const Matrix&                                        viewMatrix,
727                       const Matrix&                                        projectionMatrix,
728                       const Vector3&                                       size,
729                       bool                                                 blend,
730                       Vector<Graphics::Texture*>&                          boundTextures,
731                       const Dali::Internal::SceneGraph::RenderInstruction& instruction,
732                       uint32_t                                             queueIndex)
733 {
734   // Before doing anything test if the call happens in the right queue
735   if(mDrawCommands.empty() && queueIndex > 0)
736   {
737     return;
738   }
739
740   // Prepare commands
741   std::vector<DevelRenderer::DrawCommand*> commands;
742   for(auto& cmd : mDrawCommands)
743   {
744     if(cmd.queue == queueIndex)
745     {
746       commands.emplace_back(&cmd);
747     }
748   }
749
750   // Have commands but nothing to be drawn - abort
751   if(!mDrawCommands.empty() && commands.empty())
752   {
753     return;
754   }
755
756   Graphics::UniquePtr<Graphics::CommandBuffer> commandBuffer = mGraphicsController->CreateCommandBuffer(
757     Graphics::CommandBufferCreateInfo()
758       .SetLevel(Graphics::CommandBufferLevel::SECONDARY),
759     nullptr);
760
761   //Set blending mode
762   if(!mDrawCommands.empty())
763   {
764     blend = (commands[0]->queue == DevelRenderer::RENDER_QUEUE_OPAQUE ? false : blend);
765   }
766
767   // Create Shader.
768   // Really, need to have a pipeline cache in implementation.
769   // Get the program to use
770   // The program cache owns the Program object so we don't need to worry about this raw allocation here.
771   ShaderDataPtr shaderData = mRenderDataProvider->GetShader().GetShaderData();
772
773   Dali::Graphics::Shader& vertexShader = mShaderCache->GetShader(
774     shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::VERTEX_SHADER),
775     Graphics::PipelineStage::VERTEX_SHADER,
776     shaderData->GetSourceMode());
777
778   Dali::Graphics::Shader& fragmentShader = mShaderCache->GetShader(
779     shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER),
780     Graphics::PipelineStage::FRAGMENT_SHADER,
781     shaderData->GetSourceMode());
782
783   std::vector<Graphics::ShaderState> shaderStates{
784     Graphics::ShaderState()
785       .SetShader(vertexShader)
786       .SetPipelineStage(Graphics::PipelineStage::VERTEX_SHADER),
787     Graphics::ShaderState()
788       .SetShader(fragmentShader)
789       .SetPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER)};
790
791   auto createInfo = Graphics::ProgramCreateInfo();
792   createInfo.SetShaderState(shaderStates);
793
794   auto     graphicsProgram = mGraphicsController->CreateProgram(createInfo, nullptr);
795   Program* program         = Program::New(*mProgramCache,
796                                   shaderData,
797                                   *mGraphicsController,
798                                   std::move(graphicsProgram),
799                                   (shaderData->GetHints() & Dali::Shader::Hint::MODIFIES_GEOMETRY) != 0x0);
800
801   if(!program)
802   {
803     DALI_LOG_ERROR("Failed to get program for shader at address %p.\n", reinterpret_cast<void*>(&mRenderDataProvider->GetShader()));
804     return;
805   }
806
807   // Temporarily create a pipeline here - this will be used for transporting
808   // topology, vertex format, attrs, rasterization state
809   mGraphicsPipeline = PrepareGraphicsPipeline(*program, instruction, blend, std::move(mGraphicsPipeline));
810
811   commandBuffer->BindPipeline(*mGraphicsPipeline.get());
812
813   if(DALI_LIKELY(BindTextures(*program, *commandBuffer.get(), boundTextures)))
814   {
815     // Only set up and draw if we have textures and they are all valid
816
817     // The code below is disabled because the uniforms should now be set in the graphics backend.
818
819     /*
820     // set projection and view matrix if program has not yet received them yet this frame
821     SetMatrices(*program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix);
822
823     // set color uniform
824     GLint loc = program->GetUniformLocation(Program::UNIFORM_COLOR);
825     if(Program::UNIFORM_UNKNOWN != loc)
826     {
827       const Vector4& color = node.GetRenderColor(bufferIndex);
828       if(mPremultipledAlphaEnabled)
829       {
830         float alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex);
831         program->SetUniform4f(loc, color.r * alpha, color.g * alpha, color.b * alpha, alpha);
832       }
833       else
834       {
835         program->SetUniform4f(loc, color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex));
836       }
837     }
838 */
839
840     BuildUniformIndexMap(bufferIndex, node, size, *program);
841
842     // Create the UBO
843     uint32_t uniformBlockAllocationBytes{0u};
844     uint32_t uniformBlockMaxSize{0u};
845     uint32_t uboOffset{0u};
846
847     auto& reflection = mGraphicsController->GetProgramReflection(program->GetGraphicsProgram());
848     for(auto i = 0u; i < reflection.GetUniformBlockCount(); ++i)
849     {
850       auto blockSize = GetUniformBufferDataAlignment(reflection.GetUniformBlockSize(i));
851       if(uniformBlockMaxSize < blockSize)
852       {
853         uniformBlockMaxSize = blockSize;
854       }
855       uniformBlockAllocationBytes += blockSize;
856     }
857
858     auto pagedAllocation = ((uniformBlockAllocationBytes / UBO_PAGE_SIZE + 1u)) * UBO_PAGE_SIZE;
859
860     // Allocate twice memory as required by the uniform buffers
861     // todo: memory usage backlog to use optimal allocation
862     if(uniformBlockAllocationBytes && !mUniformBuffer[bufferIndex])
863     {
864       mUniformBuffer[bufferIndex] = std::move(mUniformBufferManager->AllocateUniformBuffer(pagedAllocation));
865     }
866     else if(uniformBlockAllocationBytes && (mUniformBuffer[bufferIndex]->GetSize() < pagedAllocation ||
867                                             (pagedAllocation < uint32_t(float(mUniformBuffer[bufferIndex]->GetSize()) * UBO_SHRINK_THRESHOLD))))
868     {
869       mUniformBuffer[bufferIndex]->Reserve(pagedAllocation);
870     }
871
872     // Clear UBO
873     if(mUniformBuffer[bufferIndex])
874     {
875       mUniformBuffer[bufferIndex]->Fill(0, 0u, 0u);
876     }
877
878     // update the uniform buffer
879     // pass shared UBO and offset, return new offset for next item to be used
880     // don't process bindings if there are no uniform buffers allocated
881     auto ubo = mUniformBuffer[bufferIndex].get();
882     if(ubo)
883     {
884       std::vector<Graphics::UniformBufferBinding>* bindings{nullptr};
885       FillUniformBuffers(*program, instruction, *ubo, bindings, uboOffset, bufferIndex);
886
887       Vector4        finalColor;
888       const Vector4& color = node.GetRenderColor(bufferIndex);
889       if(mPremultipledAlphaEnabled)
890       {
891         float alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex);
892         finalColor  = Vector4(color.r * alpha, color.g * alpha, color.b * alpha, alpha);
893       }
894       else
895       {
896         finalColor = Vector4(color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex));
897       }
898
899       // We know bindings for this renderer, so we can use 'offset' and write additional uniforms
900       Matrix modelViewProjectionMatrix(false);
901       Matrix::Multiply(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix);
902
903       WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_MATRIX), *ubo, *bindings, modelMatrix);
904       WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::VIEW_MATRIX), *ubo, *bindings, viewMatrix);
905       WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::PROJECTION_MATRIX), *ubo, *bindings, projectionMatrix);
906       WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MVP_MATRIX), *ubo, *bindings, modelViewProjectionMatrix);
907       WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_VIEW_MATRIX), *ubo, *bindings, modelViewMatrix);
908       WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::SIZE), *ubo, *bindings, size);
909       WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::COLOR), *ubo, *bindings, finalColor);
910
911       // Update normal matrix only when used in the shader
912       Matrix3 normalMatrix(modelViewMatrix);
913       normalMatrix.Invert();
914       normalMatrix.Transpose();
915       WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::NORMAL_MATRIX), *ubo, *bindings, normalMatrix);
916
917       commandBuffer->BindUniformBuffers(*bindings);
918     }
919
920     bool drawn = false; // Draw can fail if there are no vertex buffers or they haven't been uploaded yet
921                         // @todo We should detect this case much earlier to prevent unnecessary work
922
923     //@todo manage mDrawCommands in the same way as above command buffer?!
924     if(mDrawCommands.empty())
925     {
926       drawn = mGeometry->Draw(*mGraphicsController, *commandBuffer.get(), mIndexedDrawFirstElement, mIndexedDrawElementsCount);
927     }
928     else
929     {
930       for(auto& cmd : commands)
931       {
932         // @todo This should generate a command buffer per cmd
933         // Tests WILL fail. (Temporarily commented out)
934         mGeometry->Draw(*mGraphicsController, *commandBuffer.get(), cmd->firstIndex, cmd->elementCount);
935       }
936     }
937
938     // Command buffer contains Texture bindings, vertex bindings, index buffer binding, pipeline(vertex format)
939     // @todo We should return the command buffer(s) and let the calling method submit
940     // If not drawn, then don't add command buffer to submit info, and if empty, don't
941     // submit.
942     if(drawn)
943     {
944       Graphics::SubmitInfo submitInfo{{}, 0 | Graphics::SubmitFlagBits::FLUSH};
945       submitInfo.cmdBuffer.push_back(commandBuffer.get());
946       mGraphicsController->SubmitCommandBuffers(submitInfo);
947     }
948
949     mUpdated = false;
950   }
951 }
952
953 template<class T>
954 bool Renderer::WriteDefaultUniform(const Graphics::UniformInfo* uniformInfo, Render::UniformBuffer& ubo, const std::vector<Graphics::UniformBufferBinding>& bindings, const T& data)
955 {
956   if(uniformInfo)
957   {
958     WriteUniform(ubo, bindings, *uniformInfo, data);
959     return true;
960   }
961   return false;
962 }
963
964 template<class T>
965 void Renderer::WriteUniform(Render::UniformBuffer& ubo, const std::vector<Graphics::UniformBufferBinding>& bindings, const Graphics::UniformInfo& uniformInfo, const T& data)
966 {
967   WriteUniform(ubo, bindings, uniformInfo, &data, sizeof(T));
968 }
969
970 void Renderer::WriteUniform(Render::UniformBuffer& ubo, const std::vector<Graphics::UniformBufferBinding>& bindings, const Graphics::UniformInfo& uniformInfo, const void* data, uint32_t size)
971 {
972   ubo.Write(data, size, bindings[uniformInfo.bufferIndex].offset + uniformInfo.offset);
973 }
974
975 void Renderer::FillUniformBuffers(Program&                                      program,
976                                   const SceneGraph::RenderInstruction&          instruction,
977                                   Render::UniformBuffer&                        ubo,
978                                   std::vector<Graphics::UniformBufferBinding>*& outBindings,
979                                   uint32_t&                                     offset,
980                                   BufferIndex                                   updateBufferIndex)
981 {
982   auto& reflection = mGraphicsController->GetProgramReflection(program.GetGraphicsProgram());
983   auto  uboCount   = reflection.GetUniformBlockCount();
984
985   mUniformBufferBindings.resize(uboCount);
986
987   // Setup bindings
988   uint32_t dataOffset = offset;
989   for(auto i = 0u; i < uboCount; ++i)
990   {
991     mUniformBufferBindings[i].dataSize = reflection.GetUniformBlockSize(i);
992     mUniformBufferBindings[i].binding  = reflection.GetUniformBlockBinding(i);
993     mUniformBufferBindings[i].offset   = dataOffset;
994
995     dataOffset += GetUniformBufferDataAlignment(mUniformBufferBindings[i].dataSize);
996     mUniformBufferBindings[i].buffer = ubo.GetBuffer();
997
998     for(UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
999                                        end  = mUniformIndexMap.End();
1000         iter != end;
1001         ++iter)
1002     {
1003       // @todo This means parsing the uniform string every frame. Instead, store the array index if present.
1004       int arrayIndex = (*iter).arrayIndex;
1005
1006       auto uniformInfo  = Graphics::UniformInfo{};
1007       auto uniformFound = program.GetUniform((*iter).uniformName.GetCString(),
1008                                              (*iter).uniformNameHashNoArray ? (*iter).uniformNameHashNoArray : (*iter).uniformNameHash,
1009                                              uniformInfo);
1010
1011       if(uniformFound)
1012       {
1013         auto dst = mUniformBufferBindings[uniformInfo.bufferIndex].offset + uniformInfo.offset;
1014
1015         switch((*iter).propertyValue->GetType())
1016         {
1017           case Property::Type::FLOAT:
1018           case Property::Type::INTEGER:
1019           case Property::Type::BOOLEAN:
1020           {
1021             ubo.Write(&(*iter).propertyValue->GetFloat(updateBufferIndex),
1022                       sizeof(float),
1023                       dst + static_cast<uint32_t>(sizeof(Vector4)) * arrayIndex);
1024             break;
1025           }
1026           case Property::Type::VECTOR2:
1027           {
1028             ubo.Write(&(*iter).propertyValue->GetVector2(updateBufferIndex),
1029                       sizeof(Vector2),
1030                       dst + static_cast<uint32_t>(sizeof(Vector4)) * arrayIndex);
1031             break;
1032           }
1033           case Property::Type::VECTOR3:
1034           {
1035             ubo.Write(&(*iter).propertyValue->GetVector3(updateBufferIndex),
1036                       sizeof(Vector3),
1037                       dst + static_cast<uint32_t>(sizeof(Vector4)) * arrayIndex);
1038             break;
1039           }
1040           case Property::Type::VECTOR4:
1041           {
1042             ubo.Write(&(*iter).propertyValue->GetVector4(updateBufferIndex),
1043                       sizeof(Vector4),
1044                       dst + static_cast<uint32_t>(sizeof(Vector4)) * arrayIndex);
1045             break;
1046           }
1047           case Property::Type::MATRIX:
1048           {
1049             ubo.Write(&(*iter).propertyValue->GetMatrix(updateBufferIndex),
1050                       sizeof(Matrix),
1051                       dst + static_cast<uint32_t>(sizeof(Matrix)) * arrayIndex);
1052             break;
1053           }
1054           case Property::Type::MATRIX3:
1055           {
1056             const auto& matrix = &(*iter).propertyValue->GetMatrix3(updateBufferIndex);
1057             for(int i = 0; i < 3; ++i)
1058             {
1059               ubo.Write(&matrix->AsFloat()[i * 3],
1060                         sizeof(float) * 3,
1061                         dst + (i * static_cast<uint32_t>(sizeof(Vector4))));
1062             }
1063             break;
1064           }
1065           default:
1066           {
1067           }
1068         }
1069       }
1070     }
1071   }
1072   // write output bindings
1073   outBindings = &mUniformBufferBindings;
1074
1075   // Update offset
1076   offset = dataOffset;
1077 }
1078
1079 void Renderer::SetSortAttributes(BufferIndex                                             bufferIndex,
1080                                  SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes) const
1081 {
1082   sortAttributes.shader   = &(mRenderDataProvider->GetShader());
1083   sortAttributes.geometry = mGeometry;
1084 }
1085
1086 void Renderer::SetShaderChanged(bool value)
1087 {
1088   mShaderChanged = value;
1089 }
1090
1091 bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
1092 {
1093   if(mUpdated)
1094   {
1095     mUpdated = false;
1096     return true;
1097   }
1098
1099   if(mShaderChanged || mUpdateAttributeLocations || mGeometry->AttributesChanged())
1100   {
1101     return true;
1102   }
1103
1104   for(const auto& texture : mRenderDataProvider->GetTextures())
1105   {
1106     if(texture && texture->IsNativeImage())
1107     {
1108       return true;
1109     }
1110   }
1111
1112   uint64_t                               hash           = 0xc70f6907UL;
1113   const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap(bufferIndex);
1114   for(const auto& uniformProperty : uniformMapNode)
1115   {
1116     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
1117   }
1118
1119   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
1120   const SceneGraph::CollectedUniformMap&    uniformMap             = uniformMapDataProvider.GetUniformMap(bufferIndex);
1121   for(const auto& uniformProperty : uniformMap)
1122   {
1123     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
1124   }
1125
1126   if(mUniformsHash != hash)
1127   {
1128     mUniformsHash = hash;
1129     return true;
1130   }
1131
1132   return false;
1133 }
1134
1135 Graphics::UniquePtr<Graphics::Pipeline> Renderer::PrepareGraphicsPipeline(
1136   Program&                                             program,
1137   const Dali::Internal::SceneGraph::RenderInstruction& instruction,
1138   bool                                                 blend,
1139   Graphics::UniquePtr<Graphics::Pipeline>&&            oldPipeline)
1140 {
1141   Graphics::InputAssemblyState inputAssemblyState{};
1142   Graphics::VertexInputState   vertexInputState{};
1143   Graphics::ProgramState       programState{};
1144   uint32_t                     bindingIndex{0u};
1145
1146   if(mUpdateAttributeLocations || mGeometry->AttributesChanged())
1147   {
1148     mAttributeLocations.Clear();
1149     mUpdateAttributeLocations = true;
1150   }
1151
1152   auto& reflection = mGraphicsController->GetProgramReflection(program.GetGraphicsProgram());
1153
1154   /**
1155    * Bind Attributes
1156    */
1157   uint32_t base = 0;
1158   for(auto&& vertexBuffer : mGeometry->GetVertexBuffers())
1159   {
1160     const VertexBuffer::Format& vertexFormat = *vertexBuffer->GetFormat();
1161
1162     vertexInputState.bufferBindings.emplace_back(vertexFormat.size, // stride
1163                                                  Graphics::VertexInputRate::PER_VERTEX);
1164
1165     const uint32_t attributeCount = vertexBuffer->GetAttributeCount();
1166     for(uint32_t i = 0; i < attributeCount; ++i)
1167     {
1168       if(mUpdateAttributeLocations)
1169       {
1170         auto    attributeName = vertexBuffer->GetAttributeName(i);
1171         int32_t pLocation     = reflection.GetVertexAttributeLocation(std::string(attributeName.GetStringView()));
1172         if(-1 == pLocation)
1173         {
1174           DALI_LOG_WARNING("Attribute not found in the shader: %s\n", attributeName.GetCString());
1175         }
1176         mAttributeLocations.PushBack(pLocation);
1177       }
1178
1179       uint32_t location = static_cast<uint32_t>(mAttributeLocations[base + i]);
1180
1181       vertexInputState.attributes.emplace_back(location,
1182                                                bindingIndex,
1183                                                vertexFormat.components[i].offset,
1184                                                GetPropertyVertexFormat(vertexFormat.components[i].type));
1185     }
1186     base += attributeCount;
1187     ++bindingIndex;
1188   }
1189   mUpdateAttributeLocations = false;
1190
1191   // Get the topology
1192   inputAssemblyState.SetTopology(mGeometry->GetTopology());
1193
1194   // Get the program
1195   programState.SetProgram(program.GetGraphicsProgram());
1196
1197   Graphics::RasterizationState rasterizationState{};
1198
1199   //Set cull face  mode
1200   const Dali::Internal::SceneGraph::Camera* cam = instruction.GetCamera();
1201   if(cam->GetReflectionUsed())
1202   {
1203     auto adjFaceCullingMode = mFaceCullingMode;
1204     switch(mFaceCullingMode)
1205     {
1206       case FaceCullingMode::Type::FRONT:
1207       {
1208         adjFaceCullingMode = FaceCullingMode::Type::BACK;
1209         break;
1210       }
1211       case FaceCullingMode::Type::BACK:
1212       {
1213         adjFaceCullingMode = FaceCullingMode::Type::FRONT;
1214         break;
1215       }
1216       default:
1217       {
1218         // nothing to do, leave culling as it is
1219       }
1220     }
1221     rasterizationState.SetCullMode(ConvertCullFace(adjFaceCullingMode));
1222   }
1223   else
1224   {
1225     rasterizationState.SetCullMode(ConvertCullFace(mFaceCullingMode));
1226   }
1227
1228   rasterizationState.SetFrontFace(Graphics::FrontFace::COUNTER_CLOCKWISE);
1229
1230   /**
1231    * Set Polygon mode
1232    */
1233   switch(mGeometry->GetTopology())
1234   {
1235     case Graphics::PrimitiveTopology::TRIANGLE_LIST:
1236     case Graphics::PrimitiveTopology::TRIANGLE_STRIP:
1237     case Graphics::PrimitiveTopology::TRIANGLE_FAN:
1238       rasterizationState.SetPolygonMode(Graphics::PolygonMode::FILL);
1239       break;
1240     case Graphics::PrimitiveTopology::LINE_LIST:
1241     case Graphics::PrimitiveTopology::LINE_LOOP:
1242     case Graphics::PrimitiveTopology::LINE_STRIP:
1243       rasterizationState.SetPolygonMode(Graphics::PolygonMode::LINE);
1244       break;
1245     case Graphics::PrimitiveTopology::POINT_LIST:
1246       rasterizationState.SetPolygonMode(Graphics::PolygonMode::POINT);
1247       break;
1248   }
1249
1250   // @todo How to signal a blend barrier is needed?
1251   //if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled)
1252   //{
1253   //  context.BlendBarrier();
1254   //}
1255
1256   Graphics::ColorBlendState colorBlendState{};
1257   colorBlendState.SetBlendEnable(false);
1258
1259   if(blend)
1260   {
1261     colorBlendState.SetBlendEnable(true);
1262
1263     Graphics::BlendOp rgbOp   = ConvertBlendEquation(mBlendingOptions.GetBlendEquationRgb());
1264     Graphics::BlendOp alphaOp = ConvertBlendEquation(mBlendingOptions.GetBlendEquationRgb());
1265     if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled)
1266     {
1267       if(rgbOp != alphaOp)
1268       {
1269         DALI_LOG_ERROR("Advanced Blend Equation MUST be applied by using BlendEquation.\n");
1270         alphaOp = rgbOp;
1271       }
1272     }
1273
1274     colorBlendState
1275       .SetSrcColorBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendSrcFactorRgb()))
1276       .SetSrcAlphaBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendSrcFactorAlpha()))
1277       .SetDstColorBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendDestFactorRgb()))
1278       .SetDstAlphaBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendDestFactorAlpha()))
1279       .SetColorBlendOp(rgbOp)
1280       .SetAlphaBlendOp(alphaOp);
1281
1282     // Blend color is optional and rarely used
1283     Vector4* blendColor = const_cast<Vector4*>(mBlendingOptions.GetBlendColor());
1284     if(blendColor)
1285     {
1286       colorBlendState.SetBlendConstants(blendColor->AsFloat());
1287     }
1288   }
1289
1290   // Take the program into use so we can send uniforms to it
1291   // @todo Remove this call entirely!
1292   program.Use();
1293
1294   mUpdated = true;
1295
1296   // Create a new pipeline
1297   return mGraphicsController->CreatePipeline(
1298     Graphics::PipelineCreateInfo()
1299       .SetInputAssemblyState(&inputAssemblyState) // Passed as pointers - shallow copy will break. TOO C LIKE
1300       .SetVertexInputState(&vertexInputState)
1301       .SetRasterizationState(&rasterizationState)
1302       .SetColorBlendState(&colorBlendState)
1303       .SetProgramState(&programState)
1304       .SetNextExtension(&mLegacyProgram),
1305     std::move(oldPipeline));
1306 }
1307
1308 } // namespace Render
1309
1310 } // namespace Internal
1311
1312 } // namespace Dali