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