• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "config.h"
32 
33 #if ENABLE(WEBGL)
34 
35 #include "V8WebGLRenderingContext.h"
36 
37 #include "ExceptionCode.h"
38 #include "NotImplemented.h"
39 #include "V8ArrayBufferView.h"
40 #include "V8Binding.h"
41 #include "V8BindingMacros.h"
42 #include "V8WebKitLoseContext.h"
43 #include "V8Float32Array.h"
44 #include "V8HTMLCanvasElement.h"
45 #include "V8HTMLImageElement.h"
46 #include "V8HTMLVideoElement.h"
47 #include "V8ImageData.h"
48 #include "V8Int16Array.h"
49 #include "V8Int32Array.h"
50 #include "V8Int8Array.h"
51 #include "V8OESStandardDerivatives.h"
52 #include "V8OESTextureFloat.h"
53 #include "V8OESVertexArrayObject.h"
54 #include "V8Proxy.h"
55 #include "V8Uint16Array.h"
56 #include "V8Uint32Array.h"
57 #include "V8Uint8Array.h"
58 #include "V8WebGLBuffer.h"
59 #include "V8WebGLFramebuffer.h"
60 #include "V8WebGLProgram.h"
61 #include "V8WebGLRenderbuffer.h"
62 #include "V8WebGLShader.h"
63 #include "V8WebGLTexture.h"
64 #include "V8WebGLUniformLocation.h"
65 #include "V8WebGLVertexArrayObjectOES.h"
66 #include "WebGLRenderingContext.h"
67 #include <wtf/FastMalloc.h>
68 
69 namespace WebCore {
70 
71 // Allocates new storage via tryFastMalloc.
72 // Returns NULL if array failed to convert for any reason.
jsArrayToFloatArray(v8::Handle<v8::Array> array,uint32_t len)73 static float* jsArrayToFloatArray(v8::Handle<v8::Array> array, uint32_t len)
74 {
75     // Convert the data element-by-element.
76     float* data;
77     if (!tryFastMalloc(len * sizeof(float)).getValue(data))
78         return 0;
79     for (uint32_t i = 0; i < len; i++) {
80         v8::Local<v8::Value> val = array->Get(v8::Integer::New(i));
81         if (!val->IsNumber()) {
82             fastFree(data);
83             return 0;
84         }
85         data[i] = toFloat(val);
86     }
87     return data;
88 }
89 
90 // Allocates new storage via tryFastMalloc.
91 // Returns NULL if array failed to convert for any reason.
jsArrayToIntArray(v8::Handle<v8::Array> array,uint32_t len)92 static int* jsArrayToIntArray(v8::Handle<v8::Array> array, uint32_t len)
93 {
94     // Convert the data element-by-element.
95     int* data;
96     if (!tryFastMalloc(len * sizeof(int)).getValue(data))
97         return 0;
98     for (uint32_t i = 0; i < len; i++) {
99         v8::Local<v8::Value> val = array->Get(v8::Integer::New(i));
100         bool ok;
101         int ival = toInt32(val, ok);
102         if (!ok) {
103             fastFree(data);
104             return 0;
105         }
106         data[i] = ival;
107     }
108     return data;
109 }
110 
toV8Object(const WebGLGetInfo & info)111 static v8::Handle<v8::Value> toV8Object(const WebGLGetInfo& info)
112 {
113     switch (info.getType()) {
114     case WebGLGetInfo::kTypeBool:
115         return v8::Boolean::New(info.getBool());
116     case WebGLGetInfo::kTypeBoolArray: {
117         const Vector<bool>& value = info.getBoolArray();
118         v8::Local<v8::Array> array = v8::Array::New(value.size());
119         for (size_t ii = 0; ii < value.size(); ++ii)
120             array->Set(v8::Integer::New(ii), v8::Boolean::New(value[ii]));
121         return array;
122     }
123     case WebGLGetInfo::kTypeFloat:
124         return v8::Number::New(info.getFloat());
125     case WebGLGetInfo::kTypeInt:
126         return v8::Integer::New(info.getInt());
127     case WebGLGetInfo::kTypeNull:
128         return v8::Null();
129     case WebGLGetInfo::kTypeString:
130         return v8::String::New(fromWebCoreString(info.getString()), info.getString().length());
131     case WebGLGetInfo::kTypeUnsignedInt:
132         return v8::Integer::NewFromUnsigned(info.getUnsignedInt());
133     case WebGLGetInfo::kTypeWebGLBuffer:
134         return toV8(info.getWebGLBuffer());
135     case WebGLGetInfo::kTypeWebGLFloatArray:
136         return toV8(info.getWebGLFloatArray());
137     case WebGLGetInfo::kTypeWebGLFramebuffer:
138         return toV8(info.getWebGLFramebuffer());
139     case WebGLGetInfo::kTypeWebGLIntArray:
140         return toV8(info.getWebGLIntArray());
141     // FIXME: implement WebGLObjectArray
142     // case WebGLGetInfo::kTypeWebGLObjectArray:
143     case WebGLGetInfo::kTypeWebGLProgram:
144         return toV8(info.getWebGLProgram());
145     case WebGLGetInfo::kTypeWebGLRenderbuffer:
146         return toV8(info.getWebGLRenderbuffer());
147     case WebGLGetInfo::kTypeWebGLTexture:
148         return toV8(info.getWebGLTexture());
149     case WebGLGetInfo::kTypeWebGLUnsignedByteArray:
150         return toV8(info.getWebGLUnsignedByteArray());
151     case WebGLGetInfo::kTypeWebGLVertexArrayObjectOES:
152         return toV8(info.getWebGLVertexArrayObjectOES());
153     default:
154         notImplemented();
155         return v8::Undefined();
156     }
157 }
158 
toV8Object(WebGLExtension * extension,v8::Handle<v8::Object> contextObject)159 static v8::Handle<v8::Value> toV8Object(WebGLExtension* extension, v8::Handle<v8::Object> contextObject)
160 {
161     if (!extension)
162         return v8::Null();
163     v8::Handle<v8::Value> extensionObject;
164     const char* referenceName;
165     switch (extension->getName()) {
166     case WebGLExtension::WebKitLoseContextName:
167         extensionObject = toV8(static_cast<WebKitLoseContext*>(extension));
168         referenceName = "webKitLoseContextName";
169         break;
170     case WebGLExtension::OESStandardDerivativesName:
171         extensionObject = toV8(static_cast<OESStandardDerivatives*>(extension));
172         referenceName = "oesStandardDerivativesName";
173         break;
174     case WebGLExtension::OESTextureFloatName:
175         extensionObject = toV8(static_cast<OESTextureFloat*>(extension));
176         referenceName = "oesTextureFloatName";
177         break;
178     case WebGLExtension::OESVertexArrayObjectName:
179         extensionObject = toV8(static_cast<OESVertexArrayObject*>(extension));
180         referenceName = "oesVertexArrayObjectName";
181         break;
182     }
183     ASSERT(!extensionObject.IsEmpty());
184     V8DOMWrapper::setNamedHiddenReference(contextObject, referenceName, extensionObject);
185     return extensionObject;
186 }
187 
188 enum ObjectType {
189     kBuffer, kRenderbuffer, kTexture, kVertexAttrib
190 };
191 
getObjectParameter(const v8::Arguments & args,ObjectType objectType)192 static v8::Handle<v8::Value> getObjectParameter(const v8::Arguments& args, ObjectType objectType)
193 {
194     if (args.Length() != 2) {
195         V8Proxy::setDOMException(SYNTAX_ERR);
196         return notHandledByInterceptor();
197     }
198 
199     ExceptionCode ec = 0;
200     WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
201     unsigned target = toInt32(args[0]);
202     unsigned pname = toInt32(args[1]);
203     WebGLGetInfo info;
204     switch (objectType) {
205     case kBuffer:
206         info = context->getBufferParameter(target, pname, ec);
207         break;
208     case kRenderbuffer:
209         info = context->getRenderbufferParameter(target, pname, ec);
210         break;
211     case kTexture:
212         info = context->getTexParameter(target, pname, ec);
213         break;
214     case kVertexAttrib:
215         // target => index
216         info = context->getVertexAttrib(target, pname, ec);
217         break;
218     default:
219         notImplemented();
220         break;
221     }
222     if (ec) {
223         V8Proxy::setDOMException(ec);
224         return v8::Undefined();
225     }
226     return toV8Object(info);
227 }
228 
toWebGLUniformLocation(v8::Handle<v8::Value> value,bool & ok)229 static WebGLUniformLocation* toWebGLUniformLocation(v8::Handle<v8::Value> value, bool& ok)
230 {
231     ok = false;
232     WebGLUniformLocation* location = 0;
233     if (V8WebGLUniformLocation::HasInstance(value)) {
234         location = V8WebGLUniformLocation::toNative(value->ToObject());
235         ok = true;
236     }
237     return location;
238 }
239 
240 enum WhichProgramCall {
241     kProgramParameter, kUniform
242 };
243 
getAttachedShadersCallback(const v8::Arguments & args)244 v8::Handle<v8::Value> V8WebGLRenderingContext::getAttachedShadersCallback(const v8::Arguments& args)
245 {
246     INC_STATS("DOM.WebGLRenderingContext.getAttachedShaders()");
247 
248     if (args.Length() < 1) {
249         V8Proxy::setDOMException(SYNTAX_ERR);
250         return notHandledByInterceptor();
251     }
252 
253     ExceptionCode ec = 0;
254     WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
255     if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLProgram::HasInstance(args[0])) {
256         V8Proxy::throwTypeError();
257         return notHandledByInterceptor();
258     }
259     WebGLProgram* program = V8WebGLProgram::HasInstance(args[0]) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
260     Vector<WebGLShader*> shaders;
261     bool succeed = context->getAttachedShaders(program, shaders, ec);
262     if (ec) {
263         V8Proxy::setDOMException(ec);
264         return v8::Null();
265     }
266     if (!succeed)
267         return v8::Null();
268     v8::Local<v8::Array> array = v8::Array::New(shaders.size());
269     for (size_t ii = 0; ii < shaders.size(); ++ii)
270         array->Set(v8::Integer::New(ii), toV8(shaders[ii]));
271     return array;
272 }
273 
getBufferParameterCallback(const v8::Arguments & args)274 v8::Handle<v8::Value> V8WebGLRenderingContext::getBufferParameterCallback(const v8::Arguments& args)
275 {
276     INC_STATS("DOM.WebGLRenderingContext.getBufferParameter()");
277     return getObjectParameter(args, kBuffer);
278 }
279 
getExtensionCallback(const v8::Arguments & args)280 v8::Handle<v8::Value> V8WebGLRenderingContext::getExtensionCallback(const v8::Arguments& args)
281 {
282     INC_STATS("DOM.WebGLRenderingContext.getExtensionCallback()");
283     WebGLRenderingContext* imp = V8WebGLRenderingContext::toNative(args.Holder());
284     if (args.Length() < 1) {
285         V8Proxy::setDOMException(SYNTAX_ERR);
286         return notHandledByInterceptor();
287     }
288     STRING_TO_V8PARAMETER_EXCEPTION_BLOCK(V8Parameter<>, name, args[0]);
289     WebGLExtension* extension = imp->getExtension(name);
290     return toV8Object(extension, args.Holder());
291 }
292 
getFramebufferAttachmentParameterCallback(const v8::Arguments & args)293 v8::Handle<v8::Value> V8WebGLRenderingContext::getFramebufferAttachmentParameterCallback(const v8::Arguments& args)
294 {
295     INC_STATS("DOM.WebGLRenderingContext.getFramebufferAttachmentParameter()");
296 
297     if (args.Length() != 3) {
298         V8Proxy::setDOMException(SYNTAX_ERR);
299         return notHandledByInterceptor();
300     }
301 
302     ExceptionCode ec = 0;
303     WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
304     unsigned target = toInt32(args[0]);
305     unsigned attachment = toInt32(args[1]);
306     unsigned pname = toInt32(args[2]);
307     WebGLGetInfo info = context->getFramebufferAttachmentParameter(target, attachment, pname, ec);
308     if (ec) {
309         V8Proxy::setDOMException(ec);
310         return v8::Undefined();
311     }
312     return toV8Object(info);
313 }
314 
getParameterCallback(const v8::Arguments & args)315 v8::Handle<v8::Value> V8WebGLRenderingContext::getParameterCallback(const v8::Arguments& args)
316 {
317     INC_STATS("DOM.WebGLRenderingContext.getParameter()");
318 
319     if (args.Length() != 1) {
320         V8Proxy::setDOMException(SYNTAX_ERR);
321         return notHandledByInterceptor();
322     }
323 
324     ExceptionCode ec = 0;
325     WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
326     unsigned pname = toInt32(args[0]);
327     WebGLGetInfo info = context->getParameter(pname, ec);
328     if (ec) {
329         V8Proxy::setDOMException(ec);
330         return v8::Undefined();
331     }
332     return toV8Object(info);
333 }
334 
getProgramParameterCallback(const v8::Arguments & args)335 v8::Handle<v8::Value> V8WebGLRenderingContext::getProgramParameterCallback(const v8::Arguments& args)
336 {
337     INC_STATS("DOM.WebGLRenderingContext.getProgramParameter()");
338 
339     if (args.Length() != 2) {
340         V8Proxy::setDOMException(SYNTAX_ERR);
341         return notHandledByInterceptor();
342     }
343 
344     ExceptionCode ec = 0;
345     WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
346     if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLProgram::HasInstance(args[0])) {
347         V8Proxy::throwTypeError();
348         return notHandledByInterceptor();
349     }
350     WebGLProgram* program = V8WebGLProgram::HasInstance(args[0]) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
351     unsigned pname = toInt32(args[1]);
352     WebGLGetInfo info = context->getProgramParameter(program, pname, ec);
353     if (ec) {
354         V8Proxy::setDOMException(ec);
355         return v8::Undefined();
356     }
357     return toV8Object(info);
358 }
359 
getRenderbufferParameterCallback(const v8::Arguments & args)360 v8::Handle<v8::Value> V8WebGLRenderingContext::getRenderbufferParameterCallback(const v8::Arguments& args)
361 {
362     INC_STATS("DOM.WebGLRenderingContext.getRenderbufferParameter()");
363     return getObjectParameter(args, kRenderbuffer);
364 }
365 
getShaderParameterCallback(const v8::Arguments & args)366 v8::Handle<v8::Value> V8WebGLRenderingContext::getShaderParameterCallback(const v8::Arguments& args)
367 {
368     INC_STATS("DOM.WebGLRenderingContext.getShaderParameter()");
369 
370     if (args.Length() != 2) {
371         V8Proxy::setDOMException(SYNTAX_ERR);
372         return notHandledByInterceptor();
373     }
374 
375     ExceptionCode ec = 0;
376     WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
377     if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLShader::HasInstance(args[0])) {
378         V8Proxy::throwTypeError();
379         return notHandledByInterceptor();
380     }
381     WebGLShader* shader = V8WebGLShader::HasInstance(args[0]) ? V8WebGLShader::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
382     unsigned pname = toInt32(args[1]);
383     WebGLGetInfo info = context->getShaderParameter(shader, pname, ec);
384     if (ec) {
385         V8Proxy::setDOMException(ec);
386         return v8::Undefined();
387     }
388     return toV8Object(info);
389 }
390 
getSupportedExtensionsCallback(const v8::Arguments & args)391 v8::Handle<v8::Value> V8WebGLRenderingContext::getSupportedExtensionsCallback(const v8::Arguments& args)
392 {
393     INC_STATS("DOM.WebGLRenderingContext.getSupportedExtensionsCallback()");
394     WebGLRenderingContext* imp = V8WebGLRenderingContext::toNative(args.Holder());
395     if (imp->isContextLost())
396         return v8::Null();
397 
398     Vector<String> value = imp->getSupportedExtensions();
399     v8::Local<v8::Array> array = v8::Array::New(value.size());
400     for (size_t ii = 0; ii < value.size(); ++ii)
401         array->Set(v8::Integer::New(ii), v8::String::New(fromWebCoreString(value[ii]), value[ii].length()));
402     return array;
403 }
404 
getTexParameterCallback(const v8::Arguments & args)405 v8::Handle<v8::Value> V8WebGLRenderingContext::getTexParameterCallback(const v8::Arguments& args)
406 {
407     INC_STATS("DOM.WebGLRenderingContext.getTexParameter()");
408     return getObjectParameter(args, kTexture);
409 }
410 
getUniformCallback(const v8::Arguments & args)411 v8::Handle<v8::Value> V8WebGLRenderingContext::getUniformCallback(const v8::Arguments& args)
412 {
413     INC_STATS("DOM.WebGLRenderingContext.getUniform()");
414 
415     if (args.Length() != 2) {
416         V8Proxy::setDOMException(SYNTAX_ERR);
417         return notHandledByInterceptor();
418     }
419 
420     ExceptionCode ec = 0;
421     WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
422     if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLProgram::HasInstance(args[0])) {
423         V8Proxy::throwTypeError();
424         return notHandledByInterceptor();
425     }
426     WebGLProgram* program = V8WebGLProgram::HasInstance(args[0]) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
427 
428     if (args.Length() > 1 && !isUndefinedOrNull(args[1]) && !V8WebGLUniformLocation::HasInstance(args[1])) {
429         V8Proxy::throwTypeError();
430         return notHandledByInterceptor();
431     }
432     bool ok = false;
433     WebGLUniformLocation* location = toWebGLUniformLocation(args[1], ok);
434 
435     WebGLGetInfo info = context->getUniform(program, location, ec);
436     if (ec) {
437         V8Proxy::setDOMException(ec);
438         return v8::Undefined();
439     }
440     return toV8Object(info);
441 }
442 
getVertexAttribCallback(const v8::Arguments & args)443 v8::Handle<v8::Value> V8WebGLRenderingContext::getVertexAttribCallback(const v8::Arguments& args)
444 {
445     INC_STATS("DOM.WebGLRenderingContext.getVertexAttrib()");
446     return getObjectParameter(args, kVertexAttrib);
447 }
448 
449 enum FunctionToCall {
450     kUniform1v, kUniform2v, kUniform3v, kUniform4v,
451     kVertexAttrib1v, kVertexAttrib2v, kVertexAttrib3v, kVertexAttrib4v
452 };
453 
isFunctionToCallForAttribute(FunctionToCall functionToCall)454 bool isFunctionToCallForAttribute(FunctionToCall functionToCall)
455 {
456     switch (functionToCall) {
457     case kVertexAttrib1v:
458     case kVertexAttrib2v:
459     case kVertexAttrib3v:
460     case kVertexAttrib4v:
461         return true;
462     default:
463         break;
464     }
465     return false;
466 }
467 
vertexAttribAndUniformHelperf(const v8::Arguments & args,FunctionToCall functionToCall)468 static v8::Handle<v8::Value> vertexAttribAndUniformHelperf(const v8::Arguments& args,
469                                                            FunctionToCall functionToCall) {
470     // Forms:
471     // * glUniform1fv(WebGLUniformLocation location, Array data);
472     // * glUniform1fv(WebGLUniformLocation location, Float32Array data);
473     // * glUniform2fv(WebGLUniformLocation location, Array data);
474     // * glUniform2fv(WebGLUniformLocation location, Float32Array data);
475     // * glUniform3fv(WebGLUniformLocation location, Array data);
476     // * glUniform3fv(WebGLUniformLocation location, Float32Array data);
477     // * glUniform4fv(WebGLUniformLocation location, Array data);
478     // * glUniform4fv(WebGLUniformLocation location, Float32Array data);
479     // * glVertexAttrib1fv(GLint index, Array data);
480     // * glVertexAttrib1fv(GLint index, Float32Array data);
481     // * glVertexAttrib2fv(GLint index, Array data);
482     // * glVertexAttrib2fv(GLint index, Float32Array data);
483     // * glVertexAttrib3fv(GLint index, Array data);
484     // * glVertexAttrib3fv(GLint index, Float32Array data);
485     // * glVertexAttrib4fv(GLint index, Array data);
486     // * glVertexAttrib4fv(GLint index, Float32Array data);
487 
488     if (args.Length() != 2) {
489         V8Proxy::setDOMException(SYNTAX_ERR);
490         return notHandledByInterceptor();
491     }
492 
493     bool ok = false;
494     int index = -1;
495     WebGLUniformLocation* location = 0;
496 
497     if (isFunctionToCallForAttribute(functionToCall))
498         index = toInt32(args[0]);
499     else {
500         if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLUniformLocation::HasInstance(args[0])) {
501             V8Proxy::throwTypeError();
502             return notHandledByInterceptor();
503         }
504         location = toWebGLUniformLocation(args[0], ok);
505     }
506 
507     WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
508 
509     if (V8Float32Array::HasInstance(args[1])) {
510         Float32Array* array = V8Float32Array::toNative(args[1]->ToObject());
511         ASSERT(array != NULL);
512         ExceptionCode ec = 0;
513         switch (functionToCall) {
514             case kUniform1v: context->uniform1fv(location, array, ec); break;
515             case kUniform2v: context->uniform2fv(location, array, ec); break;
516             case kUniform3v: context->uniform3fv(location, array, ec); break;
517             case kUniform4v: context->uniform4fv(location, array, ec); break;
518             case kVertexAttrib1v: context->vertexAttrib1fv(index, array); break;
519             case kVertexAttrib2v: context->vertexAttrib2fv(index, array); break;
520             case kVertexAttrib3v: context->vertexAttrib3fv(index, array); break;
521             case kVertexAttrib4v: context->vertexAttrib4fv(index, array); break;
522             default: ASSERT_NOT_REACHED(); break;
523         }
524         if (ec)
525             V8Proxy::setDOMException(ec);
526         return v8::Undefined();
527     }
528 
529     if (args[1].IsEmpty() || !args[1]->IsArray()) {
530         V8Proxy::throwTypeError();
531         return notHandledByInterceptor();
532     }
533     v8::Handle<v8::Array> array =
534       v8::Local<v8::Array>::Cast(args[1]);
535     uint32_t len = array->Length();
536     float* data = jsArrayToFloatArray(array, len);
537     if (!data) {
538         // FIXME: consider different / better exception type.
539         V8Proxy::setDOMException(SYNTAX_ERR);
540         return notHandledByInterceptor();
541     }
542     ExceptionCode ec = 0;
543     switch (functionToCall) {
544         case kUniform1v: context->uniform1fv(location, data, len, ec); break;
545         case kUniform2v: context->uniform2fv(location, data, len, ec); break;
546         case kUniform3v: context->uniform3fv(location, data, len, ec); break;
547         case kUniform4v: context->uniform4fv(location, data, len, ec); break;
548         case kVertexAttrib1v: context->vertexAttrib1fv(index, data, len); break;
549         case kVertexAttrib2v: context->vertexAttrib2fv(index, data, len); break;
550         case kVertexAttrib3v: context->vertexAttrib3fv(index, data, len); break;
551         case kVertexAttrib4v: context->vertexAttrib4fv(index, data, len); break;
552         default: ASSERT_NOT_REACHED(); break;
553     }
554     fastFree(data);
555     if (ec)
556         V8Proxy::setDOMException(ec);
557     return v8::Undefined();
558 }
559 
uniformHelperi(const v8::Arguments & args,FunctionToCall functionToCall)560 static v8::Handle<v8::Value> uniformHelperi(const v8::Arguments& args,
561                                             FunctionToCall functionToCall) {
562     // Forms:
563     // * glUniform1iv(GLUniformLocation location, Array data);
564     // * glUniform1iv(GLUniformLocation location, Int32Array data);
565     // * glUniform2iv(GLUniformLocation location, Array data);
566     // * glUniform2iv(GLUniformLocation location, Int32Array data);
567     // * glUniform3iv(GLUniformLocation location, Array data);
568     // * glUniform3iv(GLUniformLocation location, Int32Array data);
569     // * glUniform4iv(GLUniformLocation location, Array data);
570     // * glUniform4iv(GLUniformLocation location, Int32Array data);
571 
572     if (args.Length() != 2) {
573         V8Proxy::setDOMException(SYNTAX_ERR);
574         return notHandledByInterceptor();
575     }
576 
577     WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
578     if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLUniformLocation::HasInstance(args[0])) {
579         V8Proxy::throwTypeError();
580         return notHandledByInterceptor();
581     }
582     bool ok = false;
583     WebGLUniformLocation* location = toWebGLUniformLocation(args[0], ok);
584 
585     if (V8Int32Array::HasInstance(args[1])) {
586         Int32Array* array = V8Int32Array::toNative(args[1]->ToObject());
587         ASSERT(array != NULL);
588         ExceptionCode ec = 0;
589         switch (functionToCall) {
590             case kUniform1v: context->uniform1iv(location, array, ec); break;
591             case kUniform2v: context->uniform2iv(location, array, ec); break;
592             case kUniform3v: context->uniform3iv(location, array, ec); break;
593             case kUniform4v: context->uniform4iv(location, array, ec); break;
594             default: ASSERT_NOT_REACHED(); break;
595         }
596         if (ec)
597             V8Proxy::setDOMException(ec);
598         return v8::Undefined();
599     }
600 
601     if (args[1].IsEmpty() || !args[1]->IsArray()) {
602         V8Proxy::throwTypeError();
603         return notHandledByInterceptor();
604     }
605     v8::Handle<v8::Array> array =
606       v8::Local<v8::Array>::Cast(args[1]);
607     uint32_t len = array->Length();
608     int* data = jsArrayToIntArray(array, len);
609     if (!data) {
610         // FIXME: consider different / better exception type.
611         V8Proxy::setDOMException(SYNTAX_ERR);
612         return notHandledByInterceptor();
613     }
614     ExceptionCode ec = 0;
615     switch (functionToCall) {
616         case kUniform1v: context->uniform1iv(location, data, len, ec); break;
617         case kUniform2v: context->uniform2iv(location, data, len, ec); break;
618         case kUniform3v: context->uniform3iv(location, data, len, ec); break;
619         case kUniform4v: context->uniform4iv(location, data, len, ec); break;
620         default: ASSERT_NOT_REACHED(); break;
621     }
622     fastFree(data);
623     if (ec)
624         V8Proxy::setDOMException(ec);
625     return v8::Undefined();
626 }
627 
uniform1fvCallback(const v8::Arguments & args)628 v8::Handle<v8::Value> V8WebGLRenderingContext::uniform1fvCallback(const v8::Arguments& args)
629 {
630     INC_STATS("DOM.WebGLRenderingContext.uniform1fv()");
631     return vertexAttribAndUniformHelperf(args, kUniform1v);
632 }
633 
uniform1ivCallback(const v8::Arguments & args)634 v8::Handle<v8::Value> V8WebGLRenderingContext::uniform1ivCallback(const v8::Arguments& args)
635 {
636     INC_STATS("DOM.WebGLRenderingContext.uniform1iv()");
637     return uniformHelperi(args, kUniform1v);
638 }
639 
uniform2fvCallback(const v8::Arguments & args)640 v8::Handle<v8::Value> V8WebGLRenderingContext::uniform2fvCallback(const v8::Arguments& args)
641 {
642     INC_STATS("DOM.WebGLRenderingContext.uniform2fv()");
643     return vertexAttribAndUniformHelperf(args, kUniform2v);
644 }
645 
uniform2ivCallback(const v8::Arguments & args)646 v8::Handle<v8::Value> V8WebGLRenderingContext::uniform2ivCallback(const v8::Arguments& args)
647 {
648     INC_STATS("DOM.WebGLRenderingContext.uniform2iv()");
649     return uniformHelperi(args, kUniform2v);
650 }
651 
uniform3fvCallback(const v8::Arguments & args)652 v8::Handle<v8::Value> V8WebGLRenderingContext::uniform3fvCallback(const v8::Arguments& args)
653 {
654     INC_STATS("DOM.WebGLRenderingContext.uniform3fv()");
655     return vertexAttribAndUniformHelperf(args, kUniform3v);
656 }
657 
uniform3ivCallback(const v8::Arguments & args)658 v8::Handle<v8::Value> V8WebGLRenderingContext::uniform3ivCallback(const v8::Arguments& args)
659 {
660     INC_STATS("DOM.WebGLRenderingContext.uniform3iv()");
661     return uniformHelperi(args, kUniform3v);
662 }
663 
uniform4fvCallback(const v8::Arguments & args)664 v8::Handle<v8::Value> V8WebGLRenderingContext::uniform4fvCallback(const v8::Arguments& args)
665 {
666     INC_STATS("DOM.WebGLRenderingContext.uniform4fv()");
667     return vertexAttribAndUniformHelperf(args, kUniform4v);
668 }
669 
uniform4ivCallback(const v8::Arguments & args)670 v8::Handle<v8::Value> V8WebGLRenderingContext::uniform4ivCallback(const v8::Arguments& args)
671 {
672     INC_STATS("DOM.WebGLRenderingContext.uniform4iv()");
673     return uniformHelperi(args, kUniform4v);
674 }
675 
uniformMatrixHelper(const v8::Arguments & args,int matrixSize)676 static v8::Handle<v8::Value> uniformMatrixHelper(const v8::Arguments& args,
677                                                  int matrixSize)
678 {
679     // Forms:
680     // * glUniformMatrix2fv(GLint location, GLboolean transpose, Array data);
681     // * glUniformMatrix2fv(GLint location, GLboolean transpose, Float32Array data);
682     // * glUniformMatrix3fv(GLint location, GLboolean transpose, Array data);
683     // * glUniformMatrix3fv(GLint location, GLboolean transpose, Float32Array data);
684     // * glUniformMatrix4fv(GLint location, GLboolean transpose, Array data);
685     // * glUniformMatrix4fv(GLint location, GLboolean transpose, Float32Array data);
686     //
687     // FIXME: need to change to accept Float32Array as well.
688     if (args.Length() != 3) {
689         V8Proxy::setDOMException(SYNTAX_ERR);
690         return notHandledByInterceptor();
691     }
692 
693     WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
694 
695     if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLUniformLocation::HasInstance(args[0])) {
696         V8Proxy::throwTypeError();
697         return notHandledByInterceptor();
698     }
699     bool ok = false;
700     WebGLUniformLocation* location = toWebGLUniformLocation(args[0], ok);
701 
702     bool transpose = args[1]->BooleanValue();
703     if (V8Float32Array::HasInstance(args[2])) {
704         Float32Array* array = V8Float32Array::toNative(args[2]->ToObject());
705         ASSERT(array != NULL);
706         ExceptionCode ec = 0;
707         switch (matrixSize) {
708             case 2: context->uniformMatrix2fv(location, transpose, array, ec); break;
709             case 3: context->uniformMatrix3fv(location, transpose, array, ec); break;
710             case 4: context->uniformMatrix4fv(location, transpose, array, ec); break;
711             default: ASSERT_NOT_REACHED(); break;
712         }
713         if (ec)
714             V8Proxy::setDOMException(ec);
715         return v8::Undefined();
716     }
717 
718     if (args[2].IsEmpty() || !args[2]->IsArray()) {
719         V8Proxy::throwTypeError();
720         return notHandledByInterceptor();
721     }
722     v8::Handle<v8::Array> array =
723       v8::Local<v8::Array>::Cast(args[2]);
724     uint32_t len = array->Length();
725     float* data = jsArrayToFloatArray(array, len);
726     if (!data) {
727         // FIXME: consider different / better exception type.
728         V8Proxy::setDOMException(SYNTAX_ERR);
729         return notHandledByInterceptor();
730     }
731     ExceptionCode ec = 0;
732     switch (matrixSize) {
733         case 2: context->uniformMatrix2fv(location, transpose, data, len, ec); break;
734         case 3: context->uniformMatrix3fv(location, transpose, data, len, ec); break;
735         case 4: context->uniformMatrix4fv(location, transpose, data, len, ec); break;
736         default: ASSERT_NOT_REACHED(); break;
737     }
738     fastFree(data);
739     if (ec)
740         V8Proxy::setDOMException(ec);
741     return v8::Undefined();
742 }
743 
uniformMatrix2fvCallback(const v8::Arguments & args)744 v8::Handle<v8::Value> V8WebGLRenderingContext::uniformMatrix2fvCallback(const v8::Arguments& args)
745 {
746     INC_STATS("DOM.WebGLRenderingContext.uniformMatrix2fv()");
747     return uniformMatrixHelper(args, 2);
748 }
749 
uniformMatrix3fvCallback(const v8::Arguments & args)750 v8::Handle<v8::Value> V8WebGLRenderingContext::uniformMatrix3fvCallback(const v8::Arguments& args)
751 {
752     INC_STATS("DOM.WebGLRenderingContext.uniformMatrix3fv()");
753     return uniformMatrixHelper(args, 3);
754 }
755 
uniformMatrix4fvCallback(const v8::Arguments & args)756 v8::Handle<v8::Value> V8WebGLRenderingContext::uniformMatrix4fvCallback(const v8::Arguments& args)
757 {
758     INC_STATS("DOM.WebGLRenderingContext.uniformMatrix4fv()");
759     return uniformMatrixHelper(args, 4);
760 }
761 
vertexAttrib1fvCallback(const v8::Arguments & args)762 v8::Handle<v8::Value> V8WebGLRenderingContext::vertexAttrib1fvCallback(const v8::Arguments& args)
763 {
764     INC_STATS("DOM.WebGLRenderingContext.vertexAttrib1fv()");
765     return vertexAttribAndUniformHelperf(args, kVertexAttrib1v);
766 }
767 
vertexAttrib2fvCallback(const v8::Arguments & args)768 v8::Handle<v8::Value> V8WebGLRenderingContext::vertexAttrib2fvCallback(const v8::Arguments& args)
769 {
770     INC_STATS("DOM.WebGLRenderingContext.vertexAttrib2fv()");
771     return vertexAttribAndUniformHelperf(args, kVertexAttrib2v);
772 }
773 
vertexAttrib3fvCallback(const v8::Arguments & args)774 v8::Handle<v8::Value> V8WebGLRenderingContext::vertexAttrib3fvCallback(const v8::Arguments& args)
775 {
776     INC_STATS("DOM.WebGLRenderingContext.vertexAttrib3fv()");
777     return vertexAttribAndUniformHelperf(args, kVertexAttrib3v);
778 }
779 
vertexAttrib4fvCallback(const v8::Arguments & args)780 v8::Handle<v8::Value> V8WebGLRenderingContext::vertexAttrib4fvCallback(const v8::Arguments& args)
781 {
782     INC_STATS("DOM.WebGLRenderingContext.vertexAttrib4fv()");
783     return vertexAttribAndUniformHelperf(args, kVertexAttrib4v);
784 }
785 
786 } // namespace WebCore
787 
788 #endif // ENABLE(WEBGL)
789