[dali_1.1.32] 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.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 {
120   return new Renderer( dataProvider, geometry, blendingBitmask, blendColor, faceCullingMode, preMultipliedAlphaEnabled );
121 }
122
123 Renderer::Renderer( SceneGraph::RenderDataProvider* dataProvider,
124                     Render::Geometry* geometry,
125                     unsigned int blendingBitmask,
126                     const Vector4* blendColor,
127                     Dali::Renderer::FaceCullingMode faceCullingMode,
128                     bool preMultipliedAlphaEnabled)
129 : mRenderDataProvider( dataProvider ),
130   mContext(NULL),
131   mTextureCache( NULL ),
132   mUniformNameCache( NULL ),
133   mGeometry( geometry ),
134   mUniformIndexMap(),
135   mAttributesLocation(),
136   mBlendingOptions(),
137   mFaceCullingMode( faceCullingMode  ),
138   mIndexedDrawFirstElement( 0 ),
139   mIndexedDrawElementsCount( 0 ),
140   mSamplerBitfield( ImageSampler::PackBitfield( FilterMode::DEFAULT, FilterMode::DEFAULT ) ),
141   mUpdateAttributesLocation( true ),
142   mPremultipledAlphaEnabled( preMultipliedAlphaEnabled )
143 {
144   if(  blendingBitmask != 0u )
145   {
146     mBlendingOptions.SetBitmask( blendingBitmask );
147   }
148
149   if( blendColor )
150   {
151     mBlendingOptions.SetBlendColor( *blendColor );
152   }
153 }
154
155 void Renderer::Initialize( Context& context, SceneGraph::TextureCache& textureCache, Render::UniformNameCache& uniformNameCache )
156 {
157   mContext = &context;
158   mTextureCache = &textureCache;
159   mUniformNameCache = &uniformNameCache;
160 }
161
162 Renderer::~Renderer()
163 {
164 }
165
166 void Renderer::SetRenderDataProvider( SceneGraph::RenderDataProvider* dataProvider )
167 {
168   mRenderDataProvider = dataProvider;
169   mUpdateAttributesLocation = true;
170 }
171
172 void Renderer::SetGeometry( Render::Geometry* geometry )
173 {
174   mGeometry = geometry;
175   mUpdateAttributesLocation = true;
176 }
177
178 // Note - this is currently called from UpdateThread, PrepareRenderInstructions,
179 // as an optimisation.
180 // @todo MESH_REWORK Should use Update thread objects only in PrepareRenderInstructions.
181 bool Renderer::RequiresDepthTest() const
182 {
183   return mGeometry->RequiresDepthTest();
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( SceneGraph::TextureCache& textureCache, Program& program )
358 {
359   int textureUnit = 0;
360   bool result = true;
361
362   std::vector<Render::Texture>& textures( mRenderDataProvider->GetTextures() );
363   for( size_t i(0); result && i<textures.size(); ++i )
364   {
365     ResourceId textureId = textures[i].GetTextureId();
366     Internal::Texture* texture = textureCache.GetTexture( textureId );
367     if( texture )
368     {
369       result = textureCache.BindTexture( texture, textureId, GL_TEXTURE_2D, (TextureUnit)textureUnit );
370
371       if( result )
372       {
373         GLint uniformLocation;
374
375         bool result = program.GetSamplerUniformLocation( i, uniformLocation );
376         if( result && Program::UNIFORM_UNKNOWN != uniformLocation )
377         {
378           program.SetUniform1i( uniformLocation, textureUnit );
379
380           unsigned int samplerBitfield(0);
381           Render::Texture& textureMapping = textures[i];
382           const Render::Sampler* sampler( textureMapping.GetSampler() );
383           if( sampler )
384           {
385             samplerBitfield = ImageSampler::PackBitfield(
386               static_cast< FilterMode::Type >(sampler->GetMinifyFilterMode()),
387               static_cast< FilterMode::Type >(sampler->GetMagnifyFilterMode()),
388               static_cast< WrapMode::Type >(sampler->GetUWrapMode()),
389               static_cast< WrapMode::Type >(sampler->GetVWrapMode())
390                                                          );
391           }
392           else
393           {
394             samplerBitfield = ImageSampler::DEFAULT_BITFIELD;
395           }
396
397           texture->ApplySampler( (TextureUnit)textureUnit, samplerBitfield );
398
399           ++textureUnit;
400         }
401       }
402     }
403   }
404   return result;
405 }
406
407 void Renderer::SetFaceCullingMode( Dali::Renderer::FaceCullingMode mode )
408 {
409   mFaceCullingMode =  mode;
410 }
411
412 void Renderer::SetBlendingBitMask( unsigned int bitmask )
413 {
414   mBlendingOptions.SetBitmask( bitmask );
415 }
416
417 void Renderer::SetBlendColor( const Vector4* color )
418 {
419   mBlendingOptions.SetBlendColor( *color );
420 }
421
422 void Renderer::SetIndexedDrawFirstElement( size_t firstElement )
423 {
424   mIndexedDrawFirstElement = firstElement;
425 }
426
427 void Renderer::SetIndexedDrawElementsCount( size_t elementsCount )
428 {
429   mIndexedDrawElementsCount = elementsCount;
430 }
431
432 void Renderer::EnablePreMultipliedAlpha( bool enable )
433 {
434   mPremultipledAlphaEnabled = enable;
435 }
436
437 void Renderer::SetSampler( unsigned int samplerBitfield )
438 {
439   mSamplerBitfield = samplerBitfield;
440 }
441
442 void Renderer::Render( Context& context,
443                        SceneGraph::TextureCache& textureCache,
444                        BufferIndex bufferIndex,
445                        const SceneGraph::NodeDataProvider& node,
446                        SceneGraph::Shader& defaultShader,
447                        const Matrix& modelViewMatrix,
448                        const Matrix& viewMatrix,
449                        const Matrix& projectionMatrix,
450                        const Vector3& size,
451                        bool blend )
452 {
453   // Get the program to use:
454   Program* program = mRenderDataProvider->GetShader().GetProgram();
455   if( !program )
456   {
457     // if program is NULL it means this is a custom shader with non matching geometry type so we need to use default shaders program
458     program = defaultShader.GetProgram();
459     DALI_ASSERT_DEBUG( program && "Default shader should always have a program available." );
460     if( !program )
461     {
462       DALI_LOG_ERROR( "Failed to get program for shader at address %p.", (void*)&mRenderDataProvider->GetShader() );
463       return;
464     }
465   }
466
467   //Set cull face  mode
468   context.CullFace( mFaceCullingMode );
469
470   //Set blending mode
471   SetBlending( context, blend );
472
473   // Take the program into use so we can send uniforms to it
474   program->Use();
475
476   if( DALI_LIKELY( BindTextures( textureCache, *program ) ) )
477   {
478     // Only set up and draw if we have textures and they are all valid
479
480     // set projection and view matrix if program has not yet received them yet this frame
481     SetMatrices( *program, node.GetModelMatrix( bufferIndex ), viewMatrix, projectionMatrix, modelViewMatrix );
482
483     // set color uniform
484     GLint loc = program->GetUniformLocation( Program::UNIFORM_COLOR );
485     if( Program::UNIFORM_UNKNOWN != loc )
486     {
487       const Vector4& color = node.GetRenderColor( bufferIndex );
488       if( mPremultipledAlphaEnabled )
489       {
490         program->SetUniform4f( loc, color.r*color.a, color.g*color.a, color.b*color.a, color.a );
491       }
492       else
493       {
494         program->SetUniform4f( loc, color.r, color.g, color.b, color.a );
495       }
496     }
497
498     SetUniforms( bufferIndex, node, size, *program );
499
500     if( mUpdateAttributesLocation || mGeometry->AttributesChanged() )
501     {
502       mGeometry->GetAttributeLocationFromProgram( mAttributesLocation, *program, bufferIndex );
503       mUpdateAttributesLocation = false;
504     }
505
506     mGeometry->UploadAndDraw( context, bufferIndex, mAttributesLocation, mIndexedDrawFirstElement, mIndexedDrawElementsCount );
507   }
508 }
509
510 void Renderer::SetSortAttributes( BufferIndex bufferIndex, SceneGraph::RendererWithSortAttributes& sortAttributes ) const
511 {
512   sortAttributes.shader = &( mRenderDataProvider->GetShader() );
513   const std::vector<Render::Texture>& textures( mRenderDataProvider->GetTextures() );
514   if( !textures.empty() )
515   {
516     sortAttributes.textureResourceId = textures[0].GetTextureId();
517   }
518   else
519   {
520     sortAttributes.textureResourceId = Integration::InvalidResourceId;
521   }
522
523   sortAttributes.geometry = mGeometry;
524 }
525
526 } // namespace SceneGraph
527
528 } // namespace Internal
529
530 } // namespace Dali