Home | History | Annotate | Download | only in js
      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 
     63 using namespace JSC;
     64 
     65 namespace WebCore {
     66 
     67 JSValue 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 
     89 JSValue 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 
    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::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 
    145 enum ObjectType {
    146     kBuffer, kRenderbuffer, kTexture, kVertexAttrib
    147 };
    148 
    149 static 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 
    188 enum WhichProgramCall {
    189     kProgramParameter, kUniform
    190 };
    191 
    192 JSValue JSWebGLRenderingContext::getBufferParameter(ExecState* exec, const ArgList& args)
    193 {
    194     return getObjectParameter(this, exec, args, kBuffer);
    195 }
    196 
    197 JSValue 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 
    221 JSValue 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 
    239 JSValue 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 
    258 JSValue JSWebGLRenderingContext::getRenderbufferParameter(ExecState* exec, const ArgList& args)
    259 {
    260     return getObjectParameter(this, exec, args, kRenderbuffer);
    261 }
    262 
    263 JSValue 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 
    282 JSValue JSWebGLRenderingContext::getTexParameter(ExecState* exec, const ArgList& args)
    283 {
    284     return getObjectParameter(this, exec, args, kTexture);
    285 }
    286 
    287 JSValue 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 
    306 JSValue 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);
    316 JSValue 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);
    417 JSValue 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 
    508 template<typename T, size_t inlineCapacity>
    509 bool 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 
    528 enum DataFunctionToCall {
    529     f_uniform1v, f_uniform2v, f_uniform3v, f_uniform4v,
    530     f_vertexAttrib1v, f_vertexAttrib2v, f_vertexAttrib3v, f_vertexAttrib4v
    531 };
    532 
    533 enum DataFunctionMatrixToCall {
    534     f_uniformMatrix2fv, f_uniformMatrix3fv, f_uniformMatrix4fv
    535 };
    536 
    537 static 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 
    551 static 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 
    639 static 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 
    702 static 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 
    758 JSC::JSValue JSWebGLRenderingContext::uniform1fv(JSC::ExecState* exec, const JSC::ArgList& args)
    759 {
    760     return dataFunctionf(f_uniform1v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
    761 }
    762 
    763 JSC::JSValue JSWebGLRenderingContext::uniform1iv(JSC::ExecState* exec, const JSC::ArgList& args)
    764 {
    765     return dataFunctioni(f_uniform1v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
    766 }
    767 
    768 JSC::JSValue JSWebGLRenderingContext::uniform2fv(JSC::ExecState* exec, const JSC::ArgList& args)
    769 {
    770     return dataFunctionf(f_uniform2v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
    771 }
    772 
    773 JSC::JSValue JSWebGLRenderingContext::uniform2iv(JSC::ExecState* exec, const JSC::ArgList& args)
    774 {
    775     return dataFunctioni(f_uniform2v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
    776 }
    777 
    778 JSC::JSValue JSWebGLRenderingContext::uniform3fv(JSC::ExecState* exec, const JSC::ArgList& args)
    779 {
    780     return dataFunctionf(f_uniform3v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
    781 }
    782 
    783 JSC::JSValue JSWebGLRenderingContext::uniform3iv(JSC::ExecState* exec, const JSC::ArgList& args)
    784 {
    785     return dataFunctioni(f_uniform3v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
    786 }
    787 
    788 JSC::JSValue JSWebGLRenderingContext::uniform4fv(JSC::ExecState* exec, const JSC::ArgList& args)
    789 {
    790     return dataFunctionf(f_uniform4v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
    791 }
    792 
    793 JSC::JSValue JSWebGLRenderingContext::uniform4iv(JSC::ExecState* exec, const JSC::ArgList& args)
    794 {
    795     return dataFunctioni(f_uniform4v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
    796 }
    797 
    798 JSC::JSValue JSWebGLRenderingContext::uniformMatrix2fv(JSC::ExecState* exec, const JSC::ArgList& args)
    799 {
    800     return dataFunctionMatrix(f_uniformMatrix2fv, exec, args, static_cast<WebGLRenderingContext*>(impl()));
    801 }
    802 
    803 JSC::JSValue JSWebGLRenderingContext::uniformMatrix3fv(JSC::ExecState* exec, const JSC::ArgList& args)
    804 {
    805     return dataFunctionMatrix(f_uniformMatrix3fv, exec, args, static_cast<WebGLRenderingContext*>(impl()));
    806 }
    807 
    808 JSC::JSValue JSWebGLRenderingContext::uniformMatrix4fv(JSC::ExecState* exec, const JSC::ArgList& args)
    809 {
    810     return dataFunctionMatrix(f_uniformMatrix4fv, exec, args, static_cast<WebGLRenderingContext*>(impl()));
    811 }
    812 
    813 JSC::JSValue JSWebGLRenderingContext::vertexAttrib1fv(JSC::ExecState* exec, const JSC::ArgList& args)
    814 {
    815     return dataFunctionf(f_vertexAttrib1v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
    816 }
    817 
    818 JSC::JSValue JSWebGLRenderingContext::vertexAttrib2fv(JSC::ExecState* exec, const JSC::ArgList& args)
    819 {
    820     return dataFunctionf(f_vertexAttrib2v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
    821 }
    822 
    823 JSC::JSValue JSWebGLRenderingContext::vertexAttrib3fv(JSC::ExecState* exec, const JSC::ArgList& args)
    824 {
    825     return dataFunctionf(f_vertexAttrib3v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
    826 }
    827 
    828 JSC::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