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 switch (extension->getName()) {
165 case WebGLExtension::WebKitLoseContextName:
166 extensionObject = toV8(static_cast<WebKitLoseContext*>(extension));
167 break;
168 case WebGLExtension::OESStandardDerivativesName:
169 extensionObject = toV8(static_cast<OESStandardDerivatives*>(extension));
170 break;
171 case WebGLExtension::OESTextureFloatName:
172 extensionObject = toV8(static_cast<OESTextureFloat*>(extension));
173 break;
174 case WebGLExtension::OESVertexArrayObjectName:
175 extensionObject = toV8(static_cast<OESVertexArrayObject*>(extension));
176 break;
177 }
178 ASSERT(!extensionObject.IsEmpty());
179 V8DOMWrapper::setHiddenReference(contextObject, extensionObject);
180 return extensionObject;
181 }
182
183 enum ObjectType {
184 kBuffer, kRenderbuffer, kTexture, kVertexAttrib
185 };
186
getObjectParameter(const v8::Arguments & args,ObjectType objectType)187 static v8::Handle<v8::Value> getObjectParameter(const v8::Arguments& args, ObjectType objectType)
188 {
189 if (args.Length() != 2) {
190 V8Proxy::setDOMException(SYNTAX_ERR);
191 return notHandledByInterceptor();
192 }
193
194 ExceptionCode ec = 0;
195 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
196 unsigned target = toInt32(args[0]);
197 unsigned pname = toInt32(args[1]);
198 WebGLGetInfo info;
199 switch (objectType) {
200 case kBuffer:
201 info = context->getBufferParameter(target, pname, ec);
202 break;
203 case kRenderbuffer:
204 info = context->getRenderbufferParameter(target, pname, ec);
205 break;
206 case kTexture:
207 info = context->getTexParameter(target, pname, ec);
208 break;
209 case kVertexAttrib:
210 // target => index
211 info = context->getVertexAttrib(target, pname, ec);
212 break;
213 default:
214 notImplemented();
215 break;
216 }
217 if (ec) {
218 V8Proxy::setDOMException(ec);
219 return v8::Undefined();
220 }
221 return toV8Object(info);
222 }
223
toWebGLUniformLocation(v8::Handle<v8::Value> value,bool & ok)224 static WebGLUniformLocation* toWebGLUniformLocation(v8::Handle<v8::Value> value, bool& ok)
225 {
226 ok = false;
227 WebGLUniformLocation* location = 0;
228 if (V8WebGLUniformLocation::HasInstance(value)) {
229 location = V8WebGLUniformLocation::toNative(value->ToObject());
230 ok = true;
231 }
232 return location;
233 }
234
235 enum WhichProgramCall {
236 kProgramParameter, kUniform
237 };
238
getAttachedShadersCallback(const v8::Arguments & args)239 v8::Handle<v8::Value> V8WebGLRenderingContext::getAttachedShadersCallback(const v8::Arguments& args)
240 {
241 INC_STATS("DOM.WebGLRenderingContext.getAttachedShaders()");
242
243 if (args.Length() < 1) {
244 V8Proxy::setDOMException(SYNTAX_ERR);
245 return notHandledByInterceptor();
246 }
247
248 ExceptionCode ec = 0;
249 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
250 if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLProgram::HasInstance(args[0])) {
251 V8Proxy::throwTypeError();
252 return notHandledByInterceptor();
253 }
254 WebGLProgram* program = V8WebGLProgram::HasInstance(args[0]) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
255 Vector<WebGLShader*> shaders;
256 bool succeed = context->getAttachedShaders(program, shaders, ec);
257 if (ec) {
258 V8Proxy::setDOMException(ec);
259 return v8::Null();
260 }
261 if (!succeed)
262 return v8::Null();
263 v8::Local<v8::Array> array = v8::Array::New(shaders.size());
264 for (size_t ii = 0; ii < shaders.size(); ++ii)
265 array->Set(v8::Integer::New(ii), toV8(shaders[ii]));
266 return array;
267 }
268
getBufferParameterCallback(const v8::Arguments & args)269 v8::Handle<v8::Value> V8WebGLRenderingContext::getBufferParameterCallback(const v8::Arguments& args)
270 {
271 INC_STATS("DOM.WebGLRenderingContext.getBufferParameter()");
272 return getObjectParameter(args, kBuffer);
273 }
274
getExtensionCallback(const v8::Arguments & args)275 v8::Handle<v8::Value> V8WebGLRenderingContext::getExtensionCallback(const v8::Arguments& args)
276 {
277 INC_STATS("DOM.WebGLRenderingContext.getExtensionCallback()");
278 WebGLRenderingContext* imp = V8WebGLRenderingContext::toNative(args.Holder());
279 if (args.Length() < 1) {
280 V8Proxy::setDOMException(SYNTAX_ERR);
281 return notHandledByInterceptor();
282 }
283 STRING_TO_V8PARAMETER_EXCEPTION_BLOCK(V8Parameter<>, name, args[0]);
284 WebGLExtension* extension = imp->getExtension(name);
285 return toV8Object(extension, args.Holder());
286 }
287
getFramebufferAttachmentParameterCallback(const v8::Arguments & args)288 v8::Handle<v8::Value> V8WebGLRenderingContext::getFramebufferAttachmentParameterCallback(const v8::Arguments& args)
289 {
290 INC_STATS("DOM.WebGLRenderingContext.getFramebufferAttachmentParameter()");
291
292 if (args.Length() != 3) {
293 V8Proxy::setDOMException(SYNTAX_ERR);
294 return notHandledByInterceptor();
295 }
296
297 ExceptionCode ec = 0;
298 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
299 unsigned target = toInt32(args[0]);
300 unsigned attachment = toInt32(args[1]);
301 unsigned pname = toInt32(args[2]);
302 WebGLGetInfo info = context->getFramebufferAttachmentParameter(target, attachment, pname, ec);
303 if (ec) {
304 V8Proxy::setDOMException(ec);
305 return v8::Undefined();
306 }
307 return toV8Object(info);
308 }
309
getParameterCallback(const v8::Arguments & args)310 v8::Handle<v8::Value> V8WebGLRenderingContext::getParameterCallback(const v8::Arguments& args)
311 {
312 INC_STATS("DOM.WebGLRenderingContext.getParameter()");
313
314 if (args.Length() != 1) {
315 V8Proxy::setDOMException(SYNTAX_ERR);
316 return notHandledByInterceptor();
317 }
318
319 ExceptionCode ec = 0;
320 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
321 unsigned pname = toInt32(args[0]);
322 WebGLGetInfo info = context->getParameter(pname, ec);
323 if (ec) {
324 V8Proxy::setDOMException(ec);
325 return v8::Undefined();
326 }
327 return toV8Object(info);
328 }
329
getProgramParameterCallback(const v8::Arguments & args)330 v8::Handle<v8::Value> V8WebGLRenderingContext::getProgramParameterCallback(const v8::Arguments& args)
331 {
332 INC_STATS("DOM.WebGLRenderingContext.getProgramParameter()");
333
334 if (args.Length() != 2) {
335 V8Proxy::setDOMException(SYNTAX_ERR);
336 return notHandledByInterceptor();
337 }
338
339 ExceptionCode ec = 0;
340 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
341 if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLProgram::HasInstance(args[0])) {
342 V8Proxy::throwTypeError();
343 return notHandledByInterceptor();
344 }
345 WebGLProgram* program = V8WebGLProgram::HasInstance(args[0]) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
346 unsigned pname = toInt32(args[1]);
347 WebGLGetInfo info = context->getProgramParameter(program, pname, ec);
348 if (ec) {
349 V8Proxy::setDOMException(ec);
350 return v8::Undefined();
351 }
352 return toV8Object(info);
353 }
354
getRenderbufferParameterCallback(const v8::Arguments & args)355 v8::Handle<v8::Value> V8WebGLRenderingContext::getRenderbufferParameterCallback(const v8::Arguments& args)
356 {
357 INC_STATS("DOM.WebGLRenderingContext.getRenderbufferParameter()");
358 return getObjectParameter(args, kRenderbuffer);
359 }
360
getShaderParameterCallback(const v8::Arguments & args)361 v8::Handle<v8::Value> V8WebGLRenderingContext::getShaderParameterCallback(const v8::Arguments& args)
362 {
363 INC_STATS("DOM.WebGLRenderingContext.getShaderParameter()");
364
365 if (args.Length() != 2) {
366 V8Proxy::setDOMException(SYNTAX_ERR);
367 return notHandledByInterceptor();
368 }
369
370 ExceptionCode ec = 0;
371 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
372 if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLShader::HasInstance(args[0])) {
373 V8Proxy::throwTypeError();
374 return notHandledByInterceptor();
375 }
376 WebGLShader* shader = V8WebGLShader::HasInstance(args[0]) ? V8WebGLShader::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
377 unsigned pname = toInt32(args[1]);
378 WebGLGetInfo info = context->getShaderParameter(shader, pname, ec);
379 if (ec) {
380 V8Proxy::setDOMException(ec);
381 return v8::Undefined();
382 }
383 return toV8Object(info);
384 }
385
getSupportedExtensionsCallback(const v8::Arguments & args)386 v8::Handle<v8::Value> V8WebGLRenderingContext::getSupportedExtensionsCallback(const v8::Arguments& args)
387 {
388 INC_STATS("DOM.WebGLRenderingContext.getSupportedExtensionsCallback()");
389 WebGLRenderingContext* imp = V8WebGLRenderingContext::toNative(args.Holder());
390 if (imp->isContextLost())
391 return v8::Null();
392
393 Vector<String> value = imp->getSupportedExtensions();
394 v8::Local<v8::Array> array = v8::Array::New(value.size());
395 for (size_t ii = 0; ii < value.size(); ++ii)
396 array->Set(v8::Integer::New(ii), v8::String::New(fromWebCoreString(value[ii]), value[ii].length()));
397 return array;
398 }
399
getTexParameterCallback(const v8::Arguments & args)400 v8::Handle<v8::Value> V8WebGLRenderingContext::getTexParameterCallback(const v8::Arguments& args)
401 {
402 INC_STATS("DOM.WebGLRenderingContext.getTexParameter()");
403 return getObjectParameter(args, kTexture);
404 }
405
getUniformCallback(const v8::Arguments & args)406 v8::Handle<v8::Value> V8WebGLRenderingContext::getUniformCallback(const v8::Arguments& args)
407 {
408 INC_STATS("DOM.WebGLRenderingContext.getUniform()");
409
410 if (args.Length() != 2) {
411 V8Proxy::setDOMException(SYNTAX_ERR);
412 return notHandledByInterceptor();
413 }
414
415 ExceptionCode ec = 0;
416 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
417 if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLProgram::HasInstance(args[0])) {
418 V8Proxy::throwTypeError();
419 return notHandledByInterceptor();
420 }
421 WebGLProgram* program = V8WebGLProgram::HasInstance(args[0]) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
422
423 if (args.Length() > 1 && !isUndefinedOrNull(args[1]) && !V8WebGLUniformLocation::HasInstance(args[1])) {
424 V8Proxy::throwTypeError();
425 return notHandledByInterceptor();
426 }
427 bool ok = false;
428 WebGLUniformLocation* location = toWebGLUniformLocation(args[1], ok);
429
430 WebGLGetInfo info = context->getUniform(program, location, ec);
431 if (ec) {
432 V8Proxy::setDOMException(ec);
433 return v8::Undefined();
434 }
435 return toV8Object(info);
436 }
437
getVertexAttribCallback(const v8::Arguments & args)438 v8::Handle<v8::Value> V8WebGLRenderingContext::getVertexAttribCallback(const v8::Arguments& args)
439 {
440 INC_STATS("DOM.WebGLRenderingContext.getVertexAttrib()");
441 return getObjectParameter(args, kVertexAttrib);
442 }
443
444 enum FunctionToCall {
445 kUniform1v, kUniform2v, kUniform3v, kUniform4v,
446 kVertexAttrib1v, kVertexAttrib2v, kVertexAttrib3v, kVertexAttrib4v
447 };
448
isFunctionToCallForAttribute(FunctionToCall functionToCall)449 bool isFunctionToCallForAttribute(FunctionToCall functionToCall)
450 {
451 switch (functionToCall) {
452 case kVertexAttrib1v:
453 case kVertexAttrib2v:
454 case kVertexAttrib3v:
455 case kVertexAttrib4v:
456 return true;
457 default:
458 break;
459 }
460 return false;
461 }
462
vertexAttribAndUniformHelperf(const v8::Arguments & args,FunctionToCall functionToCall)463 static v8::Handle<v8::Value> vertexAttribAndUniformHelperf(const v8::Arguments& args,
464 FunctionToCall functionToCall) {
465 // Forms:
466 // * glUniform1fv(WebGLUniformLocation location, Array data);
467 // * glUniform1fv(WebGLUniformLocation location, Float32Array data);
468 // * glUniform2fv(WebGLUniformLocation location, Array data);
469 // * glUniform2fv(WebGLUniformLocation location, Float32Array data);
470 // * glUniform3fv(WebGLUniformLocation location, Array data);
471 // * glUniform3fv(WebGLUniformLocation location, Float32Array data);
472 // * glUniform4fv(WebGLUniformLocation location, Array data);
473 // * glUniform4fv(WebGLUniformLocation location, Float32Array data);
474 // * glVertexAttrib1fv(GLint index, Array data);
475 // * glVertexAttrib1fv(GLint index, Float32Array data);
476 // * glVertexAttrib2fv(GLint index, Array data);
477 // * glVertexAttrib2fv(GLint index, Float32Array data);
478 // * glVertexAttrib3fv(GLint index, Array data);
479 // * glVertexAttrib3fv(GLint index, Float32Array data);
480 // * glVertexAttrib4fv(GLint index, Array data);
481 // * glVertexAttrib4fv(GLint index, Float32Array data);
482
483 if (args.Length() != 2) {
484 V8Proxy::setDOMException(SYNTAX_ERR);
485 return notHandledByInterceptor();
486 }
487
488 bool ok = false;
489 int index = -1;
490 WebGLUniformLocation* location = 0;
491
492 if (isFunctionToCallForAttribute(functionToCall))
493 index = toInt32(args[0]);
494 else {
495 if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLUniformLocation::HasInstance(args[0])) {
496 V8Proxy::throwTypeError();
497 return notHandledByInterceptor();
498 }
499 location = toWebGLUniformLocation(args[0], ok);
500 }
501
502 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
503
504 if (V8Float32Array::HasInstance(args[1])) {
505 Float32Array* array = V8Float32Array::toNative(args[1]->ToObject());
506 ASSERT(array != NULL);
507 ExceptionCode ec = 0;
508 switch (functionToCall) {
509 case kUniform1v: context->uniform1fv(location, array, ec); break;
510 case kUniform2v: context->uniform2fv(location, array, ec); break;
511 case kUniform3v: context->uniform3fv(location, array, ec); break;
512 case kUniform4v: context->uniform4fv(location, array, ec); break;
513 case kVertexAttrib1v: context->vertexAttrib1fv(index, array); break;
514 case kVertexAttrib2v: context->vertexAttrib2fv(index, array); break;
515 case kVertexAttrib3v: context->vertexAttrib3fv(index, array); break;
516 case kVertexAttrib4v: context->vertexAttrib4fv(index, array); break;
517 default: ASSERT_NOT_REACHED(); break;
518 }
519 if (ec)
520 V8Proxy::setDOMException(ec);
521 return v8::Undefined();
522 }
523
524 if (args[1].IsEmpty() || !args[1]->IsArray()) {
525 V8Proxy::throwTypeError();
526 return notHandledByInterceptor();
527 }
528 v8::Handle<v8::Array> array =
529 v8::Local<v8::Array>::Cast(args[1]);
530 uint32_t len = array->Length();
531 float* data = jsArrayToFloatArray(array, len);
532 if (!data) {
533 // FIXME: consider different / better exception type.
534 V8Proxy::setDOMException(SYNTAX_ERR);
535 return notHandledByInterceptor();
536 }
537 ExceptionCode ec = 0;
538 switch (functionToCall) {
539 case kUniform1v: context->uniform1fv(location, data, len, ec); break;
540 case kUniform2v: context->uniform2fv(location, data, len, ec); break;
541 case kUniform3v: context->uniform3fv(location, data, len, ec); break;
542 case kUniform4v: context->uniform4fv(location, data, len, ec); break;
543 case kVertexAttrib1v: context->vertexAttrib1fv(index, data, len); break;
544 case kVertexAttrib2v: context->vertexAttrib2fv(index, data, len); break;
545 case kVertexAttrib3v: context->vertexAttrib3fv(index, data, len); break;
546 case kVertexAttrib4v: context->vertexAttrib4fv(index, data, len); break;
547 default: ASSERT_NOT_REACHED(); break;
548 }
549 fastFree(data);
550 if (ec)
551 V8Proxy::setDOMException(ec);
552 return v8::Undefined();
553 }
554
uniformHelperi(const v8::Arguments & args,FunctionToCall functionToCall)555 static v8::Handle<v8::Value> uniformHelperi(const v8::Arguments& args,
556 FunctionToCall functionToCall) {
557 // Forms:
558 // * glUniform1iv(GLUniformLocation location, Array data);
559 // * glUniform1iv(GLUniformLocation location, Int32Array data);
560 // * glUniform2iv(GLUniformLocation location, Array data);
561 // * glUniform2iv(GLUniformLocation location, Int32Array data);
562 // * glUniform3iv(GLUniformLocation location, Array data);
563 // * glUniform3iv(GLUniformLocation location, Int32Array data);
564 // * glUniform4iv(GLUniformLocation location, Array data);
565 // * glUniform4iv(GLUniformLocation location, Int32Array data);
566
567 if (args.Length() != 2) {
568 V8Proxy::setDOMException(SYNTAX_ERR);
569 return notHandledByInterceptor();
570 }
571
572 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
573 if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLUniformLocation::HasInstance(args[0])) {
574 V8Proxy::throwTypeError();
575 return notHandledByInterceptor();
576 }
577 bool ok = false;
578 WebGLUniformLocation* location = toWebGLUniformLocation(args[0], ok);
579
580 if (V8Int32Array::HasInstance(args[1])) {
581 Int32Array* array = V8Int32Array::toNative(args[1]->ToObject());
582 ASSERT(array != NULL);
583 ExceptionCode ec = 0;
584 switch (functionToCall) {
585 case kUniform1v: context->uniform1iv(location, array, ec); break;
586 case kUniform2v: context->uniform2iv(location, array, ec); break;
587 case kUniform3v: context->uniform3iv(location, array, ec); break;
588 case kUniform4v: context->uniform4iv(location, array, ec); break;
589 default: ASSERT_NOT_REACHED(); break;
590 }
591 if (ec)
592 V8Proxy::setDOMException(ec);
593 return v8::Undefined();
594 }
595
596 if (args[1].IsEmpty() || !args[1]->IsArray()) {
597 V8Proxy::throwTypeError();
598 return notHandledByInterceptor();
599 }
600 v8::Handle<v8::Array> array =
601 v8::Local<v8::Array>::Cast(args[1]);
602 uint32_t len = array->Length();
603 int* data = jsArrayToIntArray(array, len);
604 if (!data) {
605 // FIXME: consider different / better exception type.
606 V8Proxy::setDOMException(SYNTAX_ERR);
607 return notHandledByInterceptor();
608 }
609 ExceptionCode ec = 0;
610 switch (functionToCall) {
611 case kUniform1v: context->uniform1iv(location, data, len, ec); break;
612 case kUniform2v: context->uniform2iv(location, data, len, ec); break;
613 case kUniform3v: context->uniform3iv(location, data, len, ec); break;
614 case kUniform4v: context->uniform4iv(location, data, len, ec); break;
615 default: ASSERT_NOT_REACHED(); break;
616 }
617 fastFree(data);
618 if (ec)
619 V8Proxy::setDOMException(ec);
620 return v8::Undefined();
621 }
622
uniform1fvCallback(const v8::Arguments & args)623 v8::Handle<v8::Value> V8WebGLRenderingContext::uniform1fvCallback(const v8::Arguments& args)
624 {
625 INC_STATS("DOM.WebGLRenderingContext.uniform1fv()");
626 return vertexAttribAndUniformHelperf(args, kUniform1v);
627 }
628
uniform1ivCallback(const v8::Arguments & args)629 v8::Handle<v8::Value> V8WebGLRenderingContext::uniform1ivCallback(const v8::Arguments& args)
630 {
631 INC_STATS("DOM.WebGLRenderingContext.uniform1iv()");
632 return uniformHelperi(args, kUniform1v);
633 }
634
uniform2fvCallback(const v8::Arguments & args)635 v8::Handle<v8::Value> V8WebGLRenderingContext::uniform2fvCallback(const v8::Arguments& args)
636 {
637 INC_STATS("DOM.WebGLRenderingContext.uniform2fv()");
638 return vertexAttribAndUniformHelperf(args, kUniform2v);
639 }
640
uniform2ivCallback(const v8::Arguments & args)641 v8::Handle<v8::Value> V8WebGLRenderingContext::uniform2ivCallback(const v8::Arguments& args)
642 {
643 INC_STATS("DOM.WebGLRenderingContext.uniform2iv()");
644 return uniformHelperi(args, kUniform2v);
645 }
646
uniform3fvCallback(const v8::Arguments & args)647 v8::Handle<v8::Value> V8WebGLRenderingContext::uniform3fvCallback(const v8::Arguments& args)
648 {
649 INC_STATS("DOM.WebGLRenderingContext.uniform3fv()");
650 return vertexAttribAndUniformHelperf(args, kUniform3v);
651 }
652
uniform3ivCallback(const v8::Arguments & args)653 v8::Handle<v8::Value> V8WebGLRenderingContext::uniform3ivCallback(const v8::Arguments& args)
654 {
655 INC_STATS("DOM.WebGLRenderingContext.uniform3iv()");
656 return uniformHelperi(args, kUniform3v);
657 }
658
uniform4fvCallback(const v8::Arguments & args)659 v8::Handle<v8::Value> V8WebGLRenderingContext::uniform4fvCallback(const v8::Arguments& args)
660 {
661 INC_STATS("DOM.WebGLRenderingContext.uniform4fv()");
662 return vertexAttribAndUniformHelperf(args, kUniform4v);
663 }
664
uniform4ivCallback(const v8::Arguments & args)665 v8::Handle<v8::Value> V8WebGLRenderingContext::uniform4ivCallback(const v8::Arguments& args)
666 {
667 INC_STATS("DOM.WebGLRenderingContext.uniform4iv()");
668 return uniformHelperi(args, kUniform4v);
669 }
670
uniformMatrixHelper(const v8::Arguments & args,int matrixSize)671 static v8::Handle<v8::Value> uniformMatrixHelper(const v8::Arguments& args,
672 int matrixSize)
673 {
674 // Forms:
675 // * glUniformMatrix2fv(GLint location, GLboolean transpose, Array data);
676 // * glUniformMatrix2fv(GLint location, GLboolean transpose, Float32Array data);
677 // * glUniformMatrix3fv(GLint location, GLboolean transpose, Array data);
678 // * glUniformMatrix3fv(GLint location, GLboolean transpose, Float32Array data);
679 // * glUniformMatrix4fv(GLint location, GLboolean transpose, Array data);
680 // * glUniformMatrix4fv(GLint location, GLboolean transpose, Float32Array data);
681 //
682 // FIXME: need to change to accept Float32Array as well.
683 if (args.Length() != 3) {
684 V8Proxy::setDOMException(SYNTAX_ERR);
685 return notHandledByInterceptor();
686 }
687
688 WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
689
690 if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLUniformLocation::HasInstance(args[0])) {
691 V8Proxy::throwTypeError();
692 return notHandledByInterceptor();
693 }
694 bool ok = false;
695 WebGLUniformLocation* location = toWebGLUniformLocation(args[0], ok);
696
697 bool transpose = args[1]->BooleanValue();
698 if (V8Float32Array::HasInstance(args[2])) {
699 Float32Array* array = V8Float32Array::toNative(args[2]->ToObject());
700 ASSERT(array != NULL);
701 ExceptionCode ec = 0;
702 switch (matrixSize) {
703 case 2: context->uniformMatrix2fv(location, transpose, array, ec); break;
704 case 3: context->uniformMatrix3fv(location, transpose, array, ec); break;
705 case 4: context->uniformMatrix4fv(location, transpose, array, ec); break;
706 default: ASSERT_NOT_REACHED(); break;
707 }
708 if (ec)
709 V8Proxy::setDOMException(ec);
710 return v8::Undefined();
711 }
712
713 if (args[2].IsEmpty() || !args[2]->IsArray()) {
714 V8Proxy::throwTypeError();
715 return notHandledByInterceptor();
716 }
717 v8::Handle<v8::Array> array =
718 v8::Local<v8::Array>::Cast(args[2]);
719 uint32_t len = array->Length();
720 float* data = jsArrayToFloatArray(array, len);
721 if (!data) {
722 // FIXME: consider different / better exception type.
723 V8Proxy::setDOMException(SYNTAX_ERR);
724 return notHandledByInterceptor();
725 }
726 ExceptionCode ec = 0;
727 switch (matrixSize) {
728 case 2: context->uniformMatrix2fv(location, transpose, data, len, ec); break;
729 case 3: context->uniformMatrix3fv(location, transpose, data, len, ec); break;
730 case 4: context->uniformMatrix4fv(location, transpose, data, len, ec); break;
731 default: ASSERT_NOT_REACHED(); break;
732 }
733 fastFree(data);
734 if (ec)
735 V8Proxy::setDOMException(ec);
736 return v8::Undefined();
737 }
738
uniformMatrix2fvCallback(const v8::Arguments & args)739 v8::Handle<v8::Value> V8WebGLRenderingContext::uniformMatrix2fvCallback(const v8::Arguments& args)
740 {
741 INC_STATS("DOM.WebGLRenderingContext.uniformMatrix2fv()");
742 return uniformMatrixHelper(args, 2);
743 }
744
uniformMatrix3fvCallback(const v8::Arguments & args)745 v8::Handle<v8::Value> V8WebGLRenderingContext::uniformMatrix3fvCallback(const v8::Arguments& args)
746 {
747 INC_STATS("DOM.WebGLRenderingContext.uniformMatrix3fv()");
748 return uniformMatrixHelper(args, 3);
749 }
750
uniformMatrix4fvCallback(const v8::Arguments & args)751 v8::Handle<v8::Value> V8WebGLRenderingContext::uniformMatrix4fvCallback(const v8::Arguments& args)
752 {
753 INC_STATS("DOM.WebGLRenderingContext.uniformMatrix4fv()");
754 return uniformMatrixHelper(args, 4);
755 }
756
vertexAttrib1fvCallback(const v8::Arguments & args)757 v8::Handle<v8::Value> V8WebGLRenderingContext::vertexAttrib1fvCallback(const v8::Arguments& args)
758 {
759 INC_STATS("DOM.WebGLRenderingContext.vertexAttrib1fv()");
760 return vertexAttribAndUniformHelperf(args, kVertexAttrib1v);
761 }
762
vertexAttrib2fvCallback(const v8::Arguments & args)763 v8::Handle<v8::Value> V8WebGLRenderingContext::vertexAttrib2fvCallback(const v8::Arguments& args)
764 {
765 INC_STATS("DOM.WebGLRenderingContext.vertexAttrib2fv()");
766 return vertexAttribAndUniformHelperf(args, kVertexAttrib2v);
767 }
768
vertexAttrib3fvCallback(const v8::Arguments & args)769 v8::Handle<v8::Value> V8WebGLRenderingContext::vertexAttrib3fvCallback(const v8::Arguments& args)
770 {
771 INC_STATS("DOM.WebGLRenderingContext.vertexAttrib3fv()");
772 return vertexAttribAndUniformHelperf(args, kVertexAttrib3v);
773 }
774
vertexAttrib4fvCallback(const v8::Arguments & args)775 v8::Handle<v8::Value> V8WebGLRenderingContext::vertexAttrib4fvCallback(const v8::Arguments& args)
776 {
777 INC_STATS("DOM.WebGLRenderingContext.vertexAttrib4fv()");
778 return vertexAttribAndUniformHelperf(args, kVertexAttrib4v);
779 }
780
781 } // namespace WebCore
782
783 #endif // ENABLE(WEBGL)
784