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