Home | History | Annotate | Download | only in custom
      1 /*
      2  * Copyright (C) 2009 Google 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 are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "V8WebGLRenderingContext.h"
     33 
     34 #include "V8ANGLEInstancedArrays.h"
     35 #include "V8EXTFragDepth.h"
     36 #include "V8EXTTextureFilterAnisotropic.h"
     37 #include "V8HTMLCanvasElement.h"
     38 #include "V8HTMLImageElement.h"
     39 #include "V8HTMLVideoElement.h"
     40 #include "V8ImageData.h"
     41 #include "V8OESElementIndexUint.h"
     42 #include "V8OESStandardDerivatives.h"
     43 #include "V8OESTextureFloat.h"
     44 #include "V8OESTextureFloatLinear.h"
     45 #include "V8OESTextureHalfFloat.h"
     46 #include "V8OESTextureHalfFloatLinear.h"
     47 #include "V8OESVertexArrayObject.h"
     48 #include "V8WebGLBuffer.h"
     49 #include "V8WebGLCompressedTextureATC.h"
     50 #include "V8WebGLCompressedTexturePVRTC.h"
     51 #include "V8WebGLCompressedTextureS3TC.h"
     52 #include "V8WebGLDebugRendererInfo.h"
     53 #include "V8WebGLDebugShaders.h"
     54 #include "V8WebGLDepthTexture.h"
     55 #include "V8WebGLDrawBuffers.h"
     56 #include "V8WebGLFramebuffer.h"
     57 #include "V8WebGLLoseContext.h"
     58 #include "V8WebGLProgram.h"
     59 #include "V8WebGLRenderbuffer.h"
     60 #include "V8WebGLShader.h"
     61 #include "V8WebGLTexture.h"
     62 #include "V8WebGLUniformLocation.h"
     63 #include "V8WebGLVertexArrayObjectOES.h"
     64 #include "bindings/v8/V8Binding.h"
     65 #include "bindings/v8/V8HiddenPropertyName.h"
     66 #include "bindings/v8/custom/V8ArrayBufferViewCustom.h"
     67 #include "bindings/v8/custom/V8Float32ArrayCustom.h"
     68 #include "bindings/v8/custom/V8Int16ArrayCustom.h"
     69 #include "bindings/v8/custom/V8Int32ArrayCustom.h"
     70 #include "bindings/v8/custom/V8Int8ArrayCustom.h"
     71 #include "bindings/v8/custom/V8Uint16ArrayCustom.h"
     72 #include "bindings/v8/custom/V8Uint32ArrayCustom.h"
     73 #include "bindings/v8/custom/V8Uint8ArrayCustom.h"
     74 #include "core/dom/ExceptionCode.h"
     75 #include "core/html/canvas/WebGLRenderingContext.h"
     76 #include "core/platform/NotImplemented.h"
     77 #include <limits>
     78 #include "wtf/FastMalloc.h"
     79 
     80 namespace WebCore {
     81 
     82 // Allocates new storage via fastMalloc.
     83 // Returns NULL if array failed to convert for any reason.
     84 static float* jsArrayToFloatArray(v8::Handle<v8::Array> array, uint32_t len)
     85 {
     86     // Convert the data element-by-element.
     87     if (len > std::numeric_limits<uint32_t>::max() / sizeof(float))
     88         return 0;
     89     float* data = static_cast<float*>(fastMalloc(len * sizeof(float)));
     90 
     91     for (uint32_t i = 0; i < len; i++) {
     92         v8::Local<v8::Value> val = array->Get(i);
     93         if (!val->IsNumber()) {
     94             fastFree(data);
     95             return 0;
     96         }
     97         data[i] = toFloat(val);
     98     }
     99     return data;
    100 }
    101 
    102 // Allocates new storage via fastMalloc.
    103 // Returns NULL if array failed to convert for any reason.
    104 static int* jsArrayToIntArray(v8::Handle<v8::Array> array, uint32_t len)
    105 {
    106     // Convert the data element-by-element.
    107     if (len > std::numeric_limits<uint32_t>::max() / sizeof(int))
    108         return 0;
    109     int* data = static_cast<int*>(fastMalloc(len * sizeof(int)));
    110 
    111     for (uint32_t i = 0; i < len; i++) {
    112         v8::Local<v8::Value> val = array->Get(i);
    113         bool ok;
    114         int ival = toInt32(val, ok);
    115         if (!ok) {
    116             fastFree(data);
    117             return 0;
    118         }
    119         data[i] = ival;
    120     }
    121     return data;
    122 }
    123 
    124 static v8::Handle<v8::Value> toV8Object(const WebGLGetInfo& info, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
    125 {
    126     switch (info.getType()) {
    127     case WebGLGetInfo::kTypeBool:
    128         return v8::Boolean::New(info.getBool());
    129     case WebGLGetInfo::kTypeBoolArray: {
    130         const Vector<bool>& value = info.getBoolArray();
    131         v8::Local<v8::Array> array = v8::Array::New(value.size());
    132         for (size_t ii = 0; ii < value.size(); ++ii)
    133             array->Set(v8::Integer::New(ii, isolate), v8::Boolean::New(value[ii]));
    134         return array;
    135     }
    136     case WebGLGetInfo::kTypeFloat:
    137         return v8::Number::New(info.getFloat());
    138     case WebGLGetInfo::kTypeInt:
    139         return v8::Integer::New(info.getInt(), isolate);
    140     case WebGLGetInfo::kTypeNull:
    141         return v8::Null(isolate);
    142     case WebGLGetInfo::kTypeString:
    143         return v8String(info.getString(), isolate);
    144     case WebGLGetInfo::kTypeUnsignedInt:
    145         return v8::Integer::NewFromUnsigned(info.getUnsignedInt(), isolate);
    146     case WebGLGetInfo::kTypeWebGLBuffer:
    147         return toV8(info.getWebGLBuffer(), creationContext, isolate);
    148     case WebGLGetInfo::kTypeWebGLFloatArray:
    149         return toV8(info.getWebGLFloatArray(), creationContext, isolate);
    150     case WebGLGetInfo::kTypeWebGLFramebuffer:
    151         return toV8(info.getWebGLFramebuffer(), creationContext, isolate);
    152     case WebGLGetInfo::kTypeWebGLIntArray:
    153         return toV8(info.getWebGLIntArray(), creationContext, isolate);
    154     // FIXME: implement WebGLObjectArray
    155     // case WebGLGetInfo::kTypeWebGLObjectArray:
    156     case WebGLGetInfo::kTypeWebGLProgram:
    157         return toV8(info.getWebGLProgram(), creationContext, isolate);
    158     case WebGLGetInfo::kTypeWebGLRenderbuffer:
    159         return toV8(info.getWebGLRenderbuffer(), creationContext, isolate);
    160     case WebGLGetInfo::kTypeWebGLTexture:
    161         return toV8(info.getWebGLTexture(), creationContext, isolate);
    162     case WebGLGetInfo::kTypeWebGLUnsignedByteArray:
    163         return toV8(info.getWebGLUnsignedByteArray(), creationContext, isolate);
    164     case WebGLGetInfo::kTypeWebGLUnsignedIntArray:
    165         return toV8(info.getWebGLUnsignedIntArray(), creationContext, isolate);
    166     case WebGLGetInfo::kTypeWebGLVertexArrayObjectOES:
    167         return toV8(info.getWebGLVertexArrayObjectOES(), creationContext, isolate);
    168     default:
    169         notImplemented();
    170         return v8::Undefined();
    171     }
    172 }
    173 
    174 static v8::Handle<v8::Value> toV8Object(WebGLExtension* extension, v8::Handle<v8::Object> contextObject, v8::Isolate* isolate)
    175 {
    176     if (!extension)
    177         return v8::Null(isolate);
    178     v8::Handle<v8::Value> extensionObject;
    179     const char* referenceName = 0;
    180     switch (extension->getName()) {
    181     case WebGLExtension::ANGLEInstancedArraysName:
    182         extensionObject = toV8(static_cast<ANGLEInstancedArrays*>(extension), contextObject, isolate);
    183         referenceName = "angleInstancedArraysName";
    184         break;
    185     case WebGLExtension::EXTFragDepthName:
    186         extensionObject = toV8(static_cast<EXTFragDepth*>(extension), contextObject, isolate);
    187         referenceName = "extFragDepthName";
    188         break;
    189     case WebGLExtension::EXTTextureFilterAnisotropicName:
    190         extensionObject = toV8(static_cast<EXTTextureFilterAnisotropic*>(extension), contextObject, isolate);
    191         referenceName = "extTextureFilterAnisotropicName";
    192         break;
    193     case WebGLExtension::OESElementIndexUintName:
    194         extensionObject = toV8(static_cast<OESElementIndexUint*>(extension), contextObject, isolate);
    195         referenceName = "oesElementIndexUintName";
    196         break;
    197     case WebGLExtension::OESStandardDerivativesName:
    198         extensionObject = toV8(static_cast<OESStandardDerivatives*>(extension), contextObject, isolate);
    199         referenceName = "oesStandardDerivativesName";
    200         break;
    201     case WebGLExtension::OESTextureFloatName:
    202         extensionObject = toV8(static_cast<OESTextureFloat*>(extension), contextObject, isolate);
    203         referenceName = "oesTextureFloatName";
    204         break;
    205     case WebGLExtension::OESTextureFloatLinearName:
    206         extensionObject = toV8(static_cast<OESTextureFloatLinear*>(extension), contextObject, isolate);
    207         referenceName = "oesTextureFloatLinearName";
    208         break;
    209     case WebGLExtension::OESTextureHalfFloatName:
    210         extensionObject = toV8(static_cast<OESTextureHalfFloat*>(extension), contextObject, isolate);
    211         referenceName = "oesTextureHalfFloatName";
    212         break;
    213     case WebGLExtension::OESTextureHalfFloatLinearName:
    214         extensionObject = toV8(static_cast<OESTextureHalfFloatLinear*>(extension), contextObject, isolate);
    215         referenceName = "oesTextureHalfFloatLinearName";
    216         break;
    217     case WebGLExtension::OESVertexArrayObjectName:
    218         extensionObject = toV8(static_cast<OESVertexArrayObject*>(extension), contextObject, isolate);
    219         referenceName = "oesVertexArrayObjectName";
    220         break;
    221     case WebGLExtension::WebGLCompressedTextureATCName:
    222         extensionObject = toV8(static_cast<WebGLCompressedTextureATC*>(extension), contextObject, isolate);
    223         referenceName = "webGLCompressedTextureATCName";
    224     case WebGLExtension::WebGLCompressedTexturePVRTCName:
    225         extensionObject = toV8(static_cast<WebGLCompressedTexturePVRTC*>(extension), contextObject, isolate);
    226         referenceName = "webGLCompressedTexturePVRTCName";
    227         break;
    228     case WebGLExtension::WebGLCompressedTextureS3TCName:
    229         extensionObject = toV8(static_cast<WebGLCompressedTextureS3TC*>(extension), contextObject, isolate);
    230         referenceName = "webGLCompressedTextureS3TCName";
    231         break;
    232     case WebGLExtension::WebGLDebugRendererInfoName:
    233         extensionObject = toV8(static_cast<WebGLDebugRendererInfo*>(extension), contextObject, isolate);
    234         referenceName = "webGLDebugRendererInfoName";
    235         break;
    236     case WebGLExtension::WebGLDebugShadersName:
    237         extensionObject = toV8(static_cast<WebGLDebugShaders*>(extension), contextObject, isolate);
    238         referenceName = "webGLDebugShadersName";
    239         break;
    240     case WebGLExtension::WebGLDepthTextureName:
    241         extensionObject = toV8(static_cast<WebGLDepthTexture*>(extension), contextObject, isolate);
    242         referenceName = "webGLDepthTextureName";
    243         break;
    244     case WebGLExtension::WebGLDrawBuffersName:
    245         extensionObject = toV8(static_cast<WebGLDrawBuffers*>(extension), contextObject, isolate);
    246         referenceName = "webGLDrawBuffersName";
    247         break;
    248     case WebGLExtension::WebGLLoseContextName:
    249         extensionObject = toV8(static_cast<WebGLLoseContext*>(extension), contextObject, isolate);
    250         referenceName = "webGLLoseContextName";
    251         break;
    252     }
    253     ASSERT(!extensionObject.IsEmpty());
    254     V8HiddenPropertyName::setNamedHiddenReference(contextObject, referenceName, extensionObject);
    255     return extensionObject;
    256 }
    257 
    258 enum ObjectType {
    259     kBuffer, kRenderbuffer, kTexture, kVertexAttrib
    260 };
    261 
    262 static void getObjectParameter(const v8::FunctionCallbackInfo<v8::Value>& args, ObjectType objectType)
    263 {
    264     if (args.Length() != 2) {
    265         throwNotEnoughArgumentsError(args.GetIsolate());
    266         return;
    267     }
    268 
    269     WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
    270     unsigned target = toInt32(args[0]);
    271     unsigned pname = toInt32(args[1]);
    272     WebGLGetInfo info;
    273     switch (objectType) {
    274     case kBuffer:
    275         info = context->getBufferParameter(target, pname);
    276         break;
    277     case kRenderbuffer:
    278         info = context->getRenderbufferParameter(target, pname);
    279         break;
    280     case kTexture:
    281         info = context->getTexParameter(target, pname);
    282         break;
    283     case kVertexAttrib:
    284         // target => index
    285         info = context->getVertexAttrib(target, pname);
    286         break;
    287     default:
    288         notImplemented();
    289         break;
    290     }
    291     v8SetReturnValue(args, toV8Object(info, args.Holder(), args.GetIsolate()));
    292 }
    293 
    294 static WebGLUniformLocation* toWebGLUniformLocation(v8::Handle<v8::Value> value, bool& ok, v8::Isolate* isolate)
    295 {
    296     ok = false;
    297     WebGLUniformLocation* location = 0;
    298     if (V8WebGLUniformLocation::HasInstance(value, isolate, worldType(isolate))) {
    299         location = V8WebGLUniformLocation::toNative(value->ToObject());
    300         ok = true;
    301     }
    302     return location;
    303 }
    304 
    305 enum WhichProgramCall {
    306     kProgramParameter, kUniform
    307 };
    308 
    309 void V8WebGLRenderingContext::getAttachedShadersMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    310 {
    311     if (args.Length() < 1) {
    312         throwNotEnoughArgumentsError(args.GetIsolate());
    313         return;
    314     }
    315 
    316     WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
    317     if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLProgram::HasInstance(args[0], args.GetIsolate(), worldType(args.GetIsolate()))) {
    318         throwTypeError(args.GetIsolate());
    319         return;
    320     }
    321     WebGLProgram* program = V8WebGLProgram::HasInstance(args[0], args.GetIsolate(), worldType(args.GetIsolate())) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
    322     Vector<RefPtr<WebGLShader> > shaders;
    323     bool succeed = context->getAttachedShaders(program, shaders);
    324     if (!succeed) {
    325         v8SetReturnValueNull(args);
    326         return;
    327     }
    328     v8::Local<v8::Array> array = v8::Array::New(shaders.size());
    329     for (size_t ii = 0; ii < shaders.size(); ++ii)
    330         array->Set(v8::Integer::New(ii, args.GetIsolate()), toV8(shaders[ii].get(), args.Holder(), args.GetIsolate()));
    331     v8SetReturnValue(args, array);
    332 }
    333 
    334 void V8WebGLRenderingContext::getBufferParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    335 {
    336     getObjectParameter(args, kBuffer);
    337 }
    338 
    339 void V8WebGLRenderingContext::getExtensionMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    340 {
    341     WebGLRenderingContext* imp = V8WebGLRenderingContext::toNative(args.Holder());
    342     if (args.Length() < 1) {
    343         throwNotEnoughArgumentsError(args.GetIsolate());
    344         return;
    345     }
    346     V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, name, args[0]);
    347     RefPtr<WebGLExtension> extension(imp->getExtension(name));
    348     v8SetReturnValue(args, toV8Object(extension.get(), args.Holder(), args.GetIsolate()));
    349 }
    350 
    351 void V8WebGLRenderingContext::getFramebufferAttachmentParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    352 {
    353     if (args.Length() != 3) {
    354         throwNotEnoughArgumentsError(args.GetIsolate());
    355         return;
    356     }
    357 
    358     WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
    359     unsigned target = toInt32(args[0]);
    360     unsigned attachment = toInt32(args[1]);
    361     unsigned pname = toInt32(args[2]);
    362     WebGLGetInfo info = context->getFramebufferAttachmentParameter(target, attachment, pname);
    363     v8SetReturnValue(args, toV8Object(info, args.Holder(), args.GetIsolate()));
    364 }
    365 
    366 void V8WebGLRenderingContext::getParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    367 {
    368     if (args.Length() != 1) {
    369         throwNotEnoughArgumentsError(args.GetIsolate());
    370         return;
    371     }
    372 
    373     WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
    374     unsigned pname = toInt32(args[0]);
    375     WebGLGetInfo info = context->getParameter(pname);
    376     v8SetReturnValue(args, toV8Object(info, args.Holder(), args.GetIsolate()));
    377 }
    378 
    379 void V8WebGLRenderingContext::getProgramParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    380 {
    381     if (args.Length() != 2) {
    382         throwNotEnoughArgumentsError(args.GetIsolate());
    383         return;
    384     }
    385 
    386     WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
    387     if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLProgram::HasInstance(args[0], args.GetIsolate(), worldType(args.GetIsolate()))) {
    388         throwTypeError(args.GetIsolate());
    389         return;
    390     }
    391     WebGLProgram* program = V8WebGLProgram::HasInstance(args[0], args.GetIsolate(), worldType(args.GetIsolate())) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
    392     unsigned pname = toInt32(args[1]);
    393     WebGLGetInfo info = context->getProgramParameter(program, pname);
    394     v8SetReturnValue(args, toV8Object(info, args.Holder(), args.GetIsolate()));
    395 }
    396 
    397 void V8WebGLRenderingContext::getRenderbufferParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    398 {
    399     getObjectParameter(args, kRenderbuffer);
    400 }
    401 
    402 void V8WebGLRenderingContext::getShaderParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    403 {
    404     if (args.Length() != 2) {
    405         throwNotEnoughArgumentsError(args.GetIsolate());
    406         return;
    407     }
    408 
    409     WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
    410     if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLShader::HasInstance(args[0], args.GetIsolate(), worldType(args.GetIsolate()))) {
    411         throwTypeError(args.GetIsolate());
    412         return;
    413     }
    414     WebGLShader* shader = V8WebGLShader::HasInstance(args[0], args.GetIsolate(), worldType(args.GetIsolate())) ? V8WebGLShader::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
    415     unsigned pname = toInt32(args[1]);
    416     WebGLGetInfo info = context->getShaderParameter(shader, pname);
    417     v8SetReturnValue(args, toV8Object(info, args.Holder(), args.GetIsolate()));
    418 }
    419 
    420 void V8WebGLRenderingContext::getSupportedExtensionsMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    421 {
    422     WebGLRenderingContext* imp = V8WebGLRenderingContext::toNative(args.Holder());
    423     if (imp->isContextLost()) {
    424         v8SetReturnValueNull(args);
    425         return;
    426     }
    427 
    428     Vector<String> value = imp->getSupportedExtensions();
    429     v8::Local<v8::Array> array = v8::Array::New(value.size());
    430     for (size_t ii = 0; ii < value.size(); ++ii)
    431         array->Set(v8::Integer::New(ii, args.GetIsolate()), v8String(value[ii], args.GetIsolate()));
    432     v8SetReturnValue(args, array);
    433 }
    434 
    435 void V8WebGLRenderingContext::getTexParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    436 {
    437     getObjectParameter(args, kTexture);
    438 }
    439 
    440 void V8WebGLRenderingContext::getUniformMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    441 {
    442     if (args.Length() != 2) {
    443         throwNotEnoughArgumentsError(args.GetIsolate());
    444         return;
    445     }
    446 
    447     WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
    448     if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLProgram::HasInstance(args[0], args.GetIsolate(), worldType(args.GetIsolate()))) {
    449         throwTypeError(args.GetIsolate());
    450         return;
    451     }
    452     WebGLProgram* program = V8WebGLProgram::HasInstance(args[0], args.GetIsolate(), worldType(args.GetIsolate())) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
    453 
    454     if (args.Length() > 1 && !isUndefinedOrNull(args[1]) && !V8WebGLUniformLocation::HasInstance(args[1], args.GetIsolate(), worldType(args.GetIsolate()))) {
    455         throwTypeError(args.GetIsolate());
    456         return;
    457     }
    458     bool ok = false;
    459     WebGLUniformLocation* location = toWebGLUniformLocation(args[1], ok, args.GetIsolate());
    460 
    461     WebGLGetInfo info = context->getUniform(program, location);
    462     v8SetReturnValue(args, toV8Object(info, args.Holder(), args.GetIsolate()));
    463 }
    464 
    465 void V8WebGLRenderingContext::getVertexAttribMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    466 {
    467     getObjectParameter(args, kVertexAttrib);
    468 }
    469 
    470 enum FunctionToCall {
    471     kUniform1v, kUniform2v, kUniform3v, kUniform4v,
    472     kVertexAttrib1v, kVertexAttrib2v, kVertexAttrib3v, kVertexAttrib4v
    473 };
    474 
    475 bool isFunctionToCallForAttribute(FunctionToCall functionToCall)
    476 {
    477     switch (functionToCall) {
    478     case kVertexAttrib1v:
    479     case kVertexAttrib2v:
    480     case kVertexAttrib3v:
    481     case kVertexAttrib4v:
    482         return true;
    483     default:
    484         break;
    485     }
    486     return false;
    487 }
    488 
    489 static void vertexAttribAndUniformHelperf(const v8::FunctionCallbackInfo<v8::Value>& args, FunctionToCall functionToCall)
    490 {
    491     // Forms:
    492     // * glUniform1fv(WebGLUniformLocation location, Array data);
    493     // * glUniform1fv(WebGLUniformLocation location, Float32Array data);
    494     // * glUniform2fv(WebGLUniformLocation location, Array data);
    495     // * glUniform2fv(WebGLUniformLocation location, Float32Array data);
    496     // * glUniform3fv(WebGLUniformLocation location, Array data);
    497     // * glUniform3fv(WebGLUniformLocation location, Float32Array data);
    498     // * glUniform4fv(WebGLUniformLocation location, Array data);
    499     // * glUniform4fv(WebGLUniformLocation location, Float32Array data);
    500     // * glVertexAttrib1fv(GLint index, Array data);
    501     // * glVertexAttrib1fv(GLint index, Float32Array data);
    502     // * glVertexAttrib2fv(GLint index, Array data);
    503     // * glVertexAttrib2fv(GLint index, Float32Array data);
    504     // * glVertexAttrib3fv(GLint index, Array data);
    505     // * glVertexAttrib3fv(GLint index, Float32Array data);
    506     // * glVertexAttrib4fv(GLint index, Array data);
    507     // * glVertexAttrib4fv(GLint index, Float32Array data);
    508 
    509     if (args.Length() != 2) {
    510         throwNotEnoughArgumentsError(args.GetIsolate());
    511         return;
    512     }
    513 
    514     bool ok = false;
    515     int index = -1;
    516     WebGLUniformLocation* location = 0;
    517 
    518     if (isFunctionToCallForAttribute(functionToCall))
    519         index = toInt32(args[0]);
    520     else {
    521         if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLUniformLocation::HasInstance(args[0], args.GetIsolate(), worldType(args.GetIsolate()))) {
    522             throwTypeError(args.GetIsolate());
    523             return;
    524         }
    525         location = toWebGLUniformLocation(args[0], ok, args.GetIsolate());
    526     }
    527 
    528     WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
    529 
    530     if (V8Float32Array::HasInstance(args[1], args.GetIsolate(), worldType(args.GetIsolate()))) {
    531         Float32Array* array = V8Float32Array::toNative(args[1]->ToObject());
    532         ASSERT(array != NULL);
    533         switch (functionToCall) {
    534         case kUniform1v: context->uniform1fv(location, array); break;
    535         case kUniform2v: context->uniform2fv(location, array); break;
    536         case kUniform3v: context->uniform3fv(location, array); break;
    537         case kUniform4v: context->uniform4fv(location, array); break;
    538         case kVertexAttrib1v: context->vertexAttrib1fv(index, array); break;
    539         case kVertexAttrib2v: context->vertexAttrib2fv(index, array); break;
    540         case kVertexAttrib3v: context->vertexAttrib3fv(index, array); break;
    541         case kVertexAttrib4v: context->vertexAttrib4fv(index, array); break;
    542         default: ASSERT_NOT_REACHED(); break;
    543         }
    544         return;
    545     }
    546 
    547     if (args[1].IsEmpty() || !args[1]->IsArray()) {
    548         throwTypeError(args.GetIsolate());
    549         return;
    550     }
    551     v8::Handle<v8::Array> array =
    552       v8::Local<v8::Array>::Cast(args[1]);
    553     uint32_t len = array->Length();
    554     float* data = jsArrayToFloatArray(array, len);
    555     if (!data) {
    556         // FIXME: consider different / better exception type.
    557         setDOMException(SyntaxError, args.GetIsolate());
    558         return;
    559     }
    560     switch (functionToCall) {
    561     case kUniform1v: context->uniform1fv(location, data, len); break;
    562     case kUniform2v: context->uniform2fv(location, data, len); break;
    563     case kUniform3v: context->uniform3fv(location, data, len); break;
    564     case kUniform4v: context->uniform4fv(location, data, len); break;
    565     case kVertexAttrib1v: context->vertexAttrib1fv(index, data, len); break;
    566     case kVertexAttrib2v: context->vertexAttrib2fv(index, data, len); break;
    567     case kVertexAttrib3v: context->vertexAttrib3fv(index, data, len); break;
    568     case kVertexAttrib4v: context->vertexAttrib4fv(index, data, len); break;
    569     default: ASSERT_NOT_REACHED(); break;
    570     }
    571     fastFree(data);
    572 }
    573 
    574 static void uniformHelperi(const v8::FunctionCallbackInfo<v8::Value>& args, FunctionToCall functionToCall)
    575 {
    576     // Forms:
    577     // * glUniform1iv(GLUniformLocation location, Array data);
    578     // * glUniform1iv(GLUniformLocation location, Int32Array data);
    579     // * glUniform2iv(GLUniformLocation location, Array data);
    580     // * glUniform2iv(GLUniformLocation location, Int32Array data);
    581     // * glUniform3iv(GLUniformLocation location, Array data);
    582     // * glUniform3iv(GLUniformLocation location, Int32Array data);
    583     // * glUniform4iv(GLUniformLocation location, Array data);
    584     // * glUniform4iv(GLUniformLocation location, Int32Array data);
    585 
    586     if (args.Length() != 2) {
    587         throwNotEnoughArgumentsError(args.GetIsolate());
    588         return;
    589     }
    590 
    591     WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
    592     if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLUniformLocation::HasInstance(args[0], args.GetIsolate(), worldType(args.GetIsolate()))) {
    593         throwTypeError(args.GetIsolate());
    594         return;
    595     }
    596     bool ok = false;
    597     WebGLUniformLocation* location = toWebGLUniformLocation(args[0], ok, args.GetIsolate());
    598 
    599     if (V8Int32Array::HasInstance(args[1], args.GetIsolate(), worldType(args.GetIsolate()))) {
    600         Int32Array* array = V8Int32Array::toNative(args[1]->ToObject());
    601         ASSERT(array != NULL);
    602         switch (functionToCall) {
    603         case kUniform1v: context->uniform1iv(location, array); break;
    604         case kUniform2v: context->uniform2iv(location, array); break;
    605         case kUniform3v: context->uniform3iv(location, array); break;
    606         case kUniform4v: context->uniform4iv(location, array); break;
    607         default: ASSERT_NOT_REACHED(); break;
    608         }
    609         return;
    610     }
    611 
    612     if (args[1].IsEmpty() || !args[1]->IsArray()) {
    613         throwTypeError(args.GetIsolate());
    614         return;
    615     }
    616     v8::Handle<v8::Array> array =
    617       v8::Local<v8::Array>::Cast(args[1]);
    618     uint32_t len = array->Length();
    619     int* data = jsArrayToIntArray(array, len);
    620     if (!data) {
    621         // FIXME: consider different / better exception type.
    622         setDOMException(SyntaxError, args.GetIsolate());
    623         return;
    624     }
    625     switch (functionToCall) {
    626     case kUniform1v: context->uniform1iv(location, data, len); break;
    627     case kUniform2v: context->uniform2iv(location, data, len); break;
    628     case kUniform3v: context->uniform3iv(location, data, len); break;
    629     case kUniform4v: context->uniform4iv(location, data, len); break;
    630     default: ASSERT_NOT_REACHED(); break;
    631     }
    632     fastFree(data);
    633 }
    634 
    635 void V8WebGLRenderingContext::uniform1fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    636 {
    637     vertexAttribAndUniformHelperf(args, kUniform1v);
    638 }
    639 
    640 void V8WebGLRenderingContext::uniform1ivMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    641 {
    642     uniformHelperi(args, kUniform1v);
    643 }
    644 
    645 void V8WebGLRenderingContext::uniform2fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    646 {
    647     vertexAttribAndUniformHelperf(args, kUniform2v);
    648 }
    649 
    650 void V8WebGLRenderingContext::uniform2ivMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    651 {
    652     uniformHelperi(args, kUniform2v);
    653 }
    654 
    655 void V8WebGLRenderingContext::uniform3fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    656 {
    657     vertexAttribAndUniformHelperf(args, kUniform3v);
    658 }
    659 
    660 void V8WebGLRenderingContext::uniform3ivMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    661 {
    662     uniformHelperi(args, kUniform3v);
    663 }
    664 
    665 void V8WebGLRenderingContext::uniform4fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    666 {
    667     vertexAttribAndUniformHelperf(args, kUniform4v);
    668 }
    669 
    670 void V8WebGLRenderingContext::uniform4ivMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    671 {
    672     uniformHelperi(args, kUniform4v);
    673 }
    674 
    675 static void uniformMatrixHelper(const v8::FunctionCallbackInfo<v8::Value>& args, int matrixSize)
    676 {
    677     // Forms:
    678     // * glUniformMatrix2fv(GLint location, GLboolean transpose, Array data);
    679     // * glUniformMatrix2fv(GLint location, GLboolean transpose, Float32Array data);
    680     // * glUniformMatrix3fv(GLint location, GLboolean transpose, Array data);
    681     // * glUniformMatrix3fv(GLint location, GLboolean transpose, Float32Array data);
    682     // * glUniformMatrix4fv(GLint location, GLboolean transpose, Array data);
    683     // * glUniformMatrix4fv(GLint location, GLboolean transpose, Float32Array data);
    684     //
    685     // FIXME: need to change to accept Float32Array as well.
    686     if (args.Length() != 3) {
    687         throwNotEnoughArgumentsError(args.GetIsolate());
    688         return;
    689     }
    690 
    691     WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
    692 
    693     if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLUniformLocation::HasInstance(args[0], args.GetIsolate(), worldType(args.GetIsolate()))) {
    694         throwTypeError(args.GetIsolate());
    695         return;
    696     }
    697     bool ok = false;
    698     WebGLUniformLocation* location = toWebGLUniformLocation(args[0], ok, args.GetIsolate());
    699 
    700     bool transpose = args[1]->BooleanValue();
    701     if (V8Float32Array::HasInstance(args[2], args.GetIsolate(), worldType(args.GetIsolate()))) {
    702         Float32Array* array = V8Float32Array::toNative(args[2]->ToObject());
    703         ASSERT(array != NULL);
    704         switch (matrixSize) {
    705         case 2: context->uniformMatrix2fv(location, transpose, array); break;
    706         case 3: context->uniformMatrix3fv(location, transpose, array); break;
    707         case 4: context->uniformMatrix4fv(location, transpose, array); break;
    708         default: ASSERT_NOT_REACHED(); break;
    709         }
    710         return;
    711     }
    712 
    713     if (args[2].IsEmpty() || !args[2]->IsArray()) {
    714         throwTypeError(args.GetIsolate());
    715         return;
    716     }
    717     v8::Handle<v8::Array> array =
    718       v8::Local<v8::Array>::Cast(args[2]);
    719     uint32_t len = array->Length();
    720     float* data = jsArrayToFloatArray(array, len);
    721     if (!data) {
    722         // FIXME: consider different / better exception type.
    723         setDOMException(SyntaxError, args.GetIsolate());
    724         return;
    725     }
    726     switch (matrixSize) {
    727     case 2: context->uniformMatrix2fv(location, transpose, data, len); break;
    728     case 3: context->uniformMatrix3fv(location, transpose, data, len); break;
    729     case 4: context->uniformMatrix4fv(location, transpose, data, len); break;
    730     default: ASSERT_NOT_REACHED(); break;
    731     }
    732     fastFree(data);
    733 }
    734 
    735 void V8WebGLRenderingContext::uniformMatrix2fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    736 {
    737     uniformMatrixHelper(args, 2);
    738 }
    739 
    740 void V8WebGLRenderingContext::uniformMatrix3fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    741 {
    742     uniformMatrixHelper(args, 3);
    743 }
    744 
    745 void V8WebGLRenderingContext::uniformMatrix4fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    746 {
    747     uniformMatrixHelper(args, 4);
    748 }
    749 
    750 void V8WebGLRenderingContext::vertexAttrib1fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    751 {
    752     vertexAttribAndUniformHelperf(args, kVertexAttrib1v);
    753 }
    754 
    755 void V8WebGLRenderingContext::vertexAttrib2fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    756 {
    757     vertexAttribAndUniformHelperf(args, kVertexAttrib2v);
    758 }
    759 
    760 void V8WebGLRenderingContext::vertexAttrib3fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    761 {
    762     vertexAttribAndUniformHelperf(args, kVertexAttrib3v);
    763 }
    764 
    765 void V8WebGLRenderingContext::vertexAttrib4fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    766 {
    767     vertexAttribAndUniformHelperf(args, kVertexAttrib4v);
    768 }
    769 
    770 } // namespace WebCore
    771