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(3D_CANVAS)
29
30#include "JSWebGLRenderingContext.h"
31
32#include "ExceptionCode.h"
33#include "HTMLCanvasElement.h"
34#include "HTMLImageElement.h"
35#include "HTMLVideoElement.h"
36#include "JSHTMLCanvasElement.h"
37#include "JSHTMLImageElement.h"
38#include "JSHTMLVideoElement.h"
39#include "JSImageData.h"
40#include "JSWebGLBuffer.h"
41#include "JSWebGLFloatArray.h"
42#include "JSWebGLFramebuffer.h"
43#include "JSWebGLIntArray.h"
44#include "JSWebGLProgram.h"
45#include "JSWebGLRenderbuffer.h"
46#include "JSWebGLShader.h"
47#include "JSWebGLTexture.h"
48#include "JSWebGLUniformLocation.h"
49#include "JSWebGLUnsignedByteArray.h"
50#include "JSWebKitCSSMatrix.h"
51#include "NotImplemented.h"
52#include "WebGLBuffer.h"
53#include "WebGLFloatArray.h"
54#include "WebGLFramebuffer.h"
55#include "WebGLGetInfo.h"
56#include "WebGLIntArray.h"
57#include "WebGLProgram.h"
58#include "WebGLRenderingContext.h"
59#include <runtime/Error.h>
60#include <wtf/FastMalloc.h>
61#include <wtf/OwnFastMallocPtr.h>
62
63using namespace JSC;
64
65namespace WebCore {
66
67JSValue JSWebGLRenderingContext::bufferData(JSC::ExecState* exec, JSC::ArgList const& args)
68{
69    if (args.size() != 3)
70        return throwError(exec, SyntaxError);
71
72    unsigned target = args.at(0).toInt32(exec);
73    unsigned usage = args.at(2).toInt32(exec);
74    ExceptionCode ec = 0;
75
76    // If argument 1 is a number, we are initializing this buffer to that size
77    if (!args.at(1).isObject()) {
78        unsigned int count = args.at(1).toInt32(exec);
79        static_cast<WebGLRenderingContext*>(impl())->bufferData(target, count, usage, ec);
80    } else {
81        WebGLArray* array = toWebGLArray(args.at(1));
82        static_cast<WebGLRenderingContext*>(impl())->bufferData(target, array, usage, ec);
83    }
84
85    setDOMException(exec, ec);
86    return jsUndefined();
87}
88
89JSValue JSWebGLRenderingContext::bufferSubData(JSC::ExecState* exec, JSC::ArgList const& args)
90{
91    if (args.size() != 3)
92        return throwError(exec, SyntaxError);
93
94    unsigned target = args.at(0).toInt32(exec);
95    unsigned offset = args.at(1).toInt32(exec);
96    ExceptionCode ec = 0;
97
98    WebGLArray* array = toWebGLArray(args.at(2));
99
100    static_cast<WebGLRenderingContext*>(impl())->bufferSubData(target, offset, array, ec);
101
102    setDOMException(exec, ec);
103    return jsUndefined();
104}
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::kTypeFloat:
112        return jsNumber(exec, info.getFloat());
113    case WebGLGetInfo::kTypeLong:
114        return jsNumber(exec, info.getLong());
115    case WebGLGetInfo::kTypeNull:
116        return jsNull();
117    case WebGLGetInfo::kTypeString:
118        return jsString(exec, info.getString());
119    case WebGLGetInfo::kTypeUnsignedLong:
120        return jsNumber(exec, info.getUnsignedLong());
121    case WebGLGetInfo::kTypeWebGLBuffer:
122        return toJS(exec, globalObject, info.getWebGLBuffer());
123    case WebGLGetInfo::kTypeWebGLFloatArray:
124        return toJS(exec, globalObject, info.getWebGLFloatArray());
125    case WebGLGetInfo::kTypeWebGLFramebuffer:
126        return toJS(exec, globalObject, info.getWebGLFramebuffer());
127    case WebGLGetInfo::kTypeWebGLIntArray:
128        return toJS(exec, globalObject, info.getWebGLIntArray());
129    // FIXME: implement WebGLObjectArray
130    // case WebGLGetInfo::kTypeWebGLObjectArray:
131    case WebGLGetInfo::kTypeWebGLProgram:
132        return toJS(exec, globalObject, info.getWebGLProgram());
133    case WebGLGetInfo::kTypeWebGLRenderbuffer:
134        return toJS(exec, globalObject, info.getWebGLRenderbuffer());
135    case WebGLGetInfo::kTypeWebGLTexture:
136        return toJS(exec, globalObject, info.getWebGLTexture());
137    case WebGLGetInfo::kTypeWebGLUnsignedByteArray:
138        return toJS(exec, globalObject, info.getWebGLUnsignedByteArray());
139    default:
140        notImplemented();
141        return jsUndefined();
142    }
143}
144
145enum ObjectType {
146    kBuffer, kRenderbuffer, kTexture, kVertexAttrib
147};
148
149static JSValue getObjectParameter(JSWebGLRenderingContext* obj, ExecState* exec, const ArgList& args, ObjectType objectType)
150{
151    if (args.size() != 2)
152        return throwError(exec, SyntaxError);
153
154    ExceptionCode ec = 0;
155    WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(obj->impl());
156    unsigned target = args.at(0).toInt32(exec);
157    if (exec->hadException())
158        return jsUndefined();
159    unsigned pname = args.at(1).toInt32(exec);
160    if (exec->hadException())
161        return jsUndefined();
162    WebGLGetInfo info;
163    switch (objectType) {
164    case kBuffer:
165        info = context->getBufferParameter(target, pname, ec);
166        break;
167    case kRenderbuffer:
168        info = context->getRenderbufferParameter(target, pname, ec);
169        break;
170    case kTexture:
171        info = context->getTexParameter(target, pname, ec);
172        break;
173    case kVertexAttrib:
174        // target => index
175        info = context->getVertexAttrib(target, pname, ec);
176        break;
177    default:
178        notImplemented();
179        break;
180    }
181    if (ec) {
182        setDOMException(exec, ec);
183        return jsUndefined();
184    }
185    return toJS(exec, obj->globalObject(), info);
186}
187
188enum WhichProgramCall {
189    kProgramParameter, kUniform
190};
191
192JSValue JSWebGLRenderingContext::getBufferParameter(ExecState* exec, const ArgList& args)
193{
194    return getObjectParameter(this, exec, args, kBuffer);
195}
196
197JSValue JSWebGLRenderingContext::getFramebufferAttachmentParameter(ExecState* exec, const ArgList& args)
198{
199    if (args.size() != 3)
200        return throwError(exec, SyntaxError);
201
202    ExceptionCode ec = 0;
203    WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl());
204    unsigned target = args.at(0).toInt32(exec);
205    if (exec->hadException())
206        return jsUndefined();
207    unsigned attachment = args.at(1).toInt32(exec);
208    if (exec->hadException())
209        return jsUndefined();
210    unsigned pname = args.at(2).toInt32(exec);
211    if (exec->hadException())
212        return jsUndefined();
213    WebGLGetInfo info = context->getFramebufferAttachmentParameter(target, attachment, pname, ec);
214    if (ec) {
215        setDOMException(exec, ec);
216        return jsUndefined();
217    }
218    return toJS(exec, globalObject(), info);
219}
220
221JSValue JSWebGLRenderingContext::getParameter(ExecState* exec, const ArgList& args)
222{
223    if (args.size() != 1)
224        return throwError(exec, SyntaxError);
225
226    ExceptionCode ec = 0;
227    WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl());
228    unsigned pname = args.at(0).toInt32(exec);
229    if (exec->hadException())
230        return jsUndefined();
231    WebGLGetInfo info = context->getParameter(pname, ec);
232    if (ec) {
233        setDOMException(exec, ec);
234        return jsUndefined();
235    }
236    return toJS(exec, globalObject(), info);
237}
238
239JSValue JSWebGLRenderingContext::getProgramParameter(ExecState* exec, const ArgList& args)
240{
241    if (args.size() != 2)
242        return throwError(exec, SyntaxError);
243
244    ExceptionCode ec = 0;
245    WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl());
246    WebGLProgram* program = toWebGLProgram(args.at(0));
247    unsigned pname = args.at(1).toInt32(exec);
248    if (exec->hadException())
249        return jsUndefined();
250    WebGLGetInfo info = context->getProgramParameter(program, pname, ec);
251    if (ec) {
252        setDOMException(exec, ec);
253        return jsUndefined();
254    }
255    return toJS(exec, globalObject(), info);
256}
257
258JSValue JSWebGLRenderingContext::getRenderbufferParameter(ExecState* exec, const ArgList& args)
259{
260    return getObjectParameter(this, exec, args, kRenderbuffer);
261}
262
263JSValue JSWebGLRenderingContext::getShaderParameter(ExecState* exec, const ArgList& args)
264{
265    if (args.size() != 2)
266        return throwError(exec, SyntaxError);
267
268    ExceptionCode ec = 0;
269    WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl());
270    WebGLShader* shader = toWebGLShader(args.at(0));
271    unsigned pname = args.at(1).toInt32(exec);
272    if (exec->hadException())
273        return jsUndefined();
274    WebGLGetInfo info = context->getShaderParameter(shader, pname, ec);
275    if (ec) {
276        setDOMException(exec, ec);
277        return jsUndefined();
278    }
279    return toJS(exec, globalObject(), info);
280}
281
282JSValue JSWebGLRenderingContext::getTexParameter(ExecState* exec, const ArgList& args)
283{
284    return getObjectParameter(this, exec, args, kTexture);
285}
286
287JSValue JSWebGLRenderingContext::getUniform(ExecState* exec, const ArgList& args)
288{
289    if (args.size() != 2)
290        return throwError(exec, SyntaxError);
291
292    ExceptionCode ec = 0;
293    WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl());
294    WebGLProgram* program = toWebGLProgram(args.at(0));
295    WebGLUniformLocation* loc = toWebGLUniformLocation(args.at(1));
296    if (exec->hadException())
297        return jsUndefined();
298    WebGLGetInfo info = context->getUniform(program, loc, ec);
299    if (ec) {
300        setDOMException(exec, ec);
301        return jsUndefined();
302    }
303    return toJS(exec, globalObject(), info);
304}
305
306JSValue JSWebGLRenderingContext::getVertexAttrib(ExecState* exec, const ArgList& args)
307{
308    return getObjectParameter(this, exec, args, kVertexAttrib);
309}
310
311//   void texImage2D(in GLenum target, in GLint level, in GLenum internalformat, in GLsizei width, in GLsizei height, in GLint border, in GLenum format, in GLenum type, in WebGLArray pixels);
312//   void texImage2D(in GLenum target, in GLint level, in ImageData pixels, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha);
313//   void texImage2D(in GLenum target, in GLint level, in HTMLImageElement image, [Optional] in GLboolean flipY, [Optional] in premultiplyAlpha);
314//   void texImage2D(in GLenum target, in GLint level, in HTMLCanvasElement canvas, [Optional] in GLboolean flipY, [Optional] in premultiplyAlpha);
315//   void texImage2D(in GLenum target, in GLint level, in HTMLVideoElement video, [Optional] in GLboolean flipY, [Optional] in premultiplyAlpha);
316JSValue JSWebGLRenderingContext::texImage2D(ExecState* exec, const ArgList& args)
317{
318    if (args.size() < 3 || args.size() > 9)
319        return throwError(exec, SyntaxError);
320
321    ExceptionCode ec = 0;
322
323    WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl());
324    unsigned target = args.at(0).toInt32(exec);
325    if (exec->hadException())
326        return jsUndefined();
327
328    unsigned level = args.at(1).toInt32(exec);
329    if (exec->hadException())
330        return jsUndefined();
331
332    JSObject* o = 0;
333
334    if (args.size() <= 5) {
335        // This is one of the last 4 forms. Param 2 can be ImageData or <img>, <canvas> or <video> element.
336        JSValue value = args.at(2);
337
338        if (!value.isObject())
339            return throwError(exec, TypeError);
340
341        o = asObject(value);
342
343        bool flipY = args.at(3).toBoolean(exec);
344        bool premultiplyAlpha = args.at(4).toBoolean(exec);
345
346        if (o->inherits(&JSImageData::s_info)) {
347            ImageData* data = static_cast<ImageData*>(static_cast<JSImageData*>(o)->impl());
348            context->texImage2D(target, level, data, flipY, premultiplyAlpha, ec);
349        } else if (o->inherits(&JSHTMLImageElement::s_info)) {
350            HTMLImageElement* element = static_cast<HTMLImageElement*>(static_cast<JSHTMLImageElement*>(o)->impl());
351            context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec);
352        } else if (o->inherits(&JSHTMLCanvasElement::s_info)) {
353            HTMLCanvasElement* element = static_cast<HTMLCanvasElement*>(static_cast<JSHTMLCanvasElement*>(o)->impl());
354            context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec);
355        } else if (o->inherits(&JSHTMLVideoElement::s_info)) {
356            HTMLVideoElement* element = static_cast<HTMLVideoElement*>(static_cast<JSHTMLVideoElement*>(o)->impl());
357            context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec);
358        } else
359            ec = TYPE_MISMATCH_ERR;
360    } else {
361        if (args.size() != 9)
362            return throwError(exec, SyntaxError);
363
364        // This must be the WebGLArray case
365        unsigned internalformat = args.at(2).toInt32(exec);
366        if (exec->hadException())
367            return jsUndefined();
368
369        unsigned width = args.at(3).toInt32(exec);
370        if (exec->hadException())
371            return jsUndefined();
372
373        unsigned height = args.at(4).toInt32(exec);
374        if (exec->hadException())
375            return jsUndefined();
376
377        unsigned border = args.at(5).toInt32(exec);
378        if (exec->hadException())
379            return jsUndefined();
380
381        unsigned format = args.at(6).toInt32(exec);
382        if (exec->hadException())
383            return jsUndefined();
384
385        unsigned type = args.at(7).toInt32(exec);
386        if (exec->hadException())
387            return jsUndefined();
388
389        JSValue value = args.at(8);
390
391        // For this case passing 0 (for a null array) is allowed
392        if (value.isNull())
393            context->texImage2D(target, level, internalformat, width, height, border, format, type, 0, ec);
394        else if (value.isObject()) {
395            o = asObject(value);
396
397            if (o->inherits(&JSWebGLArray::s_info)) {
398                // FIXME: Need to check to make sure WebGLArray is a WebGLByteArray or WebGLShortArray,
399                // depending on the passed type parameter.
400                WebGLArray* obj = static_cast<WebGLArray*>(static_cast<JSWebGLArray*>(o)->impl());
401                context->texImage2D(target, level, internalformat, width, height, border, format, type, obj, ec);
402            } else
403                return throwError(exec, TypeError);
404        } else
405            return throwError(exec, TypeError);
406    }
407
408    setDOMException(exec, ec);
409    return jsUndefined();
410}
411
412//   void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in GLsizei width, in GLsizei height, in GLenum format, in GLenum type, in WebGLArray pixels);
413//   void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in ImageData pixels, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha);
414//   void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in HTMLImageElement image, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha);
415//   void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in HTMLCanvasElement canvas, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha);
416//   void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in HTMLVideoElement video, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha);
417JSValue JSWebGLRenderingContext::texSubImage2D(ExecState* exec, const ArgList& args)
418{
419    if (args.size() < 5 || args.size() > 9)
420        return throwError(exec, SyntaxError);
421
422    ExceptionCode ec = 0;
423
424    WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl());
425    unsigned target = args.at(0).toInt32(exec);
426    if (exec->hadException())
427        return jsUndefined();
428
429    unsigned level = args.at(1).toInt32(exec);
430    if (exec->hadException())
431        return jsUndefined();
432
433    unsigned xoff = args.at(2).toInt32(exec);
434    if (exec->hadException())
435        return jsUndefined();
436
437    unsigned yoff = args.at(3).toInt32(exec);
438    if (exec->hadException())
439        return jsUndefined();
440
441    JSObject* o = 0;
442
443    if (args.size() <= 7) {
444        // This is one of the last 4 forms. Param 4 can be <img>, <canvas> or <video> element, of the format param.
445        JSValue value = args.at(4);
446
447        if (!value.isObject())
448            return throwError(exec, SyntaxError);
449
450        o = asObject(value);
451
452        bool flipY = args.at(5).toBoolean(exec);
453        bool premultiplyAlpha = args.at(6).toBoolean(exec);
454
455        if (o->inherits(&JSImageData::s_info)) {
456            ImageData* data = static_cast<ImageData*>(static_cast<JSImageData*>(o)->impl());
457            context->texSubImage2D(target, level, xoff, yoff, data, flipY, premultiplyAlpha, ec);
458        } else if (o->inherits(&JSHTMLImageElement::s_info)) {
459            HTMLImageElement* element = static_cast<HTMLImageElement*>(static_cast<JSHTMLImageElement*>(o)->impl());
460            context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec);
461        } else if (o->inherits(&JSHTMLCanvasElement::s_info)) {
462            HTMLCanvasElement* element = static_cast<HTMLCanvasElement*>(static_cast<JSHTMLCanvasElement*>(o)->impl());
463            context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec);
464        } else if (o->inherits(&JSHTMLVideoElement::s_info)) {
465            HTMLVideoElement* element = static_cast<HTMLVideoElement*>(static_cast<JSHTMLVideoElement*>(o)->impl());
466            context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec);
467        } else
468            ec = TYPE_MISMATCH_ERR;
469    } else {
470        // This must be the WebGLArray form
471        if (args.size() != 9)
472            return throwError(exec, SyntaxError);
473
474        unsigned width = args.at(4).toInt32(exec);
475        if (exec->hadException())
476            return jsUndefined();
477
478        unsigned height = args.at(5).toInt32(exec);
479        if (exec->hadException())
480            return jsUndefined();
481
482        unsigned format = args.at(6).toInt32(exec);
483        if (exec->hadException())
484            return jsUndefined();
485
486        unsigned type = args.at(7).toInt32(exec);
487        if (exec->hadException())
488            return jsUndefined();
489
490        JSValue value = args.at(8);
491        if (!value.isObject())
492            context->texSubImage2D(target, level, xoff, yoff, width, height, format, type, 0, ec);
493        else {
494            o = asObject(value);
495
496            if (o->inherits(&JSWebGLArray::s_info)) {
497                WebGLArray* obj = static_cast<WebGLArray*>(static_cast<JSWebGLArray*>(o)->impl());
498                context->texSubImage2D(target, level, xoff, yoff, width, height, format, type, obj, ec);
499            } else
500                return throwError(exec, TypeError);
501        }
502    }
503
504    setDOMException(exec, ec);
505    return jsUndefined();
506}
507
508template<typename T, size_t inlineCapacity>
509bool toVector(JSC::ExecState* exec, JSC::JSValue value, Vector<T, inlineCapacity>& vector)
510{
511    if (!value.isObject())
512        return false;
513
514    JSC::JSObject* object = asObject(value);
515    int32_t length = object->get(exec, JSC::Identifier(exec, "length")).toInt32(exec);
516    vector.resize(length);
517
518    for (int32_t i = 0; i < length; ++i) {
519        JSC::JSValue v = object->get(exec, i);
520        if (exec->hadException())
521            return false;
522        vector[i] = static_cast<T>(v.toNumber(exec));
523    }
524
525    return true;
526}
527
528enum DataFunctionToCall {
529    f_uniform1v, f_uniform2v, f_uniform3v, f_uniform4v,
530    f_vertexAttrib1v, f_vertexAttrib2v, f_vertexAttrib3v, f_vertexAttrib4v
531};
532
533enum DataFunctionMatrixToCall {
534    f_uniformMatrix2fv, f_uniformMatrix3fv, f_uniformMatrix4fv
535};
536
537static bool functionForUniform(DataFunctionToCall f)
538{
539    switch (f) {
540    case f_uniform1v:
541    case f_uniform2v:
542    case f_uniform3v:
543    case f_uniform4v:
544        return true;
545        break;
546    default: break;
547    }
548    return false;
549}
550
551static JSC::JSValue dataFunctionf(DataFunctionToCall f, JSC::ExecState* exec, const JSC::ArgList& args, WebGLRenderingContext* context)
552{
553    if (args.size() != 2)
554        return throwError(exec, SyntaxError);
555
556    WebGLUniformLocation* location = 0;
557    long index = -1;
558
559    if (functionForUniform(f))
560        location = toWebGLUniformLocation(args.at(0));
561    else
562        index = args.at(0).toInt32(exec);
563
564    if (exec->hadException())
565        return jsUndefined();
566
567    RefPtr<WebGLFloatArray> webGLArray = toWebGLFloatArray(args.at(1));
568    if (exec->hadException())
569        return jsUndefined();
570
571    ExceptionCode ec = 0;
572    if (webGLArray) {
573        switch (f) {
574        case f_uniform1v:
575            context->uniform1fv(location, webGLArray.get(), ec);
576            break;
577        case f_uniform2v:
578            context->uniform2fv(location, webGLArray.get(), ec);
579            break;
580        case f_uniform3v:
581            context->uniform3fv(location, webGLArray.get(), ec);
582            break;
583        case f_uniform4v:
584            context->uniform4fv(location, webGLArray.get(), ec);
585            break;
586        case f_vertexAttrib1v:
587            context->vertexAttrib1fv(index, webGLArray.get());
588            break;
589        case f_vertexAttrib2v:
590            context->vertexAttrib2fv(index, webGLArray.get());
591            break;
592        case f_vertexAttrib3v:
593            context->vertexAttrib3fv(index, webGLArray.get());
594            break;
595        case f_vertexAttrib4v:
596            context->vertexAttrib4fv(index, webGLArray.get());
597            break;
598        }
599
600        setDOMException(exec, ec);
601        return jsUndefined();
602    }
603
604    Vector<float, 64> array;
605    if (!toVector(exec, args.at(1), array))
606        return throwError(exec, TypeError);
607
608    switch (f) {
609    case f_uniform1v:
610        context->uniform1fv(location, array.data(), array.size(), ec);
611        break;
612    case f_uniform2v:
613        context->uniform2fv(location, array.data(), array.size(), ec);
614        break;
615    case f_uniform3v:
616        context->uniform3fv(location, array.data(), array.size(), ec);
617        break;
618    case f_uniform4v:
619        context->uniform4fv(location, array.data(), array.size(), ec);
620        break;
621    case f_vertexAttrib1v:
622        context->vertexAttrib1fv(index, array.data(), array.size());
623        break;
624    case f_vertexAttrib2v:
625        context->vertexAttrib2fv(index, array.data(), array.size());
626        break;
627    case f_vertexAttrib3v:
628        context->vertexAttrib3fv(index, array.data(), array.size());
629        break;
630    case f_vertexAttrib4v:
631        context->vertexAttrib4fv(index, array.data(), array.size());
632        break;
633    }
634
635    setDOMException(exec, ec);
636    return jsUndefined();
637}
638
639static JSC::JSValue dataFunctioni(DataFunctionToCall f, JSC::ExecState* exec, const JSC::ArgList& args, WebGLRenderingContext* context)
640{
641    if (args.size() != 2)
642        return throwError(exec, SyntaxError);
643
644    WebGLUniformLocation* location = toWebGLUniformLocation(args.at(0));
645
646    if (exec->hadException())
647        return jsUndefined();
648
649    RefPtr<WebGLIntArray> webGLArray = toWebGLIntArray(args.at(1));
650    if (exec->hadException())
651        return jsUndefined();
652
653    ExceptionCode ec = 0;
654    if (webGLArray) {
655        switch (f) {
656        case f_uniform1v:
657            context->uniform1iv(location, webGLArray.get(), ec);
658            break;
659        case f_uniform2v:
660            context->uniform2iv(location, webGLArray.get(), ec);
661            break;
662        case f_uniform3v:
663            context->uniform3iv(location, webGLArray.get(), ec);
664            break;
665        case f_uniform4v:
666            context->uniform4iv(location, webGLArray.get(), ec);
667            break;
668        default:
669            break;
670        }
671
672        setDOMException(exec, ec);
673        return jsUndefined();
674    }
675
676
677    Vector<int, 64> array;
678    if (!toVector(exec, args.at(1), array))
679        return throwError(exec, TypeError);
680
681    switch (f) {
682    case f_uniform1v:
683        context->uniform1iv(location, array.data(), array.size(), ec);
684        break;
685    case f_uniform2v:
686        context->uniform2iv(location, array.data(), array.size(), ec);
687        break;
688    case f_uniform3v:
689        context->uniform3iv(location, array.data(), array.size(), ec);
690        break;
691    case f_uniform4v:
692        context->uniform4iv(location, array.data(), array.size(), ec);
693        break;
694    default:
695        break;
696    }
697
698    setDOMException(exec, ec);
699    return jsUndefined();
700}
701
702static JSC::JSValue dataFunctionMatrix(DataFunctionMatrixToCall f, JSC::ExecState* exec, const JSC::ArgList& args, WebGLRenderingContext* context)
703{
704    if (args.size() != 3)
705        return throwError(exec, SyntaxError);
706
707    WebGLUniformLocation* location = toWebGLUniformLocation(args.at(0));
708
709    if (exec->hadException())
710        return jsUndefined();
711
712    bool transpose = args.at(1).toBoolean(exec);
713    if (exec->hadException())
714        return jsUndefined();
715
716    RefPtr<WebGLFloatArray> webGLArray = toWebGLFloatArray(args.at(2));
717    if (exec->hadException())
718        return jsUndefined();
719
720    ExceptionCode ec = 0;
721    if (webGLArray) {
722        switch (f) {
723        case f_uniformMatrix2fv:
724            context->uniformMatrix2fv(location, transpose, webGLArray.get(), ec);
725            break;
726        case f_uniformMatrix3fv:
727            context->uniformMatrix3fv(location, transpose, webGLArray.get(), ec);
728            break;
729        case f_uniformMatrix4fv:
730            context->uniformMatrix4fv(location, transpose, webGLArray.get(), ec);
731            break;
732        }
733
734        setDOMException(exec, ec);
735        return jsUndefined();
736    }
737
738    Vector<float, 64> array;
739    if (!toVector(exec, args.at(2), array))
740        return throwError(exec, TypeError);
741
742    switch (f) {
743    case f_uniformMatrix2fv:
744        context->uniformMatrix2fv(location, transpose, array.data(), array.size(), ec);
745        break;
746    case f_uniformMatrix3fv:
747        context->uniformMatrix3fv(location, transpose, array.data(), array.size(), ec);
748        break;
749    case f_uniformMatrix4fv:
750        context->uniformMatrix4fv(location, transpose, array.data(), array.size(), ec);
751        break;
752    }
753
754    setDOMException(exec, ec);
755    return jsUndefined();
756}
757
758JSC::JSValue JSWebGLRenderingContext::uniform1fv(JSC::ExecState* exec, const JSC::ArgList& args)
759{
760    return dataFunctionf(f_uniform1v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
761}
762
763JSC::JSValue JSWebGLRenderingContext::uniform1iv(JSC::ExecState* exec, const JSC::ArgList& args)
764{
765    return dataFunctioni(f_uniform1v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
766}
767
768JSC::JSValue JSWebGLRenderingContext::uniform2fv(JSC::ExecState* exec, const JSC::ArgList& args)
769{
770    return dataFunctionf(f_uniform2v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
771}
772
773JSC::JSValue JSWebGLRenderingContext::uniform2iv(JSC::ExecState* exec, const JSC::ArgList& args)
774{
775    return dataFunctioni(f_uniform2v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
776}
777
778JSC::JSValue JSWebGLRenderingContext::uniform3fv(JSC::ExecState* exec, const JSC::ArgList& args)
779{
780    return dataFunctionf(f_uniform3v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
781}
782
783JSC::JSValue JSWebGLRenderingContext::uniform3iv(JSC::ExecState* exec, const JSC::ArgList& args)
784{
785    return dataFunctioni(f_uniform3v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
786}
787
788JSC::JSValue JSWebGLRenderingContext::uniform4fv(JSC::ExecState* exec, const JSC::ArgList& args)
789{
790    return dataFunctionf(f_uniform4v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
791}
792
793JSC::JSValue JSWebGLRenderingContext::uniform4iv(JSC::ExecState* exec, const JSC::ArgList& args)
794{
795    return dataFunctioni(f_uniform4v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
796}
797
798JSC::JSValue JSWebGLRenderingContext::uniformMatrix2fv(JSC::ExecState* exec, const JSC::ArgList& args)
799{
800    return dataFunctionMatrix(f_uniformMatrix2fv, exec, args, static_cast<WebGLRenderingContext*>(impl()));
801}
802
803JSC::JSValue JSWebGLRenderingContext::uniformMatrix3fv(JSC::ExecState* exec, const JSC::ArgList& args)
804{
805    return dataFunctionMatrix(f_uniformMatrix3fv, exec, args, static_cast<WebGLRenderingContext*>(impl()));
806}
807
808JSC::JSValue JSWebGLRenderingContext::uniformMatrix4fv(JSC::ExecState* exec, const JSC::ArgList& args)
809{
810    return dataFunctionMatrix(f_uniformMatrix4fv, exec, args, static_cast<WebGLRenderingContext*>(impl()));
811}
812
813JSC::JSValue JSWebGLRenderingContext::vertexAttrib1fv(JSC::ExecState* exec, const JSC::ArgList& args)
814{
815    return dataFunctionf(f_vertexAttrib1v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
816}
817
818JSC::JSValue JSWebGLRenderingContext::vertexAttrib2fv(JSC::ExecState* exec, const JSC::ArgList& args)
819{
820    return dataFunctionf(f_vertexAttrib2v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
821}
822
823JSC::JSValue JSWebGLRenderingContext::vertexAttrib3fv(JSC::ExecState* exec, const JSC::ArgList& args)
824{
825    return dataFunctionf(f_vertexAttrib3v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
826}
827
828JSC::JSValue JSWebGLRenderingContext::vertexAttrib4fv(JSC::ExecState* exec, const JSC::ArgList& args)
829{
830    return dataFunctionf(f_vertexAttrib4v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
831}
832
833} // namespace WebCore
834
835#endif // ENABLE(3D_CANVAS)
836