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
102using namespace JSC;
103
104namespace WebCore {
105
106static 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
156enum ObjectType {
157    kBuffer, kRenderbuffer, kTexture, kVertexAttrib
158};
159
160static 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
199enum WhichProgramCall {
200    kProgramParameter, kUniform
201};
202
203static 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
249void JSWebGLRenderingContext::visitAdditionalChildren(SlotVisitor& visitor)
250{
251    visitor.addOpaqueRoot(&impl());
252}
253
254JSValue 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
277JSValue 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
290JSValue JSWebGLRenderingContext::getBufferParameter(ExecState* exec)
291{
292    return getObjectParameter(this, exec, kBuffer);
293}
294
295JSValue 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
319JSValue 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
337JSValue 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
358JSValue JSWebGLRenderingContext::getRenderbufferParameter(ExecState* exec)
359{
360    return getObjectParameter(this, exec, kRenderbuffer);
361}
362
363JSValue 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
384JSValue 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
396JSValue JSWebGLRenderingContext::getTexParameter(ExecState* exec)
397{
398    return getObjectParameter(this, exec, kTexture);
399}
400
401JSValue 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
422JSValue JSWebGLRenderingContext::getVertexAttrib(ExecState* exec)
423{
424    return getObjectParameter(this, exec, kVertexAttrib);
425}
426
427template<typename T, size_t inlineCapacity>
428bool 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
450enum DataFunctionToCall {
451    f_uniform1v, f_uniform2v, f_uniform3v, f_uniform4v,
452    f_vertexAttrib1v, f_vertexAttrib2v, f_vertexAttrib3v, f_vertexAttrib4v
453};
454
455enum DataFunctionMatrixToCall {
456    f_uniformMatrix2fv, f_uniformMatrix3fv, f_uniformMatrix4fv
457};
458
459static 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
472static 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
562static 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
622static 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
675JSC::JSValue JSWebGLRenderingContext::uniform1fv(JSC::ExecState* exec)
676{
677    return dataFunctionf(f_uniform1v, exec, impl());
678}
679
680JSC::JSValue JSWebGLRenderingContext::uniform1iv(JSC::ExecState* exec)
681{
682    return dataFunctioni(f_uniform1v, exec, impl());
683}
684
685JSC::JSValue JSWebGLRenderingContext::uniform2fv(JSC::ExecState* exec)
686{
687    return dataFunctionf(f_uniform2v, exec, impl());
688}
689
690JSC::JSValue JSWebGLRenderingContext::uniform2iv(JSC::ExecState* exec)
691{
692    return dataFunctioni(f_uniform2v, exec, impl());
693}
694
695JSC::JSValue JSWebGLRenderingContext::uniform3fv(JSC::ExecState* exec)
696{
697    return dataFunctionf(f_uniform3v, exec, impl());
698}
699
700JSC::JSValue JSWebGLRenderingContext::uniform3iv(JSC::ExecState* exec)
701{
702    return dataFunctioni(f_uniform3v, exec, impl());
703}
704
705JSC::JSValue JSWebGLRenderingContext::uniform4fv(JSC::ExecState* exec)
706{
707    return dataFunctionf(f_uniform4v, exec, impl());
708}
709
710JSC::JSValue JSWebGLRenderingContext::uniform4iv(JSC::ExecState* exec)
711{
712    return dataFunctioni(f_uniform4v, exec, impl());
713}
714
715JSC::JSValue JSWebGLRenderingContext::uniformMatrix2fv(JSC::ExecState* exec)
716{
717    return dataFunctionMatrix(f_uniformMatrix2fv, exec, impl());
718}
719
720JSC::JSValue JSWebGLRenderingContext::uniformMatrix3fv(JSC::ExecState* exec)
721{
722    return dataFunctionMatrix(f_uniformMatrix3fv, exec, impl());
723}
724
725JSC::JSValue JSWebGLRenderingContext::uniformMatrix4fv(JSC::ExecState* exec)
726{
727    return dataFunctionMatrix(f_uniformMatrix4fv, exec, impl());
728}
729
730JSC::JSValue JSWebGLRenderingContext::vertexAttrib1fv(JSC::ExecState* exec)
731{
732    return dataFunctionf(f_vertexAttrib1v, exec, impl());
733}
734
735JSC::JSValue JSWebGLRenderingContext::vertexAttrib2fv(JSC::ExecState* exec)
736{
737    return dataFunctionf(f_vertexAttrib2v, exec, impl());
738}
739
740JSC::JSValue JSWebGLRenderingContext::vertexAttrib3fv(JSC::ExecState* exec)
741{
742    return dataFunctionf(f_vertexAttrib3v, exec, impl());
743}
744
745JSC::JSValue JSWebGLRenderingContext::vertexAttrib4fv(JSC::ExecState* exec)
746{
747    return dataFunctionf(f_vertexAttrib4v, exec, impl());
748}
749
750} // namespace WebCore
751
752#endif // ENABLE(WEBGL)
753