df5a0064d77b72b689e1df3813102f0fa5b83de5
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / renderers / control-renderer-data-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 "control-renderer-data-impl.h"
20
21 // EXTERNAL HEADER
22 #include <dali/public-api/common/dali-common.h>
23 #include <dali/integration-api/debug.h>
24 #include <dali/public-api/object/property-array.h>
25
26 // EXTERNAL HEADER
27
28 namespace Dali
29 {
30
31 namespace Toolkit
32 {
33
34 namespace Internal
35 {
36
37 namespace
38 {
39 //custom shader
40 const char * const CUSTOM_SHADER( "shader" );
41 const char * const CUSTOM_VERTEX_SHADER( "vertexShader" );
42 const char * const CUSTOM_FRAGMENT_SHADER( "fragmentShader" );
43 const char * const CUSTOM_SUBDIVIDE_GRID_X( "subdivideGridX" );
44 const char * const CUSTOM_SUBDIVIDE_GRID_Y( "subdivideGridY" );
45 const char * const CUSTOM_SHADER_HINTS( "hints" ); ///< type STRING for a hint from the below hint strings or an ARRAY of of hint strings
46
47 /**
48  * where hints should be contain strings of the following shader hints:
49  *   "none"                    | corresponds to HINT_NONE
50  *   "outputIsTransparent"     | corresponds to HINT_OUTPUT_IS_TRANSPARENT
51  *   "modifiesGeometry"        | corresponds to HINT_MODIFIES_GEOMETRY
52  */
53
54 Shader::ShaderHints HintFromString( std::string hintString )
55 {
56   if( hintString == "none" )
57   {
58     return Shader::HINT_NONE;
59   }
60   else if( hintString == "outputIsTransparent" )
61   {
62     return Shader::HINT_OUTPUT_IS_TRANSPARENT;
63   }
64   else if( hintString == "modifiesGeometry" )
65   {
66     return Shader::HINT_MODIFIES_GEOMETRY;
67   }
68   else
69   {
70     DALI_LOG_ERROR( "'%s' hint string is not recognised", hintString.c_str() );
71   }
72
73   return Shader::HINT_NONE;
74 }
75
76 }// unnamed namespace
77
78 Internal::ControlRenderer::Impl::Impl()
79 : mCustomShader(NULL),
80   mDepthIndex( 0.0f ),
81   mFlags( 0 )
82 {
83 }
84
85 Internal::ControlRenderer::Impl::~Impl()
86 {
87   delete mCustomShader;
88 }
89
90 Internal::ControlRenderer::Impl::CustomShader::CustomShader( const Property::Map& map )
91 : mGridSize( 1, 1 ),
92   mHints( Shader::HINT_NONE )
93 {
94   SetPropertyMap( map );
95 }
96
97 void Internal::ControlRenderer::Impl::CustomShader::SetPropertyMap( const Property::Map& propertyMap )
98 {
99   Property::Value* shaderValue = propertyMap.Find( CUSTOM_SHADER );
100   if( shaderValue )
101   {
102     mVertexShader.clear();
103     mFragmentShader.clear();
104     mGridSize = ImageDimensions( 1, 1 );
105     mHints = Shader::HINT_NONE;
106
107     Property::Map shaderMap;
108     if( shaderValue->Get( shaderMap ) )
109     {
110       Property::Value* vertexShaderValue = shaderMap.Find( CUSTOM_VERTEX_SHADER );
111       if( vertexShaderValue )
112       {
113         if( !vertexShaderValue->Get( mVertexShader ) )
114         {
115           DALI_LOG_ERROR( "'%s' parameter does not correctly specify a string", CUSTOM_VERTEX_SHADER );
116         }
117       }
118
119       Property::Value* fragmentShaderValue = shaderMap.Find( CUSTOM_FRAGMENT_SHADER );
120       if( fragmentShaderValue )
121       {
122         if( !fragmentShaderValue->Get( mFragmentShader ) )
123         {
124           DALI_LOG_ERROR( "'%s' parameter does not correctly specify a string", CUSTOM_FRAGMENT_SHADER );
125         }
126       }
127
128       Property::Value* subdivideXValue = shaderMap.Find( CUSTOM_SUBDIVIDE_GRID_X );
129       if( subdivideXValue )
130       {
131         int subdivideX;
132         if( !subdivideXValue->Get( subdivideX ) || subdivideX < 1 )
133         {
134           DALI_LOG_ERROR( "'%s' parameter does not correctly specify a value greater than 1", CUSTOM_SUBDIVIDE_GRID_X );
135         }
136         else
137         {
138           mGridSize = ImageDimensions( subdivideX, mGridSize.GetY() );
139         }
140       }
141
142       Property::Value* subdivideYValue = shaderMap.Find( CUSTOM_SUBDIVIDE_GRID_Y );
143       if( subdivideYValue )
144       {
145         int subdivideY;
146         if( !subdivideYValue->Get( subdivideY ) || subdivideY < 1 )
147         {
148           DALI_LOG_ERROR( "'%s' parameter does not correctly specify a value greater than 1", CUSTOM_SUBDIVIDE_GRID_Y );
149         }
150         else
151         {
152           mGridSize = ImageDimensions( mGridSize.GetX(), subdivideY );
153         }
154       }
155
156       Property::Value* hintsValue = shaderMap.Find( CUSTOM_SHADER_HINTS );
157       if( hintsValue )
158       {
159         std::string hintString;
160         Property::Array hintsArray;
161
162         if( hintsValue->Get( hintString ) )
163         {
164           mHints = HintFromString( hintString );
165         }
166         else if( hintsValue->Get( hintsArray ) )
167         {
168           int hints = Shader::HINT_NONE;
169           for( Property::Array::SizeType i = 0; i < hintsArray.Count(); ++i)
170           {
171             Property::Value hintValue = hintsArray[ i ];
172             if( hintValue.Get( hintString ) )
173             {
174               hints |= static_cast< int >( HintFromString( hintString ) );
175             }
176             else
177             {
178               DALI_LOG_ERROR( "'%s' parameter does not correctly specify an hint string at index %d", CUSTOM_SHADER_HINTS, i );
179             }
180
181             mHints = static_cast< Shader::ShaderHints >( hints );
182           }
183         }
184         else
185         {
186           DALI_LOG_ERROR( "'%s' parameter does not correctly specify a hint string or an array of hint strings", CUSTOM_SHADER_HINTS );
187         }
188       }
189     }
190     else
191     {
192       //use value with no type to mean reseting the shader back to default
193       if( shaderValue->GetType() != Dali::Property::NONE )
194       {
195         DALI_LOG_ERROR( "'%s' parameter does not correctly specify a property map", CUSTOM_SHADER );
196       }
197     }
198   }
199 }
200
201 void Internal::ControlRenderer::Impl::CustomShader::CreatePropertyMap( Property::Map& map ) const
202 {
203   if( !mVertexShader.empty() || !mFragmentShader.empty() )
204   {
205     Property::Map customShader;
206     if( !mVertexShader.empty() )
207     {
208       customShader.Insert(CUSTOM_VERTEX_SHADER, mVertexShader );
209     }
210     if( !mFragmentShader.empty() )
211     {
212       customShader.Insert(CUSTOM_FRAGMENT_SHADER, mFragmentShader );
213     }
214
215     if( mGridSize.GetWidth() != 1 )
216     {
217       customShader.Insert(CUSTOM_SUBDIVIDE_GRID_X, mGridSize.GetWidth() );
218     }
219     if( mGridSize.GetHeight() != 1 )
220     {
221       customShader.Insert(CUSTOM_SUBDIVIDE_GRID_Y, mGridSize.GetHeight() );
222     }
223
224     if( mHints != Dali::Shader::HINT_NONE )
225     {
226       customShader.Insert(CUSTOM_SHADER_HINTS, static_cast< int >(mHints) );
227     }
228
229     map.Insert( CUSTOM_SHADER, customShader );
230   }
231 }
232
233 } // namespace Internal
234
235 } // namespace Toolkit
236
237 } // namespace Dali