[dali_1.2.15] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / internal / render / renderers / render-renderer.cpp
1 /*
2  * Copyright (c) 2016 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 // INTERNAL INCLUDES
22 #include <dali/internal/common/image-sampler.h>
23 #include <dali/internal/render/gl-resources/context.h>
24 #include <dali/internal/render/renderers/render-sampler.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/gl-resources/texture-cache.h>
29 #include <dali/internal/render/gl-resources/gl-texture.h>
30
31 namespace Dali
32 {
33
34 namespace Internal
35 {
36
37 namespace
38 {
39
40 static Matrix gModelViewProjectionMatrix( false ); ///< a shared matrix to calculate the MVP matrix, dont want to store it in object to reduce storage overhead
41 static Matrix3 gNormalMatrix; ///< a shared matrix to calculate normal matrix, dont want to store it in object to reduce storage overhead
42
43 /**
44  * Helper to set view and projection matrices once per program
45  * @param program to set the matrices to
46  * @param modelMatrix to set
47  * @param viewMatrix to set
48  * @param projectionMatrix to set
49  * @param modelViewMatrix to set
50  * @param modelViewProjectionMatrix to set
51  */
52 inline void SetMatrices( Program& program,
53                          const Matrix& modelMatrix,
54                          const Matrix& viewMatrix,
55                          const Matrix& projectionMatrix,
56                          const Matrix& modelViewMatrix )
57 {
58   GLint loc = program.GetUniformLocation( Program::UNIFORM_MODEL_MATRIX );
59   if( Program::UNIFORM_UNKNOWN != loc )
60   {
61     program.SetUniformMatrix4fv( loc, 1, modelMatrix.AsFloat() );
62   }
63   loc = program.GetUniformLocation( Program::UNIFORM_VIEW_MATRIX );
64   if( Program::UNIFORM_UNKNOWN != loc )
65   {
66     if( program.GetViewMatrix() != &viewMatrix )
67     {
68       program.SetViewMatrix( &viewMatrix );
69       program.SetUniformMatrix4fv( loc, 1, viewMatrix.AsFloat() );
70     }
71   }
72   // set projection matrix if program has not yet received it this frame or if it is dirty
73   loc = program.GetUniformLocation( Program::UNIFORM_PROJECTION_MATRIX );
74   if( Program::UNIFORM_UNKNOWN != loc )
75   {
76     if( program.GetProjectionMatrix() != &projectionMatrix )
77     {
78       program.SetProjectionMatrix( &projectionMatrix );
79       program.SetUniformMatrix4fv( loc, 1, projectionMatrix.AsFloat() );
80     }
81   }
82   loc = program.GetUniformLocation(Program::UNIFORM_MODELVIEW_MATRIX);
83   if( Program::UNIFORM_UNKNOWN != loc )
84   {
85     program.SetUniformMatrix4fv( loc, 1, modelViewMatrix.AsFloat() );
86   }
87
88   loc = program.GetUniformLocation( Program::UNIFORM_MVP_MATRIX );
89   if( Program::UNIFORM_UNKNOWN != loc )
90   {
91     Matrix::Multiply( gModelViewProjectionMatrix, modelViewMatrix, projectionMatrix );
92     program.SetUniformMatrix4fv( loc, 1, gModelViewProjectionMatrix.AsFloat() );
93   }
94
95   loc = program.GetUniformLocation( Program::UNIFORM_NORMAL_MATRIX );
96   if( Program::UNIFORM_UNKNOWN != loc )
97   {
98     gNormalMatrix = modelViewMatrix;
99     gNormalMatrix.Invert();
100     gNormalMatrix.Transpose();
101     program.SetUniformMatrix3fv( loc, 1, gNormalMatrix.AsFloat() );
102   }
103 }
104
105 }
106
107 namespace Render
108 {
109
110 Renderer* Renderer::New( SceneGraph::RenderDataProvider* dataProvider,
111                          Render::Geometry* geometry,
112                          unsigned int blendingBitmask,
113                          const Vector4* blendColor,
114                          FaceCullingMode::Type faceCullingMode,
115                          bool preMultipliedAlphaEnabled,
116                          DepthWriteMode::Type depthWriteMode,
117                          DepthTestMode::Type depthTestMode,
118                          DepthFunction::Type depthFunction,
119                          StencilParameters& stencilParameters )
120 {
121   return new Renderer( dataProvider, geometry, blendingBitmask, blendColor,
122                        faceCullingMode, preMultipliedAlphaEnabled, depthWriteMode, depthTestMode,
123                        depthFunction, stencilParameters );
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                     StencilParameters& stencilParameters )
136 : mRenderDataProvider( dataProvider ),
137   mContext( NULL),
138   mTextureCache( NULL ),
139   mGeometry( geometry ),
140   mUniformIndexMap(),
141   mAttributesLocation(),
142   mStencilParameters( stencilParameters ),
143   mBlendingOptions(),
144   mIndexedDrawFirstElement( 0 ),
145   mIndexedDrawElementsCount( 0 ),
146   mDepthFunction( depthFunction ),
147   mFaceCullingMode( faceCullingMode ),
148   mDepthWriteMode( depthWriteMode ),
149   mDepthTestMode( depthTestMode ),
150   mUpdateAttributesLocation( true ),
151   mPremultipledAlphaEnabled( preMultipliedAlphaEnabled ),
152   mBatchingEnabled( false )
153 {
154   if(  blendingBitmask != 0u )
155   {
156     mBlendingOptions.SetBitmask( blendingBitmask );
157   }
158
159   if( blendColor )
160   {
161     mBlendingOptions.SetBlendColor( *blendColor );
162   }
163 }
164
165 void Renderer::Initialize( Context& context, SceneGraph::TextureCache& textureCache )
166 {
167   mContext = &context;
168   mTextureCache = &textureCache;
169 }
170
171 Renderer::~Renderer()
172 {
173 }
174
175 void Renderer::SetRenderDataProvider( SceneGraph::RenderDataProvider* dataProvider )
176 {
177   mRenderDataProvider = dataProvider;
178   mUpdateAttributesLocation = true;
179
180   //Check that the number of textures match the number of samplers in the shader
181   size_t textureCount =  dataProvider->GetTextures().size() + dataProvider->GetNewTextures().size();
182   Program* program = dataProvider->GetShader().GetProgram();
183   if( program && program->GetActiveSamplerCount() != textureCount )
184   {
185     DALI_LOG_ERROR("The number of active samplers in the shader(%lu) does not match the number of textures in the TextureSet(%lu)\n",
186                    program->GetActiveSamplerCount(),
187                    textureCount );
188   }
189 }
190
191 void Renderer::SetGeometry( Render::Geometry* geometry )
192 {
193   mGeometry = geometry;
194   mUpdateAttributesLocation = true;
195 }
196
197 void Renderer::SetBlending( Context& context, bool blend )
198 {
199   context.SetBlend( blend );
200   if( blend )
201   {
202     // Blend color is optional and rarely used
203     const Vector4* blendColor = mBlendingOptions.GetBlendColor();
204     if( blendColor )
205     {
206       context.SetCustomBlendColor( *blendColor );
207     }
208     else
209     {
210       context.SetDefaultBlendColor();
211     }
212
213     // Set blend source & destination factors
214     context.BlendFuncSeparate( mBlendingOptions.GetBlendSrcFactorRgb(),
215                                mBlendingOptions.GetBlendDestFactorRgb(),
216                                mBlendingOptions.GetBlendSrcFactorAlpha(),
217                                mBlendingOptions.GetBlendDestFactorAlpha() );
218
219     // Set blend equations
220     context.BlendEquationSeparate( mBlendingOptions.GetBlendEquationRgb(),
221                                    mBlendingOptions.GetBlendEquationAlpha() );
222   }
223 }
224
225 void Renderer::GlContextDestroyed()
226 {
227   mGeometry->GlContextDestroyed();
228 }
229
230 void Renderer::GlCleanup()
231 {
232 }
233
234 void Renderer::SetUniforms( BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program )
235 {
236   // Check if the map has changed
237   DALI_ASSERT_DEBUG( mRenderDataProvider && "No Uniform map data provider available" );
238
239   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
240
241   if( uniformMapDataProvider.GetUniformMapChanged( bufferIndex ) ||
242       node.GetUniformMapChanged(bufferIndex))
243   {
244     const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap( bufferIndex );
245     const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap( bufferIndex );
246
247     unsigned int maxMaps = uniformMap.Count() + uniformMapNode.Count();
248     mUniformIndexMap.Clear(); // Clear contents, but keep memory if we don't change size
249     mUniformIndexMap.Resize( maxMaps );
250
251     unsigned int mapIndex(0);
252     for(; mapIndex < uniformMap.Count() ; ++mapIndex )
253     {
254       mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex]->propertyPtr;
255       mUniformIndexMap[mapIndex].uniformIndex = program.RegisterUniform( uniformMap[mapIndex]->uniformName );
256     }
257
258     for( unsigned int nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count() ; ++nodeMapIndex )
259     {
260       unsigned int uniformIndex = program.RegisterUniform( uniformMapNode[nodeMapIndex]->uniformName );
261       bool found(false);
262       for( unsigned int i(0); i<uniformMap.Count(); ++i )
263       {
264         if( mUniformIndexMap[i].uniformIndex == uniformIndex )
265         {
266           mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
267           found = true;
268           break;
269         }
270       }
271
272       if( !found )
273       {
274         mUniformIndexMap[mapIndex].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
275         mUniformIndexMap[mapIndex].uniformIndex = uniformIndex;
276         ++mapIndex;
277       }
278     }
279
280     mUniformIndexMap.Resize( mapIndex );
281   }
282
283   // Set uniforms in local map
284   for( UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
285          end = mUniformIndexMap.End() ;
286        iter != end ;
287        ++iter )
288   {
289     SetUniformFromProperty( bufferIndex, program, *iter );
290   }
291
292   GLint sizeLoc = program.GetUniformLocation( Program::UNIFORM_SIZE );
293   if( -1 != sizeLoc )
294   {
295     program.SetSizeUniform3f( sizeLoc, size.x, size.y, size.z );
296   }
297 }
298
299 void Renderer::SetUniformFromProperty( BufferIndex bufferIndex, Program& program, UniformIndexMap& map )
300 {
301   GLint location = program.GetUniformLocation(map.uniformIndex);
302   if( Program::UNIFORM_UNKNOWN != location )
303   {
304     // switch based on property type to use correct GL uniform setter
305     switch ( map.propertyValue->GetType() )
306     {
307       case Property::INTEGER:
308       {
309         program.SetUniform1i( location, map.propertyValue->GetInteger( bufferIndex ) );
310         break;
311       }
312       case Property::FLOAT:
313       {
314         program.SetUniform1f( location, map.propertyValue->GetFloat( bufferIndex ) );
315         break;
316       }
317       case Property::VECTOR2:
318       {
319         Vector2 value( map.propertyValue->GetVector2( bufferIndex ) );
320         program.SetUniform2f( location, value.x, value.y );
321         break;
322       }
323
324       case Property::VECTOR3:
325       {
326         Vector3 value( map.propertyValue->GetVector3( bufferIndex ) );
327         program.SetUniform3f( location, value.x, value.y, value.z );
328         break;
329       }
330
331       case Property::VECTOR4:
332       {
333         Vector4 value( map.propertyValue->GetVector4( bufferIndex ) );
334         program.SetUniform4f( location, value.x, value.y, value.z, value.w );
335         break;
336       }
337
338       case Property::ROTATION:
339       {
340         Quaternion value( map.propertyValue->GetQuaternion( bufferIndex ) );
341         program.SetUniform4f( location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w );
342         break;
343       }
344
345       case Property::MATRIX:
346       {
347         const Matrix& value = map.propertyValue->GetMatrix(bufferIndex);
348         program.SetUniformMatrix4fv(location, 1, value.AsFloat() );
349         break;
350       }
351
352       case Property::MATRIX3:
353       {
354         const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex);
355         program.SetUniformMatrix3fv(location, 1, value.AsFloat() );
356         break;
357       }
358
359       default:
360       {
361         // Other property types are ignored
362         break;
363       }
364     }
365   }
366 }
367
368 bool Renderer::BindTextures( Context& context, SceneGraph::TextureCache& textureCache, Program& program )
369 {
370   unsigned int textureUnit = 0;
371   bool result = true;
372
373   std::vector<Render::Sampler*>& samplers( mRenderDataProvider->GetSamplers() );
374
375   std::vector<Render::Texture>& textures( mRenderDataProvider->GetTextures() );
376   GLint uniformLocation(-1);
377   for( size_t i(0); result && i<textures.size(); ++i )
378   {
379     ResourceId textureId = textures[i].GetTextureId();
380     Internal::Texture* texture = textureCache.GetTexture( textureId );
381     if( texture )
382     {
383       result = textureCache.BindTexture( texture, textureId, GL_TEXTURE_2D, (TextureUnit)textureUnit );
384
385       if( result )
386       {
387         GLint uniformLocation;
388
389         //TODO : This is a bug, result variable is being shadowed. Fix it!
390         bool result = program.GetSamplerUniformLocation( i, uniformLocation );
391         if( result && Program::UNIFORM_UNKNOWN != uniformLocation )
392         {
393           program.SetUniform1i( uniformLocation, textureUnit );
394
395           unsigned int samplerBitfield(ImageSampler::DEFAULT_BITFIELD);
396           const Render::Sampler* sampler(  samplers[i] );
397           if( sampler )
398           {
399             samplerBitfield = sampler->mBitfield;
400           }
401
402           texture->ApplySampler( (TextureUnit)textureUnit, samplerBitfield );
403
404           ++textureUnit;
405         }
406       }
407     }
408   }
409
410   std::vector<Render::NewTexture*>& newTextures( mRenderDataProvider->GetNewTextures() );
411   for( size_t i(0); i<newTextures.size() && result; ++i )
412   {
413     if( newTextures[i] )
414     {
415       result = newTextures[i]->Bind(context, textureUnit, samplers[i] );
416       if( result && program.GetSamplerUniformLocation( i, uniformLocation ) )
417       {
418         program.SetUniform1i( uniformLocation, textureUnit );
419         ++textureUnit;
420       }
421     }
422   }
423
424   return result;
425 }
426
427 void Renderer::SetFaceCullingMode( FaceCullingMode::Type mode )
428 {
429   mFaceCullingMode =  mode;
430 }
431
432 void Renderer::SetBlendingBitMask( unsigned int bitmask )
433 {
434   mBlendingOptions.SetBitmask( bitmask );
435 }
436
437 void Renderer::SetBlendColor( const Vector4* color )
438 {
439   mBlendingOptions.SetBlendColor( *color );
440 }
441
442 void Renderer::SetIndexedDrawFirstElement( size_t firstElement )
443 {
444   mIndexedDrawFirstElement = firstElement;
445 }
446
447 void Renderer::SetIndexedDrawElementsCount( size_t elementsCount )
448 {
449   mIndexedDrawElementsCount = elementsCount;
450 }
451
452 void Renderer::EnablePreMultipliedAlpha( bool enable )
453 {
454   mPremultipledAlphaEnabled = enable;
455 }
456
457 void Renderer::SetDepthWriteMode( DepthWriteMode::Type depthWriteMode )
458 {
459   mDepthWriteMode = depthWriteMode;
460 }
461
462 void Renderer::SetDepthTestMode( DepthTestMode::Type depthTestMode )
463 {
464   mDepthTestMode = depthTestMode;
465 }
466
467 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
468 {
469   return mDepthWriteMode;
470 }
471
472 DepthTestMode::Type Renderer::GetDepthTestMode() const
473 {
474   return mDepthTestMode;
475 }
476
477 void Renderer::SetDepthFunction( DepthFunction::Type depthFunction )
478 {
479   mDepthFunction = depthFunction;
480 }
481
482 DepthFunction::Type Renderer::GetDepthFunction() const
483 {
484   return mDepthFunction;
485 }
486
487 void Renderer::SetRenderMode( RenderMode::Type renderMode )
488 {
489   mStencilParameters.renderMode = renderMode;
490 }
491
492 RenderMode::Type Renderer::GetRenderMode() const
493 {
494   return mStencilParameters.renderMode;
495 }
496
497 void Renderer::SetStencilFunction( StencilFunction::Type stencilFunction )
498 {
499   mStencilParameters.stencilFunction = stencilFunction;
500 }
501
502 StencilFunction::Type Renderer::GetStencilFunction() const
503 {
504   return mStencilParameters.stencilFunction;
505 }
506
507 void Renderer::SetStencilFunctionMask( int stencilFunctionMask )
508 {
509   mStencilParameters.stencilFunctionMask = stencilFunctionMask;
510 }
511
512 int Renderer::GetStencilFunctionMask() const
513 {
514   return mStencilParameters.stencilFunctionMask;
515 }
516
517 void Renderer::SetStencilFunctionReference( int stencilFunctionReference )
518 {
519   mStencilParameters.stencilFunctionReference = stencilFunctionReference;
520 }
521
522 int Renderer::GetStencilFunctionReference() const
523 {
524   return mStencilParameters.stencilFunctionReference;
525 }
526
527 void Renderer::SetStencilMask( int stencilMask )
528 {
529   mStencilParameters.stencilMask = stencilMask;
530 }
531
532 int Renderer::GetStencilMask() const
533 {
534   return mStencilParameters.stencilMask;
535 }
536
537 void Renderer::SetStencilOperationOnFail( StencilOperation::Type stencilOperationOnFail )
538 {
539   mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
540 }
541
542 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
543 {
544   return mStencilParameters.stencilOperationOnFail;
545 }
546
547 void Renderer::SetStencilOperationOnZFail( StencilOperation::Type stencilOperationOnZFail )
548 {
549   mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
550 }
551
552 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
553 {
554   return mStencilParameters.stencilOperationOnZFail;
555 }
556
557 void Renderer::SetStencilOperationOnZPass( StencilOperation::Type stencilOperationOnZPass )
558 {
559   mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
560 }
561
562 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
563 {
564   return mStencilParameters.stencilOperationOnZPass;
565 }
566
567 void Renderer::SetBatchingEnabled( bool batchingEnabled )
568 {
569   mBatchingEnabled = batchingEnabled;
570 }
571
572 void Renderer::Render( Context& context,
573                        SceneGraph::TextureCache& textureCache,
574                        BufferIndex bufferIndex,
575                        const SceneGraph::NodeDataProvider& node,
576                        SceneGraph::Shader& defaultShader,
577                        const Matrix& modelMatrix,
578                        const Matrix& modelViewMatrix,
579                        const Matrix& viewMatrix,
580                        const Matrix& projectionMatrix,
581                        const Vector3& size,
582                        Render::Geometry* externalGeometry,
583                        bool blend )
584 {
585   // Get the program to use:
586   Program* program = mRenderDataProvider->GetShader().GetProgram();
587   if( !program )
588   {
589     // if program is NULL it means this is a custom shader with non matching geometry type so we need to use default shaders program
590     program = defaultShader.GetProgram();
591     DALI_ASSERT_DEBUG( program && "Default shader should always have a program available." );
592     if( !program )
593     {
594       DALI_LOG_ERROR( "Failed to get program for shader at address %p.\n", (void*)&mRenderDataProvider->GetShader() );
595       return;
596     }
597   }
598
599   //Set cull face  mode
600   context.CullFace( mFaceCullingMode );
601
602   //Set blending mode
603   SetBlending( context, blend );
604
605   // Take the program into use so we can send uniforms to it
606   program->Use();
607
608   if( DALI_LIKELY( BindTextures( context, textureCache, *program ) ) )
609   {
610     // Only set up and draw if we have textures and they are all valid
611
612     // set projection and view matrix if program has not yet received them yet this frame
613     SetMatrices( *program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix );
614
615     // set color uniform
616     GLint loc = program->GetUniformLocation( Program::UNIFORM_COLOR );
617     if( Program::UNIFORM_UNKNOWN != loc )
618     {
619       const Vector4& color = node.GetRenderColor( bufferIndex );
620       if( mPremultipledAlphaEnabled )
621       {
622         program->SetUniform4f( loc, color.r*color.a, color.g*color.a, color.b*color.a, color.a );
623       }
624       else
625       {
626         program->SetUniform4f( loc, color.r, color.g, color.b, color.a );
627       }
628     }
629
630     SetUniforms( bufferIndex, node, size, *program );
631     Render::Geometry* geometry = externalGeometry ? externalGeometry : mGeometry;
632
633     if( mUpdateAttributesLocation || geometry->AttributesChanged() )
634     {
635       geometry->GetAttributeLocationFromProgram( mAttributesLocation, *program, bufferIndex );
636       mUpdateAttributesLocation = false;
637     }
638
639     geometry->UploadAndDraw( context, bufferIndex, mAttributesLocation, mIndexedDrawFirstElement, mIndexedDrawElementsCount );
640   }
641 }
642
643 void Renderer::SetSortAttributes( BufferIndex bufferIndex, SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes ) const
644 {
645   sortAttributes.shader = &( mRenderDataProvider->GetShader() );
646   const std::vector<Render::Texture>& textures( mRenderDataProvider->GetTextures() );
647   if( !textures.empty() )
648   {
649     sortAttributes.textureResourceId = textures[0].GetTextureId();
650   }
651   else
652   {
653     sortAttributes.textureResourceId = Integration::InvalidResourceId;
654   }
655
656   sortAttributes.geometry = mGeometry;
657 }
658
659 } // namespace SceneGraph
660
661 } // namespace Internal
662
663 } // namespace Dali