Merge "DALi Version 1.1.37" into devel/master
[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-cache.h>
31 #include <dali/public-api/actors/blending.h>
32 #include <dali/internal/render/gl-resources/gl-texture.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( Context& context, SceneGraph::TextureCache& textureCache, Program& program )
355 {
356   unsigned int textureUnit = 0;
357   bool result = true;
358
359   std::vector<Render::Sampler*>& samplers( mRenderDataProvider->GetSamplers() );
360
361   std::vector<Render::Texture>& textures( mRenderDataProvider->GetTextures() );
362   for( size_t i(0); result && i<textures.size(); ++i )
363   {
364     ResourceId textureId = textures[i].GetTextureId();
365     Internal::Texture* texture = textureCache.GetTexture( textureId );
366     if( texture )
367     {
368       result = textureCache.BindTexture( texture, textureId, GL_TEXTURE_2D, (TextureUnit)textureUnit );
369
370       if( result )
371       {
372         GLint uniformLocation;
373
374         bool result = program.GetSamplerUniformLocation( i, uniformLocation );
375         if( result && Program::UNIFORM_UNKNOWN != uniformLocation )
376         {
377           program.SetUniform1i( uniformLocation, textureUnit );
378
379           unsigned int samplerBitfield(ImageSampler::DEFAULT_BITFIELD);
380           const Render::Sampler* sampler(  samplers[i] );
381           if( sampler )
382           {
383             samplerBitfield = sampler->mBitfield;
384           }
385
386           texture->ApplySampler( (TextureUnit)textureUnit, samplerBitfield );
387
388           ++textureUnit;
389         }
390       }
391     }
392   }
393
394   std::vector<Render::NewTexture*>& newTextures( mRenderDataProvider->GetNewTextures() );
395   GLint uniformLocation(0);
396   for( size_t i(0); result && i<newTextures.size(); ++i )
397   {
398     if( newTextures[i] )
399     {
400       bool result = program.GetSamplerUniformLocation( i, uniformLocation );
401       if( result )
402       {
403         newTextures[i]->Bind(context, textureUnit, samplers[i] );
404         program.SetUniform1i( uniformLocation, textureUnit );
405         ++textureUnit;
406       }
407     }
408   }
409
410   return result;
411 }
412
413 void Renderer::SetFaceCullingMode( FaceCullingMode::Type mode )
414 {
415   mFaceCullingMode =  mode;
416 }
417
418 void Renderer::SetBlendingBitMask( unsigned int bitmask )
419 {
420   mBlendingOptions.SetBitmask( bitmask );
421 }
422
423 void Renderer::SetBlendColor( const Vector4* color )
424 {
425   mBlendingOptions.SetBlendColor( *color );
426 }
427
428 void Renderer::SetIndexedDrawFirstElement( size_t firstElement )
429 {
430   mIndexedDrawFirstElement = firstElement;
431 }
432
433 void Renderer::SetIndexedDrawElementsCount( size_t elementsCount )
434 {
435   mIndexedDrawElementsCount = elementsCount;
436 }
437
438 void Renderer::EnablePreMultipliedAlpha( bool enable )
439 {
440   mPremultipledAlphaEnabled = enable;
441 }
442
443 void Renderer::SetDepthWriteMode( DepthWriteMode::Type depthWriteMode )
444 {
445   mDepthWriteMode = depthWriteMode;
446 }
447
448 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
449 {
450   return mDepthWriteMode;
451 }
452
453 void Renderer::SetDepthFunction( DepthFunction::Type depthFunction )
454 {
455   mDepthFunction = depthFunction;
456 }
457
458 DepthFunction::Type Renderer::GetDepthFunction() const
459 {
460   return mDepthFunction;
461 }
462
463 void Renderer::Render( Context& context,
464                        SceneGraph::TextureCache& textureCache,
465                        BufferIndex bufferIndex,
466                        const SceneGraph::NodeDataProvider& node,
467                        SceneGraph::Shader& defaultShader,
468                        const Matrix& modelMatrix,
469                        const Matrix& modelViewMatrix,
470                        const Matrix& viewMatrix,
471                        const Matrix& projectionMatrix,
472                        const Vector3& size,
473                        bool blend )
474 {
475   // Get the program to use:
476   Program* program = mRenderDataProvider->GetShader().GetProgram();
477   if( !program )
478   {
479     // if program is NULL it means this is a custom shader with non matching geometry type so we need to use default shaders program
480     program = defaultShader.GetProgram();
481     DALI_ASSERT_DEBUG( program && "Default shader should always have a program available." );
482     if( !program )
483     {
484       DALI_LOG_ERROR( "Failed to get program for shader at address %p.", (void*)&mRenderDataProvider->GetShader() );
485       return;
486     }
487   }
488
489   //Set cull face  mode
490   context.CullFace( mFaceCullingMode );
491
492   //Set blending mode
493   SetBlending( context, blend );
494
495   // Take the program into use so we can send uniforms to it
496   program->Use();
497
498   if( DALI_LIKELY( BindTextures( context, textureCache, *program ) ) )
499   {
500     // Only set up and draw if we have textures and they are all valid
501
502     // set projection and view matrix if program has not yet received them yet this frame
503     SetMatrices( *program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix );
504
505     // set color uniform
506     GLint loc = program->GetUniformLocation( Program::UNIFORM_COLOR );
507     if( Program::UNIFORM_UNKNOWN != loc )
508     {
509       const Vector4& color = node.GetRenderColor( bufferIndex );
510       if( mPremultipledAlphaEnabled )
511       {
512         program->SetUniform4f( loc, color.r*color.a, color.g*color.a, color.b*color.a, color.a );
513       }
514       else
515       {
516         program->SetUniform4f( loc, color.r, color.g, color.b, color.a );
517       }
518     }
519
520     SetUniforms( bufferIndex, node, size, *program );
521
522     if( mUpdateAttributesLocation || mGeometry->AttributesChanged() )
523     {
524       mGeometry->GetAttributeLocationFromProgram( mAttributesLocation, *program, bufferIndex );
525       mUpdateAttributesLocation = false;
526     }
527
528     mGeometry->UploadAndDraw( context, bufferIndex, mAttributesLocation, mIndexedDrawFirstElement, mIndexedDrawElementsCount );
529   }
530 }
531
532 void Renderer::SetSortAttributes( BufferIndex bufferIndex, SceneGraph::RendererWithSortAttributes& sortAttributes ) const
533 {
534   sortAttributes.shader = &( mRenderDataProvider->GetShader() );
535   const std::vector<Render::Texture>& textures( mRenderDataProvider->GetTextures() );
536   if( !textures.empty() )
537   {
538     sortAttributes.textureResourceId = textures[0].GetTextureId();
539   }
540   else
541   {
542     sortAttributes.textureResourceId = Integration::InvalidResourceId;
543   }
544
545   sortAttributes.geometry = mGeometry;
546 }
547
548 } // namespace SceneGraph
549
550 } // namespace Internal
551
552 } // namespace Dali