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