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/ExceptionMessages.h" 65#include "bindings/v8/V8Binding.h" 66#include "bindings/v8/V8HiddenPropertyName.h" 67#include "bindings/v8/custom/V8ArrayBufferViewCustom.h" 68#include "bindings/v8/custom/V8Float32ArrayCustom.h" 69#include "bindings/v8/custom/V8Int16ArrayCustom.h" 70#include "bindings/v8/custom/V8Int32ArrayCustom.h" 71#include "bindings/v8/custom/V8Int8ArrayCustom.h" 72#include "bindings/v8/custom/V8Uint16ArrayCustom.h" 73#include "bindings/v8/custom/V8Uint32ArrayCustom.h" 74#include "bindings/v8/custom/V8Uint8ArrayCustom.h" 75#include "core/dom/ExceptionCode.h" 76#include "core/html/canvas/WebGLRenderingContext.h" 77#include "platform/NotImplemented.h" 78#include "wtf/FastMalloc.h" 79#include <limits> 80 81namespace WebCore { 82 83// Allocates new storage via fastMalloc. 84// Returns NULL if array failed to convert for any reason. 85static float* jsArrayToFloatArray(v8::Handle<v8::Array> array, uint32_t len) 86{ 87 // Convert the data element-by-element. 88 if (len > std::numeric_limits<uint32_t>::max() / sizeof(float)) 89 return 0; 90 float* data = static_cast<float*>(fastMalloc(len * sizeof(float))); 91 92 for (uint32_t i = 0; i < len; i++) { 93 v8::Local<v8::Value> val = array->Get(i); 94 if (!val->IsNumber()) { 95 fastFree(data); 96 return 0; 97 } 98 data[i] = toFloat(val); 99 } 100 return data; 101} 102 103// Allocates new storage via fastMalloc. 104// Returns NULL if array failed to convert for any reason. 105static int* jsArrayToIntArray(v8::Handle<v8::Array> array, uint32_t len) 106{ 107 // Convert the data element-by-element. 108 if (len > std::numeric_limits<uint32_t>::max() / sizeof(int)) 109 return 0; 110 int* data = static_cast<int*>(fastMalloc(len * sizeof(int))); 111 112 for (uint32_t i = 0; i < len; i++) { 113 v8::Local<v8::Value> val = array->Get(i); 114 bool ok; 115 int ival = toInt32(val, ok); 116 if (!ok) { 117 fastFree(data); 118 return 0; 119 } 120 data[i] = ival; 121 } 122 return data; 123} 124 125static v8::Handle<v8::Value> toV8Object(const WebGLGetInfo& args, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) 126{ 127 switch (args.getType()) { 128 case WebGLGetInfo::kTypeBool: 129 return v8Boolean(args.getBool(), isolate); 130 case WebGLGetInfo::kTypeBoolArray: { 131 const Vector<bool>& value = args.getBoolArray(); 132 v8::Local<v8::Array> array = v8::Array::New(isolate, value.size()); 133 for (size_t ii = 0; ii < value.size(); ++ii) 134 array->Set(v8::Integer::New(ii, isolate), v8Boolean(value[ii], isolate)); 135 return array; 136 } 137 case WebGLGetInfo::kTypeFloat: 138 return v8::Number::New(isolate, args.getFloat()); 139 case WebGLGetInfo::kTypeInt: 140 return v8::Integer::New(args.getInt(), isolate); 141 case WebGLGetInfo::kTypeNull: 142 return v8::Null(isolate); 143 case WebGLGetInfo::kTypeString: 144 return v8String(isolate, args.getString()); 145 case WebGLGetInfo::kTypeUnsignedInt: 146 return v8::Integer::NewFromUnsigned(args.getUnsignedInt(), isolate); 147 case WebGLGetInfo::kTypeWebGLBuffer: 148 return toV8(args.getWebGLBuffer(), creationContext, isolate); 149 case WebGLGetInfo::kTypeWebGLFloatArray: 150 return toV8(args.getWebGLFloatArray(), creationContext, isolate); 151 case WebGLGetInfo::kTypeWebGLFramebuffer: 152 return toV8(args.getWebGLFramebuffer(), creationContext, isolate); 153 case WebGLGetInfo::kTypeWebGLIntArray: 154 return toV8(args.getWebGLIntArray(), creationContext, isolate); 155 // FIXME: implement WebGLObjectArray 156 // case WebGLGetInfo::kTypeWebGLObjectArray: 157 case WebGLGetInfo::kTypeWebGLProgram: 158 return toV8(args.getWebGLProgram(), creationContext, isolate); 159 case WebGLGetInfo::kTypeWebGLRenderbuffer: 160 return toV8(args.getWebGLRenderbuffer(), creationContext, isolate); 161 case WebGLGetInfo::kTypeWebGLTexture: 162 return toV8(args.getWebGLTexture(), creationContext, isolate); 163 case WebGLGetInfo::kTypeWebGLUnsignedByteArray: 164 return toV8(args.getWebGLUnsignedByteArray(), creationContext, isolate); 165 case WebGLGetInfo::kTypeWebGLUnsignedIntArray: 166 return toV8(args.getWebGLUnsignedIntArray(), creationContext, isolate); 167 case WebGLGetInfo::kTypeWebGLVertexArrayObjectOES: 168 return toV8(args.getWebGLVertexArrayObjectOES(), creationContext, isolate); 169 default: 170 notImplemented(); 171 return v8::Undefined(isolate); 172 } 173} 174 175static v8::Handle<v8::Value> toV8Object(WebGLExtension* extension, v8::Handle<v8::Object> contextObject, v8::Isolate* isolate) 176{ 177 if (!extension) 178 return v8::Null(isolate); 179 v8::Handle<v8::Value> extensionObject; 180 const char* referenceName = 0; 181 switch (extension->name()) { 182 case WebGLExtension::ANGLEInstancedArraysName: 183 extensionObject = toV8(static_cast<ANGLEInstancedArrays*>(extension), contextObject, isolate); 184 referenceName = "angleInstancedArraysName"; 185 break; 186 case WebGLExtension::EXTFragDepthName: 187 extensionObject = toV8(static_cast<EXTFragDepth*>(extension), contextObject, isolate); 188 referenceName = "extFragDepthName"; 189 break; 190 case WebGLExtension::EXTTextureFilterAnisotropicName: 191 extensionObject = toV8(static_cast<EXTTextureFilterAnisotropic*>(extension), contextObject, isolate); 192 referenceName = "extTextureFilterAnisotropicName"; 193 break; 194 case WebGLExtension::OESElementIndexUintName: 195 extensionObject = toV8(static_cast<OESElementIndexUint*>(extension), contextObject, isolate); 196 referenceName = "oesElementIndexUintName"; 197 break; 198 case WebGLExtension::OESStandardDerivativesName: 199 extensionObject = toV8(static_cast<OESStandardDerivatives*>(extension), contextObject, isolate); 200 referenceName = "oesStandardDerivativesName"; 201 break; 202 case WebGLExtension::OESTextureFloatName: 203 extensionObject = toV8(static_cast<OESTextureFloat*>(extension), contextObject, isolate); 204 referenceName = "oesTextureFloatName"; 205 break; 206 case WebGLExtension::OESTextureFloatLinearName: 207 extensionObject = toV8(static_cast<OESTextureFloatLinear*>(extension), contextObject, isolate); 208 referenceName = "oesTextureFloatLinearName"; 209 break; 210 case WebGLExtension::OESTextureHalfFloatName: 211 extensionObject = toV8(static_cast<OESTextureHalfFloat*>(extension), contextObject, isolate); 212 referenceName = "oesTextureHalfFloatName"; 213 break; 214 case WebGLExtension::OESTextureHalfFloatLinearName: 215 extensionObject = toV8(static_cast<OESTextureHalfFloatLinear*>(extension), contextObject, isolate); 216 referenceName = "oesTextureHalfFloatLinearName"; 217 break; 218 case WebGLExtension::OESVertexArrayObjectName: 219 extensionObject = toV8(static_cast<OESVertexArrayObject*>(extension), contextObject, isolate); 220 referenceName = "oesVertexArrayObjectName"; 221 break; 222 case WebGLExtension::WebGLCompressedTextureATCName: 223 extensionObject = toV8(static_cast<WebGLCompressedTextureATC*>(extension), contextObject, isolate); 224 referenceName = "webGLCompressedTextureATCName"; 225 break; 226 case WebGLExtension::WebGLCompressedTexturePVRTCName: 227 extensionObject = toV8(static_cast<WebGLCompressedTexturePVRTC*>(extension), contextObject, isolate); 228 referenceName = "webGLCompressedTexturePVRTCName"; 229 break; 230 case WebGLExtension::WebGLCompressedTextureS3TCName: 231 extensionObject = toV8(static_cast<WebGLCompressedTextureS3TC*>(extension), contextObject, isolate); 232 referenceName = "webGLCompressedTextureS3TCName"; 233 break; 234 case WebGLExtension::WebGLDebugRendererInfoName: 235 extensionObject = toV8(static_cast<WebGLDebugRendererInfo*>(extension), contextObject, isolate); 236 referenceName = "webGLDebugRendererInfoName"; 237 break; 238 case WebGLExtension::WebGLDebugShadersName: 239 extensionObject = toV8(static_cast<WebGLDebugShaders*>(extension), contextObject, isolate); 240 referenceName = "webGLDebugShadersName"; 241 break; 242 case WebGLExtension::WebGLDepthTextureName: 243 extensionObject = toV8(static_cast<WebGLDepthTexture*>(extension), contextObject, isolate); 244 referenceName = "webGLDepthTextureName"; 245 break; 246 case WebGLExtension::WebGLDrawBuffersName: 247 extensionObject = toV8(static_cast<WebGLDrawBuffers*>(extension), contextObject, isolate); 248 referenceName = "webGLDrawBuffersName"; 249 break; 250 case WebGLExtension::WebGLLoseContextName: 251 extensionObject = toV8(static_cast<WebGLLoseContext*>(extension), contextObject, isolate); 252 referenceName = "webGLLoseContextName"; 253 break; 254 } 255 ASSERT(!extensionObject.IsEmpty()); 256 V8HiddenPropertyName::setNamedHiddenReference(contextObject, referenceName, extensionObject); 257 return extensionObject; 258} 259 260enum ObjectType { 261 kBuffer, kRenderbuffer, kTexture, kVertexAttrib 262}; 263 264static void getObjectParameter(const v8::FunctionCallbackInfo<v8::Value>& info, ObjectType objectType, const char* method) 265{ 266 if (info.Length() != 2) { 267 throwTypeError(ExceptionMessages::failedToExecute(method, "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(2, info.Length())), info.GetIsolate()); 268 return; 269 } 270 271 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); 272 unsigned target = toInt32(info[0]); 273 unsigned pname = toInt32(info[1]); 274 WebGLGetInfo args; 275 switch (objectType) { 276 case kBuffer: 277 args = context->getBufferParameter(target, pname); 278 break; 279 case kRenderbuffer: 280 args = context->getRenderbufferParameter(target, pname); 281 break; 282 case kTexture: 283 args = context->getTexParameter(target, pname); 284 break; 285 case kVertexAttrib: 286 // target => index 287 args = context->getVertexAttrib(target, pname); 288 break; 289 default: 290 notImplemented(); 291 break; 292 } 293 v8SetReturnValue(info, toV8Object(args, info.Holder(), info.GetIsolate())); 294} 295 296static WebGLUniformLocation* toWebGLUniformLocation(v8::Handle<v8::Value> value, bool& ok, v8::Isolate* isolate) 297{ 298 ok = false; 299 WebGLUniformLocation* location = 0; 300 if (V8WebGLUniformLocation::hasInstance(value, isolate, worldType(isolate))) { 301 location = V8WebGLUniformLocation::toNative(value->ToObject()); 302 ok = true; 303 } 304 return location; 305} 306 307enum WhichProgramCall { 308 kProgramParameter, kUniform 309}; 310 311void V8WebGLRenderingContext::getAttachedShadersMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 312{ 313 if (info.Length() < 1) { 314 throwTypeError(ExceptionMessages::failedToExecute("getAttachedShaders", "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(1, info.Length())), info.GetIsolate()); 315 return; 316 } 317 318 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); 319 if (info.Length() > 0 && !isUndefinedOrNull(info[0]) && !V8WebGLProgram::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { 320 throwUninformativeAndGenericTypeError(info.GetIsolate()); 321 return; 322 } 323 WebGLProgram* program = V8WebGLProgram::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate())) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(info[0])) : 0; 324 Vector<RefPtr<WebGLShader> > shaders; 325 bool succeed = context->getAttachedShaders(program, shaders); 326 if (!succeed) { 327 v8SetReturnValueNull(info); 328 return; 329 } 330 v8::Local<v8::Array> array = v8::Array::New(info.GetIsolate(), shaders.size()); 331 for (size_t ii = 0; ii < shaders.size(); ++ii) 332 array->Set(v8::Integer::New(ii, info.GetIsolate()), toV8(shaders[ii].get(), info.Holder(), info.GetIsolate())); 333 v8SetReturnValue(info, array); 334} 335 336void V8WebGLRenderingContext::getBufferParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 337{ 338 getObjectParameter(info, kBuffer, "getBufferParameter"); 339} 340 341void V8WebGLRenderingContext::getExtensionMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 342{ 343 WebGLRenderingContext* imp = V8WebGLRenderingContext::toNative(info.Holder()); 344 if (info.Length() < 1) { 345 throwTypeError(ExceptionMessages::failedToExecute("getExtension", "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(1, info.Length())), info.GetIsolate()); 346 return; 347 } 348 V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, name, info[0]); 349 RefPtr<WebGLExtension> extension(imp->getExtension(name)); 350 v8SetReturnValue(info, toV8Object(extension.get(), info.Holder(), info.GetIsolate())); 351} 352 353void V8WebGLRenderingContext::getFramebufferAttachmentParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 354{ 355 if (info.Length() != 3) { 356 throwTypeError(ExceptionMessages::failedToExecute("getFramebufferAttachmentParameter", "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(3, info.Length())), info.GetIsolate()); 357 return; 358 } 359 360 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); 361 unsigned target = toInt32(info[0]); 362 unsigned attachment = toInt32(info[1]); 363 unsigned pname = toInt32(info[2]); 364 WebGLGetInfo args = context->getFramebufferAttachmentParameter(target, attachment, pname); 365 v8SetReturnValue(info, toV8Object(args, info.Holder(), info.GetIsolate())); 366} 367 368void V8WebGLRenderingContext::getParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 369{ 370 if (info.Length() != 1) { 371 throwTypeError(ExceptionMessages::failedToExecute("getParameter", "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(1, info.Length())), info.GetIsolate()); 372 return; 373 } 374 375 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); 376 unsigned pname = toInt32(info[0]); 377 WebGLGetInfo args = context->getParameter(pname); 378 v8SetReturnValue(info, toV8Object(args, info.Holder(), info.GetIsolate())); 379} 380 381void V8WebGLRenderingContext::getProgramParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 382{ 383 if (info.Length() != 2) { 384 throwTypeError(ExceptionMessages::failedToExecute("getProgramParameter", "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(2, info.Length())), info.GetIsolate()); 385 return; 386 } 387 388 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); 389 if (info.Length() > 0 && !isUndefinedOrNull(info[0]) && !V8WebGLProgram::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { 390 throwUninformativeAndGenericTypeError(info.GetIsolate()); 391 return; 392 } 393 WebGLProgram* program = V8WebGLProgram::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate())) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(info[0])) : 0; 394 unsigned pname = toInt32(info[1]); 395 WebGLGetInfo args = context->getProgramParameter(program, pname); 396 v8SetReturnValue(info, toV8Object(args, info.Holder(), info.GetIsolate())); 397} 398 399void V8WebGLRenderingContext::getRenderbufferParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 400{ 401 getObjectParameter(info, kRenderbuffer, "getRenderbufferParameter"); 402} 403 404void V8WebGLRenderingContext::getShaderParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 405{ 406 if (info.Length() != 2) { 407 throwTypeError(ExceptionMessages::failedToExecute("getShaderParameter", "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(2, info.Length())), info.GetIsolate()); 408 return; 409 } 410 411 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); 412 if (info.Length() > 0 && !isUndefinedOrNull(info[0]) && !V8WebGLShader::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { 413 throwUninformativeAndGenericTypeError(info.GetIsolate()); 414 return; 415 } 416 WebGLShader* shader = V8WebGLShader::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate())) ? V8WebGLShader::toNative(v8::Handle<v8::Object>::Cast(info[0])) : 0; 417 unsigned pname = toInt32(info[1]); 418 WebGLGetInfo args = context->getShaderParameter(shader, pname); 419 v8SetReturnValue(info, toV8Object(args, info.Holder(), info.GetIsolate())); 420} 421 422void V8WebGLRenderingContext::getSupportedExtensionsMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 423{ 424 WebGLRenderingContext* imp = V8WebGLRenderingContext::toNative(info.Holder()); 425 if (imp->isContextLost()) { 426 v8SetReturnValueNull(info); 427 return; 428 } 429 430 Vector<String> value = imp->getSupportedExtensions(); 431 v8::Local<v8::Array> array = v8::Array::New(info.GetIsolate(), value.size()); 432 for (size_t ii = 0; ii < value.size(); ++ii) 433 array->Set(v8::Integer::New(ii, info.GetIsolate()), v8String(info.GetIsolate(), value[ii])); 434 v8SetReturnValue(info, array); 435} 436 437void V8WebGLRenderingContext::getTexParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 438{ 439 getObjectParameter(info, kTexture, "getTexParameter"); 440} 441 442void V8WebGLRenderingContext::getUniformMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 443{ 444 if (info.Length() != 2) { 445 throwTypeError(ExceptionMessages::failedToExecute("getUniform", "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(2, info.Length())), info.GetIsolate()); 446 return; 447 } 448 449 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); 450 if (info.Length() > 0 && !isUndefinedOrNull(info[0]) && !V8WebGLProgram::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { 451 throwUninformativeAndGenericTypeError(info.GetIsolate()); 452 return; 453 } 454 WebGLProgram* program = V8WebGLProgram::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate())) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(info[0])) : 0; 455 456 if (info.Length() > 1 && !isUndefinedOrNull(info[1]) && !V8WebGLUniformLocation::hasInstance(info[1], info.GetIsolate(), worldType(info.GetIsolate()))) { 457 throwUninformativeAndGenericTypeError(info.GetIsolate()); 458 return; 459 } 460 bool ok = false; 461 WebGLUniformLocation* location = toWebGLUniformLocation(info[1], ok, info.GetIsolate()); 462 463 WebGLGetInfo args = context->getUniform(program, location); 464 v8SetReturnValue(info, toV8Object(args, info.Holder(), info.GetIsolate())); 465} 466 467void V8WebGLRenderingContext::getVertexAttribMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 468{ 469 getObjectParameter(info, kVertexAttrib, "getVertexAttrib"); 470} 471 472enum FunctionToCall { 473 kUniform1v, kUniform2v, kUniform3v, kUniform4v, 474 kVertexAttrib1v, kVertexAttrib2v, kVertexAttrib3v, kVertexAttrib4v 475}; 476 477bool isFunctionToCallForAttribute(FunctionToCall functionToCall) 478{ 479 switch (functionToCall) { 480 case kVertexAttrib1v: 481 case kVertexAttrib2v: 482 case kVertexAttrib3v: 483 case kVertexAttrib4v: 484 return true; 485 default: 486 break; 487 } 488 return false; 489} 490 491static void vertexAttribAndUniformHelperf(const v8::FunctionCallbackInfo<v8::Value>& info, FunctionToCall functionToCall, const char* method) 492{ 493 // Forms: 494 // * glUniform1fv(WebGLUniformLocation location, Array data); 495 // * glUniform1fv(WebGLUniformLocation location, Float32Array data); 496 // * glUniform2fv(WebGLUniformLocation location, Array data); 497 // * glUniform2fv(WebGLUniformLocation location, Float32Array data); 498 // * glUniform3fv(WebGLUniformLocation location, Array data); 499 // * glUniform3fv(WebGLUniformLocation location, Float32Array data); 500 // * glUniform4fv(WebGLUniformLocation location, Array data); 501 // * glUniform4fv(WebGLUniformLocation location, Float32Array data); 502 // * glVertexAttrib1fv(GLint index, Array data); 503 // * glVertexAttrib1fv(GLint index, Float32Array data); 504 // * glVertexAttrib2fv(GLint index, Array data); 505 // * glVertexAttrib2fv(GLint index, Float32Array data); 506 // * glVertexAttrib3fv(GLint index, Array data); 507 // * glVertexAttrib3fv(GLint index, Float32Array data); 508 // * glVertexAttrib4fv(GLint index, Array data); 509 // * glVertexAttrib4fv(GLint index, Float32Array data); 510 511 if (info.Length() != 2) { 512 throwTypeError(ExceptionMessages::failedToExecute(method, "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(2, info.Length())), info.GetIsolate()); 513 return; 514 } 515 516 bool ok = false; 517 int index = -1; 518 WebGLUniformLocation* location = 0; 519 520 if (isFunctionToCallForAttribute(functionToCall)) 521 index = toInt32(info[0]); 522 else { 523 if (info.Length() > 0 && !isUndefinedOrNull(info[0]) && !V8WebGLUniformLocation::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { 524 throwUninformativeAndGenericTypeError(info.GetIsolate()); 525 return; 526 } 527 location = toWebGLUniformLocation(info[0], ok, info.GetIsolate()); 528 } 529 530 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); 531 532 if (V8Float32Array::hasInstance(info[1], info.GetIsolate(), worldType(info.GetIsolate()))) { 533 Float32Array* array = V8Float32Array::toNative(info[1]->ToObject()); 534 ASSERT(array != NULL); 535 switch (functionToCall) { 536 case kUniform1v: context->uniform1fv(location, array); break; 537 case kUniform2v: context->uniform2fv(location, array); break; 538 case kUniform3v: context->uniform3fv(location, array); break; 539 case kUniform4v: context->uniform4fv(location, array); break; 540 case kVertexAttrib1v: context->vertexAttrib1fv(index, array); break; 541 case kVertexAttrib2v: context->vertexAttrib2fv(index, array); break; 542 case kVertexAttrib3v: context->vertexAttrib3fv(index, array); break; 543 case kVertexAttrib4v: context->vertexAttrib4fv(index, array); break; 544 default: ASSERT_NOT_REACHED(); break; 545 } 546 return; 547 } 548 549 if (info[1].IsEmpty() || !info[1]->IsArray()) { 550 throwUninformativeAndGenericTypeError(info.GetIsolate()); 551 return; 552 } 553 v8::Handle<v8::Array> array = v8::Local<v8::Array>::Cast(info[1]); 554 uint32_t len = array->Length(); 555 float* data = jsArrayToFloatArray(array, len); 556 if (!data) { 557 // FIXME: consider different / better exception type. 558 setDOMException(SyntaxError, info.GetIsolate()); 559 return; 560 } 561 switch (functionToCall) { 562 case kUniform1v: context->uniform1fv(location, data, len); break; 563 case kUniform2v: context->uniform2fv(location, data, len); break; 564 case kUniform3v: context->uniform3fv(location, data, len); break; 565 case kUniform4v: context->uniform4fv(location, data, len); break; 566 case kVertexAttrib1v: context->vertexAttrib1fv(index, data, len); break; 567 case kVertexAttrib2v: context->vertexAttrib2fv(index, data, len); break; 568 case kVertexAttrib3v: context->vertexAttrib3fv(index, data, len); break; 569 case kVertexAttrib4v: context->vertexAttrib4fv(index, data, len); break; 570 default: ASSERT_NOT_REACHED(); break; 571 } 572 fastFree(data); 573} 574 575static void uniformHelperi(const v8::FunctionCallbackInfo<v8::Value>& info, FunctionToCall functionToCall, const char* method) 576{ 577 // Forms: 578 // * glUniform1iv(GLUniformLocation location, Array data); 579 // * glUniform1iv(GLUniformLocation location, Int32Array data); 580 // * glUniform2iv(GLUniformLocation location, Array data); 581 // * glUniform2iv(GLUniformLocation location, Int32Array data); 582 // * glUniform3iv(GLUniformLocation location, Array data); 583 // * glUniform3iv(GLUniformLocation location, Int32Array data); 584 // * glUniform4iv(GLUniformLocation location, Array data); 585 // * glUniform4iv(GLUniformLocation location, Int32Array data); 586 587 if (info.Length() != 2) { 588 throwTypeError(ExceptionMessages::failedToExecute(method, "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(2, info.Length())), info.GetIsolate()); 589 return; 590 } 591 592 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); 593 if (info.Length() > 0 && !isUndefinedOrNull(info[0]) && !V8WebGLUniformLocation::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { 594 throwUninformativeAndGenericTypeError(info.GetIsolate()); 595 return; 596 } 597 bool ok = false; 598 WebGLUniformLocation* location = toWebGLUniformLocation(info[0], ok, info.GetIsolate()); 599 600 if (V8Int32Array::hasInstance(info[1], info.GetIsolate(), worldType(info.GetIsolate()))) { 601 Int32Array* array = V8Int32Array::toNative(info[1]->ToObject()); 602 ASSERT(array != NULL); 603 switch (functionToCall) { 604 case kUniform1v: context->uniform1iv(location, array); break; 605 case kUniform2v: context->uniform2iv(location, array); break; 606 case kUniform3v: context->uniform3iv(location, array); break; 607 case kUniform4v: context->uniform4iv(location, array); break; 608 default: ASSERT_NOT_REACHED(); break; 609 } 610 return; 611 } 612 613 if (info[1].IsEmpty() || !info[1]->IsArray()) { 614 throwUninformativeAndGenericTypeError(info.GetIsolate()); 615 return; 616 } 617 v8::Handle<v8::Array> array = v8::Local<v8::Array>::Cast(info[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, info.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 635void V8WebGLRenderingContext::uniform1fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 636{ 637 vertexAttribAndUniformHelperf(info, kUniform1v, "uniform1fv"); 638} 639 640void V8WebGLRenderingContext::uniform1ivMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 641{ 642 uniformHelperi(info, kUniform1v, "uniform1iv"); 643} 644 645void V8WebGLRenderingContext::uniform2fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 646{ 647 vertexAttribAndUniformHelperf(info, kUniform2v, "uniform2fv"); 648} 649 650void V8WebGLRenderingContext::uniform2ivMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 651{ 652 uniformHelperi(info, kUniform2v, "uniform2iv"); 653} 654 655void V8WebGLRenderingContext::uniform3fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 656{ 657 vertexAttribAndUniformHelperf(info, kUniform3v, "uniform3fv"); 658} 659 660void V8WebGLRenderingContext::uniform3ivMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 661{ 662 uniformHelperi(info, kUniform3v, "uniform3iv"); 663} 664 665void V8WebGLRenderingContext::uniform4fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 666{ 667 vertexAttribAndUniformHelperf(info, kUniform4v, "uniform4fv"); 668} 669 670void V8WebGLRenderingContext::uniform4ivMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 671{ 672 uniformHelperi(info, kUniform4v, "uniform4iv"); 673} 674 675static void uniformMatrixHelper(const v8::FunctionCallbackInfo<v8::Value>& info, int matrixSize, const char* method) 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 (info.Length() != 3) { 687 throwTypeError(ExceptionMessages::failedToExecute(method, "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(3, info.Length())), info.GetIsolate()); 688 return; 689 } 690 691 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); 692 693 if (info.Length() > 0 && !isUndefinedOrNull(info[0]) && !V8WebGLUniformLocation::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { 694 throwUninformativeAndGenericTypeError(info.GetIsolate()); 695 return; 696 } 697 bool ok = false; 698 WebGLUniformLocation* location = toWebGLUniformLocation(info[0], ok, info.GetIsolate()); 699 700 bool transpose = info[1]->BooleanValue(); 701 if (V8Float32Array::hasInstance(info[2], info.GetIsolate(), worldType(info.GetIsolate()))) { 702 Float32Array* array = V8Float32Array::toNative(info[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 (info[2].IsEmpty() || !info[2]->IsArray()) { 714 throwUninformativeAndGenericTypeError(info.GetIsolate()); 715 return; 716 } 717 v8::Handle<v8::Array> array = v8::Local<v8::Array>::Cast(info[2]); 718 uint32_t len = array->Length(); 719 float* data = jsArrayToFloatArray(array, len); 720 if (!data) { 721 // FIXME: consider different / better exception type. 722 setDOMException(SyntaxError, info.GetIsolate()); 723 return; 724 } 725 switch (matrixSize) { 726 case 2: context->uniformMatrix2fv(location, transpose, data, len); break; 727 case 3: context->uniformMatrix3fv(location, transpose, data, len); break; 728 case 4: context->uniformMatrix4fv(location, transpose, data, len); break; 729 default: ASSERT_NOT_REACHED(); break; 730 } 731 fastFree(data); 732} 733 734void V8WebGLRenderingContext::uniformMatrix2fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 735{ 736 uniformMatrixHelper(info, 2, "uniformMatrix2fv"); 737} 738 739void V8WebGLRenderingContext::uniformMatrix3fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 740{ 741 uniformMatrixHelper(info, 3, "uniformMatrix3fv"); 742} 743 744void V8WebGLRenderingContext::uniformMatrix4fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 745{ 746 uniformMatrixHelper(info, 4, "uniformMatrix4fv"); 747} 748 749void V8WebGLRenderingContext::vertexAttrib1fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 750{ 751 vertexAttribAndUniformHelperf(info, kVertexAttrib1v, "vertexAttrib1fv"); 752} 753 754void V8WebGLRenderingContext::vertexAttrib2fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 755{ 756 vertexAttribAndUniformHelperf(info, kVertexAttrib2v, "vertexAttrib2fv"); 757} 758 759void V8WebGLRenderingContext::vertexAttrib3fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 760{ 761 vertexAttribAndUniformHelperf(info, kVertexAttrib3v, "vertexAttrib3fv"); 762} 763 764void V8WebGLRenderingContext::vertexAttrib4fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 765{ 766 vertexAttribAndUniformHelperf(info, kVertexAttrib4v, "vertexAttrib4fv"); 767} 768 769} // namespace WebCore 770