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