2 * Copyright (c) 2014 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.
19 #include <dali/internal/render/shaders/scene-graph-shader.h>
22 #include <dali/internal/render/queue/render-queue.h>
23 #include <dali/internal/render/common/render-debug.h>
24 #include <dali/internal/render/gl-resources/context.h>
25 #include <dali/internal/render/gl-resources/texture.h>
26 #include <dali/internal/render/gl-resources/texture-cache.h>
27 #include <dali/internal/render/gl-resources/texture-units.h>
28 #include <dali/internal/render/shaders/program.h>
29 #include <dali/internal/render/shaders/uniform-meta.h>
30 #include <dali/internal/common/image-sampler.h>
33 #ifdef DALI_PRINT_RENDER_INFO
36 #define DALI_DEBUG_OSTREAM(streamName) std::stringstream streamName;
38 #define DALI_PRINT_UNIFORM(streamName,bufferIndex,name,value) \
40 streamName << " " << name << ": " << value; \
43 #define DALI_PRINT_CUSTOM_UNIFORM(streamName,bufferIndex,name,property) \
45 streamName << " " << name << ": "; \
46 property.DebugPrint( streamName, bufferIndex ); \
49 #define DALI_PRINT_SHADER_UNIFORMS(streamName) \
51 std::string debugString( streamName.str() ); \
52 DALI_LOG_RENDER_INFO( " %s\n", debugString.c_str() ); \
55 #else // DALI_PRINT_RENDER_INFO
57 #define DALI_DEBUG_OSTREAM(streamName)
58 #define DALI_PRINT_UNIFORM(streamName,bufferIndex,name,value)
59 #define DALI_PRINT_CUSTOM_UNIFORM(streamName,bufferIndex,name,property)
60 #define DALI_PRINT_SHADER_UNIFORMS(streamName)
62 #endif // DALI_PRINT_RENDER_INFO
70 template <> struct ParameterType< Dali::ShaderEffect::GeometryHints> : public BasicType< Dali::ShaderEffect::GeometryHints > {};
71 template <> struct ParameterType< Dali::ShaderEffect::UniformCoordinateType > : public BasicType< Dali::ShaderEffect::UniformCoordinateType > {};
76 Shader::Shader( Dali::ShaderEffect::GeometryHints& hints )
77 : mGeometryHints( hints ),
78 mGridDensity( Dali::ShaderEffect::DEFAULT_GRID_DENSITY ),
80 mRenderTextureId( 0 ),
81 mUpdateTextureId( 0 ),
92 void Shader::Initialize( RenderQueue& renderQueue, TextureCache& textureCache )
94 mRenderQueue = &renderQueue;
95 mTextureCache = &textureCache;
98 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
99 // The following methods are called during UpdateManager::Update()
100 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
102 void Shader::ForwardTextureId( BufferIndex updateBufferIndex, ResourceId textureId )
104 mUpdateTextureId = textureId;
106 typedef MessageValue1< Shader, Integration::ResourceId > DerivedType;
108 // Reserve some memory inside the render queue
109 unsigned int* slot = mRenderQueue->ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
111 // Construct message in the render queue memory; note that delete should not be called on the return value
112 new (slot) DerivedType( this, &Shader::SetTextureId, textureId );
115 Integration::ResourceId Shader::GetEffectTextureResourceId()
117 return mUpdateTextureId;
120 void Shader::ForwardUniformMeta( BufferIndex updateBufferIndex, UniformMeta* meta )
122 // Defer setting uniform metadata until the next Render
124 typedef MessageValue1< Shader, UniformMeta* > DerivedType;
126 // Reserve some memory inside the render queue
127 unsigned int* slot = mRenderQueue->ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
129 // Construct message in the render queue memory; note that delete should not be called on the return value
130 new (slot) DerivedType( this, &Shader::InstallUniformMetaInRender, meta );
133 void Shader::ForwardCoordinateType( BufferIndex updateBufferIndex, unsigned int index, Dali::ShaderEffect::UniformCoordinateType type )
135 // Defer setting uniform coordinate type until the next Render
136 typedef MessageValue2< Shader, unsigned int, Dali::ShaderEffect::UniformCoordinateType > DerivedType;
138 // Reserve some memory inside the render queue
139 unsigned int* slot = mRenderQueue->ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
141 // Construct message in the render queue memory; note that delete should not be called on the return value
142 new (slot) DerivedType( this, &Shader::SetCoordinateTypeInRender, index, type );
145 void Shader::ForwardGridDensity( BufferIndex updateBufferIndex, float density )
147 typedef MessageValue1< Shader, float > DerivedType;
149 // Reserve some memory inside the render queue
150 unsigned int* slot = mRenderQueue->ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
152 // Construct message in the render queue memory; note that delete should not be called on the return value
153 new (slot) DerivedType( this, &Shader::SetGridDensity, density );
156 void Shader::ForwardHints( BufferIndex updateBufferIndex, Dali::ShaderEffect::GeometryHints hint )
158 typedef MessageValue1< Shader, Dali::ShaderEffect::GeometryHints > DerivedType;
160 // Reserve some memory inside the render queue
161 unsigned int* slot = mRenderQueue->ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
163 // Construct message in the render queue memory; note that delete should not be called on the return value
164 new (slot) DerivedType( this, &Shader::SetGeometryHints, hint );
167 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
168 // The following methods are called during RenderManager::Render()
169 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
171 void Shader::SetTextureId( Integration::ResourceId textureId )
173 if ( mRenderTextureId != textureId )
175 mRenderTextureId = textureId;
180 Integration::ResourceId Shader::GetTextureIdToRender()
182 return mRenderTextureId;
185 void Shader::SetGridDensity( float density )
187 mGridDensity = density;
190 float Shader::GetGridDensity()
195 void Shader::InstallUniformMetaInRender( UniformMeta* meta )
197 mUniformMetadata.PushBack( meta );
200 void Shader::SetCoordinateTypeInRender( unsigned int index, Dali::ShaderEffect::UniformCoordinateType type )
202 DALI_ASSERT_DEBUG( index < mUniformMetadata.Count() );
203 mUniformMetadata[ index ]->SetCoordinateType( type );
206 void Shader::SetProgram( Integration::ResourceId resourceId,
207 Integration::ShaderDataPtr shaderData,
208 ProgramCache* programCache,
209 bool modifiesGeometry )
211 DALI_LOG_TRACE_METHOD_FMT(Debug::Filter::gShader, "%d\n", resourceId);
213 mProgram = Program::New( *programCache, shaderData, modifiesGeometry );
214 // The program cache owns the Program object so we don't need to worry here.
217 Program* Shader::GetProgram()
222 void Shader::SetUniforms( Context& context,
224 BufferIndex bufferIndex )
226 if( mRenderTextureId && ( mTexture == NULL ) )
228 mTexture = mTextureCache->GetTexture( mRenderTextureId );
230 DALI_ASSERT_DEBUG( mTexture != NULL );
233 GLint loc = Program::UNIFORM_UNKNOWN;
237 // if effect sampler uniform used by the program ?
238 const GLint loc = program.GetUniformLocation( Program::UNIFORM_EFFECT_SAMPLER );
239 if( Program::UNIFORM_UNKNOWN != loc )
241 // got effect texture, bind it to texture unit 1
242 mTextureCache->BindTexture( mTexture, mRenderTextureId, GL_TEXTURE_2D, TEXTURE_UNIT_SHADER);
244 // Apply the default sampling options for now
245 mTexture->ApplySampler( TEXTURE_UNIT_SHADER, ImageSampler::PackBitfield( FilterMode::DEFAULT, FilterMode::DEFAULT ) );
247 DALI_PRINT_UNIFORM( debugStream, bufferIndex, "sEffect", TEXTURE_UNIT_SHADER );
249 program.SetUniform1i( loc, TEXTURE_UNIT_SHADER );
253 // We should have one UniformMeta per uniform property
254 for ( unsigned int i = 0u; i < mUniformMetadata.Count(); ++i )
256 UniformMeta& metadata = *mUniformMetadata[i];
257 const PropertyBase& property = metadata.property;
259 // send the updated uniform to the program
260 if ( metadata.name.length() > 0 )
262 // 0 means program has not got a cache index for this uniform
263 if( 0 == metadata.cacheIndex )
265 // register cacheindex for this program
266 metadata.cacheIndex = program.RegisterUniform( metadata.name );
268 loc = program.GetUniformLocation( metadata.cacheIndex );
270 // if we find uniform with location
271 if ( Program::UNIFORM_UNKNOWN != loc )
273 DALI_PRINT_CUSTOM_UNIFORM( debugStream, bufferIndex, metadata.name, property );
275 // switch based on property type to use correct GL uniform setter
276 switch ( property.GetType() )
278 case Property::BOOLEAN :
280 program.SetUniform1i( loc, property.GetBoolean( bufferIndex ) );
283 case Property::INTEGER :
285 program.SetUniform1i( loc, property.GetInteger( bufferIndex ) );
288 case Property::UNSIGNED_INTEGER :
290 program.SetUniform1i( loc, property.GetUnsignedInteger( bufferIndex ) );
293 case Property::FLOAT :
295 program.SetUniform1f( loc, property.GetFloat( bufferIndex ) );
298 case Property::VECTOR2 :
300 Vector2 value( property.GetVector2( bufferIndex ) );
302 switch ( metadata.coordinateType )
304 case Dali::ShaderEffect::COORDINATE_TYPE_VIEWPORT_POSITION :
307 * Convert coordinates from viewport to GL view space
309 * Viewport coordinate
317 * GL view space coordinates
318 * (width/2,-height/2)
323 * (-width/2,height/2)
325 const Rect< int >& viewport = context.GetViewport();
326 value.x = viewport.width * 0.5f - value.x;
327 value.y = value.y - viewport.height * 0.5f;
331 case Dali::ShaderEffect::COORDINATE_TYPE_VIEWPORT_DIRECTION :
333 // Check diagram in COORDINATE_TYPE_VIEWPORT_POSITION
337 case Dali::ShaderEffect::COORDINATE_TYPE_DEFAULT :
339 // nothing to do in this case
342 // no default so compiler will warn if a case is not handled
345 program.SetUniform2f( loc, value.x, value.y );
349 case Property::VECTOR3 :
351 Vector3 value( property.GetVector3( bufferIndex ) );
352 if( Dali::ShaderEffect::COORDINATE_TYPE_VIEWPORT_DIRECTION == metadata.coordinateType)
357 program.SetUniform3f( loc, value.x, value.y, value.z );
361 case Property::VECTOR4 :
363 Vector4 value( property.GetVector4( bufferIndex ) );
364 if( Dali::ShaderEffect::COORDINATE_TYPE_VIEWPORT_DIRECTION == metadata.coordinateType)
369 program.SetUniform4f( loc, value.x, value.y, value.z, value.w );
373 case Property::MATRIX:
375 const Matrix& value = property.GetMatrix(bufferIndex);
376 program.SetUniformMatrix4fv(loc, 1, value.AsFloat() );
380 case Property::MATRIX3:
382 const Matrix3& value = property.GetMatrix3(bufferIndex);
383 program.SetUniformMatrix3fv(loc, 1, value.AsFloat() );
388 case Property::ROTATION:
389 case Property::STRING:
390 case Property::RECTANGLE:
392 case Property::ARRAY:
394 DALI_LOG_ERROR( "Invalid property type for a uniform" );
402 DALI_PRINT_SHADER_UNIFORMS(debugStream);
408 void SetTextureIdMessage( EventThreadServices& eventThreadServices, const Shader& shader, Integration::ResourceId textureId )
410 typedef MessageDoubleBuffered1< Shader, Integration::ResourceId > LocalType;
412 // Reserve some memory inside the message queue
413 unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
415 // Construct message in the message queue memory; note that delete should not be called on the return value
416 new (slot) LocalType( &shader, &Shader::ForwardTextureId, textureId );
419 void SetGridDensityMessage( EventThreadServices& eventThreadServices, const Shader& shader, float density )
421 typedef MessageDoubleBuffered1< Shader, float > LocalType;
423 // Reserve some memory inside the message queue
424 unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
426 // Construct message in the message queue memory; note that delete should not be called on the return value
427 new (slot) LocalType( &shader, &Shader::ForwardGridDensity, density );
430 void SetHintsMessage( EventThreadServices& eventThreadServices, const Shader& shader, Dali::ShaderEffect::GeometryHints hint )
432 typedef MessageDoubleBuffered1< Shader, Dali::ShaderEffect::GeometryHints > LocalType;
434 // Reserve some memory inside the message queue
435 unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
437 // Construct message in the message queue memory; note that delete should not be called on the return value
438 new (slot) LocalType( &shader, &Shader::ForwardHints, hint );
441 void InstallUniformMetaMessage( EventThreadServices& eventThreadServices, const Shader& shader, UniformMeta& meta )
443 typedef MessageDoubleBuffered1< Shader, UniformMeta* > LocalType;
445 // Reserve some memory inside the message queue
446 unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
448 // Construct message in the message queue memory; note that delete should not be called on the return value
449 new (slot) LocalType( &shader, &Shader::ForwardUniformMeta, &meta );
452 void SetCoordinateTypeMessage( EventThreadServices& eventThreadServices, const Shader& shader, unsigned int index, Dali::ShaderEffect::UniformCoordinateType type )
454 typedef MessageDoubleBuffered2< Shader, unsigned int, Dali::ShaderEffect::UniformCoordinateType > LocalType;
456 // Reserve some memory inside the message queue
457 unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
459 // Construct message in the message queue memory; note that delete should not be called on the return value
460 new (slot) LocalType( &shader, &Shader::ForwardCoordinateType, index, type );
464 } // namespace SceneGraph
466 } // namespace Internal