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