[dali_1.1.31] 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                          SceneGraph::RenderGeometry* renderGeometry,
115                          unsigned int blendingBitmask,
116                          const Vector4* blendColor,
117                          Dali::Renderer::FaceCullingMode faceCullingMode,
118                          bool preMultipliedAlphaEnabled )
119 {
120   return new Renderer( dataProvider, renderGeometry, blendingBitmask, blendColor, faceCullingMode, preMultipliedAlphaEnabled );
121 }
122
123 Renderer::Renderer( SceneGraph::RenderDataProvider* dataProvider,
124                     SceneGraph::RenderGeometry* renderGeometry,
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   mRenderGeometry( renderGeometry ),
134   mUniformIndexMap(),
135   mAttributesLocation(),
136   mBlendingOptions(),
137   mFaceCullingMode( faceCullingMode  ),
138   mSamplerBitfield( ImageSampler::PackBitfield( FilterMode::DEFAULT, FilterMode::DEFAULT ) ),
139   mUpdateAttributesLocation( true ),
140   mPremultipledAlphaEnabled( preMultipliedAlphaEnabled )
141 {
142   if(  blendingBitmask != 0u )
143   {
144     mBlendingOptions.SetBitmask( blendingBitmask );
145   }
146
147   if( blendColor )
148   {
149     mBlendingOptions.SetBlendColor( *blendColor );
150   }
151 }
152
153 void Renderer::Initialize( Context& context, SceneGraph::TextureCache& textureCache, Render::UniformNameCache& uniformNameCache )
154 {
155   mContext = &context;
156   mTextureCache = &textureCache;
157   mUniformNameCache = &uniformNameCache;
158 }
159
160 Renderer::~Renderer()
161 {
162 }
163
164 void Renderer::SetRenderDataProvider( SceneGraph::RenderDataProvider* dataProvider )
165 {
166   mRenderDataProvider = dataProvider;
167   mUpdateAttributesLocation = true;
168 }
169
170 void Renderer::SetGeometry( SceneGraph::RenderGeometry* renderGeometry )
171 {
172   mRenderGeometry = renderGeometry;
173   mUpdateAttributesLocation = true;
174 }
175
176 // Note - this is currently called from UpdateThread, PrepareRenderInstructions,
177 // as an optimisation.
178 // @todo MESH_REWORK Should use Update thread objects only in PrepareRenderInstructions.
179 bool Renderer::RequiresDepthTest() const
180 {
181   return mRenderGeometry->RequiresDepthTest();
182 }
183
184 void Renderer::SetBlending( Context& context, bool blend )
185 {
186   context.SetBlend( blend );
187   if( blend )
188   {
189     // Blend color is optional and rarely used
190     const Vector4* blendColor = mBlendingOptions.GetBlendColor();
191     if( blendColor )
192     {
193       context.SetCustomBlendColor( *blendColor );
194     }
195     else
196     {
197       context.SetDefaultBlendColor();
198     }
199
200     // Set blend source & destination factors
201     context.BlendFuncSeparate( mBlendingOptions.GetBlendSrcFactorRgb(),
202                                mBlendingOptions.GetBlendDestFactorRgb(),
203                                mBlendingOptions.GetBlendSrcFactorAlpha(),
204                                mBlendingOptions.GetBlendDestFactorAlpha() );
205
206     // Set blend equations
207     context.BlendEquationSeparate( mBlendingOptions.GetBlendEquationRgb(),
208                                    mBlendingOptions.GetBlendEquationAlpha() );
209   }
210 }
211
212 void Renderer::GlContextDestroyed()
213 {
214   mRenderGeometry->GlContextDestroyed();
215 }
216
217 void Renderer::GlCleanup()
218 {
219 }
220
221 void Renderer::SetUniforms( BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program )
222 {
223   // Check if the map has changed
224   DALI_ASSERT_DEBUG( mRenderDataProvider && "No Uniform map data provider available" );
225
226   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
227
228   if( uniformMapDataProvider.GetUniformMapChanged( bufferIndex ) ||
229       node.GetUniformMapChanged(bufferIndex))
230   {
231     const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap( bufferIndex );
232     const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap( bufferIndex );
233
234     unsigned int maxMaps = uniformMap.Count() + uniformMapNode.Count();
235     mUniformIndexMap.Clear(); // Clear contents, but keep memory if we don't change size
236     mUniformIndexMap.Resize( maxMaps );
237
238     unsigned int mapIndex(0);
239     for(; mapIndex < uniformMap.Count() ; ++mapIndex )
240     {
241       mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex]->propertyPtr;
242       mUniformIndexMap[mapIndex].uniformIndex = program.RegisterUniform( uniformMap[mapIndex]->uniformName );
243     }
244
245     for( unsigned int nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count() ; ++nodeMapIndex )
246     {
247       unsigned int uniformIndex = program.RegisterUniform( uniformMapNode[nodeMapIndex]->uniformName );
248       bool found(false);
249       for( unsigned int i(0); i<uniformMap.Count(); ++i )
250       {
251         if( mUniformIndexMap[i].uniformIndex == uniformIndex )
252         {
253           mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
254           found = true;
255           break;
256         }
257       }
258
259       if( !found )
260       {
261         mUniformIndexMap[mapIndex].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
262         mUniformIndexMap[mapIndex].uniformIndex = uniformIndex;
263         ++mapIndex;
264       }
265     }
266
267     mUniformIndexMap.Resize( mapIndex );
268   }
269
270   // Set uniforms in local map
271   for( UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
272          end = mUniformIndexMap.End() ;
273        iter != end ;
274        ++iter )
275   {
276     SetUniformFromProperty( bufferIndex, program, *iter );
277   }
278
279   GLint sizeLoc = program.GetUniformLocation( Program::UNIFORM_SIZE );
280   if( -1 != sizeLoc )
281   {
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         GLint uniformLocation;
372
373         bool result = program.GetSamplerUniformLocation( i, uniformLocation );
374         if( result && Program::UNIFORM_UNKNOWN != uniformLocation )
375         {
376           program.SetUniform1i( uniformLocation, textureUnit );
377
378           unsigned int samplerBitfield(0);
379           Render::Texture& textureMapping = textures[i];
380           const Render::Sampler* sampler( textureMapping.GetSampler() );
381           if( sampler )
382           {
383             samplerBitfield = ImageSampler::PackBitfield(
384               static_cast< FilterMode::Type >(sampler->GetMinifyFilterMode()),
385               static_cast< FilterMode::Type >(sampler->GetMagnifyFilterMode()),
386               static_cast< WrapMode::Type >(sampler->GetUWrapMode()),
387               static_cast< WrapMode::Type >(sampler->GetVWrapMode())
388                                                          );
389           }
390           else
391           {
392             samplerBitfield = ImageSampler::DEFAULT_BITFIELD;
393           }
394
395           texture->ApplySampler( (TextureUnit)textureUnit, samplerBitfield );
396
397           ++textureUnit;
398         }
399       }
400     }
401   }
402   return result;
403 }
404
405 void Renderer::SetFaceCullingMode( Dali::Renderer::FaceCullingMode mode )
406 {
407   mFaceCullingMode =  mode;
408 }
409
410 void Renderer::SetBlendingBitMask( unsigned int bitmask )
411 {
412   mBlendingOptions.SetBitmask( bitmask );
413 }
414
415 void Renderer::SetBlendColor( const Vector4* color )
416 {
417   mBlendingOptions.SetBlendColor( *color );
418 }
419
420 void Renderer::EnablePreMultipliedAlpha( bool enable )
421 {
422   mPremultipledAlphaEnabled = enable;
423 }
424
425 void Renderer::SetSampler( unsigned int samplerBitfield )
426 {
427   mSamplerBitfield = samplerBitfield;
428 }
429
430 void Renderer::Render( Context& context,
431                        SceneGraph::TextureCache& textureCache,
432                        BufferIndex bufferIndex,
433                        const SceneGraph::NodeDataProvider& node,
434                        SceneGraph::Shader& defaultShader,
435                        const Matrix& modelViewMatrix,
436                        const Matrix& viewMatrix,
437                        const Matrix& projectionMatrix,
438                        const Vector3& size,
439                        bool blend )
440 {
441   // Get the program to use:
442   Program* program = mRenderDataProvider->GetShader().GetProgram();
443   if( !program )
444   {
445     // if program is NULL it means this is a custom shader with non matching geometry type so we need to use default shaders program
446     program = defaultShader.GetProgram();
447     DALI_ASSERT_DEBUG( program && "Default shader should always have a program available." );
448     if( !program )
449     {
450       DALI_LOG_ERROR( "Failed to get program for shader at address %p.", (void*)&mRenderDataProvider->GetShader() );
451       return;
452     }
453   }
454
455   //Set cull face  mode
456   context.CullFace( mFaceCullingMode );
457
458   //Set blending mode
459   SetBlending( context, blend );
460
461   // Take the program into use so we can send uniforms to it
462   program->Use();
463
464   if( DALI_LIKELY( BindTextures( textureCache, *program ) ) )
465   {
466     // Only set up and draw if we have textures and they are all valid
467
468     // set projection and view matrix if program has not yet received them yet this frame
469     SetMatrices( *program, node.GetModelMatrix( bufferIndex ), viewMatrix, projectionMatrix, modelViewMatrix );
470
471     // set color uniform
472     GLint loc = program->GetUniformLocation( Program::UNIFORM_COLOR );
473     if( Program::UNIFORM_UNKNOWN != loc )
474     {
475       const Vector4& color = node.GetRenderColor( bufferIndex );
476       if( mPremultipledAlphaEnabled )
477       {
478         program->SetUniform4f( loc, color.r*color.a, color.g*color.a, color.b*color.a, color.a );
479       }
480       else
481       {
482         program->SetUniform4f( loc, color.r, color.g, color.b, color.a );
483       }
484     }
485
486   SetUniforms( bufferIndex, node, size, *program );
487
488     if( mUpdateAttributesLocation || mRenderGeometry->AttributesChanged() )
489     {
490       mRenderGeometry->GetAttributeLocationFromProgram( mAttributesLocation, *program, bufferIndex );
491       mUpdateAttributesLocation = false;
492     }
493
494     mRenderGeometry->UploadAndDraw( context, bufferIndex, mAttributesLocation );
495   }
496 }
497
498 void Renderer::SetSortAttributes( BufferIndex bufferIndex, SceneGraph::RendererWithSortAttributes& sortAttributes ) const
499 {
500   sortAttributes.shader = &( mRenderDataProvider->GetShader() );
501   const std::vector<Render::Texture>& textures( mRenderDataProvider->GetTextures() );
502   if( !textures.empty() )
503   {
504     sortAttributes.textureResourceId = textures[0].GetTextureId();
505   }
506   else
507   {
508     sortAttributes.textureResourceId = Integration::InvalidResourceId;
509   }
510
511   sortAttributes.geometry = mRenderGeometry;
512 }
513
514 } // namespace SceneGraph
515
516 } // namespace Internal
517
518 } // namespace Dali