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