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/gl-resources/texture-cache.h>
29 #include <dali/public-api/actors/blending.h>
30 #include <dali/internal/render/gl-resources/gl-texture.h>
41 static Matrix gModelViewProjectionMatrix( false ); ///< a shared matrix to calculate the MVP matrix, dont want to store it in object to reduce storage overhead
42 static Matrix3 gNormalMatrix; ///< a shared matrix to calculate normal matrix, dont want to store it in object to reduce storage overhead
45 * Helper to set view and projection matrices once per program
46 * @param program to set the matrices to
47 * @param modelMatrix to set
48 * @param viewMatrix to set
49 * @param projectionMatrix to set
50 * @param modelViewMatrix to set
51 * @param modelViewProjectionMatrix to set
53 inline void SetMatrices( Program& program,
54 const Matrix& modelMatrix,
55 const Matrix& viewMatrix,
56 const Matrix& projectionMatrix,
57 const Matrix& modelViewMatrix )
59 GLint loc = program.GetUniformLocation( Program::UNIFORM_MODEL_MATRIX );
60 if( Program::UNIFORM_UNKNOWN != loc )
62 program.SetUniformMatrix4fv( loc, 1, modelMatrix.AsFloat() );
64 loc = program.GetUniformLocation( Program::UNIFORM_VIEW_MATRIX );
65 if( Program::UNIFORM_UNKNOWN != loc )
67 if( program.GetViewMatrix() != &viewMatrix )
69 program.SetViewMatrix( &viewMatrix );
70 program.SetUniformMatrix4fv( loc, 1, viewMatrix.AsFloat() );
73 // set projection matrix if program has not yet received it this frame or if it is dirty
74 loc = program.GetUniformLocation( Program::UNIFORM_PROJECTION_MATRIX );
75 if( Program::UNIFORM_UNKNOWN != loc )
77 if( program.GetProjectionMatrix() != &projectionMatrix )
79 program.SetProjectionMatrix( &projectionMatrix );
80 program.SetUniformMatrix4fv( loc, 1, projectionMatrix.AsFloat() );
83 loc = program.GetUniformLocation(Program::UNIFORM_MODELVIEW_MATRIX);
84 if( Program::UNIFORM_UNKNOWN != loc )
86 program.SetUniformMatrix4fv( loc, 1, modelViewMatrix.AsFloat() );
89 loc = program.GetUniformLocation( Program::UNIFORM_MVP_MATRIX );
90 if( Program::UNIFORM_UNKNOWN != loc )
92 Matrix::Multiply( gModelViewProjectionMatrix, modelViewMatrix, projectionMatrix );
93 program.SetUniformMatrix4fv( loc, 1, gModelViewProjectionMatrix.AsFloat() );
96 loc = program.GetUniformLocation( Program::UNIFORM_NORMAL_MATRIX );
97 if( Program::UNIFORM_UNKNOWN != loc )
99 gNormalMatrix = modelViewMatrix;
100 gNormalMatrix.Invert();
101 gNormalMatrix.Transpose();
102 program.SetUniformMatrix3fv( loc, 1, gNormalMatrix.AsFloat() );
111 Renderer* Renderer::New( SceneGraph::RenderDataProvider* dataProvider,
112 Render::Geometry* geometry,
113 unsigned int blendingBitmask,
114 const Vector4* blendColor,
115 FaceCullingMode::Type faceCullingMode,
116 bool preMultipliedAlphaEnabled,
117 DepthWriteMode::Type depthWriteMode,
118 DepthTestMode::Type depthTestMode,
119 DepthFunction::Type depthFunction,
120 StencilParameters& stencilParameters,
121 bool writeToColorBuffer )
123 return new Renderer( dataProvider, geometry, blendingBitmask, blendColor,
124 faceCullingMode, preMultipliedAlphaEnabled, depthWriteMode, depthTestMode,
125 depthFunction, stencilParameters, writeToColorBuffer );
128 Renderer::Renderer( SceneGraph::RenderDataProvider* dataProvider,
129 Render::Geometry* geometry,
130 unsigned int blendingBitmask,
131 const Vector4* blendColor,
132 FaceCullingMode::Type faceCullingMode,
133 bool preMultipliedAlphaEnabled,
134 DepthWriteMode::Type depthWriteMode,
135 DepthTestMode::Type depthTestMode,
136 DepthFunction::Type depthFunction,
137 StencilParameters& stencilParameters,
138 bool writeToColorBuffer )
139 : mRenderDataProvider( dataProvider ),
141 mTextureCache( NULL ),
142 mGeometry( geometry ),
144 mAttributesLocation(),
145 mStencilParameters( stencilParameters ),
147 mIndexedDrawFirstElement( 0 ),
148 mIndexedDrawElementsCount( 0 ),
149 mDepthFunction( depthFunction ),
150 mFaceCullingMode( faceCullingMode ),
151 mDepthWriteMode( depthWriteMode ),
152 mDepthTestMode( depthTestMode ),
153 mWriteToColorBuffer( writeToColorBuffer ),
154 mUpdateAttributesLocation( true ),
155 mPremultipledAlphaEnabled( preMultipliedAlphaEnabled ),
156 mBatchingEnabled( false )
158 if( blendingBitmask != 0u )
160 mBlendingOptions.SetBitmask( blendingBitmask );
165 mBlendingOptions.SetBlendColor( *blendColor );
169 void Renderer::Initialize( Context& context, SceneGraph::TextureCache& textureCache )
172 mTextureCache = &textureCache;
175 Renderer::~Renderer()
179 void Renderer::SetRenderDataProvider( SceneGraph::RenderDataProvider* dataProvider )
181 mRenderDataProvider = dataProvider;
182 mUpdateAttributesLocation = true;
185 void Renderer::SetGeometry( Render::Geometry* geometry )
187 mGeometry = geometry;
188 mUpdateAttributesLocation = true;
191 void Renderer::SetBlending( Context& context, bool blend )
193 context.SetBlend( blend );
196 // Blend color is optional and rarely used
197 const Vector4* blendColor = mBlendingOptions.GetBlendColor();
200 context.SetCustomBlendColor( *blendColor );
204 context.SetDefaultBlendColor();
207 // Set blend source & destination factors
208 context.BlendFuncSeparate( mBlendingOptions.GetBlendSrcFactorRgb(),
209 mBlendingOptions.GetBlendDestFactorRgb(),
210 mBlendingOptions.GetBlendSrcFactorAlpha(),
211 mBlendingOptions.GetBlendDestFactorAlpha() );
213 // Set blend equations
214 context.BlendEquationSeparate( mBlendingOptions.GetBlendEquationRgb(),
215 mBlendingOptions.GetBlendEquationAlpha() );
219 void Renderer::GlContextDestroyed()
221 mGeometry->GlContextDestroyed();
224 void Renderer::GlCleanup()
228 void Renderer::SetUniforms( BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program )
230 // Check if the map has changed
231 DALI_ASSERT_DEBUG( mRenderDataProvider && "No Uniform map data provider available" );
233 const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
235 if( uniformMapDataProvider.GetUniformMapChanged( bufferIndex ) ||
236 node.GetUniformMapChanged(bufferIndex))
238 const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap( bufferIndex );
239 const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap( bufferIndex );
241 unsigned int maxMaps = uniformMap.Count() + uniformMapNode.Count();
242 mUniformIndexMap.Clear(); // Clear contents, but keep memory if we don't change size
243 mUniformIndexMap.Resize( maxMaps );
245 unsigned int mapIndex(0);
246 for(; mapIndex < uniformMap.Count() ; ++mapIndex )
248 mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex]->propertyPtr;
249 mUniformIndexMap[mapIndex].uniformIndex = program.RegisterUniform( uniformMap[mapIndex]->uniformName );
252 for( unsigned int nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count() ; ++nodeMapIndex )
254 unsigned int uniformIndex = program.RegisterUniform( uniformMapNode[nodeMapIndex]->uniformName );
256 for( unsigned int i(0); i<uniformMap.Count(); ++i )
258 if( mUniformIndexMap[i].uniformIndex == uniformIndex )
260 mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
268 mUniformIndexMap[mapIndex].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
269 mUniformIndexMap[mapIndex].uniformIndex = uniformIndex;
274 mUniformIndexMap.Resize( mapIndex );
277 // Set uniforms in local map
278 for( UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
279 end = mUniformIndexMap.End() ;
283 SetUniformFromProperty( bufferIndex, program, *iter );
286 GLint sizeLoc = program.GetUniformLocation( Program::UNIFORM_SIZE );
289 program.SetSizeUniform3f( sizeLoc, size.x, size.y, size.z );
293 void Renderer::SetUniformFromProperty( BufferIndex bufferIndex, Program& program, UniformIndexMap& map )
295 GLint location = program.GetUniformLocation(map.uniformIndex);
296 if( Program::UNIFORM_UNKNOWN != location )
298 // switch based on property type to use correct GL uniform setter
299 switch ( map.propertyValue->GetType() )
301 case Property::INTEGER:
303 program.SetUniform1i( location, map.propertyValue->GetInteger( bufferIndex ) );
306 case Property::FLOAT:
308 program.SetUniform1f( location, map.propertyValue->GetFloat( bufferIndex ) );
311 case Property::VECTOR2:
313 Vector2 value( map.propertyValue->GetVector2( bufferIndex ) );
314 program.SetUniform2f( location, value.x, value.y );
318 case Property::VECTOR3:
320 Vector3 value( map.propertyValue->GetVector3( bufferIndex ) );
321 program.SetUniform3f( location, value.x, value.y, value.z );
325 case Property::VECTOR4:
327 Vector4 value( map.propertyValue->GetVector4( bufferIndex ) );
328 program.SetUniform4f( location, value.x, value.y, value.z, value.w );
332 case Property::ROTATION:
334 Quaternion value( map.propertyValue->GetQuaternion( bufferIndex ) );
335 program.SetUniform4f( location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w );
339 case Property::MATRIX:
341 const Matrix& value = map.propertyValue->GetMatrix(bufferIndex);
342 program.SetUniformMatrix4fv(location, 1, value.AsFloat() );
346 case Property::MATRIX3:
348 const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex);
349 program.SetUniformMatrix3fv(location, 1, value.AsFloat() );
355 // Other property types are ignored
362 bool Renderer::BindTextures( Context& context, SceneGraph::TextureCache& textureCache, Program& program )
364 unsigned int textureUnit = 0;
367 std::vector<Render::Sampler*>& samplers( mRenderDataProvider->GetSamplers() );
369 std::vector<Render::Texture>& textures( mRenderDataProvider->GetTextures() );
370 GLint uniformLocation(-1);
371 for( size_t i(0); result && i<textures.size(); ++i )
373 ResourceId textureId = textures[i].GetTextureId();
374 Internal::Texture* texture = textureCache.GetTexture( textureId );
377 result = textureCache.BindTexture( texture, textureId, GL_TEXTURE_2D, (TextureUnit)textureUnit );
381 GLint uniformLocation;
383 //TODO : This is a bug, result variable is being shadowed. Fix it!
384 bool result = program.GetSamplerUniformLocation( i, uniformLocation );
385 if( result && Program::UNIFORM_UNKNOWN != uniformLocation )
387 program.SetUniform1i( uniformLocation, textureUnit );
389 unsigned int samplerBitfield(ImageSampler::DEFAULT_BITFIELD);
390 const Render::Sampler* sampler( samplers[i] );
393 samplerBitfield = sampler->mBitfield;
396 texture->ApplySampler( (TextureUnit)textureUnit, samplerBitfield );
404 std::vector<Render::NewTexture*>& newTextures( mRenderDataProvider->GetNewTextures() );
405 for( size_t i(0); result && i<newTextures.size(); ++i )
409 result = program.GetSamplerUniformLocation( i, uniformLocation ) &&
410 newTextures[i]->Bind(context, textureUnit, samplers[i] );
414 program.SetUniform1i( uniformLocation, textureUnit );
423 void Renderer::SetFaceCullingMode( FaceCullingMode::Type mode )
425 mFaceCullingMode = mode;
428 void Renderer::SetBlendingBitMask( unsigned int bitmask )
430 mBlendingOptions.SetBitmask( bitmask );
433 void Renderer::SetBlendColor( const Vector4* color )
435 mBlendingOptions.SetBlendColor( *color );
438 void Renderer::SetIndexedDrawFirstElement( size_t firstElement )
440 mIndexedDrawFirstElement = firstElement;
443 void Renderer::SetIndexedDrawElementsCount( size_t elementsCount )
445 mIndexedDrawElementsCount = elementsCount;
448 void Renderer::EnablePreMultipliedAlpha( bool enable )
450 mPremultipledAlphaEnabled = enable;
453 void Renderer::SetDepthWriteMode( DepthWriteMode::Type depthWriteMode )
455 mDepthWriteMode = depthWriteMode;
458 void Renderer::SetDepthTestMode( DepthTestMode::Type depthTestMode )
460 mDepthTestMode = depthTestMode;
463 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
465 return mDepthWriteMode;
468 DepthTestMode::Type Renderer::GetDepthTestMode() const
470 return mDepthTestMode;
473 void Renderer::SetDepthFunction( DepthFunction::Type depthFunction )
475 mDepthFunction = depthFunction;
478 DepthFunction::Type Renderer::GetDepthFunction() const
480 return mDepthFunction;
483 void Renderer::SetStencilMode( StencilMode::Type stencilMode )
485 mStencilParameters.stencilMode = stencilMode;
488 StencilMode::Type Renderer::GetStencilMode() const
490 return mStencilParameters.stencilMode;
493 void Renderer::SetStencilFunction( StencilFunction::Type stencilFunction )
495 mStencilParameters.stencilFunction = stencilFunction;
498 StencilFunction::Type Renderer::GetStencilFunction() const
500 return mStencilParameters.stencilFunction;
503 void Renderer::SetStencilFunctionMask( int stencilFunctionMask )
505 mStencilParameters.stencilFunctionMask = stencilFunctionMask;
508 int Renderer::GetStencilFunctionMask() const
510 return mStencilParameters.stencilFunctionMask;
513 void Renderer::SetStencilFunctionReference( int stencilFunctionReference )
515 mStencilParameters.stencilFunctionReference = stencilFunctionReference;
518 int Renderer::GetStencilFunctionReference() const
520 return mStencilParameters.stencilFunctionReference;
523 void Renderer::SetStencilMask( int stencilMask )
525 mStencilParameters.stencilMask = stencilMask;
528 int Renderer::GetStencilMask() const
530 return mStencilParameters.stencilMask;
533 void Renderer::SetStencilOperationOnFail( StencilOperation::Type stencilOperationOnFail )
535 mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
538 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
540 return mStencilParameters.stencilOperationOnFail;
543 void Renderer::SetStencilOperationOnZFail( StencilOperation::Type stencilOperationOnZFail )
545 mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
548 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
550 return mStencilParameters.stencilOperationOnZFail;
553 void Renderer::SetStencilOperationOnZPass( StencilOperation::Type stencilOperationOnZPass )
555 mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
558 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
560 return mStencilParameters.stencilOperationOnZPass;
563 void Renderer::SetWriteToColorBuffer( bool writeToColorBuffer )
565 mWriteToColorBuffer = writeToColorBuffer;
568 bool Renderer::GetWriteToColorBuffer() const
570 return mWriteToColorBuffer;
573 void Renderer::SetBatchingEnabled( bool batchingEnabled )
575 mBatchingEnabled = batchingEnabled;
578 void Renderer::Render( Context& context,
579 SceneGraph::TextureCache& textureCache,
580 BufferIndex bufferIndex,
581 const SceneGraph::NodeDataProvider& node,
582 SceneGraph::Shader& defaultShader,
583 const Matrix& modelMatrix,
584 const Matrix& modelViewMatrix,
585 const Matrix& viewMatrix,
586 const Matrix& projectionMatrix,
588 Render::Geometry* externalGeometry,
591 // Get the program to use:
592 Program* program = mRenderDataProvider->GetShader().GetProgram();
595 // if program is NULL it means this is a custom shader with non matching geometry type so we need to use default shaders program
596 program = defaultShader.GetProgram();
597 DALI_ASSERT_DEBUG( program && "Default shader should always have a program available." );
600 DALI_LOG_ERROR( "Failed to get program for shader at address %p.\n", (void*)&mRenderDataProvider->GetShader() );
606 context.CullFace( mFaceCullingMode );
609 SetBlending( context, blend );
611 // Take the program into use so we can send uniforms to it
614 if( DALI_LIKELY( BindTextures( context, textureCache, *program ) ) )
616 // Only set up and draw if we have textures and they are all valid
618 // set projection and view matrix if program has not yet received them yet this frame
619 SetMatrices( *program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix );
622 GLint loc = program->GetUniformLocation( Program::UNIFORM_COLOR );
623 if( Program::UNIFORM_UNKNOWN != loc )
625 const Vector4& color = node.GetRenderColor( bufferIndex );
626 if( mPremultipledAlphaEnabled )
628 program->SetUniform4f( loc, color.r*color.a, color.g*color.a, color.b*color.a, color.a );
632 program->SetUniform4f( loc, color.r, color.g, color.b, color.a );
636 SetUniforms( bufferIndex, node, size, *program );
637 Render::Geometry* geometry = externalGeometry ? externalGeometry : mGeometry;
639 if( mUpdateAttributesLocation || geometry->AttributesChanged() )
641 geometry->GetAttributeLocationFromProgram( mAttributesLocation, *program, bufferIndex );
642 mUpdateAttributesLocation = false;
645 geometry->UploadAndDraw( context, bufferIndex, mAttributesLocation, mIndexedDrawFirstElement, mIndexedDrawElementsCount );
649 void Renderer::SetSortAttributes( BufferIndex bufferIndex, SceneGraph::RendererWithSortAttributes& sortAttributes ) const
651 sortAttributes.shader = &( mRenderDataProvider->GetShader() );
652 const std::vector<Render::Texture>& textures( mRenderDataProvider->GetTextures() );
653 if( !textures.empty() )
655 sortAttributes.textureResourceId = textures[0].GetTextureId();
659 sortAttributes.textureResourceId = Integration::InvalidResourceId;
662 sortAttributes.geometry = mGeometry;
665 } // namespace SceneGraph
667 } // namespace Internal