• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 Apple 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
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "config.h"
27 
28 #if ENABLE(3D_CANVAS)
29 
30 #include "JSWebGLRenderingContext.h"
31 
32 #include "ExceptionCode.h"
33 #include "HTMLCanvasElement.h"
34 #include "HTMLImageElement.h"
35 #include "HTMLVideoElement.h"
36 #include "JSHTMLCanvasElement.h"
37 #include "JSHTMLImageElement.h"
38 #include "JSHTMLVideoElement.h"
39 #include "JSImageData.h"
40 #include "JSWebGLBuffer.h"
41 #include "JSWebGLFloatArray.h"
42 #include "JSWebGLFramebuffer.h"
43 #include "JSWebGLIntArray.h"
44 #include "JSWebGLProgram.h"
45 #include "JSWebGLRenderbuffer.h"
46 #include "JSWebGLShader.h"
47 #include "JSWebGLTexture.h"
48 #include "JSWebGLUniformLocation.h"
49 #include "JSWebGLUnsignedByteArray.h"
50 #include "JSWebKitCSSMatrix.h"
51 #include "NotImplemented.h"
52 #include "WebGLBuffer.h"
53 #include "WebGLFloatArray.h"
54 #include "WebGLFramebuffer.h"
55 #include "WebGLGetInfo.h"
56 #include "WebGLIntArray.h"
57 #include "WebGLProgram.h"
58 #include "WebGLRenderingContext.h"
59 #include <runtime/Error.h>
60 #include <wtf/FastMalloc.h>
61 #include <wtf/OwnFastMallocPtr.h>
62 
63 using namespace JSC;
64 
65 namespace WebCore {
66 
bufferData(JSC::ExecState * exec,JSC::ArgList const & args)67 JSValue JSWebGLRenderingContext::bufferData(JSC::ExecState* exec, JSC::ArgList const& args)
68 {
69     if (args.size() != 3)
70         return throwError(exec, SyntaxError);
71 
72     unsigned target = args.at(0).toInt32(exec);
73     unsigned usage = args.at(2).toInt32(exec);
74     ExceptionCode ec = 0;
75 
76     // If argument 1 is a number, we are initializing this buffer to that size
77     if (!args.at(1).isObject()) {
78         unsigned int count = args.at(1).toInt32(exec);
79         static_cast<WebGLRenderingContext*>(impl())->bufferData(target, count, usage, ec);
80     } else {
81         WebGLArray* array = toWebGLArray(args.at(1));
82         static_cast<WebGLRenderingContext*>(impl())->bufferData(target, array, usage, ec);
83     }
84 
85     setDOMException(exec, ec);
86     return jsUndefined();
87 }
88 
bufferSubData(JSC::ExecState * exec,JSC::ArgList const & args)89 JSValue JSWebGLRenderingContext::bufferSubData(JSC::ExecState* exec, JSC::ArgList const& args)
90 {
91     if (args.size() != 3)
92         return throwError(exec, SyntaxError);
93 
94     unsigned target = args.at(0).toInt32(exec);
95     unsigned offset = args.at(1).toInt32(exec);
96     ExceptionCode ec = 0;
97 
98     WebGLArray* array = toWebGLArray(args.at(2));
99 
100     static_cast<WebGLRenderingContext*>(impl())->bufferSubData(target, offset, array, ec);
101 
102     setDOMException(exec, ec);
103     return jsUndefined();
104 }
105 
toJS(ExecState * exec,JSDOMGlobalObject * globalObject,const WebGLGetInfo & info)106 static JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, const WebGLGetInfo& info)
107 {
108     switch (info.getType()) {
109     case WebGLGetInfo::kTypeBool:
110         return jsBoolean(info.getBool());
111     case WebGLGetInfo::kTypeFloat:
112         return jsNumber(exec, info.getFloat());
113     case WebGLGetInfo::kTypeLong:
114         return jsNumber(exec, info.getLong());
115     case WebGLGetInfo::kTypeNull:
116         return jsNull();
117     case WebGLGetInfo::kTypeString:
118         return jsString(exec, info.getString());
119     case WebGLGetInfo::kTypeUnsignedLong:
120         return jsNumber(exec, info.getUnsignedLong());
121     case WebGLGetInfo::kTypeWebGLBuffer:
122         return toJS(exec, globalObject, info.getWebGLBuffer());
123     case WebGLGetInfo::kTypeWebGLFloatArray:
124         return toJS(exec, globalObject, info.getWebGLFloatArray());
125     case WebGLGetInfo::kTypeWebGLFramebuffer:
126         return toJS(exec, globalObject, info.getWebGLFramebuffer());
127     case WebGLGetInfo::kTypeWebGLIntArray:
128         return toJS(exec, globalObject, info.getWebGLIntArray());
129     // FIXME: implement WebGLObjectArray
130     // case WebGLGetInfo::kTypeWebGLObjectArray:
131     case WebGLGetInfo::kTypeWebGLProgram:
132         return toJS(exec, globalObject, info.getWebGLProgram());
133     case WebGLGetInfo::kTypeWebGLRenderbuffer:
134         return toJS(exec, globalObject, info.getWebGLRenderbuffer());
135     case WebGLGetInfo::kTypeWebGLTexture:
136         return toJS(exec, globalObject, info.getWebGLTexture());
137     case WebGLGetInfo::kTypeWebGLUnsignedByteArray:
138         return toJS(exec, globalObject, info.getWebGLUnsignedByteArray());
139     default:
140         notImplemented();
141         return jsUndefined();
142     }
143 }
144 
145 enum ObjectType {
146     kBuffer, kRenderbuffer, kTexture, kVertexAttrib
147 };
148 
getObjectParameter(JSWebGLRenderingContext * obj,ExecState * exec,const ArgList & args,ObjectType objectType)149 static JSValue getObjectParameter(JSWebGLRenderingContext* obj, ExecState* exec, const ArgList& args, ObjectType objectType)
150 {
151     if (args.size() != 2)
152         return throwError(exec, SyntaxError);
153 
154     ExceptionCode ec = 0;
155     WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(obj->impl());
156     unsigned target = args.at(0).toInt32(exec);
157     if (exec->hadException())
158         return jsUndefined();
159     unsigned pname = args.at(1).toInt32(exec);
160     if (exec->hadException())
161         return jsUndefined();
162     WebGLGetInfo info;
163     switch (objectType) {
164     case kBuffer:
165         info = context->getBufferParameter(target, pname, ec);
166         break;
167     case kRenderbuffer:
168         info = context->getRenderbufferParameter(target, pname, ec);
169         break;
170     case kTexture:
171         info = context->getTexParameter(target, pname, ec);
172         break;
173     case kVertexAttrib:
174         // target => index
175         info = context->getVertexAttrib(target, pname, ec);
176         break;
177     default:
178         notImplemented();
179         break;
180     }
181     if (ec) {
182         setDOMException(exec, ec);
183         return jsUndefined();
184     }
185     return toJS(exec, obj->globalObject(), info);
186 }
187 
188 enum WhichProgramCall {
189     kProgramParameter, kUniform
190 };
191 
getBufferParameter(ExecState * exec,const ArgList & args)192 JSValue JSWebGLRenderingContext::getBufferParameter(ExecState* exec, const ArgList& args)
193 {
194     return getObjectParameter(this, exec, args, kBuffer);
195 }
196 
getFramebufferAttachmentParameter(ExecState * exec,const ArgList & args)197 JSValue JSWebGLRenderingContext::getFramebufferAttachmentParameter(ExecState* exec, const ArgList& args)
198 {
199     if (args.size() != 3)
200         return throwError(exec, SyntaxError);
201 
202     ExceptionCode ec = 0;
203     WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl());
204     unsigned target = args.at(0).toInt32(exec);
205     if (exec->hadException())
206         return jsUndefined();
207     unsigned attachment = args.at(1).toInt32(exec);
208     if (exec->hadException())
209         return jsUndefined();
210     unsigned pname = args.at(2).toInt32(exec);
211     if (exec->hadException())
212         return jsUndefined();
213     WebGLGetInfo info = context->getFramebufferAttachmentParameter(target, attachment, pname, ec);
214     if (ec) {
215         setDOMException(exec, ec);
216         return jsUndefined();
217     }
218     return toJS(exec, globalObject(), info);
219 }
220 
getParameter(ExecState * exec,const ArgList & args)221 JSValue JSWebGLRenderingContext::getParameter(ExecState* exec, const ArgList& args)
222 {
223     if (args.size() != 1)
224         return throwError(exec, SyntaxError);
225 
226     ExceptionCode ec = 0;
227     WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl());
228     unsigned pname = args.at(0).toInt32(exec);
229     if (exec->hadException())
230         return jsUndefined();
231     WebGLGetInfo info = context->getParameter(pname, ec);
232     if (ec) {
233         setDOMException(exec, ec);
234         return jsUndefined();
235     }
236     return toJS(exec, globalObject(), info);
237 }
238 
getProgramParameter(ExecState * exec,const ArgList & args)239 JSValue JSWebGLRenderingContext::getProgramParameter(ExecState* exec, const ArgList& args)
240 {
241     if (args.size() != 2)
242         return throwError(exec, SyntaxError);
243 
244     ExceptionCode ec = 0;
245     WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl());
246     WebGLProgram* program = toWebGLProgram(args.at(0));
247     unsigned pname = args.at(1).toInt32(exec);
248     if (exec->hadException())
249         return jsUndefined();
250     WebGLGetInfo info = context->getProgramParameter(program, pname, ec);
251     if (ec) {
252         setDOMException(exec, ec);
253         return jsUndefined();
254     }
255     return toJS(exec, globalObject(), info);
256 }
257 
getRenderbufferParameter(ExecState * exec,const ArgList & args)258 JSValue JSWebGLRenderingContext::getRenderbufferParameter(ExecState* exec, const ArgList& args)
259 {
260     return getObjectParameter(this, exec, args, kRenderbuffer);
261 }
262 
getShaderParameter(ExecState * exec,const ArgList & args)263 JSValue JSWebGLRenderingContext::getShaderParameter(ExecState* exec, const ArgList& args)
264 {
265     if (args.size() != 2)
266         return throwError(exec, SyntaxError);
267 
268     ExceptionCode ec = 0;
269     WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl());
270     WebGLShader* shader = toWebGLShader(args.at(0));
271     unsigned pname = args.at(1).toInt32(exec);
272     if (exec->hadException())
273         return jsUndefined();
274     WebGLGetInfo info = context->getShaderParameter(shader, pname, ec);
275     if (ec) {
276         setDOMException(exec, ec);
277         return jsUndefined();
278     }
279     return toJS(exec, globalObject(), info);
280 }
281 
getTexParameter(ExecState * exec,const ArgList & args)282 JSValue JSWebGLRenderingContext::getTexParameter(ExecState* exec, const ArgList& args)
283 {
284     return getObjectParameter(this, exec, args, kTexture);
285 }
286 
getUniform(ExecState * exec,const ArgList & args)287 JSValue JSWebGLRenderingContext::getUniform(ExecState* exec, const ArgList& args)
288 {
289     if (args.size() != 2)
290         return throwError(exec, SyntaxError);
291 
292     ExceptionCode ec = 0;
293     WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl());
294     WebGLProgram* program = toWebGLProgram(args.at(0));
295     WebGLUniformLocation* loc = toWebGLUniformLocation(args.at(1));
296     if (exec->hadException())
297         return jsUndefined();
298     WebGLGetInfo info = context->getUniform(program, loc, ec);
299     if (ec) {
300         setDOMException(exec, ec);
301         return jsUndefined();
302     }
303     return toJS(exec, globalObject(), info);
304 }
305 
getVertexAttrib(ExecState * exec,const ArgList & args)306 JSValue JSWebGLRenderingContext::getVertexAttrib(ExecState* exec, const ArgList& args)
307 {
308     return getObjectParameter(this, exec, args, kVertexAttrib);
309 }
310 
311 //   void texImage2D(in GLenum target, in GLint level, in GLenum internalformat, in GLsizei width, in GLsizei height, in GLint border, in GLenum format, in GLenum type, in WebGLArray pixels);
312 //   void texImage2D(in GLenum target, in GLint level, in ImageData pixels, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha);
313 //   void texImage2D(in GLenum target, in GLint level, in HTMLImageElement image, [Optional] in GLboolean flipY, [Optional] in premultiplyAlpha);
314 //   void texImage2D(in GLenum target, in GLint level, in HTMLCanvasElement canvas, [Optional] in GLboolean flipY, [Optional] in premultiplyAlpha);
315 //   void texImage2D(in GLenum target, in GLint level, in HTMLVideoElement video, [Optional] in GLboolean flipY, [Optional] in premultiplyAlpha);
texImage2D(ExecState * exec,const ArgList & args)316 JSValue JSWebGLRenderingContext::texImage2D(ExecState* exec, const ArgList& args)
317 {
318     if (args.size() < 3 || args.size() > 9)
319         return throwError(exec, SyntaxError);
320 
321     ExceptionCode ec = 0;
322 
323     WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl());
324     unsigned target = args.at(0).toInt32(exec);
325     if (exec->hadException())
326         return jsUndefined();
327 
328     unsigned level = args.at(1).toInt32(exec);
329     if (exec->hadException())
330         return jsUndefined();
331 
332     JSObject* o = 0;
333 
334     if (args.size() <= 5) {
335         // This is one of the last 4 forms. Param 2 can be ImageData or <img>, <canvas> or <video> element.
336         JSValue value = args.at(2);
337 
338         if (!value.isObject())
339             return throwError(exec, TypeError);
340 
341         o = asObject(value);
342 
343         bool flipY = args.at(3).toBoolean(exec);
344         bool premultiplyAlpha = args.at(4).toBoolean(exec);
345 
346         if (o->inherits(&JSImageData::s_info)) {
347             ImageData* data = static_cast<ImageData*>(static_cast<JSImageData*>(o)->impl());
348             context->texImage2D(target, level, data, flipY, premultiplyAlpha, ec);
349         } else if (o->inherits(&JSHTMLImageElement::s_info)) {
350             HTMLImageElement* element = static_cast<HTMLImageElement*>(static_cast<JSHTMLImageElement*>(o)->impl());
351             context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec);
352         } else if (o->inherits(&JSHTMLCanvasElement::s_info)) {
353             HTMLCanvasElement* element = static_cast<HTMLCanvasElement*>(static_cast<JSHTMLCanvasElement*>(o)->impl());
354             context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec);
355         } else if (o->inherits(&JSHTMLVideoElement::s_info)) {
356             HTMLVideoElement* element = static_cast<HTMLVideoElement*>(static_cast<JSHTMLVideoElement*>(o)->impl());
357             context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec);
358         } else
359             ec = TYPE_MISMATCH_ERR;
360     } else {
361         if (args.size() != 9)
362             return throwError(exec, SyntaxError);
363 
364         // This must be the WebGLArray case
365         unsigned internalformat = args.at(2).toInt32(exec);
366         if (exec->hadException())
367             return jsUndefined();
368 
369         unsigned width = args.at(3).toInt32(exec);
370         if (exec->hadException())
371             return jsUndefined();
372 
373         unsigned height = args.at(4).toInt32(exec);
374         if (exec->hadException())
375             return jsUndefined();
376 
377         unsigned border = args.at(5).toInt32(exec);
378         if (exec->hadException())
379             return jsUndefined();
380 
381         unsigned format = args.at(6).toInt32(exec);
382         if (exec->hadException())
383             return jsUndefined();
384 
385         unsigned type = args.at(7).toInt32(exec);
386         if (exec->hadException())
387             return jsUndefined();
388 
389         JSValue value = args.at(8);
390 
391         // For this case passing 0 (for a null array) is allowed
392         if (value.isNull())
393             context->texImage2D(target, level, internalformat, width, height, border, format, type, 0, ec);
394         else if (value.isObject()) {
395             o = asObject(value);
396 
397             if (o->inherits(&JSWebGLArray::s_info)) {
398                 // FIXME: Need to check to make sure WebGLArray is a WebGLByteArray or WebGLShortArray,
399                 // depending on the passed type parameter.
400                 WebGLArray* obj = static_cast<WebGLArray*>(static_cast<JSWebGLArray*>(o)->impl());
401                 context->texImage2D(target, level, internalformat, width, height, border, format, type, obj, ec);
402             } else
403                 return throwError(exec, TypeError);
404         } else
405             return throwError(exec, TypeError);
406     }
407 
408     setDOMException(exec, ec);
409     return jsUndefined();
410 }
411 
412 //   void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in GLsizei width, in GLsizei height, in GLenum format, in GLenum type, in WebGLArray pixels);
413 //   void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in ImageData pixels, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha);
414 //   void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in HTMLImageElement image, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha);
415 //   void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in HTMLCanvasElement canvas, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha);
416 //   void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in HTMLVideoElement video, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha);
texSubImage2D(ExecState * exec,const ArgList & args)417 JSValue JSWebGLRenderingContext::texSubImage2D(ExecState* exec, const ArgList& args)
418 {
419     if (args.size() < 5 || args.size() > 9)
420         return throwError(exec, SyntaxError);
421 
422     ExceptionCode ec = 0;
423 
424     WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl());
425     unsigned target = args.at(0).toInt32(exec);
426     if (exec->hadException())
427         return jsUndefined();
428 
429     unsigned level = args.at(1).toInt32(exec);
430     if (exec->hadException())
431         return jsUndefined();
432 
433     unsigned xoff = args.at(2).toInt32(exec);
434     if (exec->hadException())
435         return jsUndefined();
436 
437     unsigned yoff = args.at(3).toInt32(exec);
438     if (exec->hadException())
439         return jsUndefined();
440 
441     JSObject* o = 0;
442 
443     if (args.size() <= 7) {
444         // This is one of the last 4 forms. Param 4 can be <img>, <canvas> or <video> element, of the format param.
445         JSValue value = args.at(4);
446 
447         if (!value.isObject())
448             return throwError(exec, SyntaxError);
449 
450         o = asObject(value);
451 
452         bool flipY = args.at(5).toBoolean(exec);
453         bool premultiplyAlpha = args.at(6).toBoolean(exec);
454 
455         if (o->inherits(&JSImageData::s_info)) {
456             ImageData* data = static_cast<ImageData*>(static_cast<JSImageData*>(o)->impl());
457             context->texSubImage2D(target, level, xoff, yoff, data, flipY, premultiplyAlpha, ec);
458         } else if (o->inherits(&JSHTMLImageElement::s_info)) {
459             HTMLImageElement* element = static_cast<HTMLImageElement*>(static_cast<JSHTMLImageElement*>(o)->impl());
460             context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec);
461         } else if (o->inherits(&JSHTMLCanvasElement::s_info)) {
462             HTMLCanvasElement* element = static_cast<HTMLCanvasElement*>(static_cast<JSHTMLCanvasElement*>(o)->impl());
463             context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec);
464         } else if (o->inherits(&JSHTMLVideoElement::s_info)) {
465             HTMLVideoElement* element = static_cast<HTMLVideoElement*>(static_cast<JSHTMLVideoElement*>(o)->impl());
466             context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec);
467         } else
468             ec = TYPE_MISMATCH_ERR;
469     } else {
470         // This must be the WebGLArray form
471         if (args.size() != 9)
472             return throwError(exec, SyntaxError);
473 
474         unsigned width = args.at(4).toInt32(exec);
475         if (exec->hadException())
476             return jsUndefined();
477 
478         unsigned height = args.at(5).toInt32(exec);
479         if (exec->hadException())
480             return jsUndefined();
481 
482         unsigned format = args.at(6).toInt32(exec);
483         if (exec->hadException())
484             return jsUndefined();
485 
486         unsigned type = args.at(7).toInt32(exec);
487         if (exec->hadException())
488             return jsUndefined();
489 
490         JSValue value = args.at(8);
491         if (!value.isObject())
492             context->texSubImage2D(target, level, xoff, yoff, width, height, format, type, 0, ec);
493         else {
494             o = asObject(value);
495 
496             if (o->inherits(&JSWebGLArray::s_info)) {
497                 WebGLArray* obj = static_cast<WebGLArray*>(static_cast<JSWebGLArray*>(o)->impl());
498                 context->texSubImage2D(target, level, xoff, yoff, width, height, format, type, obj, ec);
499             } else
500                 return throwError(exec, TypeError);
501         }
502     }
503 
504     setDOMException(exec, ec);
505     return jsUndefined();
506 }
507 
508 template<typename T, size_t inlineCapacity>
toVector(JSC::ExecState * exec,JSC::JSValue value,Vector<T,inlineCapacity> & vector)509 bool toVector(JSC::ExecState* exec, JSC::JSValue value, Vector<T, inlineCapacity>& vector)
510 {
511     if (!value.isObject())
512         return false;
513 
514     JSC::JSObject* object = asObject(value);
515     int32_t length = object->get(exec, JSC::Identifier(exec, "length")).toInt32(exec);
516     vector.resize(length);
517 
518     for (int32_t i = 0; i < length; ++i) {
519         JSC::JSValue v = object->get(exec, i);
520         if (exec->hadException())
521             return false;
522         vector[i] = static_cast<T>(v.toNumber(exec));
523     }
524 
525     return true;
526 }
527 
528 enum DataFunctionToCall {
529     f_uniform1v, f_uniform2v, f_uniform3v, f_uniform4v,
530     f_vertexAttrib1v, f_vertexAttrib2v, f_vertexAttrib3v, f_vertexAttrib4v
531 };
532 
533 enum DataFunctionMatrixToCall {
534     f_uniformMatrix2fv, f_uniformMatrix3fv, f_uniformMatrix4fv
535 };
536 
functionForUniform(DataFunctionToCall f)537 static bool functionForUniform(DataFunctionToCall f)
538 {
539     switch (f) {
540     case f_uniform1v:
541     case f_uniform2v:
542     case f_uniform3v:
543     case f_uniform4v:
544         return true;
545         break;
546     default: break;
547     }
548     return false;
549 }
550 
dataFunctionf(DataFunctionToCall f,JSC::ExecState * exec,const JSC::ArgList & args,WebGLRenderingContext * context)551 static JSC::JSValue dataFunctionf(DataFunctionToCall f, JSC::ExecState* exec, const JSC::ArgList& args, WebGLRenderingContext* context)
552 {
553     if (args.size() != 2)
554         return throwError(exec, SyntaxError);
555 
556     WebGLUniformLocation* location = 0;
557     long index = -1;
558 
559     if (functionForUniform(f))
560         location = toWebGLUniformLocation(args.at(0));
561     else
562         index = args.at(0).toInt32(exec);
563 
564     if (exec->hadException())
565         return jsUndefined();
566 
567     RefPtr<WebGLFloatArray> webGLArray = toWebGLFloatArray(args.at(1));
568     if (exec->hadException())
569         return jsUndefined();
570 
571     ExceptionCode ec = 0;
572     if (webGLArray) {
573         switch (f) {
574         case f_uniform1v:
575             context->uniform1fv(location, webGLArray.get(), ec);
576             break;
577         case f_uniform2v:
578             context->uniform2fv(location, webGLArray.get(), ec);
579             break;
580         case f_uniform3v:
581             context->uniform3fv(location, webGLArray.get(), ec);
582             break;
583         case f_uniform4v:
584             context->uniform4fv(location, webGLArray.get(), ec);
585             break;
586         case f_vertexAttrib1v:
587             context->vertexAttrib1fv(index, webGLArray.get());
588             break;
589         case f_vertexAttrib2v:
590             context->vertexAttrib2fv(index, webGLArray.get());
591             break;
592         case f_vertexAttrib3v:
593             context->vertexAttrib3fv(index, webGLArray.get());
594             break;
595         case f_vertexAttrib4v:
596             context->vertexAttrib4fv(index, webGLArray.get());
597             break;
598         }
599 
600         setDOMException(exec, ec);
601         return jsUndefined();
602     }
603 
604     Vector<float, 64> array;
605     if (!toVector(exec, args.at(1), array))
606         return throwError(exec, TypeError);
607 
608     switch (f) {
609     case f_uniform1v:
610         context->uniform1fv(location, array.data(), array.size(), ec);
611         break;
612     case f_uniform2v:
613         context->uniform2fv(location, array.data(), array.size(), ec);
614         break;
615     case f_uniform3v:
616         context->uniform3fv(location, array.data(), array.size(), ec);
617         break;
618     case f_uniform4v:
619         context->uniform4fv(location, array.data(), array.size(), ec);
620         break;
621     case f_vertexAttrib1v:
622         context->vertexAttrib1fv(index, array.data(), array.size());
623         break;
624     case f_vertexAttrib2v:
625         context->vertexAttrib2fv(index, array.data(), array.size());
626         break;
627     case f_vertexAttrib3v:
628         context->vertexAttrib3fv(index, array.data(), array.size());
629         break;
630     case f_vertexAttrib4v:
631         context->vertexAttrib4fv(index, array.data(), array.size());
632         break;
633     }
634 
635     setDOMException(exec, ec);
636     return jsUndefined();
637 }
638 
dataFunctioni(DataFunctionToCall f,JSC::ExecState * exec,const JSC::ArgList & args,WebGLRenderingContext * context)639 static JSC::JSValue dataFunctioni(DataFunctionToCall f, JSC::ExecState* exec, const JSC::ArgList& args, WebGLRenderingContext* context)
640 {
641     if (args.size() != 2)
642         return throwError(exec, SyntaxError);
643 
644     WebGLUniformLocation* location = toWebGLUniformLocation(args.at(0));
645 
646     if (exec->hadException())
647         return jsUndefined();
648 
649     RefPtr<WebGLIntArray> webGLArray = toWebGLIntArray(args.at(1));
650     if (exec->hadException())
651         return jsUndefined();
652 
653     ExceptionCode ec = 0;
654     if (webGLArray) {
655         switch (f) {
656         case f_uniform1v:
657             context->uniform1iv(location, webGLArray.get(), ec);
658             break;
659         case f_uniform2v:
660             context->uniform2iv(location, webGLArray.get(), ec);
661             break;
662         case f_uniform3v:
663             context->uniform3iv(location, webGLArray.get(), ec);
664             break;
665         case f_uniform4v:
666             context->uniform4iv(location, webGLArray.get(), ec);
667             break;
668         default:
669             break;
670         }
671 
672         setDOMException(exec, ec);
673         return jsUndefined();
674     }
675 
676 
677     Vector<int, 64> array;
678     if (!toVector(exec, args.at(1), array))
679         return throwError(exec, TypeError);
680 
681     switch (f) {
682     case f_uniform1v:
683         context->uniform1iv(location, array.data(), array.size(), ec);
684         break;
685     case f_uniform2v:
686         context->uniform2iv(location, array.data(), array.size(), ec);
687         break;
688     case f_uniform3v:
689         context->uniform3iv(location, array.data(), array.size(), ec);
690         break;
691     case f_uniform4v:
692         context->uniform4iv(location, array.data(), array.size(), ec);
693         break;
694     default:
695         break;
696     }
697 
698     setDOMException(exec, ec);
699     return jsUndefined();
700 }
701 
dataFunctionMatrix(DataFunctionMatrixToCall f,JSC::ExecState * exec,const JSC::ArgList & args,WebGLRenderingContext * context)702 static JSC::JSValue dataFunctionMatrix(DataFunctionMatrixToCall f, JSC::ExecState* exec, const JSC::ArgList& args, WebGLRenderingContext* context)
703 {
704     if (args.size() != 3)
705         return throwError(exec, SyntaxError);
706 
707     WebGLUniformLocation* location = toWebGLUniformLocation(args.at(0));
708 
709     if (exec->hadException())
710         return jsUndefined();
711 
712     bool transpose = args.at(1).toBoolean(exec);
713     if (exec->hadException())
714         return jsUndefined();
715 
716     RefPtr<WebGLFloatArray> webGLArray = toWebGLFloatArray(args.at(2));
717     if (exec->hadException())
718         return jsUndefined();
719 
720     ExceptionCode ec = 0;
721     if (webGLArray) {
722         switch (f) {
723         case f_uniformMatrix2fv:
724             context->uniformMatrix2fv(location, transpose, webGLArray.get(), ec);
725             break;
726         case f_uniformMatrix3fv:
727             context->uniformMatrix3fv(location, transpose, webGLArray.get(), ec);
728             break;
729         case f_uniformMatrix4fv:
730             context->uniformMatrix4fv(location, transpose, webGLArray.get(), ec);
731             break;
732         }
733 
734         setDOMException(exec, ec);
735         return jsUndefined();
736     }
737 
738     Vector<float, 64> array;
739     if (!toVector(exec, args.at(2), array))
740         return throwError(exec, TypeError);
741 
742     switch (f) {
743     case f_uniformMatrix2fv:
744         context->uniformMatrix2fv(location, transpose, array.data(), array.size(), ec);
745         break;
746     case f_uniformMatrix3fv:
747         context->uniformMatrix3fv(location, transpose, array.data(), array.size(), ec);
748         break;
749     case f_uniformMatrix4fv:
750         context->uniformMatrix4fv(location, transpose, array.data(), array.size(), ec);
751         break;
752     }
753 
754     setDOMException(exec, ec);
755     return jsUndefined();
756 }
757 
uniform1fv(JSC::ExecState * exec,const JSC::ArgList & args)758 JSC::JSValue JSWebGLRenderingContext::uniform1fv(JSC::ExecState* exec, const JSC::ArgList& args)
759 {
760     return dataFunctionf(f_uniform1v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
761 }
762 
uniform1iv(JSC::ExecState * exec,const JSC::ArgList & args)763 JSC::JSValue JSWebGLRenderingContext::uniform1iv(JSC::ExecState* exec, const JSC::ArgList& args)
764 {
765     return dataFunctioni(f_uniform1v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
766 }
767 
uniform2fv(JSC::ExecState * exec,const JSC::ArgList & args)768 JSC::JSValue JSWebGLRenderingContext::uniform2fv(JSC::ExecState* exec, const JSC::ArgList& args)
769 {
770     return dataFunctionf(f_uniform2v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
771 }
772 
uniform2iv(JSC::ExecState * exec,const JSC::ArgList & args)773 JSC::JSValue JSWebGLRenderingContext::uniform2iv(JSC::ExecState* exec, const JSC::ArgList& args)
774 {
775     return dataFunctioni(f_uniform2v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
776 }
777 
uniform3fv(JSC::ExecState * exec,const JSC::ArgList & args)778 JSC::JSValue JSWebGLRenderingContext::uniform3fv(JSC::ExecState* exec, const JSC::ArgList& args)
779 {
780     return dataFunctionf(f_uniform3v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
781 }
782 
uniform3iv(JSC::ExecState * exec,const JSC::ArgList & args)783 JSC::JSValue JSWebGLRenderingContext::uniform3iv(JSC::ExecState* exec, const JSC::ArgList& args)
784 {
785     return dataFunctioni(f_uniform3v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
786 }
787 
uniform4fv(JSC::ExecState * exec,const JSC::ArgList & args)788 JSC::JSValue JSWebGLRenderingContext::uniform4fv(JSC::ExecState* exec, const JSC::ArgList& args)
789 {
790     return dataFunctionf(f_uniform4v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
791 }
792 
uniform4iv(JSC::ExecState * exec,const JSC::ArgList & args)793 JSC::JSValue JSWebGLRenderingContext::uniform4iv(JSC::ExecState* exec, const JSC::ArgList& args)
794 {
795     return dataFunctioni(f_uniform4v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
796 }
797 
uniformMatrix2fv(JSC::ExecState * exec,const JSC::ArgList & args)798 JSC::JSValue JSWebGLRenderingContext::uniformMatrix2fv(JSC::ExecState* exec, const JSC::ArgList& args)
799 {
800     return dataFunctionMatrix(f_uniformMatrix2fv, exec, args, static_cast<WebGLRenderingContext*>(impl()));
801 }
802 
uniformMatrix3fv(JSC::ExecState * exec,const JSC::ArgList & args)803 JSC::JSValue JSWebGLRenderingContext::uniformMatrix3fv(JSC::ExecState* exec, const JSC::ArgList& args)
804 {
805     return dataFunctionMatrix(f_uniformMatrix3fv, exec, args, static_cast<WebGLRenderingContext*>(impl()));
806 }
807 
uniformMatrix4fv(JSC::ExecState * exec,const JSC::ArgList & args)808 JSC::JSValue JSWebGLRenderingContext::uniformMatrix4fv(JSC::ExecState* exec, const JSC::ArgList& args)
809 {
810     return dataFunctionMatrix(f_uniformMatrix4fv, exec, args, static_cast<WebGLRenderingContext*>(impl()));
811 }
812 
vertexAttrib1fv(JSC::ExecState * exec,const JSC::ArgList & args)813 JSC::JSValue JSWebGLRenderingContext::vertexAttrib1fv(JSC::ExecState* exec, const JSC::ArgList& args)
814 {
815     return dataFunctionf(f_vertexAttrib1v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
816 }
817 
vertexAttrib2fv(JSC::ExecState * exec,const JSC::ArgList & args)818 JSC::JSValue JSWebGLRenderingContext::vertexAttrib2fv(JSC::ExecState* exec, const JSC::ArgList& args)
819 {
820     return dataFunctionf(f_vertexAttrib2v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
821 }
822 
vertexAttrib3fv(JSC::ExecState * exec,const JSC::ArgList & args)823 JSC::JSValue JSWebGLRenderingContext::vertexAttrib3fv(JSC::ExecState* exec, const JSC::ArgList& args)
824 {
825     return dataFunctionf(f_vertexAttrib3v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
826 }
827 
vertexAttrib4fv(JSC::ExecState * exec,const JSC::ArgList & args)828 JSC::JSValue JSWebGLRenderingContext::vertexAttrib4fv(JSC::ExecState* exec, const JSC::ArgList& args)
829 {
830     return dataFunctionf(f_vertexAttrib4v, exec, args, static_cast<WebGLRenderingContext*>(impl()));
831 }
832 
833 } // namespace WebCore
834 
835 #endif // ENABLE(3D_CANVAS)
836