[3.0] Remove/move experimental features
[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 {
153   if(  blendingBitmask != 0u )
154   {
155     mBlendingOptions.SetBitmask( blendingBitmask );
156   }
157
158   if( blendColor )
159   {
160     mBlendingOptions.SetBlendColor( *blendColor );
161   }
162 }
163
164 void Renderer::Initialize( Context& context, SceneGraph::TextureCache& textureCache )
165 {
166   mContext = &context;
167   mTextureCache = &textureCache;
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::SetRenderMode( RenderMode::Type renderMode )
479 {
480   mStencilParameters.renderMode = renderMode;
481 }
482
483 RenderMode::Type Renderer::GetRenderMode() const
484 {
485   return mStencilParameters.renderMode;
486 }
487
488 void Renderer::SetStencilFunction( StencilFunction::Type stencilFunction )
489 {
490   mStencilParameters.stencilFunction = stencilFunction;
491 }
492
493 StencilFunction::Type Renderer::GetStencilFunction() const
494 {
495   return mStencilParameters.stencilFunction;
496 }
497
498 void Renderer::SetStencilFunctionMask( int stencilFunctionMask )
499 {
500   mStencilParameters.stencilFunctionMask = stencilFunctionMask;
501 }
502
503 int Renderer::GetStencilFunctionMask() const
504 {
505   return mStencilParameters.stencilFunctionMask;
506 }
507
508 void Renderer::SetStencilFunctionReference( int stencilFunctionReference )
509 {
510   mStencilParameters.stencilFunctionReference = stencilFunctionReference;
511 }
512
513 int Renderer::GetStencilFunctionReference() const
514 {
515   return mStencilParameters.stencilFunctionReference;
516 }
517
518 void Renderer::SetStencilMask( int stencilMask )
519 {
520   mStencilParameters.stencilMask = stencilMask;
521 }
522
523 int Renderer::GetStencilMask() const
524 {
525   return mStencilParameters.stencilMask;
526 }
527
528 void Renderer::SetStencilOperationOnFail( StencilOperation::Type stencilOperationOnFail )
529 {
530   mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
531 }
532
533 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
534 {
535   return mStencilParameters.stencilOperationOnFail;
536 }
537
538 void Renderer::SetStencilOperationOnZFail( StencilOperation::Type stencilOperationOnZFail )
539 {
540   mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
541 }
542
543 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
544 {
545   return mStencilParameters.stencilOperationOnZFail;
546 }
547
548 void Renderer::SetStencilOperationOnZPass( StencilOperation::Type stencilOperationOnZPass )
549 {
550   mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
551 }
552
553 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
554 {
555   return mStencilParameters.stencilOperationOnZPass;
556 }
557
558 void Renderer::Render( Context& context,
559                        SceneGraph::TextureCache& textureCache,
560                        BufferIndex bufferIndex,
561                        const SceneGraph::NodeDataProvider& node,
562                        SceneGraph::Shader& defaultShader,
563                        const Matrix& modelMatrix,
564                        const Matrix& modelViewMatrix,
565                        const Matrix& viewMatrix,
566                        const Matrix& projectionMatrix,
567                        const Vector3& size,
568                        bool blend )
569 {
570   // Get the program to use:
571   Program* program = mRenderDataProvider->GetShader().GetProgram();
572   if( !program )
573   {
574     // if program is NULL it means this is a custom shader with non matching geometry type so we need to use default shaders program
575     program = defaultShader.GetProgram();
576     DALI_ASSERT_DEBUG( program && "Default shader should always have a program available." );
577     if( !program )
578     {
579       DALI_LOG_ERROR( "Failed to get program for shader at address %p.\n", (void*)&mRenderDataProvider->GetShader() );
580       return;
581     }
582   }
583
584   //Set cull face  mode
585   context.CullFace( mFaceCullingMode );
586
587   //Set blending mode
588   SetBlending( context, blend );
589
590   // Take the program into use so we can send uniforms to it
591   program->Use();
592
593   if( DALI_LIKELY( BindTextures( context, textureCache, *program ) ) )
594   {
595     // Only set up and draw if we have textures and they are all valid
596
597     // set projection and view matrix if program has not yet received them yet this frame
598     SetMatrices( *program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix );
599
600     // set color uniform
601     GLint loc = program->GetUniformLocation( Program::UNIFORM_COLOR );
602     if( Program::UNIFORM_UNKNOWN != loc )
603     {
604       const Vector4& color = node.GetRenderColor( bufferIndex );
605       if( mPremultipledAlphaEnabled )
606       {
607         program->SetUniform4f( loc, color.r*color.a, color.g*color.a, color.b*color.a, color.a );
608       }
609       else
610       {
611         program->SetUniform4f( loc, color.r, color.g, color.b, color.a );
612       }
613     }
614
615     SetUniforms( bufferIndex, node, size, *program );
616
617     if( mUpdateAttributesLocation || mGeometry->AttributesChanged() )
618     {
619       mGeometry->GetAttributeLocationFromProgram( mAttributesLocation, *program, bufferIndex );
620       mUpdateAttributesLocation = false;
621     }
622
623     mGeometry->UploadAndDraw( context, bufferIndex, mAttributesLocation, mIndexedDrawFirstElement, mIndexedDrawElementsCount );
624   }
625 }
626
627 void Renderer::SetSortAttributes( BufferIndex bufferIndex, SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes ) const
628 {
629   sortAttributes.shader = &( mRenderDataProvider->GetShader() );
630   const std::vector<Render::Texture>& textures( mRenderDataProvider->GetTextures() );
631   if( !textures.empty() )
632   {
633     sortAttributes.textureResourceId = textures[0].GetTextureId();
634   }
635   else
636   {
637     sortAttributes.textureResourceId = Integration::InvalidResourceId;
638   }
639
640   sortAttributes.geometry = mGeometry;
641 }
642
643 } // namespace SceneGraph
644
645 } // namespace Internal
646
647 } // namespace Dali