2 * Copyright (c) 2019 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 context.BlendEquationSeparate( mBlendingOptions.GetBlendEquationRgb(),
205 mBlendingOptions.GetBlendEquationAlpha() );
211 void Renderer::GlContextDestroyed()
213 mGeometry->GlContextDestroyed();
216 void Renderer::GlCleanup()
220 void Renderer::SetUniforms( BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program )
222 // Check if the map has changed
223 DALI_ASSERT_DEBUG( mRenderDataProvider && "No Uniform map data provider available" );
225 const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
227 if( uniformMapDataProvider.GetUniformMapChanged( bufferIndex ) ||
228 node.GetUniformMapChanged(bufferIndex) ||
229 mUniformIndexMap.Count() == 0 ||
232 // Reset shader pointer
233 mShaderChanged = false;
235 const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap( bufferIndex );
236 const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap( bufferIndex );
238 uint32_t maxMaps = static_cast<uint32_t>( uniformMap.Count() + uniformMapNode.Count() ); // 4,294,967,295 maps should be enough
239 mUniformIndexMap.Clear(); // Clear contents, but keep memory if we don't change size
240 mUniformIndexMap.Resize( maxMaps );
242 uint32_t mapIndex = 0;
243 for(; mapIndex < uniformMap.Count() ; ++mapIndex )
245 mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex]->propertyPtr;
246 mUniformIndexMap[mapIndex].uniformIndex = program.RegisterUniform( uniformMap[mapIndex]->uniformName );
249 for( uint32_t nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count() ; ++nodeMapIndex )
251 uint32_t uniformIndex = program.RegisterUniform( uniformMapNode[nodeMapIndex]->uniformName );
253 for( uint32_t i = 0; i<uniformMap.Count(); ++i )
255 if( mUniformIndexMap[i].uniformIndex == uniformIndex )
257 mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
265 mUniformIndexMap[mapIndex].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
266 mUniformIndexMap[mapIndex].uniformIndex = uniformIndex;
271 mUniformIndexMap.Resize( mapIndex );
274 // Set uniforms in local map
275 for( UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
276 end = mUniformIndexMap.End() ;
280 SetUniformFromProperty( bufferIndex, program, *iter );
283 GLint sizeLoc = program.GetUniformLocation( Program::UNIFORM_SIZE );
286 program.SetSizeUniform3f( sizeLoc, size.x, size.y, size.z );
290 void Renderer::SetUniformFromProperty( BufferIndex bufferIndex, Program& program, UniformIndexMap& map )
292 GLint location = program.GetUniformLocation(map.uniformIndex);
293 if( Program::UNIFORM_UNKNOWN != location )
295 // switch based on property type to use correct GL uniform setter
296 switch ( map.propertyValue->GetType() )
298 case Property::INTEGER:
300 program.SetUniform1i( location, map.propertyValue->GetInteger( bufferIndex ) );
303 case Property::FLOAT:
305 program.SetUniform1f( location, map.propertyValue->GetFloat( bufferIndex ) );
308 case Property::VECTOR2:
310 Vector2 value( map.propertyValue->GetVector2( bufferIndex ) );
311 program.SetUniform2f( location, value.x, value.y );
315 case Property::VECTOR3:
317 Vector3 value( map.propertyValue->GetVector3( bufferIndex ) );
318 program.SetUniform3f( location, value.x, value.y, value.z );
322 case Property::VECTOR4:
324 Vector4 value( map.propertyValue->GetVector4( bufferIndex ) );
325 program.SetUniform4f( location, value.x, value.y, value.z, value.w );
329 case Property::ROTATION:
331 Quaternion value( map.propertyValue->GetQuaternion( bufferIndex ) );
332 program.SetUniform4f( location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w );
336 case Property::MATRIX:
338 const Matrix& value = map.propertyValue->GetMatrix(bufferIndex);
339 program.SetUniformMatrix4fv(location, 1, value.AsFloat() );
343 case Property::MATRIX3:
345 const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex);
346 program.SetUniformMatrix3fv(location, 1, value.AsFloat() );
352 // Other property types are ignored
359 bool Renderer::BindTextures( Context& context, Program& program, Vector<GLuint>& boundTextures )
361 uint32_t textureUnit = 0;
364 GLint uniformLocation(-1);
365 std::vector<Render::Sampler*>& samplers( mRenderDataProvider->GetSamplers() );
366 std::vector<Render::Texture*>& textures( mRenderDataProvider->GetTextures() );
367 for( uint32_t i = 0; i < static_cast<uint32_t>( textures.size() ) && result; ++i ) // not expecting more than uint32_t of textures
371 result = textures[i]->Bind(context, textureUnit, samplers[i] );
372 boundTextures.PushBack( textures[i]->GetId() );
373 if( result && program.GetSamplerUniformLocation( i, uniformLocation ) )
375 program.SetUniform1i( uniformLocation, textureUnit );
384 void Renderer::SetFaceCullingMode( FaceCullingMode::Type mode )
386 mFaceCullingMode = mode;
390 void Renderer::SetBlendingBitMask( uint32_t bitmask )
392 mBlendingOptions.SetBitmask( bitmask );
396 void Renderer::SetBlendColor( const Vector4& color )
398 mBlendingOptions.SetBlendColor( color );
402 void Renderer::SetIndexedDrawFirstElement( uint32_t firstElement )
404 mIndexedDrawFirstElement = firstElement;
408 void Renderer::SetIndexedDrawElementsCount( uint32_t elementsCount )
410 mIndexedDrawElementsCount = elementsCount;
414 void Renderer::EnablePreMultipliedAlpha( bool enable )
416 mPremultipledAlphaEnabled = enable;
420 void Renderer::SetDepthWriteMode( DepthWriteMode::Type depthWriteMode )
422 mDepthWriteMode = depthWriteMode;
426 void Renderer::SetDepthTestMode( DepthTestMode::Type depthTestMode )
428 mDepthTestMode = depthTestMode;
432 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
434 return mDepthWriteMode;
437 DepthTestMode::Type Renderer::GetDepthTestMode() const
439 return mDepthTestMode;
442 void Renderer::SetDepthFunction( DepthFunction::Type depthFunction )
444 mDepthFunction = depthFunction;
448 DepthFunction::Type Renderer::GetDepthFunction() const
450 return mDepthFunction;
453 void Renderer::SetRenderMode( RenderMode::Type renderMode )
455 mStencilParameters.renderMode = renderMode;
459 RenderMode::Type Renderer::GetRenderMode() const
461 return mStencilParameters.renderMode;
464 void Renderer::SetStencilFunction( StencilFunction::Type stencilFunction )
466 mStencilParameters.stencilFunction = stencilFunction;
470 StencilFunction::Type Renderer::GetStencilFunction() const
472 return mStencilParameters.stencilFunction;
475 void Renderer::SetStencilFunctionMask( int stencilFunctionMask )
477 mStencilParameters.stencilFunctionMask = stencilFunctionMask;
481 int Renderer::GetStencilFunctionMask() const
483 return mStencilParameters.stencilFunctionMask;
486 void Renderer::SetStencilFunctionReference( int stencilFunctionReference )
488 mStencilParameters.stencilFunctionReference = stencilFunctionReference;
492 int Renderer::GetStencilFunctionReference() const
494 return mStencilParameters.stencilFunctionReference;
497 void Renderer::SetStencilMask( int stencilMask )
499 mStencilParameters.stencilMask = stencilMask;
503 int Renderer::GetStencilMask() const
505 return mStencilParameters.stencilMask;
508 void Renderer::SetStencilOperationOnFail( StencilOperation::Type stencilOperationOnFail )
510 mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
514 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
516 return mStencilParameters.stencilOperationOnFail;
519 void Renderer::SetStencilOperationOnZFail( StencilOperation::Type stencilOperationOnZFail )
521 mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
525 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
527 return mStencilParameters.stencilOperationOnZFail;
530 void Renderer::SetStencilOperationOnZPass( StencilOperation::Type stencilOperationOnZPass )
532 mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
536 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
538 return mStencilParameters.stencilOperationOnZPass;
541 void Renderer::Upload( Context& context )
543 mGeometry->Upload( context );
546 void Renderer::Render( Context& context,
547 BufferIndex bufferIndex,
548 const SceneGraph::NodeDataProvider& node,
549 const Matrix& modelMatrix,
550 const Matrix& modelViewMatrix,
551 const Matrix& viewMatrix,
552 const Matrix& projectionMatrix,
555 Vector<GLuint>& boundTextures,
556 const Dali::Internal::SceneGraph::RenderInstruction& instruction,
557 uint32_t queueIndex )
559 // Before doing anything test if the call happens in the right queue
560 if( mDrawCommands.empty() && queueIndex > 0 )
566 std::vector<DevelRenderer::DrawCommand*> commands;
567 for( auto& cmd : mDrawCommands )
569 if(cmd.queue == queueIndex)
571 commands.emplace_back( &cmd );
575 // Have commands but nothing to be drawn - abort
576 if(!mDrawCommands.empty() && commands.empty())
581 // Get the program to use:
582 Program* program = mRenderDataProvider->GetShader().GetProgram();
585 DALI_LOG_ERROR( "Failed to get program for shader at address %p.\n", reinterpret_cast< void* >( &mRenderDataProvider->GetShader() ) );
590 const Dali::Internal::SceneGraph::Camera* cam = instruction.GetCamera();
591 if (cam->GetReflectionUsed())
593 auto adjFaceCullingMode = mFaceCullingMode;
594 switch( mFaceCullingMode )
596 case FaceCullingMode::Type::FRONT:
598 adjFaceCullingMode = FaceCullingMode::Type::BACK;
601 case FaceCullingMode::Type::BACK:
603 adjFaceCullingMode = FaceCullingMode::Type::FRONT;
608 // nothing to do, leave culling as it is
611 context.CullFace( adjFaceCullingMode );
615 context.CullFace( mFaceCullingMode );
618 // Take the program into use so we can send uniforms to it
621 if( DALI_LIKELY( BindTextures( context, *program, boundTextures ) ) )
623 // Only set up and draw if we have textures and they are all valid
625 // set projection and view matrix if program has not yet received them yet this frame
626 SetMatrices( *program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix );
629 GLint loc = program->GetUniformLocation( Program::UNIFORM_COLOR );
630 if( Program::UNIFORM_UNKNOWN != loc )
632 const Vector4& color = node.GetRenderColor( bufferIndex );
633 if( mPremultipledAlphaEnabled )
635 float alpha = color.a * mRenderDataProvider->GetOpacity( bufferIndex );
636 program->SetUniform4f( loc, color.r * alpha, color.g * alpha, color.b * alpha, alpha );
640 program->SetUniform4f( loc, color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity( bufferIndex ) );
644 SetUniforms( bufferIndex, node, size, *program );
646 if( mUpdateAttributesLocation || mGeometry->AttributesChanged() )
648 mGeometry->GetAttributeLocationFromProgram( mAttributesLocation, *program, bufferIndex );
649 mUpdateAttributesLocation = false;
652 if(mDrawCommands.empty())
654 SetBlending( context, blend );
656 mGeometry->Draw( context,
659 mIndexedDrawFirstElement,
660 mIndexedDrawElementsCount );
664 for(auto& cmd : commands )
666 if(cmd->queue == queueIndex )
669 SetBlending(context, cmd->queue == DevelRenderer::RENDER_QUEUE_OPAQUE ? false : blend);
670 mGeometry->Draw(context, bufferIndex, mAttributesLocation,
671 cmd->firstIndex, cmd->elementCount);
679 void Renderer::SetSortAttributes( BufferIndex bufferIndex,
680 SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes ) const
682 sortAttributes.shader = &( mRenderDataProvider->GetShader() );
683 sortAttributes.geometry = mGeometry;
686 void Renderer::SetShaderChanged( bool value )
688 mShaderChanged = value;
691 bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
699 if (mShaderChanged || mUpdateAttributesLocation || mGeometry->AttributesChanged())
704 for( const auto& texture : mRenderDataProvider->GetTextures() )
706 if (texture && texture->IsNativeImage())
712 uint64_t hash = 0xc70f6907UL;
713 const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap( bufferIndex );
714 for (const auto* uniformProperty : uniformMapNode)
716 hash = uniformProperty->propertyPtr->Hash(bufferIndex, hash);
719 const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
720 const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap( bufferIndex );
721 for (const auto* uniformProperty : uniformMap)
723 hash = uniformProperty->propertyPtr->Hash(bufferIndex, hash);
726 if (mUniformsHash != hash)
728 mUniformsHash = hash;
735 } // namespace SceneGraph
737 } // namespace Internal