2 * Copyright (c) 2016 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-name-cache.h>
29 #include <dali/internal/render/gl-resources/texture-cache.h>
30 #include <dali/public-api/actors/blending.h>
31 #include <dali/internal/render/gl-resources/gl-texture.h>
42 static Matrix gModelViewProjectionMatrix( false ); ///< a shared matrix to calculate the MVP matrix, dont want to store it in object to reduce storage overhead
43 static Matrix3 gNormalMatrix; ///< a shared matrix to calculate normal matrix, dont want to store it in object to reduce storage overhead
46 * Helper to set view and projection matrices once per program
47 * @param program to set the matrices to
48 * @param modelMatrix to set
49 * @param viewMatrix to set
50 * @param projectionMatrix to set
51 * @param modelViewMatrix to set
52 * @param modelViewProjectionMatrix to set
54 inline void SetMatrices( Program& program,
55 const Matrix& modelMatrix,
56 const Matrix& viewMatrix,
57 const Matrix& projectionMatrix,
58 const Matrix& modelViewMatrix )
60 GLint loc = program.GetUniformLocation( Program::UNIFORM_MODEL_MATRIX );
61 if( Program::UNIFORM_UNKNOWN != loc )
63 program.SetUniformMatrix4fv( loc, 1, modelMatrix.AsFloat() );
65 loc = program.GetUniformLocation( Program::UNIFORM_VIEW_MATRIX );
66 if( Program::UNIFORM_UNKNOWN != loc )
68 if( program.GetViewMatrix() != &viewMatrix )
70 program.SetViewMatrix( &viewMatrix );
71 program.SetUniformMatrix4fv( loc, 1, viewMatrix.AsFloat() );
74 // set projection matrix if program has not yet received it this frame or if it is dirty
75 loc = program.GetUniformLocation( Program::UNIFORM_PROJECTION_MATRIX );
76 if( Program::UNIFORM_UNKNOWN != loc )
78 if( program.GetProjectionMatrix() != &projectionMatrix )
80 program.SetProjectionMatrix( &projectionMatrix );
81 program.SetUniformMatrix4fv( loc, 1, projectionMatrix.AsFloat() );
84 loc = program.GetUniformLocation(Program::UNIFORM_MODELVIEW_MATRIX);
85 if( Program::UNIFORM_UNKNOWN != loc )
87 program.SetUniformMatrix4fv( loc, 1, modelViewMatrix.AsFloat() );
90 loc = program.GetUniformLocation( Program::UNIFORM_MVP_MATRIX );
91 if( Program::UNIFORM_UNKNOWN != loc )
93 Matrix::Multiply( gModelViewProjectionMatrix, modelViewMatrix, projectionMatrix );
94 program.SetUniformMatrix4fv( loc, 1, gModelViewProjectionMatrix.AsFloat() );
97 loc = program.GetUniformLocation( Program::UNIFORM_NORMAL_MATRIX );
98 if( Program::UNIFORM_UNKNOWN != loc )
100 gNormalMatrix = modelViewMatrix;
101 gNormalMatrix.Invert();
102 gNormalMatrix.Transpose();
103 program.SetUniformMatrix3fv( loc, 1, gNormalMatrix.AsFloat() );
112 Renderer* Renderer::New( SceneGraph::RenderDataProvider* dataProvider,
113 Render::Geometry* geometry,
114 unsigned int blendingBitmask,
115 const Vector4* blendColor,
116 FaceCullingMode::Type faceCullingMode,
117 bool preMultipliedAlphaEnabled,
118 DepthWriteMode::Type depthWriteMode,
119 DepthTestMode::Type depthTestMode,
120 DepthFunction::Type depthFunction,
121 StencilParameters& stencilParameters,
122 bool writeToColorBuffer )
124 return new Renderer( dataProvider, geometry, blendingBitmask, blendColor,
125 faceCullingMode, preMultipliedAlphaEnabled, depthWriteMode, depthTestMode,
126 depthFunction, stencilParameters, writeToColorBuffer );
129 Renderer::Renderer( SceneGraph::RenderDataProvider* dataProvider,
130 Render::Geometry* geometry,
131 unsigned int blendingBitmask,
132 const Vector4* blendColor,
133 FaceCullingMode::Type faceCullingMode,
134 bool preMultipliedAlphaEnabled,
135 DepthWriteMode::Type depthWriteMode,
136 DepthTestMode::Type depthTestMode,
137 DepthFunction::Type depthFunction,
138 StencilParameters& stencilParameters,
139 bool writeToColorBuffer )
140 : mRenderDataProvider( dataProvider ),
142 mTextureCache( NULL ),
143 mUniformNameCache( NULL ),
144 mGeometry( geometry ),
146 mAttributesLocation(),
147 mStencilParameters( stencilParameters ),
149 mIndexedDrawFirstElement( 0 ),
150 mIndexedDrawElementsCount( 0 ),
151 mDepthFunction( depthFunction ),
152 mFaceCullingMode( faceCullingMode ),
153 mDepthWriteMode( depthWriteMode ),
154 mDepthTestMode( depthTestMode ),
155 mWriteToColorBuffer( writeToColorBuffer ),
156 mUpdateAttributesLocation( true ),
157 mPremultipledAlphaEnabled( preMultipliedAlphaEnabled ),
158 mBatchingEnabled( false )
160 if( blendingBitmask != 0u )
162 mBlendingOptions.SetBitmask( blendingBitmask );
167 mBlendingOptions.SetBlendColor( *blendColor );
171 void Renderer::Initialize( Context& context, SceneGraph::TextureCache& textureCache, Render::UniformNameCache& uniformNameCache )
174 mTextureCache = &textureCache;
175 mUniformNameCache = &uniformNameCache;
178 Renderer::~Renderer()
182 void Renderer::SetRenderDataProvider( SceneGraph::RenderDataProvider* dataProvider )
184 mRenderDataProvider = dataProvider;
185 mUpdateAttributesLocation = true;
188 void Renderer::SetGeometry( Render::Geometry* geometry )
190 mGeometry = geometry;
191 mUpdateAttributesLocation = true;
194 void Renderer::SetBlending( Context& context, bool blend )
196 context.SetBlend( blend );
199 // Blend color is optional and rarely used
200 const Vector4* blendColor = mBlendingOptions.GetBlendColor();
203 context.SetCustomBlendColor( *blendColor );
207 context.SetDefaultBlendColor();
210 // Set blend source & destination factors
211 context.BlendFuncSeparate( mBlendingOptions.GetBlendSrcFactorRgb(),
212 mBlendingOptions.GetBlendDestFactorRgb(),
213 mBlendingOptions.GetBlendSrcFactorAlpha(),
214 mBlendingOptions.GetBlendDestFactorAlpha() );
216 // Set blend equations
217 context.BlendEquationSeparate( mBlendingOptions.GetBlendEquationRgb(),
218 mBlendingOptions.GetBlendEquationAlpha() );
222 void Renderer::GlContextDestroyed()
224 mGeometry->GlContextDestroyed();
227 void Renderer::GlCleanup()
231 void Renderer::SetUniforms( BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program )
233 // Check if the map has changed
234 DALI_ASSERT_DEBUG( mRenderDataProvider && "No Uniform map data provider available" );
236 const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
238 if( uniformMapDataProvider.GetUniformMapChanged( bufferIndex ) ||
239 node.GetUniformMapChanged(bufferIndex))
241 const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap( bufferIndex );
242 const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap( bufferIndex );
244 unsigned int maxMaps = uniformMap.Count() + uniformMapNode.Count();
245 mUniformIndexMap.Clear(); // Clear contents, but keep memory if we don't change size
246 mUniformIndexMap.Resize( maxMaps );
248 unsigned int mapIndex(0);
249 for(; mapIndex < uniformMap.Count() ; ++mapIndex )
251 mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex]->propertyPtr;
252 mUniformIndexMap[mapIndex].uniformIndex = program.RegisterUniform( uniformMap[mapIndex]->uniformName );
255 for( unsigned int nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count() ; ++nodeMapIndex )
257 unsigned int uniformIndex = program.RegisterUniform( uniformMapNode[nodeMapIndex]->uniformName );
259 for( unsigned int i(0); i<uniformMap.Count(); ++i )
261 if( mUniformIndexMap[i].uniformIndex == uniformIndex )
263 mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
271 mUniformIndexMap[mapIndex].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
272 mUniformIndexMap[mapIndex].uniformIndex = uniformIndex;
277 mUniformIndexMap.Resize( mapIndex );
280 // Set uniforms in local map
281 for( UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
282 end = mUniformIndexMap.End() ;
286 SetUniformFromProperty( bufferIndex, program, *iter );
289 GLint sizeLoc = program.GetUniformLocation( Program::UNIFORM_SIZE );
292 program.SetSizeUniform3f( sizeLoc, size.x, size.y, size.z );
296 void Renderer::SetUniformFromProperty( BufferIndex bufferIndex, Program& program, UniformIndexMap& map )
298 GLint location = program.GetUniformLocation(map.uniformIndex);
299 if( Program::UNIFORM_UNKNOWN != location )
301 // switch based on property type to use correct GL uniform setter
302 switch ( map.propertyValue->GetType() )
304 case Property::INTEGER:
306 program.SetUniform1i( location, map.propertyValue->GetInteger( bufferIndex ) );
309 case Property::FLOAT:
311 program.SetUniform1f( location, map.propertyValue->GetFloat( bufferIndex ) );
314 case Property::VECTOR2:
316 Vector2 value( map.propertyValue->GetVector2( bufferIndex ) );
317 program.SetUniform2f( location, value.x, value.y );
321 case Property::VECTOR3:
323 Vector3 value( map.propertyValue->GetVector3( bufferIndex ) );
324 program.SetUniform3f( location, value.x, value.y, value.z );
328 case Property::VECTOR4:
330 Vector4 value( map.propertyValue->GetVector4( bufferIndex ) );
331 program.SetUniform4f( location, value.x, value.y, value.z, value.w );
335 case Property::ROTATION:
337 Quaternion value( map.propertyValue->GetQuaternion( bufferIndex ) );
338 program.SetUniform4f( location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w );
342 case Property::MATRIX:
344 const Matrix& value = map.propertyValue->GetMatrix(bufferIndex);
345 program.SetUniformMatrix4fv(location, 1, value.AsFloat() );
349 case Property::MATRIX3:
351 const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex);
352 program.SetUniformMatrix3fv(location, 1, value.AsFloat() );
358 // Other property types are ignored
365 bool Renderer::BindTextures( Context& context, SceneGraph::TextureCache& textureCache, Program& program )
367 unsigned int textureUnit = 0;
370 std::vector<Render::Sampler*>& samplers( mRenderDataProvider->GetSamplers() );
372 std::vector<Render::Texture>& textures( mRenderDataProvider->GetTextures() );
373 GLint uniformLocation(-1);
374 for( size_t i(0); result && i<textures.size(); ++i )
376 ResourceId textureId = textures[i].GetTextureId();
377 Internal::Texture* texture = textureCache.GetTexture( textureId );
380 result = textureCache.BindTexture( texture, textureId, GL_TEXTURE_2D, (TextureUnit)textureUnit );
384 GLint uniformLocation;
386 //TODO : This is a bug, result variable is being shadowed. Fix it!
387 bool result = program.GetSamplerUniformLocation( i, uniformLocation );
388 if( result && Program::UNIFORM_UNKNOWN != uniformLocation )
390 program.SetUniform1i( uniformLocation, textureUnit );
392 unsigned int samplerBitfield(ImageSampler::DEFAULT_BITFIELD);
393 const Render::Sampler* sampler( samplers[i] );
396 samplerBitfield = sampler->mBitfield;
399 texture->ApplySampler( (TextureUnit)textureUnit, samplerBitfield );
407 std::vector<Render::NewTexture*>& newTextures( mRenderDataProvider->GetNewTextures() );
408 for( size_t i(0); result && i<newTextures.size(); ++i )
412 result = program.GetSamplerUniformLocation( i, uniformLocation ) &&
413 newTextures[i]->Bind(context, textureUnit, samplers[i] );
417 program.SetUniform1i( uniformLocation, textureUnit );
426 void Renderer::SetFaceCullingMode( FaceCullingMode::Type mode )
428 mFaceCullingMode = mode;
431 void Renderer::SetBlendingBitMask( unsigned int bitmask )
433 mBlendingOptions.SetBitmask( bitmask );
436 void Renderer::SetBlendColor( const Vector4* color )
438 mBlendingOptions.SetBlendColor( *color );
441 void Renderer::SetIndexedDrawFirstElement( size_t firstElement )
443 mIndexedDrawFirstElement = firstElement;
446 void Renderer::SetIndexedDrawElementsCount( size_t elementsCount )
448 mIndexedDrawElementsCount = elementsCount;
451 void Renderer::EnablePreMultipliedAlpha( bool enable )
453 mPremultipledAlphaEnabled = enable;
456 void Renderer::SetDepthWriteMode( DepthWriteMode::Type depthWriteMode )
458 mDepthWriteMode = depthWriteMode;
461 void Renderer::SetDepthTestMode( DepthTestMode::Type depthTestMode )
463 mDepthTestMode = depthTestMode;
466 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
468 return mDepthWriteMode;
471 DepthTestMode::Type Renderer::GetDepthTestMode() const
473 return mDepthTestMode;
476 void Renderer::SetDepthFunction( DepthFunction::Type depthFunction )
478 mDepthFunction = depthFunction;
481 DepthFunction::Type Renderer::GetDepthFunction() const
483 return mDepthFunction;
486 void Renderer::SetStencilMode( StencilMode::Type stencilMode )
488 mStencilParameters.stencilMode = stencilMode;
491 StencilMode::Type Renderer::GetStencilMode() const
493 return mStencilParameters.stencilMode;
496 void Renderer::SetStencilFunction( StencilFunction::Type stencilFunction )
498 mStencilParameters.stencilFunction = stencilFunction;
501 StencilFunction::Type Renderer::GetStencilFunction() const
503 return mStencilParameters.stencilFunction;
506 void Renderer::SetStencilFunctionMask( int stencilFunctionMask )
508 mStencilParameters.stencilFunctionMask = stencilFunctionMask;
511 int Renderer::GetStencilFunctionMask() const
513 return mStencilParameters.stencilFunctionMask;
516 void Renderer::SetStencilFunctionReference( int stencilFunctionReference )
518 mStencilParameters.stencilFunctionReference = stencilFunctionReference;
521 int Renderer::GetStencilFunctionReference() const
523 return mStencilParameters.stencilFunctionReference;
526 void Renderer::SetStencilMask( int stencilMask )
528 mStencilParameters.stencilMask = stencilMask;
531 int Renderer::GetStencilMask() const
533 return mStencilParameters.stencilMask;
536 void Renderer::SetStencilOperationOnFail( StencilOperation::Type stencilOperationOnFail )
538 mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
541 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
543 return mStencilParameters.stencilOperationOnFail;
546 void Renderer::SetStencilOperationOnZFail( StencilOperation::Type stencilOperationOnZFail )
548 mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
551 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
553 return mStencilParameters.stencilOperationOnZFail;
556 void Renderer::SetStencilOperationOnZPass( StencilOperation::Type stencilOperationOnZPass )
558 mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
561 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
563 return mStencilParameters.stencilOperationOnZPass;
566 void Renderer::SetWriteToColorBuffer( bool writeToColorBuffer )
568 mWriteToColorBuffer = writeToColorBuffer;
571 bool Renderer::GetWriteToColorBuffer() const
573 return mWriteToColorBuffer;
576 void Renderer::SetBatchingEnabled( bool batchingEnabled )
578 mBatchingEnabled = batchingEnabled;
581 void Renderer::Render( Context& context,
582 SceneGraph::TextureCache& textureCache,
583 BufferIndex bufferIndex,
584 const SceneGraph::NodeDataProvider& node,
585 SceneGraph::Shader& defaultShader,
586 const Matrix& modelMatrix,
587 const Matrix& modelViewMatrix,
588 const Matrix& viewMatrix,
589 const Matrix& projectionMatrix,
591 Render::Geometry* externalGeometry,
594 // Get the program to use:
595 Program* program = mRenderDataProvider->GetShader().GetProgram();
598 // if program is NULL it means this is a custom shader with non matching geometry type so we need to use default shaders program
599 program = defaultShader.GetProgram();
600 DALI_ASSERT_DEBUG( program && "Default shader should always have a program available." );
603 DALI_LOG_ERROR( "Failed to get program for shader at address %p.\n", (void*)&mRenderDataProvider->GetShader() );
609 context.CullFace( mFaceCullingMode );
612 SetBlending( context, blend );
614 // Take the program into use so we can send uniforms to it
617 if( DALI_LIKELY( BindTextures( context, textureCache, *program ) ) )
619 // Only set up and draw if we have textures and they are all valid
621 // set projection and view matrix if program has not yet received them yet this frame
622 SetMatrices( *program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix );
625 GLint loc = program->GetUniformLocation( Program::UNIFORM_COLOR );
626 if( Program::UNIFORM_UNKNOWN != loc )
628 const Vector4& color = node.GetRenderColor( bufferIndex );
629 if( mPremultipledAlphaEnabled )
631 program->SetUniform4f( loc, color.r*color.a, color.g*color.a, color.b*color.a, color.a );
635 program->SetUniform4f( loc, color.r, color.g, color.b, color.a );
639 SetUniforms( bufferIndex, node, size, *program );
640 Render::Geometry* geometry = externalGeometry ? externalGeometry : mGeometry;
642 if( mUpdateAttributesLocation || geometry->AttributesChanged() )
644 geometry->GetAttributeLocationFromProgram( mAttributesLocation, *program, bufferIndex );
645 mUpdateAttributesLocation = false;
648 geometry->UploadAndDraw( context, bufferIndex, mAttributesLocation, mIndexedDrawFirstElement, mIndexedDrawElementsCount );
652 void Renderer::SetSortAttributes( BufferIndex bufferIndex, SceneGraph::RendererWithSortAttributes& sortAttributes ) const
654 sortAttributes.shader = &( mRenderDataProvider->GetShader() );
655 const std::vector<Render::Texture>& textures( mRenderDataProvider->GetTextures() );
656 if( !textures.empty() )
658 sortAttributes.textureResourceId = textures[0].GetTextureId();
662 sortAttributes.textureResourceId = Integration::InvalidResourceId;
665 sortAttributes.geometry = mGeometry;
668 } // namespace SceneGraph
670 } // namespace Internal