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),
134 mAttributesLocation(),
136 mStencilParameters(stencilParameters),
138 mIndexedDrawFirstElement(0),
139 mIndexedDrawElementsCount(0),
140 mDepthFunction(depthFunction),
141 mFaceCullingMode(faceCullingMode),
142 mDepthWriteMode(depthWriteMode),
143 mDepthTestMode(depthTestMode),
144 mUpdateAttributesLocation(true),
145 mPremultipledAlphaEnabled(preMultipliedAlphaEnabled),
146 mShaderChanged(false),
149 if(blendingBitmask != 0u)
151 mBlendingOptions.SetBitmask(blendingBitmask);
154 mBlendingOptions.SetBlendColor(blendColor);
157 void Renderer::Initialize(Context& context, Graphics::Controller& graphicsController)
160 mGraphicsController = &graphicsController;
163 Renderer::~Renderer() = default;
165 void Renderer::SetGeometry(Render::Geometry* geometry)
167 mGeometry = geometry;
168 mUpdateAttributesLocation = true;
170 void Renderer::SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size)
172 mDrawCommands.clear();
173 mDrawCommands.insert(mDrawCommands.end(), pDrawCommands, pDrawCommands + size);
176 void Renderer::SetBlending(Context& context, bool blend)
178 context.SetBlend(blend);
181 // Blend color is optional and rarely used
182 const Vector4* blendColor = mBlendingOptions.GetBlendColor();
185 context.SetCustomBlendColor(*blendColor);
189 context.SetDefaultBlendColor();
192 // Set blend source & destination factors
193 context.BlendFuncSeparate(mBlendingOptions.GetBlendSrcFactorRgb(),
194 mBlendingOptions.GetBlendDestFactorRgb(),
195 mBlendingOptions.GetBlendSrcFactorAlpha(),
196 mBlendingOptions.GetBlendDestFactorAlpha());
198 // Set blend equations
199 Dali::DevelBlendEquation::Type rgbEquation = mBlendingOptions.GetBlendEquationRgb();
200 Dali::DevelBlendEquation::Type alphaEquation = mBlendingOptions.GetBlendEquationAlpha();
202 if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled)
204 if(rgbEquation != alphaEquation)
206 DALI_LOG_ERROR("Advanced Blend Equation have to be appried by using BlendEquation.\n");
208 context.BlendEquation(rgbEquation);
212 context.BlendEquationSeparate(rgbEquation, alphaEquation);
219 void Renderer::GlContextDestroyed()
221 mGeometry->GlContextDestroyed();
224 void Renderer::GlCleanup()
228 void Renderer::SetUniforms(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program)
230 // Check if the map has changed
231 DALI_ASSERT_DEBUG(mRenderDataProvider && "No Uniform map data provider available");
233 const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
235 if(uniformMapDataProvider.GetUniformMapChanged(bufferIndex) ||
236 node.GetUniformMapChanged(bufferIndex) ||
237 mUniformIndexMap.Count() == 0 ||
240 // Reset shader pointer
241 mShaderChanged = false;
243 const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap(bufferIndex);
244 const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap(bufferIndex);
246 uint32_t maxMaps = static_cast<uint32_t>(uniformMap.Count() + uniformMapNode.Count()); // 4,294,967,295 maps should be enough
247 mUniformIndexMap.Clear(); // Clear contents, but keep memory if we don't change size
248 mUniformIndexMap.Resize(maxMaps);
250 uint32_t mapIndex = 0;
251 for(; mapIndex < uniformMap.Count(); ++mapIndex)
253 mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex].propertyPtr;
254 mUniformIndexMap[mapIndex].uniformIndex = program.RegisterUniform(uniformMap[mapIndex].uniformName);
257 for(uint32_t nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count(); ++nodeMapIndex)
259 uint32_t uniformIndex = program.RegisterUniform(uniformMapNode[nodeMapIndex].uniformName);
261 for(uint32_t i = 0; i < uniformMap.Count(); ++i)
263 if(mUniformIndexMap[i].uniformIndex == uniformIndex)
265 mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr;
273 mUniformIndexMap[mapIndex].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr;
274 mUniformIndexMap[mapIndex].uniformIndex = uniformIndex;
279 mUniformIndexMap.Resize(mapIndex);
282 // Set uniforms in local map
283 for(UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
284 end = mUniformIndexMap.End();
288 SetUniformFromProperty(bufferIndex, program, *iter);
291 GLint sizeLoc = program.GetUniformLocation(Program::UNIFORM_SIZE);
294 program.SetSizeUniform3f(sizeLoc, size.x, size.y, size.z);
298 void Renderer::SetUniformFromProperty(BufferIndex bufferIndex, Program& program, UniformIndexMap& map)
300 GLint location = program.GetUniformLocation(map.uniformIndex);
301 if(Program::UNIFORM_UNKNOWN != location)
303 // switch based on property type to use correct GL uniform setter
304 switch(map.propertyValue->GetType())
306 case Property::INTEGER:
308 program.SetUniform1i(location, map.propertyValue->GetInteger(bufferIndex));
311 case Property::FLOAT:
313 program.SetUniform1f(location, map.propertyValue->GetFloat(bufferIndex));
316 case Property::VECTOR2:
318 Vector2 value(map.propertyValue->GetVector2(bufferIndex));
319 program.SetUniform2f(location, value.x, value.y);
323 case Property::VECTOR3:
325 Vector3 value(map.propertyValue->GetVector3(bufferIndex));
326 program.SetUniform3f(location, value.x, value.y, value.z);
330 case Property::VECTOR4:
332 Vector4 value(map.propertyValue->GetVector4(bufferIndex));
333 program.SetUniform4f(location, value.x, value.y, value.z, value.w);
337 case Property::ROTATION:
339 Quaternion value(map.propertyValue->GetQuaternion(bufferIndex));
340 program.SetUniform4f(location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w);
344 case Property::MATRIX:
346 const Matrix& value = map.propertyValue->GetMatrix(bufferIndex);
347 program.SetUniformMatrix4fv(location, 1, value.AsFloat());
351 case Property::MATRIX3:
353 const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex);
354 program.SetUniformMatrix3fv(location, 1, value.AsFloat());
360 // Other property types are ignored
367 bool Renderer::BindTextures(Context& context, Program& program, Graphics::CommandBuffer& commandBuffer, Vector<Graphics::Texture*>& boundTextures)
369 uint32_t textureUnit = 0;
372 GLint uniformLocation(-1);
373 std::vector<Render::Sampler*>& samplers(mRenderDataProvider->GetSamplers());
374 std::vector<Render::Texture*>& textures(mRenderDataProvider->GetTextures());
376 std::vector<Graphics::TextureBinding> textureBindings;
377 for(uint32_t i = 0; i < static_cast<uint32_t>(textures.size()) && result; ++i) // not expecting more than uint32_t of textures
381 if(program.GetSamplerUniformLocation(i, uniformLocation))
383 // if the sampler exists,
384 // if it's default, delete the graphics object
385 // otherwise re-initialize it if dirty
387 const Graphics::Sampler* graphicsSampler = (samplers[i] ? samplers[i]->GetGraphicsObject()
390 boundTextures.PushBack(textures[i]->GetGraphicsObject());
391 const Graphics::TextureBinding textureBinding{textures[i]->GetGraphicsObject(), graphicsSampler, textureUnit};
392 textureBindings.push_back(textureBinding);
394 program.SetUniform1i(uniformLocation, textureUnit); // Get through shader reflection
400 if(textureBindings.size() > 0)
402 commandBuffer.BindTextures(textureBindings);
408 void Renderer::SetFaceCullingMode(FaceCullingMode::Type mode)
410 mFaceCullingMode = mode;
414 void Renderer::SetBlendingBitMask(uint32_t bitmask)
416 mBlendingOptions.SetBitmask(bitmask);
420 void Renderer::SetBlendColor(const Vector4& color)
422 mBlendingOptions.SetBlendColor(color);
426 void Renderer::SetIndexedDrawFirstElement(uint32_t firstElement)
428 mIndexedDrawFirstElement = firstElement;
432 void Renderer::SetIndexedDrawElementsCount(uint32_t elementsCount)
434 mIndexedDrawElementsCount = elementsCount;
438 void Renderer::EnablePreMultipliedAlpha(bool enable)
440 mPremultipledAlphaEnabled = enable;
444 void Renderer::SetDepthWriteMode(DepthWriteMode::Type depthWriteMode)
446 mDepthWriteMode = depthWriteMode;
450 void Renderer::SetDepthTestMode(DepthTestMode::Type depthTestMode)
452 mDepthTestMode = depthTestMode;
456 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
458 return mDepthWriteMode;
461 DepthTestMode::Type Renderer::GetDepthTestMode() const
463 return mDepthTestMode;
466 void Renderer::SetDepthFunction(DepthFunction::Type depthFunction)
468 mDepthFunction = depthFunction;
472 DepthFunction::Type Renderer::GetDepthFunction() const
474 return mDepthFunction;
477 void Renderer::SetRenderMode(RenderMode::Type renderMode)
479 mStencilParameters.renderMode = renderMode;
483 RenderMode::Type Renderer::GetRenderMode() const
485 return mStencilParameters.renderMode;
488 void Renderer::SetStencilFunction(StencilFunction::Type stencilFunction)
490 mStencilParameters.stencilFunction = stencilFunction;
494 StencilFunction::Type Renderer::GetStencilFunction() const
496 return mStencilParameters.stencilFunction;
499 void Renderer::SetStencilFunctionMask(int stencilFunctionMask)
501 mStencilParameters.stencilFunctionMask = stencilFunctionMask;
505 int Renderer::GetStencilFunctionMask() const
507 return mStencilParameters.stencilFunctionMask;
510 void Renderer::SetStencilFunctionReference(int stencilFunctionReference)
512 mStencilParameters.stencilFunctionReference = stencilFunctionReference;
516 int Renderer::GetStencilFunctionReference() const
518 return mStencilParameters.stencilFunctionReference;
521 void Renderer::SetStencilMask(int stencilMask)
523 mStencilParameters.stencilMask = stencilMask;
527 int Renderer::GetStencilMask() const
529 return mStencilParameters.stencilMask;
532 void Renderer::SetStencilOperationOnFail(StencilOperation::Type stencilOperationOnFail)
534 mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
538 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
540 return mStencilParameters.stencilOperationOnFail;
543 void Renderer::SetStencilOperationOnZFail(StencilOperation::Type stencilOperationOnZFail)
545 mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
549 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
551 return mStencilParameters.stencilOperationOnZFail;
554 void Renderer::SetStencilOperationOnZPass(StencilOperation::Type stencilOperationOnZPass)
556 mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
560 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
562 return mStencilParameters.stencilOperationOnZPass;
565 void Renderer::Upload()
567 mGeometry->Upload(*mGraphicsController);
570 void Renderer::Render(Context& context,
571 BufferIndex bufferIndex,
572 const SceneGraph::NodeDataProvider& node,
573 const Matrix& modelMatrix,
574 const Matrix& modelViewMatrix,
575 const Matrix& viewMatrix,
576 const Matrix& projectionMatrix,
579 Vector<Graphics::Texture*>& boundTextures,
580 const Dali::Internal::SceneGraph::RenderInstruction& instruction,
583 // Before doing anything test if the call happens in the right queue
584 if(mDrawCommands.empty() && queueIndex > 0)
590 std::vector<DevelRenderer::DrawCommand*> commands;
591 for(auto& cmd : mDrawCommands)
593 if(cmd.queue == queueIndex)
595 commands.emplace_back(&cmd);
599 // Have commands but nothing to be drawn - abort
600 if(!mDrawCommands.empty() && commands.empty())
605 // Get the program to use:
606 Program* program = mRenderDataProvider->GetShader().GetProgram();
609 DALI_LOG_ERROR("Failed to get program for shader at address %p.\n", reinterpret_cast<void*>(&mRenderDataProvider->GetShader()));
613 // For now, create command buffer to perform only the texture / sample binding
615 // Expect this call to glBindTextureForUnit, and glTexParameteri() for the sampler
616 Graphics::UniquePtr<Graphics::CommandBuffer> commandBuffer = mGraphicsController->CreateCommandBuffer(
617 Graphics::CommandBufferCreateInfo()
618 .SetLevel(Graphics::CommandBufferLevel::SECONDARY),
622 const Dali::Internal::SceneGraph::Camera* cam = instruction.GetCamera();
623 if(cam->GetReflectionUsed())
625 auto adjFaceCullingMode = mFaceCullingMode;
626 switch(mFaceCullingMode)
628 case FaceCullingMode::Type::FRONT:
630 adjFaceCullingMode = FaceCullingMode::Type::BACK;
633 case FaceCullingMode::Type::BACK:
635 adjFaceCullingMode = FaceCullingMode::Type::FRONT;
640 // nothing to do, leave culling as it is
643 context.CullFace(adjFaceCullingMode);
647 context.CullFace(mFaceCullingMode);
650 // Take the program into use so we can send uniforms to it
653 if(DALI_LIKELY(BindTextures(context, *program, *commandBuffer.get(), boundTextures)))
655 // Only set up and draw if we have textures and they are all valid
657 // set projection and view matrix if program has not yet received them yet this frame
658 SetMatrices(*program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix);
661 GLint loc = program->GetUniformLocation(Program::UNIFORM_COLOR);
662 if(Program::UNIFORM_UNKNOWN != loc)
664 const Vector4& color = node.GetRenderColor(bufferIndex);
665 if(mPremultipledAlphaEnabled)
667 float alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex);
668 program->SetUniform4f(loc, color.r * alpha, color.g * alpha, color.b * alpha, alpha);
672 program->SetUniform4f(loc, color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex));
676 SetUniforms(bufferIndex, node, size, *program);
678 if(mUpdateAttributesLocation || mGeometry->AttributesChanged())
680 mGeometry->GetAttributeLocationFromProgram(mAttributesLocation, *program, bufferIndex);
681 mUpdateAttributesLocation = false;
684 if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled)
686 context.BlendBarrier();
689 if(mDrawCommands.empty())
691 SetBlending(context, blend);
693 mGeometry->Draw(context,
694 *mGraphicsController,
695 *commandBuffer.get(),
698 mIndexedDrawFirstElement,
699 mIndexedDrawElementsCount);
703 for(auto& cmd : commands)
705 if(cmd->queue == queueIndex)
708 SetBlending(context, cmd->queue == DevelRenderer::RENDER_QUEUE_OPAQUE ? false : blend);
709 mGeometry->Draw(context, *mGraphicsController, *commandBuffer.get(), bufferIndex, mAttributesLocation, cmd->firstIndex, cmd->elementCount);
717 void Renderer::SetSortAttributes(BufferIndex bufferIndex,
718 SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes) const
720 sortAttributes.shader = &(mRenderDataProvider->GetShader());
721 sortAttributes.geometry = mGeometry;
724 void Renderer::SetShaderChanged(bool value)
726 mShaderChanged = value;
729 bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
737 if(mShaderChanged || mUpdateAttributesLocation || mGeometry->AttributesChanged())
742 for(const auto& texture : mRenderDataProvider->GetTextures())
744 if(texture && texture->IsNativeImage())
750 uint64_t hash = 0xc70f6907UL;
751 const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap(bufferIndex);
752 for(const auto& uniformProperty : uniformMapNode)
754 hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
757 const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
758 const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap(bufferIndex);
759 for(const auto& uniformProperty : uniformMap)
761 hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
764 if(mUniformsHash != hash)
766 mUniformsHash = hash;
773 } // namespace Render
775 } // namespace Internal