Merge branch 'devel/master' into tizen
[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/shaders/scene-graph-shader.h>
26 #include <dali/internal/render/shaders/program.h>
27 #include <dali/internal/render/data-providers/node-data-provider.h>
28 #include <dali/internal/render/data-providers/uniform-name-cache.h>
29 #include <dali/internal/render/gl-resources/texture.h>
30 #include <dali/internal/render/gl-resources/texture-cache.h>
31 #include <dali/public-api/actors/blending.h>
32
33 namespace Dali
34 {
35
36 namespace Internal
37 {
38
39 namespace
40 {
41
42 static Matrix gModelViewProjectionMatrix( false ); ///< a shared matrix to calculate the MVP matrix, dont want to store it in object to reduce storage overhead
43 static Matrix3 gNormalMatrix; ///< a shared matrix to calculate normal matrix, dont want to store it in object to reduce storage overhead
44
45 /**
46  * Helper to set view and projection matrices once per program
47  * @param program to set the matrices to
48  * @param modelMatrix to set
49  * @param viewMatrix to set
50  * @param projectionMatrix to set
51  * @param modelViewMatrix to set
52  * @param modelViewProjectionMatrix to set
53  */
54 inline void SetMatrices( Program& program,
55                          const Matrix& modelMatrix,
56                          const Matrix& viewMatrix,
57                          const Matrix& projectionMatrix,
58                          const Matrix& modelViewMatrix )
59 {
60   GLint loc = program.GetUniformLocation( Program::UNIFORM_MODEL_MATRIX );
61   if( Program::UNIFORM_UNKNOWN != loc )
62   {
63     program.SetUniformMatrix4fv( loc, 1, modelMatrix.AsFloat() );
64   }
65   loc = program.GetUniformLocation( Program::UNIFORM_VIEW_MATRIX );
66   if( Program::UNIFORM_UNKNOWN != loc )
67   {
68     if( program.GetViewMatrix() != &viewMatrix )
69     {
70       program.SetViewMatrix( &viewMatrix );
71       program.SetUniformMatrix4fv( loc, 1, viewMatrix.AsFloat() );
72     }
73   }
74   // set projection matrix if program has not yet received it this frame or if it is dirty
75   loc = program.GetUniformLocation( Program::UNIFORM_PROJECTION_MATRIX );
76   if( Program::UNIFORM_UNKNOWN != loc )
77   {
78     if( program.GetProjectionMatrix() != &projectionMatrix )
79     {
80       program.SetProjectionMatrix( &projectionMatrix );
81       program.SetUniformMatrix4fv( loc, 1, projectionMatrix.AsFloat() );
82     }
83   }
84   loc = program.GetUniformLocation(Program::UNIFORM_MODELVIEW_MATRIX);
85   if( Program::UNIFORM_UNKNOWN != loc )
86   {
87     program.SetUniformMatrix4fv( loc, 1, modelViewMatrix.AsFloat() );
88   }
89
90   loc = program.GetUniformLocation( Program::UNIFORM_MVP_MATRIX );
91   if( Program::UNIFORM_UNKNOWN != loc )
92   {
93     Matrix::Multiply( gModelViewProjectionMatrix, modelViewMatrix, projectionMatrix );
94     program.SetUniformMatrix4fv( loc, 1, gModelViewProjectionMatrix.AsFloat() );
95   }
96
97   loc = program.GetUniformLocation( Program::UNIFORM_NORMAL_MATRIX );
98   if( Program::UNIFORM_UNKNOWN != loc )
99   {
100     gNormalMatrix = modelViewMatrix;
101     gNormalMatrix.Invert();
102     gNormalMatrix.Transpose();
103     program.SetUniformMatrix3fv( loc, 1, gNormalMatrix.AsFloat() );
104   }
105 }
106
107 }
108
109 namespace Render
110 {
111
112 Renderer* Renderer::New( SceneGraph::RenderDataProvider* dataProvider,
113                          SceneGraph::RenderGeometry* renderGeometry,
114                          unsigned int blendingBitmask,
115                          const Vector4* blendColor,
116                          Dali::Renderer::FaceCullingMode faceCullingMode,
117                          bool preMultipliedAlphaEnabled )
118 {
119   return new Renderer( dataProvider, renderGeometry, blendingBitmask, blendColor, faceCullingMode, preMultipliedAlphaEnabled );
120 }
121
122 Renderer::Renderer( SceneGraph::RenderDataProvider* dataProvider,
123                     SceneGraph::RenderGeometry* renderGeometry,
124                     unsigned int blendingBitmask,
125                     const Vector4* blendColor,
126                     Dali::Renderer::FaceCullingMode faceCullingMode,
127                     bool preMultipliedAlphaEnabled)
128 : mRenderDataProvider( dataProvider ),
129   mContext(NULL),
130   mTextureCache( NULL ),
131   mUniformNameCache( NULL ),
132   mRenderGeometry( renderGeometry ),
133   mUniformIndexMap(),
134   mAttributesLocation(),
135   mBlendingOptions(),
136   mFaceCullingMode( faceCullingMode  ),
137   mSamplerBitfield( ImageSampler::PackBitfield( FilterMode::DEFAULT, FilterMode::DEFAULT ) ),
138   mUpdateAttributesLocation( true ),
139   mPremultipledAlphaEnabled( preMultipliedAlphaEnabled )
140 {
141   if(  blendingBitmask != 0u )
142   {
143     mBlendingOptions.SetBitmask( blendingBitmask );
144   }
145
146   if( blendColor )
147   {
148     mBlendingOptions.SetBlendColor( *blendColor );
149   }
150 }
151
152 void Renderer::Initialize( Context& context, SceneGraph::TextureCache& textureCache, Render::UniformNameCache& uniformNameCache )
153 {
154   mContext = &context;
155   mTextureCache = &textureCache;
156   mUniformNameCache = &uniformNameCache;
157 }
158
159 Renderer::~Renderer()
160 {
161 }
162
163 void Renderer::SetRenderDataProvider( SceneGraph::RenderDataProvider* dataProvider )
164 {
165   mRenderDataProvider = dataProvider;
166   mUpdateAttributesLocation = true;
167 }
168
169 void Renderer::SetGeometry( SceneGraph::RenderGeometry* renderGeometry )
170 {
171   mRenderGeometry = renderGeometry;
172   mUpdateAttributesLocation = true;
173 }
174
175 // Note - this is currently called from UpdateThread, PrepareRenderInstructions,
176 // as an optimisation.
177 // @todo MESH_REWORK Should use Update thread objects only in PrepareRenderInstructions.
178 bool Renderer::RequiresDepthTest() const
179 {
180   return mRenderGeometry->RequiresDepthTest();
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   mRenderGeometry->GlContextDestroyed();
214 }
215
216 void Renderer::GlCleanup()
217 {
218 }
219
220 void Renderer::SetUniforms( BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, 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     Vector3 size = node.GetRenderSize( bufferIndex );
282     program.SetSizeUniform3f( sizeLoc, size.x, size.y, size.z );
283   }
284 }
285
286 void Renderer::SetUniformFromProperty( BufferIndex bufferIndex, Program& program, UniformIndexMap& map )
287 {
288   GLint location = program.GetUniformLocation(map.uniformIndex);
289   if( Program::UNIFORM_UNKNOWN != location )
290   {
291     // switch based on property type to use correct GL uniform setter
292     switch ( map.propertyValue->GetType() )
293     {
294       case Property::INTEGER:
295       {
296         program.SetUniform1i( location, map.propertyValue->GetInteger( bufferIndex ) );
297         break;
298       }
299       case Property::FLOAT:
300       {
301         program.SetUniform1f( location, map.propertyValue->GetFloat( bufferIndex ) );
302         break;
303       }
304       case Property::VECTOR2:
305       {
306         Vector2 value( map.propertyValue->GetVector2( bufferIndex ) );
307         program.SetUniform2f( location, value.x, value.y );
308         break;
309       }
310
311       case Property::VECTOR3:
312       {
313         Vector3 value( map.propertyValue->GetVector3( bufferIndex ) );
314         program.SetUniform3f( location, value.x, value.y, value.z );
315         break;
316       }
317
318       case Property::VECTOR4:
319       {
320         Vector4 value( map.propertyValue->GetVector4( bufferIndex ) );
321         program.SetUniform4f( location, value.x, value.y, value.z, value.w );
322         break;
323       }
324
325       case Property::ROTATION:
326       {
327         Quaternion value( map.propertyValue->GetQuaternion( bufferIndex ) );
328         program.SetUniform4f( location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w );
329         break;
330       }
331
332       case Property::MATRIX:
333       {
334         const Matrix& value = map.propertyValue->GetMatrix(bufferIndex);
335         program.SetUniformMatrix4fv(location, 1, value.AsFloat() );
336         break;
337       }
338
339       case Property::MATRIX3:
340       {
341         const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex);
342         program.SetUniformMatrix3fv(location, 1, value.AsFloat() );
343         break;
344       }
345
346       default:
347       {
348         // Other property types are ignored
349         break;
350       }
351     }
352   }
353 }
354
355 bool Renderer::BindTextures( SceneGraph::TextureCache& textureCache, Program& program )
356 {
357   int textureUnit = 0;
358   bool result = true;
359
360   std::vector<Render::Texture>& textures( mRenderDataProvider->GetTextures() );
361   for( size_t i(0); result && i<textures.size(); ++i )
362   {
363     ResourceId textureId = textures[i].GetTextureId();
364     Internal::Texture* texture = textureCache.GetTexture( textureId );
365     if( texture )
366     {
367       result = textureCache.BindTexture( texture, textureId, GL_TEXTURE_2D, (TextureUnit)textureUnit );
368
369       if( result )
370       {
371         Render::Texture& textureMapping = textures[i];
372         // Set sampler uniform location for the texture
373         int32_t uniqueIndex = textureMapping.GetUniformUniqueIndex();
374         if( Render::Texture::NOT_INITIALIZED == uniqueIndex )
375         {
376           uniqueIndex = mUniformNameCache->GetSamplerUniformUniqueIndex( textureMapping.GetUniformName() );
377           textureMapping.SetUniformUniqueIndex( uniqueIndex );
378         }
379         GLint uniformLocation = program.GetSamplerUniformLocation( uniqueIndex, textureMapping.GetUniformName() );
380         if( Program::UNIFORM_UNKNOWN != uniformLocation )
381         {
382           program.SetUniform1i( uniformLocation, textureUnit );
383         }
384
385         unsigned int samplerBitfield(0);
386         const Render::Sampler* sampler( textureMapping.GetSampler() );
387         if( sampler )
388         {
389           samplerBitfield = ImageSampler::PackBitfield(
390             static_cast< FilterMode::Type >(sampler->GetMinifyFilterMode()),
391             static_cast< FilterMode::Type >(sampler->GetMagnifyFilterMode()),
392             static_cast< WrapMode::Type >(sampler->GetUWrapMode()),
393             static_cast< WrapMode::Type >(sampler->GetVWrapMode())
394                                                        );
395         }
396         else
397         {
398           samplerBitfield = ImageSampler::DEFAULT_BITFIELD;
399         }
400
401         texture->ApplySampler( (TextureUnit)textureUnit, samplerBitfield );
402
403         ++textureUnit;
404       }
405     }
406   }
407   return result;
408 }
409
410 void Renderer::SetFaceCullingMode( Dali::Renderer::FaceCullingMode mode )
411 {
412   mFaceCullingMode =  mode;
413 }
414
415 void Renderer::SetBlendingBitMask( unsigned int bitmask )
416 {
417   mBlendingOptions.SetBitmask( bitmask );
418 }
419
420 void Renderer::SetBlendColor( const Vector4* color )
421 {
422   mBlendingOptions.SetBlendColor( *color );
423 }
424
425 void Renderer::EnablePreMultipliedAlpha( bool enable )
426 {
427   mPremultipledAlphaEnabled = enable;
428 }
429
430 void Renderer::SetSampler( unsigned int samplerBitfield )
431 {
432   mSamplerBitfield = samplerBitfield;
433 }
434
435 void Renderer::Render( Context& context,
436                        SceneGraph::TextureCache& textureCache,
437                        BufferIndex bufferIndex,
438                        const SceneGraph::NodeDataProvider& node,
439                        SceneGraph::Shader& defaultShader,
440                        const Matrix& modelViewMatrix,
441                        const Matrix& viewMatrix,
442                        const Matrix& projectionMatrix,
443                        bool blend )
444 {
445   // Get the program to use:
446   Program* program = mRenderDataProvider->GetShader().GetProgram();
447   if( !program )
448   {
449     // if program is NULL it means this is a custom shader with non matching geometry type so we need to use default shaders program
450     program = defaultShader.GetProgram();
451     DALI_ASSERT_DEBUG( program && "Default shader should always have a program available." );
452     if( !program )
453     {
454       DALI_LOG_ERROR( "Failed to get program for shader at address %p.", (void*)&mRenderDataProvider->GetShader() );
455       return;
456     }
457   }
458
459   //Set cull face  mode
460   context.CullFace( mFaceCullingMode );
461
462   //Set blending mode
463   SetBlending( context, blend );
464
465   // Take the program into use so we can send uniforms to it
466   program->Use();
467
468   if( DALI_LIKELY( BindTextures( textureCache, *program ) ) )
469   {
470     // Only set up and draw if we have textures and they are all valid
471
472     // set projection and view matrix if program has not yet received them yet this frame
473     SetMatrices( *program, node.GetModelMatrix( bufferIndex ), viewMatrix, projectionMatrix, modelViewMatrix );
474
475     // set color uniform
476     GLint loc = program->GetUniformLocation( Program::UNIFORM_COLOR );
477     if( Program::UNIFORM_UNKNOWN != loc )
478     {
479       const Vector4& color = node.GetRenderColor( bufferIndex );
480       if( mPremultipledAlphaEnabled )
481       {
482         program->SetUniform4f( loc, color.r*color.a, color.g*color.a, color.b*color.a, color.a );
483       }
484       else
485       {
486         program->SetUniform4f( loc, color.r, color.g, color.b, color.a );
487       }
488     }
489
490     SetUniforms( bufferIndex, node, *program );
491
492     if( mUpdateAttributesLocation || mRenderGeometry->AttributesChanged() )
493     {
494       mRenderGeometry->GetAttributeLocationFromProgram( mAttributesLocation, *program, bufferIndex );
495       mUpdateAttributesLocation = false;
496     }
497
498     mRenderGeometry->UploadAndDraw( context, bufferIndex, mAttributesLocation );
499   }
500 }
501
502 void Renderer::SetSortAttributes( BufferIndex bufferIndex, SceneGraph::RendererWithSortAttributes& sortAttributes ) const
503 {
504   sortAttributes.shader = &( mRenderDataProvider->GetShader() );
505   const std::vector<Render::Texture>& textures( mRenderDataProvider->GetTextures() );
506   if( !textures.empty() )
507   {
508     sortAttributes.textureResourceId = textures[0].GetTextureId();
509   }
510   else
511   {
512     sortAttributes.textureResourceId = Integration::InvalidResourceId;
513   }
514
515   sortAttributes.geometry = mRenderGeometry;
516 }
517
518 } // namespace SceneGraph
519
520 } // namespace Internal
521
522 } // namespace Dali