Cleanup dead declaration from ShaderEffect
[platform/core/uifw/dali-core.git] / dali / internal / render / shaders / scene-graph-shader.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
18 // CLASS HEADER
19 #include <dali/internal/render/shaders/scene-graph-shader.h>
20
21 // INTERNAL INCLUDES
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>
31
32 // See render-debug.h
33 #ifdef DALI_PRINT_RENDER_INFO
34
35 #include <sstream>
36 #define DALI_DEBUG_OSTREAM(streamName) std::stringstream streamName;
37
38 #define DALI_PRINT_UNIFORM(streamName,bufferIndex,name,value) \
39   { \
40     streamName << " " << name << ": " << value; \
41   }
42
43 #define DALI_PRINT_CUSTOM_UNIFORM(streamName,bufferIndex,name,property) \
44   { \
45     streamName << " " << name << ": "; \
46     property.DebugPrint( streamName, bufferIndex ); \
47   }
48
49 #define DALI_PRINT_SHADER_UNIFORMS(streamName) \
50   { \
51     std::string debugString( streamName.str() ); \
52     DALI_LOG_RENDER_INFO( "           %s\n", debugString.c_str() ); \
53   }
54
55 #else // DALI_PRINT_RENDER_INFO
56
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)
61
62 #endif // DALI_PRINT_RENDER_INFO
63
64 namespace Dali
65 {
66
67 namespace Internal
68 {
69
70 template <> struct ParameterType< Dali::ShaderEffect::GeometryHints> : public BasicType< Dali::ShaderEffect::GeometryHints > {};
71 template <> struct ParameterType< Dali::ShaderEffect::UniformCoordinateType > : public BasicType< Dali::ShaderEffect::UniformCoordinateType > {};
72
73 namespace SceneGraph
74 {
75
76 Shader::Shader( Dali::ShaderEffect::GeometryHints& hints )
77 : mGeometryHints( hints ),
78   mGridDensity( Dali::ShaderEffect::DEFAULT_GRID_DENSITY ),
79   mTexture( NULL ),
80   mRenderTextureId( 0 ),
81   mUpdateTextureId( 0 ),
82   mProgram( NULL ),
83   mRenderQueue( NULL ),
84   mTextureCache( NULL )
85 {
86 }
87
88 Shader::~Shader()
89 {
90 }
91
92 void Shader::Initialize( RenderQueue& renderQueue, TextureCache& textureCache )
93 {
94   mRenderQueue = &renderQueue;
95   mTextureCache = &textureCache;
96 }
97
98 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
99 // The following methods are called during UpdateManager::Update()
100 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
101
102 void Shader::ForwardTextureId( BufferIndex updateBufferIndex, ResourceId textureId )
103 {
104   mUpdateTextureId = textureId;
105
106   typedef MessageValue1< Shader, Integration::ResourceId > DerivedType;
107
108   // Reserve some memory inside the render queue
109   unsigned int* slot = mRenderQueue->ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
110
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 );
113 }
114
115 Integration::ResourceId Shader::GetEffectTextureResourceId()
116 {
117   return mUpdateTextureId;
118 }
119
120 void Shader::ForwardUniformMeta( BufferIndex updateBufferIndex, UniformMeta* meta )
121 {
122   // Defer setting uniform metadata until the next Render
123
124   typedef MessageValue1< Shader, UniformMeta* > DerivedType;
125
126   // Reserve some memory inside the render queue
127   unsigned int* slot = mRenderQueue->ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
128
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 );
131 }
132
133 void Shader::ForwardCoordinateType( BufferIndex updateBufferIndex, unsigned int index, Dali::ShaderEffect::UniformCoordinateType type )
134 {
135   // Defer setting uniform coordinate type until the next Render
136   typedef MessageValue2< Shader, unsigned int, Dali::ShaderEffect::UniformCoordinateType > DerivedType;
137
138   // Reserve some memory inside the render queue
139   unsigned int* slot = mRenderQueue->ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
140
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 );
143 }
144
145 void Shader::ForwardGridDensity( BufferIndex updateBufferIndex, float density )
146 {
147   typedef MessageValue1< Shader, float > DerivedType;
148
149   // Reserve some memory inside the render queue
150   unsigned int* slot = mRenderQueue->ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
151
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 );
154 }
155
156 void Shader::ForwardHints( BufferIndex updateBufferIndex, Dali::ShaderEffect::GeometryHints hint )
157 {
158   typedef MessageValue1< Shader, Dali::ShaderEffect::GeometryHints > DerivedType;
159
160   // Reserve some memory inside the render queue
161   unsigned int* slot = mRenderQueue->ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
162
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 );
165 }
166
167 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
168 // The following methods are called during RenderManager::Render()
169 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
170
171 void Shader::SetTextureId( Integration::ResourceId textureId )
172 {
173   if ( mRenderTextureId != textureId )
174   {
175     mRenderTextureId = textureId;
176     mTexture = NULL;
177   }
178 }
179
180 Integration::ResourceId Shader::GetTextureIdToRender()
181 {
182   return mRenderTextureId;
183 }
184
185 void Shader::SetGridDensity( float density )
186 {
187   mGridDensity = density;
188 }
189
190 float Shader::GetGridDensity()
191 {
192   return mGridDensity;
193 }
194
195 void Shader::InstallUniformMetaInRender( UniformMeta* meta )
196 {
197   mUniformMetadata.PushBack( meta );
198 }
199
200 void Shader::SetCoordinateTypeInRender( unsigned int index, Dali::ShaderEffect::UniformCoordinateType type )
201 {
202   DALI_ASSERT_DEBUG( index < mUniformMetadata.Count() );
203   mUniformMetadata[ index ]->SetCoordinateType( type );
204 }
205
206 void Shader::SetProgram( Internal::ShaderDataPtr shaderData,
207                          ProgramCache* programCache,
208                          bool modifiesGeometry )
209 {
210   DALI_LOG_TRACE_METHOD_FMT( Debug::Filter::gShader, "%d\n", shaderData->GetHashValue() );
211
212   mProgram = Program::New( *programCache, shaderData, modifiesGeometry );
213   // The program cache owns the Program object so we don't need to worry about this raw allocation here.
214 }
215
216 Program* Shader::GetProgram()
217 {
218   return mProgram;
219 }
220
221 void Shader::SetUniforms( Context& context,
222                           Program& program,
223                           BufferIndex bufferIndex )
224 {
225   if( mRenderTextureId && ( mTexture == NULL ) )
226   {
227     mTexture = mTextureCache->GetTexture( mRenderTextureId );
228
229     DALI_ASSERT_DEBUG( mTexture != NULL );
230   }
231
232   GLint loc = Program::UNIFORM_UNKNOWN;
233
234   if( mTexture )
235   {
236     // if effect sampler uniform used by the program ?
237     const GLint loc = program.GetUniformLocation( Program::UNIFORM_EFFECT_SAMPLER );
238     if( Program::UNIFORM_UNKNOWN != loc )
239     {
240       // got effect texture, bind it to texture unit 1
241       mTextureCache->BindTexture( mTexture, mRenderTextureId, GL_TEXTURE_2D, TEXTURE_UNIT_SHADER);
242
243       // Apply the default sampling options for now
244       mTexture->ApplySampler( TEXTURE_UNIT_SHADER, ImageSampler::PackBitfield( FilterMode::DEFAULT, FilterMode::DEFAULT ) );
245
246       DALI_PRINT_UNIFORM( debugStream, bufferIndex, "sEffect", TEXTURE_UNIT_SHADER );
247       // set the uniform
248       program.SetUniform1i( loc, TEXTURE_UNIT_SHADER );
249     }
250   }
251
252   // We should have one UniformMeta per uniform property
253   for ( unsigned int i = 0u; i < mUniformMetadata.Count(); ++i )
254   {
255     UniformMeta& metadata = *mUniformMetadata[i];
256     const PropertyBase& property = metadata.property;
257
258     // send the updated uniform to the program
259     if ( metadata.name.length() > 0 )
260     {
261       // 0 means program has not got a cache index for this uniform
262       if( 0 == metadata.cacheIndex )
263       {
264         // register cacheindex for this program
265         metadata.cacheIndex = program.RegisterUniform( metadata.name );
266       }
267       loc = program.GetUniformLocation( metadata.cacheIndex );
268
269       // if we find uniform with location
270       if ( Program::UNIFORM_UNKNOWN != loc )
271       {
272         DALI_PRINT_CUSTOM_UNIFORM( debugStream, bufferIndex, metadata.name, property );
273
274         // switch based on property type to use correct GL uniform setter
275         switch ( property.GetType() )
276         {
277           case Property::BOOLEAN :
278           {
279             program.SetUniform1i( loc, property.GetBoolean( bufferIndex ) );
280             break;
281           }
282           case Property::INTEGER :
283           {
284             program.SetUniform1i( loc, property.GetInteger( bufferIndex ) );
285             break;
286           }
287           case Property::FLOAT :
288           {
289             program.SetUniform1f( loc, property.GetFloat( bufferIndex ) );
290             break;
291           }
292           case Property::VECTOR2 :
293           {
294             Vector2 value( property.GetVector2( bufferIndex ) );
295
296             switch ( metadata.coordinateType )
297             {
298               case Dali::ShaderEffect::COORDINATE_TYPE_VIEWPORT_POSITION :
299               {
300                 /**
301                  * Convert coordinates from viewport to GL view space
302                  *
303                  * Viewport coordinate
304                  * (0,0)
305                  *      +-----+
306                  *      |     |
307                  *      |     |
308                  *      +-----+
309                  *             (width,height)
310                  *
311                  * GL view space coordinates
312                  * (width/2,-height/2)
313                  *      +-----+
314                  *      |     |
315                  *      |     |
316                  *      +-----+
317                  *             (-width/2,height/2)
318                  **/
319                 const Rect< int >& viewport = context.GetViewport();
320                 value.x = viewport.width * 0.5f - value.x;
321                 value.y = value.y - viewport.height * 0.5f;
322
323                 break;
324               }
325               case Dali::ShaderEffect::COORDINATE_TYPE_VIEWPORT_DIRECTION :
326               {
327                 // Check diagram in COORDINATE_TYPE_VIEWPORT_POSITION
328                 value.x *= -1.0f;
329                 break;
330               }
331               case Dali::ShaderEffect::COORDINATE_TYPE_DEFAULT :
332               {
333                 // nothing to do in this case
334                 break;
335               }
336               // no default so compiler will warn if a case is not handled
337             }
338
339             program.SetUniform2f( loc, value.x, value.y );
340             break;
341           }
342
343           case Property::VECTOR3 :
344           {
345             Vector3 value( property.GetVector3( bufferIndex ) );
346             if( Dali::ShaderEffect::COORDINATE_TYPE_VIEWPORT_DIRECTION == metadata.coordinateType)
347             {
348               value.y *= -1.0f;
349             }
350
351             program.SetUniform3f( loc, value.x, value.y, value.z );
352             break;
353           }
354
355           case Property::VECTOR4 :
356           {
357             Vector4 value( property.GetVector4( bufferIndex ) );
358             if( Dali::ShaderEffect::COORDINATE_TYPE_VIEWPORT_DIRECTION == metadata.coordinateType)
359             {
360               value.y *= -1.0f;
361             }
362
363             program.SetUniform4f( loc, value.x, value.y, value.z, value.w );
364             break;
365           }
366
367           case Property::MATRIX:
368           {
369             const Matrix& value = property.GetMatrix(bufferIndex);
370             program.SetUniformMatrix4fv(loc, 1, value.AsFloat() );
371             break;
372           }
373
374           case Property::MATRIX3:
375           {
376             const Matrix3& value = property.GetMatrix3(bufferIndex);
377             program.SetUniformMatrix3fv(loc, 1, value.AsFloat() );
378             break;
379           }
380
381           case Property::NONE:
382           case Property::ROTATION:
383           case Property::STRING:
384           case Property::RECTANGLE:
385           case Property::MAP:
386           case Property::ARRAY:
387           {
388             DALI_LOG_ERROR( "Invalid property type for a uniform" );
389             break;
390           }
391         }
392       }
393     }
394   }
395
396   DALI_PRINT_SHADER_UNIFORMS(debugStream);
397 }
398
399
400 // Messages
401
402 void SetTextureIdMessage( EventThreadServices& eventThreadServices, const Shader& shader, Integration::ResourceId textureId )
403 {
404   typedef MessageDoubleBuffered1< Shader, Integration::ResourceId > LocalType;
405
406   // Reserve some memory inside the message queue
407   unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
408
409   // Construct message in the message queue memory; note that delete should not be called on the return value
410   new (slot) LocalType( &shader, &Shader::ForwardTextureId, textureId );
411 }
412
413 void SetGridDensityMessage( EventThreadServices& eventThreadServices, const Shader& shader, float density )
414 {
415   typedef MessageDoubleBuffered1< Shader, float > LocalType;
416
417   // Reserve some memory inside the message queue
418   unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
419
420   // Construct message in the message queue memory; note that delete should not be called on the return value
421   new (slot) LocalType( &shader, &Shader::ForwardGridDensity, density );
422 }
423
424 void SetHintsMessage( EventThreadServices& eventThreadServices, const Shader& shader, Dali::ShaderEffect::GeometryHints hint )
425 {
426   typedef MessageDoubleBuffered1< Shader, Dali::ShaderEffect::GeometryHints > LocalType;
427
428   // Reserve some memory inside the message queue
429   unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
430
431   // Construct message in the message queue memory; note that delete should not be called on the return value
432   new (slot) LocalType( &shader, &Shader::ForwardHints, hint );
433 }
434
435 void InstallUniformMetaMessage( EventThreadServices& eventThreadServices, const Shader& shader, UniformMeta& meta )
436 {
437   typedef MessageDoubleBuffered1< Shader, UniformMeta* > LocalType;
438
439   // Reserve some memory inside the message queue
440   unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
441
442   // Construct message in the message queue memory; note that delete should not be called on the return value
443   new (slot) LocalType( &shader, &Shader::ForwardUniformMeta, &meta );
444 }
445
446 void SetCoordinateTypeMessage( EventThreadServices& eventThreadServices, const Shader& shader, unsigned int index, Dali::ShaderEffect::UniformCoordinateType type )
447 {
448   typedef MessageDoubleBuffered2< Shader, unsigned int, Dali::ShaderEffect::UniformCoordinateType > LocalType;
449
450   // Reserve some memory inside the message queue
451   unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
452
453   // Construct message in the message queue memory; note that delete should not be called on the return value
454   new (slot) LocalType( &shader, &Shader::ForwardCoordinateType, index, type );
455 }
456
457
458 } // namespace SceneGraph
459
460 } // namespace Internal
461
462 } // namespace Dali