Merge branch 'devel/new_mesh' into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / render / shaders / scene-graph-shader.cpp
1 /*
2  * Copyright (c) 2014 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( Integration::ResourceId resourceId,
207                          Integration::ShaderDataPtr shaderData,
208                          ProgramCache* programCache,
209                          bool modifiesGeometry )
210 {
211   DALI_LOG_TRACE_METHOD_FMT(Debug::Filter::gShader, "%d\n", resourceId);
212
213   mProgram = Program::New( *programCache, shaderData, modifiesGeometry );
214   // The program cache owns the Program object so we don't need to worry here.
215 }
216
217 Program* Shader::GetProgram()
218 {
219   return mProgram;
220 }
221
222 void Shader::SetUniforms( Context& context,
223                           Program& program,
224                           BufferIndex bufferIndex )
225 {
226   if( mRenderTextureId && ( mTexture == NULL ) )
227   {
228     mTexture = mTextureCache->GetTexture( mRenderTextureId );
229
230     DALI_ASSERT_DEBUG( mTexture != NULL );
231   }
232
233   GLint loc = Program::UNIFORM_UNKNOWN;
234
235   if( mTexture )
236   {
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 )
240     {
241       // got effect texture, bind it to texture unit 1
242       mTextureCache->BindTexture( mTexture, mRenderTextureId, GL_TEXTURE_2D, TEXTURE_UNIT_SHADER);
243
244       // Apply the default sampling options for now
245       mTexture->ApplySampler( TEXTURE_UNIT_SHADER, ImageSampler::PackBitfield( FilterMode::DEFAULT, FilterMode::DEFAULT ) );
246
247       DALI_PRINT_UNIFORM( debugStream, bufferIndex, "sEffect", TEXTURE_UNIT_SHADER );
248       // set the uniform
249       program.SetUniform1i( loc, TEXTURE_UNIT_SHADER );
250     }
251   }
252
253   // We should have one UniformMeta per uniform property
254   for ( unsigned int i = 0u; i < mUniformMetadata.Count(); ++i )
255   {
256     UniformMeta& metadata = *mUniformMetadata[i];
257     const PropertyBase& property = metadata.property;
258
259     // send the updated uniform to the program
260     if ( metadata.name.length() > 0 )
261     {
262       // 0 means program has not got a cache index for this uniform
263       if( 0 == metadata.cacheIndex )
264       {
265         // register cacheindex for this program
266         metadata.cacheIndex = program.RegisterUniform( metadata.name );
267       }
268       loc = program.GetUniformLocation( metadata.cacheIndex );
269
270       // if we find uniform with location
271       if ( Program::UNIFORM_UNKNOWN != loc )
272       {
273         DALI_PRINT_CUSTOM_UNIFORM( debugStream, bufferIndex, metadata.name, property );
274
275         // switch based on property type to use correct GL uniform setter
276         switch ( property.GetType() )
277         {
278           case Property::BOOLEAN :
279           {
280             program.SetUniform1i( loc, property.GetBoolean( bufferIndex ) );
281             break;
282           }
283           case Property::INTEGER :
284           {
285             program.SetUniform1i( loc, property.GetInteger( bufferIndex ) );
286             break;
287           }
288           case Property::UNSIGNED_INTEGER :
289           {
290             program.SetUniform1i( loc, property.GetUnsignedInteger( bufferIndex ) );
291             break;
292           }
293           case Property::FLOAT :
294           {
295             program.SetUniform1f( loc, property.GetFloat( bufferIndex ) );
296             break;
297           }
298           case Property::VECTOR2 :
299           {
300             Vector2 value( property.GetVector2( bufferIndex ) );
301
302             switch ( metadata.coordinateType )
303             {
304               case Dali::ShaderEffect::COORDINATE_TYPE_VIEWPORT_POSITION :
305               {
306                 /**
307                  * Convert coordinates from viewport to GL view space
308                  *
309                  * Viewport coordinate
310                  * (0,0)
311                  *      +-----+
312                  *      |     |
313                  *      |     |
314                  *      +-----+
315                  *             (width,height)
316                  *
317                  * GL view space coordinates
318                  * (width/2,-height/2)
319                  *      +-----+
320                  *      |     |
321                  *      |     |
322                  *      +-----+
323                  *             (-width/2,height/2)
324                  **/
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;
328
329                 break;
330               }
331               case Dali::ShaderEffect::COORDINATE_TYPE_VIEWPORT_DIRECTION :
332               {
333                 // Check diagram in COORDINATE_TYPE_VIEWPORT_POSITION
334                 value.x *= -1.0f;
335                 break;
336               }
337               case Dali::ShaderEffect::COORDINATE_TYPE_DEFAULT :
338               {
339                 // nothing to do in this case
340                 break;
341               }
342               // no default so compiler will warn if a case is not handled
343             }
344
345             program.SetUniform2f( loc, value.x, value.y );
346             break;
347           }
348
349           case Property::VECTOR3 :
350           {
351             Vector3 value( property.GetVector3( bufferIndex ) );
352             if( Dali::ShaderEffect::COORDINATE_TYPE_VIEWPORT_DIRECTION == metadata.coordinateType)
353             {
354               value.y *= -1.0f;
355             }
356
357             program.SetUniform3f( loc, value.x, value.y, value.z );
358             break;
359           }
360
361           case Property::VECTOR4 :
362           {
363             Vector4 value( property.GetVector4( bufferIndex ) );
364             if( Dali::ShaderEffect::COORDINATE_TYPE_VIEWPORT_DIRECTION == metadata.coordinateType)
365             {
366               value.y *= -1.0f;
367             }
368
369             program.SetUniform4f( loc, value.x, value.y, value.z, value.w );
370             break;
371           }
372
373           case Property::MATRIX:
374           {
375             const Matrix& value = property.GetMatrix(bufferIndex);
376             program.SetUniformMatrix4fv(loc, 1, value.AsFloat() );
377             break;
378           }
379
380           case Property::MATRIX3:
381           {
382             const Matrix3& value = property.GetMatrix3(bufferIndex);
383             program.SetUniformMatrix3fv(loc, 1, value.AsFloat() );
384             break;
385           }
386
387           case Property::NONE:
388           case Property::ROTATION:
389           case Property::STRING:
390           case Property::RECTANGLE:
391           case Property::MAP:
392           case Property::ARRAY:
393           {
394             DALI_LOG_ERROR( "Invalid property type for a uniform" );
395             break;
396           }
397         }
398       }
399     }
400   }
401
402   DALI_PRINT_SHADER_UNIFORMS(debugStream);
403 }
404
405
406 // Messages
407
408 void SetTextureIdMessage( EventThreadServices& eventThreadServices, const Shader& shader, Integration::ResourceId textureId )
409 {
410   typedef MessageDoubleBuffered1< Shader, Integration::ResourceId > LocalType;
411
412   // Reserve some memory inside the message queue
413   unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
414
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 );
417 }
418
419 void SetGridDensityMessage( EventThreadServices& eventThreadServices, const Shader& shader, float density )
420 {
421   typedef MessageDoubleBuffered1< Shader, float > LocalType;
422
423   // Reserve some memory inside the message queue
424   unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
425
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 );
428 }
429
430 void SetHintsMessage( EventThreadServices& eventThreadServices, const Shader& shader, Dali::ShaderEffect::GeometryHints hint )
431 {
432   typedef MessageDoubleBuffered1< Shader, Dali::ShaderEffect::GeometryHints > LocalType;
433
434   // Reserve some memory inside the message queue
435   unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
436
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 );
439 }
440
441 void InstallUniformMetaMessage( EventThreadServices& eventThreadServices, const Shader& shader, UniformMeta& meta )
442 {
443   typedef MessageDoubleBuffered1< Shader, UniformMeta* > LocalType;
444
445   // Reserve some memory inside the message queue
446   unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
447
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 );
450 }
451
452 void SetCoordinateTypeMessage( EventThreadServices& eventThreadServices, const Shader& shader, unsigned int index, Dali::ShaderEffect::UniformCoordinateType type )
453 {
454   typedef MessageDoubleBuffered2< Shader, unsigned int, Dali::ShaderEffect::UniformCoordinateType > LocalType;
455
456   // Reserve some memory inside the message queue
457   unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
458
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 );
461 }
462
463
464 } // namespace SceneGraph
465
466 } // namespace Internal
467
468 } // namespace Dali