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