[dali_1.2.6] 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
181 void Renderer::SetGeometry( Render::Geometry* geometry )
182 {
183   mGeometry = geometry;
184   mUpdateAttributesLocation = true;
185 }
186
187 void Renderer::SetBlending( Context& context, bool blend )
188 {
189   context.SetBlend( blend );
190   if( blend )
191   {
192     // Blend color is optional and rarely used
193     const Vector4* blendColor = mBlendingOptions.GetBlendColor();
194     if( blendColor )
195     {
196       context.SetCustomBlendColor( *blendColor );
197     }
198     else
199     {
200       context.SetDefaultBlendColor();
201     }
202
203     // Set blend source & destination factors
204     context.BlendFuncSeparate( mBlendingOptions.GetBlendSrcFactorRgb(),
205                                mBlendingOptions.GetBlendDestFactorRgb(),
206                                mBlendingOptions.GetBlendSrcFactorAlpha(),
207                                mBlendingOptions.GetBlendDestFactorAlpha() );
208
209     // Set blend equations
210     context.BlendEquationSeparate( mBlendingOptions.GetBlendEquationRgb(),
211                                    mBlendingOptions.GetBlendEquationAlpha() );
212   }
213 }
214
215 void Renderer::GlContextDestroyed()
216 {
217   mGeometry->GlContextDestroyed();
218 }
219
220 void Renderer::GlCleanup()
221 {
222 }
223
224 void Renderer::SetUniforms( BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program )
225 {
226   // Check if the map has changed
227   DALI_ASSERT_DEBUG( mRenderDataProvider && "No Uniform map data provider available" );
228
229   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
230
231   if( uniformMapDataProvider.GetUniformMapChanged( bufferIndex ) ||
232       node.GetUniformMapChanged(bufferIndex))
233   {
234     const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap( bufferIndex );
235     const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap( bufferIndex );
236
237     unsigned int maxMaps = uniformMap.Count() + uniformMapNode.Count();
238     mUniformIndexMap.Clear(); // Clear contents, but keep memory if we don't change size
239     mUniformIndexMap.Resize( maxMaps );
240
241     unsigned int mapIndex(0);
242     for(; mapIndex < uniformMap.Count() ; ++mapIndex )
243     {
244       mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex]->propertyPtr;
245       mUniformIndexMap[mapIndex].uniformIndex = program.RegisterUniform( uniformMap[mapIndex]->uniformName );
246     }
247
248     for( unsigned int nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count() ; ++nodeMapIndex )
249     {
250       unsigned int uniformIndex = program.RegisterUniform( uniformMapNode[nodeMapIndex]->uniformName );
251       bool found(false);
252       for( unsigned int i(0); i<uniformMap.Count(); ++i )
253       {
254         if( mUniformIndexMap[i].uniformIndex == uniformIndex )
255         {
256           mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
257           found = true;
258           break;
259         }
260       }
261
262       if( !found )
263       {
264         mUniformIndexMap[mapIndex].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
265         mUniformIndexMap[mapIndex].uniformIndex = uniformIndex;
266         ++mapIndex;
267       }
268     }
269
270     mUniformIndexMap.Resize( mapIndex );
271   }
272
273   // Set uniforms in local map
274   for( UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
275          end = mUniformIndexMap.End() ;
276        iter != end ;
277        ++iter )
278   {
279     SetUniformFromProperty( bufferIndex, program, *iter );
280   }
281
282   GLint sizeLoc = program.GetUniformLocation( Program::UNIFORM_SIZE );
283   if( -1 != sizeLoc )
284   {
285     program.SetSizeUniform3f( sizeLoc, size.x, size.y, size.z );
286   }
287 }
288
289 void Renderer::SetUniformFromProperty( BufferIndex bufferIndex, Program& program, UniformIndexMap& map )
290 {
291   GLint location = program.GetUniformLocation(map.uniformIndex);
292   if( Program::UNIFORM_UNKNOWN != location )
293   {
294     // switch based on property type to use correct GL uniform setter
295     switch ( map.propertyValue->GetType() )
296     {
297       case Property::INTEGER:
298       {
299         program.SetUniform1i( location, map.propertyValue->GetInteger( bufferIndex ) );
300         break;
301       }
302       case Property::FLOAT:
303       {
304         program.SetUniform1f( location, map.propertyValue->GetFloat( bufferIndex ) );
305         break;
306       }
307       case Property::VECTOR2:
308       {
309         Vector2 value( map.propertyValue->GetVector2( bufferIndex ) );
310         program.SetUniform2f( location, value.x, value.y );
311         break;
312       }
313
314       case Property::VECTOR3:
315       {
316         Vector3 value( map.propertyValue->GetVector3( bufferIndex ) );
317         program.SetUniform3f( location, value.x, value.y, value.z );
318         break;
319       }
320
321       case Property::VECTOR4:
322       {
323         Vector4 value( map.propertyValue->GetVector4( bufferIndex ) );
324         program.SetUniform4f( location, value.x, value.y, value.z, value.w );
325         break;
326       }
327
328       case Property::ROTATION:
329       {
330         Quaternion value( map.propertyValue->GetQuaternion( bufferIndex ) );
331         program.SetUniform4f( location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w );
332         break;
333       }
334
335       case Property::MATRIX:
336       {
337         const Matrix& value = map.propertyValue->GetMatrix(bufferIndex);
338         program.SetUniformMatrix4fv(location, 1, value.AsFloat() );
339         break;
340       }
341
342       case Property::MATRIX3:
343       {
344         const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex);
345         program.SetUniformMatrix3fv(location, 1, value.AsFloat() );
346         break;
347       }
348
349       default:
350       {
351         // Other property types are ignored
352         break;
353       }
354     }
355   }
356 }
357
358 bool Renderer::BindTextures( Context& context, SceneGraph::TextureCache& textureCache, Program& program )
359 {
360   unsigned int textureUnit = 0;
361   bool result = true;
362
363   std::vector<Render::Sampler*>& samplers( mRenderDataProvider->GetSamplers() );
364
365   std::vector<Render::Texture>& textures( mRenderDataProvider->GetTextures() );
366   GLint uniformLocation(-1);
367   for( size_t i(0); result && i<textures.size(); ++i )
368   {
369     ResourceId textureId = textures[i].GetTextureId();
370     Internal::Texture* texture = textureCache.GetTexture( textureId );
371     if( texture )
372     {
373       result = textureCache.BindTexture( texture, textureId, GL_TEXTURE_2D, (TextureUnit)textureUnit );
374
375       if( result )
376       {
377         GLint uniformLocation;
378
379         //TODO : This is a bug, result variable is being shadowed. Fix it!
380         bool result = program.GetSamplerUniformLocation( i, uniformLocation );
381         if( result && Program::UNIFORM_UNKNOWN != uniformLocation )
382         {
383           program.SetUniform1i( uniformLocation, textureUnit );
384
385           unsigned int samplerBitfield(ImageSampler::DEFAULT_BITFIELD);
386           const Render::Sampler* sampler(  samplers[i] );
387           if( sampler )
388           {
389             samplerBitfield = sampler->mBitfield;
390           }
391
392           texture->ApplySampler( (TextureUnit)textureUnit, samplerBitfield );
393
394           ++textureUnit;
395         }
396       }
397     }
398   }
399
400   std::vector<Render::NewTexture*>& newTextures( mRenderDataProvider->GetNewTextures() );
401   for( size_t i(0); result && i<newTextures.size(); ++i )
402   {
403     if( newTextures[i] )
404     {
405       result = program.GetSamplerUniformLocation( i, uniformLocation ) &&
406                newTextures[i]->Bind(context, textureUnit, samplers[i] );
407
408       if( result )
409       {
410         program.SetUniform1i( uniformLocation, textureUnit );
411         ++textureUnit;
412       }
413     }
414   }
415
416   return result;
417 }
418
419 void Renderer::SetFaceCullingMode( FaceCullingMode::Type mode )
420 {
421   mFaceCullingMode =  mode;
422 }
423
424 void Renderer::SetBlendingBitMask( unsigned int bitmask )
425 {
426   mBlendingOptions.SetBitmask( bitmask );
427 }
428
429 void Renderer::SetBlendColor( const Vector4* color )
430 {
431   mBlendingOptions.SetBlendColor( *color );
432 }
433
434 void Renderer::SetIndexedDrawFirstElement( size_t firstElement )
435 {
436   mIndexedDrawFirstElement = firstElement;
437 }
438
439 void Renderer::SetIndexedDrawElementsCount( size_t elementsCount )
440 {
441   mIndexedDrawElementsCount = elementsCount;
442 }
443
444 void Renderer::EnablePreMultipliedAlpha( bool enable )
445 {
446   mPremultipledAlphaEnabled = enable;
447 }
448
449 void Renderer::SetDepthWriteMode( DepthWriteMode::Type depthWriteMode )
450 {
451   mDepthWriteMode = depthWriteMode;
452 }
453
454 void Renderer::SetDepthTestMode( DepthTestMode::Type depthTestMode )
455 {
456   mDepthTestMode = depthTestMode;
457 }
458
459 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
460 {
461   return mDepthWriteMode;
462 }
463
464 DepthTestMode::Type Renderer::GetDepthTestMode() const
465 {
466   return mDepthTestMode;
467 }
468
469 void Renderer::SetDepthFunction( DepthFunction::Type depthFunction )
470 {
471   mDepthFunction = depthFunction;
472 }
473
474 DepthFunction::Type Renderer::GetDepthFunction() const
475 {
476   return mDepthFunction;
477 }
478
479 void Renderer::SetRenderMode( RenderMode::Type renderMode )
480 {
481   mStencilParameters.renderMode = renderMode;
482 }
483
484 RenderMode::Type Renderer::GetRenderMode() const
485 {
486   return mStencilParameters.renderMode;
487 }
488
489 void Renderer::SetStencilFunction( StencilFunction::Type stencilFunction )
490 {
491   mStencilParameters.stencilFunction = stencilFunction;
492 }
493
494 StencilFunction::Type Renderer::GetStencilFunction() const
495 {
496   return mStencilParameters.stencilFunction;
497 }
498
499 void Renderer::SetStencilFunctionMask( int stencilFunctionMask )
500 {
501   mStencilParameters.stencilFunctionMask = stencilFunctionMask;
502 }
503
504 int Renderer::GetStencilFunctionMask() const
505 {
506   return mStencilParameters.stencilFunctionMask;
507 }
508
509 void Renderer::SetStencilFunctionReference( int stencilFunctionReference )
510 {
511   mStencilParameters.stencilFunctionReference = stencilFunctionReference;
512 }
513
514 int Renderer::GetStencilFunctionReference() const
515 {
516   return mStencilParameters.stencilFunctionReference;
517 }
518
519 void Renderer::SetStencilMask( int stencilMask )
520 {
521   mStencilParameters.stencilMask = stencilMask;
522 }
523
524 int Renderer::GetStencilMask() const
525 {
526   return mStencilParameters.stencilMask;
527 }
528
529 void Renderer::SetStencilOperationOnFail( StencilOperation::Type stencilOperationOnFail )
530 {
531   mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
532 }
533
534 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
535 {
536   return mStencilParameters.stencilOperationOnFail;
537 }
538
539 void Renderer::SetStencilOperationOnZFail( StencilOperation::Type stencilOperationOnZFail )
540 {
541   mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
542 }
543
544 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
545 {
546   return mStencilParameters.stencilOperationOnZFail;
547 }
548
549 void Renderer::SetStencilOperationOnZPass( StencilOperation::Type stencilOperationOnZPass )
550 {
551   mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
552 }
553
554 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
555 {
556   return mStencilParameters.stencilOperationOnZPass;
557 }
558
559 void Renderer::SetBatchingEnabled( bool batchingEnabled )
560 {
561   mBatchingEnabled = batchingEnabled;
562 }
563
564 void Renderer::Render( Context& context,
565                        SceneGraph::TextureCache& textureCache,
566                        BufferIndex bufferIndex,
567                        const SceneGraph::NodeDataProvider& node,
568                        SceneGraph::Shader& defaultShader,
569                        const Matrix& modelMatrix,
570                        const Matrix& modelViewMatrix,
571                        const Matrix& viewMatrix,
572                        const Matrix& projectionMatrix,
573                        const Vector3& size,
574                        Render::Geometry* externalGeometry,
575                        bool blend )
576 {
577   // Get the program to use:
578   Program* program = mRenderDataProvider->GetShader().GetProgram();
579   if( !program )
580   {
581     // if program is NULL it means this is a custom shader with non matching geometry type so we need to use default shaders program
582     program = defaultShader.GetProgram();
583     DALI_ASSERT_DEBUG( program && "Default shader should always have a program available." );
584     if( !program )
585     {
586       DALI_LOG_ERROR( "Failed to get program for shader at address %p.\n", (void*)&mRenderDataProvider->GetShader() );
587       return;
588     }
589   }
590
591   //Set cull face  mode
592   context.CullFace( mFaceCullingMode );
593
594   //Set blending mode
595   SetBlending( context, blend );
596
597   // Take the program into use so we can send uniforms to it
598   program->Use();
599
600   if( DALI_LIKELY( BindTextures( context, textureCache, *program ) ) )
601   {
602     // Only set up and draw if we have textures and they are all valid
603
604     // set projection and view matrix if program has not yet received them yet this frame
605     SetMatrices( *program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix );
606
607     // set color uniform
608     GLint loc = program->GetUniformLocation( Program::UNIFORM_COLOR );
609     if( Program::UNIFORM_UNKNOWN != loc )
610     {
611       const Vector4& color = node.GetRenderColor( bufferIndex );
612       if( mPremultipledAlphaEnabled )
613       {
614         program->SetUniform4f( loc, color.r*color.a, color.g*color.a, color.b*color.a, color.a );
615       }
616       else
617       {
618         program->SetUniform4f( loc, color.r, color.g, color.b, color.a );
619       }
620     }
621
622     SetUniforms( bufferIndex, node, size, *program );
623     Render::Geometry* geometry = externalGeometry ? externalGeometry : mGeometry;
624
625     if( mUpdateAttributesLocation || geometry->AttributesChanged() )
626     {
627       geometry->GetAttributeLocationFromProgram( mAttributesLocation, *program, bufferIndex );
628       mUpdateAttributesLocation = false;
629     }
630
631     geometry->UploadAndDraw( context, bufferIndex, mAttributesLocation, mIndexedDrawFirstElement, mIndexedDrawElementsCount );
632   }
633 }
634
635 void Renderer::SetSortAttributes( BufferIndex bufferIndex, SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes ) const
636 {
637   sortAttributes.shader = &( mRenderDataProvider->GetShader() );
638   const std::vector<Render::Texture>& textures( mRenderDataProvider->GetTextures() );
639   if( !textures.empty() )
640   {
641     sortAttributes.textureResourceId = textures[0].GetTextureId();
642   }
643   else
644   {
645     sortAttributes.textureResourceId = Integration::InvalidResourceId;
646   }
647
648   sortAttributes.geometry = mGeometry;
649 }
650
651 } // namespace SceneGraph
652
653 } // namespace Internal
654
655 } // namespace Dali