Source/JavaScriptCore: https://bugs.webkit.org/show_bug.cgi?id=119548
[WebKit-https.git] / Source / WebCore / bindings / js / JSWebGLRenderingContextCustom.cpp
1 /*
2  * Copyright (C) 2009 Apple 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
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27
28 #if ENABLE(WEBGL)
29
30 #include "JSWebGLRenderingContext.h"
31
32 #include "EXTDrawBuffers.h"
33 #include "EXTTextureFilterAnisotropic.h"
34 #include "ExceptionCode.h"
35 #include "HTMLCanvasElement.h"
36 #include "HTMLImageElement.h"
37 #include "JSEXTDrawBuffers.h"
38 #include "JSEXTTextureFilterAnisotropic.h"
39 #include "JSHTMLCanvasElement.h"
40 #include "JSHTMLImageElement.h"
41 #include "JSImageData.h"
42 #include "JSOESElementIndexUint.h"
43 #include "JSOESStandardDerivatives.h"
44 #include "JSOESTextureFloat.h"
45 #include "JSOESTextureHalfFloat.h"
46 #include "JSOESVertexArrayObject.h"
47 #include "JSWebGLBuffer.h"
48 #include "JSWebGLCompressedTextureATC.h"
49 #include "JSWebGLCompressedTexturePVRTC.h"
50 #include "JSWebGLCompressedTextureS3TC.h"
51 #include "JSWebGLDebugRendererInfo.h"
52 #include "JSWebGLDebugShaders.h"
53 #include "JSWebGLDepthTexture.h"
54 #include "JSWebGLFramebuffer.h"
55 #include "JSWebGLLoseContext.h"
56 #include "JSWebGLProgram.h"
57 #include "JSWebGLRenderbuffer.h"
58 #include "JSWebGLShader.h"
59 #include "JSWebGLTexture.h"
60 #include "JSWebGLUniformLocation.h"
61 #include "JSWebGLVertexArrayObjectOES.h"
62 #include "JSWebKitCSSMatrix.h"
63 #include "NotImplemented.h"
64 #include "OESElementIndexUint.h"
65 #include "OESStandardDerivatives.h"
66 #include "OESTextureFloat.h"
67 #include "OESTextureHalfFloat.h"
68 #include "OESVertexArrayObject.h"
69 #include "WebGLBuffer.h"
70 #include "WebGLCompressedTextureATC.h"
71 #include "WebGLCompressedTexturePVRTC.h"
72 #include "WebGLCompressedTextureS3TC.h"
73 #include "WebGLDebugRendererInfo.h"
74 #include "WebGLDebugShaders.h"
75 #include "WebGLDepthTexture.h"
76 #include "WebGLExtension.h"
77 #include "WebGLFramebuffer.h"
78 #include "WebGLGetInfo.h"
79 #include "WebGLLoseContext.h"
80 #include "WebGLProgram.h"
81 #include "WebGLRenderingContext.h"
82 #include "WebGLVertexArrayObjectOES.h"
83 #include <runtime/Error.h>
84 #include <runtime/JSTypedArrays.h>
85 #include <runtime/TypedArrayInlines.h>
86 #include <runtime/TypedArrays.h>
87 #include <wtf/FastMalloc.h>
88
89 #if ENABLE(VIDEO)
90 #include "HTMLVideoElement.h"
91 #include "JSHTMLVideoElement.h"
92 #endif
93
94 using namespace JSC;
95
96 namespace WebCore {
97
98 static JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, const WebGLGetInfo& info)
99 {
100     switch (info.getType()) {
101     case WebGLGetInfo::kTypeBool:
102         return jsBoolean(info.getBool());
103     case WebGLGetInfo::kTypeBoolArray: {
104         MarkedArgumentBuffer list;
105         const Vector<bool>& value = info.getBoolArray();
106         for (size_t ii = 0; ii < value.size(); ++ii)
107             list.append(jsBoolean(value[ii]));
108         return constructArray(exec, 0, globalObject, list);
109     }
110     case WebGLGetInfo::kTypeFloat:
111         return jsNumber(info.getFloat());
112     case WebGLGetInfo::kTypeInt:
113         return jsNumber(info.getInt());
114     case WebGLGetInfo::kTypeNull:
115         return jsNull();
116     case WebGLGetInfo::kTypeString:
117         return jsStringWithCache(exec, info.getString());
118     case WebGLGetInfo::kTypeUnsignedInt:
119         return jsNumber(info.getUnsignedInt());
120     case WebGLGetInfo::kTypeWebGLBuffer:
121         return toJS(exec, globalObject, info.getWebGLBuffer());
122     case WebGLGetInfo::kTypeWebGLFloatArray:
123         return toJS(exec, globalObject, info.getWebGLFloatArray());
124     case WebGLGetInfo::kTypeWebGLFramebuffer:
125         return toJS(exec, globalObject, info.getWebGLFramebuffer());
126     case WebGLGetInfo::kTypeWebGLIntArray:
127         return toJS(exec, globalObject, info.getWebGLIntArray());
128     // FIXME: implement WebGLObjectArray
129     // case WebGLGetInfo::kTypeWebGLObjectArray:
130     case WebGLGetInfo::kTypeWebGLProgram:
131         return toJS(exec, globalObject, info.getWebGLProgram());
132     case WebGLGetInfo::kTypeWebGLRenderbuffer:
133         return toJS(exec, globalObject, info.getWebGLRenderbuffer());
134     case WebGLGetInfo::kTypeWebGLTexture:
135         return toJS(exec, globalObject, info.getWebGLTexture());
136     case WebGLGetInfo::kTypeWebGLUnsignedByteArray:
137         return toJS(exec, globalObject, info.getWebGLUnsignedByteArray());
138     case WebGLGetInfo::kTypeWebGLUnsignedIntArray:
139         return toJS(exec, globalObject, info.getWebGLUnsignedIntArray());
140     case WebGLGetInfo::kTypeWebGLVertexArrayObjectOES:
141         return toJS(exec, globalObject, info.getWebGLVertexArrayObjectOES());
142     default:
143         notImplemented();
144         return jsUndefined();
145     }
146 }
147
148 enum ObjectType {
149     kBuffer, kRenderbuffer, kTexture, kVertexAttrib
150 };
151
152 static JSValue getObjectParameter(JSWebGLRenderingContext* obj, ExecState* exec, ObjectType objectType)
153 {
154     if (exec->argumentCount() != 2)
155         return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
156
157     ExceptionCode ec = 0;
158     WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(obj->impl());
159     unsigned target = exec->argument(0).toInt32(exec);
160     if (exec->hadException())
161         return jsUndefined();
162     unsigned pname = exec->argument(1).toInt32(exec);
163     if (exec->hadException())
164         return jsUndefined();
165     WebGLGetInfo info;
166     switch (objectType) {
167     case kBuffer:
168         info = context->getBufferParameter(target, pname, ec);
169         break;
170     case kRenderbuffer:
171         info = context->getRenderbufferParameter(target, pname, ec);
172         break;
173     case kTexture:
174         info = context->getTexParameter(target, pname, ec);
175         break;
176     case kVertexAttrib:
177         // target => index
178         info = context->getVertexAttrib(target, pname, ec);
179         break;
180     default:
181         notImplemented();
182         break;
183     }
184     if (ec) {
185         setDOMException(exec, ec);
186         return jsUndefined();
187     }
188     return toJS(exec, obj->globalObject(), info);
189 }
190
191 enum WhichProgramCall {
192     kProgramParameter, kUniform
193 };
194
195 static JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, WebGLExtension* extension)
196 {
197     if (!extension)
198         return jsNull();
199     switch (extension->getName()) {
200     case WebGLExtension::WebGLLoseContextName:
201         return toJS(exec, globalObject, static_cast<WebGLLoseContext*>(extension));
202     case WebGLExtension::EXTDrawBuffersName:
203         return toJS(exec, globalObject, static_cast<EXTDrawBuffers*>(extension));
204     case WebGLExtension::EXTTextureFilterAnisotropicName:
205         return toJS(exec, globalObject, static_cast<EXTTextureFilterAnisotropic*>(extension));
206     case WebGLExtension::OESStandardDerivativesName:
207         return toJS(exec, globalObject, static_cast<OESStandardDerivatives*>(extension));
208     case WebGLExtension::OESTextureFloatName:
209         return toJS(exec, globalObject, static_cast<OESTextureFloat*>(extension));
210     case WebGLExtension::OESTextureHalfFloatName:
211         return toJS(exec, globalObject, static_cast<OESTextureHalfFloat*>(extension));
212     case WebGLExtension::OESVertexArrayObjectName:
213         return toJS(exec, globalObject, static_cast<OESVertexArrayObject*>(extension));
214     case WebGLExtension::OESElementIndexUintName:
215         return toJS(exec, globalObject, static_cast<OESElementIndexUint*>(extension));
216     case WebGLExtension::WebGLDebugRendererInfoName:
217         return toJS(exec, globalObject, static_cast<WebGLDebugRendererInfo*>(extension));
218     case WebGLExtension::WebGLDebugShadersName:
219         return toJS(exec, globalObject, static_cast<WebGLDebugShaders*>(extension));
220     case WebGLExtension::WebGLCompressedTextureATCName:
221         return toJS(exec, globalObject, static_cast<WebGLCompressedTextureATC*>(extension));
222     case WebGLExtension::WebGLCompressedTexturePVRTCName:
223         return toJS(exec, globalObject, static_cast<WebGLCompressedTexturePVRTC*>(extension));
224     case WebGLExtension::WebGLCompressedTextureS3TCName:
225         return toJS(exec, globalObject, static_cast<WebGLCompressedTextureS3TC*>(extension));
226     case WebGLExtension::WebGLDepthTextureName:
227         return toJS(exec, globalObject, static_cast<WebGLDepthTexture*>(extension));
228     }
229     ASSERT_NOT_REACHED();
230     return jsNull();
231 }
232
233 void JSWebGLRenderingContext::visitChildren(JSCell* cell, SlotVisitor& visitor)
234 {
235     JSWebGLRenderingContext* thisObject = jsCast<JSWebGLRenderingContext*>(cell);
236     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
237     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
238     ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
239     Base::visitChildren(thisObject, visitor);
240     visitor.addOpaqueRoot(thisObject->impl());
241 }
242
243 JSValue JSWebGLRenderingContext::getAttachedShaders(ExecState* exec)
244 {
245     if (exec->argumentCount() < 1)
246         return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
247     ExceptionCode ec = 0;
248     WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl());
249     if (exec->argumentCount() > 0 && !exec->argument(0).isUndefinedOrNull() && !exec->argument(0).inherits(JSWebGLProgram::info()))
250         return throwTypeError(exec);
251     WebGLProgram* program = toWebGLProgram(exec->argument(0));
252     if (exec->hadException())
253         return jsNull();
254     Vector<RefPtr<WebGLShader> > shaders;
255     bool succeed = context->getAttachedShaders(program, shaders, ec);
256     if (ec) {
257         setDOMException(exec, ec);
258         return jsNull();
259     }
260     if (!succeed)
261         return jsNull();
262     MarkedArgumentBuffer list;
263     for (size_t ii = 0; ii < shaders.size(); ++ii)
264         list.append(toJS(exec, globalObject(), shaders[ii].get()));
265     return constructArray(exec, 0, globalObject(), list);
266 }
267
268 JSValue JSWebGLRenderingContext::getExtension(ExecState* exec)
269 {
270     if (exec->argumentCount() < 1)
271         return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
272
273     WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl());
274     const String name = exec->argument(0).toString(exec)->value(exec);
275     if (exec->hadException())
276         return jsUndefined();
277     WebGLExtension* extension = context->getExtension(name);
278     return toJS(exec, globalObject(), extension);
279 }
280
281 JSValue JSWebGLRenderingContext::getBufferParameter(ExecState* exec)
282 {
283     return getObjectParameter(this, exec, kBuffer);
284 }
285
286 JSValue JSWebGLRenderingContext::getFramebufferAttachmentParameter(ExecState* exec)
287 {
288     if (exec->argumentCount() != 3)
289         return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
290
291     ExceptionCode ec = 0;
292     WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl());
293     unsigned target = exec->argument(0).toInt32(exec);
294     if (exec->hadException())
295         return jsUndefined();
296     unsigned attachment = exec->argument(1).toInt32(exec);
297     if (exec->hadException())
298         return jsUndefined();
299     unsigned pname = exec->argument(2).toInt32(exec);
300     if (exec->hadException())
301         return jsUndefined();
302     WebGLGetInfo info = context->getFramebufferAttachmentParameter(target, attachment, pname, ec);
303     if (ec) {
304         setDOMException(exec, ec);
305         return jsUndefined();
306     }
307     return toJS(exec, globalObject(), info);
308 }
309
310 JSValue JSWebGLRenderingContext::getParameter(ExecState* exec)
311 {
312     if (exec->argumentCount() != 1)
313         return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
314
315     ExceptionCode ec = 0;
316     WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl());
317     unsigned pname = exec->argument(0).toInt32(exec);
318     if (exec->hadException())
319         return jsUndefined();
320     WebGLGetInfo info = context->getParameter(pname, ec);
321     if (ec) {
322         setDOMException(exec, ec);
323         return jsUndefined();
324     }
325     return toJS(exec, globalObject(), info);
326 }
327
328 JSValue JSWebGLRenderingContext::getProgramParameter(ExecState* exec)
329 {
330     if (exec->argumentCount() != 2)
331         return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
332
333     ExceptionCode ec = 0;
334     WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl());
335     if (exec->argumentCount() > 0 && !exec->argument(0).isUndefinedOrNull() && !exec->argument(0).inherits(JSWebGLProgram::info()))
336         return throwTypeError(exec);
337     WebGLProgram* program = toWebGLProgram(exec->argument(0));
338     unsigned pname = exec->argument(1).toInt32(exec);
339     if (exec->hadException())
340         return jsUndefined();
341     WebGLGetInfo info = context->getProgramParameter(program, pname, ec);
342     if (ec) {
343         setDOMException(exec, ec);
344         return jsUndefined();
345     }
346     return toJS(exec, globalObject(), info);
347 }
348
349 JSValue JSWebGLRenderingContext::getRenderbufferParameter(ExecState* exec)
350 {
351     return getObjectParameter(this, exec, kRenderbuffer);
352 }
353
354 JSValue JSWebGLRenderingContext::getShaderParameter(ExecState* exec)
355 {
356     if (exec->argumentCount() != 2)
357         return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
358
359     ExceptionCode ec = 0;
360     WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl());
361     if (exec->argumentCount() > 0 && !exec->argument(0).isUndefinedOrNull() && !exec->argument(0).inherits(JSWebGLShader::info()))
362         return throwTypeError(exec);
363     WebGLShader* shader = toWebGLShader(exec->argument(0));
364     unsigned pname = exec->argument(1).toInt32(exec);
365     if (exec->hadException())
366         return jsUndefined();
367     WebGLGetInfo info = context->getShaderParameter(shader, pname, ec);
368     if (ec) {
369         setDOMException(exec, ec);
370         return jsUndefined();
371     }
372     return toJS(exec, globalObject(), info);
373 }
374
375 JSValue JSWebGLRenderingContext::getSupportedExtensions(ExecState* exec)
376 {
377     WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl());
378     if (context->isContextLost())
379         return jsNull();
380     Vector<String> value = context->getSupportedExtensions();
381     MarkedArgumentBuffer list;
382     for (size_t ii = 0; ii < value.size(); ++ii)
383         list.append(jsStringWithCache(exec, value[ii]));
384     return constructArray(exec, 0, globalObject(), list);
385 }
386
387 JSValue JSWebGLRenderingContext::getTexParameter(ExecState* exec)
388 {
389     return getObjectParameter(this, exec, kTexture);
390 }
391
392 JSValue JSWebGLRenderingContext::getUniform(ExecState* exec)
393 {
394     if (exec->argumentCount() != 2)
395         return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
396
397     ExceptionCode ec = 0;
398     WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl());
399     if (exec->argumentCount() > 0 && !exec->argument(0).isUndefinedOrNull() && !exec->argument(0).inherits(JSWebGLProgram::info()))
400         return throwTypeError(exec);
401     WebGLProgram* program = toWebGLProgram(exec->argument(0));
402     if (exec->argumentCount() > 1 && !exec->argument(1).isUndefinedOrNull() && !exec->argument(1).inherits(JSWebGLUniformLocation::info()))
403         return throwTypeError(exec);
404     WebGLUniformLocation* loc = toWebGLUniformLocation(exec->argument(1));
405     if (exec->hadException())
406         return jsUndefined();
407     WebGLGetInfo info = context->getUniform(program, loc, ec);
408     if (ec) {
409         setDOMException(exec, ec);
410         return jsUndefined();
411     }
412     return toJS(exec, globalObject(), info);
413 }
414
415 JSValue JSWebGLRenderingContext::getVertexAttrib(ExecState* exec)
416 {
417     return getObjectParameter(this, exec, kVertexAttrib);
418 }
419
420 template<typename T, size_t inlineCapacity>
421 bool toVector(JSC::ExecState* exec, JSC::JSValue value, Vector<T, inlineCapacity>& vector)
422 {
423     if (!value.isObject())
424         return false;
425
426     JSC::JSObject* object = asObject(value);
427     int32_t length = object->get(exec, exec->vm().propertyNames->length).toInt32(exec);
428
429     if (!vector.tryReserveCapacity(length))
430         return false;
431     vector.resize(length);
432
433     for (int32_t i = 0; i < length; ++i) {
434         JSC::JSValue v = object->get(exec, i);
435         if (exec->hadException())
436             return false;
437         vector[i] = static_cast<T>(v.toNumber(exec));
438     }
439
440     return true;
441 }
442
443 enum DataFunctionToCall {
444     f_uniform1v, f_uniform2v, f_uniform3v, f_uniform4v,
445     f_vertexAttrib1v, f_vertexAttrib2v, f_vertexAttrib3v, f_vertexAttrib4v
446 };
447
448 enum DataFunctionMatrixToCall {
449     f_uniformMatrix2fv, f_uniformMatrix3fv, f_uniformMatrix4fv
450 };
451
452 static bool functionForUniform(DataFunctionToCall f)
453 {
454     switch (f) {
455     case f_uniform1v:
456     case f_uniform2v:
457     case f_uniform3v:
458     case f_uniform4v:
459         return true;
460         break;
461     default: break;
462     }
463     return false;
464 }
465
466 static JSC::JSValue dataFunctionf(DataFunctionToCall f, JSC::ExecState* exec, WebGLRenderingContext* context)
467 {
468     if (exec->argumentCount() != 2)
469         return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
470     
471     WebGLUniformLocation* location = 0;
472     long index = -1;
473     
474     if (functionForUniform(f)) {
475         if (exec->argumentCount() > 0 && !exec->argument(0).isUndefinedOrNull() && !exec->argument(0).inherits(JSWebGLUniformLocation::info()))
476             return throwTypeError(exec);
477         location = toWebGLUniformLocation(exec->argument(0));
478     } else
479         index = exec->argument(0).toInt32(exec);
480
481     if (exec->hadException())
482         return jsUndefined();
483         
484     RefPtr<Float32Array> webGLArray = toFloat32Array(exec->argument(1));
485     if (exec->hadException())    
486         return jsUndefined();
487         
488     ExceptionCode ec = 0;
489     if (webGLArray) {
490         switch (f) {
491         case f_uniform1v:
492             context->uniform1fv(location, webGLArray.get(), ec);
493             break;
494         case f_uniform2v:
495             context->uniform2fv(location, webGLArray.get(), ec);
496             break;
497         case f_uniform3v:
498             context->uniform3fv(location, webGLArray.get(), ec);
499             break;
500         case f_uniform4v:
501             context->uniform4fv(location, webGLArray.get(), ec);
502             break;
503         case f_vertexAttrib1v:
504             context->vertexAttrib1fv(index, webGLArray.get());
505             break;
506         case f_vertexAttrib2v:
507             context->vertexAttrib2fv(index, webGLArray.get());
508             break;
509         case f_vertexAttrib3v:
510             context->vertexAttrib3fv(index, webGLArray.get());
511             break;
512         case f_vertexAttrib4v:
513             context->vertexAttrib4fv(index, webGLArray.get());
514             break;
515         }
516         
517         setDOMException(exec, ec);
518         return jsUndefined();
519     }
520
521     Vector<float, 64> array;
522     if (!toVector(exec, exec->argument(1), array))
523         return throwTypeError(exec);
524
525     switch (f) {
526     case f_uniform1v:
527         context->uniform1fv(location, array.data(), array.size(), ec);
528         break;
529     case f_uniform2v:
530         context->uniform2fv(location, array.data(), array.size(), ec);
531         break;
532     case f_uniform3v:
533         context->uniform3fv(location, array.data(), array.size(), ec);
534         break;
535     case f_uniform4v:
536         context->uniform4fv(location, array.data(), array.size(), ec);
537         break;
538     case f_vertexAttrib1v:
539         context->vertexAttrib1fv(index, array.data(), array.size());
540         break;
541     case f_vertexAttrib2v:
542         context->vertexAttrib2fv(index, array.data(), array.size());
543         break;
544     case f_vertexAttrib3v:
545         context->vertexAttrib3fv(index, array.data(), array.size());
546         break;
547     case f_vertexAttrib4v:
548         context->vertexAttrib4fv(index, array.data(), array.size());
549         break;
550     }
551     
552     setDOMException(exec, ec);
553     return jsUndefined();
554 }
555
556 static JSC::JSValue dataFunctioni(DataFunctionToCall f, JSC::ExecState* exec, WebGLRenderingContext* context)
557 {
558     if (exec->argumentCount() != 2)
559         return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
560
561     if (exec->argumentCount() > 0 && !exec->argument(0).isUndefinedOrNull() && !exec->argument(0).inherits(JSWebGLUniformLocation::info()))
562         return throwTypeError(exec);
563     WebGLUniformLocation* location = toWebGLUniformLocation(exec->argument(0));
564   
565     if (exec->hadException())
566         return jsUndefined();
567         
568     RefPtr<Int32Array> webGLArray = toInt32Array(exec->argument(1));
569     if (exec->hadException())    
570         return jsUndefined();
571         
572     ExceptionCode ec = 0;
573     if (webGLArray) {
574         switch (f) {
575         case f_uniform1v:
576             context->uniform1iv(location, webGLArray.get(), ec);
577             break;
578         case f_uniform2v:
579             context->uniform2iv(location, webGLArray.get(), ec);
580             break;
581         case f_uniform3v:
582             context->uniform3iv(location, webGLArray.get(), ec);
583             break;
584         case f_uniform4v:
585             context->uniform4iv(location, webGLArray.get(), ec);
586             break;
587         default:
588             break;
589         }
590         
591         setDOMException(exec, ec);
592         return jsUndefined();
593     }
594
595
596     Vector<int, 64> array;
597     if (!toVector(exec, exec->argument(1), array))
598         return throwTypeError(exec);
599
600     switch (f) {
601     case f_uniform1v:
602         context->uniform1iv(location, array.data(), array.size(), ec);
603         break;
604     case f_uniform2v:
605         context->uniform2iv(location, array.data(), array.size(), ec);
606         break;
607     case f_uniform3v:
608         context->uniform3iv(location, array.data(), array.size(), ec);
609         break;
610     case f_uniform4v:
611         context->uniform4iv(location, array.data(), array.size(), ec);
612         break;
613     default:
614         break;
615     }
616     
617     setDOMException(exec, ec);
618     return jsUndefined();
619 }
620
621 static JSC::JSValue dataFunctionMatrix(DataFunctionMatrixToCall f, JSC::ExecState* exec, WebGLRenderingContext* context)
622 {
623     if (exec->argumentCount() != 3)
624         return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
625
626     if (exec->argumentCount() > 0 && !exec->argument(0).isUndefinedOrNull() && !exec->argument(0).inherits(JSWebGLUniformLocation::info()))
627         return throwTypeError(exec);
628     WebGLUniformLocation* location = toWebGLUniformLocation(exec->argument(0));
629
630     if (exec->hadException())    
631         return jsUndefined();
632         
633     bool transpose = exec->argument(1).toBoolean(exec);
634     if (exec->hadException())    
635         return jsUndefined();
636         
637     RefPtr<Float32Array> webGLArray = toFloat32Array(exec->argument(2));
638     if (exec->hadException())    
639         return jsUndefined();
640         
641     ExceptionCode ec = 0;
642     if (webGLArray) {
643         switch (f) {
644         case f_uniformMatrix2fv:
645             context->uniformMatrix2fv(location, transpose, webGLArray.get(), ec);
646             break;
647         case f_uniformMatrix3fv:
648             context->uniformMatrix3fv(location, transpose, webGLArray.get(), ec);
649             break;
650         case f_uniformMatrix4fv:
651             context->uniformMatrix4fv(location, transpose, webGLArray.get(), ec);
652             break;
653         }
654         
655         setDOMException(exec, ec);
656         return jsUndefined();
657     }
658
659     Vector<float, 64> array;
660     if (!toVector(exec, exec->argument(2), array))
661         return throwTypeError(exec);
662
663     switch (f) {
664     case f_uniformMatrix2fv:
665         context->uniformMatrix2fv(location, transpose, array.data(), array.size(), ec);
666         break;
667     case f_uniformMatrix3fv:
668         context->uniformMatrix3fv(location, transpose, array.data(), array.size(), ec);
669         break;
670     case f_uniformMatrix4fv:
671         context->uniformMatrix4fv(location, transpose, array.data(), array.size(), ec);
672         break;
673     }
674
675     setDOMException(exec, ec);
676     return jsUndefined();
677 }
678
679 JSC::JSValue JSWebGLRenderingContext::uniform1fv(JSC::ExecState* exec)
680 {
681     return dataFunctionf(f_uniform1v, exec, static_cast<WebGLRenderingContext*>(impl()));
682 }
683
684 JSC::JSValue JSWebGLRenderingContext::uniform1iv(JSC::ExecState* exec)
685 {
686     return dataFunctioni(f_uniform1v, exec, static_cast<WebGLRenderingContext*>(impl()));
687 }
688
689 JSC::JSValue JSWebGLRenderingContext::uniform2fv(JSC::ExecState* exec)
690 {
691     return dataFunctionf(f_uniform2v, exec, static_cast<WebGLRenderingContext*>(impl()));
692 }
693
694 JSC::JSValue JSWebGLRenderingContext::uniform2iv(JSC::ExecState* exec)
695 {
696     return dataFunctioni(f_uniform2v, exec, static_cast<WebGLRenderingContext*>(impl()));
697 }
698
699 JSC::JSValue JSWebGLRenderingContext::uniform3fv(JSC::ExecState* exec)
700 {
701     return dataFunctionf(f_uniform3v, exec, static_cast<WebGLRenderingContext*>(impl()));
702 }
703
704 JSC::JSValue JSWebGLRenderingContext::uniform3iv(JSC::ExecState* exec)
705 {
706     return dataFunctioni(f_uniform3v, exec, static_cast<WebGLRenderingContext*>(impl()));
707 }
708
709 JSC::JSValue JSWebGLRenderingContext::uniform4fv(JSC::ExecState* exec)
710 {
711     return dataFunctionf(f_uniform4v, exec, static_cast<WebGLRenderingContext*>(impl()));
712 }
713
714 JSC::JSValue JSWebGLRenderingContext::uniform4iv(JSC::ExecState* exec)
715 {
716     return dataFunctioni(f_uniform4v, exec, static_cast<WebGLRenderingContext*>(impl()));
717 }
718
719 JSC::JSValue JSWebGLRenderingContext::uniformMatrix2fv(JSC::ExecState* exec)
720 {
721     return dataFunctionMatrix(f_uniformMatrix2fv, exec, static_cast<WebGLRenderingContext*>(impl()));
722 }
723
724 JSC::JSValue JSWebGLRenderingContext::uniformMatrix3fv(JSC::ExecState* exec)
725 {
726     return dataFunctionMatrix(f_uniformMatrix3fv, exec, static_cast<WebGLRenderingContext*>(impl()));
727 }
728
729 JSC::JSValue JSWebGLRenderingContext::uniformMatrix4fv(JSC::ExecState* exec)
730 {
731     return dataFunctionMatrix(f_uniformMatrix4fv, exec, static_cast<WebGLRenderingContext*>(impl()));
732 }
733
734 JSC::JSValue JSWebGLRenderingContext::vertexAttrib1fv(JSC::ExecState* exec)
735 {
736     return dataFunctionf(f_vertexAttrib1v, exec, static_cast<WebGLRenderingContext*>(impl()));
737 }
738
739 JSC::JSValue JSWebGLRenderingContext::vertexAttrib2fv(JSC::ExecState* exec)
740 {
741     return dataFunctionf(f_vertexAttrib2v, exec, static_cast<WebGLRenderingContext*>(impl()));
742 }
743
744 JSC::JSValue JSWebGLRenderingContext::vertexAttrib3fv(JSC::ExecState* exec)
745 {
746     return dataFunctionf(f_vertexAttrib3v, exec, static_cast<WebGLRenderingContext*>(impl()));
747 }
748
749 JSC::JSValue JSWebGLRenderingContext::vertexAttrib4fv(JSC::ExecState* exec)
750 {
751     return dataFunctionf(f_vertexAttrib4v, exec, static_cast<WebGLRenderingContext*>(impl()));
752 }
753
754 } // namespace WebCore
755
756 #endif // ENABLE(WEBGL)