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;
178 void Renderer::SetBlending( Context& context, bool blend )
180 context.SetBlend( blend );
183 // Blend color is optional and rarely used
184 const Vector4* blendColor = mBlendingOptions.GetBlendColor();
187 context.SetCustomBlendColor( *blendColor );
191 context.SetDefaultBlendColor();
194 // Set blend source & destination factors
195 context.BlendFuncSeparate( mBlendingOptions.GetBlendSrcFactorRgb(),
196 mBlendingOptions.GetBlendDestFactorRgb(),
197 mBlendingOptions.GetBlendSrcFactorAlpha(),
198 mBlendingOptions.GetBlendDestFactorAlpha() );
200 // Set blend equations
201 context.BlendEquationSeparate( mBlendingOptions.GetBlendEquationRgb(),
202 mBlendingOptions.GetBlendEquationAlpha() );
208 void Renderer::GlContextDestroyed()
210 mGeometry->GlContextDestroyed();
213 void Renderer::GlCleanup()
217 void Renderer::SetUniforms( BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program )
219 // Check if the map has changed
220 DALI_ASSERT_DEBUG( mRenderDataProvider && "No Uniform map data provider available" );
222 const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
224 if( uniformMapDataProvider.GetUniformMapChanged( bufferIndex ) ||
225 node.GetUniformMapChanged(bufferIndex) ||
226 mUniformIndexMap.Count() == 0 ||
229 // Reset shader pointer
230 mShaderChanged = false;
232 const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap( bufferIndex );
233 const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap( bufferIndex );
235 uint32_t maxMaps = static_cast<uint32_t>( uniformMap.Count() + uniformMapNode.Count() ); // 4,294,967,295 maps should be enough
236 mUniformIndexMap.Clear(); // Clear contents, but keep memory if we don't change size
237 mUniformIndexMap.Resize( maxMaps );
239 uint32_t mapIndex = 0;
240 for(; mapIndex < uniformMap.Count() ; ++mapIndex )
242 mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex]->propertyPtr;
243 mUniformIndexMap[mapIndex].uniformIndex = program.RegisterUniform( uniformMap[mapIndex]->uniformName );
246 for( uint32_t nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count() ; ++nodeMapIndex )
248 uint32_t uniformIndex = program.RegisterUniform( uniformMapNode[nodeMapIndex]->uniformName );
250 for( uint32_t i = 0; i<uniformMap.Count(); ++i )
252 if( mUniformIndexMap[i].uniformIndex == uniformIndex )
254 mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
262 mUniformIndexMap[mapIndex].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
263 mUniformIndexMap[mapIndex].uniformIndex = uniformIndex;
268 mUniformIndexMap.Resize( mapIndex );
271 // Set uniforms in local map
272 for( UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
273 end = mUniformIndexMap.End() ;
277 SetUniformFromProperty( bufferIndex, program, *iter );
280 GLint sizeLoc = program.GetUniformLocation( Program::UNIFORM_SIZE );
283 program.SetSizeUniform3f( sizeLoc, size.x, size.y, size.z );
287 void Renderer::SetUniformFromProperty( BufferIndex bufferIndex, Program& program, UniformIndexMap& map )
289 GLint location = program.GetUniformLocation(map.uniformIndex);
290 if( Program::UNIFORM_UNKNOWN != location )
292 // switch based on property type to use correct GL uniform setter
293 switch ( map.propertyValue->GetType() )
295 case Property::INTEGER:
297 program.SetUniform1i( location, map.propertyValue->GetInteger( bufferIndex ) );
300 case Property::FLOAT:
302 program.SetUniform1f( location, map.propertyValue->GetFloat( bufferIndex ) );
305 case Property::VECTOR2:
307 Vector2 value( map.propertyValue->GetVector2( bufferIndex ) );
308 program.SetUniform2f( location, value.x, value.y );
312 case Property::VECTOR3:
314 Vector3 value( map.propertyValue->GetVector3( bufferIndex ) );
315 program.SetUniform3f( location, value.x, value.y, value.z );
319 case Property::VECTOR4:
321 Vector4 value( map.propertyValue->GetVector4( bufferIndex ) );
322 program.SetUniform4f( location, value.x, value.y, value.z, value.w );
326 case Property::ROTATION:
328 Quaternion value( map.propertyValue->GetQuaternion( bufferIndex ) );
329 program.SetUniform4f( location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w );
333 case Property::MATRIX:
335 const Matrix& value = map.propertyValue->GetMatrix(bufferIndex);
336 program.SetUniformMatrix4fv(location, 1, value.AsFloat() );
340 case Property::MATRIX3:
342 const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex);
343 program.SetUniformMatrix3fv(location, 1, value.AsFloat() );
349 // Other property types are ignored
356 bool Renderer::BindTextures( Context& context, Program& program, Vector<GLuint>& boundTextures )
358 uint32_t textureUnit = 0;
361 GLint uniformLocation(-1);
362 std::vector<Render::Sampler*>& samplers( mRenderDataProvider->GetSamplers() );
363 std::vector<Render::Texture*>& textures( mRenderDataProvider->GetTextures() );
364 for( uint32_t i = 0; i < static_cast<uint32_t>( textures.size() ) && result; ++i ) // not expecting more than uint32_t of textures
368 result = textures[i]->Bind(context, textureUnit, samplers[i] );
369 boundTextures.PushBack( textures[i]->GetId() );
370 if( result && program.GetSamplerUniformLocation( i, uniformLocation ) )
372 program.SetUniform1i( uniformLocation, textureUnit );
381 void Renderer::SetFaceCullingMode( FaceCullingMode::Type mode )
383 mFaceCullingMode = mode;
387 void Renderer::SetBlendingBitMask( uint32_t bitmask )
389 mBlendingOptions.SetBitmask( bitmask );
393 void Renderer::SetBlendColor( const Vector4& color )
395 mBlendingOptions.SetBlendColor( color );
399 void Renderer::SetIndexedDrawFirstElement( uint32_t firstElement )
401 mIndexedDrawFirstElement = firstElement;
405 void Renderer::SetIndexedDrawElementsCount( uint32_t elementsCount )
407 mIndexedDrawElementsCount = elementsCount;
411 void Renderer::EnablePreMultipliedAlpha( bool enable )
413 mPremultipledAlphaEnabled = enable;
417 void Renderer::SetDepthWriteMode( DepthWriteMode::Type depthWriteMode )
419 mDepthWriteMode = depthWriteMode;
423 void Renderer::SetDepthTestMode( DepthTestMode::Type depthTestMode )
425 mDepthTestMode = depthTestMode;
429 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
431 return mDepthWriteMode;
434 DepthTestMode::Type Renderer::GetDepthTestMode() const
436 return mDepthTestMode;
439 void Renderer::SetDepthFunction( DepthFunction::Type depthFunction )
441 mDepthFunction = depthFunction;
445 DepthFunction::Type Renderer::GetDepthFunction() const
447 return mDepthFunction;
450 void Renderer::SetRenderMode( RenderMode::Type renderMode )
452 mStencilParameters.renderMode = renderMode;
456 RenderMode::Type Renderer::GetRenderMode() const
458 return mStencilParameters.renderMode;
461 void Renderer::SetStencilFunction( StencilFunction::Type stencilFunction )
463 mStencilParameters.stencilFunction = stencilFunction;
467 StencilFunction::Type Renderer::GetStencilFunction() const
469 return mStencilParameters.stencilFunction;
472 void Renderer::SetStencilFunctionMask( int stencilFunctionMask )
474 mStencilParameters.stencilFunctionMask = stencilFunctionMask;
478 int Renderer::GetStencilFunctionMask() const
480 return mStencilParameters.stencilFunctionMask;
483 void Renderer::SetStencilFunctionReference( int stencilFunctionReference )
485 mStencilParameters.stencilFunctionReference = stencilFunctionReference;
489 int Renderer::GetStencilFunctionReference() const
491 return mStencilParameters.stencilFunctionReference;
494 void Renderer::SetStencilMask( int stencilMask )
496 mStencilParameters.stencilMask = stencilMask;
500 int Renderer::GetStencilMask() const
502 return mStencilParameters.stencilMask;
505 void Renderer::SetStencilOperationOnFail( StencilOperation::Type stencilOperationOnFail )
507 mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
511 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
513 return mStencilParameters.stencilOperationOnFail;
516 void Renderer::SetStencilOperationOnZFail( StencilOperation::Type stencilOperationOnZFail )
518 mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
522 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
524 return mStencilParameters.stencilOperationOnZFail;
527 void Renderer::SetStencilOperationOnZPass( StencilOperation::Type stencilOperationOnZPass )
529 mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
533 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
535 return mStencilParameters.stencilOperationOnZPass;
538 void Renderer::Upload( Context& context )
540 mGeometry->Upload( context );
543 void Renderer::Render( Context& context,
544 BufferIndex bufferIndex,
545 const SceneGraph::NodeDataProvider& node,
546 const Matrix& modelMatrix,
547 const Matrix& modelViewMatrix,
548 const Matrix& viewMatrix,
549 const Matrix& projectionMatrix,
552 Vector<GLuint>& boundTextures,
553 const Dali::Internal::SceneGraph::RenderInstruction& instruction )
555 // Get the program to use:
556 Program* program = mRenderDataProvider->GetShader().GetProgram();
559 DALI_LOG_ERROR( "Failed to get program for shader at address %p.\n", reinterpret_cast< void* >( &mRenderDataProvider->GetShader() ) );
564 const Dali::Internal::SceneGraph::Camera* cam = instruction.GetCamera();
565 if (cam->GetReflectionUsed())
567 auto adjFaceCullingMode = mFaceCullingMode;
568 switch( mFaceCullingMode )
570 case FaceCullingMode::Type::FRONT:
572 adjFaceCullingMode = FaceCullingMode::Type::BACK;
575 case FaceCullingMode::Type::BACK:
577 adjFaceCullingMode = FaceCullingMode::Type::FRONT;
582 // nothing to do, leave culling as it is
585 context.CullFace( adjFaceCullingMode );
589 context.CullFace( mFaceCullingMode );
593 SetBlending( context, blend );
595 // Take the program into use so we can send uniforms to it
598 if( DALI_LIKELY( BindTextures( context, *program, boundTextures ) ) )
600 // Only set up and draw if we have textures and they are all valid
602 // set projection and view matrix if program has not yet received them yet this frame
603 SetMatrices( *program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix );
606 GLint loc = program->GetUniformLocation( Program::UNIFORM_COLOR );
607 if( Program::UNIFORM_UNKNOWN != loc )
609 const Vector4& color = node.GetRenderColor( bufferIndex );
610 if( mPremultipledAlphaEnabled )
612 float alpha = color.a * mRenderDataProvider->GetOpacity( bufferIndex );
613 program->SetUniform4f( loc, color.r * alpha, color.g * alpha, color.b * alpha, alpha );
617 program->SetUniform4f( loc, color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity( bufferIndex ) );
621 SetUniforms( bufferIndex, node, size, *program );
623 if( mUpdateAttributesLocation || mGeometry->AttributesChanged() )
625 mGeometry->GetAttributeLocationFromProgram( mAttributesLocation, *program, bufferIndex );
626 mUpdateAttributesLocation = false;
629 mGeometry->Draw( context,
632 mIndexedDrawFirstElement,
633 mIndexedDrawElementsCount );
639 void Renderer::SetSortAttributes( BufferIndex bufferIndex,
640 SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes ) const
642 sortAttributes.shader = &( mRenderDataProvider->GetShader() );
643 sortAttributes.geometry = mGeometry;
646 void Renderer::SetShaderChanged( bool value )
648 mShaderChanged = value;
651 bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
659 if (mShaderChanged || mUpdateAttributesLocation || mGeometry->AttributesChanged())
664 std::vector<Render::Texture*> textures = mRenderDataProvider->GetTextures();
665 for (Render::Texture* texture : textures)
667 if (texture && texture->IsNativeImage())
673 uint64_t hash = 0xc70f6907UL;
674 const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap( bufferIndex );
675 for (const auto* uniformProperty : uniformMapNode)
677 hash = uniformProperty->propertyPtr->Hash(bufferIndex, hash);
680 const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
681 const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap( bufferIndex );
682 for (const auto* uniformProperty : uniformMap)
684 hash = uniformProperty->propertyPtr->Hash(bufferIndex, hash);
687 if (mUniformsHash != hash)
689 mUniformsHash = hash;
696 } // namespace SceneGraph
698 } // namespace Internal