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