Added getters in Renderer to get material and geometry, and in Material to get samplers
[platform/core/uifw/dali-core.git] / dali / internal / event / effects / material-impl.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/event/effects/material-impl.h> // Dali::Internal::Material
20
21 // INTERNAL INCLUDES
22 #include <dali/public-api/shader-effects/material.h> // Dali::Internal::Material
23 #include <dali/internal/event/common/object-impl-helper.h> // Dali::Internal::ObjectHelper
24 #include <dali/internal/event/common/property-helper.h> // DALI_PROPERTY_TABLE_BEGIN, DALI_PROPERTY, DALI_PROPERTY_TABLE_END
25 #include <dali/internal/update/effects/scene-graph-material.h>
26 #include <dali/internal/update/effects/scene-graph-sampler.h>
27 #include <dali/internal/update/manager/update-manager.h>
28
29 namespace Dali
30 {
31 namespace Internal
32 {
33
34 namespace
35 {
36
37 /**
38  *            |name                              |type     |writable|animatable|constraint-input|enum for index-checking|
39  */
40 DALI_PROPERTY_TABLE_BEGIN
41 DALI_PROPERTY( "color",                           VECTOR4,  true, true,   true, Dali::Material::Property::COLOR )
42 DALI_PROPERTY( "face-culling-mode",               STRING,   true, false,  false, Dali::Material::Property::FACE_CULLING_MODE )
43 DALI_PROPERTY( "blending-mode",                   STRING,   true, false,  false, Dali::Material::Property::BLENDING_MODE )
44 DALI_PROPERTY( "blend-equation-rgb",                  STRING,   true, false,  false, Dali::Material::Property::BLEND_EQUATION_RGB )
45 DALI_PROPERTY( "blend-equation-alpha",                  STRING,   true, false,  false, Dali::Material::Property::BLEND_EQUATION_ALPHA )
46 DALI_PROPERTY( "source-blend-factor-rgb",         STRING,   true, false,  false, Dali::Material::Property::BLENDING_SRC_FACTOR_RGB )
47 DALI_PROPERTY( "destination-blend-factor-rgb",    STRING,   true, false,  false, Dali::Material::Property::BLENDING_DEST_FACTOR_RGB )
48 DALI_PROPERTY( "source-blend-factor-alpha",       STRING,   true, false,  false, Dali::Material::Property::BLENDING_SRC_FACTOR_ALPHA )
49 DALI_PROPERTY( "destination-blend-factor-alpha",  STRING,   true, false,  false, Dali::Material::Property::BLENDING_DEST_FACTOR_ALPHA )
50 DALI_PROPERTY( "blend-color",                     VECTOR4,  true, true,   true, Dali::Material::Property::BLEND_COLOR )
51 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
52
53 const ObjectImplHelper<DEFAULT_PROPERTY_COUNT> MATERIAL_IMPL = { DEFAULT_PROPERTY_DETAILS };
54
55 } // unnamed namespace
56
57 MaterialPtr Material::New()
58 {
59   MaterialPtr material( new Material() );
60   material->Initialize();
61   return material;
62 }
63
64 void Material::SetShader( Shader& shader )
65 {
66   DALI_ASSERT_DEBUG( mSceneObject )
67   mShaderConnector.Set( shader, OnStage() );
68
69   const SceneGraph::Shader& sceneGraphShader = dynamic_cast<const SceneGraph::Shader&>( *shader.GetSceneObject() );
70   SceneGraph::SetShaderMessage( GetEventThreadServices(), *mSceneObject, sceneGraphShader );
71 }
72
73 void Material::AddSampler( Sampler& sampler )
74 {
75   SamplerConnector connector;
76   connector.Set( sampler, OnStage() );
77   mSamplerConnectors.push_back( connector );
78
79   const SceneGraph::Sampler& sceneGraphSampler = dynamic_cast<const SceneGraph::Sampler&>( *sampler.GetSceneObject() );
80   SceneGraph::AddSamplerMessage( GetEventThreadServices(), *mSceneObject, sceneGraphSampler );
81 }
82
83 std::size_t Material::GetNumberOfSamplers() const
84 {
85   return mSamplerConnectors.size();
86 }
87
88 void Material::RemoveSampler( std::size_t index )
89 {
90   mSamplerConnectors.erase( mSamplerConnectors.begin() + index );
91 }
92
93 Sampler* Material::GetSamplerAt( unsigned int index ) const
94 {
95   return mSamplerConnectors[index].Get().Get();
96 }
97
98 void Material::SetFaceCullingMode( Dali::Material::FaceCullingMode cullingMode )
99 {
100   if( NULL != mSceneObject )
101   {
102     SceneGraph::DoubleBufferedPropertyMessage<int>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mFaceCullingMode, &SceneGraph::DoubleBufferedProperty<int>::Set, static_cast<int>(cullingMode) );
103   }
104 }
105
106 void Material::SetBlendMode( BlendingMode::Type mode )
107 {
108   mBlendingMode = mode;
109
110   if( NULL != mSceneObject )
111   {
112     SceneGraph::DoubleBufferedPropertyMessage<int>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mBlendingMode, &SceneGraph::DoubleBufferedProperty<int>::Set, static_cast<int>(mode) );
113   }
114 }
115
116 BlendingMode::Type Material::GetBlendMode() const
117 {
118   return mBlendingMode;
119 }
120
121 void Material::SetBlendFunc( BlendingFactor::Type srcFactorRgba, BlendingFactor::Type destFactorRgba )
122 {
123   mBlendingOptions.SetBlendFunc( srcFactorRgba, destFactorRgba, srcFactorRgba, destFactorRgba );
124   SetBlendingOptionsMessage( GetEventThreadServices(), *mSceneObject, mBlendingOptions.GetBitmask() );
125 }
126
127 void Material::SetBlendFunc( BlendingFactor::Type srcFactorRgb,
128                              BlendingFactor::Type destFactorRgb,
129                              BlendingFactor::Type srcFactorAlpha,
130                              BlendingFactor::Type destFactorAlpha )
131 {
132   mBlendingOptions.SetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
133   SetBlendingOptionsMessage( GetEventThreadServices(), *mSceneObject, mBlendingOptions.GetBitmask() );
134 }
135
136 void Material::GetBlendFunc( BlendingFactor::Type& srcFactorRgb,
137                              BlendingFactor::Type& destFactorRgb,
138                              BlendingFactor::Type& srcFactorAlpha,
139                              BlendingFactor::Type& destFactorAlpha ) const
140 {
141   srcFactorRgb    = mBlendingOptions.GetBlendSrcFactorRgb();
142   destFactorRgb   = mBlendingOptions.GetBlendDestFactorRgb();
143   srcFactorAlpha  = mBlendingOptions.GetBlendSrcFactorAlpha();
144   destFactorAlpha = mBlendingOptions.GetBlendDestFactorAlpha();
145 }
146
147 void Material::SetBlendEquation( BlendingEquation::Type equationRgba )
148 {
149   mBlendingOptions.SetBlendEquation( equationRgba, equationRgba );
150   SetBlendingOptionsMessage( GetEventThreadServices(), *mSceneObject, mBlendingOptions.GetBitmask() );
151 }
152
153 void Material::SetBlendEquation( BlendingEquation::Type equationRgb,
154                                  BlendingEquation::Type equationAlpha )
155 {
156   mBlendingOptions.SetBlendEquation( equationRgb, equationAlpha );
157   SetBlendingOptionsMessage( GetEventThreadServices(), *mSceneObject, mBlendingOptions.GetBitmask() );
158 }
159
160 void Material::GetBlendEquation( BlendingEquation::Type& equationRgb,
161                                  BlendingEquation::Type& equationAlpha ) const
162 {
163   // These are not animatable, the cached values are up-to-date.
164   equationRgb   = mBlendingOptions.GetBlendEquationRgb();
165   equationAlpha = mBlendingOptions.GetBlendEquationAlpha();
166 }
167
168 void Material::SetBlendColor( const Vector4& color )
169 {
170   if( mSceneObject )
171   {
172     SceneGraph::AnimatablePropertyMessage<Vector4>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mBlendColor, &SceneGraph::AnimatableProperty<Vector4>::Bake, color );
173   }
174 }
175
176 const Vector4& Material::GetBlendColor() const
177 {
178   return mSceneObject->mBlendColor[ GetEventThreadServices().GetEventBufferIndex() ];
179 }
180
181 const SceneGraph::Material* Material::GetMaterialSceneObject() const
182 {
183   return mSceneObject;
184 }
185
186 unsigned int Material::GetDefaultPropertyCount() const
187 {
188   return MATERIAL_IMPL.GetDefaultPropertyCount();
189 }
190
191 void Material::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
192 {
193   MATERIAL_IMPL.GetDefaultPropertyIndices( indices );
194 }
195
196 const char* Material::GetDefaultPropertyName(Property::Index index) const
197 {
198   return MATERIAL_IMPL.GetDefaultPropertyName( index );
199 }
200
201 Property::Index Material::GetDefaultPropertyIndex( const std::string& name ) const
202 {
203   return MATERIAL_IMPL.GetDefaultPropertyIndex( name );
204 }
205
206 bool Material::IsDefaultPropertyWritable( Property::Index index ) const
207 {
208   return MATERIAL_IMPL.IsDefaultPropertyWritable( index );
209 }
210
211 bool Material::IsDefaultPropertyAnimatable( Property::Index index ) const
212 {
213   return MATERIAL_IMPL.IsDefaultPropertyAnimatable( index );
214 }
215
216 bool Material::IsDefaultPropertyAConstraintInput( Property::Index index ) const
217 {
218   return MATERIAL_IMPL.IsDefaultPropertyAConstraintInput( index );
219 }
220
221 Property::Type Material::GetDefaultPropertyType( Property::Index index ) const
222 {
223   return MATERIAL_IMPL.GetDefaultPropertyType( index );
224 }
225
226 void Material::SetDefaultProperty( Property::Index index,
227                                    const Property::Value& propertyValue )
228 {
229   switch( index )
230   {
231     case Dali::Material::Property::COLOR:
232     {
233       SceneGraph::AnimatablePropertyMessage<Vector4>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mColor, &SceneGraph::AnimatableProperty<Vector4>::Bake, propertyValue.Get<Vector4>() );
234       break;
235     }
236     case Dali::Material::Property::FACE_CULLING_MODE:
237     {
238       SceneGraph::DoubleBufferedPropertyMessage<int>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mFaceCullingMode, &SceneGraph::DoubleBufferedProperty<int>::Set, propertyValue.Get<int>() );
239       break;
240     }
241     case Dali::Material::Property::BLENDING_MODE:
242     {
243       if( mSceneObject )
244       {
245         SceneGraph::DoubleBufferedPropertyMessage<int>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mBlendingMode, &SceneGraph::DoubleBufferedProperty<int>::Set, propertyValue.Get<int>() );
246       }
247       break;
248     }
249     case Dali::Material::Property::BLEND_EQUATION_RGB:
250     {
251       BlendingEquation::Type alphaEquation = mBlendingOptions.GetBlendEquationAlpha();
252       mBlendingOptions.SetBlendEquation( static_cast<BlendingEquation::Type>(propertyValue.Get<int>()), alphaEquation );
253       break;
254     }
255     case Dali::Material::Property::BLEND_EQUATION_ALPHA:
256     {
257       BlendingEquation::Type rgbEquation = mBlendingOptions.GetBlendEquationRgb();
258       mBlendingOptions.SetBlendEquation( rgbEquation, static_cast<BlendingEquation::Type>(propertyValue.Get<int>()) );
259       break;
260     }
261     case Dali::Material::Property::BLENDING_SRC_FACTOR_RGB:
262     {
263       BlendingFactor::Type srcFactorRgb;
264       BlendingFactor::Type destFactorRgb;
265       BlendingFactor::Type srcFactorAlpha;
266       BlendingFactor::Type destFactorAlpha;
267       GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
268       SetBlendFunc( static_cast<BlendingFactor::Type>(propertyValue.Get<int>()),
269                     destFactorRgb,
270                     srcFactorAlpha,
271                     destFactorAlpha );
272       break;
273     }
274     case Dali::Material::Property::BLENDING_DEST_FACTOR_RGB:
275     {
276       BlendingFactor::Type srcFactorRgb;
277       BlendingFactor::Type destFactorRgb;
278       BlendingFactor::Type srcFactorAlpha;
279       BlendingFactor::Type destFactorAlpha;
280       GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
281       SetBlendFunc( srcFactorRgb,
282                     static_cast<BlendingFactor::Type>(propertyValue.Get<int>()),
283                     srcFactorAlpha,
284                     destFactorAlpha );
285       break;
286     }
287     case Dali::Material::Property::BLENDING_SRC_FACTOR_ALPHA:
288     {
289       BlendingFactor::Type srcFactorRgb;
290       BlendingFactor::Type destFactorRgb;
291       BlendingFactor::Type srcFactorAlpha;
292       BlendingFactor::Type destFactorAlpha;
293       GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
294       SetBlendFunc( srcFactorRgb,
295                     destFactorRgb,
296                     static_cast<BlendingFactor::Type>(propertyValue.Get<int>()),
297                     destFactorAlpha );
298       break;
299     }
300     case Dali::Material::Property::BLENDING_DEST_FACTOR_ALPHA:
301     {
302       BlendingFactor::Type srcFactorRgb;
303       BlendingFactor::Type destFactorRgb;
304       BlendingFactor::Type srcFactorAlpha;
305       BlendingFactor::Type destFactorAlpha;
306       GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
307       SetBlendFunc( srcFactorRgb,
308                     destFactorRgb,
309                     srcFactorAlpha,
310                     static_cast<BlendingFactor::Type>(propertyValue.Get<int>()) );
311       break;
312     }
313     case Dali::Material::Property::BLEND_COLOR:
314     {
315       SceneGraph::AnimatablePropertyMessage<Vector4>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mBlendColor, &SceneGraph::AnimatableProperty<Vector4>::Bake, propertyValue.Get<Vector4>() );
316       break;
317     }
318   }
319 }
320
321 void Material::SetSceneGraphProperty( Property::Index index,
322                                       const PropertyMetadata& entry,
323                                       const Property::Value& value )
324 {
325   MATERIAL_IMPL.SetSceneGraphProperty( GetEventThreadServices(), this, index, entry, value );
326   OnPropertySet(index, value);
327 }
328
329 Property::Value Material::GetDefaultProperty( Property::Index index ) const
330 {
331   BufferIndex bufferIndex = GetEventThreadServices().GetEventBufferIndex();
332   Property::Value value;
333
334   switch( index )
335   {
336     case Dali::Material::Property::COLOR:
337     {
338       if( mSceneObject )
339       {
340         value = mSceneObject->mColor[bufferIndex];
341       }
342       break;
343     }
344     case Dali::Material::Property::FACE_CULLING_MODE:
345     {
346       if( mSceneObject )
347       {
348         value = mSceneObject->mFaceCullingMode[bufferIndex];
349       }
350       break;
351     }
352     case Dali::Material::Property::BLENDING_MODE:
353     {
354       if( mSceneObject )
355       {
356         value = mSceneObject->mBlendingMode[bufferIndex];
357       }
358       break;
359     }
360     case Dali::Material::Property::BLEND_EQUATION_RGB:
361     {
362       value = static_cast<int>( mBlendingOptions.GetBlendEquationRgb() );
363       break;
364     }
365     case Dali::Material::Property::BLEND_EQUATION_ALPHA:
366     {
367       value = static_cast<int>( mBlendingOptions.GetBlendEquationAlpha() );
368       break;
369     }
370     case Dali::Material::Property::BLENDING_SRC_FACTOR_RGB:
371     {
372       BlendingFactor::Type srcFactorRgb;
373       BlendingFactor::Type destFactorRgb;
374       BlendingFactor::Type srcFactorAlpha;
375       BlendingFactor::Type destFactorAlpha;
376       GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
377       value = static_cast<int>( srcFactorRgb );
378       break;
379     }
380     case Dali::Material::Property::BLENDING_DEST_FACTOR_RGB:
381     {
382       BlendingFactor::Type srcFactorRgb;
383       BlendingFactor::Type destFactorRgb;
384       BlendingFactor::Type srcFactorAlpha;
385       BlendingFactor::Type destFactorAlpha;
386       GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
387       value = static_cast<int>( destFactorRgb );
388       break;
389     }
390     case Dali::Material::Property::BLENDING_SRC_FACTOR_ALPHA:
391     {
392       BlendingFactor::Type srcFactorRgb;
393       BlendingFactor::Type destFactorRgb;
394       BlendingFactor::Type srcFactorAlpha;
395       BlendingFactor::Type destFactorAlpha;
396       GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
397       value = static_cast<int>( srcFactorAlpha );
398       break;
399     }
400     case Dali::Material::Property::BLENDING_DEST_FACTOR_ALPHA:
401     {
402       BlendingFactor::Type srcFactorRgb;
403       BlendingFactor::Type destFactorRgb;
404       BlendingFactor::Type srcFactorAlpha;
405       BlendingFactor::Type destFactorAlpha;
406       GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
407       value = static_cast<int>( destFactorAlpha );
408       break;
409     }
410     case Dali::Material::Property::BLEND_COLOR:
411     {
412       if( mSceneObject )
413       {
414         value = mSceneObject->mBlendColor[bufferIndex];
415       }
416       break;
417     }
418   }
419
420   return value;
421 }
422
423 const SceneGraph::PropertyOwner* Material::GetPropertyOwner() const
424 {
425   return mSceneObject;
426 }
427
428 const SceneGraph::PropertyOwner* Material::GetSceneObject() const
429 {
430   return mSceneObject;
431 }
432
433 const SceneGraph::PropertyBase* Material::GetSceneObjectAnimatableProperty( Property::Index index ) const
434 {
435   DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
436
437   const SceneGraph::PropertyBase* property = NULL;
438
439   if( OnStage() )
440   {
441     property = MATERIAL_IMPL.GetRegisteredSceneGraphProperty( this,
442                                                               &Material::FindAnimatableProperty,
443                                                               &Material::FindCustomProperty,
444                                                               index );
445
446     if( property == NULL && index < DEFAULT_PROPERTY_MAX_COUNT )
447     {
448       switch(index)
449       {
450         case Dali::Material::Property::COLOR:
451         {
452           property = &mSceneObject->mColor;
453           break;
454         }
455         case Dali::Material::Property::BLEND_COLOR:
456         {
457           property = &mSceneObject->mBlendColor;
458           break;
459         }
460         default:
461         {
462           DALI_ASSERT_ALWAYS( 0 && "Property is not animatable");
463           break;
464         }
465       }
466     }
467   }
468
469   return property;
470 }
471
472 const PropertyInputImpl* Material::GetSceneObjectInputProperty( Property::Index index ) const
473 {
474   const PropertyInputImpl* property = NULL;
475
476   if( OnStage() )
477   {
478     const SceneGraph::PropertyBase* baseProperty =
479       MATERIAL_IMPL.GetRegisteredSceneGraphProperty( this,
480                                                      &Material::FindAnimatableProperty,
481                                                      &Material::FindCustomProperty,
482                                                      index );
483     property = static_cast<const PropertyInputImpl*>( baseProperty );
484
485     if( property == NULL && index < DEFAULT_PROPERTY_MAX_COUNT )
486     {
487       switch(index)
488       {
489         case Dali::Material::Property::COLOR:
490         {
491           property = &mSceneObject->mColor;
492           break;
493         }
494         case Dali::Material::Property::FACE_CULLING_MODE:
495         {
496           property = &mSceneObject->mFaceCullingMode;
497           break;
498         }
499         case Dali::Material::Property::BLEND_COLOR:
500         {
501           property = &mSceneObject->mBlendColor;
502           break;
503         }
504         default:
505         {
506           DALI_ASSERT_ALWAYS( 0 && "Property cannot be a constraint input");
507           break;
508         }
509       }
510     }
511   }
512
513   return property;
514 }
515
516 int Material::GetPropertyComponentIndex( Property::Index index ) const
517 {
518   // @todo MESH_REWORK - Change this if component properties are added for color/blend-color
519   return Property::INVALID_COMPONENT_INDEX;
520 }
521
522 bool Material::OnStage() const
523 {
524   return mOnStage;
525 }
526
527 void Material::Connect()
528 {
529   mOnStage = true;
530
531   SamplerConnectorContainer::const_iterator end = mSamplerConnectors.end();
532   for( SamplerConnectorContainer::iterator it = mSamplerConnectors.begin();
533        it < end;
534        ++it )
535   {
536     it->OnStageConnect();
537   }
538   mShaderConnector.OnStageConnect();
539 }
540
541 void Material::Disconnect()
542 {
543   mOnStage = false;
544
545   SamplerConnectorContainer::const_iterator end = mSamplerConnectors.end();
546   for( SamplerConnectorContainer::iterator it = mSamplerConnectors.begin();
547        it < end;
548        ++it )
549   {
550     it->OnStageDisconnect();
551   }
552   mShaderConnector.OnStageDisconnect();
553 }
554
555 Material::Material()
556 : mSceneObject( NULL ),
557   mOnStage( false )
558 {
559 }
560
561 void Material::Initialize()
562 {
563   EventThreadServices& eventThreadServices = GetEventThreadServices();
564   SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
565
566   DALI_ASSERT_ALWAYS( EventThreadServices::IsCoreRunning() && "Core is not running" );
567
568   mSceneObject = new SceneGraph::Material();
569   AddMessage( updateManager, updateManager.GetMaterialOwner(), *mSceneObject );
570 }
571
572 Material::~Material()
573 {
574   if( EventThreadServices::IsCoreRunning() )
575   {
576     EventThreadServices& eventThreadServices = GetEventThreadServices();
577     SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
578     RemoveMessage( updateManager, updateManager.GetMaterialOwner(), *mSceneObject );
579   }
580 }
581
582 } // namespace Internal
583 } // namespace Dali