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