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
33 #if ENABLE(WEBGL)
34
35 #include "V8WebGLRenderingContext.h"
36
37 #include "ExceptionCode.h"
38 #include "NotImplemented.h"
39 #include "V8ArrayBufferView.h"
40 #include "V8Binding.h"
41 #include "V8BindingMacros.h"
42 #include "V8WebKitLoseContext.h"
43 #include "V8Float32Array.h"
44 #include "V8HTMLCanvasElement.h"
45 #include "V8HTMLImageElement.h"
46 #include "V8HTMLVideoElement.h"
47 #include "V8ImageData.h"
48 #include "V8Int16Array.h"
49 #include "V8Int32Array.h"
50 #include "V8Int8Array.h"
51 #include "V8OESStandardDerivatives.h"
52 #include "V8OESTextureFloat.h"
53 #include "V8OESVertexArrayObject.h"
54 #include "V8Proxy.h"
55 #include "V8Uint16Array.h"
56 #include "V8Uint32Array.h"
57 #include "V8Uint8Array.h"
58 #include "V8WebGLBuffer.h"
59 #include "V8WebGLFramebuffer.h"
60 #include "V8WebGLProgram.h"
61 #include "V8WebGLRenderbuffer.h"
62 #include "V8WebGLShader.h"
63 #include "V8WebGLTexture.h"
64 #include "V8WebGLUniformLocation.h"
65 #include "V8WebGLVertexArrayObjectOES.h"
66 #include "WebGLRenderingContext.h"
67 #include <wtf/FastMalloc.h>
68
69 namespace WebCore {
70
71 // Allocates new storage via tryFastMalloc.
72 // Returns NULL if array failed to convert for any reason.
jsArrayToFloatArray(v8::Handle<v8::Array> array,uint32_t len)73 static float* jsArrayToFloatArray(v8::Handle<v8::Array> array, uint32_t len)
74 {
75 // Convert the data element-by-element.
76 float* data;
77 if (!tryFastMalloc(len * sizeof(float)).getValue(data))
78 return 0;
79 for (uint32_t i = 0; i < len; i++) {
80 v8::Local<v8::Value> val = array->Get(v8::Integer::New(i));
81 if (!val->IsNumber()) {
82 fastFree(data);
83 return 0;
84 }
85 data[i] = toFloat(val);
86 }
87 return data;
88 }
89
90 // Allocates new storage via tryFastMalloc.
91 // Returns NULL if array failed to convert for any reason.
jsArrayToIntArray(v8::Handle<v8::Array> array,uint32_t len)92 static int* jsArrayToIntArray(v8::Handle<v8::Array> array, uint32_t len)
93 {
94 // Convert the data element-by-element.
95 int* data;
96 if (!tryFastMalloc(len * sizeof(int)).getValue(data))
97 return 0;
98 for (uint32_t i = 0; i < len; i++) {
99 v8::Local<v8::Value> val = array->Get(v8::Integer::New(i));
100 bool ok;
101 int ival = toInt32(val, ok);
102 if (!ok) {
103 fastFree(data);
104 return 0;
105 }
106 data[i] = ival;
107 }
108 return data;
109 }
110
toV8Object(const WebGLGetInfo & info)111 static v8::Handle<v8::Value> toV8Object(const WebGLGetInfo& info)
112 {
113 switch (info.getType()) {
114 case WebGLGetInfo::kTypeBool:
115 return v8::Boolean::New(info.getBool());
116 case WebGLGetInfo::kTypeBoolArray: {
117 const Vector<bool>& value = info.getBoolArray();
118 v8::Local<v8::Array> array = v8::Array::New(value.size());
119 for (size_t ii = 0; ii < value.size(); ++ii)
120 array->Set(v8::Integer::New(ii), v8::Boolean::New(value[ii]));
121 return array;
122 }
123 case WebGLGetInfo::kTypeFloat:
124 return v8::Number::New(info.getFloat());
125 case WebGLGetInfo::kTypeInt:
126 return v8::Integer::New(info.getInt());
127 case WebGLGetInfo::kTypeNull:
128 return v8::Null();
129 case WebGLGetInfo::kTypeString:
130 return v8::String::New(fromWebCoreString(info.getString()), info.getString().length());
131 case WebGLGetInfo::kTypeUnsignedInt:
132 return v8::Integer::NewFromUnsigned(info.getUnsignedInt());
133 case WebGLGetInfo::kTypeWebGLBuffer:
134 return toV8(info.getWebGLBuffer());
135 case WebGLGetInfo::kTypeWebGLFloatArray:
136 return toV8(info.getWebGLFloatArray());
137 case WebGLGetInfo::kTypeWebGLFramebuffer:
138 return toV8(info.getWebGLFramebuffer());
139 case WebGLGetInfo::kTypeWebGLIntArray:
140 return toV8(info.getWebGLIntArray());
141 // FIXME: implement WebGLObjectArray
142 // case WebGLGetInfo::kTypeWebGLObjectArray:
143 case WebGLGetInfo::kTypeWebGLProgram:
144 return toV8(info.getWebGLProgram());
145 case WebGLGetInfo::kTypeWebGLRenderbuffer:
146 return toV8(info.getWebGLRenderbuffer());
147 case WebGLGetInfo::kTypeWebGLTexture:
148 return toV8(info.getWebGLTexture());
149 case WebGLGetInfo::kTypeWebGLUnsignedByteArray:
150 return toV8(info.getWebGLUnsignedByteArray());
151 case WebGLGetInfo::kTypeWebGLVertexArrayObjectOES:
152 return toV8(info.getWebGLVertexArrayObjectOES());
153 default:
154 notImplemented();
155 return v8::Undefined();
156 }
157 }
158
toV8Object(WebGLExtension * extension,v8::Handle<v8::Object> contextObject)159 static v8::Handle<v8::Value> toV8Object(WebGLExtension* extension, v8::Handle<v8::Object> contextObject)
160 {
161 if (!extension)
162 return v8::Null();
163 v8::Handle<v8::Value> extensionObject;
164 const char* referenceName;
165 switch (extension->getName()) {
166 case WebGLExtension::WebKitLoseContextName:
167 extensionObject = toV8(static_cast<WebKitLoseContext*>(extension));
168 referenceName = "webKitLoseContextName";
169 break;
170 case WebGLExtension::OESStandardDerivativesName:
171 extensionObject = toV8(static_cast<OESStandardDerivatives*>(extension));
172 referenceName = "oesStandardDerivativesName";
173 break;
174 case WebGLExtension::OESTextureFloatName:
175 extensionObject = toV8(static_cast<OESTextureFloat*>(extension));
176 referenceName = "oesTextureFloatName";
177 break;
178 case WebGLExtension::OESVertexArrayObjectName:
179 extensionObject = toV8(static_cast<OESVertexArrayObject*>(extension));
180 referenceName = "oesVertexArrayObjectName";
181 break;
182 }
183 ASSERT(!extensionObject.IsEmpty());
184 V8DOMWrapper::setNamedHiddenReference(contextObject, referenceName, extensionObject);
185 return extensionObject;
186 }
187
188 enum ObjectType {
189 kBuffer, kRenderbuffer, kTexture, kVertexAttrib
190 };
191
getObjectParameter(const v8::Arguments & args,ObjectType objectType)192 static v8::Handle<v8::Value> getObjectParameter(const v8::Arguments& args, ObjectType objectType)
193 {
194 if (args.Length() != 2) {
195 V8Proxy::setDOMException(SYNTAX_ERR);
196 return notHandledByInterceptor();
197 }
198
199 ExceptionCode ec = 0;
200 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
201 unsigned target = toInt32(args[0]);
202 unsigned pname = toInt32(args[1]);
203 WebGLGetInfo info;
204 switch (objectType) {
205 case kBuffer:
206 info = context->getBufferParameter(target, pname, ec);
207 break;
208 case kRenderbuffer:
209 info = context->getRenderbufferParameter(target, pname, ec);
210 break;
211 case kTexture:
212 info = context->getTexParameter(target, pname, ec);
213 break;
214 case kVertexAttrib:
215 // target => index
216 info = context->getVertexAttrib(target, pname, ec);
217 break;
218 default:
219 notImplemented();
220 break;
221 }
222 if (ec) {
223 V8Proxy::setDOMException(ec);
224 return v8::Undefined();
225 }
226 return toV8Object(info);
227 }
228
toWebGLUniformLocation(v8::Handle<v8::Value> value,bool & ok)229 static WebGLUniformLocation* toWebGLUniformLocation(v8::Handle<v8::Value> value, bool& ok)
230 {
231 ok = false;
232 WebGLUniformLocation* location = 0;
233 if (V8WebGLUniformLocation::HasInstance(value)) {
234 location = V8WebGLUniformLocation::toNative(value->ToObject());
235 ok = true;
236 }
237 return location;
238 }
239
240 enum WhichProgramCall {
241 kProgramParameter, kUniform
242 };
243
getAttachedShadersCallback(const v8::Arguments & args)244 v8::Handle<v8::Value> V8WebGLRenderingContext::getAttachedShadersCallback(const v8::Arguments& args)
245 {
246 INC_STATS("DOM.WebGLRenderingContext.getAttachedShaders()");
247
248 if (args.Length() < 1) {
249 V8Proxy::setDOMException(SYNTAX_ERR);
250 return notHandledByInterceptor();
251 }
252
253 ExceptionCode ec = 0;
254 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
255 if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLProgram::HasInstance(args[0])) {
256 V8Proxy::throwTypeError();
257 return notHandledByInterceptor();
258 }
259 WebGLProgram* program = V8WebGLProgram::HasInstance(args[0]) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
260 Vector<WebGLShader*> shaders;
261 bool succeed = context->getAttachedShaders(program, shaders, ec);
262 if (ec) {
263 V8Proxy::setDOMException(ec);
264 return v8::Null();
265 }
266 if (!succeed)
267 return v8::Null();
268 v8::Local<v8::Array> array = v8::Array::New(shaders.size());
269 for (size_t ii = 0; ii < shaders.size(); ++ii)
270 array->Set(v8::Integer::New(ii), toV8(shaders[ii]));
271 return array;
272 }
273
getBufferParameterCallback(const v8::Arguments & args)274 v8::Handle<v8::Value> V8WebGLRenderingContext::getBufferParameterCallback(const v8::Arguments& args)
275 {
276 INC_STATS("DOM.WebGLRenderingContext.getBufferParameter()");
277 return getObjectParameter(args, kBuffer);
278 }
279
getExtensionCallback(const v8::Arguments & args)280 v8::Handle<v8::Value> V8WebGLRenderingContext::getExtensionCallback(const v8::Arguments& args)
281 {
282 INC_STATS("DOM.WebGLRenderingContext.getExtensionCallback()");
283 WebGLRenderingContext* imp = V8WebGLRenderingContext::toNative(args.Holder());
284 if (args.Length() < 1) {
285 V8Proxy::setDOMException(SYNTAX_ERR);
286 return notHandledByInterceptor();
287 }
288 STRING_TO_V8PARAMETER_EXCEPTION_BLOCK(V8Parameter<>, name, args[0]);
289 WebGLExtension* extension = imp->getExtension(name);
290 return toV8Object(extension, args.Holder());
291 }
292
getFramebufferAttachmentParameterCallback(const v8::Arguments & args)293 v8::Handle<v8::Value> V8WebGLRenderingContext::getFramebufferAttachmentParameterCallback(const v8::Arguments& args)
294 {
295 INC_STATS("DOM.WebGLRenderingContext.getFramebufferAttachmentParameter()");
296
297 if (args.Length() != 3) {
298 V8Proxy::setDOMException(SYNTAX_ERR);
299 return notHandledByInterceptor();
300 }
301
302 ExceptionCode ec = 0;
303 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
304 unsigned target = toInt32(args[0]);
305 unsigned attachment = toInt32(args[1]);
306 unsigned pname = toInt32(args[2]);
307 WebGLGetInfo info = context->getFramebufferAttachmentParameter(target, attachment, pname, ec);
308 if (ec) {
309 V8Proxy::setDOMException(ec);
310 return v8::Undefined();
311 }
312 return toV8Object(info);
313 }
314
getParameterCallback(const v8::Arguments & args)315 v8::Handle<v8::Value> V8WebGLRenderingContext::getParameterCallback(const v8::Arguments& args)
316 {
317 INC_STATS("DOM.WebGLRenderingContext.getParameter()");
318
319 if (args.Length() != 1) {
320 V8Proxy::setDOMException(SYNTAX_ERR);
321 return notHandledByInterceptor();
322 }
323
324 ExceptionCode ec = 0;
325 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
326 unsigned pname = toInt32(args[0]);
327 WebGLGetInfo info = context->getParameter(pname, ec);
328 if (ec) {
329 V8Proxy::setDOMException(ec);
330 return v8::Undefined();
331 }
332 return toV8Object(info);
333 }
334
getProgramParameterCallback(const v8::Arguments & args)335 v8::Handle<v8::Value> V8WebGLRenderingContext::getProgramParameterCallback(const v8::Arguments& args)
336 {
337 INC_STATS("DOM.WebGLRenderingContext.getProgramParameter()");
338
339 if (args.Length() != 2) {
340 V8Proxy::setDOMException(SYNTAX_ERR);
341 return notHandledByInterceptor();
342 }
343
344 ExceptionCode ec = 0;
345 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
346 if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLProgram::HasInstance(args[0])) {
347 V8Proxy::throwTypeError();
348 return notHandledByInterceptor();
349 }
350 WebGLProgram* program = V8WebGLProgram::HasInstance(args[0]) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
351 unsigned pname = toInt32(args[1]);
352 WebGLGetInfo info = context->getProgramParameter(program, pname, ec);
353 if (ec) {
354 V8Proxy::setDOMException(ec);
355 return v8::Undefined();
356 }
357 return toV8Object(info);
358 }
359
getRenderbufferParameterCallback(const v8::Arguments & args)360 v8::Handle<v8::Value> V8WebGLRenderingContext::getRenderbufferParameterCallback(const v8::Arguments& args)
361 {
362 INC_STATS("DOM.WebGLRenderingContext.getRenderbufferParameter()");
363 return getObjectParameter(args, kRenderbuffer);
364 }
365
getShaderParameterCallback(const v8::Arguments & args)366 v8::Handle<v8::Value> V8WebGLRenderingContext::getShaderParameterCallback(const v8::Arguments& args)
367 {
368 INC_STATS("DOM.WebGLRenderingContext.getShaderParameter()");
369
370 if (args.Length() != 2) {
371 V8Proxy::setDOMException(SYNTAX_ERR);
372 return notHandledByInterceptor();
373 }
374
375 ExceptionCode ec = 0;
376 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
377 if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLShader::HasInstance(args[0])) {
378 V8Proxy::throwTypeError();
379 return notHandledByInterceptor();
380 }
381 WebGLShader* shader = V8WebGLShader::HasInstance(args[0]) ? V8WebGLShader::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
382 unsigned pname = toInt32(args[1]);
383 WebGLGetInfo info = context->getShaderParameter(shader, pname, ec);
384 if (ec) {
385 V8Proxy::setDOMException(ec);
386 return v8::Undefined();
387 }
388 return toV8Object(info);
389 }
390
getSupportedExtensionsCallback(const v8::Arguments & args)391 v8::Handle<v8::Value> V8WebGLRenderingContext::getSupportedExtensionsCallback(const v8::Arguments& args)
392 {
393 INC_STATS("DOM.WebGLRenderingContext.getSupportedExtensionsCallback()");
394 WebGLRenderingContext* imp = V8WebGLRenderingContext::toNative(args.Holder());
395 if (imp->isContextLost())
396 return v8::Null();
397
398 Vector<String> value = imp->getSupportedExtensions();
399 v8::Local<v8::Array> array = v8::Array::New(value.size());
400 for (size_t ii = 0; ii < value.size(); ++ii)
401 array->Set(v8::Integer::New(ii), v8::String::New(fromWebCoreString(value[ii]), value[ii].length()));
402 return array;
403 }
404
getTexParameterCallback(const v8::Arguments & args)405 v8::Handle<v8::Value> V8WebGLRenderingContext::getTexParameterCallback(const v8::Arguments& args)
406 {
407 INC_STATS("DOM.WebGLRenderingContext.getTexParameter()");
408 return getObjectParameter(args, kTexture);
409 }
410
getUniformCallback(const v8::Arguments & args)411 v8::Handle<v8::Value> V8WebGLRenderingContext::getUniformCallback(const v8::Arguments& args)
412 {
413 INC_STATS("DOM.WebGLRenderingContext.getUniform()");
414
415 if (args.Length() != 2) {
416 V8Proxy::setDOMException(SYNTAX_ERR);
417 return notHandledByInterceptor();
418 }
419
420 ExceptionCode ec = 0;
421 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
422 if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLProgram::HasInstance(args[0])) {
423 V8Proxy::throwTypeError();
424 return notHandledByInterceptor();
425 }
426 WebGLProgram* program = V8WebGLProgram::HasInstance(args[0]) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
427
428 if (args.Length() > 1 && !isUndefinedOrNull(args[1]) && !V8WebGLUniformLocation::HasInstance(args[1])) {
429 V8Proxy::throwTypeError();
430 return notHandledByInterceptor();
431 }
432 bool ok = false;
433 WebGLUniformLocation* location = toWebGLUniformLocation(args[1], ok);
434
435 WebGLGetInfo info = context->getUniform(program, location, ec);
436 if (ec) {
437 V8Proxy::setDOMException(ec);
438 return v8::Undefined();
439 }
440 return toV8Object(info);
441 }
442
getVertexAttribCallback(const v8::Arguments & args)443 v8::Handle<v8::Value> V8WebGLRenderingContext::getVertexAttribCallback(const v8::Arguments& args)
444 {
445 INC_STATS("DOM.WebGLRenderingContext.getVertexAttrib()");
446 return getObjectParameter(args, kVertexAttrib);
447 }
448
449 enum FunctionToCall {
450 kUniform1v, kUniform2v, kUniform3v, kUniform4v,
451 kVertexAttrib1v, kVertexAttrib2v, kVertexAttrib3v, kVertexAttrib4v
452 };
453
isFunctionToCallForAttribute(FunctionToCall functionToCall)454 bool isFunctionToCallForAttribute(FunctionToCall functionToCall)
455 {
456 switch (functionToCall) {
457 case kVertexAttrib1v:
458 case kVertexAttrib2v:
459 case kVertexAttrib3v:
460 case kVertexAttrib4v:
461 return true;
462 default:
463 break;
464 }
465 return false;
466 }
467
vertexAttribAndUniformHelperf(const v8::Arguments & args,FunctionToCall functionToCall)468 static v8::Handle<v8::Value> vertexAttribAndUniformHelperf(const v8::Arguments& args,
469 FunctionToCall functionToCall) {
470 // Forms:
471 // * glUniform1fv(WebGLUniformLocation location, Array data);
472 // * glUniform1fv(WebGLUniformLocation location, Float32Array data);
473 // * glUniform2fv(WebGLUniformLocation location, Array data);
474 // * glUniform2fv(WebGLUniformLocation location, Float32Array data);
475 // * glUniform3fv(WebGLUniformLocation location, Array data);
476 // * glUniform3fv(WebGLUniformLocation location, Float32Array data);
477 // * glUniform4fv(WebGLUniformLocation location, Array data);
478 // * glUniform4fv(WebGLUniformLocation location, Float32Array data);
479 // * glVertexAttrib1fv(GLint index, Array data);
480 // * glVertexAttrib1fv(GLint index, Float32Array data);
481 // * glVertexAttrib2fv(GLint index, Array data);
482 // * glVertexAttrib2fv(GLint index, Float32Array data);
483 // * glVertexAttrib3fv(GLint index, Array data);
484 // * glVertexAttrib3fv(GLint index, Float32Array data);
485 // * glVertexAttrib4fv(GLint index, Array data);
486 // * glVertexAttrib4fv(GLint index, Float32Array data);
487
488 if (args.Length() != 2) {
489 V8Proxy::setDOMException(SYNTAX_ERR);
490 return notHandledByInterceptor();
491 }
492
493 bool ok = false;
494 int index = -1;
495 WebGLUniformLocation* location = 0;
496
497 if (isFunctionToCallForAttribute(functionToCall))
498 index = toInt32(args[0]);
499 else {
500 if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLUniformLocation::HasInstance(args[0])) {
501 V8Proxy::throwTypeError();
502 return notHandledByInterceptor();
503 }
504 location = toWebGLUniformLocation(args[0], ok);
505 }
506
507 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
508
509 if (V8Float32Array::HasInstance(args[1])) {
510 Float32Array* array = V8Float32Array::toNative(args[1]->ToObject());
511 ASSERT(array != NULL);
512 ExceptionCode ec = 0;
513 switch (functionToCall) {
514 case kUniform1v: context->uniform1fv(location, array, ec); break;
515 case kUniform2v: context->uniform2fv(location, array, ec); break;
516 case kUniform3v: context->uniform3fv(location, array, ec); break;
517 case kUniform4v: context->uniform4fv(location, array, ec); break;
518 case kVertexAttrib1v: context->vertexAttrib1fv(index, array); break;
519 case kVertexAttrib2v: context->vertexAttrib2fv(index, array); break;
520 case kVertexAttrib3v: context->vertexAttrib3fv(index, array); break;
521 case kVertexAttrib4v: context->vertexAttrib4fv(index, array); break;
522 default: ASSERT_NOT_REACHED(); break;
523 }
524 if (ec)
525 V8Proxy::setDOMException(ec);
526 return v8::Undefined();
527 }
528
529 if (args[1].IsEmpty() || !args[1]->IsArray()) {
530 V8Proxy::throwTypeError();
531 return notHandledByInterceptor();
532 }
533 v8::Handle<v8::Array> array =
534 v8::Local<v8::Array>::Cast(args[1]);
535 uint32_t len = array->Length();
536 float* data = jsArrayToFloatArray(array, len);
537 if (!data) {
538 // FIXME: consider different / better exception type.
539 V8Proxy::setDOMException(SYNTAX_ERR);
540 return notHandledByInterceptor();
541 }
542 ExceptionCode ec = 0;
543 switch (functionToCall) {
544 case kUniform1v: context->uniform1fv(location, data, len, ec); break;
545 case kUniform2v: context->uniform2fv(location, data, len, ec); break;
546 case kUniform3v: context->uniform3fv(location, data, len, ec); break;
547 case kUniform4v: context->uniform4fv(location, data, len, ec); break;
548 case kVertexAttrib1v: context->vertexAttrib1fv(index, data, len); break;
549 case kVertexAttrib2v: context->vertexAttrib2fv(index, data, len); break;
550 case kVertexAttrib3v: context->vertexAttrib3fv(index, data, len); break;
551 case kVertexAttrib4v: context->vertexAttrib4fv(index, data, len); break;
552 default: ASSERT_NOT_REACHED(); break;
553 }
554 fastFree(data);
555 if (ec)
556 V8Proxy::setDOMException(ec);
557 return v8::Undefined();
558 }
559
uniformHelperi(const v8::Arguments & args,FunctionToCall functionToCall)560 static v8::Handle<v8::Value> uniformHelperi(const v8::Arguments& args,
561 FunctionToCall functionToCall) {
562 // Forms:
563 // * glUniform1iv(GLUniformLocation location, Array data);
564 // * glUniform1iv(GLUniformLocation location, Int32Array data);
565 // * glUniform2iv(GLUniformLocation location, Array data);
566 // * glUniform2iv(GLUniformLocation location, Int32Array data);
567 // * glUniform3iv(GLUniformLocation location, Array data);
568 // * glUniform3iv(GLUniformLocation location, Int32Array data);
569 // * glUniform4iv(GLUniformLocation location, Array data);
570 // * glUniform4iv(GLUniformLocation location, Int32Array data);
571
572 if (args.Length() != 2) {
573 V8Proxy::setDOMException(SYNTAX_ERR);
574 return notHandledByInterceptor();
575 }
576
577 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
578 if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLUniformLocation::HasInstance(args[0])) {
579 V8Proxy::throwTypeError();
580 return notHandledByInterceptor();
581 }
582 bool ok = false;
583 WebGLUniformLocation* location = toWebGLUniformLocation(args[0], ok);
584
585 if (V8Int32Array::HasInstance(args[1])) {
586 Int32Array* array = V8Int32Array::toNative(args[1]->ToObject());
587 ASSERT(array != NULL);
588 ExceptionCode ec = 0;
589 switch (functionToCall) {
590 case kUniform1v: context->uniform1iv(location, array, ec); break;
591 case kUniform2v: context->uniform2iv(location, array, ec); break;
592 case kUniform3v: context->uniform3iv(location, array, ec); break;
593 case kUniform4v: context->uniform4iv(location, array, ec); break;
594 default: ASSERT_NOT_REACHED(); break;
595 }
596 if (ec)
597 V8Proxy::setDOMException(ec);
598 return v8::Undefined();
599 }
600
601 if (args[1].IsEmpty() || !args[1]->IsArray()) {
602 V8Proxy::throwTypeError();
603 return notHandledByInterceptor();
604 }
605 v8::Handle<v8::Array> array =
606 v8::Local<v8::Array>::Cast(args[1]);
607 uint32_t len = array->Length();
608 int* data = jsArrayToIntArray(array, len);
609 if (!data) {
610 // FIXME: consider different / better exception type.
611 V8Proxy::setDOMException(SYNTAX_ERR);
612 return notHandledByInterceptor();
613 }
614 ExceptionCode ec = 0;
615 switch (functionToCall) {
616 case kUniform1v: context->uniform1iv(location, data, len, ec); break;
617 case kUniform2v: context->uniform2iv(location, data, len, ec); break;
618 case kUniform3v: context->uniform3iv(location, data, len, ec); break;
619 case kUniform4v: context->uniform4iv(location, data, len, ec); break;
620 default: ASSERT_NOT_REACHED(); break;
621 }
622 fastFree(data);
623 if (ec)
624 V8Proxy::setDOMException(ec);
625 return v8::Undefined();
626 }
627
uniform1fvCallback(const v8::Arguments & args)628 v8::Handle<v8::Value> V8WebGLRenderingContext::uniform1fvCallback(const v8::Arguments& args)
629 {
630 INC_STATS("DOM.WebGLRenderingContext.uniform1fv()");
631 return vertexAttribAndUniformHelperf(args, kUniform1v);
632 }
633
uniform1ivCallback(const v8::Arguments & args)634 v8::Handle<v8::Value> V8WebGLRenderingContext::uniform1ivCallback(const v8::Arguments& args)
635 {
636 INC_STATS("DOM.WebGLRenderingContext.uniform1iv()");
637 return uniformHelperi(args, kUniform1v);
638 }
639
uniform2fvCallback(const v8::Arguments & args)640 v8::Handle<v8::Value> V8WebGLRenderingContext::uniform2fvCallback(const v8::Arguments& args)
641 {
642 INC_STATS("DOM.WebGLRenderingContext.uniform2fv()");
643 return vertexAttribAndUniformHelperf(args, kUniform2v);
644 }
645
uniform2ivCallback(const v8::Arguments & args)646 v8::Handle<v8::Value> V8WebGLRenderingContext::uniform2ivCallback(const v8::Arguments& args)
647 {
648 INC_STATS("DOM.WebGLRenderingContext.uniform2iv()");
649 return uniformHelperi(args, kUniform2v);
650 }
651
uniform3fvCallback(const v8::Arguments & args)652 v8::Handle<v8::Value> V8WebGLRenderingContext::uniform3fvCallback(const v8::Arguments& args)
653 {
654 INC_STATS("DOM.WebGLRenderingContext.uniform3fv()");
655 return vertexAttribAndUniformHelperf(args, kUniform3v);
656 }
657
uniform3ivCallback(const v8::Arguments & args)658 v8::Handle<v8::Value> V8WebGLRenderingContext::uniform3ivCallback(const v8::Arguments& args)
659 {
660 INC_STATS("DOM.WebGLRenderingContext.uniform3iv()");
661 return uniformHelperi(args, kUniform3v);
662 }
663
uniform4fvCallback(const v8::Arguments & args)664 v8::Handle<v8::Value> V8WebGLRenderingContext::uniform4fvCallback(const v8::Arguments& args)
665 {
666 INC_STATS("DOM.WebGLRenderingContext.uniform4fv()");
667 return vertexAttribAndUniformHelperf(args, kUniform4v);
668 }
669
uniform4ivCallback(const v8::Arguments & args)670 v8::Handle<v8::Value> V8WebGLRenderingContext::uniform4ivCallback(const v8::Arguments& args)
671 {
672 INC_STATS("DOM.WebGLRenderingContext.uniform4iv()");
673 return uniformHelperi(args, kUniform4v);
674 }
675
uniformMatrixHelper(const v8::Arguments & args,int matrixSize)676 static v8::Handle<v8::Value> uniformMatrixHelper(const v8::Arguments& args,
677 int matrixSize)
678 {
679 // Forms:
680 // * glUniformMatrix2fv(GLint location, GLboolean transpose, Array data);
681 // * glUniformMatrix2fv(GLint location, GLboolean transpose, Float32Array data);
682 // * glUniformMatrix3fv(GLint location, GLboolean transpose, Array data);
683 // * glUniformMatrix3fv(GLint location, GLboolean transpose, Float32Array data);
684 // * glUniformMatrix4fv(GLint location, GLboolean transpose, Array data);
685 // * glUniformMatrix4fv(GLint location, GLboolean transpose, Float32Array data);
686 //
687 // FIXME: need to change to accept Float32Array as well.
688 if (args.Length() != 3) {
689 V8Proxy::setDOMException(SYNTAX_ERR);
690 return notHandledByInterceptor();
691 }
692
693 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
694
695 if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLUniformLocation::HasInstance(args[0])) {
696 V8Proxy::throwTypeError();
697 return notHandledByInterceptor();
698 }
699 bool ok = false;
700 WebGLUniformLocation* location = toWebGLUniformLocation(args[0], ok);
701
702 bool transpose = args[1]->BooleanValue();
703 if (V8Float32Array::HasInstance(args[2])) {
704 Float32Array* array = V8Float32Array::toNative(args[2]->ToObject());
705 ASSERT(array != NULL);
706 ExceptionCode ec = 0;
707 switch (matrixSize) {
708 case 2: context->uniformMatrix2fv(location, transpose, array, ec); break;
709 case 3: context->uniformMatrix3fv(location, transpose, array, ec); break;
710 case 4: context->uniformMatrix4fv(location, transpose, array, ec); break;
711 default: ASSERT_NOT_REACHED(); break;
712 }
713 if (ec)
714 V8Proxy::setDOMException(ec);
715 return v8::Undefined();
716 }
717
718 if (args[2].IsEmpty() || !args[2]->IsArray()) {
719 V8Proxy::throwTypeError();
720 return notHandledByInterceptor();
721 }
722 v8::Handle<v8::Array> array =
723 v8::Local<v8::Array>::Cast(args[2]);
724 uint32_t len = array->Length();
725 float* data = jsArrayToFloatArray(array, len);
726 if (!data) {
727 // FIXME: consider different / better exception type.
728 V8Proxy::setDOMException(SYNTAX_ERR);
729 return notHandledByInterceptor();
730 }
731 ExceptionCode ec = 0;
732 switch (matrixSize) {
733 case 2: context->uniformMatrix2fv(location, transpose, data, len, ec); break;
734 case 3: context->uniformMatrix3fv(location, transpose, data, len, ec); break;
735 case 4: context->uniformMatrix4fv(location, transpose, data, len, ec); break;
736 default: ASSERT_NOT_REACHED(); break;
737 }
738 fastFree(data);
739 if (ec)
740 V8Proxy::setDOMException(ec);
741 return v8::Undefined();
742 }
743
uniformMatrix2fvCallback(const v8::Arguments & args)744 v8::Handle<v8::Value> V8WebGLRenderingContext::uniformMatrix2fvCallback(const v8::Arguments& args)
745 {
746 INC_STATS("DOM.WebGLRenderingContext.uniformMatrix2fv()");
747 return uniformMatrixHelper(args, 2);
748 }
749
uniformMatrix3fvCallback(const v8::Arguments & args)750 v8::Handle<v8::Value> V8WebGLRenderingContext::uniformMatrix3fvCallback(const v8::Arguments& args)
751 {
752 INC_STATS("DOM.WebGLRenderingContext.uniformMatrix3fv()");
753 return uniformMatrixHelper(args, 3);
754 }
755
uniformMatrix4fvCallback(const v8::Arguments & args)756 v8::Handle<v8::Value> V8WebGLRenderingContext::uniformMatrix4fvCallback(const v8::Arguments& args)
757 {
758 INC_STATS("DOM.WebGLRenderingContext.uniformMatrix4fv()");
759 return uniformMatrixHelper(args, 4);
760 }
761
vertexAttrib1fvCallback(const v8::Arguments & args)762 v8::Handle<v8::Value> V8WebGLRenderingContext::vertexAttrib1fvCallback(const v8::Arguments& args)
763 {
764 INC_STATS("DOM.WebGLRenderingContext.vertexAttrib1fv()");
765 return vertexAttribAndUniformHelperf(args, kVertexAttrib1v);
766 }
767
vertexAttrib2fvCallback(const v8::Arguments & args)768 v8::Handle<v8::Value> V8WebGLRenderingContext::vertexAttrib2fvCallback(const v8::Arguments& args)
769 {
770 INC_STATS("DOM.WebGLRenderingContext.vertexAttrib2fv()");
771 return vertexAttribAndUniformHelperf(args, kVertexAttrib2v);
772 }
773
vertexAttrib3fvCallback(const v8::Arguments & args)774 v8::Handle<v8::Value> V8WebGLRenderingContext::vertexAttrib3fvCallback(const v8::Arguments& args)
775 {
776 INC_STATS("DOM.WebGLRenderingContext.vertexAttrib3fv()");
777 return vertexAttribAndUniformHelperf(args, kVertexAttrib3v);
778 }
779
vertexAttrib4fvCallback(const v8::Arguments & args)780 v8::Handle<v8::Value> V8WebGLRenderingContext::vertexAttrib4fvCallback(const v8::Arguments& args)
781 {
782 INC_STATS("DOM.WebGLRenderingContext.vertexAttrib4fv()");
783 return vertexAttribAndUniformHelperf(args, kVertexAttrib4v);
784 }
785
786 } // namespace WebCore
787
788 #endif // ENABLE(WEBGL)
789