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