2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "render-renderer.h"
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>
39 NewRenderer* NewRenderer::New( NodeDataProvider& nodeDataProvider,
40 const UniformMapDataProvider& uniformMapDataProvider,
41 const GeometryDataProvider* geometryDataProvider,
42 const MaterialDataProvider* materialDataProvider)
44 return new NewRenderer(nodeDataProvider, uniformMapDataProvider, geometryDataProvider, materialDataProvider);
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 )
60 NewRenderer::~NewRenderer()
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 )
68 mGeometryDataProvider = geometryDataProvider;
69 mRenderGeometry.GeometryUpdated();
72 void NewRenderer::SetMaterialDataProvider( const MaterialDataProvider* materialDataProvider )
74 mMaterialDataProvider = materialDataProvider;
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
86 bool NewRenderer::CheckResources()
88 // Query material to check it has texture pointers & image has size
89 // Query geometry to check it has vertex buffers
91 // General point though - why would we have a render item in RenderThread with no ready
92 // resources in UpdateThread?
96 void NewRenderer::ResolveGeometryTypes( BufferIndex bufferIndex, GeometryType& outType, ShaderSubTypes& outSubType )
98 // @todo MESH_REWORK Remove after merge
103 bool NewRenderer::IsOutsideClipSpace( const Matrix& modelMatrix, const Matrix& modelViewProjectionMatrix )
105 // @todo MESH_REWORK Add clipping
109 void NewRenderer::DoSetUniforms( Shader* shader, Context* context, Program* program, BufferIndex bufferIndex, unsigned int programIndex, ShaderSubTypes subType )
111 // Do nothing, we're going to set up the uniforms with our own code instead
115 void NewRenderer::DoRender( BufferIndex bufferIndex, Program& program, const Matrix& modelViewMatrix, const Matrix& viewMatrix )
117 BindTextures( bufferIndex, program, mMaterialDataProvider->GetSamplers() );
119 SetUniforms( bufferIndex, program );
121 mRenderGeometry.UploadAndDraw( mContext, program, bufferIndex, *mGeometryDataProvider );
124 void NewRenderer::GlContextDestroyed()
126 mRenderGeometry.GlContextDestroyed();
129 void NewRenderer::GlCleanup()
133 void NewRenderer::SetUniforms( BufferIndex bufferIndex, Program& program )
135 // Check if the map has changed
136 if( mUniformMapDataProvider.GetUniformMapChanged( bufferIndex ) )
138 const CollectedUniformMap& uniformMap = mUniformMapDataProvider.GetUniformMap( bufferIndex );
140 unsigned int numberOfMaps = uniformMap.Count();
141 mUniformIndexMap.Clear(); // Clear contents, but keep memory if we don't change size
142 mUniformIndexMap.Resize( numberOfMaps );
144 // Remap uniform indexes to property value addresses
146 for( unsigned int mapIndex = 0 ; mapIndex < numberOfMaps ; ++mapIndex )
148 mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex]->propertyPtr;
149 mUniformIndexMap[mapIndex].uniformIndex = program.RegisterUniform( uniformMap[mapIndex]->uniformName );
153 // Set uniforms in local map
154 for( UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
155 end = mUniformIndexMap.End() ;
159 SetUniformFromProperty( bufferIndex, program, *iter );
162 // @todo MESH_REWORK On merge, copy code from renderer to setup standard matrices and color
164 GLint sizeLoc = program.GetUniformLocation( Program::UNIFORM_SIZE );
167 Vector3 size = mDataProvider.GetRenderSize( bufferIndex );
168 program.SetUniform3f( sizeLoc, size.x, size.y, size.z );
172 void NewRenderer::SetUniformFromProperty( BufferIndex bufferIndex, Program& program, UniformIndexMap& map )
174 GLint location = program.GetUniformLocation(map.uniformIndex);
175 if( Program::UNIFORM_UNKNOWN != location )
177 // switch based on property type to use correct GL uniform setter
178 switch ( map.propertyValue->GetType() )
180 case Property::INTEGER:
182 program.SetUniform1i( location, map.propertyValue->GetInteger( bufferIndex ) );
185 case Property::FLOAT:
187 program.SetUniform1f( location, map.propertyValue->GetFloat( bufferIndex ) );
190 case Property::VECTOR2:
192 Vector2 value( map.propertyValue->GetVector2( bufferIndex ) );
193 program.SetUniform2f( location, value.x, value.y );
197 case Property::VECTOR3:
199 Vector3 value( map.propertyValue->GetVector3( bufferIndex ) );
200 program.SetUniform3f( location, value.x, value.y, value.z );
204 case Property::VECTOR4:
206 Vector4 value( map.propertyValue->GetVector4( bufferIndex ) );
207 program.SetUniform4f( location, value.x, value.y, value.z, value.w );
211 case Property::ROTATION:
213 Quaternion value( map.propertyValue->GetQuaternion( bufferIndex ) );
214 program.SetUniform4f( location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w );
218 case Property::MATRIX:
220 const Matrix& value = map.propertyValue->GetMatrix(bufferIndex);
221 program.SetUniformMatrix4fv(location, 1, value.AsFloat() );
225 case Property::MATRIX3:
227 const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex);
228 program.SetUniformMatrix3fv(location, 1, value.AsFloat() );
234 // Other property types are ignored
241 void NewRenderer::BindTextures(
242 BufferIndex bufferIndex,
244 const MaterialDataProvider::Samplers& samplers )
246 // @todo MESH_REWORK Write a cache of texture units to commonly used sampler textures
247 unsigned int textureUnit = 0;
249 for( MaterialDataProvider::Samplers::Iterator iter = samplers.Begin();
250 iter != samplers.End();
253 const SamplerDataProvider* sampler = *iter;
254 ResourceId textureId = sampler->GetTextureId(bufferIndex);
255 Texture* texture = mTextureCache->GetTexture( textureId );
256 if( texture != NULL )
258 unsigned int textureUnitUniformIndex = GetTextureUnitUniformIndex( program, *sampler );
259 TextureUnit theTextureUnit = static_cast<TextureUnit>(textureUnit);
260 BindTexture( program, textureId, texture, theTextureUnit, textureUnitUniformIndex );
261 ApplySampler( bufferIndex, texture, theTextureUnit, *sampler );
268 void NewRenderer::BindTexture(
272 TextureUnit textureUnit,
273 unsigned int textureUnitUniformIndex )
275 DALI_ASSERT_DEBUG( NULL != mTextureCache );
277 if( texture != NULL )
279 mTextureCache->BindTexture( texture, id, GL_TEXTURE_2D, textureUnit );
281 // Set sampler uniform location for the texture
282 GLint textureUnitLoc = program.GetUniformLocation( textureUnitUniformIndex );
283 if( Program::UNIFORM_UNKNOWN != textureUnitLoc )
285 program.SetUniform1i( textureUnitLoc, textureUnit );
290 void NewRenderer::ApplySampler(
291 BufferIndex bufferIndex,
293 TextureUnit textureUnit,
294 const SamplerDataProvider& sampler )
296 unsigned int samplerBitfield = ImageSampler::PackBitfield(
297 static_cast< FilterMode::Type >(sampler.GetMinifyFilterMode(bufferIndex)),
298 static_cast< FilterMode::Type >(sampler.GetMagnifyFilterMode(bufferIndex)) );
300 texture->ApplySampler( textureUnit, samplerBitfield );
302 // @todo MESH_REWORK add support for wrap modes
305 unsigned int NewRenderer::GetTextureUnitUniformIndex(
307 const SamplerDataProvider& sampler )
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
315 unsigned int uniformIndex = 0;
318 for( unsigned int i=0; i< mTextureUnitUniforms.Count(); ++i )
320 if( mTextureUnitUniforms[i].sampler == &sampler )
322 uniformIndex = mTextureUnitUniforms[i].index;
329 TextureUnitUniformIndex textureUnitUniformIndex;
330 textureUnitUniformIndex.sampler = &sampler;
331 textureUnitUniformIndex.index = program.RegisterUniform( sampler.GetUnitName() );
332 mTextureUnitUniforms.PushBack( textureUnitUniformIndex );
333 uniformIndex = textureUnitUniformIndex.index;