diff --git a/content/canvas/src/CustomQS_WebGL.h b/content/canvas/src/CustomQS_WebGL.h index d53cf499498f..62c99085f5c5 100644 --- a/content/canvas/src/CustomQS_WebGL.h +++ b/content/canvas/src/CustomQS_WebGL.h @@ -42,6 +42,29 @@ #include "jstypedarray.h" +#define GET_INT32_ARG(var, index) \ + int32 var; \ + do { \ + if (!JS_ValueToECMAInt32(cx, argv[index], &(var))) \ + return JS_FALSE; \ + } while (0) + +#define GET_UINT32_ARG(var, index) \ + uint32 var; \ + do { \ + if (!JS_ValueToECMAUint32(cx, argv[index], &(var))) \ + return JS_FALSE; \ + } while (0) + +#define GET_OPTIONAL_UINT32_ARG(var, index) \ + uint32 var = 0; \ + do { \ + if (argc > index) \ + if (!JS_ValueToECMAUint32(cx, argv[index], &(var))) \ + return JS_FALSE; \ + } while (0) + + static inline bool helper_isInt32Array(JSObject *obj) { return obj->getClass() == &js::TypedArray::fastClasses[js::TypedArray::TYPE_INT32]; @@ -102,7 +125,7 @@ nsICanvasRenderingContextWebGL_BufferData(JSContext *cx, uintN argc, jsval *vp) { return JS_FALSE; } - + nsresult rv; if (wa) @@ -188,9 +211,8 @@ nsICanvasRenderingContextWebGL_BufferSubData(JSContext *cx, uintN argc, jsval *v /* * 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]]) + * TexImage2D(uint, int, uint, int, int, int, uint, uint, ArrayBufferView)\ + * TexImage2D(uint, int, uint, uint, uint, nsIDOMElement) */ static JSBool nsICanvasRenderingContextWebGL_TexImage2D(JSContext *cx, uintN argc, jsval *vp) @@ -208,71 +230,74 @@ nsICanvasRenderingContextWebGL_TexImage2D(JSContext *cx, uintN argc, jsval *vp) if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.addr(), nsnull)) return JS_FALSE; + // XXX we currently allow passing only 3 args to support the API. Eventually drop that. + // if (argc < 6 || argc == 7 || argc == 8) if (argc < 3) return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS); jsval *argv = JS_ARGV(cx, vp); - int32 intargs[8]; - JSObject *arg9 = nsnull; + // arguments common to all cases + GET_UINT32_ARG(argv0, 0); + GET_INT32_ARG(argv1, 1); - // 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 (argc > 2 && JSVAL_IS_OBJECT(argv[2])) { + // the old API. Eventually drop that. - 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; + if (NS_FAILED(rv)) return JS_FALSE; - // 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; - } + GET_OPTIONAL_UINT32_ARG(argv3, 3); + GET_OPTIONAL_UINT32_ARG(argv4, 4); - rv = self->TexImage2D_dom(intargs[0], intargs[1], elt, (WebGLboolean) intargs[3], (WebGLboolean) intargs[4]); - goto check_rv_and_return; - } - } + rv = self->TexImage2D_dom_old_API_deprecated(argv0, argv1, elt, argv3, argv4); + } else if (argc > 5 && JSVAL_IS_OBJECT(argv[5])) { + // implement the variants taking a DOMElement as argv[5] + GET_UINT32_ARG(argv2, 2); + GET_UINT32_ARG(argv3, 3); + GET_UINT32_ARG(argv4, 4); - // 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])) + nsIDOMElement *elt; + xpc_qsSelfRef eltRef; + rv = xpc_qsUnwrapArg(cx, argv[5], &elt, &eltRef.ptr, &argv[5]); + if (NS_FAILED(rv)) return JS_FALSE; + + rv = self->TexImage2D_dom(argv0, argv1, argv2, argv3, argv4, elt); + } else if (argc > 8 && JSVAL_IS_OBJECT(argv[8])) { + // implement the variants taking a buffer/array as argv[8] + GET_UINT32_ARG(argv2, 2); + GET_INT32_ARG(argv3, 3); + GET_INT32_ARG(argv4, 4); + GET_INT32_ARG(argv5, 5); + GET_UINT32_ARG(argv6, 6); + GET_UINT32_ARG(argv7, 7); + + JSObject *argv8 = JSVAL_TO_OBJECT(argv[8]); + + // then try to grab either a js::ArrayBuffer, js::TypedArray, or null + if (argv8 == nsnull) { + rv = self->TexImage2D_buf(argv0, argv1, argv2, argv3, + argv4, argv5, argv6, argv7, + nsnull); + } else if (js_IsArrayBuffer(argv8)) { + rv = self->TexImage2D_buf(argv0, argv1, argv2, argv3, + argv4, argv5, argv6, argv7, + js::ArrayBuffer::fromJSObject(argv8)); + } else if (js_IsTypedArray(argv8)) { + rv = self->TexImage2D_array(argv0, argv1, argv2, argv3, + argv4, argv5, argv6, argv7, + js::TypedArray::fromJSObject(argv8)); + } else { + xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 8); 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, js::TypedArray, or null - arg9 = JSVAL_TO_OBJECT(argv[8]); - if (arg9 == nsnull) { - rv = self->TexImage2D_buf(intargs[0], intargs[1], intargs[2], intargs[3], - intargs[4], intargs[5], intargs[6], intargs[7], - nsnull); - } else if (js_IsArrayBuffer(arg9)) { - rv = self->TexImage2D_buf(intargs[0], intargs[1], intargs[2], intargs[3], - intargs[4], intargs[5], intargs[6], intargs[7], - js::ArrayBuffer::fromJSObject(arg9)); - } else if (js_IsTypedArray(arg9)) { - rv = self->TexImage2D_array(intargs[0], intargs[1], intargs[2], intargs[3], - intargs[4], intargs[5], intargs[6], intargs[7], - js::TypedArray::fromJSObject(arg9)); + } } else { - xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 8); + xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS); return JS_FALSE; } -check_rv_and_return: if (NS_FAILED(rv)) return xpc_qsThrowMethodFailed(cx, rv, vp); @@ -280,11 +305,9 @@ check_rv_and_return: 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]]) +/* TexSubImage2D takes: + * TexSubImage2D(uint, int, int, int, int, int, uint, uint, ArrayBufferView) + * TexSubImage2D(uint, int, int, int, uint, uint, nsIDOMElement) */ static JSBool nsICanvasRenderingContextWebGL_TexSubImage2D(JSContext *cx, uintN argc, jsval *vp) @@ -302,80 +325,51 @@ nsICanvasRenderingContextWebGL_TexSubImage2D(JSContext *cx, uintN argc, jsval *v if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.addr(), nsnull)) return JS_FALSE; - if (argc < 7) + if (argc < 7 || argc == 8) return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS); jsval *argv = JS_ARGV(cx, vp); - int32 intargs[9]; + // arguments common to all cases + GET_UINT32_ARG(argv0, 0); + GET_INT32_ARG(argv1, 1); + GET_INT32_ARG(argv2, 2); + GET_INT32_ARG(argv3, 3); - // 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 (argc > 6 && JSVAL_IS_OBJECT(argv[6])) { + // implement the variants taking a DOMElement as argv[6] + GET_UINT32_ARG(argv4, 4); + GET_UINT32_ARG(argv5, 5); - if (JSVAL_IS_OBJECT(argv[6])) { - // try to make this a nsIDOMElement nsIDOMElement *elt; xpc_qsSelfRef eltRef; + rv = xpc_qsUnwrapArg(cx, argv[6], &elt, &eltRef.ptr, &argv[6]); + if (NS_FAILED(rv)) return JS_FALSE; - // these are two optinal args, default to 0 - intargs[7] = 0; - intargs[8] = 0; + rv = self->TexSubImage2D_dom(argv0, argv1, argv2, argv3, argv4, argv5, elt); + } else if (argc > 8 && JSVAL_IS_OBJECT(argv[8])) { + // implement the variants taking a buffer/array as argv[8] + GET_INT32_ARG(argv4, 4); + GET_INT32_ARG(argv5, 5); + GET_UINT32_ARG(argv6, 6); + GET_UINT32_ARG(argv7, 7); - // 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, (WebGLboolean) intargs[7], (WebGLboolean) 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])) + JSObject *argv8 = JSVAL_TO_OBJECT(argv[8]); + // try to grab either a js::ArrayBuffer or js::TypedArray + if (js_IsArrayBuffer(argv8)) { + rv = self->TexSubImage2D_buf(argv0, argv1, argv2, argv3, + argv4, argv5, argv6, argv7, + js::ArrayBuffer::fromJSObject(argv8)); + } else if (js_IsTypedArray(argv8)) { + rv = self->TexSubImage2D_array(argv0, argv1, argv2, argv3, + argv4, argv5, argv6, argv7, + js::TypedArray::fromJSObject(argv8)); + } else { + xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 8); return JS_FALSE; - } - - if (JSVAL_IS_PRIMITIVE(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); + xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS); return JS_FALSE; } @@ -563,7 +557,7 @@ helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv(JSContext *cx, uintN ar xpc_qsThrowBadArg(cx, rv, vp, 0); return JS_FALSE; } - + int32 transpose; if (!JS_ValueToECMAInt32(cx, argv[1], &transpose)) return JS_FALSE; diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index 97c8385f5499..6f5eb7f15b07 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -2806,21 +2806,53 @@ WebGLContext::TexImage2D_array(WebGLenum target, WebGLint level, WebGLenum inter } NS_IMETHODIMP -WebGLContext::TexImage2D_dom(WebGLenum target, WebGLint level, - nsIDOMElement *elt, - WebGLboolean flipY, WebGLboolean premultiplyAlpha) +WebGLContext::TexImage2D_dom(WebGLenum target, WebGLint level, WebGLenum internalformat, + WebGLenum format, GLenum type, nsIDOMElement *elt) { nsRefPtr isurf; + nsresult rv = DOMElementToImageSurface(elt, getter_AddRefs(isurf), + PR_FALSE/*flipY*/, PR_FALSE/*premultiplyAlpha*/); + if (NS_FAILED(rv)) + return rv; + + NS_ASSERTION(isurf->Stride() == isurf->Width() * 4, "Bad stride!"); + + PRUint32 byteLength = isurf->Stride() * isurf->Height(); + + return TexImage2D_base(target, level, internalformat, + isurf->Width(), isurf->Height(), 0, + format, type, + isurf->Data(), byteLength); +} + +NS_IMETHODIMP +WebGLContext::TexImage2D_dom_old_API_deprecated(WebGLenum target, WebGLint level, nsIDOMElement *elt, + PRBool flipY, PRBool premultiplyAlpha) +{ + static PRBool firsttime = PR_TRUE; + + if (firsttime) { + LogMessage("The WebGL spec changed, TexImage2D is now taking at least 6 parameters, please " + "adapt your JavaScript code as support for the old API will soon be dropped!"); + firsttime = PR_FALSE; + } + + nsRefPtr isurf; + nsresult rv = DOMElementToImageSurface(elt, getter_AddRefs(isurf), flipY, premultiplyAlpha); if (NS_FAILED(rv)) return rv; + NS_ASSERTION(isurf->Stride() == isurf->Width() * 4, "Bad stride!"); + + PRUint32 byteLength = isurf->Stride() * isurf->Height(); + 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()); + isurf->Data(), byteLength); } NS_IMETHODIMP @@ -2948,22 +2980,23 @@ WebGLContext::TexSubImage2D_array(WebGLenum target, WebGLint level, NS_IMETHODIMP WebGLContext::TexSubImage2D_dom(WebGLenum target, WebGLint level, WebGLint xoffset, WebGLint yoffset, - WebGLsizei width, WebGLsizei height, - nsIDOMElement *elt, - WebGLboolean flipY, WebGLboolean premultiplyAlpha) + WebGLenum format, WebGLenum type, + nsIDOMElement *elt) { nsRefPtr isurf; nsresult rv = DOMElementToImageSurface(elt, getter_AddRefs(isurf), - flipY, premultiplyAlpha); + PR_FALSE/*flipY*/, PR_FALSE/*premultiplyAlpha*/); if (NS_FAILED(rv)) return rv; + PRUint32 byteLength = isurf->Stride() * isurf->Height(); + return TexSubImage2D_base(target, level, xoffset, yoffset, - width, height, + isurf->Width(), isurf->Height(), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, - isurf->Data(), isurf->Stride() * isurf->Height()); + isurf->Data(), byteLength); } #if 0 diff --git a/dom/interfaces/canvas/nsICanvasRenderingContextWebGL.idl b/dom/interfaces/canvas/nsICanvasRenderingContextWebGL.idl index 87b33091275a..0fff2cc1c19b 100644 --- a/dom/interfaces/canvas/nsICanvasRenderingContextWebGL.idl +++ b/dom/interfaces/canvas/nsICanvasRenderingContextWebGL.idl @@ -745,9 +745,11 @@ interface nsICanvasRenderingContextWebGL : nsISupports in WebGLsizei width, in WebGLsizei height, in WebGLint border, in WebGLenum format, in WebGLenum type, in WebGLArrayPtr pixels); // HTMLImageElement, HTMLCanvasElement, HTMLVideoElement - [noscript] void texImage2D_dom(in WebGLenum target, in WebGLint level, in nsIDOMElement element, - [optional] in WebGLboolean premultiply, [optional] in WebGLboolean asPremultipliedAlpha); - + [noscript] void texImage2D_dom(in WebGLenum target, in WebGLint level, in WebGLenum internalformat, + in WebGLenum format, in WebGLenum type, in nsIDOMElement element); + // XXX the old API. Eventually drop that. + [noscript] void TexImage2D_dom_old_API_deprecated(in WebGLenum target, in WebGLint level, + in nsIDOMElement element, in PRBool flipY, in PRBool premultiplyAlpha); void texSubImage2D([optional] in long dummy); [noscript] void texSubImage2D_buf(in WebGLenum target, in WebGLint level, @@ -758,9 +760,8 @@ interface nsICanvasRenderingContextWebGL : nsISupports in WebGLenum format, in WebGLenum type, in WebGLArrayPtr pixels); // HTMLImageElement, HTMLCanvasElement, HTMLVideoElement [noscript] void texSubImage2D_dom(in WebGLenum target, in WebGLint level, - in WebGLint xoffset, in WebGLint yoffset, in WebGLsizei width, in WebGLsizei height, - in nsIDOMElement element, - [optional] in WebGLboolean premultiply, [optional] in WebGLboolean asPremultipliedAlpha); + in WebGLint xoffset, in WebGLint yoffset, in WebGLenum format, in WebGLenum type, + in nsIDOMElement element); // Modified: This replaces glTexParameterf, glTexParameterfv, glTexParameteri and glTexParameteriv void texParameterf(in WebGLenum target, in WebGLenum pname, in WebGLfloat param);