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()
172 void Renderer::SetGeometry( Render::Geometry* geometry )
174 mGeometry = geometry;
175 mUpdateAttributesLocation = true;
177 void Renderer::SetDrawCommands( Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size )
179 mDrawCommands.clear();
180 mDrawCommands.insert( mDrawCommands.end(), pDrawCommands, pDrawCommands+size );
183 void Renderer::SetBlending( Context& context, bool blend )
185 context.SetBlend( blend );
188 // Blend color is optional and rarely used
189 const Vector4* blendColor = mBlendingOptions.GetBlendColor();
192 context.SetCustomBlendColor( *blendColor );
196 context.SetDefaultBlendColor();
199 // Set blend source & destination factors
200 context.BlendFuncSeparate( mBlendingOptions.GetBlendSrcFactorRgb(),
201 mBlendingOptions.GetBlendDestFactorRgb(),
202 mBlendingOptions.GetBlendSrcFactorAlpha(),
203 mBlendingOptions.GetBlendDestFactorAlpha() );
205 // Set blend equations
206 context.BlendEquationSeparate( mBlendingOptions.GetBlendEquationRgb(),
207 mBlendingOptions.GetBlendEquationAlpha() );
213 void Renderer::GlContextDestroyed()
215 mGeometry->GlContextDestroyed();
218 void Renderer::GlCleanup()
222 void Renderer::SetUniforms( BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program )
224 // Check if the map has changed
225 DALI_ASSERT_DEBUG( mRenderDataProvider && "No Uniform map data provider available" );
227 const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
229 if( uniformMapDataProvider.GetUniformMapChanged( bufferIndex ) ||
230 node.GetUniformMapChanged(bufferIndex) ||
231 mUniformIndexMap.Count() == 0 ||
234 // Reset shader pointer
235 mShaderChanged = false;
237 const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap( bufferIndex );
238 const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap( bufferIndex );
240 uint32_t maxMaps = static_cast<uint32_t>( uniformMap.Count() + uniformMapNode.Count() ); // 4,294,967,295 maps should be enough
241 mUniformIndexMap.Clear(); // Clear contents, but keep memory if we don't change size
242 mUniformIndexMap.Resize( maxMaps );
244 uint32_t mapIndex = 0;
245 for(; mapIndex < uniformMap.Count() ; ++mapIndex )
247 mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex]->propertyPtr;
248 mUniformIndexMap[mapIndex].uniformIndex = program.RegisterUniform( uniformMap[mapIndex]->uniformName );
251 for( uint32_t nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count() ; ++nodeMapIndex )
253 uint32_t uniformIndex = program.RegisterUniform( uniformMapNode[nodeMapIndex]->uniformName );
255 for( uint32_t i = 0; i<uniformMap.Count(); ++i )
257 if( mUniformIndexMap[i].uniformIndex == uniformIndex )
259 mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
267 mUniformIndexMap[mapIndex].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
268 mUniformIndexMap[mapIndex].uniformIndex = uniformIndex;
273 mUniformIndexMap.Resize( mapIndex );
276 // Set uniforms in local map
277 for( UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
278 end = mUniformIndexMap.End() ;
282 SetUniformFromProperty( bufferIndex, program, *iter );
285 GLint sizeLoc = program.GetUniformLocation( Program::UNIFORM_SIZE );
288 program.SetSizeUniform3f( sizeLoc, size.x, size.y, size.z );
292 void Renderer::SetUniformFromProperty( BufferIndex bufferIndex, Program& program, UniformIndexMap& map )
294 GLint location = program.GetUniformLocation(map.uniformIndex);
295 if( Program::UNIFORM_UNKNOWN != location )
297 // switch based on property type to use correct GL uniform setter
298 switch ( map.propertyValue->GetType() )
300 case Property::INTEGER:
302 program.SetUniform1i( location, map.propertyValue->GetInteger( bufferIndex ) );
305 case Property::FLOAT:
307 program.SetUniform1f( location, map.propertyValue->GetFloat( bufferIndex ) );
310 case Property::VECTOR2:
312 Vector2 value( map.propertyValue->GetVector2( bufferIndex ) );
313 program.SetUniform2f( location, value.x, value.y );
317 case Property::VECTOR3:
319 Vector3 value( map.propertyValue->GetVector3( bufferIndex ) );
320 program.SetUniform3f( location, value.x, value.y, value.z );
324 case Property::VECTOR4:
326 Vector4 value( map.propertyValue->GetVector4( bufferIndex ) );
327 program.SetUniform4f( location, value.x, value.y, value.z, value.w );
331 case Property::ROTATION:
333 Quaternion value( map.propertyValue->GetQuaternion( bufferIndex ) );
334 program.SetUniform4f( location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w );
338 case Property::MATRIX:
340 const Matrix& value = map.propertyValue->GetMatrix(bufferIndex);
341 program.SetUniformMatrix4fv(location, 1, value.AsFloat() );
345 case Property::MATRIX3:
347 const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex);
348 program.SetUniformMatrix3fv(location, 1, value.AsFloat() );
354 // Other property types are ignored
361 bool Renderer::BindTextures( Context& context, Program& program, Vector<GLuint>& boundTextures )
363 uint32_t textureUnit = 0;
366 GLint uniformLocation(-1);
367 std::vector<Render::Sampler*>& samplers( mRenderDataProvider->GetSamplers() );
368 std::vector<Render::Texture*>& textures( mRenderDataProvider->GetTextures() );
369 for( uint32_t i = 0; i < static_cast<uint32_t>( textures.size() ) && result; ++i ) // not expecting more than uint32_t of textures
373 result = textures[i]->Bind(context, textureUnit, samplers[i] );
374 boundTextures.PushBack( textures[i]->GetId() );
375 if( result && program.GetSamplerUniformLocation( i, uniformLocation ) )
377 program.SetUniform1i( uniformLocation, textureUnit );
386 void Renderer::SetFaceCullingMode( FaceCullingMode::Type mode )
388 mFaceCullingMode = mode;
392 void Renderer::SetBlendingBitMask( uint32_t bitmask )
394 mBlendingOptions.SetBitmask( bitmask );
398 void Renderer::SetBlendColor( const Vector4& color )
400 mBlendingOptions.SetBlendColor( color );
404 void Renderer::SetIndexedDrawFirstElement( uint32_t firstElement )
406 mIndexedDrawFirstElement = firstElement;
410 void Renderer::SetIndexedDrawElementsCount( uint32_t elementsCount )
412 mIndexedDrawElementsCount = elementsCount;
416 void Renderer::EnablePreMultipliedAlpha( bool enable )
418 mPremultipledAlphaEnabled = enable;
422 void Renderer::SetDepthWriteMode( DepthWriteMode::Type depthWriteMode )
424 mDepthWriteMode = depthWriteMode;
428 void Renderer::SetDepthTestMode( DepthTestMode::Type depthTestMode )
430 mDepthTestMode = depthTestMode;
434 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
436 return mDepthWriteMode;
439 DepthTestMode::Type Renderer::GetDepthTestMode() const
441 return mDepthTestMode;
444 void Renderer::SetDepthFunction( DepthFunction::Type depthFunction )
446 mDepthFunction = depthFunction;
450 DepthFunction::Type Renderer::GetDepthFunction() const
452 return mDepthFunction;
455 void Renderer::SetRenderMode( RenderMode::Type renderMode )
457 mStencilParameters.renderMode = renderMode;
461 RenderMode::Type Renderer::GetRenderMode() const
463 return mStencilParameters.renderMode;
466 void Renderer::SetStencilFunction( StencilFunction::Type stencilFunction )
468 mStencilParameters.stencilFunction = stencilFunction;
472 StencilFunction::Type Renderer::GetStencilFunction() const
474 return mStencilParameters.stencilFunction;
477 void Renderer::SetStencilFunctionMask( int stencilFunctionMask )
479 mStencilParameters.stencilFunctionMask = stencilFunctionMask;
483 int Renderer::GetStencilFunctionMask() const
485 return mStencilParameters.stencilFunctionMask;
488 void Renderer::SetStencilFunctionReference( int stencilFunctionReference )
490 mStencilParameters.stencilFunctionReference = stencilFunctionReference;
494 int Renderer::GetStencilFunctionReference() const
496 return mStencilParameters.stencilFunctionReference;
499 void Renderer::SetStencilMask( int stencilMask )
501 mStencilParameters.stencilMask = stencilMask;
505 int Renderer::GetStencilMask() const
507 return mStencilParameters.stencilMask;
510 void Renderer::SetStencilOperationOnFail( StencilOperation::Type stencilOperationOnFail )
512 mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
516 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
518 return mStencilParameters.stencilOperationOnFail;
521 void Renderer::SetStencilOperationOnZFail( StencilOperation::Type stencilOperationOnZFail )
523 mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
527 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
529 return mStencilParameters.stencilOperationOnZFail;
532 void Renderer::SetStencilOperationOnZPass( StencilOperation::Type stencilOperationOnZPass )
534 mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
538 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
540 return mStencilParameters.stencilOperationOnZPass;
543 void Renderer::Upload( Context& context )
545 mGeometry->Upload( context );
548 void Renderer::Render( Context& context,
549 BufferIndex bufferIndex,
550 const SceneGraph::NodeDataProvider& node,
551 const Matrix& modelMatrix,
552 const Matrix& modelViewMatrix,
553 const Matrix& viewMatrix,
554 const Matrix& projectionMatrix,
557 Vector<GLuint>& boundTextures,
558 const Dali::Internal::SceneGraph::RenderInstruction& instruction,
559 uint32_t queueIndex )
561 // Before doing anything test if the call happens in the right queue
562 if( mDrawCommands.empty() && queueIndex > 0 )
568 std::vector<DevelRenderer::DrawCommand*> commands;
569 for( auto& cmd : mDrawCommands )
571 if(cmd.queue == queueIndex)
573 commands.emplace_back( &cmd );
577 // Have commands but nothing to be drawn - abort
578 if(!mDrawCommands.empty() && commands.empty())
583 // Get the program to use:
584 Program* program = mRenderDataProvider->GetShader().GetProgram();
587 DALI_LOG_ERROR( "Failed to get program for shader at address %p.\n", reinterpret_cast< void* >( &mRenderDataProvider->GetShader() ) );
592 const Dali::Internal::SceneGraph::Camera* cam = instruction.GetCamera();
593 if (cam->GetReflectionUsed())
595 auto adjFaceCullingMode = mFaceCullingMode;
596 switch( mFaceCullingMode )
598 case FaceCullingMode::Type::FRONT:
600 adjFaceCullingMode = FaceCullingMode::Type::BACK;
603 case FaceCullingMode::Type::BACK:
605 adjFaceCullingMode = FaceCullingMode::Type::FRONT;
610 // nothing to do, leave culling as it is
613 context.CullFace( adjFaceCullingMode );
617 context.CullFace( mFaceCullingMode );
620 // Take the program into use so we can send uniforms to it
623 if( DALI_LIKELY( BindTextures( context, *program, boundTextures ) ) )
625 // Only set up and draw if we have textures and they are all valid
627 // set projection and view matrix if program has not yet received them yet this frame
628 SetMatrices( *program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix );
631 GLint loc = program->GetUniformLocation( Program::UNIFORM_COLOR );
632 if( Program::UNIFORM_UNKNOWN != loc )
634 const Vector4& color = node.GetRenderColor( bufferIndex );
635 if( mPremultipledAlphaEnabled )
637 float alpha = color.a * mRenderDataProvider->GetOpacity( bufferIndex );
638 program->SetUniform4f( loc, color.r * alpha, color.g * alpha, color.b * alpha, alpha );
642 program->SetUniform4f( loc, color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity( bufferIndex ) );
646 SetUniforms( bufferIndex, node, size, *program );
648 if( mUpdateAttributesLocation || mGeometry->AttributesChanged() )
650 mGeometry->GetAttributeLocationFromProgram( mAttributesLocation, *program, bufferIndex );
651 mUpdateAttributesLocation = false;
654 if(mDrawCommands.empty())
656 SetBlending( context, blend );
658 mGeometry->Draw( context,
661 mIndexedDrawFirstElement,
662 mIndexedDrawElementsCount );
666 for(auto& cmd : commands )
668 if(cmd->queue == queueIndex )
671 SetBlending(context, cmd->queue == DevelRenderer::RENDER_QUEUE_OPAQUE ? false : blend);
672 mGeometry->Draw(context, bufferIndex, mAttributesLocation,
673 cmd->firstIndex, cmd->elementCount);
681 void Renderer::SetSortAttributes( BufferIndex bufferIndex,
682 SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes ) const
684 sortAttributes.shader = &( mRenderDataProvider->GetShader() );
685 sortAttributes.geometry = mGeometry;
688 void Renderer::SetShaderChanged( bool value )
690 mShaderChanged = value;
693 bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
701 if (mShaderChanged || mUpdateAttributesLocation || mGeometry->AttributesChanged())
706 std::vector<Render::Texture*> textures = mRenderDataProvider->GetTextures();
707 for (Render::Texture* texture : textures)
709 if (texture && texture->IsNativeImage())
715 uint64_t hash = 0xc70f6907UL;
716 const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap( bufferIndex );
717 for (const auto* uniformProperty : uniformMapNode)
719 hash = uniformProperty->propertyPtr->Hash(bufferIndex, hash);
722 const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
723 const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap( bufferIndex );
724 for (const auto* uniformProperty : uniformMap)
726 hash = uniformProperty->propertyPtr->Hash(bufferIndex, hash);
729 if (mUniformsHash != hash)
731 mUniformsHash = hash;
738 } // namespace SceneGraph
740 } // namespace Internal