6080bd2c01f872300d62316cab1ed7ae71fa7769
[platform/core/uifw/dali-toolkit.git] / plugins / dali-script-v8 / src / rendering / shader-api.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
19 // CLASS HEADER
20 #include "shader-api.h"
21
22 // EXTERNAL INCLUDES
23 #include <dali/public-api/object/type-registry.h>
24
25 // INTERNAL INCLUDES
26 #include <v8-utils.h>
27 #include <rendering/shader-wrapper.h>
28
29 namespace Dali
30 {
31
32 namespace V8Plugin
33 {
34
35 /**
36  * ## Shader API
37  *
38  * Shaders allows custom vertex and color transformations in the GPU
39  *
40  * ### Simple example
41  *
42  *```
43  *    // this will match the default shaders for image
44  *    var vertexShader = " void main() \
45  *    { \
46  *      gl_Position = uProjection * uModelView * vec4(aPosition, 1.0); \
47  *      vTexCoord = aTexCoord; \
48  *    }; "
49  *   var fragShader = " void main() \
50  *    { \
51  *     gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\
52  *    }; "
53  *    var shaderOptions = {
54  *          vertexShader: vertexShader,
55  *          fragmentShader: fragShader
56  *    };
57  *
58  *    var shader = new dali.Shader(shaderOptions);
59  *```
60  * @class Shader
61  * @extends Handle
62  */
63
64 namespace // unnamed namespace
65 {
66
67 typedef  std::vector< std::string > HintsArray;
68
69 struct ShaderHintPair
70 {
71   const char* name;
72   Shader::ShaderHints hint;
73 };
74
75 const ShaderHintPair ShaderHintTable[]=
76 {
77     {"requiresSelfDepthTest",  Shader::HINT_REQUIRES_SELF_DEPTH_TEST },
78     {"outputIsTransparent",    Shader::HINT_OUTPUT_IS_TRANSPARENT },
79     {"outputIsOpaque",         Shader::HINT_OUTPUT_IS_OPAQUE   },
80     {"modifiesGeometry",       Shader::HINT_MODIFIES_GEOMETRY },
81 };
82
83 const unsigned int ShaderHintTableCount = sizeof(ShaderHintTable)/sizeof(ShaderHintTable[0]);
84
85 struct ShaderParameters
86 {
87   ShaderParameters()
88       : mHints( Shader::HINT_NONE )
89   {
90   }
91
92   Shader::ShaderHints GetShaderHint( const std::string& hint )
93   {
94     for( unsigned int i = 0 ; i < ShaderHintTableCount; ++i )
95     {
96       if( hint == ShaderHintTable[i].name )
97       {
98         return ShaderHintTable[i].hint;
99       }
100     }
101     return Shader::HINT_NONE;
102   }
103
104   void ProcessHintsArray( const HintsArray& hintsArray )
105   {
106     for( HintsArray::const_iterator iter  = hintsArray.begin(); iter != hintsArray.end() ; ++iter )
107     {
108       mHints= static_cast<Shader::ShaderHints>( mHints | GetShaderHint( *iter ) );
109     }
110   }
111
112   Shader NewShader()
113   {
114     return Shader::New( mVertex,
115                          mFragment,
116                          mHints);
117   }
118
119   std::string mVertex;
120   std::string mFragment;
121   Shader::ShaderHints mHints;
122 };
123
124 Shader GetShader( v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args )
125 {
126   v8::HandleScope handleScope( isolate );
127
128   v8::Local<v8::Object> object = args.This();
129   v8::Local<v8::External> field = v8::Local<v8::External>::Cast( object->GetInternalField(0) );
130   void* ptr = field->Value();
131
132   ShaderWrapper* wrapper = static_cast< ShaderWrapper *>(ptr);
133   return wrapper->GetShader();
134 }
135
136 } // unnamed space
137
138 /**
139  * Create a new Shader
140  * @constructor
141  * @for Shader
142  * @method Shader
143  * @param {Object} shaderOptions
144  * @param {String} [shaderOptions.vertexShader] VertexShader code for the shader. If not defined, the default version will be used
145  * @param {String} [shaderOptions.fragmentShader] FragmentShader code for the shader. If not defined, the default version will be used
146  * @param {Array}  [shaderOptions.shaderHints] Hints for rendering/subdividing geometry, e.g.  [ "requiresSelfDepthTest", "outputIsTransparent", "outputIsOpaque","modifiesGeometry" ]
147  * @return {Object} Shader
148  * @example
149
150       // this will match the default shaders for image
151       var vertexShader = " void main() \
152       { \
153         gl_Position = uProjection * uModelView * vec4(aPosition, 1.0); \
154         vTexCoord = aTexCoord; \
155       }; "
156
157       var fragShader = " void main() \
158       { \
159        gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\
160       }; "
161
162       var shaderOptions = {
163             vertexShader: vertexShader,
164             fragmentShader: fragShader
165       };
166
167       var shader = new dali.Shader(shaderOptions);
168  *
169  */
170 Shader ShaderApi::New(  v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args )
171 {
172   v8::HandleScope handleScope( isolate );
173
174   ShaderParameters shaderParams;
175
176   if( args[0]->IsObject() )
177   {
178     v8::Local<v8::Object > obj = args[0]->ToObject();
179
180     v8::Local<v8::Value> vertexValue = obj->Get(v8::String::NewFromUtf8( isolate, "vertexShader"));
181     if( vertexValue->IsString() )
182     {
183       shaderParams.mVertex = V8Utils::v8StringToStdString( vertexValue );
184     }
185
186     v8::Local<v8::Value> fragmentValue = obj->Get(v8::String::NewFromUtf8( isolate, "fragmentShader"));
187     if( fragmentValue->IsString() )
188     {
189       shaderParams.mFragment = V8Utils::v8StringToStdString( fragmentValue );
190     }
191     // Get any hints
192     v8::Local<v8::Value> hints = obj->Get(v8::String::NewFromUtf8( isolate, "shaderHints"));
193     if( hints->IsArray() )
194     {
195       HintsArray hintsArray;
196       v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast( hints );
197       for( uint32_t i=0; i <  array->Length(); ++i)
198       {
199         v8::Handle<v8::Value> entry = array->Get(  v8::Integer::New( isolate, i) );
200         if( entry->IsString() )
201         {
202           std::string entryString = V8Utils::v8StringToStdString( entry );
203           hintsArray.push_back( entryString );
204         }
205       }
206       shaderParams.ProcessHintsArray( hintsArray );
207     }
208   }
209
210   return shaderParams.NewShader();
211 }
212
213 Shader ShaderApi::GetShaderFromParams( int paramIndex,
214                           bool& found,
215                           v8::Isolate* isolate,
216                           const v8::FunctionCallbackInfo< v8::Value >& args )
217 {
218   found = false;
219
220   v8::HandleScope handleScope( isolate );
221   BaseWrappedObject* wrappedObject = V8Utils::GetWrappedDaliObjectParameter( paramIndex, BaseWrappedObject::SHADER, isolate, args );
222   if( wrappedObject )
223   {
224     found = true;
225     ShaderWrapper* wrapper = static_cast< ShaderWrapper *>(wrappedObject);
226     return wrapper->GetShader();
227   }
228   else
229   {
230     return Shader();
231   }
232 }
233
234 } // namespace V8Plugin
235
236 } // namespace Dali