Added property to Renderer to specify the depth function
[platform/core/uifw/dali-core.git] / dali / internal / render / renderers / render-renderer.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/render/renderers/render-renderer.h>
20
21
22 // INTERNAL INCLUDES
23 #include <dali/internal/common/image-sampler.h>
24 #include <dali/internal/render/gl-resources/context.h>
25 #include <dali/internal/render/renderers/render-sampler.h>
26 #include <dali/internal/render/shaders/scene-graph-shader.h>
27 #include <dali/internal/render/shaders/program.h>
28 #include <dali/internal/render/data-providers/node-data-provider.h>
29 #include <dali/internal/render/data-providers/uniform-name-cache.h>
30 #include <dali/internal/render/gl-resources/texture.h>
31 #include <dali/internal/render/gl-resources/texture-cache.h>
32 #include <dali/public-api/actors/blending.h>
33
34 namespace Dali
35 {
36
37 namespace Internal
38 {
39
40 namespace
41 {
42
43 static Matrix gModelViewProjectionMatrix( false ); ///< a shared matrix to calculate the MVP matrix, dont want to store it in object to reduce storage overhead
44 static Matrix3 gNormalMatrix; ///< a shared matrix to calculate normal matrix, dont want to store it in object to reduce storage overhead
45
46 /**
47  * Helper to set view and projection matrices once per program
48  * @param program to set the matrices to
49  * @param modelMatrix to set
50  * @param viewMatrix to set
51  * @param projectionMatrix to set
52  * @param modelViewMatrix to set
53  * @param modelViewProjectionMatrix to set
54  */
55 inline void SetMatrices( Program& program,
56                          const Matrix& modelMatrix,
57                          const Matrix& viewMatrix,
58                          const Matrix& projectionMatrix,
59                          const Matrix& modelViewMatrix )
60 {
61   GLint loc = program.GetUniformLocation( Program::UNIFORM_MODEL_MATRIX );
62   if( Program::UNIFORM_UNKNOWN != loc )
63   {
64     program.SetUniformMatrix4fv( loc, 1, modelMatrix.AsFloat() );
65   }
66   loc = program.GetUniformLocation( Program::UNIFORM_VIEW_MATRIX );
67   if( Program::UNIFORM_UNKNOWN != loc )
68   {
69     if( program.GetViewMatrix() != &viewMatrix )
70     {
71       program.SetViewMatrix( &viewMatrix );
72       program.SetUniformMatrix4fv( loc, 1, viewMatrix.AsFloat() );
73     }
74   }
75   // set projection matrix if program has not yet received it this frame or if it is dirty
76   loc = program.GetUniformLocation( Program::UNIFORM_PROJECTION_MATRIX );
77   if( Program::UNIFORM_UNKNOWN != loc )
78   {
79     if( program.GetProjectionMatrix() != &projectionMatrix )
80     {
81       program.SetProjectionMatrix( &projectionMatrix );
82       program.SetUniformMatrix4fv( loc, 1, projectionMatrix.AsFloat() );
83     }
84   }
85   loc = program.GetUniformLocation(Program::UNIFORM_MODELVIEW_MATRIX);
86   if( Program::UNIFORM_UNKNOWN != loc )
87   {
88     program.SetUniformMatrix4fv( loc, 1, modelViewMatrix.AsFloat() );
89   }
90
91   loc = program.GetUniformLocation( Program::UNIFORM_MVP_MATRIX );
92   if( Program::UNIFORM_UNKNOWN != loc )
93   {
94     Matrix::Multiply( gModelViewProjectionMatrix, modelViewMatrix, projectionMatrix );
95     program.SetUniformMatrix4fv( loc, 1, gModelViewProjectionMatrix.AsFloat() );
96   }
97
98   loc = program.GetUniformLocation( Program::UNIFORM_NORMAL_MATRIX );
99   if( Program::UNIFORM_UNKNOWN != loc )
100   {
101     gNormalMatrix = modelViewMatrix;
102     gNormalMatrix.Invert();
103     gNormalMatrix.Transpose();
104     program.SetUniformMatrix3fv( loc, 1, gNormalMatrix.AsFloat() );
105   }
106 }
107
108 }
109
110 namespace Render
111 {
112
113 Renderer* Renderer::New( SceneGraph::RenderDataProvider* dataProvider,
114                          Render::Geometry* geometry,
115                          unsigned int blendingBitmask,
116                          const Vector4* blendColor,
117                          FaceCullingMode::Type faceCullingMode,
118                          bool preMultipliedAlphaEnabled,
119                          DepthWriteMode::Type depthWriteMode,
120                          DepthFunction::Type depthFunction )
121 {
122   return new Renderer( dataProvider, geometry, blendingBitmask, blendColor, faceCullingMode, preMultipliedAlphaEnabled, depthWriteMode, depthFunction );
123 }
124
125 Renderer::Renderer( SceneGraph::RenderDataProvider* dataProvider,
126                     Render::Geometry* geometry,
127                     unsigned int blendingBitmask,
128                     const Vector4* blendColor,
129                     FaceCullingMode::Type faceCullingMode,
130                     bool preMultipliedAlphaEnabled,
131                     DepthWriteMode::Type depthWriteMode,
132                     DepthFunction::Type depthFunction )
133 : mRenderDataProvider( dataProvider ),
134   mContext(NULL),
135   mTextureCache( NULL ),
136   mUniformNameCache( NULL ),
137   mGeometry( geometry ),
138   mUniformIndexMap(),
139   mAttributesLocation(),
140   mBlendingOptions(),
141   mFaceCullingMode( faceCullingMode  ),
142   mDepthWriteMode( depthWriteMode ),
143   mDepthFunction( depthFunction ),
144   mIndexedDrawFirstElement( 0 ),
145   mIndexedDrawElementsCount( 0 ),
146   mUpdateAttributesLocation( true ),
147   mPremultipledAlphaEnabled( preMultipliedAlphaEnabled )
148 {
149   if(  blendingBitmask != 0u )
150   {
151     mBlendingOptions.SetBitmask( blendingBitmask );
152   }
153
154   if( blendColor )
155   {
156     mBlendingOptions.SetBlendColor( *blendColor );
157   }
158 }
159
160 void Renderer::Initialize( Context& context, SceneGraph::TextureCache& textureCache, Render::UniformNameCache& uniformNameCache )
161 {
162   mContext = &context;
163   mTextureCache = &textureCache;
164   mUniformNameCache = &uniformNameCache;
165 }
166
167 Renderer::~Renderer()
168 {
169 }
170
171 void Renderer::SetRenderDataProvider( SceneGraph::RenderDataProvider* dataProvider )
172 {
173   mRenderDataProvider = dataProvider;
174   mUpdateAttributesLocation = true;
175 }
176
177 void Renderer::SetGeometry( Render::Geometry* geometry )
178 {
179   mGeometry = geometry;
180   mUpdateAttributesLocation = true;
181 }
182
183 void Renderer::SetBlending( Context& context, bool blend )
184 {
185   context.SetBlend( blend );
186   if( blend )
187   {
188     // Blend color is optional and rarely used
189     const Vector4* blendColor = mBlendingOptions.GetBlendColor();
190     if( blendColor )
191     {
192       context.SetCustomBlendColor( *blendColor );
193     }
194     else
195     {
196       context.SetDefaultBlendColor();
197     }
198
199     // Set blend source & destination factors
200     context.BlendFuncSeparate( mBlendingOptions.GetBlendSrcFactorRgb(),
201                                mBlendingOptions.GetBlendDestFactorRgb(),
202                                mBlendingOptions.GetBlendSrcFactorAlpha(),
203                                mBlendingOptions.GetBlendDestFactorAlpha() );
204
205     // Set blend equations
206     context.BlendEquationSeparate( mBlendingOptions.GetBlendEquationRgb(),
207                                    mBlendingOptions.GetBlendEquationAlpha() );
208   }
209 }
210
211 void Renderer::GlContextDestroyed()
212 {
213   mGeometry->GlContextDestroyed();
214 }
215
216 void Renderer::GlCleanup()
217 {
218 }
219
220 void Renderer::SetUniforms( BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program )
221 {
222   // Check if the map has changed
223   DALI_ASSERT_DEBUG( mRenderDataProvider && "No Uniform map data provider available" );
224
225   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
226
227   if( uniformMapDataProvider.GetUniformMapChanged( bufferIndex ) ||
228       node.GetUniformMapChanged(bufferIndex))
229   {
230     const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap( bufferIndex );
231     const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap( bufferIndex );
232
233     unsigned int maxMaps = uniformMap.Count() + uniformMapNode.Count();
234     mUniformIndexMap.Clear(); // Clear contents, but keep memory if we don't change size
235     mUniformIndexMap.Resize( maxMaps );
236
237     unsigned int mapIndex(0);
238     for(; mapIndex < uniformMap.Count() ; ++mapIndex )
239     {
240       mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex]->propertyPtr;
241       mUniformIndexMap[mapIndex].uniformIndex = program.RegisterUniform( uniformMap[mapIndex]->uniformName );
242     }
243
244     for( unsigned int nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count() ; ++nodeMapIndex )
245     {
246       unsigned int uniformIndex = program.RegisterUniform( uniformMapNode[nodeMapIndex]->uniformName );
247       bool found(false);
248       for( unsigned int i(0); i<uniformMap.Count(); ++i )
249       {
250         if( mUniformIndexMap[i].uniformIndex == uniformIndex )
251         {
252           mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
253           found = true;
254           break;
255         }
256       }
257
258       if( !found )
259       {
260         mUniformIndexMap[mapIndex].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
261         mUniformIndexMap[mapIndex].uniformIndex = uniformIndex;
262         ++mapIndex;
263       }
264     }
265
266     mUniformIndexMap.Resize( mapIndex );
267   }
268
269   // Set uniforms in local map
270   for( UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
271          end = mUniformIndexMap.End() ;
272        iter != end ;
273        ++iter )
274   {
275     SetUniformFromProperty( bufferIndex, program, *iter );
276   }
277
278   GLint sizeLoc = program.GetUniformLocation( Program::UNIFORM_SIZE );
279   if( -1 != sizeLoc )
280   {
281     program.SetSizeUniform3f( sizeLoc, size.x, size.y, size.z );
282   }
283 }
284
285 void Renderer::SetUniformFromProperty( BufferIndex bufferIndex, Program& program, UniformIndexMap& map )
286 {
287   GLint location = program.GetUniformLocation(map.uniformIndex);
288   if( Program::UNIFORM_UNKNOWN != location )
289   {
290     // switch based on property type to use correct GL uniform setter
291     switch ( map.propertyValue->GetType() )
292     {
293       case Property::INTEGER:
294       {
295         program.SetUniform1i( location, map.propertyValue->GetInteger( bufferIndex ) );
296         break;
297       }
298       case Property::FLOAT:
299       {
300         program.SetUniform1f( location, map.propertyValue->GetFloat( bufferIndex ) );
301         break;
302       }
303       case Property::VECTOR2:
304       {
305         Vector2 value( map.propertyValue->GetVector2( bufferIndex ) );
306         program.SetUniform2f( location, value.x, value.y );
307         break;
308       }
309
310       case Property::VECTOR3:
311       {
312         Vector3 value( map.propertyValue->GetVector3( bufferIndex ) );
313         program.SetUniform3f( location, value.x, value.y, value.z );
314         break;
315       }
316
317       case Property::VECTOR4:
318       {
319         Vector4 value( map.propertyValue->GetVector4( bufferIndex ) );
320         program.SetUniform4f( location, value.x, value.y, value.z, value.w );
321         break;
322       }
323
324       case Property::ROTATION:
325       {
326         Quaternion value( map.propertyValue->GetQuaternion( bufferIndex ) );
327         program.SetUniform4f( location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w );
328         break;
329       }
330
331       case Property::MATRIX:
332       {
333         const Matrix& value = map.propertyValue->GetMatrix(bufferIndex);
334         program.SetUniformMatrix4fv(location, 1, value.AsFloat() );
335         break;
336       }
337
338       case Property::MATRIX3:
339       {
340         const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex);
341         program.SetUniformMatrix3fv(location, 1, value.AsFloat() );
342         break;
343       }
344
345       default:
346       {
347         // Other property types are ignored
348         break;
349       }
350     }
351   }
352 }
353
354 bool Renderer::BindTextures( SceneGraph::TextureCache& textureCache, Program& program )
355 {
356   int textureUnit = 0;
357   bool result = true;
358
359   std::vector<Render::Texture>& textures( mRenderDataProvider->GetTextures() );
360   for( size_t i(0); result && i<textures.size(); ++i )
361   {
362     ResourceId textureId = textures[i].GetTextureId();
363     Internal::Texture* texture = textureCache.GetTexture( textureId );
364     if( texture )
365     {
366       result = textureCache.BindTexture( texture, textureId, GL_TEXTURE_2D, (TextureUnit)textureUnit );
367
368       if( result )
369       {
370         GLint uniformLocation;
371
372         bool result = program.GetSamplerUniformLocation( i, uniformLocation );
373         if( result && Program::UNIFORM_UNKNOWN != uniformLocation )
374         {
375           program.SetUniform1i( uniformLocation, textureUnit );
376
377           unsigned int samplerBitfield(0);
378           Render::Texture& textureMapping = textures[i];
379           const Render::Sampler* sampler( textureMapping.GetSampler() );
380           if( sampler )
381           {
382             samplerBitfield = ImageSampler::PackBitfield(
383               static_cast< FilterMode::Type >(sampler->GetMinifyFilterMode()),
384               static_cast< FilterMode::Type >(sampler->GetMagnifyFilterMode()),
385               static_cast< WrapMode::Type >(sampler->GetUWrapMode()),
386               static_cast< WrapMode::Type >(sampler->GetVWrapMode())
387                                                          );
388           }
389           else
390           {
391             samplerBitfield = ImageSampler::DEFAULT_BITFIELD;
392           }
393
394           texture->ApplySampler( (TextureUnit)textureUnit, samplerBitfield );
395
396           ++textureUnit;
397         }
398       }
399     }
400   }
401   return result;
402 }
403
404 void Renderer::SetFaceCullingMode( FaceCullingMode::Type mode )
405 {
406   mFaceCullingMode =  mode;
407 }
408
409 void Renderer::SetBlendingBitMask( unsigned int bitmask )
410 {
411   mBlendingOptions.SetBitmask( bitmask );
412 }
413
414 void Renderer::SetBlendColor( const Vector4* color )
415 {
416   mBlendingOptions.SetBlendColor( *color );
417 }
418
419 void Renderer::SetIndexedDrawFirstElement( size_t firstElement )
420 {
421   mIndexedDrawFirstElement = firstElement;
422 }
423
424 void Renderer::SetIndexedDrawElementsCount( size_t elementsCount )
425 {
426   mIndexedDrawElementsCount = elementsCount;
427 }
428
429 void Renderer::EnablePreMultipliedAlpha( bool enable )
430 {
431   mPremultipledAlphaEnabled = enable;
432 }
433
434 void Renderer::SetDepthWriteMode( DepthWriteMode::Type depthWriteMode )
435 {
436   mDepthWriteMode = depthWriteMode;
437 }
438
439 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
440 {
441   return mDepthWriteMode;
442 }
443
444 void Renderer::SetDepthFunction( DepthFunction::Type depthFunction )
445 {
446   mDepthFunction = depthFunction;
447 }
448
449 DepthFunction::Type Renderer::GetDepthFunction() const
450 {
451   return mDepthFunction;
452 }
453
454 void Renderer::Render( Context& context,
455                        SceneGraph::TextureCache& textureCache,
456                        BufferIndex bufferIndex,
457                        const SceneGraph::NodeDataProvider& node,
458                        SceneGraph::Shader& defaultShader,
459                        const Matrix& modelMatrix,
460                        const Matrix& modelViewMatrix,
461                        const Matrix& viewMatrix,
462                        const Matrix& projectionMatrix,
463                        const Vector3& size,
464                        bool blend )
465 {
466   // Get the program to use:
467   Program* program = mRenderDataProvider->GetShader().GetProgram();
468   if( !program )
469   {
470     // if program is NULL it means this is a custom shader with non matching geometry type so we need to use default shaders program
471     program = defaultShader.GetProgram();
472     DALI_ASSERT_DEBUG( program && "Default shader should always have a program available." );
473     if( !program )
474     {
475       DALI_LOG_ERROR( "Failed to get program for shader at address %p.", (void*)&mRenderDataProvider->GetShader() );
476       return;
477     }
478   }
479
480   //Set cull face  mode
481   context.CullFace( mFaceCullingMode );
482
483   //Set blending mode
484   SetBlending( context, blend );
485
486   // Take the program into use so we can send uniforms to it
487   program->Use();
488
489   if( DALI_LIKELY( BindTextures( textureCache, *program ) ) )
490   {
491     // Only set up and draw if we have textures and they are all valid
492
493     // set projection and view matrix if program has not yet received them yet this frame
494     SetMatrices( *program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix );
495
496     // set color uniform
497     GLint loc = program->GetUniformLocation( Program::UNIFORM_COLOR );
498     if( Program::UNIFORM_UNKNOWN != loc )
499     {
500       const Vector4& color = node.GetRenderColor( bufferIndex );
501       if( mPremultipledAlphaEnabled )
502       {
503         program->SetUniform4f( loc, color.r*color.a, color.g*color.a, color.b*color.a, color.a );
504       }
505       else
506       {
507         program->SetUniform4f( loc, color.r, color.g, color.b, color.a );
508       }
509     }
510
511     SetUniforms( bufferIndex, node, size, *program );
512
513     if( mUpdateAttributesLocation || mGeometry->AttributesChanged() )
514     {
515       mGeometry->GetAttributeLocationFromProgram( mAttributesLocation, *program, bufferIndex );
516       mUpdateAttributesLocation = false;
517     }
518
519     mGeometry->UploadAndDraw( context, bufferIndex, mAttributesLocation, mIndexedDrawFirstElement, mIndexedDrawElementsCount );
520   }
521 }
522
523 void Renderer::SetSortAttributes( BufferIndex bufferIndex, SceneGraph::RendererWithSortAttributes& sortAttributes ) const
524 {
525   sortAttributes.shader = &( mRenderDataProvider->GetShader() );
526   const std::vector<Render::Texture>& textures( mRenderDataProvider->GetTextures() );
527   if( !textures.empty() )
528   {
529     sortAttributes.textureResourceId = textures[0].GetTextureId();
530   }
531   else
532   {
533     sortAttributes.textureResourceId = Integration::InvalidResourceId;
534   }
535
536   sortAttributes.geometry = mGeometry;
537 }
538
539 } // namespace SceneGraph
540
541 } // namespace Internal
542
543 } // namespace Dali