Merge branch 'devel/master' 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/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); i<newTextures.size() && result; ++i )
402   {
403     if( newTextures[i] )
404     {
405       result = newTextures[i]->Bind(context, textureUnit, samplers[i] );
406       if( result && program.GetSamplerUniformLocation( i, uniformLocation ) )
407       {
408         program.SetUniform1i( uniformLocation, textureUnit );
409         ++textureUnit;
410       }
411     }
412   }
413
414   return result;
415 }
416
417 void Renderer::SetFaceCullingMode( FaceCullingMode::Type mode )
418 {
419   mFaceCullingMode =  mode;
420 }
421
422 void Renderer::SetBlendingBitMask( unsigned int bitmask )
423 {
424   mBlendingOptions.SetBitmask( bitmask );
425 }
426
427 void Renderer::SetBlendColor( const Vector4* color )
428 {
429   mBlendingOptions.SetBlendColor( *color );
430 }
431
432 void Renderer::SetIndexedDrawFirstElement( size_t firstElement )
433 {
434   mIndexedDrawFirstElement = firstElement;
435 }
436
437 void Renderer::SetIndexedDrawElementsCount( size_t elementsCount )
438 {
439   mIndexedDrawElementsCount = elementsCount;
440 }
441
442 void Renderer::EnablePreMultipliedAlpha( bool enable )
443 {
444   mPremultipledAlphaEnabled = enable;
445 }
446
447 void Renderer::SetDepthWriteMode( DepthWriteMode::Type depthWriteMode )
448 {
449   mDepthWriteMode = depthWriteMode;
450 }
451
452 void Renderer::SetDepthTestMode( DepthTestMode::Type depthTestMode )
453 {
454   mDepthTestMode = depthTestMode;
455 }
456
457 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
458 {
459   return mDepthWriteMode;
460 }
461
462 DepthTestMode::Type Renderer::GetDepthTestMode() const
463 {
464   return mDepthTestMode;
465 }
466
467 void Renderer::SetDepthFunction( DepthFunction::Type depthFunction )
468 {
469   mDepthFunction = depthFunction;
470 }
471
472 DepthFunction::Type Renderer::GetDepthFunction() const
473 {
474   return mDepthFunction;
475 }
476
477 void Renderer::SetRenderMode( RenderMode::Type renderMode )
478 {
479   mStencilParameters.renderMode = renderMode;
480 }
481
482 RenderMode::Type Renderer::GetRenderMode() const
483 {
484   return mStencilParameters.renderMode;
485 }
486
487 void Renderer::SetStencilFunction( StencilFunction::Type stencilFunction )
488 {
489   mStencilParameters.stencilFunction = stencilFunction;
490 }
491
492 StencilFunction::Type Renderer::GetStencilFunction() const
493 {
494   return mStencilParameters.stencilFunction;
495 }
496
497 void Renderer::SetStencilFunctionMask( int stencilFunctionMask )
498 {
499   mStencilParameters.stencilFunctionMask = stencilFunctionMask;
500 }
501
502 int Renderer::GetStencilFunctionMask() const
503 {
504   return mStencilParameters.stencilFunctionMask;
505 }
506
507 void Renderer::SetStencilFunctionReference( int stencilFunctionReference )
508 {
509   mStencilParameters.stencilFunctionReference = stencilFunctionReference;
510 }
511
512 int Renderer::GetStencilFunctionReference() const
513 {
514   return mStencilParameters.stencilFunctionReference;
515 }
516
517 void Renderer::SetStencilMask( int stencilMask )
518 {
519   mStencilParameters.stencilMask = stencilMask;
520 }
521
522 int Renderer::GetStencilMask() const
523 {
524   return mStencilParameters.stencilMask;
525 }
526
527 void Renderer::SetStencilOperationOnFail( StencilOperation::Type stencilOperationOnFail )
528 {
529   mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
530 }
531
532 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
533 {
534   return mStencilParameters.stencilOperationOnFail;
535 }
536
537 void Renderer::SetStencilOperationOnZFail( StencilOperation::Type stencilOperationOnZFail )
538 {
539   mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
540 }
541
542 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
543 {
544   return mStencilParameters.stencilOperationOnZFail;
545 }
546
547 void Renderer::SetStencilOperationOnZPass( StencilOperation::Type stencilOperationOnZPass )
548 {
549   mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
550 }
551
552 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
553 {
554   return mStencilParameters.stencilOperationOnZPass;
555 }
556
557 void Renderer::SetBatchingEnabled( bool batchingEnabled )
558 {
559   mBatchingEnabled = batchingEnabled;
560 }
561
562 void Renderer::Render( Context& context,
563                        SceneGraph::TextureCache& textureCache,
564                        BufferIndex bufferIndex,
565                        const SceneGraph::NodeDataProvider& node,
566                        SceneGraph::Shader& defaultShader,
567                        const Matrix& modelMatrix,
568                        const Matrix& modelViewMatrix,
569                        const Matrix& viewMatrix,
570                        const Matrix& projectionMatrix,
571                        const Vector3& size,
572                        Render::Geometry* externalGeometry,
573                        bool blend )
574 {
575   // Get the program to use:
576   Program* program = mRenderDataProvider->GetShader().GetProgram();
577   if( !program )
578   {
579     // if program is NULL it means this is a custom shader with non matching geometry type so we need to use default shaders program
580     program = defaultShader.GetProgram();
581     DALI_ASSERT_DEBUG( program && "Default shader should always have a program available." );
582     if( !program )
583     {
584       DALI_LOG_ERROR( "Failed to get program for shader at address %p.\n", (void*)&mRenderDataProvider->GetShader() );
585       return;
586     }
587   }
588
589   //Set cull face  mode
590   context.CullFace( mFaceCullingMode );
591
592   //Set blending mode
593   SetBlending( context, blend );
594
595   // Take the program into use so we can send uniforms to it
596   program->Use();
597
598   if( DALI_LIKELY( BindTextures( context, textureCache, *program ) ) )
599   {
600     // Only set up and draw if we have textures and they are all valid
601
602     // set projection and view matrix if program has not yet received them yet this frame
603     SetMatrices( *program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix );
604
605     // set color uniform
606     GLint loc = program->GetUniformLocation( Program::UNIFORM_COLOR );
607     if( Program::UNIFORM_UNKNOWN != loc )
608     {
609       const Vector4& color = node.GetRenderColor( bufferIndex );
610       if( mPremultipledAlphaEnabled )
611       {
612         program->SetUniform4f( loc, color.r*color.a, color.g*color.a, color.b*color.a, color.a );
613       }
614       else
615       {
616         program->SetUniform4f( loc, color.r, color.g, color.b, color.a );
617       }
618     }
619
620     SetUniforms( bufferIndex, node, size, *program );
621     Render::Geometry* geometry = externalGeometry ? externalGeometry : mGeometry;
622
623     if( mUpdateAttributesLocation || geometry->AttributesChanged() )
624     {
625       geometry->GetAttributeLocationFromProgram( mAttributesLocation, *program, bufferIndex );
626       mUpdateAttributesLocation = false;
627     }
628
629     geometry->UploadAndDraw( context, bufferIndex, mAttributesLocation, mIndexedDrawFirstElement, mIndexedDrawElementsCount );
630   }
631 }
632
633 void Renderer::SetSortAttributes( BufferIndex bufferIndex, SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes ) const
634 {
635   sortAttributes.shader = &( mRenderDataProvider->GetShader() );
636   const std::vector<Render::Texture>& textures( mRenderDataProvider->GetTextures() );
637   if( !textures.empty() )
638   {
639     sortAttributes.textureResourceId = textures[0].GetTextureId();
640   }
641   else
642   {
643     sortAttributes.textureResourceId = Integration::InvalidResourceId;
644   }
645
646   sortAttributes.geometry = mGeometry;
647 }
648
649 } // namespace SceneGraph
650
651 } // namespace Internal
652
653 } // namespace Dali