Removal of renderable attachment
[platform/core/uifw/dali-core.git] / dali / internal / render / renderers / render-renderer.cpp
1 /*
2  * Copyright (c) 2015 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
22 // INTERNAL INCLUDES
23 #include <dali/internal/common/image-sampler.h>
24 #include <dali/internal/render/gl-resources/context.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.h>
30 #include <dali/internal/render/gl-resources/texture-cache.h>
31 #include <dali/public-api/actors/blending.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                          SceneGraph::RenderGeometry* renderGeometry )
114 {
115   return new Renderer( dataProvider, renderGeometry);
116 }
117
118 Renderer::Renderer( SceneGraph::RenderDataProvider* dataProvider,
119                     SceneGraph::RenderGeometry* renderGeometry )
120 : mRenderDataProvider( dataProvider ),
121   mContext(NULL),
122   mTextureCache( NULL ),
123   mUniformNameCache( NULL ),
124   mRenderGeometry( renderGeometry ),
125   mUniformIndexMap(),
126   mAttributesLocation(),
127   mSamplerBitfield( ImageSampler::PackBitfield( FilterMode::DEFAULT, FilterMode::DEFAULT ) ),
128   mUpdateAttributesLocation( true ),
129   mCullFaceMode( Dali::Material::NONE  )
130 {
131 }
132
133 void Renderer::Initialize( Context& context, SceneGraph::TextureCache& textureCache, Render::UniformNameCache& uniformNameCache )
134 {
135   mContext = &context;
136   mTextureCache = &textureCache;
137   mUniformNameCache = &uniformNameCache;
138 }
139
140 Renderer::~Renderer()
141 {
142 }
143
144 void Renderer::SetRenderDataProvider( SceneGraph::RenderDataProvider* dataProvider )
145 {
146   mRenderDataProvider = dataProvider;
147   mUpdateAttributesLocation = true;
148 }
149
150 void Renderer::SetGeometry( SceneGraph::RenderGeometry* renderGeometry )
151 {
152   mRenderGeometry = renderGeometry;
153   mUpdateAttributesLocation = true;
154 }
155
156 // Note - this is currently called from UpdateThread, PrepareRenderInstructions,
157 // as an optimisation.
158 // @todo MESH_REWORK Should use Update thread objects only in PrepareRenderInstructions.
159 bool Renderer::RequiresDepthTest() const
160 {
161   return mRenderGeometry->RequiresDepthTest();
162 }
163
164 void Renderer::SetBlending( Context& context, bool blend )
165 {
166   context.SetBlend( blend );
167   if( blend )
168   {
169     const SceneGraph::MaterialDataProvider& material = mRenderDataProvider->GetMaterial();
170
171     // Blend color is optional and rarely used
172     Vector4* blendColor = material.GetBlendColor();
173     if( blendColor )
174     {
175       context.SetCustomBlendColor( *blendColor );
176     }
177     else
178     {
179       context.SetDefaultBlendColor();
180     }
181
182     const BlendingOptions& blending = material.GetBlendingOptions();
183     // Set blend source & destination factors
184     context.BlendFuncSeparate( blending.GetBlendSrcFactorRgb(),
185                                blending.GetBlendDestFactorRgb(),
186                                blending.GetBlendSrcFactorAlpha(),
187                                blending.GetBlendDestFactorAlpha() );
188
189     // Set blend equations
190     context.BlendEquationSeparate( blending.GetBlendEquationRgb(),
191                                    blending.GetBlendEquationAlpha() );
192   }
193 }
194
195 void Renderer::GlContextDestroyed()
196 {
197   mRenderGeometry->GlContextDestroyed();
198 }
199
200 void Renderer::GlCleanup()
201 {
202 }
203
204 void Renderer::SetUniforms( BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, Program& program )
205 {
206   // Check if the map has changed
207   DALI_ASSERT_DEBUG( mRenderDataProvider && "No Uniform map data provider available" );
208
209   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
210
211   if( uniformMapDataProvider.GetUniformMapChanged( bufferIndex ) ||
212       node.GetUniformMapChanged(bufferIndex))
213   {
214     const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap( bufferIndex );
215     const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap( bufferIndex );
216
217     unsigned int maxMaps = uniformMap.Count() + uniformMapNode.Count();
218     mUniformIndexMap.Clear(); // Clear contents, but keep memory if we don't change size
219     mUniformIndexMap.Resize( maxMaps );
220
221     unsigned int mapIndex(0);
222     for(; mapIndex < uniformMap.Count() ; ++mapIndex )
223     {
224       mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex]->propertyPtr;
225       mUniformIndexMap[mapIndex].uniformIndex = program.RegisterUniform( uniformMap[mapIndex]->uniformName );
226     }
227
228     for( unsigned int nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count() ; ++nodeMapIndex )
229     {
230       unsigned int uniformIndex = program.RegisterUniform( uniformMapNode[nodeMapIndex]->uniformName );
231       bool found(false);
232       for( unsigned int i(0); i<uniformMap.Count(); ++i )
233       {
234         if( mUniformIndexMap[i].uniformIndex == uniformIndex )
235         {
236           mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
237           found = true;
238           break;
239         }
240       }
241
242       if( !found )
243       {
244         mUniformIndexMap[mapIndex].propertyValue = uniformMapNode[nodeMapIndex]->propertyPtr;
245         mUniformIndexMap[mapIndex].uniformIndex = uniformIndex;
246         ++mapIndex;
247       }
248     }
249
250     mUniformIndexMap.Resize( mapIndex );
251   }
252
253   // Set uniforms in local map
254   for( UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
255          end = mUniformIndexMap.End() ;
256        iter != end ;
257        ++iter )
258   {
259     SetUniformFromProperty( bufferIndex, program, *iter );
260   }
261
262   GLint sizeLoc = program.GetUniformLocation( Program::UNIFORM_SIZE );
263   if( -1 != sizeLoc )
264   {
265     Vector3 size = node.GetRenderSize( bufferIndex );
266     program.SetSizeUniform3f( sizeLoc, size.x, size.y, size.z );
267   }
268 }
269
270 void Renderer::SetUniformFromProperty( BufferIndex bufferIndex, Program& program, UniformIndexMap& map )
271 {
272   GLint location = program.GetUniformLocation(map.uniformIndex);
273   if( Program::UNIFORM_UNKNOWN != location )
274   {
275     // switch based on property type to use correct GL uniform setter
276     switch ( map.propertyValue->GetType() )
277     {
278       case Property::INTEGER:
279       {
280         program.SetUniform1i( location, map.propertyValue->GetInteger( bufferIndex ) );
281         break;
282       }
283       case Property::FLOAT:
284       {
285         program.SetUniform1f( location, map.propertyValue->GetFloat( bufferIndex ) );
286         break;
287       }
288       case Property::VECTOR2:
289       {
290         Vector2 value( map.propertyValue->GetVector2( bufferIndex ) );
291         program.SetUniform2f( location, value.x, value.y );
292         break;
293       }
294
295       case Property::VECTOR3:
296       {
297         Vector3 value( map.propertyValue->GetVector3( bufferIndex ) );
298         program.SetUniform3f( location, value.x, value.y, value.z );
299         break;
300       }
301
302       case Property::VECTOR4:
303       {
304         Vector4 value( map.propertyValue->GetVector4( bufferIndex ) );
305         program.SetUniform4f( location, value.x, value.y, value.z, value.w );
306         break;
307       }
308
309       case Property::ROTATION:
310       {
311         Quaternion value( map.propertyValue->GetQuaternion( bufferIndex ) );
312         program.SetUniform4f( location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w );
313         break;
314       }
315
316       case Property::MATRIX:
317       {
318         const Matrix& value = map.propertyValue->GetMatrix(bufferIndex);
319         program.SetUniformMatrix4fv(location, 1, value.AsFloat() );
320         break;
321       }
322
323       case Property::MATRIX3:
324       {
325         const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex);
326         program.SetUniformMatrix3fv(location, 1, value.AsFloat() );
327         break;
328       }
329
330       default:
331       {
332         // Other property types are ignored
333         break;
334       }
335     }
336   }
337 }
338
339 void Renderer::BindTextures( SceneGraph::TextureCache& textureCache, Program& program )
340 {
341   int textureUnit = 0;
342
343   std::vector<Render::Texture>& textures( mRenderDataProvider->GetTextures() );
344   for( size_t i(0); i<textures.size(); ++i )
345   {
346     ResourceId textureId = textures[i].GetTextureId();
347     Internal::Texture* texture = textureCache.GetTexture( textureId );
348     if( texture )
349     {
350       textureCache.BindTexture( texture, textureId, GL_TEXTURE_2D, (TextureUnit)textureUnit );
351
352       Render::Texture& textureMapping = textures[i];
353       // Set sampler uniform location for the texture
354       int32_t uniqueIndex = textureMapping.GetUniformUniqueIndex();
355       if( Render::Texture::NOT_INITIALIZED == uniqueIndex )
356       {
357         uniqueIndex = mUniformNameCache->GetSamplerUniformUniqueIndex( textureMapping.GetUniformName() );
358         textureMapping.SetUniformUniqueIndex( uniqueIndex );
359       }
360       GLint uniformLocation = program.GetSamplerUniformLocation( uniqueIndex, textureMapping.GetUniformName() );
361       if( Program::UNIFORM_UNKNOWN != uniformLocation )
362       {
363         program.SetUniform1i( uniformLocation, textureUnit );
364       }
365
366       unsigned int samplerBitfield(0);
367       const Render::Sampler* sampler( textureMapping.GetSampler() );
368       if( sampler )
369       {
370         samplerBitfield = ImageSampler::PackBitfield(
371           static_cast< FilterMode::Type >(sampler->GetMinifyFilterMode()),
372           static_cast< FilterMode::Type >(sampler->GetMagnifyFilterMode()),
373           static_cast< WrapMode::Type >(sampler->GetUWrapMode()),
374           static_cast< WrapMode::Type >(sampler->GetVWrapMode())
375           );
376       }
377       else
378       {
379         samplerBitfield = ImageSampler::DEFAULT_BITFIELD;
380       }
381
382       texture->ApplySampler( (TextureUnit)textureUnit, samplerBitfield );
383
384       ++textureUnit;
385     }
386   }
387 }
388
389 void Renderer::SetCullFace( Dali::Material::FaceCullingMode mode )
390 {
391   DALI_ASSERT_DEBUG( mode >= Dali::Material::NONE && mode <= Dali::Material::CULL_BACK_AND_FRONT );
392   mCullFaceMode = mode;
393 }
394
395 void Renderer::SetSampler( unsigned int samplerBitfield )
396 {
397   mSamplerBitfield = samplerBitfield;
398 }
399
400 void Renderer::Render( Context& context,
401                        SceneGraph::TextureCache& textureCache,
402                        BufferIndex bufferIndex,
403                        const SceneGraph::NodeDataProvider& node,
404                        SceneGraph::Shader& defaultShader,
405                        const Matrix& modelViewMatrix,
406                        const Matrix& viewMatrix,
407                        const Matrix& projectionMatrix,
408                        bool cull,
409                        bool blend )
410 {
411   // Get the program to use:
412   Program* program = mRenderDataProvider->GetShader().GetProgram();
413   if( !program )
414   {
415     // if program is NULL it means this is a custom shader with non matching geometry type so we need to use default shaders program
416     program = defaultShader.GetProgram();
417     DALI_ASSERT_DEBUG( program && "Default shader should always have a program available." );
418     if( !program )
419     {
420       DALI_LOG_ERROR( "Failed to get program for shader at address %p.", (void*)&mRenderDataProvider->GetShader() );
421       return;
422     }
423   }
424
425   //Set cull face  mode
426   context.CullFace( mRenderDataProvider->GetMaterial().GetFaceCullingMode() );
427
428   //Set blending mode
429   SetBlending( context, blend );
430
431   // Take the program into use so we can send uniforms to it
432   program->Use();
433
434   // set projection and view matrix if program has not yet received them yet this frame
435   SetMatrices( *program, node.GetModelMatrix( bufferIndex ), viewMatrix, projectionMatrix, modelViewMatrix );
436
437   // set color uniform
438   GLint loc = program->GetUniformLocation( Program::UNIFORM_COLOR );
439   if( Program::UNIFORM_UNKNOWN != loc )
440   {
441     const Vector4& color = node.GetRenderColor( bufferIndex );
442     program->SetUniform4f( loc, color.r, color.g, color.b, color.a );
443   }
444
445   //Bind textures
446   BindTextures( textureCache, *program );
447
448   //Set uniforms
449   SetUniforms( bufferIndex, node, *program );
450
451   if( mUpdateAttributesLocation || mRenderGeometry->AttributesChanged() )
452   {
453     mRenderGeometry->GetAttributeLocationFromProgram( mAttributesLocation, *program, bufferIndex );
454     mUpdateAttributesLocation = false;
455   }
456
457   mRenderGeometry->UploadAndDraw( context, bufferIndex, mAttributesLocation );
458 }
459
460 void Renderer::SetSortAttributes( BufferIndex bufferIndex, SceneGraph::RendererWithSortAttributes& sortAttributes ) const
461 {
462   sortAttributes.shader = &( mRenderDataProvider->GetShader() );
463   const std::vector<Render::Texture>& textures( mRenderDataProvider->GetTextures() );
464   if( !textures.empty() )
465   {
466     sortAttributes.textureResourceId = textures[0].GetTextureId();
467   }
468   else
469   {
470     sortAttributes.textureResourceId = Integration::InvalidResourceId;
471   }
472
473   sortAttributes.geometry = mRenderGeometry;
474 }
475
476 } // namespace SceneGraph
477
478 } // namespace Internal
479
480 } // namespace Dali