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 commandBuffer.BindTextures(textureBindings);
405 void Renderer::SetFaceCullingMode(FaceCullingMode::Type mode)
407 mFaceCullingMode = mode;
411 void Renderer::SetBlendingBitMask(uint32_t bitmask)
413 mBlendingOptions.SetBitmask(bitmask);
417 void Renderer::SetBlendColor(const Vector4& color)
419 mBlendingOptions.SetBlendColor(color);
423 void Renderer::SetIndexedDrawFirstElement(uint32_t firstElement)
425 mIndexedDrawFirstElement = firstElement;
429 void Renderer::SetIndexedDrawElementsCount(uint32_t elementsCount)
431 mIndexedDrawElementsCount = elementsCount;
435 void Renderer::EnablePreMultipliedAlpha(bool enable)
437 mPremultipledAlphaEnabled = enable;
441 void Renderer::SetDepthWriteMode(DepthWriteMode::Type depthWriteMode)
443 mDepthWriteMode = depthWriteMode;
447 void Renderer::SetDepthTestMode(DepthTestMode::Type depthTestMode)
449 mDepthTestMode = depthTestMode;
453 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
455 return mDepthWriteMode;
458 DepthTestMode::Type Renderer::GetDepthTestMode() const
460 return mDepthTestMode;
463 void Renderer::SetDepthFunction(DepthFunction::Type depthFunction)
465 mDepthFunction = depthFunction;
469 DepthFunction::Type Renderer::GetDepthFunction() const
471 return mDepthFunction;
474 void Renderer::SetRenderMode(RenderMode::Type renderMode)
476 mStencilParameters.renderMode = renderMode;
480 RenderMode::Type Renderer::GetRenderMode() const
482 return mStencilParameters.renderMode;
485 void Renderer::SetStencilFunction(StencilFunction::Type stencilFunction)
487 mStencilParameters.stencilFunction = stencilFunction;
491 StencilFunction::Type Renderer::GetStencilFunction() const
493 return mStencilParameters.stencilFunction;
496 void Renderer::SetStencilFunctionMask(int stencilFunctionMask)
498 mStencilParameters.stencilFunctionMask = stencilFunctionMask;
502 int Renderer::GetStencilFunctionMask() const
504 return mStencilParameters.stencilFunctionMask;
507 void Renderer::SetStencilFunctionReference(int stencilFunctionReference)
509 mStencilParameters.stencilFunctionReference = stencilFunctionReference;
513 int Renderer::GetStencilFunctionReference() const
515 return mStencilParameters.stencilFunctionReference;
518 void Renderer::SetStencilMask(int stencilMask)
520 mStencilParameters.stencilMask = stencilMask;
524 int Renderer::GetStencilMask() const
526 return mStencilParameters.stencilMask;
529 void Renderer::SetStencilOperationOnFail(StencilOperation::Type stencilOperationOnFail)
531 mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
535 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
537 return mStencilParameters.stencilOperationOnFail;
540 void Renderer::SetStencilOperationOnZFail(StencilOperation::Type stencilOperationOnZFail)
542 mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
546 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
548 return mStencilParameters.stencilOperationOnZFail;
551 void Renderer::SetStencilOperationOnZPass(StencilOperation::Type stencilOperationOnZPass)
553 mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
557 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
559 return mStencilParameters.stencilOperationOnZPass;
562 void Renderer::Upload()
564 mGeometry->Upload(*mGraphicsController);
567 void Renderer::Render(Context& context,
568 BufferIndex bufferIndex,
569 const SceneGraph::NodeDataProvider& node,
570 const Matrix& modelMatrix,
571 const Matrix& modelViewMatrix,
572 const Matrix& viewMatrix,
573 const Matrix& projectionMatrix,
576 Vector<Graphics::Texture*>& boundTextures,
577 const Dali::Internal::SceneGraph::RenderInstruction& instruction,
580 // Before doing anything test if the call happens in the right queue
581 if(mDrawCommands.empty() && queueIndex > 0)
587 std::vector<DevelRenderer::DrawCommand*> commands;
588 for(auto& cmd : mDrawCommands)
590 if(cmd.queue == queueIndex)
592 commands.emplace_back(&cmd);
596 // Have commands but nothing to be drawn - abort
597 if(!mDrawCommands.empty() && commands.empty())
602 // Get the program to use:
603 Program* program = mRenderDataProvider->GetShader().GetProgram();
606 DALI_LOG_ERROR("Failed to get program for shader at address %p.\n", reinterpret_cast<void*>(&mRenderDataProvider->GetShader()));
610 // For now, create command buffer to perform only the texture / sample binding
612 // Expect this call to glBindTextureForUnit, and glTexParameteri() for the sampler
613 Graphics::UniquePtr<Graphics::CommandBuffer> commandBuffer = mGraphicsController->CreateCommandBuffer(
614 Graphics::CommandBufferCreateInfo()
615 .SetLevel(Graphics::CommandBufferLevel::SECONDARY),
619 const Dali::Internal::SceneGraph::Camera* cam = instruction.GetCamera();
620 if(cam->GetReflectionUsed())
622 auto adjFaceCullingMode = mFaceCullingMode;
623 switch(mFaceCullingMode)
625 case FaceCullingMode::Type::FRONT:
627 adjFaceCullingMode = FaceCullingMode::Type::BACK;
630 case FaceCullingMode::Type::BACK:
632 adjFaceCullingMode = FaceCullingMode::Type::FRONT;
637 // nothing to do, leave culling as it is
640 context.CullFace(adjFaceCullingMode);
644 context.CullFace(mFaceCullingMode);
647 // Take the program into use so we can send uniforms to it
650 if(DALI_LIKELY(BindTextures(context, *program, *commandBuffer.get(), boundTextures)))
652 // Only set up and draw if we have textures and they are all valid
654 // set projection and view matrix if program has not yet received them yet this frame
655 SetMatrices(*program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix);
658 GLint loc = program->GetUniformLocation(Program::UNIFORM_COLOR);
659 if(Program::UNIFORM_UNKNOWN != loc)
661 const Vector4& color = node.GetRenderColor(bufferIndex);
662 if(mPremultipledAlphaEnabled)
664 float alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex);
665 program->SetUniform4f(loc, color.r * alpha, color.g * alpha, color.b * alpha, alpha);
669 program->SetUniform4f(loc, color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex));
673 SetUniforms(bufferIndex, node, size, *program);
675 if(mUpdateAttributesLocation || mGeometry->AttributesChanged())
677 mGeometry->GetAttributeLocationFromProgram(mAttributesLocation, *program, bufferIndex);
678 mUpdateAttributesLocation = false;
681 if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled)
683 context.BlendBarrier();
686 if(mDrawCommands.empty())
688 SetBlending(context, blend);
690 mGeometry->Draw(context,
691 *mGraphicsController,
692 *commandBuffer.get(),
695 mIndexedDrawFirstElement,
696 mIndexedDrawElementsCount);
700 for(auto& cmd : commands)
702 if(cmd->queue == queueIndex)
705 SetBlending(context, cmd->queue == DevelRenderer::RENDER_QUEUE_OPAQUE ? false : blend);
706 mGeometry->Draw(context, *mGraphicsController, *commandBuffer.get(), bufferIndex, mAttributesLocation, cmd->firstIndex, cmd->elementCount);
714 void Renderer::SetSortAttributes(BufferIndex bufferIndex,
715 SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes) const
717 sortAttributes.shader = &(mRenderDataProvider->GetShader());
718 sortAttributes.geometry = mGeometry;
721 void Renderer::SetShaderChanged(bool value)
723 mShaderChanged = value;
726 bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
734 if(mShaderChanged || mUpdateAttributesLocation || mGeometry->AttributesChanged())
739 for(const auto& texture : mRenderDataProvider->GetTextures())
741 if(texture && texture->IsNativeImage())
747 uint64_t hash = 0xc70f6907UL;
748 const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap(bufferIndex);
749 for(const auto& uniformProperty : uniformMapNode)
751 hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
754 const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
755 const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap(bufferIndex);
756 for(const auto& uniformProperty : uniformMap)
758 hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
761 if(mUniformsHash != hash)
763 mUniformsHash = hash;
770 } // namespace Render
772 } // namespace Internal