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