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