2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/render/renderers/render-renderer.h>
22 #include <dali/internal/common/image-sampler.h>
23 #include <dali/internal/render/common/render-instruction.h>
24 #include <dali/internal/render/data-providers/node-data-provider.h>
25 #include <dali/internal/render/data-providers/uniform-map-data-provider.h>
26 #include <dali/internal/render/gl-resources/context.h>
27 #include <dali/internal/render/renderers/render-sampler.h>
28 #include <dali/internal/render/renderers/render-texture.h>
29 #include <dali/internal/render/shaders/program.h>
30 #include <dali/internal/render/shaders/scene-graph-shader.h>
39 * Helper to set view and projection matrices once per program
40 * @param program to set the matrices to
41 * @param modelMatrix to set
42 * @param viewMatrix to set
43 * @param projectionMatrix to set
44 * @param modelViewMatrix to set
45 * @param modelViewProjectionMatrix to set
47 inline void SetMatrices(Program& program,
48 const Matrix& modelMatrix,
49 const Matrix& viewMatrix,
50 const Matrix& projectionMatrix,
51 const Matrix& modelViewMatrix)
53 GLint loc = program.GetUniformLocation(Program::UNIFORM_MODEL_MATRIX);
54 if(Program::UNIFORM_UNKNOWN != loc)
56 program.SetUniformMatrix4fv(loc, 1, modelMatrix.AsFloat());
58 loc = program.GetUniformLocation(Program::UNIFORM_VIEW_MATRIX);
59 if(Program::UNIFORM_UNKNOWN != loc)
61 if(program.GetViewMatrix() != &viewMatrix)
63 program.SetViewMatrix(&viewMatrix);
64 program.SetUniformMatrix4fv(loc, 1, viewMatrix.AsFloat());
67 // set projection matrix if program has not yet received it this frame or if it is dirty
68 loc = program.GetUniformLocation(Program::UNIFORM_PROJECTION_MATRIX);
69 if(Program::UNIFORM_UNKNOWN != loc)
71 if(program.GetProjectionMatrix() != &projectionMatrix)
73 program.SetProjectionMatrix(&projectionMatrix);
74 program.SetUniformMatrix4fv(loc, 1, projectionMatrix.AsFloat());
77 loc = program.GetUniformLocation(Program::UNIFORM_MODELVIEW_MATRIX);
78 if(Program::UNIFORM_UNKNOWN != loc)
80 program.SetUniformMatrix4fv(loc, 1, modelViewMatrix.AsFloat());
83 loc = program.GetUniformLocation(Program::UNIFORM_MVP_MATRIX);
84 if(Program::UNIFORM_UNKNOWN != loc)
86 Matrix modelViewProjectionMatrix(false);
87 Matrix::Multiply(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix);
88 program.SetUniformMatrix4fv(loc, 1, modelViewProjectionMatrix.AsFloat());
91 loc = program.GetUniformLocation(Program::UNIFORM_NORMAL_MATRIX);
92 if(Program::UNIFORM_UNKNOWN != loc)
95 normalMatrix = modelViewMatrix;
96 normalMatrix.Invert();
97 normalMatrix.Transpose();
98 program.SetUniformMatrix3fv(loc, 1, normalMatrix.AsFloat());
106 Renderer* Renderer::New(SceneGraph::RenderDataProvider* dataProvider,
107 Render::Geometry* geometry,
108 uint32_t blendingBitmask,
109 const Vector4& blendColor,
110 FaceCullingMode::Type faceCullingMode,
111 bool preMultipliedAlphaEnabled,
112 DepthWriteMode::Type depthWriteMode,
113 DepthTestMode::Type depthTestMode,
114 DepthFunction::Type depthFunction,
115 StencilParameters& stencilParameters)
117 return new Renderer(dataProvider, geometry, blendingBitmask, blendColor, faceCullingMode, preMultipliedAlphaEnabled, depthWriteMode, depthTestMode, depthFunction, stencilParameters);
120 Renderer::Renderer(SceneGraph::RenderDataProvider* dataProvider,
121 Render::Geometry* geometry,
122 uint32_t blendingBitmask,
123 const Vector4& blendColor,
124 FaceCullingMode::Type faceCullingMode,
125 bool preMultipliedAlphaEnabled,
126 DepthWriteMode::Type depthWriteMode,
127 DepthTestMode::Type depthTestMode,
128 DepthFunction::Type depthFunction,
129 StencilParameters& stencilParameters)
130 : mRenderDataProvider(dataProvider),
133 mProgramCache(nullptr),
135 mAttributesLocation(),
137 mStencilParameters(stencilParameters),
139 mIndexedDrawFirstElement(0),
140 mIndexedDrawElementsCount(0),
141 mDepthFunction(depthFunction),
142 mFaceCullingMode(faceCullingMode),
143 mDepthWriteMode(depthWriteMode),
144 mDepthTestMode(depthTestMode),
145 mUpdateAttributesLocation(true),
146 mPremultipledAlphaEnabled(preMultipliedAlphaEnabled),
147 mShaderChanged(false),
150 if(blendingBitmask != 0u)
152 mBlendingOptions.SetBitmask(blendingBitmask);
155 mBlendingOptions.SetBlendColor(blendColor);
158 void Renderer::Initialize(Context& context, ProgramCache& programCache)
161 mProgramCache = &programCache;
164 Renderer::~Renderer() = default;
166 void Renderer::SetGeometry(Render::Geometry* geometry)
168 mGeometry = geometry;
169 mUpdateAttributesLocation = true;
171 void Renderer::SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size)
173 mDrawCommands.clear();
174 mDrawCommands.insert(mDrawCommands.end(), pDrawCommands, pDrawCommands + size);
177 void Renderer::SetBlending(Context& context, bool blend)
179 context.SetBlend(blend);
182 // Blend color is optional and rarely used
183 const Vector4* blendColor = mBlendingOptions.GetBlendColor();
186 context.SetCustomBlendColor(*blendColor);
190 context.SetDefaultBlendColor();
193 // Set blend source & destination factors
194 context.BlendFuncSeparate(mBlendingOptions.GetBlendSrcFactorRgb(),
195 mBlendingOptions.GetBlendDestFactorRgb(),
196 mBlendingOptions.GetBlendSrcFactorAlpha(),
197 mBlendingOptions.GetBlendDestFactorAlpha());
199 // Set blend equations
200 Dali::DevelBlendEquation::Type rgbEquation = mBlendingOptions.GetBlendEquationRgb();
201 Dali::DevelBlendEquation::Type alphaEquation = mBlendingOptions.GetBlendEquationAlpha();
203 if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled)
205 if(rgbEquation != alphaEquation)
207 DALI_LOG_ERROR("Advanced Blend Equation have to be appried by using BlendEquation.\n");
209 context.BlendEquation(rgbEquation);
213 context.BlendEquationSeparate(rgbEquation, alphaEquation);
220 void Renderer::GlContextDestroyed()
222 mGeometry->GlContextDestroyed();
225 void Renderer::GlCleanup()
229 void Renderer::SetUniforms(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program)
231 // Check if the map has changed
232 DALI_ASSERT_DEBUG(mRenderDataProvider && "No Uniform map data provider available");
234 const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
236 if(uniformMapDataProvider.GetUniformMapChanged(bufferIndex) ||
237 node.GetUniformMapChanged(bufferIndex) ||
238 mUniformIndexMap.Count() == 0 ||
241 // Reset shader pointer
242 mShaderChanged = false;
244 const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap(bufferIndex);
245 const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap(bufferIndex);
247 uint32_t maxMaps = static_cast<uint32_t>(uniformMap.Count() + uniformMapNode.Count()); // 4,294,967,295 maps should be enough
248 mUniformIndexMap.Clear(); // Clear contents, but keep memory if we don't change size
249 mUniformIndexMap.Resize(maxMaps);
251 uint32_t mapIndex = 0;
252 for(; mapIndex < uniformMap.Count(); ++mapIndex)
254 mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex].propertyPtr;
255 mUniformIndexMap[mapIndex].uniformIndex = program.RegisterUniform(uniformMap[mapIndex].uniformName);
258 for(uint32_t nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count(); ++nodeMapIndex)
260 uint32_t uniformIndex = program.RegisterUniform(uniformMapNode[nodeMapIndex].uniformName);
262 for(uint32_t i = 0; i < uniformMap.Count(); ++i)
264 if(mUniformIndexMap[i].uniformIndex == uniformIndex)
266 mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr;
274 mUniformIndexMap[mapIndex].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr;
275 mUniformIndexMap[mapIndex].uniformIndex = uniformIndex;
280 mUniformIndexMap.Resize(mapIndex);
283 // Set uniforms in local map
284 for(UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
285 end = mUniformIndexMap.End();
289 SetUniformFromProperty(bufferIndex, program, *iter);
292 GLint sizeLoc = program.GetUniformLocation(Program::UNIFORM_SIZE);
295 program.SetSizeUniform3f(sizeLoc, size.x, size.y, size.z);
299 void Renderer::SetUniformFromProperty(BufferIndex bufferIndex, Program& program, UniformIndexMap& map)
301 GLint location = program.GetUniformLocation(map.uniformIndex);
302 if(Program::UNIFORM_UNKNOWN != location)
304 // switch based on property type to use correct GL uniform setter
305 switch(map.propertyValue->GetType())
307 case Property::INTEGER:
309 program.SetUniform1i(location, map.propertyValue->GetInteger(bufferIndex));
312 case Property::FLOAT:
314 program.SetUniform1f(location, map.propertyValue->GetFloat(bufferIndex));
317 case Property::VECTOR2:
319 Vector2 value(map.propertyValue->GetVector2(bufferIndex));
320 program.SetUniform2f(location, value.x, value.y);
324 case Property::VECTOR3:
326 Vector3 value(map.propertyValue->GetVector3(bufferIndex));
327 program.SetUniform3f(location, value.x, value.y, value.z);
331 case Property::VECTOR4:
333 Vector4 value(map.propertyValue->GetVector4(bufferIndex));
334 program.SetUniform4f(location, value.x, value.y, value.z, value.w);
338 case Property::ROTATION:
340 Quaternion value(map.propertyValue->GetQuaternion(bufferIndex));
341 program.SetUniform4f(location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w);
345 case Property::MATRIX:
347 const Matrix& value = map.propertyValue->GetMatrix(bufferIndex);
348 program.SetUniformMatrix4fv(location, 1, value.AsFloat());
352 case Property::MATRIX3:
354 const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex);
355 program.SetUniformMatrix3fv(location, 1, value.AsFloat());
361 // Other property types are ignored
368 bool Renderer::BindTextures(Context& context, Program& program, Vector<GLuint>& boundTextures)
370 uint32_t textureUnit = 0;
373 GLint uniformLocation(-1);
374 std::vector<Render::Sampler*>& samplers(mRenderDataProvider->GetSamplers());
375 std::vector<Render::Texture*>& textures(mRenderDataProvider->GetTextures());
376 for(uint32_t i = 0; i < static_cast<uint32_t>(textures.size()) && result; ++i) // not expecting more than uint32_t of textures
380 result = textures[i]->Bind(context, textureUnit, samplers[i]);
381 boundTextures.PushBack(textures[i]->GetId());
382 if(result && program.GetSamplerUniformLocation(i, uniformLocation))
384 program.SetUniform1i(uniformLocation, textureUnit);
393 void Renderer::SetFaceCullingMode(FaceCullingMode::Type mode)
395 mFaceCullingMode = mode;
399 void Renderer::SetBlendingBitMask(uint32_t bitmask)
401 mBlendingOptions.SetBitmask(bitmask);
405 void Renderer::SetBlendColor(const Vector4& color)
407 mBlendingOptions.SetBlendColor(color);
411 void Renderer::SetIndexedDrawFirstElement(uint32_t firstElement)
413 mIndexedDrawFirstElement = firstElement;
417 void Renderer::SetIndexedDrawElementsCount(uint32_t elementsCount)
419 mIndexedDrawElementsCount = elementsCount;
423 void Renderer::EnablePreMultipliedAlpha(bool enable)
425 mPremultipledAlphaEnabled = enable;
429 void Renderer::SetDepthWriteMode(DepthWriteMode::Type depthWriteMode)
431 mDepthWriteMode = depthWriteMode;
435 void Renderer::SetDepthTestMode(DepthTestMode::Type depthTestMode)
437 mDepthTestMode = depthTestMode;
441 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
443 return mDepthWriteMode;
446 DepthTestMode::Type Renderer::GetDepthTestMode() const
448 return mDepthTestMode;
451 void Renderer::SetDepthFunction(DepthFunction::Type depthFunction)
453 mDepthFunction = depthFunction;
457 DepthFunction::Type Renderer::GetDepthFunction() const
459 return mDepthFunction;
462 void Renderer::SetRenderMode(RenderMode::Type renderMode)
464 mStencilParameters.renderMode = renderMode;
468 RenderMode::Type Renderer::GetRenderMode() const
470 return mStencilParameters.renderMode;
473 void Renderer::SetStencilFunction(StencilFunction::Type stencilFunction)
475 mStencilParameters.stencilFunction = stencilFunction;
479 StencilFunction::Type Renderer::GetStencilFunction() const
481 return mStencilParameters.stencilFunction;
484 void Renderer::SetStencilFunctionMask(int stencilFunctionMask)
486 mStencilParameters.stencilFunctionMask = stencilFunctionMask;
490 int Renderer::GetStencilFunctionMask() const
492 return mStencilParameters.stencilFunctionMask;
495 void Renderer::SetStencilFunctionReference(int stencilFunctionReference)
497 mStencilParameters.stencilFunctionReference = stencilFunctionReference;
501 int Renderer::GetStencilFunctionReference() const
503 return mStencilParameters.stencilFunctionReference;
506 void Renderer::SetStencilMask(int stencilMask)
508 mStencilParameters.stencilMask = stencilMask;
512 int Renderer::GetStencilMask() const
514 return mStencilParameters.stencilMask;
517 void Renderer::SetStencilOperationOnFail(StencilOperation::Type stencilOperationOnFail)
519 mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
523 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
525 return mStencilParameters.stencilOperationOnFail;
528 void Renderer::SetStencilOperationOnZFail(StencilOperation::Type stencilOperationOnZFail)
530 mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
534 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
536 return mStencilParameters.stencilOperationOnZFail;
539 void Renderer::SetStencilOperationOnZPass(StencilOperation::Type stencilOperationOnZPass)
541 mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
545 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
547 return mStencilParameters.stencilOperationOnZPass;
550 void Renderer::Upload(Context& context)
552 mGeometry->Upload(context);
555 void Renderer::Render(Context& context,
556 BufferIndex bufferIndex,
557 const SceneGraph::NodeDataProvider& node,
558 const Matrix& modelMatrix,
559 const Matrix& modelViewMatrix,
560 const Matrix& viewMatrix,
561 const Matrix& projectionMatrix,
564 Vector<GLuint>& boundTextures,
565 const Dali::Internal::SceneGraph::RenderInstruction& instruction,
568 // Before doing anything test if the call happens in the right queue
569 if(mDrawCommands.empty() && queueIndex > 0)
575 std::vector<DevelRenderer::DrawCommand*> commands;
576 for(auto& cmd : mDrawCommands)
578 if(cmd.queue == queueIndex)
580 commands.emplace_back(&cmd);
584 // Have commands but nothing to be drawn - abort
585 if(!mDrawCommands.empty() && commands.empty())
590 // Get the program to use
591 // The program cache owns the Program object so we don't need to worry about this raw allocation here.
592 ShaderDataPtr shaderData = mRenderDataProvider->GetShader().GetShaderData();
593 Program* program = Program::New(*mProgramCache, shaderData, (shaderData->GetHints() & Dali::Shader::Hint::MODIFIES_GEOMETRY) != 0x0);
597 DALI_LOG_ERROR("Failed to get program for shader at address %p.\n", reinterpret_cast<void*>(&mRenderDataProvider->GetShader()));
602 const Dali::Internal::SceneGraph::Camera* cam = instruction.GetCamera();
603 if(cam->GetReflectionUsed())
605 auto adjFaceCullingMode = mFaceCullingMode;
606 switch(mFaceCullingMode)
608 case FaceCullingMode::Type::FRONT:
610 adjFaceCullingMode = FaceCullingMode::Type::BACK;
613 case FaceCullingMode::Type::BACK:
615 adjFaceCullingMode = FaceCullingMode::Type::FRONT;
620 // nothing to do, leave culling as it is
623 context.CullFace(adjFaceCullingMode);
627 context.CullFace(mFaceCullingMode);
630 // Take the program into use so we can send uniforms to it
633 if(DALI_LIKELY(BindTextures(context, *program, boundTextures)))
635 // Only set up and draw if we have textures and they are all valid
637 // set projection and view matrix if program has not yet received them yet this frame
638 SetMatrices(*program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix);
641 GLint loc = program->GetUniformLocation(Program::UNIFORM_COLOR);
642 if(Program::UNIFORM_UNKNOWN != loc)
644 const Vector4& color = node.GetRenderColor(bufferIndex);
645 if(mPremultipledAlphaEnabled)
647 float alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex);
648 program->SetUniform4f(loc, color.r * alpha, color.g * alpha, color.b * alpha, alpha);
652 program->SetUniform4f(loc, color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex));
656 SetUniforms(bufferIndex, node, size, *program);
658 if(mUpdateAttributesLocation || mGeometry->AttributesChanged())
660 mGeometry->GetAttributeLocationFromProgram(mAttributesLocation, *program, bufferIndex);
661 mUpdateAttributesLocation = false;
664 if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled)
666 context.BlendBarrier();
669 if(mDrawCommands.empty())
671 SetBlending(context, blend);
673 mGeometry->Draw(context,
676 mIndexedDrawFirstElement,
677 mIndexedDrawElementsCount);
681 for(auto& cmd : commands)
683 if(cmd->queue == queueIndex)
686 SetBlending(context, cmd->queue == DevelRenderer::RENDER_QUEUE_OPAQUE ? false : blend);
687 mGeometry->Draw(context, bufferIndex, mAttributesLocation, cmd->firstIndex, cmd->elementCount);
695 void Renderer::SetSortAttributes(BufferIndex bufferIndex,
696 SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes) const
698 sortAttributes.shader = &(mRenderDataProvider->GetShader());
699 sortAttributes.geometry = mGeometry;
702 void Renderer::SetShaderChanged(bool value)
704 mShaderChanged = value;
707 bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
715 if(mShaderChanged || mUpdateAttributesLocation || mGeometry->AttributesChanged())
720 for(const auto& texture : mRenderDataProvider->GetTextures())
722 if(texture && texture->IsNativeImage())
728 uint64_t hash = 0xc70f6907UL;
729 const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap(bufferIndex);
730 for(const auto& uniformProperty : uniformMapNode)
732 hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
735 const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
736 const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap(bufferIndex);
737 for(const auto& uniformProperty : uniformMap)
739 hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
742 if(mUniformsHash != hash)
744 mUniformsHash = hash;
751 } // namespace Render
753 } // namespace Internal