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