[dali_1.1.9] Merge branch 'devel/master'
[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  *   "requiresSelfDepthTest"   | corresponds to HINT_REQUIRES_SELF_DEPTH_TEST
51  *   "outputIsTransparent"     | corresponds to HINT_OUTPUT_IS_TRANSPARENT
52  *   "outputIsOpaque"          | corresponds to HINT_OUTPUT_IS_OPAQUE
53  *   "modifiesGeometry"        | corresponds to HINT_MODIFIES_GEOMETRY
54  */
55
56 Shader::ShaderHints HintFromString( std::string hintString )
57 {
58   if( hintString == "none" )
59   {
60     return Shader::HINT_NONE;
61   }
62   else if( hintString == "requiresSelfDepthTest" )
63   {
64     return Shader::HINT_REQUIRES_SELF_DEPTH_TEST;
65   }
66   else if( hintString == "outputIsTransparent" )
67   {
68     return Shader::HINT_OUTPUT_IS_TRANSPARENT;
69   }
70   else if( hintString == "outputIsOpaque" )
71   {
72     return Shader::HINT_OUTPUT_IS_OPAQUE;
73   }
74   else if( hintString == "modifiesGeometry" )
75   {
76     return Shader::HINT_MODIFIES_GEOMETRY;
77   }
78   else
79   {
80     DALI_LOG_ERROR( "'%s' hint string is not recognised", hintString.c_str() );
81   }
82
83   return Shader::HINT_NONE;
84 }
85
86 }// unnamed namespace
87
88 Internal::ControlRenderer::Impl::Impl()
89 : mCustomShader(NULL),
90   mDepthIndex( 0.0f ),
91   mFlags( 0 )
92 {
93 }
94
95 Internal::ControlRenderer::Impl::~Impl()
96 {
97   delete mCustomShader;
98 }
99
100 Internal::ControlRenderer::Impl::CustomShader::CustomShader( const Property::Map& map )
101 : mGridSize( 1, 1 ),
102   mHints( Shader::HINT_NONE )
103 {
104   SetPropertyMap( map );
105 }
106
107 void Internal::ControlRenderer::Impl::CustomShader::SetPropertyMap( const Property::Map& propertyMap )
108 {
109   Property::Value* shaderValue = propertyMap.Find( CUSTOM_SHADER );
110   if( shaderValue )
111   {
112     mVertexShader.clear();
113     mFragmentShader.clear();
114     mGridSize = ImageDimensions( 1, 1 );
115     mHints = Shader::HINT_NONE;
116
117     Property::Map shaderMap;
118     if( shaderValue->Get( shaderMap ) )
119     {
120       Property::Value* vertexShaderValue = shaderMap.Find( CUSTOM_VERTEX_SHADER );
121       if( vertexShaderValue )
122       {
123         if( !vertexShaderValue->Get( mVertexShader ) )
124         {
125           DALI_LOG_ERROR( "'%s' parameter does not correctly specify a string", CUSTOM_VERTEX_SHADER );
126         }
127       }
128
129       Property::Value* fragmentShaderValue = shaderMap.Find( CUSTOM_FRAGMENT_SHADER );
130       if( fragmentShaderValue )
131       {
132         if( !fragmentShaderValue->Get( mFragmentShader ) )
133         {
134           DALI_LOG_ERROR( "'%s' parameter does not correctly specify a string", CUSTOM_FRAGMENT_SHADER );
135         }
136       }
137
138       Property::Value* subdivideXValue = shaderMap.Find( CUSTOM_SUBDIVIDE_GRID_X );
139       if( subdivideXValue )
140       {
141         int subdivideX;
142         if( !subdivideXValue->Get( subdivideX ) || subdivideX < 1 )
143         {
144           DALI_LOG_ERROR( "'%s' parameter does not correctly specify a value greater than 1", CUSTOM_SUBDIVIDE_GRID_X );
145         }
146         else
147         {
148           mGridSize = ImageDimensions( subdivideX, mGridSize.GetY() );
149         }
150       }
151
152       Property::Value* subdivideYValue = shaderMap.Find( CUSTOM_SUBDIVIDE_GRID_Y );
153       if( subdivideYValue )
154       {
155         int subdivideY;
156         if( !subdivideYValue->Get( subdivideY ) || subdivideY < 1 )
157         {
158           DALI_LOG_ERROR( "'%s' parameter does not correctly specify a value greater than 1", CUSTOM_SUBDIVIDE_GRID_Y );
159         }
160         else
161         {
162           mGridSize = ImageDimensions( mGridSize.GetX(), subdivideY );
163         }
164       }
165
166       Property::Value* hintsValue = shaderMap.Find( CUSTOM_SHADER_HINTS );
167       if( hintsValue )
168       {
169         std::string hintString;
170         Property::Array hintsArray;
171
172         if( hintsValue->Get( hintString ) )
173         {
174           mHints = HintFromString( hintString );
175         }
176         else if( hintsValue->Get( hintsArray ) )
177         {
178           int hints = Shader::HINT_NONE;
179           for( Property::Array::SizeType i = 0; i < hintsArray.Count(); ++i)
180           {
181             Property::Value hintValue = hintsArray[ i ];
182             if( hintValue.Get( hintString ) )
183             {
184               hints |= static_cast< int >( HintFromString( hintString ) );
185             }
186             else
187             {
188               DALI_LOG_ERROR( "'%s' parameter does not correctly specify an hint string at index %d", CUSTOM_SHADER_HINTS, i );
189             }
190
191             mHints = static_cast< Shader::ShaderHints >( hints );
192           }
193         }
194         else
195         {
196           DALI_LOG_ERROR( "'%s' parameter does not correctly specify a hint string or an array of hint strings", CUSTOM_SHADER_HINTS );
197         }
198       }
199     }
200     else
201     {
202       //use value with no type to mean reseting the shader back to default
203       if( shaderValue->GetType() != Dali::Property::NONE )
204       {
205         DALI_LOG_ERROR( "'%s' parameter does not correctly specify a property map", CUSTOM_SHADER );
206       }
207     }
208   }
209 }
210
211 void Internal::ControlRenderer::Impl::CustomShader::CreatePropertyMap( Property::Map& map ) const
212 {
213   if( !mVertexShader.empty() || !mFragmentShader.empty() )
214   {
215     Property::Map customShader;
216     if( !mVertexShader.empty() )
217     {
218       customShader.Insert(CUSTOM_VERTEX_SHADER, mVertexShader );
219     }
220     if( !mFragmentShader.empty() )
221     {
222       customShader.Insert(CUSTOM_FRAGMENT_SHADER, mFragmentShader );
223     }
224
225     if( mGridSize.GetWidth() != 1 )
226     {
227       customShader.Insert(CUSTOM_SUBDIVIDE_GRID_X, mGridSize.GetWidth() );
228     }
229     if( mGridSize.GetHeight() != 1 )
230     {
231       customShader.Insert(CUSTOM_SUBDIVIDE_GRID_Y, mGridSize.GetHeight() );
232     }
233
234     if( mHints != Dali::Shader::HINT_NONE )
235     {
236       customShader.Insert(CUSTOM_SHADER_HINTS, static_cast< int >(mHints) );
237     }
238
239     map.Insert( CUSTOM_SHADER, customShader );
240   }
241 }
242
243 } // namespace Internal
244
245 } // namespace Toolkit
246
247 } // namespace Dali