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