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