Bugfix: Gfx program discarded while DALi ProgramCache still holds to the GL resource
[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   Graphics::UniquePtr<Graphics::CommandBuffer> commandBuffer = mGraphicsController->CreateCommandBuffer(
727     Graphics::CommandBufferCreateInfo()
728       .SetLevel(Graphics::CommandBufferLevel::SECONDARY),
729     nullptr);
730
731   //Set blending mode
732   if(!mDrawCommands.empty())
733   {
734     blend = (commands[0]->queue == DevelRenderer::RENDER_QUEUE_OPAQUE ? false : blend);
735   }
736
737   // Create Shader.
738   // Really, need to have a pipeline cache in implementation.
739   // Get the program to use
740   // The program cache owns the Program object so we don't need to worry about this raw allocation here.
741   ShaderDataPtr shaderData = mRenderDataProvider->GetShader().GetShaderData();
742
743   Dali::Graphics::Shader& vertexShader = mShaderCache->GetShader(
744     shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::VERTEX_SHADER),
745     Graphics::PipelineStage::VERTEX_SHADER,
746     shaderData->GetSourceMode());
747
748   Dali::Graphics::Shader& fragmentShader = mShaderCache->GetShader(
749     shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER),
750     Graphics::PipelineStage::FRAGMENT_SHADER,
751     shaderData->GetSourceMode());
752
753   std::vector<Graphics::ShaderState> shaderStates{
754     Graphics::ShaderState()
755       .SetShader(vertexShader)
756       .SetPipelineStage(Graphics::PipelineStage::VERTEX_SHADER),
757     Graphics::ShaderState()
758       .SetShader(fragmentShader)
759       .SetPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER)};
760
761   auto createInfo = Graphics::ProgramCreateInfo();
762   createInfo.SetShaderState(shaderStates);
763
764   auto graphicsProgram = mGraphicsController->CreateProgram(createInfo, nullptr);
765   Program* program = Program::New(*mProgramCache,
766                                   shaderData,
767                                   *mGraphicsController,
768                                   std::move(graphicsProgram),
769                                   (shaderData->GetHints() & Dali::Shader::Hint::MODIFIES_GEOMETRY) != 0x0);
770
771   if(!program)
772   {
773     DALI_LOG_ERROR("Failed to get program for shader at address %p.\n", reinterpret_cast<void*>(&mRenderDataProvider->GetShader()));
774     return;
775   }
776
777   // Temporarily create a pipeline here - this will be used for transporting
778   // topology, vertex format, attrs, rasterization state
779   mGraphicsPipeline = PrepareGraphicsPipeline(*program, instruction, blend, std::move(mGraphicsPipeline));
780
781   commandBuffer->BindPipeline(*mGraphicsPipeline.get());
782
783   if(DALI_LIKELY(BindTextures(*program, *commandBuffer.get(), boundTextures)))
784   {
785     // Only set up and draw if we have textures and they are all valid
786
787     // set projection and view matrix if program has not yet received them yet this frame
788     SetMatrices(*program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix);
789
790     // set color uniform
791     GLint loc = program->GetUniformLocation(Program::UNIFORM_COLOR);
792     if(Program::UNIFORM_UNKNOWN != loc)
793     {
794       const Vector4& color = node.GetRenderColor(bufferIndex);
795       if(mPremultipledAlphaEnabled)
796       {
797         float alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex);
798         program->SetUniform4f(loc, color.r * alpha, color.g * alpha, color.b * alpha, alpha);
799       }
800       else
801       {
802         program->SetUniform4f(loc, color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex));
803       }
804     }
805
806     SetUniforms(bufferIndex, node, size, *program);
807
808     bool drawn = false; // Draw can fail if there are no vertex buffers or they haven't been uploaded yet
809                         // @todo We should detect this case much earlier to prevent unnecessary work
810
811     //@todo manage mDrawCommands in the same way as above command buffer?!
812     if(mDrawCommands.empty())
813     {
814       drawn = mGeometry->Draw(*mGraphicsController, *commandBuffer.get(), mIndexedDrawFirstElement, mIndexedDrawElementsCount);
815     }
816     else
817     {
818       for(auto& cmd : commands)
819       {
820         // @todo This should generate a command buffer per cmd
821         // Tests WILL fail. (Temporarily commented out)
822         mGeometry->Draw(*mGraphicsController, *commandBuffer.get(), cmd->firstIndex, cmd->elementCount);
823       }
824     }
825
826     // Command buffer contains Texture bindings, vertex bindings, index buffer binding, pipeline(vertex format)
827     // @todo We should return the command buffer(s) and let the calling method submit
828     // If not drawn, then don't add command buffer to submit info, and if empty, don't
829     // submit.
830     if(drawn)
831     {
832       Graphics::SubmitInfo submitInfo{{}, 0 | Graphics::SubmitFlagBits::FLUSH};
833       submitInfo.cmdBuffer.push_back(commandBuffer.get());
834       mGraphicsController->SubmitCommandBuffers(submitInfo);
835     }
836
837     mUpdated = false;
838   }
839 }
840
841 void Renderer::SetSortAttributes(BufferIndex                                             bufferIndex,
842                                  SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes) const
843 {
844   sortAttributes.shader   = &(mRenderDataProvider->GetShader());
845   sortAttributes.geometry = mGeometry;
846 }
847
848 void Renderer::SetShaderChanged(bool value)
849 {
850   mShaderChanged = value;
851 }
852
853 bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
854 {
855   if(mUpdated)
856   {
857     mUpdated = false;
858     return true;
859   }
860
861   if(mShaderChanged || mUpdateAttributeLocations || mGeometry->AttributesChanged())
862   {
863     return true;
864   }
865
866   for(const auto& texture : mRenderDataProvider->GetTextures())
867   {
868     if(texture && texture->IsNativeImage())
869     {
870       return true;
871     }
872   }
873
874   uint64_t                               hash           = 0xc70f6907UL;
875   const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap(bufferIndex);
876   for(const auto& uniformProperty : uniformMapNode)
877   {
878     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
879   }
880
881   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
882   const SceneGraph::CollectedUniformMap&    uniformMap             = uniformMapDataProvider.GetUniformMap(bufferIndex);
883   for(const auto& uniformProperty : uniformMap)
884   {
885     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
886   }
887
888   if(mUniformsHash != hash)
889   {
890     mUniformsHash = hash;
891     return true;
892   }
893
894   return false;
895 }
896
897 Graphics::UniquePtr<Graphics::Pipeline> Renderer::PrepareGraphicsPipeline(
898   Program&                                             program,
899   const Dali::Internal::SceneGraph::RenderInstruction& instruction,
900   bool                                                 blend,
901   Graphics::UniquePtr<Graphics::Pipeline>&&            oldPipeline)
902 {
903   Graphics::InputAssemblyState inputAssemblyState{};
904   Graphics::VertexInputState   vertexInputState{};
905   Graphics::ProgramState       programState{};
906   uint32_t                     bindingIndex{0u};
907
908   if(mUpdateAttributeLocations || mGeometry->AttributesChanged())
909   {
910     mAttributeLocations.Clear();
911     mUpdateAttributeLocations = true;
912   }
913
914   auto& reflection = mGraphicsController->GetProgramReflection(program.GetGraphicsProgram());
915
916   /**
917    * Bind Attributes
918    */
919   uint32_t base = 0;
920   for(auto&& vertexBuffer : mGeometry->GetVertexBuffers())
921   {
922     const VertexBuffer::Format& vertexFormat = *vertexBuffer->GetFormat();
923
924     vertexInputState.bufferBindings.emplace_back(vertexFormat.size, // stride
925                                                  Graphics::VertexInputRate::PER_VERTEX);
926
927     const uint32_t attributeCount = vertexBuffer->GetAttributeCount();
928     for(uint32_t i = 0; i < attributeCount; ++i)
929     {
930       if(mUpdateAttributeLocations)
931       {
932         auto    attributeName = vertexBuffer->GetAttributeName(i);
933         int32_t pLocation     = reflection.GetVertexAttributeLocation(std::string(attributeName.GetStringView()));
934         if(-1 == pLocation)
935         {
936           DALI_LOG_WARNING("Attribute not found in the shader: %s\n", attributeName.GetCString());
937         }
938         mAttributeLocations.PushBack(pLocation);
939       }
940
941       uint32_t location = static_cast<uint32_t>(mAttributeLocations[base + i]);
942
943       vertexInputState.attributes.emplace_back(location,
944                                                bindingIndex,
945                                                vertexFormat.components[i].offset,
946                                                GetPropertyVertexFormat(vertexFormat.components[i].type));
947     }
948     base += attributeCount;
949     ++bindingIndex;
950   }
951   mUpdateAttributeLocations = false;
952
953   // Get the topology
954   inputAssemblyState.SetTopology(mGeometry->GetTopology());
955
956   // Get the program
957   programState.SetProgram(program.GetGraphicsProgram());
958
959   Graphics::RasterizationState rasterizationState{};
960
961   //Set cull face  mode
962   const Dali::Internal::SceneGraph::Camera* cam = instruction.GetCamera();
963   if(cam->GetReflectionUsed())
964   {
965     auto adjFaceCullingMode = mFaceCullingMode;
966     switch(mFaceCullingMode)
967     {
968       case FaceCullingMode::Type::FRONT:
969       {
970         adjFaceCullingMode = FaceCullingMode::Type::BACK;
971         break;
972       }
973       case FaceCullingMode::Type::BACK:
974       {
975         adjFaceCullingMode = FaceCullingMode::Type::FRONT;
976         break;
977       }
978       default:
979       {
980         // nothing to do, leave culling as it is
981       }
982     }
983     rasterizationState.SetCullMode(ConvertCullFace(adjFaceCullingMode));
984   }
985   else
986   {
987     rasterizationState.SetCullMode(ConvertCullFace(mFaceCullingMode));
988   }
989
990   rasterizationState.SetFrontFace(Graphics::FrontFace::COUNTER_CLOCKWISE);
991
992   /**
993    * Set Polygon mode
994    */
995   switch(mGeometry->GetTopology())
996   {
997     case Graphics::PrimitiveTopology::TRIANGLE_LIST:
998     case Graphics::PrimitiveTopology::TRIANGLE_STRIP:
999     case Graphics::PrimitiveTopology::TRIANGLE_FAN:
1000       rasterizationState.SetPolygonMode(Graphics::PolygonMode::FILL);
1001       break;
1002     case Graphics::PrimitiveTopology::LINE_LIST:
1003     case Graphics::PrimitiveTopology::LINE_LOOP:
1004     case Graphics::PrimitiveTopology::LINE_STRIP:
1005       rasterizationState.SetPolygonMode(Graphics::PolygonMode::LINE);
1006       break;
1007     case Graphics::PrimitiveTopology::POINT_LIST:
1008       rasterizationState.SetPolygonMode(Graphics::PolygonMode::POINT);
1009       break;
1010   }
1011
1012   // @todo How to signal a blend barrier is needed?
1013   //if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled)
1014   //{
1015   //  context.BlendBarrier();
1016   //}
1017
1018   Graphics::ColorBlendState colorBlendState{};
1019   colorBlendState.SetBlendEnable(false);
1020
1021   if(blend)
1022   {
1023     colorBlendState.SetBlendEnable(true);
1024
1025     Graphics::BlendOp rgbOp   = ConvertBlendEquation(mBlendingOptions.GetBlendEquationRgb());
1026     Graphics::BlendOp alphaOp = ConvertBlendEquation(mBlendingOptions.GetBlendEquationRgb());
1027     if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled)
1028     {
1029       if(rgbOp != alphaOp)
1030       {
1031         DALI_LOG_ERROR("Advanced Blend Equation MUST be applied by using BlendEquation.\n");
1032         alphaOp = rgbOp;
1033       }
1034     }
1035
1036     colorBlendState
1037       .SetSrcColorBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendSrcFactorRgb()))
1038       .SetSrcAlphaBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendSrcFactorAlpha()))
1039       .SetDstColorBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendDestFactorRgb()))
1040       .SetDstAlphaBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendDestFactorAlpha()))
1041       .SetColorBlendOp(rgbOp)
1042       .SetAlphaBlendOp(alphaOp);
1043
1044     // Blend color is optional and rarely used
1045     Vector4* blendColor = const_cast<Vector4*>(mBlendingOptions.GetBlendColor());
1046     if(blendColor)
1047     {
1048       colorBlendState.SetBlendConstants(blendColor->AsFloat());
1049     }
1050   }
1051
1052   // Take the program into use so we can send uniforms to it
1053   // @todo Remove this call entirely!
1054   program.Use();
1055
1056   mUpdated = true;
1057
1058   // Create a new pipeline
1059   return mGraphicsController->CreatePipeline(
1060     Graphics::PipelineCreateInfo()
1061       .SetInputAssemblyState(&inputAssemblyState) // Passed as pointers - shallow copy will break. TOO C LIKE
1062       .SetVertexInputState(&vertexInputState)
1063       .SetRasterizationState(&rasterizationState)
1064       .SetColorBlendState(&colorBlendState)
1065       .SetProgramState(&programState)
1066       .SetNextExtension(&mLegacyProgram),
1067     std::move(oldPipeline));
1068 }
1069
1070 } // namespace Render
1071
1072 } // namespace Internal
1073
1074 } // namespace Dali