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