PageRenderTime 94ms CodeModel.GetById 8ms app.highlight 79ms RepoModel.GetById 1ms app.codeStats 0ms

/platform/external/webkit/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp

https://github.com/aharish/totoro-gb-opensource-update2
C++ | 1072 lines | 866 code | 90 blank | 116 comment | 156 complexity | 1486a8d8bd5a6c03ac96fd83f463c691 MD5 | raw file
   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 areV8ClassIndex::WEBGL
   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
  33#if ENABLE(3D_CANVAS)
  34
  35#include "V8WebGLRenderingContext.h"
  36
  37#include "ExceptionCode.h"
  38
  39#include "NotImplemented.h"
  40
  41#include <wtf/FastMalloc.h>
  42
  43#include "V8Binding.h"
  44#include "V8WebGLArray.h"
  45#include "V8WebGLBuffer.h"
  46#include "V8WebGLByteArray.h"
  47#include "V8WebGLFloatArray.h"
  48#include "V8WebGLFramebuffer.h"
  49#include "V8WebGLIntArray.h"
  50#include "V8WebGLProgram.h"
  51#include "V8WebGLRenderbuffer.h"
  52#include "V8WebGLShader.h"
  53#include "V8WebGLShortArray.h"
  54#include "V8WebGLTexture.h"
  55#include "V8WebGLUniformLocation.h"
  56#include "V8WebGLUnsignedByteArray.h"
  57#include "V8WebGLUnsignedIntArray.h"
  58#include "V8WebGLUnsignedShortArray.h"
  59#include "V8HTMLCanvasElement.h"
  60#include "V8HTMLImageElement.h"
  61#include "V8HTMLVideoElement.h"
  62#include "V8ImageData.h"
  63#include "V8Proxy.h"
  64#include "WebGLRenderingContext.h"
  65
  66namespace WebCore {
  67
  68// Allocates new storage via tryFastMalloc.
  69// Returns NULL if array failed to convert for any reason.
  70static float* jsArrayToFloatArray(v8::Handle<v8::Array> array, uint32_t len)
  71{
  72    // Convert the data element-by-element.
  73    float* data;
  74    if (!tryFastMalloc(len * sizeof(float)).getValue(data))
  75        return 0;
  76    for (uint32_t i = 0; i < len; i++) {
  77        v8::Local<v8::Value> val = array->Get(v8::Integer::New(i));
  78        if (!val->IsNumber()) {
  79            fastFree(data);
  80            return 0;
  81        }
  82        data[i] = toFloat(val);
  83    }
  84    return data;
  85}
  86
  87// Allocates new storage via tryFastMalloc.
  88// Returns NULL if array failed to convert for any reason.
  89static int* jsArrayToIntArray(v8::Handle<v8::Array> array, uint32_t len)
  90{
  91    // Convert the data element-by-element.
  92    int* data;
  93    if (!tryFastMalloc(len * sizeof(int)).getValue(data))
  94        return 0;
  95    for (uint32_t i = 0; i < len; i++) {
  96        v8::Local<v8::Value> val = array->Get(v8::Integer::New(i));
  97        bool ok;
  98        int ival = toInt32(val, ok);
  99        if (!ok) {
 100            fastFree(data);
 101            return 0;
 102        }
 103        data[i] = ival;
 104    }
 105    return data;
 106}
 107
 108v8::Handle<v8::Value> V8WebGLRenderingContext::bufferDataCallback(const v8::Arguments& args)
 109{
 110    INC_STATS("DOM.WebGLRenderingContext.bufferData()");
 111
 112    // Forms:
 113    // * bufferData(GLenum target, WebGLArray data, GLenum usage);
 114    //   - Sets the buffer's data from the given WebGLArray
 115    // * bufferData(GLenum target, GLsizeiptr size, GLenum usage);
 116    //   - Sets the size of the buffer to the given size in bytes
 117    if (args.Length() != 3) {
 118        V8Proxy::setDOMException(SYNTAX_ERR);
 119        return notHandledByInterceptor();
 120    }
 121
 122    WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
 123    bool ok;
 124    int target = toInt32(args[0], ok);
 125    if (!ok) {
 126        V8Proxy::setDOMException(SYNTAX_ERR);
 127        return notHandledByInterceptor();
 128    }
 129    int usage = toInt32(args[2], ok);
 130    if (!ok) {
 131        V8Proxy::setDOMException(SYNTAX_ERR);
 132        return notHandledByInterceptor();
 133    }
 134    if (args[1]->IsInt32()) {
 135        int size = toInt32(args[1]);
 136        ExceptionCode exceptionCode;
 137        context->bufferData(target, size, usage, exceptionCode);
 138    } else if (V8WebGLArray::HasInstance(args[1])) {
 139        WebGLArray* array = V8WebGLArray::toNative(args[1]->ToObject());
 140        ExceptionCode exceptionCode;
 141        context->bufferData(target, array, usage, exceptionCode);
 142    } else {
 143        V8Proxy::setDOMException(SYNTAX_ERR);
 144        return notHandledByInterceptor();
 145    }
 146    return v8::Undefined();
 147}
 148
 149v8::Handle<v8::Value> V8WebGLRenderingContext::bufferSubDataCallback(const v8::Arguments& args)
 150{
 151    INC_STATS("DOM.WebGLRenderingContext.bufferSubData()");
 152
 153    // Forms:
 154    // * bufferSubData(GLenum target, GLintptr offset, WebGLArray data);
 155    if (args.Length() != 3) {
 156        V8Proxy::setDOMException(SYNTAX_ERR);
 157        return notHandledByInterceptor();
 158    }
 159
 160    WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
 161    bool ok;
 162    int target = toInt32(args[0], ok);
 163    if (!ok) {
 164        V8Proxy::setDOMException(SYNTAX_ERR);
 165        return notHandledByInterceptor();
 166    }
 167    int offset = toInt32(args[1], ok);
 168    if (!ok) {
 169        V8Proxy::setDOMException(SYNTAX_ERR);
 170        return notHandledByInterceptor();
 171    }
 172    if (!V8WebGLArray::HasInstance(args[2])) {
 173        V8Proxy::setDOMException(SYNTAX_ERR);
 174        return notHandledByInterceptor();
 175    }
 176    WebGLArray* array = V8WebGLArray::toNative(args[2]->ToObject());
 177    ExceptionCode exceptionCode;
 178    context->bufferSubData(target, offset, array, exceptionCode);
 179    return v8::Undefined();
 180}
 181
 182static v8::Handle<v8::Value> toV8Object(const WebGLGetInfo& info)
 183{
 184    switch (info.getType()) {
 185    case WebGLGetInfo::kTypeBool:
 186        return v8::Boolean::New(info.getBool());
 187    case WebGLGetInfo::kTypeFloat:
 188        return v8::Number::New(info.getFloat());
 189    case WebGLGetInfo::kTypeLong:
 190        return v8::Integer::New(info.getLong());
 191    case WebGLGetInfo::kTypeNull:
 192        return v8::Null();
 193    case WebGLGetInfo::kTypeString:
 194        return v8::String::New(fromWebCoreString(info.getString()), info.getString().length());
 195    case WebGLGetInfo::kTypeUnsignedLong:
 196        return v8::Integer::NewFromUnsigned(info.getUnsignedLong());
 197    case WebGLGetInfo::kTypeWebGLBuffer:
 198        return toV8(info.getWebGLBuffer());
 199    case WebGLGetInfo::kTypeWebGLFloatArray:
 200        return toV8(info.getWebGLFloatArray());
 201    case WebGLGetInfo::kTypeWebGLFramebuffer:
 202        return toV8(info.getWebGLFramebuffer());
 203    case WebGLGetInfo::kTypeWebGLIntArray:
 204        return toV8(info.getWebGLIntArray());
 205    // FIXME: implement WebGLObjectArray
 206    // case WebGLGetInfo::kTypeWebGLObjectArray:
 207    case WebGLGetInfo::kTypeWebGLProgram:
 208        return toV8(info.getWebGLProgram());
 209    case WebGLGetInfo::kTypeWebGLRenderbuffer:
 210        return toV8(info.getWebGLRenderbuffer());
 211    case WebGLGetInfo::kTypeWebGLTexture:
 212        return toV8(info.getWebGLTexture());
 213    case WebGLGetInfo::kTypeWebGLUnsignedByteArray:
 214        return toV8(info.getWebGLUnsignedByteArray());
 215    default:
 216        notImplemented();
 217        return v8::Undefined();
 218    }
 219}
 220
 221enum ObjectType {
 222    kBuffer, kRenderbuffer, kTexture, kVertexAttrib
 223};
 224
 225static v8::Handle<v8::Value> getObjectParameter(const v8::Arguments& args, ObjectType objectType)
 226{
 227    if (args.Length() != 2) {
 228        V8Proxy::setDOMException(SYNTAX_ERR);
 229        return notHandledByInterceptor();
 230    }
 231
 232    ExceptionCode ec = 0;
 233    WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
 234    bool ok;
 235    unsigned target = toInt32(args[0], ok);
 236    if (!ok) {
 237        V8Proxy::setDOMException(SYNTAX_ERR);
 238        return notHandledByInterceptor();
 239    }
 240    unsigned pname = toInt32(args[1], ok);
 241    if (!ok) {
 242        V8Proxy::setDOMException(SYNTAX_ERR);
 243        return notHandledByInterceptor();
 244    }
 245    WebGLGetInfo info;
 246    switch (objectType) {
 247    case kBuffer:
 248        info = context->getBufferParameter(target, pname, ec);
 249        break;
 250    case kRenderbuffer:
 251        info = context->getRenderbufferParameter(target, pname, ec);
 252        break;
 253    case kTexture:
 254        info = context->getTexParameter(target, pname, ec);
 255        break;
 256    case kVertexAttrib:
 257        // target => index
 258        info = context->getVertexAttrib(target, pname, ec);
 259        break;
 260    default:
 261        notImplemented();
 262        break;
 263    }
 264    if (ec) {
 265        V8Proxy::setDOMException(ec);
 266        return v8::Undefined();
 267    }
 268    return toV8Object(info);
 269}
 270
 271static WebGLUniformLocation* toWebGLUniformLocation(v8::Handle<v8::Value> value, bool& ok)
 272{
 273    ok = false;
 274    WebGLUniformLocation* location = 0;
 275    if (V8WebGLUniformLocation::HasInstance(value)) {
 276        location = V8WebGLUniformLocation::toNative(value->ToObject());
 277        ok = true;
 278    }
 279    return location;
 280}
 281
 282enum WhichProgramCall {
 283    kProgramParameter, kUniform
 284};
 285
 286v8::Handle<v8::Value> V8WebGLRenderingContext::getBufferParameterCallback(const v8::Arguments& args)
 287{
 288    INC_STATS("DOM.WebGLRenderingContext.getBufferParameter()");
 289    return getObjectParameter(args, kBuffer);
 290}
 291
 292v8::Handle<v8::Value> V8WebGLRenderingContext::getFramebufferAttachmentParameterCallback(const v8::Arguments& args)
 293{
 294    INC_STATS("DOM.WebGLRenderingContext.getFramebufferAttachmentParameter()");
 295
 296    if (args.Length() != 3) {
 297        V8Proxy::setDOMException(SYNTAX_ERR);
 298        return notHandledByInterceptor();
 299    }
 300
 301    ExceptionCode ec = 0;
 302    WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
 303    bool ok;
 304    unsigned target = toInt32(args[0], ok);
 305    if (!ok) {
 306        V8Proxy::setDOMException(SYNTAX_ERR);
 307        return notHandledByInterceptor();
 308    }
 309    unsigned attachment = toInt32(args[1], ok);
 310    if (!ok) {
 311        V8Proxy::setDOMException(SYNTAX_ERR);
 312        return notHandledByInterceptor();
 313    }
 314    unsigned pname = toInt32(args[2], ok);
 315    if (!ok) {
 316        V8Proxy::setDOMException(SYNTAX_ERR);
 317        return notHandledByInterceptor();
 318    }
 319    WebGLGetInfo info = context->getFramebufferAttachmentParameter(target, attachment, pname, ec);
 320    if (ec) {
 321        V8Proxy::setDOMException(ec);
 322        return v8::Undefined();
 323    }
 324    return toV8Object(info);
 325}
 326
 327v8::Handle<v8::Value> V8WebGLRenderingContext::getParameterCallback(const v8::Arguments& args)
 328{
 329    INC_STATS("DOM.WebGLRenderingContext.getParameter()");
 330
 331    if (args.Length() != 1) {
 332        V8Proxy::setDOMException(SYNTAX_ERR);
 333        return notHandledByInterceptor();
 334    }
 335
 336    ExceptionCode ec = 0;
 337    WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
 338    bool ok;
 339    unsigned pname = toInt32(args[0], ok);
 340    if (!ok) {
 341        V8Proxy::setDOMException(SYNTAX_ERR);
 342        return notHandledByInterceptor();
 343    }
 344    WebGLGetInfo info = context->getParameter(pname, ec);
 345    if (ec) {
 346        V8Proxy::setDOMException(ec);
 347        return v8::Undefined();
 348    }
 349    return toV8Object(info);
 350}
 351
 352v8::Handle<v8::Value> V8WebGLRenderingContext::getProgramParameterCallback(const v8::Arguments& args)
 353{
 354    INC_STATS("DOM.WebGLRenderingContext.getProgramParameter()");
 355
 356    if (args.Length() != 2) {
 357        V8Proxy::setDOMException(SYNTAX_ERR);
 358        return notHandledByInterceptor();
 359    }
 360
 361    ExceptionCode ec = 0;
 362    WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
 363    WebGLProgram* program = V8WebGLProgram::HasInstance(args[0]) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
 364    bool ok;
 365    unsigned pname = toInt32(args[1], ok);
 366    if (!ok) {
 367        V8Proxy::setDOMException(SYNTAX_ERR);
 368        return notHandledByInterceptor();
 369    }
 370    WebGLGetInfo info = context->getProgramParameter(program, pname, ec);
 371    if (ec) {
 372        V8Proxy::setDOMException(ec);
 373        return v8::Undefined();
 374    }
 375    return toV8Object(info);
 376}
 377
 378v8::Handle<v8::Value> V8WebGLRenderingContext::getRenderbufferParameterCallback(const v8::Arguments& args)
 379{
 380    INC_STATS("DOM.WebGLRenderingContext.getRenderbufferParameter()");
 381    return getObjectParameter(args, kRenderbuffer);
 382}
 383
 384v8::Handle<v8::Value> V8WebGLRenderingContext::getShaderParameterCallback(const v8::Arguments& args)
 385{
 386    INC_STATS("DOM.WebGLRenderingContext.getShaderParameter()");
 387
 388    if (args.Length() != 2) {
 389        V8Proxy::setDOMException(SYNTAX_ERR);
 390        return notHandledByInterceptor();
 391    }
 392
 393    ExceptionCode ec = 0;
 394    WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
 395    WebGLShader* shader = V8WebGLShader::HasInstance(args[0]) ? V8WebGLShader::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
 396    bool ok;
 397    unsigned pname = toInt32(args[1], ok);
 398    if (!ok) {
 399        V8Proxy::setDOMException(SYNTAX_ERR);
 400        return notHandledByInterceptor();
 401    }
 402    WebGLGetInfo info = context->getShaderParameter(shader, pname, ec);
 403    if (ec) {
 404        V8Proxy::setDOMException(ec);
 405        return v8::Undefined();
 406    }
 407    return toV8Object(info);
 408}
 409
 410v8::Handle<v8::Value> V8WebGLRenderingContext::getTexParameterCallback(const v8::Arguments& args)
 411{
 412    INC_STATS("DOM.WebGLRenderingContext.getTexParameter()");
 413    return getObjectParameter(args, kTexture);
 414}
 415
 416v8::Handle<v8::Value> V8WebGLRenderingContext::getUniformCallback(const v8::Arguments& args)
 417{
 418    INC_STATS("DOM.WebGLRenderingContext.getUniform()");
 419
 420    if (args.Length() != 2) {
 421        V8Proxy::setDOMException(SYNTAX_ERR);
 422        return notHandledByInterceptor();
 423    }
 424
 425    ExceptionCode ec = 0;
 426    WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
 427    WebGLProgram* program = V8WebGLProgram::HasInstance(args[0]) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
 428
 429    bool ok = false;
 430    WebGLUniformLocation* location = toWebGLUniformLocation(args[1], ok);
 431
 432    if (!ok) {
 433        V8Proxy::setDOMException(SYNTAX_ERR);
 434        return notHandledByInterceptor();
 435    }
 436    WebGLGetInfo info = context->getUniform(program, location, ec);
 437    if (ec) {
 438        V8Proxy::setDOMException(ec);
 439        return v8::Undefined();
 440    }
 441    return toV8Object(info);
 442}
 443
 444v8::Handle<v8::Value> V8WebGLRenderingContext::getVertexAttribCallback(const v8::Arguments& args)
 445{
 446    INC_STATS("DOM.WebGLRenderingContext.getVertexAttrib()");
 447    return getObjectParameter(args, kVertexAttrib);
 448}
 449
 450v8::Handle<v8::Value> V8WebGLRenderingContext::texImage2DCallback(const v8::Arguments& args)
 451{
 452    INC_STATS("DOM.WebGLRenderingContext.texImage2D()");
 453
 454    // Currently supported forms:
 455    // * void texImage2D(in GLenum target, in GLint level,
 456    //                   in GLint internalformat,
 457    //                   in GLsizei width, in GLsizei height, in GLint border,
 458    //                   in GLenum format, in GLenum type, in WebGLArray pixels);
 459    // * void texImage2D(in GLenum target, in GLint level, in ImageData pixels,
 460    //                   [Optional] in GLboolean flipY, [Optional] in GLboolean premulitplyAlpha);
 461    // * void texImage2D(in GLenum target, in GLint level, in HTMLImageElement image,
 462    //                   [Optional] in GLboolean flipY, [Optional] in GLboolean premultiplyAlpha);
 463    // * void texImage2D(in GLenum target, in GLint level, in HTMLCanvasElement image,
 464    //                   [Optional] in GLboolean flipY, [Optional] in GLboolean premultiplyAlpha);
 465    // * void texImage2D(in GLenum target, in GLint level, in HTMLVideoElement image,
 466    //                   [Optional] in GLboolean flipY, [Optional] in GLboolean premultiplyAlpha);
 467    if (args.Length() != 3 &&
 468        args.Length() != 4 &&
 469        args.Length() != 5 &&
 470        args.Length() != 9) {
 471        V8Proxy::setDOMException(SYNTAX_ERR);
 472        return notHandledByInterceptor();
 473    }
 474
 475    WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
 476    bool ok;
 477    int target = toInt32(args[0], ok);
 478    if (!ok) {
 479        V8Proxy::setDOMException(SYNTAX_ERR);
 480        return notHandledByInterceptor();
 481    }
 482    int level = toInt32(args[1], ok);
 483    if (!ok) {
 484        V8Proxy::setDOMException(SYNTAX_ERR);
 485        return notHandledByInterceptor();
 486    }
 487
 488    ExceptionCode ec = 0;
 489    if (args.Length() == 3 ||
 490        args.Length() == 4 ||
 491        args.Length() == 5) {
 492        bool flipY = false;
 493        bool premultiplyAlpha = false;
 494        if (args.Length() >= 4)
 495            flipY = args[3]->BooleanValue();
 496        if (args.Length() >= 5)
 497            premultiplyAlpha = args[4]->BooleanValue();
 498
 499        v8::Handle<v8::Value> arg = args[2];
 500        if (V8HTMLImageElement::HasInstance(arg)) {
 501            HTMLImageElement* element = V8HTMLImageElement::toNative(v8::Handle<v8::Object>::Cast(arg));
 502            context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec);
 503        } else if (V8HTMLCanvasElement::HasInstance(arg)) {
 504            HTMLCanvasElement* element = V8HTMLCanvasElement::toNative(v8::Handle<v8::Object>::Cast(arg));
 505            context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec);
 506        } else if(V8ImageData::HasInstance(arg)) {
 507            ImageData* imageElement = V8ImageData::toNative(v8::Handle<v8::Object>::Cast(arg));
 508            context->texImage2D(target, level, imageElement, flipY, premultiplyAlpha, ec);
 509        } else if (V8HTMLVideoElement::HasInstance(arg)) {
 510            HTMLVideoElement* element = V8HTMLVideoElement::toNative(v8::Handle<v8::Object>::Cast(arg));
 511            context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec);
 512        }
 513        else {
 514            // FIXME: consider different / better exception type.
 515            V8Proxy::setDOMException(SYNTAX_ERR);
 516            return notHandledByInterceptor();
 517        }
 518        // Fall through
 519    } else if (args.Length() == 9) {
 520        int internalformat = toInt32(args[2], ok);
 521        if (!ok) {
 522            V8Proxy::setDOMException(SYNTAX_ERR);
 523            return notHandledByInterceptor();
 524        }
 525        int width = toInt32(args[3], ok);
 526        if (!ok) {
 527            V8Proxy::setDOMException(SYNTAX_ERR);
 528            return notHandledByInterceptor();
 529        }
 530        int height = toInt32(args[4], ok);
 531        if (!ok) {
 532            V8Proxy::setDOMException(SYNTAX_ERR);
 533            return notHandledByInterceptor();
 534        }
 535        int border = toInt32(args[5], ok);
 536        if (!ok) {
 537            V8Proxy::setDOMException(SYNTAX_ERR);
 538            return notHandledByInterceptor();
 539        }
 540        int format = toInt32(args[6], ok);
 541        if (!ok) {
 542            V8Proxy::setDOMException(SYNTAX_ERR);
 543            return notHandledByInterceptor();
 544        }
 545        int type = toInt32(args[7], ok);
 546        if (!ok) {
 547            V8Proxy::setDOMException(SYNTAX_ERR);
 548            return notHandledByInterceptor();
 549        }
 550        v8::Handle<v8::Value> arg = args[8];
 551        if (!arg->IsObject())
 552        // Assume that the user is passing null for texture
 553            context->texImage2D(target,
 554                                level,
 555                                internalformat,
 556                                width,
 557                                height,
 558                                border,
 559                                format,
 560                                type,
 561                                0,
 562                                ec);
 563     else if (V8WebGLArray::HasInstance(arg)) {
 564            WebGLArray* array = V8WebGLArray::toNative(arg->ToObject());
 565            context->texImage2D(target,
 566                                level,
 567                                internalformat,
 568                                width,
 569                                height,
 570                                border,
 571                                format,
 572                                type,
 573                                array,
 574                                ec);
 575            // Fall through
 576        } else {
 577            V8Proxy::setDOMException(SYNTAX_ERR);
 578            return notHandledByInterceptor();
 579        }
 580    } else {
 581        ASSERT_NOT_REACHED();
 582        V8Proxy::setDOMException(SYNTAX_ERR);
 583        return notHandledByInterceptor();
 584    }
 585    if (ec) {
 586        V8Proxy::setDOMException(ec);
 587        return v8::Handle<v8::Value>();
 588    }
 589    return v8::Undefined();
 590}
 591
 592v8::Handle<v8::Value> V8WebGLRenderingContext::texSubImage2DCallback(const v8::Arguments& args)
 593{
 594    INC_STATS("DOM.WebGLRenderingContext.texSubImage2D()");
 595
 596    // Currently supported forms:
 597    // * void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, 
 598    //                      in GLsizei width, in GLsizei height, 
 599    //                      in GLenum format, in GLenum type, in WebGLArray pixels);
 600    // * void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset,
 601    //                      in ImageData pixels, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha);
 602    // * void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, 
 603    //                      in HTMLImageElement image, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha);
 604    // * void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, 
 605    //                      in HTMLCanvasElement canvas, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha);
 606    // * void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, 
 607    //                      in HTMLVideoElement video, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha);
 608
 609    if (args.Length() != 5 &&
 610        args.Length() != 6 &&
 611        args.Length() != 7 &&
 612        args.Length() != 9) {
 613        V8Proxy::setDOMException(SYNTAX_ERR);
 614        return notHandledByInterceptor();
 615    }
 616
 617    WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
 618    bool ok;
 619    int target = toInt32(args[0], ok);
 620    if (!ok) {
 621        V8Proxy::setDOMException(SYNTAX_ERR);
 622        return notHandledByInterceptor();
 623    }
 624    int level = toInt32(args[1], ok);
 625    if (!ok) {
 626        V8Proxy::setDOMException(SYNTAX_ERR);
 627        return notHandledByInterceptor();
 628    }
 629    int xoff = toInt32(args[2], ok);
 630    if (!ok) {
 631        V8Proxy::setDOMException(SYNTAX_ERR);
 632        return notHandledByInterceptor();
 633    }
 634    int yoff = toInt32(args[3], ok);
 635    if (!ok) {
 636        V8Proxy::setDOMException(SYNTAX_ERR);
 637        return notHandledByInterceptor();
 638    }
 639
 640    ExceptionCode ec = 0;
 641    if (args.Length() == 5 ||
 642        args.Length() == 6 ||
 643        args.Length() == 7) {
 644        bool flipY = false;
 645        bool premultiplyAlpha = false;
 646        if (args.Length() >= 6)
 647            flipY = args[5]->BooleanValue();
 648        if (args.Length() >= 7)
 649            premultiplyAlpha = args[6]->BooleanValue();
 650
 651        v8::Handle<v8::Value> arg = args[4];
 652        if (V8HTMLImageElement::HasInstance(arg)) {
 653            HTMLImageElement* element = V8HTMLImageElement::toNative(v8::Handle<v8::Object>::Cast(arg));
 654            context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec);
 655        } else if (V8HTMLCanvasElement::HasInstance(arg)) {
 656            HTMLCanvasElement* element = V8HTMLCanvasElement::toNative(v8::Handle<v8::Object>::Cast(arg));
 657            context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec);
 658        } else if(V8ImageData::HasInstance(arg)) {
 659            ImageData* imageElement = V8ImageData::toNative(v8::Handle<v8::Object>::Cast(arg));
 660            context->texSubImage2D(target, level, xoff, yoff, imageElement, flipY, premultiplyAlpha, ec);
 661        } else if (V8HTMLVideoElement::HasInstance(arg)) {
 662            HTMLVideoElement* element = V8HTMLVideoElement::toNative(v8::Handle<v8::Object>::Cast(arg));
 663            context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec);
 664        }
 665        else {
 666            // FIXME: consider different / better exception type.
 667            V8Proxy::setDOMException(SYNTAX_ERR);
 668            return notHandledByInterceptor();
 669        }
 670        // Fall through
 671    } else if (args.Length() == 9) {
 672        int width = toInt32(args[4], ok);
 673        if (!ok) {
 674            V8Proxy::setDOMException(SYNTAX_ERR);
 675            return notHandledByInterceptor();
 676        }
 677        int height = toInt32(args[5], ok);
 678        if (!ok) {
 679            V8Proxy::setDOMException(SYNTAX_ERR);
 680            return notHandledByInterceptor();
 681        }
 682        int format = toInt32(args[6], ok);
 683        if (!ok) {
 684            V8Proxy::setDOMException(SYNTAX_ERR);
 685            return notHandledByInterceptor();
 686        }
 687        int type = toInt32(args[7], ok);
 688        if (!ok) {
 689            V8Proxy::setDOMException(SYNTAX_ERR);
 690            return notHandledByInterceptor();
 691        }
 692        v8::Handle<v8::Value> arg = args[8];
 693        if (!arg->IsObject())
 694        // Assume that the user is passing null for texture
 695            context->texSubImage2D(target,
 696                                   level,
 697                                   xoff,
 698                                   yoff,
 699                                   width,
 700                                   height,
 701                                   format,
 702                                   type,
 703                                   0,
 704                                   ec);
 705     else if (V8WebGLArray::HasInstance(arg)) {
 706            WebGLArray* array = V8WebGLArray::toNative(arg->ToObject());
 707            context->texSubImage2D(target,
 708                                   level,
 709                                   xoff,
 710                                   yoff,
 711                                   width,
 712                                   height,
 713                                   format,
 714                                   type,
 715                                   array,
 716                                   ec);
 717            // Fall through
 718        } else {
 719            V8Proxy::setDOMException(SYNTAX_ERR);
 720            return notHandledByInterceptor();
 721        }
 722    } else {
 723        ASSERT_NOT_REACHED();
 724        V8Proxy::setDOMException(SYNTAX_ERR);
 725        return notHandledByInterceptor();
 726    }
 727    if (ec) {
 728        V8Proxy::setDOMException(ec);
 729        return v8::Handle<v8::Value>();
 730    }
 731    return v8::Undefined();
 732}
 733
 734enum FunctionToCall {
 735    kUniform1v, kUniform2v, kUniform3v, kUniform4v,
 736    kVertexAttrib1v, kVertexAttrib2v, kVertexAttrib3v, kVertexAttrib4v
 737};
 738
 739bool isFunctionToCallForAttribute(FunctionToCall functionToCall)
 740{
 741    switch (functionToCall) {
 742    case kVertexAttrib1v:
 743    case kVertexAttrib2v:
 744    case kVertexAttrib3v:
 745    case kVertexAttrib4v:
 746        return true;
 747    default:
 748        break;
 749    }
 750    return false;
 751}
 752
 753static v8::Handle<v8::Value> vertexAttribAndUniformHelperf(const v8::Arguments& args,
 754                                                           FunctionToCall functionToCall) {
 755    // Forms:
 756    // * glUniform1fv(WebGLUniformLocation location, Array data);
 757    // * glUniform1fv(WebGLUniformLocation location, WebGLFloatArray data);
 758    // * glUniform2fv(WebGLUniformLocation location, Array data);
 759    // * glUniform2fv(WebGLUniformLocation location, WebGLFloatArray data);
 760    // * glUniform3fv(WebGLUniformLocation location, Array data);
 761    // * glUniform3fv(WebGLUniformLocation location, WebGLFloatArray data);
 762    // * glUniform4fv(WebGLUniformLocation location, Array data);
 763    // * glUniform4fv(WebGLUniformLocation location, WebGLFloatArray data);
 764    // * glVertexAttrib1fv(GLint index, Array data);
 765    // * glVertexAttrib1fv(GLint index, WebGLFloatArray data);
 766    // * glVertexAttrib2fv(GLint index, Array data);
 767    // * glVertexAttrib2fv(GLint index, WebGLFloatArray data);
 768    // * glVertexAttrib3fv(GLint index, Array data);
 769    // * glVertexAttrib3fv(GLint index, WebGLFloatArray data);
 770    // * glVertexAttrib4fv(GLint index, Array data);
 771    // * glVertexAttrib4fv(GLint index, WebGLFloatArray data);
 772
 773    if (args.Length() != 2) {
 774        V8Proxy::setDOMException(SYNTAX_ERR);
 775        return notHandledByInterceptor();
 776    }
 777
 778    bool ok = false;
 779    int index = -1;
 780    WebGLUniformLocation* location = 0;
 781
 782    if (isFunctionToCallForAttribute(functionToCall))
 783        index = toInt32(args[0], ok);
 784    else
 785        location = toWebGLUniformLocation(args[0], ok);
 786
 787    WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
 788
 789    if (!ok) {
 790        V8Proxy::setDOMException(SYNTAX_ERR);
 791        return notHandledByInterceptor();
 792    }
 793    if (V8WebGLFloatArray::HasInstance(args[1])) {
 794        WebGLFloatArray* array = V8WebGLFloatArray::toNative(args[1]->ToObject());
 795        ASSERT(array != NULL);
 796        ExceptionCode ec = 0;
 797        switch (functionToCall) {
 798            case kUniform1v: context->uniform1fv(location, array, ec); break;
 799            case kUniform2v: context->uniform2fv(location, array, ec); break;
 800            case kUniform3v: context->uniform3fv(location, array, ec); break;
 801            case kUniform4v: context->uniform4fv(location, array, ec); break;
 802            case kVertexAttrib1v: context->vertexAttrib1fv(index, array); break;
 803            case kVertexAttrib2v: context->vertexAttrib2fv(index, array); break;
 804            case kVertexAttrib3v: context->vertexAttrib3fv(index, array); break;
 805            case kVertexAttrib4v: context->vertexAttrib4fv(index, array); break;
 806            default: ASSERT_NOT_REACHED(); break;
 807        }
 808        if (ec)
 809            V8Proxy::setDOMException(ec);
 810        return v8::Undefined();
 811    }
 812
 813    v8::Handle<v8::Array> array =
 814      v8::Local<v8::Array>::Cast(args[1]);
 815    if (array.IsEmpty()) {
 816        V8Proxy::setDOMException(SYNTAX_ERR);
 817        return notHandledByInterceptor();
 818    }
 819    uint32_t len = array->Length();
 820    float* data = jsArrayToFloatArray(array, len);
 821    if (!data) {
 822        // FIXME: consider different / better exception type.
 823        V8Proxy::setDOMException(SYNTAX_ERR);
 824        return notHandledByInterceptor();
 825    }
 826    ExceptionCode ec = 0;
 827    switch (functionToCall) {
 828        case kUniform1v: context->uniform1fv(location, data, len, ec); break;
 829        case kUniform2v: context->uniform2fv(location, data, len, ec); break;
 830        case kUniform3v: context->uniform3fv(location, data, len, ec); break;
 831        case kUniform4v: context->uniform4fv(location, data, len, ec); break;
 832        case kVertexAttrib1v: context->vertexAttrib1fv(index, data, len); break;
 833        case kVertexAttrib2v: context->vertexAttrib2fv(index, data, len); break;
 834        case kVertexAttrib3v: context->vertexAttrib3fv(index, data, len); break;
 835        case kVertexAttrib4v: context->vertexAttrib4fv(index, data, len); break;
 836        default: ASSERT_NOT_REACHED(); break;
 837    }
 838    fastFree(data);
 839    if (ec)
 840        V8Proxy::setDOMException(ec);
 841    return v8::Undefined();
 842}
 843
 844static v8::Handle<v8::Value> uniformHelperi(const v8::Arguments& args,
 845                                            FunctionToCall functionToCall) {
 846    // Forms:
 847    // * glUniform1iv(GLUniformLocation location, Array data);
 848    // * glUniform1iv(GLUniformLocation location, WebGLIntArray data);
 849    // * glUniform2iv(GLUniformLocation location, Array data);
 850    // * glUniform2iv(GLUniformLocation location, WebGLIntArray data);
 851    // * glUniform3iv(GLUniformLocation location, Array data);
 852    // * glUniform3iv(GLUniformLocation location, WebGLIntArray data);
 853    // * glUniform4iv(GLUniformLocation location, Array data);
 854    // * glUniform4iv(GLUniformLocation location, WebGLIntArray data);
 855
 856    if (args.Length() != 2) {
 857        V8Proxy::setDOMException(SYNTAX_ERR);
 858        return notHandledByInterceptor();
 859    }
 860
 861    WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
 862    bool ok = false;
 863    WebGLUniformLocation* location = toWebGLUniformLocation(args[0], ok);
 864
 865    if (!ok) {
 866        V8Proxy::setDOMException(SYNTAX_ERR);
 867        return notHandledByInterceptor();
 868    }
 869    if (V8WebGLIntArray::HasInstance(args[1])) {
 870        WebGLIntArray* array = V8WebGLIntArray::toNative(args[1]->ToObject());
 871        ASSERT(array != NULL);
 872        ExceptionCode ec = 0;
 873        switch (functionToCall) {
 874            case kUniform1v: context->uniform1iv(location, array, ec); break;
 875            case kUniform2v: context->uniform2iv(location, array, ec); break;
 876            case kUniform3v: context->uniform3iv(location, array, ec); break;
 877            case kUniform4v: context->uniform4iv(location, array, ec); break;
 878            default: ASSERT_NOT_REACHED(); break;
 879        }
 880        if (ec)
 881            V8Proxy::setDOMException(ec);
 882        return v8::Undefined();
 883    }
 884
 885    v8::Handle<v8::Array> array =
 886      v8::Local<v8::Array>::Cast(args[1]);
 887    if (array.IsEmpty()) {
 888        V8Proxy::setDOMException(SYNTAX_ERR);
 889        return notHandledByInterceptor();
 890    }
 891    uint32_t len = array->Length();
 892    int* data = jsArrayToIntArray(array, len);
 893    if (!data) {
 894        // FIXME: consider different / better exception type.
 895        V8Proxy::setDOMException(SYNTAX_ERR);
 896        return notHandledByInterceptor();
 897    }
 898    ExceptionCode ec = 0;
 899    switch (functionToCall) {
 900        case kUniform1v: context->uniform1iv(location, data, len, ec); break;
 901        case kUniform2v: context->uniform2iv(location, data, len, ec); break;
 902        case kUniform3v: context->uniform3iv(location, data, len, ec); break;
 903        case kUniform4v: context->uniform4iv(location, data, len, ec); break;
 904        default: ASSERT_NOT_REACHED(); break;
 905    }
 906    fastFree(data);
 907    if (ec)
 908        V8Proxy::setDOMException(ec);
 909    return v8::Undefined();
 910}
 911
 912v8::Handle<v8::Value> V8WebGLRenderingContext::uniform1fvCallback(const v8::Arguments& args)
 913{
 914    INC_STATS("DOM.WebGLRenderingContext.uniform1fv()");
 915    return vertexAttribAndUniformHelperf(args, kUniform1v);
 916}
 917
 918v8::Handle<v8::Value> V8WebGLRenderingContext::uniform1ivCallback(const v8::Arguments& args)
 919{
 920    INC_STATS("DOM.WebGLRenderingContext.uniform1iv()");
 921    return uniformHelperi(args, kUniform1v);
 922}
 923
 924v8::Handle<v8::Value> V8WebGLRenderingContext::uniform2fvCallback(const v8::Arguments& args)
 925{
 926    INC_STATS("DOM.WebGLRenderingContext.uniform2fv()");
 927    return vertexAttribAndUniformHelperf(args, kUniform2v);
 928}
 929
 930v8::Handle<v8::Value> V8WebGLRenderingContext::uniform2ivCallback(const v8::Arguments& args)
 931{
 932    INC_STATS("DOM.WebGLRenderingContext.uniform2iv()");
 933    return uniformHelperi(args, kUniform2v);
 934}
 935
 936v8::Handle<v8::Value> V8WebGLRenderingContext::uniform3fvCallback(const v8::Arguments& args)
 937{
 938    INC_STATS("DOM.WebGLRenderingContext.uniform3fv()");
 939    return vertexAttribAndUniformHelperf(args, kUniform3v);
 940}
 941
 942v8::Handle<v8::Value> V8WebGLRenderingContext::uniform3ivCallback(const v8::Arguments& args)
 943{
 944    INC_STATS("DOM.WebGLRenderingContext.uniform3iv()");
 945    return uniformHelperi(args, kUniform3v);
 946}
 947
 948v8::Handle<v8::Value> V8WebGLRenderingContext::uniform4fvCallback(const v8::Arguments& args)
 949{
 950    INC_STATS("DOM.WebGLRenderingContext.uniform4fv()");
 951    return vertexAttribAndUniformHelperf(args, kUniform4v);
 952}
 953
 954v8::Handle<v8::Value> V8WebGLRenderingContext::uniform4ivCallback(const v8::Arguments& args)
 955{
 956    INC_STATS("DOM.WebGLRenderingContext.uniform4iv()");
 957    return uniformHelperi(args, kUniform4v);
 958}
 959
 960static v8::Handle<v8::Value> uniformMatrixHelper(const v8::Arguments& args,
 961                                                 int matrixSize)
 962{
 963    // Forms:
 964    // * glUniformMatrix2fv(GLint location, GLboolean transpose, Array data);
 965    // * glUniformMatrix2fv(GLint location, GLboolean transpose, WebGLFloatArray data);
 966    // * glUniformMatrix3fv(GLint location, GLboolean transpose, Array data);
 967    // * glUniformMatrix3fv(GLint location, GLboolean transpose, WebGLFloatArray data);
 968    // * glUniformMatrix4fv(GLint location, GLboolean transpose, Array data);
 969    // * glUniformMatrix4fv(GLint location, GLboolean transpose, WebGLFloatArray data);
 970    //
 971    // FIXME: need to change to accept WebGLFloatArray as well.
 972    if (args.Length() != 3) {
 973        V8Proxy::setDOMException(SYNTAX_ERR);
 974        return notHandledByInterceptor();
 975    }
 976
 977    WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
 978
 979    bool ok = false;
 980    WebGLUniformLocation* location = toWebGLUniformLocation(args[0], ok);
 981    
 982    if (!ok) {
 983        V8Proxy::setDOMException(SYNTAX_ERR);
 984        return notHandledByInterceptor();
 985    }
 986    bool transpose = args[1]->BooleanValue();
 987    if (V8WebGLFloatArray::HasInstance(args[2])) {
 988        WebGLFloatArray* array = V8WebGLFloatArray::toNative(args[2]->ToObject());
 989        ASSERT(array != NULL);
 990        ExceptionCode ec = 0;
 991        switch (matrixSize) {
 992            case 2: context->uniformMatrix2fv(location, transpose, array, ec); break;
 993            case 3: context->uniformMatrix3fv(location, transpose, array, ec); break;
 994            case 4: context->uniformMatrix4fv(location, transpose, array, ec); break;
 995            default: ASSERT_NOT_REACHED(); break;
 996        }
 997        if (ec)
 998            V8Proxy::setDOMException(ec);
 999        return v8::Undefined();
1000    }
1001
1002    v8::Handle<v8::Array> array =
1003      v8::Local<v8::Array>::Cast(args[2]);
1004    if (array.IsEmpty()) {
1005        V8Proxy::setDOMException(SYNTAX_ERR);
1006        return notHandledByInterceptor();
1007    }
1008    uint32_t len = array->Length();
1009    float* data = jsArrayToFloatArray(array, len);
1010    if (!data) {
1011        // FIXME: consider different / better exception type.
1012        V8Proxy::setDOMException(SYNTAX_ERR);
1013        return notHandledByInterceptor();
1014    }
1015    ExceptionCode ec = 0;
1016    switch (matrixSize) {
1017        case 2: context->uniformMatrix2fv(location, transpose, data, len, ec); break;
1018        case 3: context->uniformMatrix3fv(location, transpose, data, len, ec); break;
1019        case 4: context->uniformMatrix4fv(location, transpose, data, len, ec); break;
1020        default: ASSERT_NOT_REACHED(); break;
1021    }
1022    fastFree(data);
1023    if (ec)
1024        V8Proxy::setDOMException(ec); 
1025    return v8::Undefined();
1026}
1027
1028v8::Handle<v8::Value> V8WebGLRenderingContext::uniformMatrix2fvCallback(const v8::Arguments& args)
1029{
1030    INC_STATS("DOM.WebGLRenderingContext.uniformMatrix2fv()");
1031    return uniformMatrixHelper(args, 2);
1032}
1033
1034v8::Handle<v8::Value> V8WebGLRenderingContext::uniformMatrix3fvCallback(const v8::Arguments& args)
1035{
1036    INC_STATS("DOM.WebGLRenderingContext.uniformMatrix3fv()");
1037    return uniformMatrixHelper(args, 3);
1038}
1039
1040v8::Handle<v8::Value> V8WebGLRenderingContext::uniformMatrix4fvCallback(const v8::Arguments& args)
1041{
1042    INC_STATS("DOM.WebGLRenderingContext.uniformMatrix4fv()");
1043    return uniformMatrixHelper(args, 4);
1044}
1045
1046v8::Handle<v8::Value> V8WebGLRenderingContext::vertexAttrib1fvCallback(const v8::Arguments& args)
1047{
1048    INC_STATS("DOM.WebGLRenderingContext.vertexAttrib1fv()");
1049    return vertexAttribAndUniformHelperf(args, kVertexAttrib1v);
1050}
1051
1052v8::Handle<v8::Value> V8WebGLRenderingContext::vertexAttrib2fvCallback(const v8::Arguments& args)
1053{
1054    INC_STATS("DOM.WebGLRenderingContext.vertexAttrib2fv()");
1055    return vertexAttribAndUniformHelperf(args, kVertexAttrib2v);
1056}
1057
1058v8::Handle<v8::Value> V8WebGLRenderingContext::vertexAttrib3fvCallback(const v8::Arguments& args)
1059{
1060    INC_STATS("DOM.WebGLRenderingContext.vertexAttrib3fv()");
1061    return vertexAttribAndUniformHelperf(args, kVertexAttrib3v);
1062}
1063
1064v8::Handle<v8::Value> V8WebGLRenderingContext::vertexAttrib4fvCallback(const v8::Arguments& args)
1065{
1066    INC_STATS("DOM.WebGLRenderingContext.vertexAttrib4fv()");
1067    return vertexAttribAndUniformHelperf(args, kVertexAttrib4v);
1068}
1069
1070} // namespace WebCore
1071
1072#endif // ENABLE(3D_CANVAS)