2 * Copyright (c) 2020 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/gl-resources/context.h>
24 #include <dali/internal/render/renderers/render-sampler.h>
25 #include <dali/internal/render/shaders/scene-graph-shader.h>
26 #include <dali/internal/render/shaders/program.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/common/render-instruction.h>
42 * Helper to set view and projection matrices once per program
43 * @param program to set the matrices to
44 * @param modelMatrix to set
45 * @param viewMatrix to set
46 * @param projectionMatrix to set
47 * @param modelViewMatrix to set
48 * @param modelViewProjectionMatrix to set
50 inline void SetMatrices( Program& program,
51 const Matrix& modelMatrix,
52 const Matrix& viewMatrix,
53 const Matrix& projectionMatrix,
54 const Matrix& modelViewMatrix )
56 GLint loc = program.GetUniformLocation( Program::UNIFORM_MODEL_MATRIX );
57 if( Program::UNIFORM_UNKNOWN != loc )
59 program.SetUniformMatrix4fv( loc, 1, modelMatrix.AsFloat() );
61 loc = program.GetUniformLocation( Program::UNIFORM_VIEW_MATRIX );
62 if( Program::UNIFORM_UNKNOWN != loc )
64 if( program.GetViewMatrix() != &viewMatrix )
66 program.SetViewMatrix( &viewMatrix );
67 program.SetUniformMatrix4fv( loc, 1, viewMatrix.AsFloat() );
70 // set projection matrix if program has not yet received it this frame or if it is dirty
71 loc = program.GetUniformLocation( Program::UNIFORM_PROJECTION_MATRIX );
72 if( Program::UNIFORM_UNKNOWN != loc )
74 if( program.GetProjectionMatrix() != &projectionMatrix )
76 program.SetProjectionMatrix( &projectionMatrix );
77 program.SetUniformMatrix4fv( loc, 1, projectionMatrix.AsFloat() );
80 loc = program.GetUniformLocation(Program::UNIFORM_MODELVIEW_MATRIX);
81 if( Program::UNIFORM_UNKNOWN != loc )
83 program.SetUniformMatrix4fv( loc, 1, modelViewMatrix.AsFloat() );
86 loc = program.GetUniformLocation( Program::UNIFORM_MVP_MATRIX );
87 if( Program::UNIFORM_UNKNOWN != loc )
89 Matrix modelViewProjectionMatrix(false);
90 Matrix::Multiply( modelViewProjectionMatrix, modelViewMatrix, projectionMatrix );
91 program.SetUniformMatrix4fv( loc, 1, modelViewProjectionMatrix.AsFloat() );
94 loc = program.GetUniformLocation( Program::UNIFORM_NORMAL_MATRIX );
95 if( Program::UNIFORM_UNKNOWN != loc )
98 normalMatrix = modelViewMatrix;
99 normalMatrix.Invert();
100 normalMatrix.Transpose();
101 program.SetUniformMatrix3fv( loc, 1, normalMatrix.AsFloat() );
110 Renderer* Renderer::New( SceneGraph::RenderDataProvider* dataProvider,
111 Render::Geometry* geometry,
112 uint32_t blendingBitmask,
113 const Vector4& blendColor,
114 FaceCullingMode::Type faceCullingMode,
115 bool preMultipliedAlphaEnabled,
116 DepthWriteMode::Type depthWriteMode,
117 DepthTestMode::Type depthTestMode,
118 DepthFunction::Type depthFunction,
119 StencilParameters& stencilParameters )
121 return new Renderer( dataProvider, geometry, blendingBitmask, blendColor,
122 faceCullingMode, preMultipliedAlphaEnabled, depthWriteMode, depthTestMode,
123 depthFunction, stencilParameters );
126 Renderer::Renderer( SceneGraph::RenderDataProvider* dataProvider,
127 Render::Geometry* geometry,
128 uint32_t blendingBitmask,
129 const Vector4& blendColor,
130 FaceCullingMode::Type faceCullingMode,
131 bool preMultipliedAlphaEnabled,
132 DepthWriteMode::Type depthWriteMode,
133 DepthTestMode::Type depthTestMode,
134 DepthFunction::Type depthFunction,
135 StencilParameters& stencilParameters )
136 : mRenderDataProvider( dataProvider ),
138 mGeometry( geometry ),
140 mAttributesLocation(),
142 mStencilParameters( stencilParameters ),
144 mIndexedDrawFirstElement( 0 ),
145 mIndexedDrawElementsCount( 0 ),
146 mDepthFunction( depthFunction ),
147 mFaceCullingMode( faceCullingMode ),
148 mDepthWriteMode( depthWriteMode ),
149 mDepthTestMode( depthTestMode ),
150 mUpdateAttributesLocation( true ),
151 mPremultipledAlphaEnabled( preMultipliedAlphaEnabled ),
152 mShaderChanged( false ),
155 if( blendingBitmask != 0u )
157 mBlendingOptions.SetBitmask( blendingBitmask );
160 mBlendingOptions.SetBlendColor( blendColor );
163 void Renderer::Initialize( Context& context )
168 Renderer::~Renderer() = default;
170 void Renderer::SetGeometry( Render::Geometry* geometry )
172 mGeometry = geometry;
173 mUpdateAttributesLocation = true;
175 void Renderer::SetDrawCommands( Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size )
177 mDrawCommands.clear();
178 mDrawCommands.insert( mDrawCommands.end(), pDrawCommands, pDrawCommands+size );
181 void Renderer::SetBlending( Context& context, bool blend )
183 context.SetBlend( blend );
186 // Blend color is optional and rarely used
187 const Vector4* blendColor = mBlendingOptions.GetBlendColor();
190 context.SetCustomBlendColor( *blendColor );
194 context.SetDefaultBlendColor();
197 // Set blend source & destination factors
198 context.BlendFuncSeparate( mBlendingOptions.GetBlendSrcFactorRgb(),
199 mBlendingOptions.GetBlendDestFactorRgb(),
200 mBlendingOptions.GetBlendSrcFactorAlpha(),
201 mBlendingOptions.GetBlendDestFactorAlpha() );
203 // Set blend equations
204 Dali::DevelBlendEquation::Type rgbEquation = mBlendingOptions.GetBlendEquationRgb();
205 Dali::DevelBlendEquation::Type alphaEquation = mBlendingOptions.GetBlendEquationAlpha();
207 if( mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled )
209 if( rgbEquation != alphaEquation )
211 DALI_LOG_ERROR( "Advanced Blend Equation have to be appried by using BlendEquation.\n" );
213 context.BlendEquation( rgbEquation );
217 context.BlendEquationSeparate( rgbEquation, alphaEquation );
224 void Renderer::GlContextDestroyed()
226 mGeometry->GlContextDestroyed();
229 void Renderer::GlCleanup()
233 void Renderer::SetUniforms( BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program )
235 // Check if the map has changed
236 DALI_ASSERT_DEBUG( mRenderDataProvider && "No Uniform map data provider available" );
238 const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
240 if( uniformMapDataProvider.GetUniformMapChanged( bufferIndex ) ||
241 node.GetUniformMapChanged(bufferIndex) ||
242 mUniformIndexMap.Count() == 0 ||
245 // Reset shader pointer
246 mShaderChanged = false;
248 const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap( bufferIndex );
249 const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap( bufferIndex );
251 uint32_t maxMaps = static_cast<uint32_t>( uniformMap.Count() + uniformMapNode.Count() ); // 4,294,967,295 maps should be enough
252 mUniformIndexMap.Clear(); // Clear contents, but keep memory if we don't change size
253 mUniformIndexMap.Resize( maxMaps );
255 uint32_t mapIndex = 0;
256 for(; mapIndex < uniformMap.Count() ; ++mapIndex )
258 mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex]->propertyPtr;
259 mUniformIndexMap[mapIndex].uniformIndex = program.RegisterUniform( uniformMap[mapIndex]->uniformName );
262 for( uint32_t nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count() ; ++nodeMapIndex )
264 uint32_t uniformIndex = program.RegisterUniform( uniformMapNode[nodeMapIndex]->uniformName );
266 for( uint32_t i = 0; i<uniformMap.Count(); ++i )
268 if( mUniformIndexMap[i].uniformIndex == uniformIndex )
270 mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
278 mUniformIndexMap[mapIndex].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
279 mUniformIndexMap[mapIndex].uniformIndex = uniformIndex;
284 mUniformIndexMap.Resize( mapIndex );
287 // Set uniforms in local map
288 for( UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
289 end = mUniformIndexMap.End() ;
293 SetUniformFromProperty( bufferIndex, program, *iter );
296 GLint sizeLoc = program.GetUniformLocation( Program::UNIFORM_SIZE );
299 program.SetSizeUniform3f( sizeLoc, size.x, size.y, size.z );
303 void Renderer::SetUniformFromProperty( BufferIndex bufferIndex, Program& program, UniformIndexMap& map )
305 GLint location = program.GetUniformLocation(map.uniformIndex);
306 if( Program::UNIFORM_UNKNOWN != location )
308 // switch based on property type to use correct GL uniform setter
309 switch ( map.propertyValue->GetType() )
311 case Property::INTEGER:
313 program.SetUniform1i( location, map.propertyValue->GetInteger( bufferIndex ) );
316 case Property::FLOAT:
318 program.SetUniform1f( location, map.propertyValue->GetFloat( bufferIndex ) );
321 case Property::VECTOR2:
323 Vector2 value( map.propertyValue->GetVector2( bufferIndex ) );
324 program.SetUniform2f( location, value.x, value.y );
328 case Property::VECTOR3:
330 Vector3 value( map.propertyValue->GetVector3( bufferIndex ) );
331 program.SetUniform3f( location, value.x, value.y, value.z );
335 case Property::VECTOR4:
337 Vector4 value( map.propertyValue->GetVector4( bufferIndex ) );
338 program.SetUniform4f( location, value.x, value.y, value.z, value.w );
342 case Property::ROTATION:
344 Quaternion value( map.propertyValue->GetQuaternion( bufferIndex ) );
345 program.SetUniform4f( location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w );
349 case Property::MATRIX:
351 const Matrix& value = map.propertyValue->GetMatrix(bufferIndex);
352 program.SetUniformMatrix4fv(location, 1, value.AsFloat() );
356 case Property::MATRIX3:
358 const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex);
359 program.SetUniformMatrix3fv(location, 1, value.AsFloat() );
365 // Other property types are ignored
372 bool Renderer::BindTextures( Context& context, Program& program, Vector<GLuint>& boundTextures )
374 uint32_t textureUnit = 0;
377 GLint uniformLocation(-1);
378 std::vector<Render::Sampler*>& samplers( mRenderDataProvider->GetSamplers() );
379 std::vector<Render::Texture*>& textures( mRenderDataProvider->GetTextures() );
380 for( uint32_t i = 0; i < static_cast<uint32_t>( textures.size() ) && result; ++i ) // not expecting more than uint32_t of textures
384 result = textures[i]->Bind(context, textureUnit, samplers[i] );
385 boundTextures.PushBack( textures[i]->GetId() );
386 if( result && program.GetSamplerUniformLocation( i, uniformLocation ) )
388 program.SetUniform1i( uniformLocation, textureUnit );
397 void Renderer::SetFaceCullingMode( FaceCullingMode::Type mode )
399 mFaceCullingMode = mode;
403 void Renderer::SetBlendingBitMask( uint32_t bitmask )
405 mBlendingOptions.SetBitmask( bitmask );
409 void Renderer::SetBlendColor( const Vector4& color )
411 mBlendingOptions.SetBlendColor( color );
415 void Renderer::SetIndexedDrawFirstElement( uint32_t firstElement )
417 mIndexedDrawFirstElement = firstElement;
421 void Renderer::SetIndexedDrawElementsCount( uint32_t elementsCount )
423 mIndexedDrawElementsCount = elementsCount;
427 void Renderer::EnablePreMultipliedAlpha( bool enable )
429 mPremultipledAlphaEnabled = enable;
433 void Renderer::SetDepthWriteMode( DepthWriteMode::Type depthWriteMode )
435 mDepthWriteMode = depthWriteMode;
439 void Renderer::SetDepthTestMode( DepthTestMode::Type depthTestMode )
441 mDepthTestMode = depthTestMode;
445 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
447 return mDepthWriteMode;
450 DepthTestMode::Type Renderer::GetDepthTestMode() const
452 return mDepthTestMode;
455 void Renderer::SetDepthFunction( DepthFunction::Type depthFunction )
457 mDepthFunction = depthFunction;
461 DepthFunction::Type Renderer::GetDepthFunction() const
463 return mDepthFunction;
466 void Renderer::SetRenderMode( RenderMode::Type renderMode )
468 mStencilParameters.renderMode = renderMode;
472 RenderMode::Type Renderer::GetRenderMode() const
474 return mStencilParameters.renderMode;
477 void Renderer::SetStencilFunction( StencilFunction::Type stencilFunction )
479 mStencilParameters.stencilFunction = stencilFunction;
483 StencilFunction::Type Renderer::GetStencilFunction() const
485 return mStencilParameters.stencilFunction;
488 void Renderer::SetStencilFunctionMask( int stencilFunctionMask )
490 mStencilParameters.stencilFunctionMask = stencilFunctionMask;
494 int Renderer::GetStencilFunctionMask() const
496 return mStencilParameters.stencilFunctionMask;
499 void Renderer::SetStencilFunctionReference( int stencilFunctionReference )
501 mStencilParameters.stencilFunctionReference = stencilFunctionReference;
505 int Renderer::GetStencilFunctionReference() const
507 return mStencilParameters.stencilFunctionReference;
510 void Renderer::SetStencilMask( int stencilMask )
512 mStencilParameters.stencilMask = stencilMask;
516 int Renderer::GetStencilMask() const
518 return mStencilParameters.stencilMask;
521 void Renderer::SetStencilOperationOnFail( StencilOperation::Type stencilOperationOnFail )
523 mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
527 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
529 return mStencilParameters.stencilOperationOnFail;
532 void Renderer::SetStencilOperationOnZFail( StencilOperation::Type stencilOperationOnZFail )
534 mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
538 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
540 return mStencilParameters.stencilOperationOnZFail;
543 void Renderer::SetStencilOperationOnZPass( StencilOperation::Type stencilOperationOnZPass )
545 mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
549 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
551 return mStencilParameters.stencilOperationOnZPass;
554 void Renderer::Upload( Context& context )
556 mGeometry->Upload( context );
559 void Renderer::Render( Context& context,
560 BufferIndex bufferIndex,
561 const SceneGraph::NodeDataProvider& node,
562 const Matrix& modelMatrix,
563 const Matrix& modelViewMatrix,
564 const Matrix& viewMatrix,
565 const Matrix& projectionMatrix,
568 Vector<GLuint>& boundTextures,
569 const Dali::Internal::SceneGraph::RenderInstruction& instruction,
570 uint32_t queueIndex )
572 // Before doing anything test if the call happens in the right queue
573 if( mDrawCommands.empty() && queueIndex > 0 )
579 std::vector<DevelRenderer::DrawCommand*> commands;
580 for( auto& cmd : mDrawCommands )
582 if(cmd.queue == queueIndex)
584 commands.emplace_back( &cmd );
588 // Have commands but nothing to be drawn - abort
589 if(!mDrawCommands.empty() && commands.empty())
594 // Get the program to use:
595 Program* program = mRenderDataProvider->GetShader().GetProgram();
598 DALI_LOG_ERROR( "Failed to get program for shader at address %p.\n", reinterpret_cast< void* >( &mRenderDataProvider->GetShader() ) );
603 const Dali::Internal::SceneGraph::Camera* cam = instruction.GetCamera();
604 if (cam->GetReflectionUsed())
606 auto adjFaceCullingMode = mFaceCullingMode;
607 switch( mFaceCullingMode )
609 case FaceCullingMode::Type::FRONT:
611 adjFaceCullingMode = FaceCullingMode::Type::BACK;
614 case FaceCullingMode::Type::BACK:
616 adjFaceCullingMode = FaceCullingMode::Type::FRONT;
621 // nothing to do, leave culling as it is
624 context.CullFace( adjFaceCullingMode );
628 context.CullFace( mFaceCullingMode );
631 // Take the program into use so we can send uniforms to it
634 if( DALI_LIKELY( BindTextures( context, *program, boundTextures ) ) )
636 // Only set up and draw if we have textures and they are all valid
638 // set projection and view matrix if program has not yet received them yet this frame
639 SetMatrices( *program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix );
642 GLint loc = program->GetUniformLocation( Program::UNIFORM_COLOR );
643 if( Program::UNIFORM_UNKNOWN != loc )
645 const Vector4& color = node.GetRenderColor( bufferIndex );
646 if( mPremultipledAlphaEnabled )
648 float alpha = color.a * mRenderDataProvider->GetOpacity( bufferIndex );
649 program->SetUniform4f( loc, color.r * alpha, color.g * alpha, color.b * alpha, alpha );
653 program->SetUniform4f( loc, color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity( bufferIndex ) );
657 SetUniforms( bufferIndex, node, size, *program );
659 if( mUpdateAttributesLocation || mGeometry->AttributesChanged() )
661 mGeometry->GetAttributeLocationFromProgram( mAttributesLocation, *program, bufferIndex );
662 mUpdateAttributesLocation = false;
665 if( mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled )
667 context.BlendBarrier();
670 if(mDrawCommands.empty())
672 SetBlending( context, blend );
674 mGeometry->Draw( context,
677 mIndexedDrawFirstElement,
678 mIndexedDrawElementsCount );
682 for(auto& cmd : commands )
684 if(cmd->queue == queueIndex )
687 SetBlending(context, cmd->queue == DevelRenderer::RENDER_QUEUE_OPAQUE ? false : blend);
688 mGeometry->Draw(context, bufferIndex, mAttributesLocation,
689 cmd->firstIndex, cmd->elementCount);
697 void Renderer::SetSortAttributes( BufferIndex bufferIndex,
698 SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes ) const
700 sortAttributes.shader = &( mRenderDataProvider->GetShader() );
701 sortAttributes.geometry = mGeometry;
704 void Renderer::SetShaderChanged( bool value )
706 mShaderChanged = value;
709 bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
717 if (mShaderChanged || mUpdateAttributesLocation || mGeometry->AttributesChanged())
722 for( const auto& texture : mRenderDataProvider->GetTextures() )
724 if (texture && texture->IsNativeImage())
730 uint64_t hash = 0xc70f6907UL;
731 const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap( bufferIndex );
732 for (const auto* uniformProperty : uniformMapNode)
734 hash = uniformProperty->propertyPtr->Hash(bufferIndex, hash);
737 const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
738 const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap( bufferIndex );
739 for (const auto* uniformProperty : uniformMap)
741 hash = uniformProperty->propertyPtr->Hash(bufferIndex, hash);
744 if (mUniformsHash != hash)
746 mUniformsHash = hash;
753 } // namespace SceneGraph
755 } // namespace Internal