From 553a8c9c5a1a0e7bfbecc7531ceb7d5255d20403 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Fri, 22 Jan 2010 13:34:25 -0800 Subject: [PATCH] b=533663; use js typed arrays in webgl; r=jmuizelaar,mrbkap,brendan --- content/canvas/src/CustomQS_WebGL.h | 1031 +++++++++++++++ content/canvas/src/Makefile.in | 5 +- content/canvas/src/WebGLContext.cpp | 2 - content/canvas/src/WebGLContext.h | 46 +- content/canvas/src/WebGLContextGL.cpp | 1165 ++++++----------- content/canvas/src/WebGLContextValidate.cpp | 12 +- dom/base/nsDOMClassInfo.cpp | 66 - dom/base/nsDOMClassInfoID.h | 10 - .../canvas/nsICanvasRenderingContextWebGL.idl | 242 ++-- js/src/xpconnect/src/dom_quickstubs.qsconf | 121 +- js/src/xpconnect/src/qsgen.py | 17 +- 11 files changed, 1646 insertions(+), 1071 deletions(-) create mode 100644 content/canvas/src/CustomQS_WebGL.h diff --git a/content/canvas/src/CustomQS_WebGL.h b/content/canvas/src/CustomQS_WebGL.h new file mode 100644 index 00000000000..a74dcdc86dc --- /dev/null +++ b/content/canvas/src/CustomQS_WebGL.h @@ -0,0 +1,1031 @@ +/* -*- Mode: c++; c-basic-offset: 4; tab-width: 40; indent-tabs-mode: nil; -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Corporation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Vladimir Vukicevic (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * Intended to be #included in dom_quickstubs.cpp via qsconf! + */ + +#include "jstypedarray.h" + +static inline bool +helper_isInt32Array(JSObject *obj) { + return obj->getClass() == &js::TypedArray::fastClasses[js::TypedArray::TYPE_INT32]; +} + +static inline bool +helper_isFloat32Array(JSObject *obj) { + return obj->getClass() == &js::TypedArray::fastClasses[js::TypedArray::TYPE_FLOAT32]; +} + +/* + * BufferData takes: + * BufferData (int, int, int) + * BufferData_buf (int, js::ArrayBuffer *, int) + * BufferData_array (int, js::TypedArray *, int) + */ +static JSBool +nsICanvasRenderingContextWebGL_BufferData(JSContext *cx, uintN argc, jsval *vp) +{ + XPC_QS_ASSERT_CONTEXT_OK(cx); + JSObject *obj = JS_THIS_OBJECT(cx, vp); + if (!obj) + return JS_FALSE; + + nsICanvasRenderingContextWebGL *self; + xpc_qsSelfRef selfref; + JSAutoTempValueRooter tvr(cx); + if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.addr(), nsnull)) + return JS_FALSE; + + if (argc < 3) + return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS); + + jsval *argv = JS_ARGV(cx, vp); + + int32 target; + js::TypedArray *wa = 0; + js::ArrayBuffer *wb = 0; + int32 size; + int32 usage; + + if (!JS_ValueToECMAInt32(cx, argv[0], &target)) + return JS_FALSE; + if (!JS_ValueToECMAInt32(cx, argv[2], &usage)) + return JS_FALSE; + + if (JSVAL_IS_OBJECT(argv[1])) { + JSObject *arg2 = JSVAL_TO_OBJECT(argv[1]); + if (js_IsArrayBuffer(arg2)) { + wb = js::ArrayBuffer::fromJSObject(arg2); + } else if (js_IsTypedArray(arg2)) { + wa = js::TypedArray::fromJSObject(arg2); + } + } + + if (!wa && !wb && + !JS_ValueToECMAInt32(cx, argv[1], &size)) + { + return JS_FALSE; + } + + nsresult rv; + + if (wa) + rv = self->BufferData_array(target, wa, usage); + else if (wb) + rv = self->BufferData_buf(target, wb, usage); + else + rv = self->BufferData_size(target, size, usage); + + if (NS_FAILED(rv)) + return xpc_qsThrowMethodFailed(cx, rv, vp); + + *vp = JSVAL_VOID; + return JS_TRUE; +} + +/* + * BufferSubData takes: + * BufferSubData (int, int, js::ArrayBuffer *) + * BufferSubData_array (int, int, js::TypedArray *) + */ +static JSBool +nsICanvasRenderingContextWebGL_BufferSubData(JSContext *cx, uintN argc, jsval *vp) +{ + XPC_QS_ASSERT_CONTEXT_OK(cx); + JSObject *obj = JS_THIS_OBJECT(cx, vp); + if (!obj) + return JS_FALSE; + + nsICanvasRenderingContextWebGL *self; + xpc_qsSelfRef selfref; + JSAutoTempValueRooter tvr(cx); + if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.addr(), nsnull)) + return JS_FALSE; + + if (argc < 3) + return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS); + + jsval *argv = JS_ARGV(cx, vp); + + int32 target; + int32 offset; + js::TypedArray *wa = 0; + js::ArrayBuffer *wb = 0; + + if (!JS_ValueToECMAInt32(cx, argv[0], &target)) + return JS_FALSE; + if (!JS_ValueToECMAInt32(cx, argv[1], &offset)) + return JS_FALSE; + + if (!JSVAL_IS_OBJECT(argv[2])) { + xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 2); + return JS_FALSE; + } + + JSObject *arg3 = JSVAL_TO_OBJECT(argv[2]); + if (js_IsArrayBuffer(arg3)) { + wb = js::ArrayBuffer::fromJSObject(arg3); + } else if (js_IsTypedArray(arg3)) { + wa = js::TypedArray::fromJSObject(arg3); + } else { + xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 2); + return JS_FALSE; + } + + nsresult rv; + + if (wa) { + rv = self->BufferSubData_array(target, offset, wa); + } else if (wb) { + rv = self->BufferSubData_buf(target, offset, wb); + } else { + xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 2); + return JS_FALSE; + } + + if (NS_FAILED(rv)) + return xpc_qsThrowMethodFailed(cx, rv, vp); + + *vp = JSVAL_VOID; + return JS_TRUE; +} + +/* + * TexImage2D takes: + * TexImage2D(int, int, int, int, int, int, int, int, WebGLArray) + * TexImage2D(int, int, int, int, int, int, int, int, WebGLArrayBuffer) + * TexImage2D(int, int, nsIDOMElement, [bool[, bool]]) + */ +static JSBool +nsICanvasRenderingContextWebGL_TexImage2D(JSContext *cx, uintN argc, jsval *vp) +{ + XPC_QS_ASSERT_CONTEXT_OK(cx); + JSObject *obj = JS_THIS_OBJECT(cx, vp); + if (!obj) + return JS_FALSE; + + nsresult rv; + + nsICanvasRenderingContextWebGL *self; + xpc_qsSelfRef selfref; + JSAutoTempValueRooter tvr(cx); + if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.addr(), nsnull)) + return JS_FALSE; + + if (argc < 3 || (argc > 3 && argc < 9)) + return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS); + + jsval *argv = JS_ARGV(cx, vp); + + int32 intargs[8]; + + // convert the first two args, they must be ints + for (jsuint i = 0; i < 2; ++i) { + if (!JS_ValueToECMAInt32(cx, argv[i], &intargs[i])) + return JS_FALSE; + } + + if (JSVAL_IS_OBJECT(argv[2])) { + // try to make this a nsIDOMElement + nsIDOMElement *elt; + xpc_qsSelfRef eltRef; + rv = xpc_qsUnwrapArg(cx, argv[2], &elt, &eltRef.ptr, &argv[2]); + if (NS_SUCCEEDED(rv)) { + intargs[3] = 0; + intargs[4] = 0; + + // convert args 4 and 5 if present, default to 0 + for (jsuint i = 3; i < 5 && i < argc; ++i) { + if (!JS_ValueToECMAInt32(cx, argv[i], &intargs[i])) + return JS_FALSE; + } + + rv = self->TexImage2D_dom(intargs[0], intargs[1], elt, (GLboolean) intargs[3], (GLboolean) intargs[4]); + if (NS_FAILED(rv)) + return xpc_qsThrowMethodFailed(cx, rv, vp); + return JS_TRUE; + } + } + + // didn't succeed? convert the rest of the int args + for (jsuint i = 2; i < 8; ++i) { + if (!JS_ValueToECMAInt32(cx, argv[i], &intargs[i])) + return JS_FALSE; + } + + if (!JSVAL_IS_OBJECT(argv[8])) { + xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 8); + return JS_FALSE; + } + + // then try to grab either a js::ArrayBuffer or js::TypedArray + js::TypedArray *wa = 0; + js::ArrayBuffer *wb = 0; + + JSObject *arg9 = JSVAL_TO_OBJECT(argv[8]); + if (js_IsArrayBuffer(arg9)) { + wb = js::ArrayBuffer::fromJSObject(arg9); + } else if (js_IsTypedArray(arg9)) { + wa = js::TypedArray::fromJSObject(arg9); + } else { + xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 8); + return JS_FALSE; + } + + if (wa) { + rv = self->TexImage2D_array(intargs[0], intargs[1], intargs[2], intargs[3], + intargs[4], intargs[5], intargs[6], intargs[7], + wa); + } else if (wb) { + rv = self->TexImage2D_buf(intargs[0], intargs[1], intargs[2], intargs[3], + intargs[4], intargs[5], intargs[6], intargs[7], + wb); + } else { + xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 8); + return JS_FALSE; + } + + if (NS_FAILED(rv)) + return xpc_qsThrowMethodFailed(cx, rv, vp); + + *vp = JSVAL_VOID; + return JS_TRUE; +} + +/* + * TexSubImage2D takes: + * TexSubImage2D(int, int, int, int, int, int, int, int, WebGLArray) + * TexSubImage2D(int, int, int, int, int, int, int, int, WebGLArrayBuffer) + * TexSubImage2D(int, int, int, int, int, int, nsIDOMElement, [bool[, bool]]) + */ +static JSBool +nsICanvasRenderingContextWebGL_TexSubImage2D(JSContext *cx, uintN argc, jsval *vp) +{ + XPC_QS_ASSERT_CONTEXT_OK(cx); + JSObject *obj = JS_THIS_OBJECT(cx, vp); + if (!obj) + return JS_FALSE; + + nsresult rv; + + nsICanvasRenderingContextWebGL *self; + xpc_qsSelfRef selfref; + JSAutoTempValueRooter tvr(cx); + if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.addr(), nsnull)) + return JS_FALSE; + + if (argc < 7 || (argc > 7 && argc < 9)) + return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS); + + jsval *argv = JS_ARGV(cx, vp); + + int32 intargs[8]; + + // convert the first six args, they must be ints + for (jsuint i = 0; i < 6; ++i) { + if (!JS_ValueToECMAInt32(cx, argv[i], &intargs[i])) + return JS_FALSE; + } + + if (JSVAL_IS_OBJECT(argv[6])) { + // try to make this a nsIDOMElement + nsIDOMElement *elt; + xpc_qsSelfRef eltRef; + + // these are two optinal args, default to 0 + intargs[7] = 0; + intargs[8] = 0; + + // convert args 7 and 8 if present + for (jsuint i = 7; i < 9 && i < argc; ++i) { + if (!JS_ValueToECMAInt32(cx, argv[i], &intargs[i])) + return JS_FALSE; + } + + rv = xpc_qsUnwrapArg(cx, argv[2], &elt, &eltRef.ptr, &argv[2]); + if (NS_SUCCEEDED(rv)) { + rv = self->TexSubImage2D_dom(intargs[0], intargs[1], intargs[2], + intargs[2], intargs[4], intargs[5], + elt, (GLboolean) intargs[7], (GLboolean) intargs[8]); + if (NS_FAILED(rv)) + return xpc_qsThrowMethodFailed(cx, rv, vp); + return JS_TRUE; + } + } + + // didn't succeed? convert the rest of the int args + for (jsuint i = 6; i < 8; ++i) { + if (!JS_ValueToECMAInt32(cx, argv[i], &intargs[i])) + return JS_FALSE; + } + + if (!JSVAL_IS_OBJECT(argv[8])) { + xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 8); + return JS_FALSE; + } + + // then try to grab either a js::ArrayBuffer or js::TypedArray + js::TypedArray *wa = 0; + js::ArrayBuffer *wb = 0; + + JSObject *arg9 = JSVAL_TO_OBJECT(argv[8]); + if (js_IsArrayBuffer(arg9)) { + wb = js::ArrayBuffer::fromJSObject(arg9); + } else if (js_IsTypedArray(arg9)) { + wa = js::TypedArray::fromJSObject(arg9); + } else { + xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 8); + return JS_FALSE; + } + + if (wa) { + rv = self->TexSubImage2D_array(intargs[0], intargs[1], intargs[2], intargs[3], + intargs[4], intargs[5], intargs[6], intargs[7], + wa); + } else if (wb) { + rv = self->TexSubImage2D_buf(intargs[0], intargs[1], intargs[2], intargs[3], + intargs[4], intargs[5], intargs[6], intargs[7], + wb); + } else { + xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 8); + return JS_FALSE; + } + + if (NS_FAILED(rv)) + return xpc_qsThrowMethodFailed(cx, rv, vp); + + *vp = JSVAL_VOID; + return JS_TRUE; +} + +/* NOTE: There is a TN version of this below, update it as well */ +static inline JSBool +helper_nsICanvasRenderingContextWebGL_Uniform_x_iv(JSContext *cx, uintN argc, jsval *vp, int nElements) +{ + XPC_QS_ASSERT_CONTEXT_OK(cx); + JSObject *obj = JS_THIS_OBJECT(cx, vp); + if (!obj) + return JS_FALSE; + + nsresult rv; + + nsICanvasRenderingContextWebGL *self; + xpc_qsSelfRef selfref; + JSAutoTempValueRooter tvr(cx); + if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.addr(), nsnull)) + return JS_FALSE; + + if (argc < 2) + return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS); + + jsval *argv = JS_ARGV(cx, vp); + + uint32 location; + if (!JS_ValueToECMAUint32(cx, argv[0], &location)) + return JS_FALSE; + + if (!JSVAL_IS_OBJECT(argv[1])) { + xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 1); + return JS_FALSE; + } + + JSObject *arg1 = JSVAL_TO_OBJECT(argv[1]); + + JSAutoTempValueRooter obj_tvr(cx); + + js::TypedArray *wa = 0; + + if (helper_isInt32Array(arg1)) { + wa = js::TypedArray::fromJSObject(arg1); + } else if (JS_IsArrayObject(cx, arg1)) { + JSObject *nobj = js_CreateTypedArrayWithArray(cx, js::TypedArray::TYPE_INT32, arg1); + if (!nobj) { + // XXX this will likely return a strange error message if it goes wrong + return JS_FALSE; + } + + *obj_tvr.addr() = OBJECT_TO_JSVAL(nobj); + wa = js::TypedArray::fromJSObject(nobj); + } else { + xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 1); + return JS_FALSE; + } + + if (nElements == 1) { + rv = self->Uniform1iv_array(location, wa); + } else if (nElements == 2) { + rv = self->Uniform2iv_array(location, wa); + } else if (nElements == 3) { + rv = self->Uniform3iv_array(location, wa); + } else if (nElements == 4) { + rv = self->Uniform4iv_array(location, wa); + } + + if (NS_FAILED(rv)) + return xpc_qsThrowMethodFailed(cx, rv, vp); + + *vp = JSVAL_VOID; + return JS_TRUE; +} + +/* NOTE: There is a TN version of this below, update it as well */ +static inline JSBool +helper_nsICanvasRenderingContextWebGL_Uniform_x_fv(JSContext *cx, uintN argc, jsval *vp, int nElements) +{ + XPC_QS_ASSERT_CONTEXT_OK(cx); + JSObject *obj = JS_THIS_OBJECT(cx, vp); + if (!obj) + return JS_FALSE; + + nsresult rv; + + nsICanvasRenderingContextWebGL *self; + xpc_qsSelfRef selfref; + JSAutoTempValueRooter tvr(cx); + if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.addr(), nsnull)) + return JS_FALSE; + + if (argc < 2) + return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS); + + jsval *argv = JS_ARGV(cx, vp); + + uint32 location; + if (!JS_ValueToECMAUint32(cx, argv[0], &location)) + return JS_FALSE; + + if (!JSVAL_IS_OBJECT(argv[1])) { + xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 1); + return JS_FALSE; + } + + JSObject *arg1 = JSVAL_TO_OBJECT(argv[1]); + + JSAutoTempValueRooter obj_tvr(cx); + + js::TypedArray *wa = 0; + + if (helper_isFloat32Array(arg1)) { + wa = js::TypedArray::fromJSObject(arg1); + } else if (JS_IsArrayObject(cx, arg1)) { + JSObject *nobj = js_CreateTypedArrayWithArray(cx, js::TypedArray::TYPE_FLOAT32, arg1); + if (!nobj) { + // XXX this will likely return a strange error message if it goes wrong + return JS_FALSE; + } + + *obj_tvr.addr() = OBJECT_TO_JSVAL(nobj); + wa = js::TypedArray::fromJSObject(nobj); + } else { + xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 1); + return JS_FALSE; + } + + if (nElements == 1) { + rv = self->Uniform1fv_array(location, wa); + } else if (nElements == 2) { + rv = self->Uniform2fv_array(location, wa); + } else if (nElements == 3) { + rv = self->Uniform3fv_array(location, wa); + } else if (nElements == 4) { + rv = self->Uniform4fv_array(location, wa); + } + + if (NS_FAILED(rv)) + return xpc_qsThrowMethodFailed(cx, rv, vp); + + *vp = JSVAL_VOID; + return JS_TRUE; +} + +/* NOTE: There is a TN version of this below, update it as well */ +static inline JSBool +helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv(JSContext *cx, uintN argc, jsval *vp, int nElements) +{ + XPC_QS_ASSERT_CONTEXT_OK(cx); + JSObject *obj = JS_THIS_OBJECT(cx, vp); + if (!obj) + return JS_FALSE; + + nsresult rv; + + nsICanvasRenderingContextWebGL *self; + xpc_qsSelfRef selfref; + JSAutoTempValueRooter tvr(cx); + if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.addr(), nsnull)) + return JS_FALSE; + + if (argc < 3) + return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS); + + jsval *argv = JS_ARGV(cx, vp); + + uint32 location; + int32 transpose; + if (!JS_ValueToECMAUint32(cx, argv[0], &location)) + return JS_FALSE; + + if (!JS_ValueToECMAInt32(cx, argv[1], &transpose)) + return JS_FALSE; + + if (!JSVAL_IS_OBJECT(argv[2])) { + xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 2); + return JS_FALSE; + } + + JSObject *arg2 = JSVAL_TO_OBJECT(argv[2]); + + JSAutoTempValueRooter obj_tvr(cx); + + js::TypedArray *wa = 0; + + if (helper_isFloat32Array(arg2)) { + wa = js::TypedArray::fromJSObject(arg2); + } else if (JS_IsArrayObject(cx, arg2)) { + JSObject *nobj = js_CreateTypedArrayWithArray(cx, js::TypedArray::TYPE_FLOAT32, arg2); + if (!nobj) { + // XXX this will likely return a strange error message if it goes wrong + return JS_FALSE; + } + + *obj_tvr.addr() = OBJECT_TO_JSVAL(nobj); + wa = js::TypedArray::fromJSObject(nobj); + } else { + xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 2); + return JS_FALSE; + } + + if (nElements == 2) { + rv = self->UniformMatrix2fv_array(location, transpose ? 1 : 0, wa); + } else if (nElements == 3) { + rv = self->UniformMatrix3fv_array(location, transpose ? 1 : 0, wa); + } else if (nElements == 4) { + rv = self->UniformMatrix4fv_array(location, transpose ? 1 : 0, wa); + } + + if (NS_FAILED(rv)) + return xpc_qsThrowMethodFailed(cx, rv, vp); + + *vp = JSVAL_VOID; + return JS_TRUE; +} + +static inline JSBool +helper_nsICanvasRenderingContextWebGL_VertexAttrib_x_fv(JSContext *cx, uintN argc, jsval *vp, int nElements) +{ + XPC_QS_ASSERT_CONTEXT_OK(cx); + JSObject *obj = JS_THIS_OBJECT(cx, vp); + if (!obj) + return JS_FALSE; + + nsresult rv; + + nsICanvasRenderingContextWebGL *self; + xpc_qsSelfRef selfref; + JSAutoTempValueRooter tvr(cx); + if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.addr(), nsnull)) + return JS_FALSE; + + if (argc < 2) + return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS); + + jsval *argv = JS_ARGV(cx, vp); + + uint32 location; + if (!JS_ValueToECMAUint32(cx, argv[0], &location)) + return JS_FALSE; + + if (!JSVAL_IS_OBJECT(argv[1])) { + xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 1); + return JS_FALSE; + } + + JSObject *arg1 = JSVAL_TO_OBJECT(argv[1]); + + JSAutoTempValueRooter obj_tvr(cx); + + js::TypedArray *wa = 0; + + if (helper_isFloat32Array(arg1)) { + wa = js::TypedArray::fromJSObject(arg1); + } else if (JS_IsArrayObject(cx, arg1)) { + JSObject *nobj = js_CreateTypedArrayWithArray(cx, js::TypedArray::TYPE_FLOAT32, arg1); + if (!nobj) { + // XXX this will likely return a strange error message if it goes wrong + return JS_FALSE; + } + + *obj_tvr.addr() = OBJECT_TO_JSVAL(nobj); + wa = js::TypedArray::fromJSObject(nobj); + } else { + xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 1); + return JS_FALSE; + } + + if (nElements == 1) { + rv = self->VertexAttrib1fv_array(location, wa); + } else if (nElements == 2) { + rv = self->VertexAttrib2fv_array(location, wa); + } else if (nElements == 3) { + rv = self->VertexAttrib3fv_array(location, wa); + } else if (nElements == 4) { + rv = self->VertexAttrib4fv_array(location, wa); + } + + if (NS_FAILED(rv)) + return xpc_qsThrowMethodFailed(cx, rv, vp); + + *vp = JSVAL_VOID; + return JS_TRUE; +} + +static JSBool +nsICanvasRenderingContextWebGL_Uniform1iv(JSContext *cx, uintN argc, jsval *vp) +{ + return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv(cx, argc, vp, 1); +} + +static JSBool +nsICanvasRenderingContextWebGL_Uniform2iv(JSContext *cx, uintN argc, jsval *vp) +{ + return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv(cx, argc, vp, 2); +} + +static JSBool +nsICanvasRenderingContextWebGL_Uniform3iv(JSContext *cx, uintN argc, jsval *vp) +{ + return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv(cx, argc, vp, 3); +} + +static JSBool +nsICanvasRenderingContextWebGL_Uniform4iv(JSContext *cx, uintN argc, jsval *vp) +{ + return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv(cx, argc, vp, 4); +} + +static JSBool +nsICanvasRenderingContextWebGL_Uniform1fv(JSContext *cx, uintN argc, jsval *vp) +{ + return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv(cx, argc, vp, 1); +} + +static JSBool +nsICanvasRenderingContextWebGL_Uniform2fv(JSContext *cx, uintN argc, jsval *vp) +{ + return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv(cx, argc, vp, 2); +} + +static JSBool +nsICanvasRenderingContextWebGL_Uniform3fv(JSContext *cx, uintN argc, jsval *vp) +{ + return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv(cx, argc, vp, 3); +} + +static JSBool +nsICanvasRenderingContextWebGL_Uniform4fv(JSContext *cx, uintN argc, jsval *vp) +{ + return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv(cx, argc, vp, 4); +} + +static JSBool +nsICanvasRenderingContextWebGL_UniformMatrix2fv(JSContext *cx, uintN argc, jsval *vp) +{ + return helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv(cx, argc, vp, 2); +} + +static JSBool +nsICanvasRenderingContextWebGL_UniformMatrix3fv(JSContext *cx, uintN argc, jsval *vp) +{ + return helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv(cx, argc, vp, 3); +} + +static JSBool +nsICanvasRenderingContextWebGL_UniformMatrix4fv(JSContext *cx, uintN argc, jsval *vp) +{ + return helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv(cx, argc, vp, 4); +} + +static JSBool +nsICanvasRenderingContextWebGL_VertexAttrib1fv(JSContext *cx, uintN argc, jsval *vp) +{ + return helper_nsICanvasRenderingContextWebGL_VertexAttrib_x_fv(cx, argc, vp, 1); +} + +static JSBool +nsICanvasRenderingContextWebGL_VertexAttrib2fv(JSContext *cx, uintN argc, jsval *vp) +{ + return helper_nsICanvasRenderingContextWebGL_VertexAttrib_x_fv(cx, argc, vp, 2); +} + +static JSBool +nsICanvasRenderingContextWebGL_VertexAttrib3fv(JSContext *cx, uintN argc, jsval *vp) +{ + return helper_nsICanvasRenderingContextWebGL_VertexAttrib_x_fv(cx, argc, vp, 3); +} + +static JSBool +nsICanvasRenderingContextWebGL_VertexAttrib4fv(JSContext *cx, uintN argc, jsval *vp) +{ + return helper_nsICanvasRenderingContextWebGL_VertexAttrib_x_fv(cx, argc, vp, 4); +} + +#ifdef JS_TRACER + +static inline jsval FASTCALL +helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg, int nElements) +{ + XPC_QS_ASSERT_CONTEXT_OK(cx); + + nsICanvasRenderingContextWebGL *self; + xpc_qsSelfRef selfref; + xpc_qsArgValArray<3> vp(cx); + if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, &vp.array[0], nsnull)) { + js_SetTraceableNativeFailed(cx); + return JSVAL_VOID; + } + + JSAutoTempValueRooter obj_tvr(cx); + + js::TypedArray *wa = 0; + + if (helper_isInt32Array(arg)) { + wa = js::TypedArray::fromJSObject(arg); + } else if (JS_IsArrayObject(cx, arg)) { + JSObject *nobj = js_CreateTypedArrayWithArray(cx, js::TypedArray::TYPE_INT32, arg); + if (!nobj) { + // XXX this will likely return a strange error message if it goes wrong + js_SetTraceableNativeFailed(cx); + return JSVAL_VOID; + } + + *obj_tvr.addr() = OBJECT_TO_JSVAL(nobj); + wa = js::TypedArray::fromJSObject(nobj); + } else { + xpc_qsThrowMethodFailedWithDetails(cx, NS_ERROR_FAILURE, "nsICanvasRenderingContextWebGL", "uniformNiv"); + js_SetTraceableNativeFailed(cx); + return JSVAL_VOID; + } + + nsresult rv; + + if (nElements == 1) { + rv = self->Uniform1iv_array(location, wa); + } else if (nElements == 2) { + rv = self->Uniform2iv_array(location, wa); + } else if (nElements == 3) { + rv = self->Uniform3iv_array(location, wa); + } else if (nElements == 4) { + rv = self->Uniform4iv_array(location, wa); + } + + if (NS_FAILED(rv)) { + xpc_qsThrowMethodFailedWithDetails(cx, rv, "nsICanvasRenderingContextWebGL", "uniformNiv"); + js_SetTraceableNativeFailed(cx); + } + + return JSVAL_VOID; +} + +static inline jsval FASTCALL +helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg, int nElements) +{ + XPC_QS_ASSERT_CONTEXT_OK(cx); + + nsICanvasRenderingContextWebGL *self; + xpc_qsSelfRef selfref; + xpc_qsArgValArray<3> vp(cx); + if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, &vp.array[0], nsnull)) { + js_SetTraceableNativeFailed(cx); + return JSVAL_VOID; + } + + JSAutoTempValueRooter obj_tvr(cx); + + js::TypedArray *wa = 0; + + if (helper_isFloat32Array(arg)) { + wa = js::TypedArray::fromJSObject(arg); + } else if (JS_IsArrayObject(cx, arg)) { + JSObject *nobj = js_CreateTypedArrayWithArray(cx, js::TypedArray::TYPE_FLOAT32, arg); + if (!nobj) { + // XXX this will likely return a strange error message if it goes wrong + js_SetTraceableNativeFailed(cx); + return JSVAL_VOID; + } + + *obj_tvr.addr() = OBJECT_TO_JSVAL(nobj); + wa = js::TypedArray::fromJSObject(nobj); + } else { + xpc_qsThrowMethodFailedWithDetails(cx, NS_ERROR_FAILURE, "nsICanvasRenderingContextWebGL", "uniformNfv"); + js_SetTraceableNativeFailed(cx); + return JSVAL_VOID; + } + + nsresult rv; + + if (nElements == 1) { + rv = self->Uniform1fv_array(location, wa); + } else if (nElements == 2) { + rv = self->Uniform2fv_array(location, wa); + } else if (nElements == 3) { + rv = self->Uniform3fv_array(location, wa); + } else if (nElements == 4) { + rv = self->Uniform4fv_array(location, wa); + } + + if (NS_FAILED(rv)) { + xpc_qsThrowMethodFailedWithDetails(cx, rv, "nsICanvasRenderingContextWebGL", "uniformNfv"); + js_SetTraceableNativeFailed(cx); + } + + return JSVAL_VOID; +} + +static inline jsval FASTCALL +helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(JSContext *cx, JSObject *obj, uint32 location, JSBool transpose, JSObject *arg, int nElements) +{ + XPC_QS_ASSERT_CONTEXT_OK(cx); + + nsICanvasRenderingContextWebGL *self; + xpc_qsSelfRef selfref; + xpc_qsArgValArray<4> vp(cx); + if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, &vp.array[0], nsnull)) { + js_SetTraceableNativeFailed(cx); + return JSVAL_VOID; + } + + JSAutoTempValueRooter obj_tvr(cx); + + js::TypedArray *wa = 0; + + if (helper_isFloat32Array(arg)) { + wa = js::TypedArray::fromJSObject(arg); + } else if (JS_IsArrayObject(cx, arg)) { + JSObject *nobj = js_CreateTypedArrayWithArray(cx, js::TypedArray::TYPE_FLOAT32, arg); + if (!nobj) { + // XXX this will likely return a strange error message if it goes wrong + js_SetTraceableNativeFailed(cx); + return JSVAL_VOID; + } + + *obj_tvr.addr() = OBJECT_TO_JSVAL(nobj); + wa = js::TypedArray::fromJSObject(nobj); + } else { + xpc_qsThrowMethodFailedWithDetails(cx, NS_ERROR_FAILURE, "nsICanvasRenderingContextWebGL", "uniformMatrixNfv"); + js_SetTraceableNativeFailed(cx); + return JSVAL_VOID; + } + + nsresult rv; + if (nElements == 2) { + rv = self->UniformMatrix2fv_array(location, transpose, wa); + } else if (nElements == 3) { + rv = self->UniformMatrix3fv_array(location, transpose, wa); + } else if (nElements == 4) { + rv = self->UniformMatrix4fv_array(location, transpose, wa); + } + + if (NS_FAILED(rv)) { + xpc_qsThrowMethodFailedWithDetails(cx, rv, "nsICanvasRenderingContextWebGL", "uniformMatrixNfv"); + js_SetTraceableNativeFailed(cx); + } + + return JSVAL_VOID; +} + +static jsval FASTCALL +nsICanvasRenderingContextWebGL_Uniform1iv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg) +{ + return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(cx, obj, location, arg, 1); +} + +JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform1iv, + (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform1iv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, 0))) + +static jsval FASTCALL +nsICanvasRenderingContextWebGL_Uniform2iv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg) +{ + return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(cx, obj, location, arg, 2); +} + +JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform2iv, + (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform2iv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, 0))) + +static jsval FASTCALL +nsICanvasRenderingContextWebGL_Uniform3iv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg) +{ + return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(cx, obj, location, arg, 3); +} + +JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform3iv, + (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform3iv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, 0))) + +static jsval FASTCALL +nsICanvasRenderingContextWebGL_Uniform4iv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg) +{ + return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(cx, obj, location, arg, 4); +} + +JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform4iv, + (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform4iv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, 0))) + +static jsval FASTCALL +nsICanvasRenderingContextWebGL_Uniform1fv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg) +{ + return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(cx, obj, location, arg, 1); +} + +JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform1fv, + (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform1fv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, 0))) + +static jsval FASTCALL +nsICanvasRenderingContextWebGL_Uniform2fv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg) +{ + return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(cx, obj, location, arg, 2); +} + +JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform2fv, + (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform2fv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, 0))) + +static jsval FASTCALL +nsICanvasRenderingContextWebGL_Uniform3fv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg) +{ + return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(cx, obj, location, arg, 3); +} + +JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform3fv, + (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform3fv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, 0))) + +static jsval FASTCALL +nsICanvasRenderingContextWebGL_Uniform4fv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg) +{ + return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(cx, obj, location, arg, 4); +} + +JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform4fv, + (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform4fv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, 0))) + +static jsval FASTCALL +nsICanvasRenderingContextWebGL_UniformMatrix2fv_tn(JSContext *cx, JSObject *obj, uint32 loc, JSBool transpose, JSObject *arg) +{ + return helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(cx, obj, loc, transpose, arg, 2); +} + +JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_UniformMatrix2fv, + (5, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix2fv_tn, CONTEXT, THIS, UINT32, BOOL, OBJECT, 0, 0))) + +static jsval FASTCALL +nsICanvasRenderingContextWebGL_UniformMatrix3fv_tn(JSContext *cx, JSObject *obj, uint32 loc, JSBool transpose, JSObject *arg) +{ + return helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(cx, obj, loc, transpose, arg, 3); +} + +JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_UniformMatrix3fv, + (5, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix3fv_tn, CONTEXT, THIS, UINT32, BOOL, OBJECT, 0, 0))) + +static jsval FASTCALL +nsICanvasRenderingContextWebGL_UniformMatrix4fv_tn(JSContext *cx, JSObject *obj, uint32 loc, JSBool transpose, JSObject *arg) +{ + return helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(cx, obj, loc, transpose, arg, 4); +} + +JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_UniformMatrix4fv, + (5, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix4fv_tn, CONTEXT, THIS, UINT32, BOOL, OBJECT, 0, 0))) + +#endif /* JS_TRACER */ diff --git a/content/canvas/src/Makefile.in b/content/canvas/src/Makefile.in index 7e3d0636d95..308c77fd135 100644 --- a/content/canvas/src/Makefile.in +++ b/content/canvas/src/Makefile.in @@ -46,7 +46,9 @@ MODULE = content LIBRARY_NAME = gkconcvs_s LIBXUL_LIBRARY = 1 - +EXPORTS = \ + CustomQS_WebGL.h \ + $(NULL) CPPSRCS = \ CanvasUtils.cpp \ @@ -82,7 +84,6 @@ WEBGL_PLATFORM = CGL endif CPPSRCS += \ - WebGLArrays.cpp \ WebGLContext.cpp \ WebGLContextGL.cpp \ WebGLContextUtils.cpp \ diff --git a/content/canvas/src/WebGLContext.cpp b/content/canvas/src/WebGLContext.cpp index 1d13f611d5d..f43f29403e1 100644 --- a/content/canvas/src/WebGLContext.cpp +++ b/content/canvas/src/WebGLContext.cpp @@ -15,8 +15,6 @@ #include "CanvasUtils.h" #include "NativeJSContext.h" -#include "WebGLArray.h" - using namespace mozilla; nsresult NS_NewCanvasRenderingContextWebGL(nsICanvasRenderingContextWebGL** aResult); diff --git a/content/canvas/src/WebGLContext.h b/content/canvas/src/WebGLContext.h index 441b7d7c445..06295374a0d 100644 --- a/content/canvas/src/WebGLContext.h +++ b/content/canvas/src/WebGLContext.h @@ -58,13 +58,10 @@ #include "SimpleBuffer.h" #include "nsGLPbuffer.h" -#include "WebGLArrays.h" - class nsIDocShell; namespace mozilla { -class WebGLArray; class WebGLTexture; class WebGLBuffer; class WebGLProgram; @@ -264,9 +261,20 @@ protected: void MakeContextCurrent() { mGLPbuffer->MakeContextCurrent(); } - nsresult TexImageElementBase(nsIDOMHTMLElement *imageOrCanvas, - gfxImageSurface **imageOut, - PRBool flipY, PRBool premultiplyAlpha); + // helpers + nsresult TexImage2D_base(GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, + void *data, PRUint32 byteLength); + nsresult TexSubImage2D_base(GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + void *pixels, PRUint32 byteLength); + + nsresult DOMElementToImageSurface(nsIDOMElement *imageOrCanvas, + gfxImageSurface **imageOut, + PRBool flipY, PRBool premultiplyAlpha); GLuint mActiveTexture; @@ -343,42 +351,32 @@ class WebGLBuffer : { public: WebGLBuffer(GLuint name) - : mName(name), mDeleted(PR_FALSE), mGLType(0) + : mName(name), mDeleted(PR_FALSE), mByteLength(0) { } void Delete() { if (mDeleted) return; ZeroOwners(); + mDeleted = PR_TRUE; + mByteLength = 0; } + PRBool Deleted() { return mDeleted; } GLuint GLName() { return mName; } + PRUint32 ByteLength() { return mByteLength; } - void Set(nsIWebGLArray *na) { - mGLType = na->NativeType(); - mElementSize = na->NativeElementSize(); - mCount = na->NativeCount(); + void SetByteLength(GLuint len) { + mByteLength = len; } - void SetCount(GLuint count) { - mCount = count; - } - - GLenum GLType() { return mGLType; } - PRUint32 ByteCount() { return mElementSize * mCount; } - PRUint32 Count() { return mCount; } - PRUint32 ElementSize() { return mElementSize; } - NS_DECL_ISUPPORTS NS_DECL_NSIWEBGLBUFFER protected: GLuint mName; PRBool mDeleted; - - GLenum mGLType; - PRUint32 mElementSize; - PRUint32 mCount; + PRUint32 mByteLength; }; class WebGLTexture : diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index fceabd6c8fe..3e6ed02da7c 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -54,6 +54,8 @@ #include "NativeJSContext.h" #include "SimpleBuffer.h" +#include "jstypedarray.h" + using namespace mozilla; // XXX why is this broken? @@ -107,190 +109,6 @@ NS_IMETHODIMP WebGLContext::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) { \ // WebGL API // -/* nsIWebGLFloatArray createFloatArray (); */ -NS_IMETHODIMP -WebGLContext::CreateFloatArray(nsIWebGLFloatArray **retval) -{ - NativeJSContext js; - - if (js.argc != 1) - return NS_ERROR_DOM_SYNTAX_ERR; - - JSObject *arrayObj; - jsuint arrayLen; - - if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "o", &arrayObj) || - arrayObj == NULL || - !::JS_IsArrayObject(js.ctx, arrayObj) || - !::JS_GetArrayLength(js.ctx, arrayObj, &arrayLen)) - { - return NS_ERROR_DOM_SYNTAX_ERR; - } - - WebGLFloatArray *wgfa = new WebGLFloatArray(js.ctx, arrayObj, arrayLen); - if (wgfa) - NS_ADDREF(*retval = wgfa); - - return NS_OK; -} - -/* nsIWebGLByteArray createByteArray (); */ -NS_IMETHODIMP -WebGLContext::CreateByteArray(nsIWebGLByteArray **retval) -{ - NativeJSContext js; - - if (js.argc != 1) - return NS_ERROR_DOM_SYNTAX_ERR; - - JSObject *arrayObj; - jsuint arrayLen; - - if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "o", &arrayObj) || - arrayObj == NULL || - !::JS_IsArrayObject(js.ctx, arrayObj) || - !::JS_GetArrayLength(js.ctx, arrayObj, &arrayLen)) - { - return NS_ERROR_DOM_SYNTAX_ERR; - } - - WebGLByteArray *wgba = new WebGLByteArray(js.ctx, arrayObj, arrayLen); - if (wgba) - NS_ADDREF(*retval = wgba); - return NS_OK; -} - -/* nsIWebGLUnsignedByteArray createUnsignedByteArray (); */ -NS_IMETHODIMP -WebGLContext::CreateUnsignedByteArray(nsIWebGLUnsignedByteArray **retval) -{ - NativeJSContext js; - - if (js.argc != 1) - return NS_ERROR_DOM_SYNTAX_ERR; - - JSObject *arrayObj; - jsuint arrayLen; - - if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "o", &arrayObj) || - arrayObj == NULL || - !::JS_IsArrayObject(js.ctx, arrayObj) || - !::JS_GetArrayLength(js.ctx, arrayObj, &arrayLen)) - { - return NS_ERROR_DOM_SYNTAX_ERR; - } - - WebGLUnsignedByteArray *wguba = new WebGLUnsignedByteArray(js.ctx, arrayObj, arrayLen); - if (wguba) - NS_ADDREF(*retval = wguba); - return NS_OK; -} - -/* nsIWebGLShortArray createShortArray (); */ -NS_IMETHODIMP -WebGLContext::CreateShortArray(nsIWebGLShortArray **retval) -{ - NativeJSContext js; - - if (js.argc != 1) - return NS_ERROR_DOM_SYNTAX_ERR; - - JSObject *arrayObj; - jsuint arrayLen; - - if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "o", &arrayObj) || - arrayObj == NULL || - !::JS_IsArrayObject(js.ctx, arrayObj) || - !::JS_GetArrayLength(js.ctx, arrayObj, &arrayLen)) - { - return NS_ERROR_DOM_SYNTAX_ERR; - } - - WebGLShortArray *wgsa = new WebGLShortArray(js.ctx, arrayObj, arrayLen); - if (wgsa) - NS_ADDREF(*retval = wgsa); - return NS_OK; -} - -/* nsIWebGLUnsignedShortArray createUnsignedShortArray (); */ -NS_IMETHODIMP -WebGLContext::CreateUnsignedShortArray(nsIWebGLUnsignedShortArray **retval) -{ - NativeJSContext js; - - if (js.argc != 1) - return NS_ERROR_DOM_SYNTAX_ERR; - - JSObject *arrayObj; - jsuint arrayLen; - - if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "o", &arrayObj) || - arrayObj == NULL || - !::JS_IsArrayObject(js.ctx, arrayObj) || - !::JS_GetArrayLength(js.ctx, arrayObj, &arrayLen)) - { - return NS_ERROR_DOM_SYNTAX_ERR; - } - - WebGLUnsignedShortArray *wgusa = new WebGLUnsignedShortArray(js.ctx, arrayObj, arrayLen); - if (wgusa) - NS_ADDREF(*retval = wgusa); - return NS_OK; -} - - -/* nsIWebGLUnsignedIntArray createUnsignedIntArray (); */ -NS_IMETHODIMP -WebGLContext::CreateIntArray(nsIWebGLIntArray **retval) -{ - NativeJSContext js; - - if (js.argc != 1) - return NS_ERROR_DOM_SYNTAX_ERR; - - JSObject *arrayObj; - jsuint arrayLen; - - if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "o", &arrayObj) || - arrayObj == NULL || - !::JS_IsArrayObject(js.ctx, arrayObj) || - !::JS_GetArrayLength(js.ctx, arrayObj, &arrayLen)) - { - return NS_ERROR_DOM_SYNTAX_ERR; - } - - WebGLIntArray *wgia = new WebGLIntArray(js.ctx, arrayObj, arrayLen); - if (wgia) - NS_ADDREF(*retval = wgia); - return NS_OK; -} - -/* nsIWebGLUnsignedIntArray createUnsignedIntArray (); */ -NS_IMETHODIMP -WebGLContext::CreateUnsignedIntArray(nsIWebGLUnsignedIntArray **retval) -{ - NativeJSContext js; - - if (js.argc != 1) - return NS_ERROR_DOM_SYNTAX_ERR; - - JSObject *arrayObj; - jsuint arrayLen; - - if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "o", &arrayObj) || - arrayObj == NULL || - !::JS_IsArrayObject(js.ctx, arrayObj) || - !::JS_GetArrayLength(js.ctx, arrayObj, &arrayLen)) - { - return NS_ERROR_DOM_SYNTAX_ERR; - } - - WebGLUnsignedIntArray *wguia = new WebGLUnsignedIntArray(js.ctx, arrayObj, arrayLen); - if (wguia) - NS_ADDREF(*retval = wguia); - return NS_OK; -} - /* readonly attribute nsIDOMHTMLCanvasElement canvas; */ NS_IMETHODIMP WebGLContext::GetCanvas(nsIDOMHTMLCanvasElement **aCanvas) @@ -470,94 +288,42 @@ GL_SAME_METHOD_2(BlendFunc, BlendFunc, PRUint32, PRUint32) GL_SAME_METHOD_4(BlendFuncSeparate, BlendFuncSeparate, PRUint32, PRUint32, PRUint32, PRUint32) NS_IMETHODIMP -WebGLContext::BufferData(GLenum target) +WebGLContext::BufferData(PRInt32 dummy) { - // overloaded: - // void bufferData (in GLenum target, in GLsizei size, in GLenum usage); - // void bufferData (in GLenum target, in nsIWebGLArray data, in GLenum usage); - // void bufferData (in GLenum target, in nsIWebGLArrayBuffer data, in GLenum usage) - - NativeJSContext js; - if (NS_FAILED(js.error)) - return js.error; - - if (js.argc != 3) - return NS_ERROR_DOM_SYNTAX_ERR; + // this should never be called + LogMessage("BufferData"); + return NS_ERROR_FAILURE; +} +NS_IMETHODIMP +WebGLContext::BufferData_size(GLenum target, GLsizei size, GLenum usage) +{ WebGLBuffer *boundBuffer = NULL; if (target == LOCAL_GL_ARRAY_BUFFER) { boundBuffer = mBoundArrayBuffer; } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) { - // XXX fix type check - //if (na->NativeType() != LOCAL_GL_UNSIGNED_SHORT) - // return ErrorMessage("glBufferData: %x - GL_ELEMENT_ARRAY_BUFFER target must be used with UnsignedShortBuffer", na->NativeType()); - boundBuffer = mBoundElementArrayBuffer; } else { - return ErrorMessage("glBufferData: invalid target"); - } - - if (boundBuffer == NULL) { - return ErrorMessage("glBufferData: no buffer bound!"); + return ErrorMessage("BufferData: invalid target"); } + if (boundBuffer == nsnull) + return ErrorMessage("BufferData: no buffer bound!"); MakeContextCurrent(); - uint32 usage; - - if (!::JS_ValueToECMAUint32(js.ctx, js.argv[2], &usage)) { - return ErrorMessage("bufferData: invalid usage parameter"); - } - - if (JSVAL_IS_NUMBER(js.argv[1])) { - int32 size; - if (!::JS_ValueToECMAInt32(js.ctx, js.argv[1], &size)) { - return ErrorMessage("bufferData: invalid size parameter"); - } - boundBuffer->SetCount(size); - gl->fBufferData(target, size, 0, usage); - } else if (JSVAL_IS_OBJECT(js.argv[1])) { - nsCOMPtr canvasArrayObj; - nsresult rv; - - rv = nsContentUtils::XPConnect()->WrapJS(js.ctx, JSVAL_TO_OBJECT(js.argv[1]), - NS_GET_IID(nsIWebGLArray), getter_AddRefs(canvasArrayObj)); - if (NS_FAILED(rv) || !canvasArrayObj) { - nsCOMPtr arrayBuf; - rv = nsContentUtils::XPConnect()->WrapJS(js.ctx, JSVAL_TO_OBJECT(js.argv[1]), - NS_GET_IID(nsIWebGLArrayBuffer), getter_AddRefs(arrayBuf)); - if (NS_FAILED(rv) || !arrayBuf) - return ErrorMessage("bufferData: need CanvasArray or CanvasArrayBuffer"); - - boundBuffer->SetCount(arrayBuf->NativeSize()); - gl->fBufferData(target, arrayBuf->NativeSize(), arrayBuf->NativePointer(), usage); - } else { - boundBuffer->Set(canvasArrayObj); - gl->fBufferData(target, canvasArrayObj->NativeSize(), canvasArrayObj->NativePointer(), usage); - } - } else { - return ErrorMessage("bufferData: invalid data"); - } + // XXX what happens if BufferData fails? We probably shouldn't + // update our size here then, right? + boundBuffer->SetByteLength(size); + gl->fBufferData(target, size, 0, usage); return NS_OK; } NS_IMETHODIMP -WebGLContext::BufferSubData(GLenum target, GLsizeiptr offset) +WebGLContext::BufferData_buf(GLenum target, js::ArrayBuffer *wb, GLenum usage) { - // overloaded: - // void bufferSubData(in GLenum target, in GLsizeiptr offset, in CanvasArray data) - // void bufferSubData(in GLenum target, in GLsizeiptr offset, in CanvasArrayBuffer data) - - NativeJSContext js; - if (NS_FAILED(js.error)) - return js.error; - - if (js.argc != 3) - return NS_ERROR_DOM_SYNTAX_ERR; - WebGLBuffer *boundBuffer = NULL; if (target == LOCAL_GL_ARRAY_BUFFER) { @@ -565,70 +331,101 @@ WebGLContext::BufferSubData(GLenum target, GLsizeiptr offset) } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) { boundBuffer = mBoundElementArrayBuffer; } else { - return ErrorMessage("glBufferSubData: invalid target"); + return ErrorMessage("BufferData: invalid target"); } - if (boundBuffer == NULL) { - return ErrorMessage("glBufferSubData: no buffer bound!"); - } + if (boundBuffer == nsnull) + return ErrorMessage("BufferData: no buffer bound!"); - /* XXX FIXME - // check type - if (na->NativeType() != boundBuffer->GLType()) { - return ErrorMessage("glBufferSubData: existing buffer has different base type (0x%04x) the sub data (0x%04x)!", boundBuffer->GLType(), na->NativeType()); - return NS_ERROR_FAILURE; - } - */ + MakeContextCurrent(); - if (JSVAL_IS_OBJECT(js.argv[2])) { - nsCOMPtr canvasArrayObj; - nsresult rv; + boundBuffer->SetByteLength(wb->byteLength); + gl->fBufferData(target, wb->byteLength, wb->data, usage); - rv = nsContentUtils::XPConnect()->WrapJS(js.ctx, JSVAL_TO_OBJECT(js.argv[2]), - NS_GET_IID(nsIWebGLArray), getter_AddRefs(canvasArrayObj)); - if (NS_FAILED(rv) || !canvasArrayObj) { - nsCOMPtr arrayBuf; - rv = nsContentUtils::XPConnect()->WrapJS(js.ctx, JSVAL_TO_OBJECT(js.argv[2]), - NS_GET_IID(nsIWebGLArrayBuffer), getter_AddRefs(arrayBuf)); - if (NS_FAILED(rv) || !arrayBuf) - return ErrorMessage("bufferData: need CanvasArray or CanvasArrayBuffer"); + return NS_OK; +} - // check size - // XXX should be bytes - if ((offset + arrayBuf->NativeSize()) > boundBuffer->Count()) { - return ErrorMessage("glBufferSubData: existing buffer is too small (%d) for data at offset (%d+%d)", - boundBuffer->Count(), offset, arrayBuf->NativeSize()); - return NS_ERROR_FAILURE; - } -#ifdef DEBUG_mwsteele - LogMessage("bufferSubData: buffer (%d) for data at offset (%d+%d)", boundBuffer->Count(), offset, arrayBuf->NativeSize()); -#endif - // all good +NS_IMETHODIMP +WebGLContext::BufferData_array(GLenum target, js::TypedArray *wa, GLenum usage) +{ + WebGLBuffer *boundBuffer = NULL; - MakeContextCurrent(); - - gl->fBufferSubData(target, offset, arrayBuf->NativeSize(), arrayBuf->NativePointer()); - } else { - // check size - // XXX should be bytes - if ((offset + canvasArrayObj->NativeCount()) > boundBuffer->Count()) { - return ErrorMessage("glBufferSubData: existing buffer is too small (%d) for data at offset (%d+%d)", - boundBuffer->Count(), offset, canvasArrayObj->NativeCount()); - return NS_ERROR_FAILURE; - } -#ifdef DEBUG_mwsteele - LogMessage("bufferSubData: buffer (%d) for data at offset (%d+%d)", boundBuffer->Count(), offset, canvasArrayObj->NativeSize()); -#endif - // all good - - MakeContextCurrent(); - - gl->fBufferSubData(target, offset, canvasArrayObj->NativeSize(), canvasArrayObj->NativePointer()); - } + if (target == LOCAL_GL_ARRAY_BUFFER) { + boundBuffer = mBoundArrayBuffer; + } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) { + boundBuffer = mBoundElementArrayBuffer; } else { - return ErrorMessage("bufferData: invalid data"); + return ErrorMessage("BufferData: invalid target"); } + if (boundBuffer == nsnull) + return ErrorMessage("BufferData: no buffer bound!"); + + MakeContextCurrent(); + + boundBuffer->SetByteLength(wa->byteLength); + gl->fBufferData(target, wa->byteLength, wa->data, usage); + + return NS_OK; +} + +NS_IMETHODIMP +WebGLContext::BufferSubData(PRInt32 dummy) +{ + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +WebGLContext::BufferSubData_buf(GLenum target, GLsizei offset, js::ArrayBuffer *wb) +{ + WebGLBuffer *boundBuffer = NULL; + + if (target == LOCAL_GL_ARRAY_BUFFER) { + boundBuffer = mBoundArrayBuffer; + } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) { + boundBuffer = mBoundElementArrayBuffer; + } else { + return ErrorMessage("BufferSubData: invalid target"); + } + + if (boundBuffer == nsnull) + return ErrorMessage("BufferSubData: no buffer bound!"); + + // XXX check for overflow + if (offset + wb->byteLength > boundBuffer->ByteLength()) + return ErrorMessage("BufferSubData: data too big! Operation requires %d bytes, but buffer only has %d bytes.", offset, wb->byteLength, boundBuffer->ByteLength()); + + MakeContextCurrent(); + + gl->fBufferSubData(target, offset, wb->byteLength, wb->data); + + return NS_OK; +} + +NS_IMETHODIMP +WebGLContext::BufferSubData_array(GLenum target, GLsizei offset, js::TypedArray *wa) +{ + WebGLBuffer *boundBuffer = NULL; + + if (target == LOCAL_GL_ARRAY_BUFFER) { + boundBuffer = mBoundArrayBuffer; + } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) { + boundBuffer = mBoundElementArrayBuffer; + } else { + return ErrorMessage("BufferSubData: invalid target"); + } + + if (boundBuffer == nsnull) + return ErrorMessage("BufferSubData: no buffer bound!"); + + // XXX check for overflow + if (offset + wa->byteLength > boundBuffer->ByteLength()) + return ErrorMessage("BufferSubData: data too big! Operation requires %d bytes, but buffer only has %d bytes.", offset, wa->byteLength, boundBuffer->ByteLength()); + + MakeContextCurrent(); + + gl->fBufferSubData(target, offset, wa->byteLength, wa->data); + return NS_OK; } @@ -1026,7 +823,7 @@ WebGLContext::DrawElements(GLenum mode, GLuint count, GLenum type, GLuint offset if (offset+count < offset || offset+count < count) return ErrorMessage("glDrawElements: overflow in offset+count"); - if (count*elementSize + offset > mBoundElementArrayBuffer->ByteCount()) + if (count*elementSize + offset > mBoundElementArrayBuffer->ByteLength()) return ErrorMessage("glDrawElements: bound element array buffer is too small for given count and offset"); MakeContextCurrent(); @@ -1264,8 +1061,8 @@ WebGLContext::GetAttachedShaders(nsIWebGLProgram *prog) NS_IMETHODIMP WebGLContext::GetAttribLocation(nsIWebGLProgram *prog, - const nsAString& name, - PRInt32 *retval) + const nsAString& name, + PRInt32 *retval) { if (!prog || static_cast(prog)->Deleted()) return ErrorMessage("%s: program is null or deleted!", __FUNCTION__); @@ -2331,9 +2128,9 @@ GL_SAME_METHOD_4(StencilOpSeparate, StencilOpSeparate, GLenum, GLenum, GLenum, G nsresult -WebGLContext::TexImageElementBase(nsIDOMHTMLElement *imageOrCanvas, - gfxImageSurface **imageOut, - PRBool flipY, PRBool premultiplyAlpha) +WebGLContext::DOMElementToImageSurface(nsIDOMElement *imageOrCanvas, + gfxImageSurface **imageOut, + PRBool flipY, PRBool premultiplyAlpha) { gfxImageSurface *surf = nsnull; @@ -2456,6 +2253,57 @@ WebGLContext::TexImageElementBase(nsIDOMHTMLElement *imageOrCanvas, return NS_OK; } +#define GL_SIMPLE_ARRAY_METHOD(name, cnt, arrayType, ptrType) \ +NS_IMETHODIMP \ +WebGLContext::name(PRInt32 dummy) { \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} \ +NS_IMETHODIMP \ +WebGLContext::name##_array(GLint idx, js::TypedArray *wa) \ +{ \ + if (!wa || wa->type != js::TypedArray::arrayType) \ + return ErrorMessage("array must be " #arrayType); \ + if (wa->length == 0 || wa->length % cnt != 0) \ + return ErrorMessage("array must be > 0 elements and have a length multiple of %d", cnt); \ + MakeContextCurrent(); \ + gl->f##name(idx, wa->length / cnt, (ptrType *)wa->data); \ + return NS_OK; \ +} + +#define GL_SIMPLE_ARRAY_METHOD_NO_COUNT(name, cnt, arrayType, ptrType) \ +NS_IMETHODIMP \ +WebGLContext::name(PRInt32 dummy) { \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} \ +NS_IMETHODIMP \ +WebGLContext::name##_array(GLuint idx, js::TypedArray *wa) \ +{ \ + if (!wa || wa->type != js::TypedArray::arrayType) \ + return ErrorMessage("array must be " #arrayType); \ + if (wa->length < cnt) \ + return ErrorMessage("array must be >= %d elements", cnt); \ + MakeContextCurrent(); \ + gl->f##name(idx, (ptrType *)wa->data); \ + return NS_OK; \ +} + +#define GL_SIMPLE_MATRIX_METHOD(name, dim, arrayType, ptrType) \ +NS_IMETHODIMP \ +WebGLContext::name(PRInt32 dummy) { \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} \ +NS_IMETHODIMP \ +WebGLContext::name##_array(GLint idx, GLboolean transpose, js::TypedArray *wa) \ +{ \ + if (!wa || wa->type != js::TypedArray::arrayType) \ + return ErrorMessage("array must be " #arrayType); \ + if (wa->length == 0 || wa->length % (dim*dim) != 0) \ + return ErrorMessage("array must be > 0 elements and have a length multiple of %d", dim*dim); \ + MakeContextCurrent(); \ + gl->f##name(idx, wa->length / (dim*dim), transpose, (ptrType *)wa->data); \ + return NS_OK; \ +} + GL_SAME_METHOD_2(Uniform1i, Uniform1i, GLint, GLint) GL_SAME_METHOD_3(Uniform2i, Uniform2i, GLint, GLint, GLint) GL_SAME_METHOD_4(Uniform3i, Uniform3i, GLint, GLint, GLint, GLint) @@ -2466,149 +2314,29 @@ GL_SAME_METHOD_3(Uniform2f, Uniform2f, GLint, GLfloat, GLfloat) GL_SAME_METHOD_4(Uniform3f, Uniform3f, GLint, GLfloat, GLfloat, GLfloat) GL_SAME_METHOD_5(Uniform4f, Uniform4f, GLint, GLfloat, GLfloat, GLfloat, GLfloat) -// one uint arg followed by an array of c elements of glTypeConst. -#define GL_SIMPLE_ARRAY_METHOD(glname, name, c, glTypeConst, ptrType) \ -NS_IMETHODIMP \ -WebGLContext::name(GLint idx, nsIWebGLArray *v) \ -{ \ - NativeJSContext js; \ - if (NS_FAILED(js.error)) \ - return js.error; \ - JSObject *arrayObj; \ - jsuint arrayLen; \ - if (js.argc != 2) \ - return NS_ERROR_INVALID_ARG; \ - if (NativeJSContext::JSValToJSArrayAndLength(js.ctx, js.argv[1], &arrayObj, &arrayLen)) { \ - if (arrayLen % c != 0) { \ - return ErrorMessage(#name ": array length not divisible by " #c); \ - } \ - SimpleBuffer sbuffer(glTypeConst, c, js.ctx, arrayObj, arrayLen); \ - if (!sbuffer.Valid()) \ - return NS_ERROR_FAILURE; \ - MakeContextCurrent(); \ - gl->f##glname(idx, arrayLen / c, ( ptrType *)sbuffer.data); \ - } else { \ - if (glTypeConst == LOCAL_GL_INT) { \ - if (v->NativeType() != LOCAL_GL_INT) { \ - return ErrorMessage(#name ": arg not an array"); \ - } \ - if (v->NativeCount() % c != 0) { \ - return ErrorMessage(#name ": array length not divisible by " #c); \ - } \ - MakeContextCurrent(); \ - gl->f##glname(idx, v->NativeCount() / c, ( ptrType *)v->NativePointer()); \ - } else if (glTypeConst == LOCAL_GL_FLOAT) { \ - if (v->NativeType() != LOCAL_GL_FLOAT) { \ - return ErrorMessage(#name ": arg not an array"); \ - } \ - if (v->NativeCount() % c != 0) { \ - return ErrorMessage(#name ": array length not divisible by " #c); \ - } \ - MakeContextCurrent(); \ - gl->f##glname(idx, v->NativeCount() / c, ( ptrType *)v->NativePointer()); \ - } else { \ - return ErrorMessage("Unhandled glTypeConst"); /* need compiler fail */\ - } \ - } \ - return NS_OK; \ -} +GL_SIMPLE_ARRAY_METHOD(Uniform1iv, 1, TYPE_INT32, GLint) +GL_SIMPLE_ARRAY_METHOD(Uniform2iv, 2, TYPE_INT32, GLint) +GL_SIMPLE_ARRAY_METHOD(Uniform3iv, 3, TYPE_INT32, GLint) +GL_SIMPLE_ARRAY_METHOD(Uniform4iv, 4, TYPE_INT32, GLint) -#define GL_SIMPLE_ARRAY_METHOD_NO_COUNT(glname, name, c, glTypeConst, ptrType) \ -NS_IMETHODIMP \ -WebGLContext::name(GLuint idx, nsIWebGLArray *v) \ -{ \ - NativeJSContext js; \ - if (NS_FAILED(js.error)) \ - return js.error; \ - JSObject *arrayObj; \ - jsuint arrayLen; \ - if (js.argc != 2) \ - return NS_ERROR_INVALID_ARG; \ - if (NativeJSContext::JSValToJSArrayAndLength(js.ctx, js.argv[1], &arrayObj, &arrayLen)) { \ - if (arrayLen % c != 0) { \ - return ErrorMessage(#name ": array wrong size, expected " #c); \ - } \ - SimpleBuffer sbuffer(glTypeConst, c, js.ctx, arrayObj, arrayLen); \ - if (!sbuffer.Valid()) \ - return NS_ERROR_FAILURE; \ - MakeContextCurrent(); \ - gl->f##glname(idx, ( ptrType *)sbuffer.data); \ - } else { \ - if (glTypeConst == LOCAL_GL_INT) { \ - if (v->NativeType() != LOCAL_GL_INT) { \ - return ErrorMessage(#name ": arg not an array"); \ - } \ - if (v->NativeCount() % c != 0) { \ - return ErrorMessage(#name ": array wrong size %d, expected " #c, v->NativeCount()); \ - } \ - MakeContextCurrent(); \ - gl->f##glname(idx, ( ptrType *)v->NativePointer()); \ - } else if (glTypeConst == LOCAL_GL_FLOAT) { \ - if (v->NativeType() != LOCAL_GL_FLOAT) { \ - return ErrorMessage(#name ": arg not an array"); \ - } \ - if (v->NativeCount() % c != 0) { \ - return ErrorMessage(#name ": array wrong size %d, expected " #c, v->NativeCount()); \ - } \ - MakeContextCurrent(); \ - gl->f##glname(idx, ( ptrType *)v->NativePointer()); \ - } else { \ - return ErrorMessage("Unhandled glTypeConst"); /* need compiler fail */\ - } \ - } \ - return NS_OK; \ -} +GL_SIMPLE_ARRAY_METHOD(Uniform1fv, 1, TYPE_FLOAT32, GLfloat) +GL_SIMPLE_ARRAY_METHOD(Uniform2fv, 2, TYPE_FLOAT32, GLfloat) +GL_SIMPLE_ARRAY_METHOD(Uniform3fv, 3, TYPE_FLOAT32, GLfloat) +GL_SIMPLE_ARRAY_METHOD(Uniform4fv, 4, TYPE_FLOAT32, GLfloat) -#define GL_SIMPLE_MATRIX_METHOD(glname, name, c, glTypeConst, ptrType) \ -NS_IMETHODIMP \ -WebGLContext::name(GLint location, GLboolean transpose, nsIWebGLArray *value) \ -{ \ - NativeJSContext js; \ - if (NS_FAILED(js.error)) \ - return js.error; \ - JSObject *arrayObj; \ - jsuint arrayLen; \ - if (js.argc != 3) \ - return NS_ERROR_INVALID_ARG; \ - if (NativeJSContext::JSValToJSArrayAndLength(js.ctx, js.argv[2], &arrayObj, &arrayLen)) { \ - if (arrayLen % c != 0) { \ - return ErrorMessage(#name ": array wrong size, expected " #c); \ - } \ - SimpleBuffer sbuffer(glTypeConst, c, js.ctx, arrayObj, arrayLen); \ - if (!sbuffer.Valid()) \ - return NS_ERROR_FAILURE; \ - MakeContextCurrent(); \ - gl->f##glname(location, arrayLen / c, transpose, ( ptrType *)sbuffer.data); \ - } else { \ - if (glTypeConst == LOCAL_GL_FLOAT) { \ - if (value->NativeType() != LOCAL_GL_FLOAT) { \ - return ErrorMessage(#name ": arg not an array"); \ - } \ - if (value->NativeCount() % c != 0) { \ - return ErrorMessage(#name ": array wrong size %d, expected " #c, value->NativeCount()); \ - } \ - MakeContextCurrent(); \ - gl->f##glname(location, value->NativeCount() / c, transpose, ( ptrType *)value->NativePointer()); \ - } else { \ - return ErrorMessage("Unhandled glTypeConst"); /* need compiler fail */\ - } \ - } \ - return NS_OK; \ -} +GL_SIMPLE_MATRIX_METHOD(UniformMatrix2fv, 2, TYPE_FLOAT32, GLfloat) +GL_SIMPLE_MATRIX_METHOD(UniformMatrix3fv, 3, TYPE_FLOAT32, GLfloat) +GL_SIMPLE_MATRIX_METHOD(UniformMatrix4fv, 4, TYPE_FLOAT32, GLfloat) -GL_SIMPLE_ARRAY_METHOD(Uniform1iv, Uniform1iv, 1, LOCAL_GL_INT, GLint) -GL_SIMPLE_ARRAY_METHOD(Uniform2iv, Uniform2iv, 2, LOCAL_GL_INT, GLint) -GL_SIMPLE_ARRAY_METHOD(Uniform3iv, Uniform3iv, 3, LOCAL_GL_INT, GLint) -GL_SIMPLE_ARRAY_METHOD(Uniform4iv, Uniform4iv, 4, LOCAL_GL_INT, GLint) +GL_SAME_METHOD_2(VertexAttrib1f, VertexAttrib1f, PRUint32, GLfloat) +GL_SAME_METHOD_3(VertexAttrib2f, VertexAttrib2f, PRUint32, GLfloat, GLfloat) +GL_SAME_METHOD_4(VertexAttrib3f, VertexAttrib3f, PRUint32, GLfloat, GLfloat, GLfloat) +GL_SAME_METHOD_5(VertexAttrib4f, VertexAttrib4f, PRUint32, GLfloat, GLfloat, GLfloat, GLfloat) -GL_SIMPLE_ARRAY_METHOD(Uniform1fv, Uniform1fv, 1, LOCAL_GL_FLOAT, GLfloat) -GL_SIMPLE_ARRAY_METHOD(Uniform2fv, Uniform2fv, 2, LOCAL_GL_FLOAT, GLfloat) -GL_SIMPLE_ARRAY_METHOD(Uniform3fv, Uniform3fv, 3, LOCAL_GL_FLOAT, GLfloat) -GL_SIMPLE_ARRAY_METHOD(Uniform4fv, Uniform4fv, 4, LOCAL_GL_FLOAT, GLfloat) - -GL_SIMPLE_MATRIX_METHOD(UniformMatrix2fv, UniformMatrix2fv, 4, LOCAL_GL_FLOAT, GLfloat) -GL_SIMPLE_MATRIX_METHOD(UniformMatrix3fv, UniformMatrix3fv, 9, LOCAL_GL_FLOAT, GLfloat) -GL_SIMPLE_MATRIX_METHOD(UniformMatrix4fv, UniformMatrix4fv, 16, LOCAL_GL_FLOAT, GLfloat) +GL_SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib1fv, 1, TYPE_FLOAT32, GLfloat) +GL_SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib2fv, 2, TYPE_FLOAT32, GLfloat) +GL_SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib3fv, 3, TYPE_FLOAT32, GLfloat) +GL_SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib4fv, 4, TYPE_FLOAT32, GLfloat) NS_IMETHODIMP WebGLContext::UseProgram(nsIWebGLProgram *prog) @@ -2642,16 +2370,6 @@ WebGLContext::ValidateProgram(nsIWebGLProgram *prog) return NS_OK; } -GL_SAME_METHOD_2(VertexAttrib1f, VertexAttrib1f, PRUint32, float) -GL_SAME_METHOD_3(VertexAttrib2f, VertexAttrib2f, PRUint32, float, float) -GL_SAME_METHOD_4(VertexAttrib3f, VertexAttrib3f, PRUint32, float, float, float) -GL_SAME_METHOD_5(VertexAttrib4f, VertexAttrib4f, PRUint32, float, float, float, float) - -GL_SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib1fv, VertexAttrib1fv, 1, LOCAL_GL_FLOAT, GLfloat) -GL_SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib2fv, VertexAttrib2fv, 2, LOCAL_GL_FLOAT, GLfloat) -GL_SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib3fv, VertexAttrib3fv, 3, LOCAL_GL_FLOAT, GLfloat) -GL_SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib4fv, VertexAttrib4fv, 4, LOCAL_GL_FLOAT, GLfloat) - NS_IMETHODIMP WebGLContext::CreateFramebuffer(nsIWebGLFramebuffer **retval) { @@ -2859,8 +2577,8 @@ WebGLContext::ShaderSource(nsIWebGLShader *shobj, const nsAString& source) NS_IMETHODIMP WebGLContext::VertexAttribPointer(GLuint index, GLint size, GLenum type, - GLboolean normalized, GLuint stride, - GLuint offset) + GLboolean normalized, GLuint stride, + GLuint offset) { if (mBoundArrayBuffer == nsnull) return ErrorMessage("glvertexattribpointer: must have GL_ARRAY_BUFFER binding!"); @@ -2946,237 +2664,18 @@ WebGLContext::ValidateGL() } NS_IMETHODIMP -WebGLContext::TexSubImage2D() +WebGLContext::TexImage2D(PRInt32 dummy) { - // 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 CanvasArray pixels) - // void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, - // in ImageData pixels, - // [Optional] GLboolean flipY, [Optional] in asPremultipliedAlpha) - // void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, - // in HTMLImageElement image, - // [Optional] GLboolean flipY, [Optional] in asPremultipliedAlpha) - // void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, - // in HTMLCanvasElement image, - // [Optional] GLboolean flipY, [Optional] in asPremultipliedAlpha) - // void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, - // in HTMLVideoElement image, - // [Optional] GLboolean flipY, [Optional] in asPremultipliedAlpha) - - // XXX TODO - NativeJSContext js; - if (NS_FAILED(js.error)) - return js.error; - - if (js.argc < 5 || js.argc > 9) { - return ErrorMessage("texSubImage2D: expected 5 to 9 arguments"); - return NS_ERROR_DOM_SYNTAX_ERR; - } - - if (js.argc < 8) { - jsuint argTarget, argLevel, argX, argY; - JSObject *argPixelsObj; - JSBool flipY = JS_FALSE; - JSBool premultiplyAlpha = JS_TRUE; - - if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "uuuuo/bb", - &argTarget, &argLevel, &argX, &argY, - &argPixelsObj, &flipY, &premultiplyAlpha) || - !argPixelsObj) - { - return ErrorMessage("texSubImage2D: argument error"); - return NS_ERROR_DOM_SYNTAX_ERR; - } - nsCOMPtr imgElt; - nsresult rv; - rv = nsContentUtils::XPConnect()->WrapJS(js.ctx, argPixelsObj, NS_GET_IID(nsIDOMHTMLElement), getter_AddRefs(imgElt)); - - nsRefPtr isurf; - - rv = TexImageElementBase(imgElt, getter_AddRefs(isurf), flipY, premultiplyAlpha); - - if (NS_FAILED(rv)) - return ErrorMessage("texImage2D: failed to get image for element"); - - MakeContextCurrent(); - - gl->fTexSubImage2D (argTarget, argLevel, argX, argY, isurf->Width(), isurf->Height(), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, isurf->Data()); - } else { - jsuint argTarget, argLevel, argX, argY, argWidth, argHeight, argFormat, argType; - JSObject *argPixelsObj; - if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "uuuuuuuuo", - &argTarget, &argLevel, &argX, &argY, - &argWidth, &argHeight, &argFormat, &argType, - &argPixelsObj) || - !argPixelsObj) - { - return ErrorMessage("texSubImage2D: argument error"); - return NS_ERROR_DOM_SYNTAX_ERR; - } - - switch (argTarget) { - case LOCAL_GL_TEXTURE_2D: - case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - break; - default: - return ErrorMessage("texSubImage2D: unsupported target"); - return NS_ERROR_DOM_SYNTAX_ERR; - } - - PRUint32 bufferType, bufferSize; - switch (argFormat) { - case LOCAL_GL_RED: - case LOCAL_GL_GREEN: - case LOCAL_GL_BLUE: - case LOCAL_GL_ALPHA: - case LOCAL_GL_LUMINANCE: - bufferSize = 1; - break; - case LOCAL_GL_LUMINANCE_ALPHA: - bufferSize = 2; - break; - case LOCAL_GL_RGB: - bufferSize = 3; - break; - case LOCAL_GL_RGBA: - bufferSize = 4; - break; - default: - return ErrorMessage("texSubImage2D: pixel format not supported"); - return NS_ERROR_DOM_SYNTAX_ERR; - } - - switch (argType) { - case LOCAL_GL_SHORT: - case LOCAL_GL_UNSIGNED_SHORT: - case LOCAL_GL_BYTE: - case LOCAL_GL_UNSIGNED_BYTE: - case LOCAL_GL_INT: - case LOCAL_GL_UNSIGNED_INT: - case LOCAL_GL_FLOAT: - bufferType = argType; - break; - case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4: - case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1: - case LOCAL_GL_UNSIGNED_SHORT_5_6_5: - bufferType = LOCAL_GL_UNSIGNED_SHORT; - break; - default: - return ErrorMessage("texSubImage2D: pixel packing not supported"); - return NS_ERROR_DOM_SYNTAX_ERR; - } - - // make sure the size is valid - PRInt32 tmp = argWidth * argHeight; - if (tmp && tmp / argHeight != argWidth) { - return ErrorMessage("texSubImage2D: too large width or height"); - return NS_ERROR_DOM_SYNTAX_ERR; - } - - tmp = tmp * bufferSize; - if (tmp && tmp / bufferSize != (argWidth * argHeight)) { - return ErrorMessage("texSubImage2D: too large width or height (after multiplying with pixel size)"); - return NS_ERROR_DOM_SYNTAX_ERR; - } - - nsCOMPtr arrayObj; - nsresult rv; - rv = nsContentUtils::XPConnect()->WrapJS(js.ctx, argPixelsObj, NS_GET_IID(nsISupports), getter_AddRefs(arrayObj)); - arrayObj = do_QueryInterface(arrayObj, &rv); - - if (NS_FAILED(rv) || !arrayObj) { - return ErrorMessage("texSubImage2D: pixels arg is not a WebGL array"); - } - - if ((PRUint32) tmp > arrayObj->NativeSize()) { - return ErrorMessage("texSubImage2D: array dimensions too small for width, height and pixel format"); - return NS_ERROR_DOM_SYNTAX_ERR; - } - - MakeContextCurrent(); - gl->fTexSubImage2D (argTarget, argLevel, argX, argY, argWidth, argHeight, argFormat, argType, arrayObj->NativePointer()); - } - return NS_OK; + return NS_ERROR_FAILURE; } -NS_IMETHODIMP -WebGLContext::TexImage2D() +nsresult +WebGLContext::TexImage2D_base(GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, + void *data, PRUint32 byteLength) { - // 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 CanvasArray pixels) - // void texImage2D(in GLenum target, in GLint level, in ImageData pixels, - // [Optional] GLboolean flipY, [Optional] in asPremultipliedAlpha) - // void texImage2D(in GLenum target, in GLint level, in HTMLImageElement image, - // [Optional] GLboolean flipY, [Optional] in asPremultipliedAlpha) - // void texImage2D(in GLenum target, in GLint level, in HTMLCanvasElement image, - // [Optional] GLboolean flipY, [Optional] in asPremultipliedAlpha) - // void texImage2D(in GLenum target, in GLint level, in HTMLVideoElement image, - // [Optional] GLboolean flipY, [Optional] in asPremultipliedAlpha) - - // XXX TODO - NativeJSContext js; - if (NS_FAILED(js.error)) - return js.error; - - if (js.argc < 3 || js.argc > 9) { - return ErrorMessage("texImage2D: expected 3-5 or 9 arguments, got %d", js.argc); - return NS_ERROR_DOM_SYNTAX_ERR; - } - - jsuint argTarget, argLevel, argInternalFormat, argWidth, argHeight, argBorder, argFormat, argType; - - if (js.argc > 2 && js.argc < 6) { - JSObject *argPixelsObj; - JSBool flipY = JS_FALSE; - JSBool premultiplyAlpha = JS_TRUE; - - if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "uuo/bb", - &argTarget, &argLevel, - &argPixelsObj, &flipY, &premultiplyAlpha) || - !argPixelsObj) - { - return ErrorMessage("texImage2D: argument error"); - return NS_ERROR_DOM_SYNTAX_ERR; - } - nsCOMPtr imgElt; - nsresult rv; - rv = nsContentUtils::XPConnect()->WrapJS(js.ctx, argPixelsObj, NS_GET_IID(nsIDOMHTMLElement), getter_AddRefs(imgElt)); - - nsRefPtr isurf; - - rv = TexImageElementBase(imgElt, getter_AddRefs(isurf), flipY, premultiplyAlpha); - - if (NS_FAILED(rv)) - return ErrorMessage("texImage2D: failed to get image for element"); - - MakeContextCurrent(); - - gl->fTexImage2D (argTarget, argLevel, LOCAL_GL_RGBA, isurf->Width(), isurf->Height(), 0, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, isurf->Data()); - - } else if (js.argc == 9) { - JSObject *argPixelsObj; - if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "uuuuuuuuo", - &argTarget, &argLevel, &argInternalFormat, &argWidth, - &argHeight, &argBorder, &argFormat, &argType, - &argPixelsObj) || - !argPixelsObj) - { - return ErrorMessage("texImage2D: argument error"); - return NS_ERROR_DOM_SYNTAX_ERR; - } - if (argWidth == 0 || argHeight == 0) { - return ErrorMessage("texImage2D: width or height is zero"); - return NS_ERROR_DOM_SYNTAX_ERR; - } - - switch (argTarget) { + switch (target) { case LOCAL_GL_TEXTURE_2D: case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X: case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X: @@ -3187,15 +2686,12 @@ WebGLContext::TexImage2D() break; default: return ErrorMessage("texImage2D: unsupported target"); - return NS_ERROR_DOM_SYNTAX_ERR; - } + } - if (argBorder != 0) { - return ErrorMessage("texImage2D: non-zero border given"); - return NS_ERROR_DOM_SYNTAX_ERR; - } + if (level < 0) + return ErrorMessage("texImage2D: level must be >= 0"); - switch (argInternalFormat) { + switch (internalformat) { case LOCAL_GL_RGB: case LOCAL_GL_RGBA: case LOCAL_GL_ALPHA: @@ -3204,92 +2700,257 @@ WebGLContext::TexImage2D() break; default: return ErrorMessage("texImage2D: internal format not supported"); - return NS_ERROR_DOM_SYNTAX_ERR; - } + } - PRUint32 bufferType, bufferSize; - switch (argFormat) { + if (width <= 0 || height <= 0) + return ErrorMessage("texImage2D: width and height must be > 0!"); + + if (border != 0) + return ErrorMessage("texImage2D: border must be 0"); + + // number of bytes per pixel + uint32 bufferPixelSize = 0; + switch (format) { case LOCAL_GL_RED: case LOCAL_GL_GREEN: case LOCAL_GL_BLUE: case LOCAL_GL_ALPHA: case LOCAL_GL_LUMINANCE: - bufferSize = 1; + bufferPixelSize = 1; break; case LOCAL_GL_LUMINANCE_ALPHA: - bufferSize = 2; + bufferPixelSize = 2; break; case LOCAL_GL_RGB: - bufferSize = 3; + bufferPixelSize = 3; break; case LOCAL_GL_RGBA: - bufferSize = 4; + bufferPixelSize = 4; break; default: return ErrorMessage("texImage2D: pixel format not supported"); - return NS_ERROR_DOM_SYNTAX_ERR; - } + } - switch (argType) { - case LOCAL_GL_SHORT: - case LOCAL_GL_UNSIGNED_SHORT: + switch (type) { case LOCAL_GL_BYTE: case LOCAL_GL_UNSIGNED_BYTE: + break; + case LOCAL_GL_SHORT: + case LOCAL_GL_UNSIGNED_SHORT: + bufferPixelSize *= 2; + break; case LOCAL_GL_INT: case LOCAL_GL_UNSIGNED_INT: case LOCAL_GL_FLOAT: - bufferType = argType; + bufferPixelSize *= 4; break; case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4: case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1: case LOCAL_GL_UNSIGNED_SHORT_5_6_5: - bufferType = LOCAL_GL_UNSIGNED_SHORT; + bufferPixelSize *= 2; break; default: - return ErrorMessage("texImage2D: pixel packing not supported"); - return NS_ERROR_DOM_SYNTAX_ERR; - } - - // make sure the size is valid - PRInt32 tmp = argWidth * argHeight; - if (tmp && tmp / argHeight != argWidth) { - return ErrorMessage("texImage2D: too large width or height"); - return NS_ERROR_DOM_SYNTAX_ERR; - } - - tmp = tmp * bufferSize; - if (tmp && tmp / bufferSize != (argWidth * argHeight)) { - return ErrorMessage("texImage2D: too large width or height (after multiplying with pixel size)"); - return NS_ERROR_DOM_SYNTAX_ERR; - } - - // XXX handle LOCAL_GL_UNPACK_ALIGNMENT ! - - if (argPixelsObj == NULL) { - MakeContextCurrent(); - gl->fTexImage2D (argTarget, argLevel, argInternalFormat, argWidth, argHeight, argBorder, argFormat, argType, NULL); - } else { - nsCOMPtr arrayObj; - nsresult rv; - rv = nsContentUtils::XPConnect()->WrapJS(js.ctx, argPixelsObj, NS_GET_IID(nsISupports), getter_AddRefs(arrayObj)); - arrayObj = do_QueryInterface(arrayObj, &rv); - - if (NS_FAILED(rv) || !arrayObj) { - return ErrorMessage("texImage2D: pixels arg is not a WebGL array"); - } - - if ((PRUint32) tmp > arrayObj->NativeSize()) { - return ErrorMessage("texImage2D: array dimensions too small for width, height and pixel format"); - return NS_ERROR_DOM_SYNTAX_ERR; - } - - MakeContextCurrent(); - gl->fTexImage2D (argTarget, argLevel, argInternalFormat, argWidth, argHeight, argBorder, argFormat, argType, arrayObj->NativePointer()); - } + return ErrorMessage("texImage2D: invalid type argument"); } + + // XXX overflow! + uint32 bytesNeeded = width * height * bufferPixelSize; + + if (byteLength && byteLength < bytesNeeded) + return ErrorMessage("texImage2D: not enough data for operation (need %d, have %d)", bytesNeeded, byteLength); + + MakeContextCurrent(); + + if (byteLength) { + gl->fTexImage2D(target, level, internalformat, width, height, border, format, type, data); + } else { + gl->fTexImage2D(target, level, internalformat, width, height, border, format, type, NULL); + } + return NS_OK; } +NS_IMETHODIMP +WebGLContext::TexImage2D_buf(GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, + js::ArrayBuffer *pixels) +{ + return TexImage2D_base(target, level, internalformat, width, height, border, format, type, + pixels ? pixels->data : 0, + pixels ? pixels->byteLength : 0); +} + +NS_IMETHODIMP +WebGLContext::TexImage2D_array(GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, + js::TypedArray *pixels) +{ + return TexImage2D_base(target, level, internalformat, width, height, border, format, type, + pixels ? pixels->data : 0, + pixels ? pixels->byteLength : 0); +} + +NS_IMETHODIMP +WebGLContext::TexImage2D_dom(GLenum target, GLint level, + nsIDOMElement *elt, + GLboolean flipY, GLboolean premultiplyAlpha) +{ + nsRefPtr isurf; + + nsresult rv = DOMElementToImageSurface(elt, getter_AddRefs(isurf), + flipY, premultiplyAlpha); + if (NS_FAILED(rv)) + return rv; + + return TexImage2D_base(target, level, LOCAL_GL_RGBA, + isurf->Width(), isurf->Height(), 0, + LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, + isurf->Data(), isurf->Stride() * isurf->Height()); +} + +NS_IMETHODIMP +WebGLContext::TexSubImage2D(PRInt32 dummy) +{ + return NS_ERROR_FAILURE; +} + +nsresult +WebGLContext::TexSubImage2D_base(GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + void *pixels, PRUint32 byteLength) +{ + switch (target) { + case LOCAL_GL_TEXTURE_2D: + case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + break; + default: + return ErrorMessage("texSubImage2D: unsupported target"); + } + + if (level < 0) + return ErrorMessage("texSubImage2D: level must be >= 0"); + + if (width <= 0 || height <= 0) + return ErrorMessage("texSubImage2D: width and height must be > 0!"); + + // number of bytes per pixel + uint32 bufferPixelSize = 0; + switch (format) { + case LOCAL_GL_RED: + case LOCAL_GL_GREEN: + case LOCAL_GL_BLUE: + case LOCAL_GL_ALPHA: + case LOCAL_GL_LUMINANCE: + bufferPixelSize = 1; + break; + case LOCAL_GL_LUMINANCE_ALPHA: + bufferPixelSize = 2; + break; + case LOCAL_GL_RGB: + bufferPixelSize = 3; + break; + case LOCAL_GL_RGBA: + bufferPixelSize = 4; + break; + default: + return ErrorMessage("texImage2D: pixel format not supported"); + } + + switch (type) { + case LOCAL_GL_BYTE: + case LOCAL_GL_UNSIGNED_BYTE: + break; + case LOCAL_GL_SHORT: + case LOCAL_GL_UNSIGNED_SHORT: + bufferPixelSize *= 2; + break; + case LOCAL_GL_INT: + case LOCAL_GL_UNSIGNED_INT: + case LOCAL_GL_FLOAT: + bufferPixelSize *= 4; + break; + case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4: + case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1: + case LOCAL_GL_UNSIGNED_SHORT_5_6_5: + bufferPixelSize *= 2; + break; + default: + return ErrorMessage("texImage2D: invalid type argument"); + } + + // XXX overflow! + uint32 bytesNeeded = width * height * bufferPixelSize; + + if (byteLength < bytesNeeded) + return ErrorMessage("texSubImage2D: not enough data for operation (need %d, have %d)", bytesNeeded, byteLength); + + MakeContextCurrent(); + + gl->fTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); + + return NS_OK; +} + +NS_IMETHODIMP +WebGLContext::TexSubImage2D_buf(GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + js::ArrayBuffer *pixels) +{ + if (!pixels) + return ErrorMessage("texSubImage2D: pixels must not be null!"); + + return TexSubImage2D_base(target, level, xoffset, yoffset, + width, height, format, type, + pixels->data, pixels->byteLength); +} + +NS_IMETHODIMP +WebGLContext::TexSubImage2D_array(GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + js::TypedArray *pixels) +{ + if (!pixels) + return ErrorMessage("texSubImage2D: pixels must not be null!"); + + return TexSubImage2D_base(target, level, xoffset, yoffset, + width, height, format, type, + pixels->data, pixels->byteLength); +} + +NS_IMETHODIMP +WebGLContext::TexSubImage2D_dom(GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + nsIDOMElement *elt, + GLboolean flipY, GLboolean premultiplyAlpha) +{ + nsRefPtr isurf; + + nsresult rv = DOMElementToImageSurface(elt, getter_AddRefs(isurf), + flipY, premultiplyAlpha); + if (NS_FAILED(rv)) + return rv; + + return TexSubImage2D_base(target, level, + xoffset, yoffset, + width, height, + LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, + isurf->Data(), isurf->Stride() * isurf->Height()); +} + #if 0 // ImageData getImageData (in float x, in float y, in float width, in float height); NS_IMETHODIMP diff --git a/content/canvas/src/WebGLContextValidate.cpp b/content/canvas/src/WebGLContextValidate.cpp index ab21f7a123b..2f607f45b04 100644 --- a/content/canvas/src/WebGLContextValidate.cpp +++ b/content/canvas/src/WebGLContextValidate.cpp @@ -81,17 +81,17 @@ WebGLContext::ValidateBuffers(PRUint32 count) // is this a problem? if (!vd.enabled) - continue; + continue; if (vd.buf == nsnull) { - LogMessage("No VBO bound to index %d (or it's been deleted)!", i); - return PR_FALSE; + LogMessage("No VBO bound to index %d (or it's been deleted)!", i); + return PR_FALSE; } GLuint needed = vd.offset + (vd.stride ? vd.stride : vd.size) * count; - if (vd.buf->Count() < needed) { - LogMessage("VBO too small for bound attrib index %d: need at least %d elements, but have only %d", i, needed, vd.buf->Count()); - return PR_FALSE; + if (vd.buf->ByteLength() < needed) { + LogMessage("VBO too small for bound attrib index %d: need at least %d bytes, but have only %d", i, needed, vd.buf->ByteLength()); + return PR_FALSE; } } diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index 4fd3144c6ee..42fcbf65098 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -435,7 +435,6 @@ #include "nsIDOMCanvasRenderingContext2D.h" #include "nsICanvasRenderingContextWebGL.h" -#include "WebGLArray.h" #include "nsIImageDocument.h" @@ -1321,29 +1320,6 @@ static nsDOMClassInfoData sClassInfoData[] = { DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(WebGLRenderbuffer, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) - NS_DEFINE_CLASSINFO_DATA(WebGLArrayBuffer, nsDOMGenericSH, - DOM_DEFAULT_SCRIPTABLE_FLAGS) - NS_DEFINE_CLASSINFO_DATA(WebGLFloatArray, nsDOMGenericSH, - nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE | - nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY) - NS_DEFINE_CLASSINFO_DATA(WebGLByteArray, nsDOMGenericSH, - nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE | - nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY) - NS_DEFINE_CLASSINFO_DATA(WebGLUnsignedByteArray, nsDOMGenericSH, - nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE | - nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY) - NS_DEFINE_CLASSINFO_DATA(WebGLShortArray, nsDOMGenericSH, - nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE | - nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY) - NS_DEFINE_CLASSINFO_DATA(WebGLUnsignedShortArray, nsDOMGenericSH, - nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE | - nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY) - NS_DEFINE_CLASSINFO_DATA(WebGLIntArray, nsDOMGenericSH, - nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE | - nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY) - NS_DEFINE_CLASSINFO_DATA(WebGLUnsignedIntArray, nsDOMGenericSH, - nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE | - nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY) NS_DEFINE_CLASSINFO_DATA(PaintRequest, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) @@ -1391,16 +1367,6 @@ struct nsConstructorFuncMapData static const nsConstructorFuncMapData kConstructorFuncMap[] = { NS_DEFINE_CONSTRUCTOR_FUNC_DATA(Worker, nsDOMWorker::NewWorker) - - // WebGL Array Types - NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebGLArrayBuffer, NS_NewWebGLArrayBuffer) - NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebGLFloatArray, NS_NewWebGLFloatArray) - NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebGLByteArray, NS_NewWebGLByteArray) - NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebGLUnsignedByteArray, NS_NewWebGLUnsignedByteArray) - NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebGLShortArray, NS_NewWebGLShortArray) - NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebGLUnsignedShortArray, NS_NewWebGLUnsignedShortArray) - NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebGLIntArray, NS_NewWebGLIntArray) - NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebGLUnsignedIntArray, NS_NewWebGLUnsignedIntArray) }; nsIXPConnect *nsDOMClassInfo::sXPConnect = nsnull; @@ -3741,38 +3707,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_ENTRY(nsIWebGLRenderbuffer) DOM_CLASSINFO_MAP_END - DOM_CLASSINFO_MAP_BEGIN(WebGLArrayBuffer, nsIWebGLArrayBuffer) - DOM_CLASSINFO_MAP_ENTRY(nsIWebGLArrayBuffer) - DOM_CLASSINFO_MAP_END - - DOM_CLASSINFO_MAP_BEGIN(WebGLFloatArray, nsIWebGLFloatArray) - DOM_CLASSINFO_MAP_ENTRY(nsIWebGLFloatArray) - DOM_CLASSINFO_MAP_END - - DOM_CLASSINFO_MAP_BEGIN(WebGLByteArray, nsIWebGLByteArray) - DOM_CLASSINFO_MAP_ENTRY(nsIWebGLByteArray) - DOM_CLASSINFO_MAP_END - - DOM_CLASSINFO_MAP_BEGIN(WebGLUnsignedByteArray, nsIWebGLUnsignedByteArray) - DOM_CLASSINFO_MAP_ENTRY(nsIWebGLUnsignedByteArray) - DOM_CLASSINFO_MAP_END - - DOM_CLASSINFO_MAP_BEGIN(WebGLShortArray, nsIWebGLShortArray) - DOM_CLASSINFO_MAP_ENTRY(nsIWebGLShortArray) - DOM_CLASSINFO_MAP_END - - DOM_CLASSINFO_MAP_BEGIN(WebGLUnsignedShortArray, nsIWebGLUnsignedShortArray) - DOM_CLASSINFO_MAP_ENTRY(nsIWebGLUnsignedShortArray) - DOM_CLASSINFO_MAP_END - - DOM_CLASSINFO_MAP_BEGIN(WebGLIntArray, nsIWebGLIntArray) - DOM_CLASSINFO_MAP_ENTRY(nsIWebGLIntArray) - DOM_CLASSINFO_MAP_END - - DOM_CLASSINFO_MAP_BEGIN(WebGLUnsignedIntArray, nsIWebGLUnsignedIntArray) - DOM_CLASSINFO_MAP_ENTRY(nsIWebGLUnsignedIntArray) - DOM_CLASSINFO_MAP_END - DOM_CLASSINFO_MAP_BEGIN(PaintRequest, nsIDOMPaintRequest) DOM_CLASSINFO_MAP_ENTRY(nsIDOMPaintRequest) DOM_CLASSINFO_MAP_END diff --git a/dom/base/nsDOMClassInfoID.h b/dom/base/nsDOMClassInfoID.h index cd959e1bdb6..124abebcabb 100644 --- a/dom/base/nsDOMClassInfoID.h +++ b/dom/base/nsDOMClassInfoID.h @@ -468,16 +468,6 @@ enum nsDOMClassInfoID { eDOMClassInfo_WebGLFramebuffer_id, eDOMClassInfo_WebGLRenderbuffer_id, - // WebGL Buffers - eDOMClassInfo_WebGLArrayBuffer_id, - eDOMClassInfo_WebGLFloatArray_id, - eDOMClassInfo_WebGLByteArray_id, - eDOMClassInfo_WebGLUnsignedByteArray_id, - eDOMClassInfo_WebGLShortArray_id, - eDOMClassInfo_WebGLUnsignedShortArray_id, - eDOMClassInfo_WebGLIntArray_id, - eDOMClassInfo_WebGLUnsignedIntArray_id, - eDOMClassInfo_PaintRequest_id, eDOMClassInfo_PaintRequestList_id, diff --git a/dom/interfaces/canvas/nsICanvasRenderingContextWebGL.idl b/dom/interfaces/canvas/nsICanvasRenderingContextWebGL.idl index 4b813e48866..793193f5297 100644 --- a/dom/interfaces/canvas/nsICanvasRenderingContextWebGL.idl +++ b/dom/interfaces/canvas/nsICanvasRenderingContextWebGL.idl @@ -38,6 +38,7 @@ #include "nsISupports.idl" +interface nsIDOMElement; interface nsIDOMHTMLCanvasElement; // XXX should we comment out these typedefs in the C++ header? @@ -62,113 +63,17 @@ typedef long GLfixed; typedef long GLsizeiptr; %{C++ -namespace mozilla { - class WebGLArrayBuffer; +namespace js { +struct ArrayBuffer; +struct TypedArray; } + +/* Avoid conflict with WinAPI */ +#undef NO_ERROR %} -[ptr] native WebGLArrayBufferPtr (mozilla::WebGLArrayBuffer); -// -// Array types -// -[scriptable, uuid(34b6cf8e-47da-458e-ab42-0451a3533ee5)] -interface nsIWebGLArrayBuffer : nsISupports -{ - readonly attribute unsigned long byteLength; - [noscript, notxpcom] WebGLArrayBufferPtr GetNativeArrayBuffer(); - [noscript, notxpcom] voidPtr nativePointer(); - [noscript, notxpcom] unsigned long nativeSize(); -}; - -[scriptable, uuid(84ba4e98-8173-7c10-dca0-b5ba7809fcf3)] -interface nsIWebGLArray : nsISupports -{ - readonly attribute nsIWebGLArrayBuffer buffer; - readonly attribute unsigned long byteOffset; - readonly attribute unsigned long byteLength; - readonly attribute unsigned long length; - - // XXX kill this. - unsigned long alignedSizeInBytes(); - - nsIWebGLArray slice(in unsigned long offset, in unsigned long length); - - [noscript, notxpcom] unsigned long nativeType(); - [noscript, notxpcom] voidPtr nativePointer(); - [noscript, notxpcom] unsigned long nativeSize(); - [noscript, notxpcom] unsigned long nativeElementSize(); - [noscript, notxpcom] unsigned long nativeCount(); -}; - -[scriptable, Uuid(0f6d0e7b-bcfc-9305-6a1d-a9653b5e8c80)] -interface nsIWebGLFloatArray : nsIWebGLArray -{ - [IndexGetter] float get(in unsigned long index); - //[IndexSetter] void set(in unsigned long index, in float value); - //void set(in CanvasFloatArray array, [Optional] in unsigned long offset); - //void set(in sequence array, [Optional] in unsigned long offset); - void set(); -}; - -[scriptable, uuid(b29db7cf-fa58-435f-8d45-611cc50979ad)] -interface nsIWebGLByteArray : nsIWebGLArray -{ - [IndexGetter] long get(in unsigned long index); - //[IndexSetter] void set(in unsigned long index, in long value); - //void set(in nsIWebGLByteArray array, [Optional] in unsigned long offset); - //void set(in sequence array, [Optional] in unsigned long offset); - void set(); -}; - -[scriptable, uuid(3daa67fa-e743-2cbd-a212-805c2fc520cc)] -interface nsIWebGLUnsignedByteArray : nsIWebGLArray -{ - [IndexGetter] unsigned long get(in unsigned long index); - //[IndexSetter] void set(in unsigned long index, in unsigned long value); - //void set(in CanvasUnsignedByteArray array, [Optional] in unsigned long offset); - //void set(in sequence array, [Optional] in unsigned long offset); - void set(); -}; - -[scriptable, uuid(a8a982e3-3977-7364-f012-c497a5ab7681)] -interface nsIWebGLShortArray : nsIWebGLArray -{ - [IndexGetter] long get(in unsigned long index); - //[IndexSetter] void set(in unsigned long index, in long value); - //void set(in CanvasShortArray array, [Optional] in unsigned long offset); - //void set(in sequence array, [Optional] in unsigned long offset); - void set(); -}; - -[scriptable, uuid(8b9c67cc-c7be-a062-84b0-76a910a5c1e6)] -interface nsIWebGLUnsignedShortArray : nsIWebGLArray -{ - [IndexGetter] unsigned long get(in unsigned long index); - //[IndexSetter] void set(in unsigned long index, in unsigned long value); - //void set(in CanvasUnsignedShortArray array, [Optional] in unsigned long offset); - //void set(in sequence array, [Optional] in unsigned long offset); - void set(); -}; - -[scriptable, uuid(b9b2e861-3a28-4311-993c-799e4f77dcba)] -interface nsIWebGLIntArray : nsIWebGLArray -{ - [IndexGetter] long get(in unsigned long index); - //[IndexSetter] void set(in unsigned long index, in long value); - //void set(in CanvasIntArray array, [Optional] in unsigned long offset); - //void set(in sequence array, [Optional] in unsigned long offset); - void set(); -}; - -[scriptable, uuid(0d6ee3f8-71b6-460d-b05a-d579cc55edbe)] -interface nsIWebGLUnsignedIntArray : nsIWebGLArray -{ - [IndexGetter] unsigned long get(in unsigned long index); - //[IndexSetter] void set(in unsigned long index, in unsigned long value); - //void set(in CanvasUnsignedIntArray array, [Optional] in unsigned long offset); - //void set(in sequence array, [Optional] in unsigned long offset); - void set(); -}; +[ptr] native WebGLArrayBufferPtr (js::ArrayBuffer); +[ptr] native WebGLArrayPtr (js::TypedArray); // // OpenGL object wrappers @@ -199,7 +104,8 @@ interface nsIWebGLShader : nsISupports }; [scriptable, uuid(beea4b38-3094-4e8d-b6e6-8b21d07e8994)] -interface nsIWebGLShaderArray { +interface nsIWebGLShaderArray : nsISupports +{ readonly attribute unsigned long length; nsIWebGLShader item(in unsigned long index); }; @@ -217,7 +123,8 @@ interface nsIWebGLRenderbuffer : nsISupports }; [scriptable, uuid(a85d4fd0-5b9f-4cb8-aeee-5a2c5c5bad76)] -interface nsIWebGLActiveInfo { +interface nsIWebGLActiveInfo : nsISupports +{ readonly attribute GLint size; readonly attribute GLenum type; readonly attribute DOMString name; @@ -231,6 +138,7 @@ interface nsICanvasRenderingContextWebGL : nsISupports // ARRAY CONSTRUCTORS // + /* nsIWebGLFloatArray createFloatArray(); nsIWebGLByteArray createByteArray(); nsIWebGLUnsignedByteArray createUnsignedByteArray(); @@ -238,6 +146,7 @@ interface nsICanvasRenderingContextWebGL : nsISupports nsIWebGLUnsignedShortArray createUnsignedShortArray(); nsIWebGLIntArray createIntArray(); nsIWebGLUnsignedIntArray createUnsignedIntArray(); + */ // // CONSTANTS @@ -357,10 +266,6 @@ interface nsICanvasRenderingContextWebGL : nsISupports const unsigned long SAMPLE_COVERAGE = 0x80A0; /* ErrorCode */ -%{C++ -/* Avoid conflict with WinAPI */ -#undef NO_ERROR -%} const unsigned long NO_ERROR = 0; const unsigned long INVALID_ENUM = 0x0500; const unsigned long INVALID_VALUE = 0x0501; @@ -695,15 +600,14 @@ interface nsICanvasRenderingContextWebGL : nsISupports void blendFuncSeparate (in GLenum srcRGB, in GLenum dstRGB, in GLenum srcAlpha, in GLenum dstAlpha); // Modified: void glBufferData (GLenum target, GLsizeiptr size, const void* data, GLenum usage); - // void bufferData (in GLenum target, in GLsizei size, in GLenum usage); - // void bufferData (in GLenum target, in nsIWebGLArray data, in GLenum usage); - // void bufferData (in GLenum target, in nsIWebGLArrayBuffer data, in GLenum usage); - void bufferData (in GLenum target); + void bufferData([optional] in long dummy); + [noscript] void bufferData_size (in GLenum target, in GLsizei size, in GLenum usage); + [noscript] void bufferData_buf (in GLenum target, in WebGLArrayBufferPtr data, in GLenum usage); + [noscript] void bufferData_array (in GLenum target, in WebGLArrayPtr data, in GLenum usage); - // Modified: void glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void* data); - // void bufferSubData (in GLenum target, in GLsizeiptr offset, in nsIWebGLArray data); - // void bufferSubData (in GLenum target, in GLsizeiptr offset, in CanvasArrayBuffer data); - void bufferSubData (in GLenum target, in GLsizeiptr offset); + void bufferSubData([optional] in long dummy); + [noscript] void bufferSubData_buf (in GLenum target, in GLsizeiptr offset, in WebGLArrayBufferPtr data); + [noscript] void bufferSubData_array (in GLenum target, in GLsizeiptr offset, in WebGLArrayPtr data); GLenum checkFramebufferStatus (in GLenum target); void clear (in GLbitfield mask); @@ -713,13 +617,10 @@ interface nsICanvasRenderingContextWebGL : nsISupports void colorMask (in GLboolean red, in GLboolean green, in GLboolean blue, in GLboolean alpha); void compileShader (in nsIWebGLShader shader); - //void glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); - //void glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); - void copyTexImage2D (in GLenum target, in GLint level, in GLenum internalformat, - in GLint x, in GLint y, in GLsizei width, in GLsizei height, in GLint border); + in GLint x, in GLint y, in GLsizei width, in GLsizei height, in GLint border); void copyTexSubImage2D (in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, - in GLint x, in GLint y, in GLsizei width, in GLsizei height); + in GLint x, in GLint y, in GLsizei width, in GLsizei height); nsIWebGLBuffer createBuffer(); nsIWebGLProgram createProgram (); @@ -867,28 +768,36 @@ interface nsICanvasRenderingContextWebGL : nsISupports void stencilOp (in GLenum fail, in GLenum zfail, in GLenum zpass); void stencilOpSeparate (in GLenum face, in GLenum fail, in GLenum zfail, in GLenum zpass); - // Modified: glTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, - // GLint border, GLenum format, GLenum type, const void* pixels); - //void glTexImage2D (in GLenum target, in GLint level, in GLenum internalformat, in GLsizei width, in GLsizei height, in GLint border, in GLenum format, in GLenum type, nsIWebGLArray pixels); - //void glTexImage2D (in GLenum target, in GLint level, in HTMLImageElement image); - //void glTexImage2D (in GLenum target, in GLint level, in HTMLnsIWebGLElement canvas); - //void glTexImage2D (in GLenum target, in GLint level, in HTMLVideoElement video); - void texImage2D (); + void texImage2D([optional] in long dummy); + [noscript] void texImage2D_buf (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 WebGLArrayBufferPtr pixels); + [noscript] void texImage2D_array (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 WebGLArrayPtr pixels); + // HTMLImageElement, HTMLCanvasElement, HTMLVideoElement + [noscript] void texImage2D_dom (in GLenum target, in GLint level, in nsIDOMElement element, + [optional] in GLboolean premultiply, [optional] in GLboolean asPremultipliedAlpha); + void texSubImage2D([optional] in long dummy); + [noscript] void texSubImage2D_buf (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 WebGLArrayBufferPtr pixels); + [noscript] void texSubImage2D_array (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 WebGLArrayPtr pixels); + // HTMLImageElement, HTMLCanvasElement, HTMLVideoElement + [noscript] void texSubImage2D_dom (in GLenum target, in GLint level, + in GLint xoffset, in GLint yoffset, in GLsizei width, in GLsizei height, + in nsIDOMElement element, + [optional] in GLboolean premultiply, [optional] in GLboolean asPremultipliedAlpha); + // Modified: This replaces glTexParameterf, glTexParameterfv, glTexParameteri and glTexParameteriv void texParameterf (in GLenum target, in GLenum pname, in GLfloat param); void texParameteri (in GLenum target, in GLenum pname, in GLint param); //void glTexParameter (in GLenum target, in GLenum pname, in nsIWebGLArray params); - // Modified: void glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); - //void glTexSubImage2D (in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in GLsizei width, in GLsizei height, in GLenum format, in GLenum type, nsIWebGLArray pixels); - //void glTexSubImage2D (in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in GLsizei width, in GLsizei height, in HTMLImageElement image); - //void glTexSubImage2D (in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in GLsizei width, in GLsizei height, in HTMLnsIWebGLElement canvas); - //void glTexSubImage2D (in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in GLsizei width, in GLsizei height, in HTMLVideoElement video); - - void texSubImage2D (); - // Modified: All the glUniform*v forms below are modified by replacing 'count' and 'v' with a nsIWebGLArray void uniform1f (in GLint location, in GLfloat x); void uniform1i (in GLint location, in GLint x); @@ -899,19 +808,32 @@ interface nsICanvasRenderingContextWebGL : nsISupports void uniform4f (in GLint location, in GLfloat x, in GLfloat y, in GLfloat z, in GLfloat w); void uniform4i (in GLint location, in GLint x, in GLint y, in GLint z, in GLint w); - void uniform1fv (in GLint location, in nsIWebGLArray v); - void uniform1iv (in GLint location, in nsIWebGLArray v); - void uniform2fv (in GLint location, in nsIWebGLArray v); - void uniform2iv (in GLint location, in nsIWebGLArray v); - void uniform3fv (in GLint location, in nsIWebGLArray v); - void uniform3iv (in GLint location, in nsIWebGLArray v); - void uniform4fv (in GLint location, in nsIWebGLArray v); - void uniform4iv (in GLint location, in nsIWebGLArray v); + void uniform1fv ([optional] in long dummy); + void uniform1iv ([optional] in long dummy); + void uniform2fv ([optional] in long dummy); + void uniform2iv ([optional] in long dummy); + void uniform3fv ([optional] in long dummy); + void uniform3iv ([optional] in long dummy); + void uniform4fv ([optional] in long dummy); + void uniform4iv ([optional] in long dummy); - // Modified. These are modified by replacing 'count' and 'value' with a nsIWebGLArray - void uniformMatrix2fv (in GLint location, in GLboolean transpose, in nsIWebGLArray value); - void uniformMatrix3fv (in GLint location, in GLboolean transpose, in nsIWebGLArray value); - void uniformMatrix4fv (in GLint location, in GLboolean transpose, in nsIWebGLArray value); + [noscript] void uniform1fv_array (in GLint location, in WebGLArrayPtr v); + [noscript] void uniform1iv_array (in GLint location, in WebGLArrayPtr v); + [noscript] void uniform2fv_array (in GLint location, in WebGLArrayPtr v); + [noscript] void uniform2iv_array (in GLint location, in WebGLArrayPtr v); + [noscript] void uniform3fv_array (in GLint location, in WebGLArrayPtr v); + [noscript] void uniform3iv_array (in GLint location, in WebGLArrayPtr v); + [noscript] void uniform4fv_array (in GLint location, in WebGLArrayPtr v); + [noscript] void uniform4iv_array (in GLint location, in WebGLArrayPtr v); + + // Modified. These are modified by replacing 'count' and 'value' with a WebGLArrayPtr + void uniformMatrix2fv ([optional] in long dummy); + void uniformMatrix3fv ([optional] in long dummy); + void uniformMatrix4fv ([optional] in long dummy); + + [noscript] void uniformMatrix2fv_array (in GLint location, in GLboolean transpose, in WebGLArrayPtr value); + [noscript] void uniformMatrix3fv_array (in GLint location, in GLboolean transpose, in WebGLArrayPtr value); + [noscript] void uniformMatrix4fv_array (in GLint location, in GLboolean transpose, in WebGLArrayPtr value); // Added API using top entry from the passed nsIWebGLMatrixStack //ZZ void glUniformMatrix (in GLint location, in GLboolean transpose, in nsIWebGLMatrixStack value); @@ -919,24 +841,24 @@ interface nsICanvasRenderingContextWebGL : nsISupports void useProgram (in nsIWebGLProgram program); void validateProgram (in nsIWebGLProgram program); - // Modified: All the glVertexAttrib*v forms below are modified by replacing 'values' with a nsIWebGLArray + // Modified: All the glVertexAttrib*v forms below are modified by replacing 'values' with a WebGLArrayPtr void vertexAttrib1f (in GLuint indx, in GLfloat x); void vertexAttrib2f (in GLuint indx, in GLfloat x, in GLfloat y); void vertexAttrib3f (in GLuint indx, in GLfloat x, in GLfloat y, in GLfloat z); void vertexAttrib4f (in GLuint indx, in GLfloat x, in GLfloat y, in GLfloat z, in GLfloat w); - void vertexAttrib1fv (in GLuint indx, in nsIWebGLArray values); - void vertexAttrib2fv (in GLuint indx, in nsIWebGLArray values); - void vertexAttrib3fv (in GLuint indx, in nsIWebGLArray values); - void vertexAttrib4fv (in GLuint indx, in nsIWebGLArray values); + void vertexAttrib1fv ([optional] in long dummy); + void vertexAttrib2fv ([optional] in long dummy); + void vertexAttrib3fv ([optional] in long dummy); + void vertexAttrib4fv ([optional] in long dummy); - // TBD - //void glVertexAttribPointer (in GLuint indx, GLint size, GLenum type, GLboolean normalized, - // GLsizei stride, const void* ptr); + [noscript] void vertexAttrib1fv_array (in GLuint indx, in WebGLArrayPtr values); + [noscript] void vertexAttrib2fv_array (in GLuint indx, in WebGLArrayPtr values); + [noscript] void vertexAttrib3fv_array (in GLuint indx, in WebGLArrayPtr values); + [noscript] void vertexAttrib4fv_array (in GLuint indx, in WebGLArrayPtr values); - // size is number of elements; type must match the bound vbo type; offset is in elements + // size is number of elements per attrib; offset, stride are in bytes void vertexAttribPointer (in GLuint idx, in GLint size, in GLenum type, in GLboolean normalized, in GLuint stride, in GLuint offset); void viewport (in GLint x, in GLint y, in GLsizei width, in GLsizei height); - }; diff --git a/js/src/xpconnect/src/dom_quickstubs.qsconf b/js/src/xpconnect/src/dom_quickstubs.qsconf index c8667ebce4a..c9a68e29ec3 100644 --- a/js/src/xpconnect/src/dom_quickstubs.qsconf +++ b/js/src/xpconnect/src/dom_quickstubs.qsconf @@ -88,47 +88,16 @@ members = [ # dom/interfaces/canvas # # nsIDOMCanvasRenderingContext2D + 'nsIDOMCanvasRenderingContext2D.*', # NOTE: attributes strokeStyle and fillStyle are nsIVariant - # NOTE: getImageData(), and putImageData() use + # NOTE: createImageDate(), getImageData(), and putImageData() use # GetCurrentNativeCallContext - 'nsIDOMCanvasRenderingContext2D.canvas', - 'nsIDOMCanvasRenderingContext2D.save', - 'nsIDOMCanvasRenderingContext2D.restore', - 'nsIDOMCanvasRenderingContext2D.scale', - 'nsIDOMCanvasRenderingContext2D.rotate', - 'nsIDOMCanvasRenderingContext2D.translate', - 'nsIDOMCanvasRenderingContext2D.transform', - 'nsIDOMCanvasRenderingContext2D.setTransform', - 'nsIDOMCanvasRenderingContext2D.globalAlpha', - 'nsIDOMCanvasRenderingContext2D.globalCompositeOperation', - 'nsIDOMCanvasRenderingContext2D.lineWidth', - 'nsIDOMCanvasRenderingContext2D.lineCap', - 'nsIDOMCanvasRenderingContext2D.lineJoin', - 'nsIDOMCanvasRenderingContext2D.miterLimit', - 'nsIDOMCanvasRenderingContext2D.clearRect', - 'nsIDOMCanvasRenderingContext2D.fillRect', - 'nsIDOMCanvasRenderingContext2D.strokeRect', - 'nsIDOMCanvasRenderingContext2D.beginPath', - 'nsIDOMCanvasRenderingContext2D.closePath', - 'nsIDOMCanvasRenderingContext2D.moveTo', - 'nsIDOMCanvasRenderingContext2D.lineTo', - 'nsIDOMCanvasRenderingContext2D.quadraticCurveTo', - 'nsIDOMCanvasRenderingContext2D.bezierCurveTo', - 'nsIDOMCanvasRenderingContext2D.arcTo', - 'nsIDOMCanvasRenderingContext2D.arc', - 'nsIDOMCanvasRenderingContext2D.rect', - 'nsIDOMCanvasRenderingContext2D.fill', - 'nsIDOMCanvasRenderingContext2D.stroke', - 'nsIDOMCanvasRenderingContext2D.clip', - 'nsIDOMCanvasRenderingContext2D.font', - 'nsIDOMCanvasRenderingContext2D.textAlign', - 'nsIDOMCanvasRenderingContext2D.textBaseline', - 'nsIDOMCanvasRenderingContext2D.fillText', - 'nsIDOMCanvasRenderingContext2D.strokeText', - 'nsIDOMCanvasRenderingContext2D.measureText', - 'nsIDOMCanvasRenderingContext2D.drawImage', - 'nsIDOMCanvasRenderingContext2D.isPointInPath', - 'nsIDOMTextMetrics.width', + '-nsIDOMCanvasRenderingContext2D.strokeStyle', + '-nsIDOMCanvasRenderingContext2D.fillStyle', + '-nsIDOMCanvasRenderingContext2D.createImageData', + '-nsIDOMCanvasRenderingContext2D.getImageData', + '-nsIDOMCanvasRenderingContext2D.putImageData', + 'nsIDOMTextMetrics.*', # dom/interfaces/core 'nsIDOMCharacterData.data', @@ -475,6 +444,31 @@ members = [ 'nsIDOMNSXPathExpression.evaluateWithContext', # dom/interfaces/xul - None. + + # webgl + 'nsICanvasRenderingContextWebGL.*', + # These all use GetCurrentNativeCallContext and should be + # custom-quickstubbed. + '-nsICanvasRenderingContextWebGL.getActiveAttrib', + '-nsICanvasRenderingContextWebGL.getActiveUniform', + '-nsICanvasRenderingContextWebGL.getParameter', + '-nsICanvasRenderingContextWebGL.getBufferParameteri', + '-nsICanvasRenderingContextWebGL.getBufferParameter', + '-nsICanvasRenderingContextWebGL.getFramebufferAttachmentParameteri', + '-nsICanvasRenderingContextWebGL.getFramebufferAttachmentParameter', + '-nsICanvasRenderingContextWebGL.getRenderbufferParameteri', + '-nsICanvasRenderingContextWebGL.getRenderbufferParameter', + '-nsICanvasRenderingContextWebGL.getProgrami', + '-nsICanvasRenderingContextWebGL.getProgramParameter', + '-nsICanvasRenderingContextWebGL.texParameterf', + '-nsICanvasRenderingContextWebGL.texParameteri', + '-nsICanvasRenderingContextWebGL.getTexParameterf', + '-nsICanvasRenderingContextWebGL.getTexParameteri', + '-nsICanvasRenderingContextWebGL.getUniform', + '-nsICanvasRenderingContextWebGL.getVertexAttrib', + '-nsICanvasRenderingContextWebGL.readPixels', + '-nsICanvasRenderingContextWebGL.getShaderi', + '-nsICanvasRenderingContextWebGL.getShaderParameter', ] # Most interfaces can be found by searching the includePath; to find @@ -490,7 +484,18 @@ irregularFilenames = { # stowaways 'nsIDOMTextMetrics': 'nsIDOMCanvasRenderingContext2D', + 'nsIDOMCanvasGradient': 'nsIDOMCanvasRenderingContext2D', + 'nsIDOMCanvasPattern': 'nsIDOMCanvasRenderingContext2D', 'nsIXPointerResult': 'nsIXPointer', + + 'nsIWebGLTexture': 'nsICanvasRenderingContextWebGL', + 'nsIWebGLBuffer': 'nsICanvasRenderingContextWebGL', + 'nsIWebGLProgram': 'nsICanvasRenderingContextWebGL', + 'nsIWebGLShader': 'nsICanvasRenderingContextWebGL', + 'nsIWebGLShaderArray': 'nsICanvasRenderingContextWebGL', + 'nsIWebGLFramebuffer': 'nsICanvasRenderingContextWebGL', + 'nsIWebGLRenderbuffer': 'nsICanvasRenderingContextWebGL', + 'nsIWebGLActiveInfo': 'nsICanvasRenderingContextWebGL', } customIncludes = [ @@ -498,7 +503,11 @@ customIncludes = [ 'nsIContent.h', 'nsIDocument.h', 'nsINodeList.h', - 'nsCSSPropertiesQS.h' + 'nsCSSPropertiesQS.h', + ] + +customQuickStubs = [ + 'CustomQS_WebGL.h' ] nsIDOMNode_GetChildNodes_customMethodCallCode = """ @@ -537,6 +546,16 @@ CSS2Properties_ = { 'canFail': True } +CUSTOM_QS = { + 'skipgen': True, + 'traceable': False +} + +CUSTOM_QS_TN = { + 'skipgen': True, + 'traceable': True +} + customMethodCalls = { 'nsIDOMNode_GetNextSibling': { 'thisType': 'nsINode', @@ -583,6 +602,26 @@ customMethodCalls = { 'code': nsIDOMStorage_Clear_customMethodCallCode }, 'nsIDOMCSS2Properties_': CSS2Properties_, - 'nsIDOMNSCSS2Properties_': CSS2Properties_ + 'nsIDOMNSCSS2Properties_': CSS2Properties_, + # WebGL + 'nsICanvasRenderingContextWebGL_BufferData': CUSTOM_QS, + 'nsICanvasRenderingContextWebGL_BufferSubData': CUSTOM_QS, + 'nsICanvasRenderingContextWebGL_TexImage2D': CUSTOM_QS, + 'nsICanvasRenderingContextWebGL_TexSubImage2D': CUSTOM_QS, + 'nsICanvasRenderingContextWebGL_Uniform1iv': CUSTOM_QS_TN, + 'nsICanvasRenderingContextWebGL_Uniform2iv': CUSTOM_QS_TN, + 'nsICanvasRenderingContextWebGL_Uniform3iv': CUSTOM_QS_TN, + 'nsICanvasRenderingContextWebGL_Uniform4iv': CUSTOM_QS_TN, + 'nsICanvasRenderingContextWebGL_Uniform1fv': CUSTOM_QS_TN, + 'nsICanvasRenderingContextWebGL_Uniform2fv': CUSTOM_QS_TN, + 'nsICanvasRenderingContextWebGL_Uniform3fv': CUSTOM_QS_TN, + 'nsICanvasRenderingContextWebGL_Uniform4fv': CUSTOM_QS_TN, + 'nsICanvasRenderingContextWebGL_UniformMatrix2fv': CUSTOM_QS_TN, + 'nsICanvasRenderingContextWebGL_UniformMatrix3fv': CUSTOM_QS_TN, + 'nsICanvasRenderingContextWebGL_UniformMatrix4fv': CUSTOM_QS_TN, + 'nsICanvasRenderingContextWebGL_VertexAttrib1fv': CUSTOM_QS, + 'nsICanvasRenderingContextWebGL_VertexAttrib2fv': CUSTOM_QS, + 'nsICanvasRenderingContextWebGL_VertexAttrib3fv': CUSTOM_QS, + 'nsICanvasRenderingContextWebGL_VertexAttrib4fv': CUSTOM_QS } diff --git a/js/src/xpconnect/src/qsgen.py b/js/src/xpconnect/src/qsgen.py index 89840471d0a..19fdf38fe87 100644 --- a/js/src/xpconnect/src/qsgen.py +++ b/js/src/xpconnect/src/qsgen.py @@ -326,8 +326,12 @@ def readConfigFile(filename, includePath, cachedir, traceable): # Stub all scriptable members of this interface. for member in iface.members: if member.kind in ('method', 'attribute') and not member.noscript: + cmc = conf.customMethodCalls.get(interfaceName + "_" + header.methodNativeName(member), None) + mayTrace = cmc is None or cmc.get('traceable', True) + addStubMember(iface.name + '.' + member.name, member, - traceable) + traceable and mayTrace) + if member.iface not in stubbedInterfaces: stubbedInterfaces.append(member.iface) else: @@ -342,13 +346,10 @@ def readConfigFile(filename, includePath, cachedir, traceable): if member in iface.stubMembers: raise UserError("Member %s is specified more than once." % memberId) - mayTrace = True - if member.noscript: - cmc = conf.customMethodCalls.get(interfaceName + "_" + header.methodNativeName(member), None) - if cmc is not None and cmc.get('skipgen', False): - # We're doing magic custom stuff for this, so pretend it's not noscript - member.noscript = False - mayTrace = False + + cmc = conf.customMethodCalls.get(interfaceName + "_" + header.methodNativeName(member), None) + mayTrace = cmc is None or cmc.get('traceable', True) + addStubMember(memberId, member, traceable and mayTrace) if member.iface not in stubbedInterfaces: stubbedInterfaces.append(member.iface)