Allow new texture to be created from native images
[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/renderers/render-sampler.h>
26 #include <dali/internal/render/shaders/scene-graph-shader.h>
27 #include <dali/internal/render/shaders/program.h>
28 #include <dali/internal/render/data-providers/node-data-provider.h>
29 #include <dali/internal/render/data-providers/uniform-name-cache.h>
30 #include <dali/internal/render/gl-resources/texture-cache.h>
31 #include <dali/public-api/actors/blending.h>
32 #include <dali/internal/render/gl-resources/gl-texture.h>
33
34 namespace Dali
35 {
36
37 namespace Internal
38 {
39
40 namespace
41 {
42
43 static Matrix gModelViewProjectionMatrix( false ); ///< a shared matrix to calculate the MVP matrix, dont want to store it in object to reduce storage overhead
44 static Matrix3 gNormalMatrix; ///< a shared matrix to calculate normal matrix, dont want to store it in object to reduce storage overhead
45
46 /**
47  * Helper to set view and projection matrices once per program
48  * @param program to set the matrices to
49  * @param modelMatrix to set
50  * @param viewMatrix to set
51  * @param projectionMatrix to set
52  * @param modelViewMatrix to set
53  * @param modelViewProjectionMatrix to set
54  */
55 inline void SetMatrices( Program& program,
56                          const Matrix& modelMatrix,
57                          const Matrix& viewMatrix,
58                          const Matrix& projectionMatrix,
59                          const Matrix& modelViewMatrix )
60 {
61   GLint loc = program.GetUniformLocation( Program::UNIFORM_MODEL_MATRIX );
62   if( Program::UNIFORM_UNKNOWN != loc )
63   {
64     program.SetUniformMatrix4fv( loc, 1, modelMatrix.AsFloat() );
65   }
66   loc = program.GetUniformLocation( Program::UNIFORM_VIEW_MATRIX );
67   if( Program::UNIFORM_UNKNOWN != loc )
68   {
69     if( program.GetViewMatrix() != &viewMatrix )
70     {
71       program.SetViewMatrix( &viewMatrix );
72       program.SetUniformMatrix4fv( loc, 1, viewMatrix.AsFloat() );
73     }
74   }
75   // set projection matrix if program has not yet received it this frame or if it is dirty
76   loc = program.GetUniformLocation( Program::UNIFORM_PROJECTION_MATRIX );
77   if( Program::UNIFORM_UNKNOWN != loc )
78   {
79     if( program.GetProjectionMatrix() != &projectionMatrix )
80     {
81       program.SetProjectionMatrix( &projectionMatrix );
82       program.SetUniformMatrix4fv( loc, 1, projectionMatrix.AsFloat() );
83     }
84   }
85   loc = program.GetUniformLocation(Program::UNIFORM_MODELVIEW_MATRIX);
86   if( Program::UNIFORM_UNKNOWN != loc )
87   {
88     program.SetUniformMatrix4fv( loc, 1, modelViewMatrix.AsFloat() );
89   }
90
91   loc = program.GetUniformLocation( Program::UNIFORM_MVP_MATRIX );
92   if( Program::UNIFORM_UNKNOWN != loc )
93   {
94     Matrix::Multiply( gModelViewProjectionMatrix, modelViewMatrix, projectionMatrix );
95     program.SetUniformMatrix4fv( loc, 1, gModelViewProjectionMatrix.AsFloat() );
96   }
97
98   loc = program.GetUniformLocation( Program::UNIFORM_NORMAL_MATRIX );
99   if( Program::UNIFORM_UNKNOWN != loc )
100   {
101     gNormalMatrix = modelViewMatrix;
102     gNormalMatrix.Invert();
103     gNormalMatrix.Transpose();
104     program.SetUniformMatrix3fv( loc, 1, gNormalMatrix.AsFloat() );
105   }
106 }
107
108 }
109
110 namespace Render
111 {
112
113 Renderer* Renderer::New( SceneGraph::RenderDataProvider* dataProvider,
114                          Render::Geometry* geometry,
115                          unsigned int blendingBitmask,
116                          const Vector4* blendColor,
117                          FaceCullingMode::Type faceCullingMode,
118                          bool preMultipliedAlphaEnabled,
119                          DepthWriteMode::Type depthWriteMode,
120                          DepthTestMode::Type depthTestMode,
121                          DepthFunction::Type depthFunction )
122 {
123   return new Renderer( dataProvider, geometry, blendingBitmask, blendColor, faceCullingMode, preMultipliedAlphaEnabled, depthWriteMode, depthTestMode, depthFunction );
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 : mRenderDataProvider( dataProvider ),
136   mContext(NULL),
137   mTextureCache( NULL ),
138   mUniformNameCache( NULL ),
139   mGeometry( geometry ),
140   mUniformIndexMap(),
141   mAttributesLocation(),
142   mBlendingOptions(),
143   mFaceCullingMode( faceCullingMode ),
144   mDepthFunction( depthFunction ),
145   mIndexedDrawFirstElement( 0 ),
146   mIndexedDrawElementsCount( 0 ),
147   mDepthWriteMode( depthWriteMode ),
148   mDepthTestMode( depthTestMode ),
149   mUpdateAttributesLocation( true ),
150   mPremultipledAlphaEnabled( preMultipliedAlphaEnabled )
151 {
152   if(  blendingBitmask != 0u )
153   {
154     mBlendingOptions.SetBitmask( blendingBitmask );
155   }
156
157   if( blendColor )
158   {
159     mBlendingOptions.SetBlendColor( *blendColor );
160   }
161 }
162
163 void Renderer::Initialize( Context& context, SceneGraph::TextureCache& textureCache, Render::UniformNameCache& uniformNameCache )
164 {
165   mContext = &context;
166   mTextureCache = &textureCache;
167   mUniformNameCache = &uniformNameCache;
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 = program.GetSamplerUniformLocation( i, uniformLocation ) &&
373                textureCache.BindTexture( texture, textureId, GL_TEXTURE_2D, (TextureUnit)textureUnit );
374
375       if( result && Program::UNIFORM_UNKNOWN != uniformLocation )
376       {
377         program.SetUniform1i( uniformLocation, textureUnit );
378
379         unsigned int samplerBitfield(ImageSampler::DEFAULT_BITFIELD);
380         const Render::Sampler* sampler(  samplers[i] );
381         if( sampler )
382         {
383           samplerBitfield = sampler->mBitfield;
384         }
385
386         texture->ApplySampler( (TextureUnit)textureUnit, samplerBitfield );
387
388         ++textureUnit;
389       }
390     }
391   }
392
393   std::vector<Render::NewTexture*>& newTextures( mRenderDataProvider->GetNewTextures() );
394   for( size_t i(0); result && i<newTextures.size(); ++i )
395   {
396     if( newTextures[i] )
397     {
398       result = program.GetSamplerUniformLocation( i, uniformLocation ) &&
399                newTextures[i]->Bind(context, textureUnit, samplers[i] );
400
401       if( result )
402       {
403         program.SetUniform1i( uniformLocation, textureUnit );
404         ++textureUnit;
405       }
406     }
407   }
408
409   return result;
410 }
411
412 void Renderer::SetFaceCullingMode( FaceCullingMode::Type mode )
413 {
414   mFaceCullingMode =  mode;
415 }
416
417 void Renderer::SetBlendingBitMask( unsigned int bitmask )
418 {
419   mBlendingOptions.SetBitmask( bitmask );
420 }
421
422 void Renderer::SetBlendColor( const Vector4* color )
423 {
424   mBlendingOptions.SetBlendColor( *color );
425 }
426
427 void Renderer::SetIndexedDrawFirstElement( size_t firstElement )
428 {
429   mIndexedDrawFirstElement = firstElement;
430 }
431
432 void Renderer::SetIndexedDrawElementsCount( size_t elementsCount )
433 {
434   mIndexedDrawElementsCount = elementsCount;
435 }
436
437 void Renderer::EnablePreMultipliedAlpha( bool enable )
438 {
439   mPremultipledAlphaEnabled = enable;
440 }
441
442 void Renderer::SetDepthWriteMode( DepthWriteMode::Type depthWriteMode )
443 {
444   mDepthWriteMode = depthWriteMode;
445 }
446
447 void Renderer::SetDepthTestMode( DepthTestMode::Type depthTestMode )
448 {
449   mDepthTestMode = depthTestMode;
450 }
451
452 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
453 {
454   return mDepthWriteMode;
455 }
456
457 DepthTestMode::Type Renderer::GetDepthTestMode() const
458 {
459   return mDepthTestMode;
460 }
461
462 void Renderer::SetDepthFunction( DepthFunction::Type depthFunction )
463 {
464   mDepthFunction = depthFunction;
465 }
466
467 DepthFunction::Type Renderer::GetDepthFunction() const
468 {
469   return mDepthFunction;
470 }
471
472 void Renderer::Render( Context& context,
473                        SceneGraph::TextureCache& textureCache,
474                        BufferIndex bufferIndex,
475                        const SceneGraph::NodeDataProvider& node,
476                        SceneGraph::Shader& defaultShader,
477                        const Matrix& modelMatrix,
478                        const Matrix& modelViewMatrix,
479                        const Matrix& viewMatrix,
480                        const Matrix& projectionMatrix,
481                        const Vector3& size,
482                        bool blend )
483 {
484   // Get the program to use:
485   Program* program = mRenderDataProvider->GetShader().GetProgram();
486   if( !program )
487   {
488     // if program is NULL it means this is a custom shader with non matching geometry type so we need to use default shaders program
489     program = defaultShader.GetProgram();
490     DALI_ASSERT_DEBUG( program && "Default shader should always have a program available." );
491     if( !program )
492     {
493       DALI_LOG_ERROR( "Failed to get program for shader at address %p.", (void*)&mRenderDataProvider->GetShader() );
494       return;
495     }
496   }
497
498   //Set cull face  mode
499   context.CullFace( mFaceCullingMode );
500
501   //Set blending mode
502   SetBlending( context, blend );
503
504   // Take the program into use so we can send uniforms to it
505   program->Use();
506
507   if( DALI_LIKELY( BindTextures( context, textureCache, *program ) ) )
508   {
509     // Only set up and draw if we have textures and they are all valid
510
511     // set projection and view matrix if program has not yet received them yet this frame
512     SetMatrices( *program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix );
513
514     // set color uniform
515     GLint loc = program->GetUniformLocation( Program::UNIFORM_COLOR );
516     if( Program::UNIFORM_UNKNOWN != loc )
517     {
518       const Vector4& color = node.GetRenderColor( bufferIndex );
519       if( mPremultipledAlphaEnabled )
520       {
521         program->SetUniform4f( loc, color.r*color.a, color.g*color.a, color.b*color.a, color.a );
522       }
523       else
524       {
525         program->SetUniform4f( loc, color.r, color.g, color.b, color.a );
526       }
527     }
528
529     SetUniforms( bufferIndex, node, size, *program );
530
531     if( mUpdateAttributesLocation || mGeometry->AttributesChanged() )
532     {
533       mGeometry->GetAttributeLocationFromProgram( mAttributesLocation, *program, bufferIndex );
534       mUpdateAttributesLocation = false;
535     }
536
537     mGeometry->UploadAndDraw( context, bufferIndex, mAttributesLocation, mIndexedDrawFirstElement, mIndexedDrawElementsCount );
538   }
539 }
540
541 void Renderer::SetSortAttributes( BufferIndex bufferIndex, SceneGraph::RendererWithSortAttributes& sortAttributes ) const
542 {
543   sortAttributes.shader = &( mRenderDataProvider->GetShader() );
544   const std::vector<Render::Texture>& textures( mRenderDataProvider->GetTextures() );
545   if( !textures.empty() )
546   {
547     sortAttributes.textureResourceId = textures[0].GetTextureId();
548   }
549   else
550   {
551     sortAttributes.textureResourceId = Integration::InvalidResourceId;
552   }
553
554   sortAttributes.geometry = mGeometry;
555 }
556
557 } // namespace SceneGraph
558
559 } // namespace Internal
560
561 } // namespace Dali