Merge "Remove API to set if a geometry requires writing to the depth buffer" into...
[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                          Dali::Renderer::FaceCullingMode faceCullingMode,
118                          bool preMultipliedAlphaEnabled,
119                          Dali::Renderer::DepthWriteMode depthWriteMode )
120 {
121   return new Renderer( dataProvider, geometry, blendingBitmask, blendColor, faceCullingMode, preMultipliedAlphaEnabled, depthWriteMode );
122 }
123
124 Renderer::Renderer( SceneGraph::RenderDataProvider* dataProvider,
125                     Render::Geometry* geometry,
126                     unsigned int blendingBitmask,
127                     const Vector4* blendColor,
128                     Dali::Renderer::FaceCullingMode faceCullingMode,
129                     bool preMultipliedAlphaEnabled,
130                     Dali::Renderer::DepthWriteMode depthWriteMode )
131 : mRenderDataProvider( dataProvider ),
132   mContext(NULL),
133   mTextureCache( NULL ),
134   mUniformNameCache( NULL ),
135   mGeometry( geometry ),
136   mUniformIndexMap(),
137   mAttributesLocation(),
138   mBlendingOptions(),
139   mFaceCullingMode( faceCullingMode  ),
140   mDepthWriteMode( depthWriteMode ),
141   mIndexedDrawFirstElement( 0 ),
142   mIndexedDrawElementsCount( 0 ),
143   mUpdateAttributesLocation( true ),
144   mPremultipledAlphaEnabled( preMultipliedAlphaEnabled )
145 {
146   if(  blendingBitmask != 0u )
147   {
148     mBlendingOptions.SetBitmask( blendingBitmask );
149   }
150
151   if( blendColor )
152   {
153     mBlendingOptions.SetBlendColor( *blendColor );
154   }
155 }
156
157 void Renderer::Initialize( Context& context, SceneGraph::TextureCache& textureCache, Render::UniformNameCache& uniformNameCache )
158 {
159   mContext = &context;
160   mTextureCache = &textureCache;
161   mUniformNameCache = &uniformNameCache;
162 }
163
164 Renderer::~Renderer()
165 {
166 }
167
168 void Renderer::SetRenderDataProvider( SceneGraph::RenderDataProvider* dataProvider )
169 {
170   mRenderDataProvider = dataProvider;
171   mUpdateAttributesLocation = true;
172 }
173
174 void Renderer::SetGeometry( Render::Geometry* geometry )
175 {
176   mGeometry = geometry;
177   mUpdateAttributesLocation = true;
178 }
179
180 void Renderer::SetBlending( Context& context, bool blend )
181 {
182   context.SetBlend( blend );
183   if( blend )
184   {
185     // Blend color is optional and rarely used
186     const Vector4* blendColor = mBlendingOptions.GetBlendColor();
187     if( blendColor )
188     {
189       context.SetCustomBlendColor( *blendColor );
190     }
191     else
192     {
193       context.SetDefaultBlendColor();
194     }
195
196     // Set blend source & destination factors
197     context.BlendFuncSeparate( mBlendingOptions.GetBlendSrcFactorRgb(),
198                                mBlendingOptions.GetBlendDestFactorRgb(),
199                                mBlendingOptions.GetBlendSrcFactorAlpha(),
200                                mBlendingOptions.GetBlendDestFactorAlpha() );
201
202     // Set blend equations
203     context.BlendEquationSeparate( mBlendingOptions.GetBlendEquationRgb(),
204                                    mBlendingOptions.GetBlendEquationAlpha() );
205   }
206 }
207
208 void Renderer::GlContextDestroyed()
209 {
210   mGeometry->GlContextDestroyed();
211 }
212
213 void Renderer::GlCleanup()
214 {
215 }
216
217 void Renderer::SetUniforms( BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program )
218 {
219   // Check if the map has changed
220   DALI_ASSERT_DEBUG( mRenderDataProvider && "No Uniform map data provider available" );
221
222   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
223
224   if( uniformMapDataProvider.GetUniformMapChanged( bufferIndex ) ||
225       node.GetUniformMapChanged(bufferIndex))
226   {
227     const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap( bufferIndex );
228     const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap( bufferIndex );
229
230     unsigned int maxMaps = uniformMap.Count() + uniformMapNode.Count();
231     mUniformIndexMap.Clear(); // Clear contents, but keep memory if we don't change size
232     mUniformIndexMap.Resize( maxMaps );
233
234     unsigned int mapIndex(0);
235     for(; mapIndex < uniformMap.Count() ; ++mapIndex )
236     {
237       mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex]->propertyPtr;
238       mUniformIndexMap[mapIndex].uniformIndex = program.RegisterUniform( uniformMap[mapIndex]->uniformName );
239     }
240
241     for( unsigned int nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count() ; ++nodeMapIndex )
242     {
243       unsigned int uniformIndex = program.RegisterUniform( uniformMapNode[nodeMapIndex]->uniformName );
244       bool found(false);
245       for( unsigned int i(0); i<uniformMap.Count(); ++i )
246       {
247         if( mUniformIndexMap[i].uniformIndex == uniformIndex )
248         {
249           mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
250           found = true;
251           break;
252         }
253       }
254
255       if( !found )
256       {
257         mUniformIndexMap[mapIndex].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
258         mUniformIndexMap[mapIndex].uniformIndex = uniformIndex;
259         ++mapIndex;
260       }
261     }
262
263     mUniformIndexMap.Resize( mapIndex );
264   }
265
266   // Set uniforms in local map
267   for( UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
268          end = mUniformIndexMap.End() ;
269        iter != end ;
270        ++iter )
271   {
272     SetUniformFromProperty( bufferIndex, program, *iter );
273   }
274
275   GLint sizeLoc = program.GetUniformLocation( Program::UNIFORM_SIZE );
276   if( -1 != sizeLoc )
277   {
278     program.SetSizeUniform3f( sizeLoc, size.x, size.y, size.z );
279   }
280 }
281
282 void Renderer::SetUniformFromProperty( BufferIndex bufferIndex, Program& program, UniformIndexMap& map )
283 {
284   GLint location = program.GetUniformLocation(map.uniformIndex);
285   if( Program::UNIFORM_UNKNOWN != location )
286   {
287     // switch based on property type to use correct GL uniform setter
288     switch ( map.propertyValue->GetType() )
289     {
290       case Property::INTEGER:
291       {
292         program.SetUniform1i( location, map.propertyValue->GetInteger( bufferIndex ) );
293         break;
294       }
295       case Property::FLOAT:
296       {
297         program.SetUniform1f( location, map.propertyValue->GetFloat( bufferIndex ) );
298         break;
299       }
300       case Property::VECTOR2:
301       {
302         Vector2 value( map.propertyValue->GetVector2( bufferIndex ) );
303         program.SetUniform2f( location, value.x, value.y );
304         break;
305       }
306
307       case Property::VECTOR3:
308       {
309         Vector3 value( map.propertyValue->GetVector3( bufferIndex ) );
310         program.SetUniform3f( location, value.x, value.y, value.z );
311         break;
312       }
313
314       case Property::VECTOR4:
315       {
316         Vector4 value( map.propertyValue->GetVector4( bufferIndex ) );
317         program.SetUniform4f( location, value.x, value.y, value.z, value.w );
318         break;
319       }
320
321       case Property::ROTATION:
322       {
323         Quaternion value( map.propertyValue->GetQuaternion( bufferIndex ) );
324         program.SetUniform4f( location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w );
325         break;
326       }
327
328       case Property::MATRIX:
329       {
330         const Matrix& value = map.propertyValue->GetMatrix(bufferIndex);
331         program.SetUniformMatrix4fv(location, 1, value.AsFloat() );
332         break;
333       }
334
335       case Property::MATRIX3:
336       {
337         const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex);
338         program.SetUniformMatrix3fv(location, 1, value.AsFloat() );
339         break;
340       }
341
342       default:
343       {
344         // Other property types are ignored
345         break;
346       }
347     }
348   }
349 }
350
351 bool Renderer::BindTextures( SceneGraph::TextureCache& textureCache, Program& program )
352 {
353   int textureUnit = 0;
354   bool result = true;
355
356   std::vector<Render::Texture>& textures( mRenderDataProvider->GetTextures() );
357   for( size_t i(0); result && i<textures.size(); ++i )
358   {
359     ResourceId textureId = textures[i].GetTextureId();
360     Internal::Texture* texture = textureCache.GetTexture( textureId );
361     if( texture )
362     {
363       result = textureCache.BindTexture( texture, textureId, GL_TEXTURE_2D, (TextureUnit)textureUnit );
364
365       if( result )
366       {
367         GLint uniformLocation;
368
369         bool result = program.GetSamplerUniformLocation( i, uniformLocation );
370         if( result && Program::UNIFORM_UNKNOWN != uniformLocation )
371         {
372           program.SetUniform1i( uniformLocation, textureUnit );
373
374           unsigned int samplerBitfield(0);
375           Render::Texture& textureMapping = textures[i];
376           const Render::Sampler* sampler( textureMapping.GetSampler() );
377           if( sampler )
378           {
379             samplerBitfield = ImageSampler::PackBitfield(
380               static_cast< FilterMode::Type >(sampler->GetMinifyFilterMode()),
381               static_cast< FilterMode::Type >(sampler->GetMagnifyFilterMode()),
382               static_cast< WrapMode::Type >(sampler->GetUWrapMode()),
383               static_cast< WrapMode::Type >(sampler->GetVWrapMode())
384                                                          );
385           }
386           else
387           {
388             samplerBitfield = ImageSampler::DEFAULT_BITFIELD;
389           }
390
391           texture->ApplySampler( (TextureUnit)textureUnit, samplerBitfield );
392
393           ++textureUnit;
394         }
395       }
396     }
397   }
398   return result;
399 }
400
401 void Renderer::SetFaceCullingMode( Dali::Renderer::FaceCullingMode mode )
402 {
403   mFaceCullingMode =  mode;
404 }
405
406 void Renderer::SetBlendingBitMask( unsigned int bitmask )
407 {
408   mBlendingOptions.SetBitmask( bitmask );
409 }
410
411 void Renderer::SetBlendColor( const Vector4* color )
412 {
413   mBlendingOptions.SetBlendColor( *color );
414 }
415
416 void Renderer::SetIndexedDrawFirstElement( size_t firstElement )
417 {
418   mIndexedDrawFirstElement = firstElement;
419 }
420
421 void Renderer::SetIndexedDrawElementsCount( size_t elementsCount )
422 {
423   mIndexedDrawElementsCount = elementsCount;
424 }
425
426 void Renderer::EnablePreMultipliedAlpha( bool enable )
427 {
428   mPremultipledAlphaEnabled = enable;
429 }
430
431 void Renderer::SetDepthWriteMode( Dali::Renderer::DepthWriteMode depthWriteMode )
432 {
433   mDepthWriteMode = depthWriteMode;
434 }
435
436 Dali::Renderer::DepthWriteMode Renderer::GetDepthWriteMode() const
437 {
438   return mDepthWriteMode;
439 }
440
441 void Renderer::Render( Context& context,
442                        SceneGraph::TextureCache& textureCache,
443                        BufferIndex bufferIndex,
444                        const SceneGraph::NodeDataProvider& node,
445                        SceneGraph::Shader& defaultShader,
446                        const Matrix& modelViewMatrix,
447                        const Matrix& viewMatrix,
448                        const Matrix& projectionMatrix,
449                        const Vector3& size,
450                        bool blend )
451 {
452   // Get the program to use:
453   Program* program = mRenderDataProvider->GetShader().GetProgram();
454   if( !program )
455   {
456     // if program is NULL it means this is a custom shader with non matching geometry type so we need to use default shaders program
457     program = defaultShader.GetProgram();
458     DALI_ASSERT_DEBUG( program && "Default shader should always have a program available." );
459     if( !program )
460     {
461       DALI_LOG_ERROR( "Failed to get program for shader at address %p.", (void*)&mRenderDataProvider->GetShader() );
462       return;
463     }
464   }
465
466   //Set cull face  mode
467   context.CullFace( mFaceCullingMode );
468
469   //Set blending mode
470   SetBlending( context, blend );
471
472   // Take the program into use so we can send uniforms to it
473   program->Use();
474
475   if( DALI_LIKELY( BindTextures( textureCache, *program ) ) )
476   {
477     // Only set up and draw if we have textures and they are all valid
478
479     // set projection and view matrix if program has not yet received them yet this frame
480     SetMatrices( *program, node.GetModelMatrix( bufferIndex ), viewMatrix, projectionMatrix, modelViewMatrix );
481
482     // set color uniform
483     GLint loc = program->GetUniformLocation( Program::UNIFORM_COLOR );
484     if( Program::UNIFORM_UNKNOWN != loc )
485     {
486       const Vector4& color = node.GetRenderColor( bufferIndex );
487       if( mPremultipledAlphaEnabled )
488       {
489         program->SetUniform4f( loc, color.r*color.a, color.g*color.a, color.b*color.a, color.a );
490       }
491       else
492       {
493         program->SetUniform4f( loc, color.r, color.g, color.b, color.a );
494       }
495     }
496
497     SetUniforms( bufferIndex, node, size, *program );
498
499     if( mUpdateAttributesLocation || mGeometry->AttributesChanged() )
500     {
501       mGeometry->GetAttributeLocationFromProgram( mAttributesLocation, *program, bufferIndex );
502       mUpdateAttributesLocation = false;
503     }
504
505     mGeometry->UploadAndDraw( context, bufferIndex, mAttributesLocation, mIndexedDrawFirstElement, mIndexedDrawElementsCount );
506   }
507 }
508
509 void Renderer::SetSortAttributes( BufferIndex bufferIndex, SceneGraph::RendererWithSortAttributes& sortAttributes ) const
510 {
511   sortAttributes.shader = &( mRenderDataProvider->GetShader() );
512   const std::vector<Render::Texture>& textures( mRenderDataProvider->GetTextures() );
513   if( !textures.empty() )
514   {
515     sortAttributes.textureResourceId = textures[0].GetTextureId();
516   }
517   else
518   {
519     sortAttributes.textureResourceId = Integration::InvalidResourceId;
520   }
521
522   sortAttributes.geometry = mGeometry;
523 }
524
525 } // namespace SceneGraph
526
527 } // namespace Internal
528
529 } // namespace Dali