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