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