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