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