Added Blending handling for materials and renderers
[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 #include "render-renderer.h"
18
19 #include <dali/internal/common/image-sampler.h>
20 #include <dali/internal/event/common/property-input-impl.h>
21 #include <dali/internal/update/common/uniform-map.h>
22 #include <dali/internal/render/data-providers/render-data-provider.h>
23 #include <dali/internal/render/gl-resources/texture.h>
24 #include <dali/internal/render/gl-resources/texture-cache.h>
25 #include <dali/internal/render/shaders/program.h>
26
27 namespace Dali
28 {
29 namespace Internal
30 {
31 namespace SceneGraph
32 {
33
34 NewRenderer* NewRenderer::New( NodeDataProvider& nodeDataProvider,
35                                RenderDataProvider* dataProvider )
36 {
37   return new NewRenderer(nodeDataProvider, dataProvider);
38 }
39
40
41 NewRenderer::NewRenderer( NodeDataProvider& nodeDataProvider,
42                           RenderDataProvider* dataProvider )
43 : Renderer( nodeDataProvider ),
44   mRenderDataProvider( dataProvider )
45 {
46 }
47
48 NewRenderer::~NewRenderer()
49 {
50 }
51
52 void NewRenderer::SetRenderDataProvider( RenderDataProvider* dataProvider )
53 {
54   mRenderDataProvider = dataProvider;
55   mRenderGeometry.GeometryUpdated();
56 }
57
58 // Note - this is currently called from UpdateThread, PrepareRenderInstructions,
59 // as an optimisation.
60 // @todo MESH_REWORK Should use Update thread objects only in PrepareRenderInstructions.
61 bool NewRenderer::RequiresDepthTest() const
62 {
63   return true;
64 }
65
66 bool NewRenderer::CheckResources()
67 {
68   // Query material to check it has texture pointers & image has size
69   // Query geometry to check it has vertex buffers
70
71   // General point though - why would we have a render item in RenderThread with no ready
72   // resources in UpdateThread?
73   return true;
74 }
75
76 void NewRenderer::ResolveGeometryTypes( BufferIndex bufferIndex, GeometryType& outType, ShaderSubTypes& outSubType )
77 {
78   // @todo MESH_REWORK Remove after merge
79
80   // Do nothing
81 }
82
83 bool NewRenderer::IsOutsideClipSpace( Context& context, const Matrix& modelMatrix, const Matrix& modelViewProjectionMatrix )
84 {
85   // @todo MESH_REWORK Add clipping
86   return false;
87 }
88
89 void NewRenderer::DoSetUniforms( Context& context, BufferIndex bufferIndex, Shader* shader, Program* program, unsigned int programIndex, ShaderSubTypes subType )
90 {
91   // Do nothing, we're going to set up the uniforms with our own code instead
92 }
93
94 void NewRenderer::DoSetCullFaceMode( Context& context, BufferIndex bufferIndex )
95 {
96 }
97
98 void NewRenderer::DoSetBlending( Context& context, BufferIndex bufferIndex )
99 {
100   context.SetBlend(mUseBlend); // @todo MESH_REWORK Should use a RendererDataProvider
101
102   if( mUseBlend )
103   {
104     const MaterialDataProvider& material = mRenderDataProvider->GetMaterial();
105
106     context.SetCustomBlendColor( material.GetBlendColor( bufferIndex ) );
107
108     // Set blend source & destination factors
109     context.BlendFuncSeparate( material.GetBlendSrcFactorRgb( bufferIndex ),
110                                material.GetBlendDestFactorRgb( bufferIndex ),
111                                material.GetBlendSrcFactorAlpha( bufferIndex ),
112                                material.GetBlendDestFactorAlpha( bufferIndex ) );
113
114     // Set blend equations
115     context.BlendEquationSeparate( material.GetBlendEquationRgb( bufferIndex ),
116                                    material.GetBlendEquationAlpha( bufferIndex ) );
117   }
118 }
119
120 void NewRenderer::DoRender( Context& context, TextureCache& textureCache, BufferIndex bufferIndex, Program& program, const Matrix& modelViewMatrix, const Matrix& viewMatrix )
121 {
122   BindTextures( textureCache, bufferIndex, program, mRenderDataProvider->GetSamplers() );
123
124   SetUniforms( bufferIndex, program );
125
126   mRenderGeometry.UploadAndDraw( context, program, bufferIndex, mRenderDataProvider.Get() );
127 }
128
129 void NewRenderer::GlContextDestroyed()
130 {
131   mRenderGeometry.GlContextDestroyed();
132 }
133
134 void NewRenderer::GlCleanup()
135 {
136 }
137
138 void NewRenderer::SetUniforms( BufferIndex bufferIndex, Program& program )
139 {
140   // Check if the map has changed
141   DALI_ASSERT_DEBUG( mRenderDataProvider && "No Uniform map data provider available" );
142
143   const UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
144
145   if( uniformMapDataProvider.GetUniformMapChanged( bufferIndex ) )
146   {
147     const CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap( bufferIndex );
148
149     unsigned int numberOfMaps = uniformMap.Count();
150     mUniformIndexMap.Clear(); // Clear contents, but keep memory if we don't change size
151     mUniformIndexMap.Resize( numberOfMaps );
152
153     // Remap uniform indexes to property value addresses
154     for( unsigned int mapIndex = 0 ; mapIndex < numberOfMaps ; ++mapIndex )
155     {
156       mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex]->propertyPtr;
157       mUniformIndexMap[mapIndex].uniformIndex = program.RegisterUniform( uniformMap[mapIndex]->uniformName );
158     }
159   }
160
161   // Set uniforms in local map
162   for( UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
163          end = mUniformIndexMap.End() ;
164        iter != end ;
165        ++iter )
166   {
167     SetUniformFromProperty( bufferIndex, program, *iter );
168   }
169
170   // @todo MESH_REWORK On merge, copy code from renderer to setup standard matrices and color
171
172   GLint sizeLoc = program.GetUniformLocation( Program::UNIFORM_SIZE );
173   if( -1 != sizeLoc )
174   {
175     Vector3 size = mDataProvider.GetRenderSize( bufferIndex );
176     program.SetUniform3f( sizeLoc, size.x, size.y, size.z );
177   }
178 }
179
180 void NewRenderer::SetUniformFromProperty( BufferIndex bufferIndex, Program& program, UniformIndexMap& map )
181 {
182   GLint location = program.GetUniformLocation(map.uniformIndex);
183   if( Program::UNIFORM_UNKNOWN != location )
184   {
185     // switch based on property type to use correct GL uniform setter
186     switch ( map.propertyValue->GetType() )
187     {
188       case Property::INTEGER:
189       {
190         program.SetUniform1i( location, map.propertyValue->GetInteger( bufferIndex ) );
191         break;
192       }
193       case Property::FLOAT:
194       {
195         program.SetUniform1f( location, map.propertyValue->GetFloat( bufferIndex ) );
196         break;
197       }
198       case Property::VECTOR2:
199       {
200         Vector2 value( map.propertyValue->GetVector2( bufferIndex ) );
201         program.SetUniform2f( location, value.x, value.y );
202         break;
203       }
204
205       case Property::VECTOR3:
206       {
207         Vector3 value( map.propertyValue->GetVector3( bufferIndex ) );
208         program.SetUniform3f( location, value.x, value.y, value.z );
209         break;
210       }
211
212       case Property::VECTOR4:
213       {
214         Vector4 value( map.propertyValue->GetVector4( bufferIndex ) );
215         program.SetUniform4f( location, value.x, value.y, value.z, value.w );
216         break;
217       }
218
219       case Property::ROTATION:
220       {
221         Quaternion value( map.propertyValue->GetQuaternion( bufferIndex ) );
222         program.SetUniform4f( location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w );
223         break;
224       }
225
226       case Property::MATRIX:
227       {
228         const Matrix& value = map.propertyValue->GetMatrix(bufferIndex);
229         program.SetUniformMatrix4fv(location, 1, value.AsFloat() );
230         break;
231       }
232
233       case Property::MATRIX3:
234       {
235         const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex);
236         program.SetUniformMatrix3fv(location, 1, value.AsFloat() );
237         break;
238       }
239
240       default:
241       {
242         // Other property types are ignored
243         break;
244       }
245     }
246   }
247 }
248
249 void NewRenderer::BindTextures(
250   TextureCache& textureCache,
251   BufferIndex bufferIndex,
252   Program& program,
253   const RenderDataProvider::Samplers& samplers )
254 {
255   // @todo MESH_REWORK Write a cache of texture units to commonly used sampler textures
256   unsigned int textureUnit = 0;
257
258   for( RenderDataProvider::Samplers::Iterator iter = samplers.Begin();
259        iter != samplers.End();
260        ++iter )
261   {
262     const SamplerDataProvider* sampler = *iter;
263     ResourceId textureId = sampler->GetTextureId(bufferIndex);
264     Texture* texture = textureCache.GetTexture( textureId );
265     if( texture != NULL )
266     {
267       unsigned int textureUnitUniformIndex = GetTextureUnitUniformIndex( program, *sampler );
268       TextureUnit theTextureUnit = static_cast<TextureUnit>(textureUnit);
269       BindTexture( textureCache, program, textureId, texture, theTextureUnit, textureUnitUniformIndex );
270       ApplySampler( bufferIndex, texture, theTextureUnit, *sampler );
271     }
272
273     ++textureUnit;
274   }
275 }
276
277 void NewRenderer::BindTexture(
278   TextureCache& textureCache,
279   Program& program,
280   ResourceId id,
281   Texture* texture,
282   TextureUnit textureUnit,
283   unsigned int textureUnitUniformIndex )
284 {
285   if( texture != NULL )
286   {
287     textureCache.BindTexture( texture, id, GL_TEXTURE_2D, textureUnit );
288
289     // Set sampler uniform location for the texture
290     GLint textureUnitLoc = program.GetUniformLocation( textureUnitUniformIndex );
291     if( Program::UNIFORM_UNKNOWN != textureUnitLoc )
292     {
293       program.SetUniform1i( textureUnitLoc, textureUnit );
294     }
295   }
296 }
297
298 void NewRenderer::ApplySampler(
299   BufferIndex bufferIndex,
300   Texture*    texture,
301   TextureUnit textureUnit,
302   const SamplerDataProvider& sampler )
303 {
304   unsigned int samplerBitfield = ImageSampler::PackBitfield(
305     static_cast< FilterMode::Type >(sampler.GetMinifyFilterMode(bufferIndex)),
306     static_cast< FilterMode::Type >(sampler.GetMagnifyFilterMode(bufferIndex)) );
307
308   texture->ApplySampler( textureUnit, samplerBitfield );
309
310   // @todo MESH_REWORK add support for wrap modes
311 }
312
313 unsigned int NewRenderer::GetTextureUnitUniformIndex(
314   Program& program,
315   const SamplerDataProvider& sampler )
316 {
317   // Find sampler in mSamplerNameCache
318   // If it doesn't exist,
319   //   get the index by calling program.RegisterUniform and store it
320   // If it exists, it's index should be set.
321   // @todo Cache should be reset on scene change
322
323   unsigned int uniformIndex = 0;
324   bool found = false;
325
326   for( unsigned int i=0; i< mTextureUnitUniforms.Count(); ++i )
327   {
328     if( mTextureUnitUniforms[i].sampler == &sampler )
329     {
330       uniformIndex = mTextureUnitUniforms[i].index;
331       found = true;
332     }
333   }
334
335   if( ! found )
336   {
337     TextureUnitUniformIndex textureUnitUniformIndex;
338     textureUnitUniformIndex.sampler = &sampler;
339     textureUnitUniformIndex.index = program.RegisterUniform( sampler.GetTextureUnitUniformName() );
340     mTextureUnitUniforms.PushBack( textureUnitUniformIndex );
341     uniformIndex = textureUnitUniformIndex.index;
342   }
343
344   return uniformIndex;
345 }
346
347
348 } // SceneGraph
349 } // Internal
350 } // Dali