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