From 5efb5489a484f93b207525984da618187b1e3ba2 Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Thu, 23 Oct 2014 15:10:57 -0700 Subject: [PATCH] Bug 1088345 - Don't run GL commands that may cause non-OOM errors. - r=kamidphish --- dom/canvas/WebGLContext.h | 225 +++++++++-------- dom/canvas/WebGLContextGL.cpp | 377 +++++++++++++++++----------- dom/canvas/WebGLContextValidate.cpp | 221 ++++++++++------ dom/canvas/WebGLContextVertices.cpp | 113 ++++++--- dom/canvas/WebGLVertexArray.cpp | 20 +- dom/canvas/WebGLVertexArray.h | 2 +- 6 files changed, 580 insertions(+), 378 deletions(-) diff --git a/dom/canvas/WebGLContext.h b/dom/canvas/WebGLContext.h index 6a10cfe38c2f..644235828a42 100644 --- a/dom/canvas/WebGLContext.h +++ b/dom/canvas/WebGLContext.h @@ -610,172 +610,180 @@ public: } - void Uniform1i(WebGLUniformLocation* location, GLint x); - void Uniform2i(WebGLUniformLocation* location, GLint x, GLint y); - void Uniform3i(WebGLUniformLocation* location, GLint x, GLint y, - GLint z); - void Uniform4i(WebGLUniformLocation* location, GLint x, GLint y, - GLint z, GLint w); + void Uniform1i(WebGLUniformLocation* loc, GLint x); + void Uniform2i(WebGLUniformLocation* loc, GLint x, GLint y); + void Uniform3i(WebGLUniformLocation* loc, GLint x, GLint y, GLint z); + void Uniform4i(WebGLUniformLocation* loc, GLint x, GLint y, GLint z, + GLint w); - void Uniform1f(WebGLUniformLocation* location, GLfloat x); - void Uniform2f(WebGLUniformLocation* location, GLfloat x, GLfloat y); - void Uniform3f(WebGLUniformLocation* location, GLfloat x, GLfloat y, - GLfloat z); - void Uniform4f(WebGLUniformLocation* location, GLfloat x, GLfloat y, - GLfloat z, GLfloat w); + void Uniform1f(WebGLUniformLocation* loc, GLfloat x); + void Uniform2f(WebGLUniformLocation* loc, GLfloat x, GLfloat y); + void Uniform3f(WebGLUniformLocation* loc, GLfloat x, GLfloat y, GLfloat z); + void Uniform4f(WebGLUniformLocation* loc, GLfloat x, GLfloat y, GLfloat z, + GLfloat w); - void Uniform1iv(WebGLUniformLocation* location, - const dom::Int32Array& arr) { + // Int array + void Uniform1iv(WebGLUniformLocation* loc, const dom::Int32Array& arr) { arr.ComputeLengthAndData(); - Uniform1iv_base(location, arr.Length(), arr.Data()); + Uniform1iv_base(loc, arr.Length(), arr.Data()); } - void Uniform1iv(WebGLUniformLocation* location, - const dom::Sequence& arr) { - Uniform1iv_base(location, arr.Length(), arr.Elements()); + void Uniform1iv(WebGLUniformLocation* loc, + const dom::Sequence& arr) + { + Uniform1iv_base(loc, arr.Length(), arr.Elements()); } - void Uniform1iv_base(WebGLUniformLocation* location, uint32_t arrayLength, + void Uniform1iv_base(WebGLUniformLocation* loc, size_t arrayLength, const GLint* data); - void Uniform2iv(WebGLUniformLocation* location, - const dom::Int32Array& arr) { + void Uniform2iv(WebGLUniformLocation* loc, const dom::Int32Array& arr) { arr.ComputeLengthAndData(); - Uniform2iv_base(location, arr.Length(), arr.Data()); + Uniform2iv_base(loc, arr.Length(), arr.Data()); } - void Uniform2iv(WebGLUniformLocation* location, - const dom::Sequence& arr) { - Uniform2iv_base(location, arr.Length(), arr.Elements()); + void Uniform2iv(WebGLUniformLocation* loc, + const dom::Sequence& arr) + { + Uniform2iv_base(loc, arr.Length(), arr.Elements()); } - void Uniform2iv_base(WebGLUniformLocation* location, uint32_t arrayLength, + void Uniform2iv_base(WebGLUniformLocation* loc, size_t arrayLength, const GLint* data); - void Uniform3iv(WebGLUniformLocation* location, - const dom::Int32Array& arr) { + void Uniform3iv(WebGLUniformLocation* loc, const dom::Int32Array& arr) { arr.ComputeLengthAndData(); - Uniform3iv_base(location, arr.Length(), arr.Data()); + Uniform3iv_base(loc, arr.Length(), arr.Data()); } - void Uniform3iv(WebGLUniformLocation* location, - const dom::Sequence& arr) { - Uniform3iv_base(location, arr.Length(), arr.Elements()); + void Uniform3iv(WebGLUniformLocation* loc, + const dom::Sequence& arr) + { + Uniform3iv_base(loc, arr.Length(), arr.Elements()); } - void Uniform3iv_base(WebGLUniformLocation* location, uint32_t arrayLength, + void Uniform3iv_base(WebGLUniformLocation* loc, size_t arrayLength, const GLint* data); - void Uniform4iv(WebGLUniformLocation* location, - const dom::Int32Array& arr) { + void Uniform4iv(WebGLUniformLocation* loc, const dom::Int32Array& arr) { arr.ComputeLengthAndData(); - Uniform4iv_base(location, arr.Length(), arr.Data()); + Uniform4iv_base(loc, arr.Length(), arr.Data()); } - void Uniform4iv(WebGLUniformLocation* location, - const dom::Sequence& arr) { - Uniform4iv_base(location, arr.Length(), arr.Elements()); + void Uniform4iv(WebGLUniformLocation* loc, + const dom::Sequence& arr) + { + Uniform4iv_base(loc, arr.Length(), arr.Elements()); } - void Uniform4iv_base(WebGLUniformLocation* location, uint32_t arrayLength, + void Uniform4iv_base(WebGLUniformLocation* loc, size_t arrayLength, const GLint* data); - void Uniform1fv(WebGLUniformLocation* location, - const dom::Float32Array& arr) { + // Float array + void Uniform1fv(WebGLUniformLocation* loc, const dom::Float32Array& arr) { arr.ComputeLengthAndData(); - Uniform1fv_base(location, arr.Length(), arr.Data()); + Uniform1fv_base(loc, arr.Length(), arr.Data()); } - void Uniform1fv(WebGLUniformLocation* location, - const dom::Sequence& arr) { - Uniform1fv_base(location, arr.Length(), arr.Elements()); + void Uniform1fv(WebGLUniformLocation* loc, + const dom::Sequence& arr) + { + Uniform1fv_base(loc, arr.Length(), arr.Elements()); } - void Uniform1fv_base(WebGLUniformLocation* location, uint32_t arrayLength, + void Uniform1fv_base(WebGLUniformLocation* loc, size_t arrayLength, const GLfloat* data); - void Uniform2fv(WebGLUniformLocation* location, - const dom::Float32Array& arr) { + void Uniform2fv(WebGLUniformLocation* loc, const dom::Float32Array& arr) { arr.ComputeLengthAndData(); - Uniform2fv_base(location, arr.Length(), arr.Data()); + Uniform2fv_base(loc, arr.Length(), arr.Data()); } - void Uniform2fv(WebGLUniformLocation* location, - const dom::Sequence& arr) { - Uniform2fv_base(location, arr.Length(), arr.Elements()); + void Uniform2fv(WebGLUniformLocation* loc, + const dom::Sequence& arr) + { + Uniform2fv_base(loc, arr.Length(), arr.Elements()); } - void Uniform2fv_base(WebGLUniformLocation* location, uint32_t arrayLength, + void Uniform2fv_base(WebGLUniformLocation* loc, size_t arrayLength, const GLfloat* data); - void Uniform3fv(WebGLUniformLocation* location, - const dom::Float32Array& arr) { + void Uniform3fv(WebGLUniformLocation* loc, const dom::Float32Array& arr) { arr.ComputeLengthAndData(); - Uniform3fv_base(location, arr.Length(), arr.Data()); + Uniform3fv_base(loc, arr.Length(), arr.Data()); } - void Uniform3fv(WebGLUniformLocation* location, - const dom::Sequence& arr) { - Uniform3fv_base(location, arr.Length(), arr.Elements()); + void Uniform3fv(WebGLUniformLocation* loc, + const dom::Sequence& arr) + { + Uniform3fv_base(loc, arr.Length(), arr.Elements()); } - void Uniform3fv_base(WebGLUniformLocation* location, uint32_t arrayLength, + void Uniform3fv_base(WebGLUniformLocation* loc, size_t arrayLength, const GLfloat* data); - void Uniform4fv(WebGLUniformLocation* location, - const dom::Float32Array& arr) { + void Uniform4fv(WebGLUniformLocation* loc, const dom::Float32Array& arr) { arr.ComputeLengthAndData(); - Uniform4fv_base(location, arr.Length(), arr.Data()); + Uniform4fv_base(loc, arr.Length(), arr.Data()); } - void Uniform4fv(WebGLUniformLocation* location, - const dom::Sequence& arr) { - Uniform4fv_base(location, arr.Length(), arr.Elements()); + void Uniform4fv(WebGLUniformLocation* loc, + const dom::Sequence& arr) + { + Uniform4fv_base(loc, arr.Length(), arr.Elements()); } - void Uniform4fv_base(WebGLUniformLocation* location, uint32_t arrayLength, + void Uniform4fv_base(WebGLUniformLocation* loc, size_t arrayLength, const GLfloat* data); - void UniformMatrix2fv(WebGLUniformLocation* location, - WebGLboolean transpose, - const dom::Float32Array &value) { + // Matrix + void UniformMatrix2fv(WebGLUniformLocation* loc, WebGLboolean transpose, + const dom::Float32Array& value) + { value.ComputeLengthAndData(); - UniformMatrix2fv_base(location, transpose, value.Length(), value.Data()); + UniformMatrix2fv_base(loc, transpose, value.Length(), value.Data()); } - void UniformMatrix2fv(WebGLUniformLocation* location, - WebGLboolean transpose, - const dom::Sequence &value) { - UniformMatrix2fv_base(location, transpose, value.Length(), + void UniformMatrix2fv(WebGLUniformLocation* loc, WebGLboolean transpose, + const dom::Sequence& value) + { + UniformMatrix2fv_base(loc, transpose, value.Length(), value.Elements()); } - void UniformMatrix2fv_base(WebGLUniformLocation* location, - WebGLboolean transpose, uint32_t arrayLength, + void UniformMatrix2fv_base(WebGLUniformLocation* loc, + WebGLboolean transpose, size_t arrayLength, const float* data); - void UniformMatrix3fv(WebGLUniformLocation* location, - WebGLboolean transpose, - const dom::Float32Array &value) { + void UniformMatrix3fv(WebGLUniformLocation* loc, WebGLboolean transpose, + const dom::Float32Array& value) + { value.ComputeLengthAndData(); - UniformMatrix3fv_base(location, transpose, value.Length(), value.Data()); + UniformMatrix3fv_base(loc, transpose, value.Length(), value.Data()); } - void UniformMatrix3fv(WebGLUniformLocation* location, - WebGLboolean transpose, - const dom::Sequence &value) { - UniformMatrix3fv_base(location, transpose, value.Length(), - value.Elements()); + void UniformMatrix3fv(WebGLUniformLocation* loc, WebGLboolean transpose, + const dom::Sequence& value) + { + UniformMatrix3fv_base(loc, transpose, value.Length(), value.Elements()); } - void UniformMatrix3fv_base(WebGLUniformLocation* location, - WebGLboolean transpose, uint32_t arrayLength, + void UniformMatrix3fv_base(WebGLUniformLocation* loc, + WebGLboolean transpose, size_t arrayLength, const float* data); - void UniformMatrix4fv(WebGLUniformLocation* location, - WebGLboolean transpose, - const dom::Float32Array &value) { + void UniformMatrix4fv(WebGLUniformLocation* loc, WebGLboolean transpose, + const dom::Float32Array& value) + { value.ComputeLengthAndData(); - UniformMatrix4fv_base(location, transpose, value.Length(), value.Data()); + UniformMatrix4fv_base(loc, transpose, value.Length(), value.Data()); } - void UniformMatrix4fv(WebGLUniformLocation* location, - WebGLboolean transpose, - const dom::Sequence &value) { - UniformMatrix4fv_base(location, transpose, value.Length(), + void UniformMatrix4fv(WebGLUniformLocation* loc, WebGLboolean transpose, + const dom::Sequence& value) + { + UniformMatrix4fv_base(loc, transpose, value.Length(), value.Elements()); } - void UniformMatrix4fv_base(WebGLUniformLocation* location, - WebGLboolean transpose, uint32_t arrayLength, + void UniformMatrix4fv_base(WebGLUniformLocation* loc, + WebGLboolean transpose, size_t arrayLength, const float* data); void UseProgram(WebGLProgram *prog); bool ValidateAttribArraySetter(const char* name, uint32_t cnt, uint32_t arrayLength); - bool ValidateUniformArraySetter(const char* name, uint32_t expectedElemSize, WebGLUniformLocation *location_object, - GLint& location, uint32_t& numElementsToUpload, uint32_t arrayLength); - bool ValidateUniformMatrixArraySetter(const char* name, int dim, WebGLUniformLocation *location_object, - GLint& location, uint32_t& numElementsToUpload, uint32_t arrayLength, - WebGLboolean aTranspose); - bool ValidateUniformSetter(const char* name, WebGLUniformLocation *location_object, GLint& location); + bool ValidateUniformSetter(WebGLUniformLocation* loc, uint8_t setterSize, + GLenum setterType, const char* info, + GLuint* out_rawLoc); + bool ValidateUniformArraySetter(WebGLUniformLocation* loc, + uint8_t setterElemSize, GLenum setterType, + size_t setterArraySize, const char* info, + GLuint* out_rawLoc, + GLsizei* out_numElementsToUpload); + bool ValidateUniformMatrixArraySetter(WebGLUniformLocation* loc, + uint8_t setterDims, GLenum setterType, + size_t setterArraySize, + bool setterTranspose, + const char* info, GLuint* out_rawLoc, + GLsizei* out_numElementsToUpload); void ValidateProgram(WebGLProgram *prog); bool ValidateUniformLocation(const char* info, WebGLUniformLocation *location_object); bool ValidateSamplerUniformSetter(const char* info, @@ -1047,6 +1055,12 @@ protected: int32_t mGLMaxDrawBuffers; uint32_t mGLMaxTransformFeedbackSeparateAttribs; +public: + GLuint MaxVertexAttribs() const { + return mGLMaxVertexAttribs; + } + +protected: // Represents current status of the context with respect to context loss. // That is, whether the context is lost, and what part of the context loss // process we currently are at. @@ -1115,7 +1129,6 @@ protected: WebGLTexImageFunc func, WebGLTexDimensions dims); bool ValidateDrawModeEnum(GLenum mode, const char *info); - bool ValidateAttribIndex(GLuint index, const char *info); bool ValidateStencilParamsForDrawCall(); bool ValidateGLSLVariableName(const nsAString& name, const char *info); diff --git a/dom/canvas/WebGLContextGL.cpp b/dom/canvas/WebGLContextGL.cpp index 75b3ba44e110..b2047d5f9d8b 100644 --- a/dom/canvas/WebGLContextGL.cpp +++ b/dom/canvas/WebGLContextGL.cpp @@ -120,9 +120,8 @@ WebGLContext::AttachShader(WebGLProgram *program, WebGLShader *shader) return ErrorInvalidOperation("attachShader: shader is already attached"); } - void -WebGLContext::BindAttribLocation(WebGLProgram *prog, GLuint location, +WebGLContext::BindAttribLocation(WebGLProgram* prog, GLuint location, const nsAString& name) { if (IsContextLost()) @@ -136,11 +135,15 @@ WebGLContext::BindAttribLocation(WebGLProgram *prog, GLuint location, if (!ValidateGLSLVariableName(name, "bindAttribLocation")) return; - if (!ValidateAttribIndex(location, "bindAttribLocation")) - return; + if (location >= MaxVertexAttribs()) { + return ErrorInvalidValue("bindAttribLocation: `location` must be less" + " than MAX_VERTEX_ATTRIBS."); + } if (StringBeginsWith(name, NS_LITERAL_STRING("gl_"))) - return ErrorInvalidOperation("bindAttribLocation: can't set the location of a name that starts with 'gl_'"); + return ErrorInvalidOperation("bindAttribLocation: can't set the" + " location of a name that starts with" + " 'gl_'."); NS_LossyConvertUTF16toASCII cname(name); nsCString mappedName; @@ -427,6 +430,17 @@ WebGLContext::CopyTexSubImage2D_base(TexImageTarget texImageTarget, // this should never fail, validation happened earlier. MOZ_ASSERT(effectiveInternalFormat != LOCAL_GL_NONE); + const bool widthOrHeightIsZero = (width == 0 || height == 0); + if (gl->WorkAroundDriverBugs() && + sub && widthOrHeightIsZero) + { + // NV driver on Linux complains that CopyTexSubImage2D(level=0, + // xoffset=0, yoffset=2, x=0, y=0, width=0, height=0) from a 300x150 FB + // to a 0x2 texture. This a useless thing to do, but technically legal. + // NV331.38 generates INVALID_VALUE. + return DummyFramebufferOperation(info); + } + // check if the memory size of this texture may change with this call bool sizeMayChange = !sub; if (!sub && tex->HasImageInfoAt(texImageTarget, level)) { @@ -879,9 +893,19 @@ WebGLContext::GetActiveAttrib(WebGLProgram *prog, uint32_t index) return nullptr; MakeContextCurrent(); + GLuint progname = prog->GLName(); + + GLuint activeAttribs = 0; + gl->fGetProgramiv(progname, LOCAL_GL_ACTIVE_ATTRIBUTES, + (GLint*)&activeAttribs); + if (index >= activeAttribs) { + ErrorInvalidValue("`index` (%i) must be less than ACTIVE_ATTRIBUTES" + " (%i).", + index, activeAttribs); + return nullptr; + } GLint len = 0; - GLuint progname = prog->GLName();; gl->fGetProgramiv(progname, LOCAL_GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &len); if (len == 0) return nullptr; @@ -977,9 +1001,19 @@ WebGLContext::GetActiveUniform(WebGLProgram *prog, uint32_t index) return nullptr; MakeContextCurrent(); + GLuint progname = prog->GLName(); + + GLuint activeUniforms = 0; + gl->fGetProgramiv(progname, LOCAL_GL_ACTIVE_UNIFORMS, + (GLint*)&activeUniforms); + if (index >= activeUniforms) { + ErrorInvalidValue("`index` (%i) must be less than ACTIVE_UNIFORMS" + " (%i).", + index, activeUniforms); + return nullptr; + } GLint len = 0; - GLuint progname = prog->GLName(); gl->fGetProgramiv(progname, LOCAL_GL_ACTIVE_UNIFORM_MAX_LENGTH, &len); if (len == 0) return nullptr; @@ -1069,8 +1103,14 @@ WebGLContext::GetBufferParameter(GLenum target, GLenum pname) if (IsContextLost()) return JS::NullValue(); - if (target != LOCAL_GL_ARRAY_BUFFER && target != LOCAL_GL_ELEMENT_ARRAY_BUFFER) { - ErrorInvalidEnumInfo("getBufferParameter: target", target); + + WebGLRefPtr* slot = GetBufferSlotByTarget(target, + "getBufferParameter"); + if (!slot) + return JS::NullValue(); + + if (!*slot) { + ErrorInvalidOperation("No buffer bound to `target` (0x%4x).", target); return JS::NullValue(); } @@ -2690,286 +2730,322 @@ WebGLContext::SurfaceFromElementResultToImageSurface(nsLayoutUtils::SurfaceFromE return NS_OK; } - +//////////////////////////////////////////////////////////////////////////////// +// Uniform setters. void -WebGLContext::Uniform1i(WebGLUniformLocation *location_object, GLint a1) +WebGLContext::Uniform1i(WebGLUniformLocation* loc, GLint a1) { - GLint location; - if (!ValidateUniformSetter("Uniform1i", location_object, location)) + GLuint rawLoc; + if (!ValidateUniformSetter(loc, 1, LOCAL_GL_INT, "uniform1i", &rawLoc)) return; // Only uniform1i can take sampler settings. - if (!ValidateSamplerUniformSetter("Uniform1i", location_object, a1)) + if (!ValidateSamplerUniformSetter("Uniform1i", loc, a1)) return; MakeContextCurrent(); - gl->fUniform1i(location, a1); + gl->fUniform1i(rawLoc, a1); } void -WebGLContext::Uniform2i(WebGLUniformLocation *location_object, GLint a1, - GLint a2) +WebGLContext::Uniform2i(WebGLUniformLocation* loc, GLint a1, GLint a2) { - GLint location; - if (!ValidateUniformSetter("Uniform2i", location_object, location)) + GLuint rawLoc; + if (!ValidateUniformSetter(loc, 2, LOCAL_GL_INT, "uniform2i", &rawLoc)) return; MakeContextCurrent(); - gl->fUniform2i(location, a1, a2); + gl->fUniform2i(rawLoc, a1, a2); } void -WebGLContext::Uniform3i(WebGLUniformLocation *location_object, GLint a1, - GLint a2, GLint a3) +WebGLContext::Uniform3i(WebGLUniformLocation* loc, GLint a1, GLint a2, GLint a3) { - GLint location; - if (!ValidateUniformSetter("Uniform3i", location_object, location)) + GLuint rawLoc; + if (!ValidateUniformSetter(loc, 3, LOCAL_GL_INT, "uniform3i", &rawLoc)) return; MakeContextCurrent(); - gl->fUniform3i(location, a1, a2, a3); + gl->fUniform3i(rawLoc, a1, a2, a3); } void -WebGLContext::Uniform4i(WebGLUniformLocation *location_object, GLint a1, - GLint a2, GLint a3, GLint a4) +WebGLContext::Uniform4i(WebGLUniformLocation* loc, GLint a1, GLint a2, GLint a3, + GLint a4) { - GLint location; - if (!ValidateUniformSetter("Uniform4i", location_object, location)) + GLuint rawLoc; + if (!ValidateUniformSetter(loc, 4, LOCAL_GL_INT, "uniform4i", &rawLoc)) return; MakeContextCurrent(); - gl->fUniform4i(location, a1, a2, a3, a4); + gl->fUniform4i(rawLoc, a1, a2, a3, a4); } void -WebGLContext::Uniform1f(WebGLUniformLocation *location_object, GLfloat a1) +WebGLContext::Uniform1f(WebGLUniformLocation* loc, GLfloat a1) { - GLint location; - if (!ValidateUniformSetter("Uniform1f", location_object, location)) + GLuint rawLoc; + if (!ValidateUniformSetter(loc, 1, LOCAL_GL_FLOAT, "uniform1f", &rawLoc)) return; + MakeContextCurrent(); - gl->fUniform1f(location, a1); + gl->fUniform1f(rawLoc, a1); } void -WebGLContext::Uniform2f(WebGLUniformLocation *location_object, GLfloat a1, - GLfloat a2) +WebGLContext::Uniform2f(WebGLUniformLocation* loc, GLfloat a1, GLfloat a2) { - GLint location; - if (!ValidateUniformSetter("Uniform2f", location_object, location)) + GLuint rawLoc; + if (!ValidateUniformSetter(loc, 2, LOCAL_GL_FLOAT, "uniform2f", &rawLoc)) return; + MakeContextCurrent(); - gl->fUniform2f(location, a1, a2); + gl->fUniform2f(rawLoc, a1, a2); } void -WebGLContext::Uniform3f(WebGLUniformLocation *location_object, GLfloat a1, - GLfloat a2, GLfloat a3) +WebGLContext::Uniform3f(WebGLUniformLocation* loc, GLfloat a1, GLfloat a2, + GLfloat a3) { - GLint location; - if (!ValidateUniformSetter("Uniform3f", location_object, location)) + GLuint rawLoc; + if (!ValidateUniformSetter(loc, 3, LOCAL_GL_FLOAT, "uniform3f", &rawLoc)) return; + MakeContextCurrent(); - gl->fUniform3f(location, a1, a2, a3); + gl->fUniform3f(rawLoc, a1, a2, a3); } void -WebGLContext::Uniform4f(WebGLUniformLocation *location_object, GLfloat a1, - GLfloat a2, GLfloat a3, GLfloat a4) +WebGLContext::Uniform4f(WebGLUniformLocation* loc, GLfloat a1, GLfloat a2, + GLfloat a3, GLfloat a4) { - GLint location; - if (!ValidateUniformSetter("Uniform4f", location_object, location)) + GLuint rawLoc; + if (!ValidateUniformSetter(loc, 4, LOCAL_GL_FLOAT, "uniform4f", &rawLoc)) return; + MakeContextCurrent(); - gl->fUniform4f(location, a1, a2, a3, a4); + gl->fUniform4f(rawLoc, a1, a2, a3, a4); } +//////////////////////////////////////// +// Array + void -WebGLContext::Uniform1iv_base(WebGLUniformLocation *location_object, - uint32_t arrayLength, const GLint* data) +WebGLContext::Uniform1iv_base(WebGLUniformLocation* loc, size_t arrayLength, + const GLint* data) { - uint32_t numElementsToUpload; - GLint location; - if (!ValidateUniformArraySetter("Uniform1iv", 1, location_object, location, - numElementsToUpload, arrayLength)) { + GLuint rawLoc; + GLsizei numElementsToUpload; + if (!ValidateUniformArraySetter(loc, 1, LOCAL_GL_INT, arrayLength, + "uniform1iv", &rawLoc, + &numElementsToUpload)) + { return; } - if (!ValidateSamplerUniformSetter("Uniform1iv", location_object, data[0])) + if (!ValidateSamplerUniformSetter("uniform1iv", loc, data[0])) return; MakeContextCurrent(); - gl->fUniform1iv(location, numElementsToUpload, data); + gl->fUniform1iv(rawLoc, numElementsToUpload, data); } void -WebGLContext::Uniform2iv_base(WebGLUniformLocation *location_object, - uint32_t arrayLength, const GLint* data) +WebGLContext::Uniform2iv_base(WebGLUniformLocation* loc, size_t arrayLength, + const GLint* data) { - uint32_t numElementsToUpload; - GLint location; - if (!ValidateUniformArraySetter("Uniform2iv", 2, location_object, location, - numElementsToUpload, arrayLength)) { + GLuint rawLoc; + GLsizei numElementsToUpload; + if (!ValidateUniformArraySetter(loc, 2, LOCAL_GL_INT, arrayLength, + "uniform2iv", &rawLoc, + &numElementsToUpload)) + { return; } - if (!ValidateSamplerUniformSetter("Uniform2iv", location_object, data[0]) || - !ValidateSamplerUniformSetter("Uniform2iv", location_object, data[1])) + if (!ValidateSamplerUniformSetter("uniform2iv", loc, data[0]) || + !ValidateSamplerUniformSetter("uniform2iv", loc, data[1])) { return; } MakeContextCurrent(); - gl->fUniform2iv(location, numElementsToUpload, data); + gl->fUniform2iv(rawLoc, numElementsToUpload, data); } void -WebGLContext::Uniform3iv_base(WebGLUniformLocation *location_object, - uint32_t arrayLength, const GLint* data) +WebGLContext::Uniform3iv_base(WebGLUniformLocation* loc, size_t arrayLength, + const GLint* data) { - uint32_t numElementsToUpload; - GLint location; - if (!ValidateUniformArraySetter("Uniform3iv", 3, location_object, location, - numElementsToUpload, arrayLength)) { + GLuint rawLoc; + GLsizei numElementsToUpload; + if (!ValidateUniformArraySetter(loc, 3, LOCAL_GL_INT, arrayLength, + "uniform3iv", &rawLoc, + &numElementsToUpload)) + { return; } - if (!ValidateSamplerUniformSetter("Uniform3iv", location_object, data[0]) || - !ValidateSamplerUniformSetter("Uniform3iv", location_object, data[1]) || - !ValidateSamplerUniformSetter("Uniform3iv", location_object, data[2])) + if (!ValidateSamplerUniformSetter("uniform3iv", loc, data[0]) || + !ValidateSamplerUniformSetter("uniform3iv", loc, data[1]) || + !ValidateSamplerUniformSetter("uniform3iv", loc, data[2])) { return; } MakeContextCurrent(); - gl->fUniform3iv(location, numElementsToUpload, data); + gl->fUniform3iv(rawLoc, numElementsToUpload, data); } void -WebGLContext::Uniform4iv_base(WebGLUniformLocation *location_object, - uint32_t arrayLength, const GLint* data) +WebGLContext::Uniform4iv_base(WebGLUniformLocation* loc, size_t arrayLength, + const GLint* data) { - uint32_t numElementsToUpload; - GLint location; - if (!ValidateUniformArraySetter("Uniform4iv", 4, location_object, location, - numElementsToUpload, arrayLength)) { + GLuint rawLoc; + GLsizei numElementsToUpload; + if (!ValidateUniformArraySetter(loc, 4, LOCAL_GL_INT, arrayLength, + "uniform4iv", &rawLoc, + &numElementsToUpload)) + { return; } - if (!ValidateSamplerUniformSetter("Uniform4iv", location_object, data[0]) || - !ValidateSamplerUniformSetter("Uniform4iv", location_object, data[1]) || - !ValidateSamplerUniformSetter("Uniform4iv", location_object, data[2]) || - !ValidateSamplerUniformSetter("Uniform4iv", location_object, data[3])) + if (!ValidateSamplerUniformSetter("uniform4iv", loc, data[0]) || + !ValidateSamplerUniformSetter("uniform4iv", loc, data[1]) || + !ValidateSamplerUniformSetter("uniform4iv", loc, data[2]) || + !ValidateSamplerUniformSetter("uniform4iv", loc, data[3])) { return; } MakeContextCurrent(); - gl->fUniform4iv(location, numElementsToUpload, data); + gl->fUniform4iv(rawLoc, numElementsToUpload, data); } void -WebGLContext::Uniform1fv_base(WebGLUniformLocation *location_object, - uint32_t arrayLength, const GLfloat* data) +WebGLContext::Uniform1fv_base(WebGLUniformLocation* loc, size_t arrayLength, + const GLfloat* data) { - uint32_t numElementsToUpload; - GLint location; - if (!ValidateUniformArraySetter("Uniform1fv", 1, location_object, location, - numElementsToUpload, arrayLength)) { + GLuint rawLoc; + GLsizei numElementsToUpload; + if (!ValidateUniformArraySetter(loc, 1, LOCAL_GL_FLOAT, arrayLength, + "uniform1fv", &rawLoc, + &numElementsToUpload)) + { return; } + MakeContextCurrent(); - gl->fUniform1fv(location, numElementsToUpload, data); + gl->fUniform1fv(rawLoc, numElementsToUpload, data); } void -WebGLContext::Uniform2fv_base(WebGLUniformLocation *location_object, - uint32_t arrayLength, const GLfloat* data) +WebGLContext::Uniform2fv_base(WebGLUniformLocation* loc, size_t arrayLength, + const GLfloat* data) { - uint32_t numElementsToUpload; - GLint location; - if (!ValidateUniformArraySetter("Uniform2fv", 2, location_object, location, - numElementsToUpload, arrayLength)) { + GLuint rawLoc; + GLsizei numElementsToUpload; + if (!ValidateUniformArraySetter(loc, 2, LOCAL_GL_FLOAT, arrayLength, + "uniform2fv", &rawLoc, + &numElementsToUpload)) + { return; } + MakeContextCurrent(); - gl->fUniform2fv(location, numElementsToUpload, data); + gl->fUniform2fv(rawLoc, numElementsToUpload, data); } void -WebGLContext::Uniform3fv_base(WebGLUniformLocation *location_object, - uint32_t arrayLength, const GLfloat* data) +WebGLContext::Uniform3fv_base(WebGLUniformLocation* loc, size_t arrayLength, + const GLfloat* data) { - uint32_t numElementsToUpload; - GLint location; - if (!ValidateUniformArraySetter("Uniform3fv", 3, location_object, location, - numElementsToUpload, arrayLength)) { + GLuint rawLoc; + GLsizei numElementsToUpload; + if (!ValidateUniformArraySetter(loc, 3, LOCAL_GL_FLOAT, arrayLength, + "uniform3fv", &rawLoc, + &numElementsToUpload)) + { return; } + MakeContextCurrent(); - gl->fUniform3fv(location, numElementsToUpload, data); + gl->fUniform3fv(rawLoc, numElementsToUpload, data); } void -WebGLContext::Uniform4fv_base(WebGLUniformLocation *location_object, - uint32_t arrayLength, const GLfloat* data) +WebGLContext::Uniform4fv_base(WebGLUniformLocation* loc, size_t arrayLength, + const GLfloat* data) { - uint32_t numElementsToUpload; - GLint location; - if (!ValidateUniformArraySetter("Uniform4fv", 4, location_object, location, - numElementsToUpload, arrayLength)) { + GLuint rawLoc; + GLsizei numElementsToUpload; + if (!ValidateUniformArraySetter(loc, 4, LOCAL_GL_FLOAT, arrayLength, + "uniform4fv", &rawLoc, + &numElementsToUpload)) + { return; } + MakeContextCurrent(); - gl->fUniform4fv(location, numElementsToUpload, data); + gl->fUniform4fv(rawLoc, numElementsToUpload, data); +} + +//////////////////////////////////////// +// Matrix + +void +WebGLContext::UniformMatrix2fv_base(WebGLUniformLocation* loc, bool transpose, + size_t arrayLength, const float* data) +{ + GLuint rawLoc; + GLsizei numElementsToUpload; + if (!ValidateUniformMatrixArraySetter(loc, 2, LOCAL_GL_FLOAT, arrayLength, + transpose, "uniformMatrix2fv", + &rawLoc, &numElementsToUpload)) + { + return; + } + + MakeContextCurrent(); + gl->fUniformMatrix2fv(rawLoc, numElementsToUpload, false, data); } void -WebGLContext::UniformMatrix2fv_base(WebGLUniformLocation* location_object, - WebGLboolean aTranspose, uint32_t arrayLength, - const float* data) +WebGLContext::UniformMatrix3fv_base(WebGLUniformLocation* loc, bool transpose, + size_t arrayLength, const float* data) { - uint32_t numElementsToUpload; - GLint location; - if (!ValidateUniformMatrixArraySetter("UniformMatrix2fv", 2, location_object, location, - numElementsToUpload, arrayLength, aTranspose)) { + GLuint rawLoc; + GLsizei numElementsToUpload; + if (!ValidateUniformMatrixArraySetter(loc, 3, LOCAL_GL_FLOAT, arrayLength, + transpose, "uniformMatrix3fv", + &rawLoc, &numElementsToUpload)) + { return; } + MakeContextCurrent(); - gl->fUniformMatrix2fv(location, numElementsToUpload, false, data); + gl->fUniformMatrix3fv(rawLoc, numElementsToUpload, false, data); } void -WebGLContext::UniformMatrix3fv_base(WebGLUniformLocation* location_object, - WebGLboolean aTranspose, uint32_t arrayLength, - const float* data) +WebGLContext::UniformMatrix4fv_base(WebGLUniformLocation* loc, bool transpose, + size_t arrayLength, const float* data) { - uint32_t numElementsToUpload; - GLint location; - if (!ValidateUniformMatrixArraySetter("UniformMatrix3fv", 3, location_object, location, - numElementsToUpload, arrayLength, aTranspose)) { + GLuint rawLoc; + GLsizei numElementsToUpload; + if (!ValidateUniformMatrixArraySetter(loc, 4, LOCAL_GL_FLOAT, arrayLength, + transpose, "uniformMatrix4fv", + &rawLoc, &numElementsToUpload)) + { return; } + MakeContextCurrent(); - gl->fUniformMatrix3fv(location, numElementsToUpload, false, data); + gl->fUniformMatrix4fv(rawLoc, numElementsToUpload, false, data); } -void -WebGLContext::UniformMatrix4fv_base(WebGLUniformLocation* location_object, - WebGLboolean aTranspose, uint32_t arrayLength, - const float* data) -{ - uint32_t numElementsToUpload; - GLint location; - if (!ValidateUniformMatrixArraySetter("UniformMatrix4fv", 4, location_object, location, - numElementsToUpload, arrayLength, aTranspose)) { - return; - } - MakeContextCurrent(); - gl->fUniformMatrix4fv(location, numElementsToUpload, false, data); -} +//////////////////////////////////////////////////////////////////////////////// void WebGLContext::UseProgram(WebGLProgram *prog) @@ -4267,9 +4343,18 @@ WebGLContext::Finish() { } void -WebGLContext::LineWidth(GLfloat width) { +WebGLContext::LineWidth(GLfloat width) +{ if (IsContextLost()) return; + + // Doing it this way instead of `if (width <= 0.0)` handles NaNs. + const bool isValid = width > 0.0; + if (!isValid) { + ErrorInvalidValue("lineWidth: `width` must be positive and non-zero."); + return; + } + MakeContextCurrent(); gl->fLineWidth(width); } diff --git a/dom/canvas/WebGLContextValidate.cpp b/dom/canvas/WebGLContextValidate.cpp index 8f562d509e2a..3fccdce76f50 100644 --- a/dom/canvas/WebGLContextValidate.cpp +++ b/dom/canvas/WebGLContextValidate.cpp @@ -1322,109 +1322,168 @@ WebGLContext::ValidateAttribArraySetter(const char* name, uint32_t cnt, uint32_t return true; } -bool -WebGLContext::ValidateUniformArraySetter(const char* name, uint32_t expectedElemSize, WebGLUniformLocation *location_object, - GLint& location, uint32_t& numElementsToUpload, uint32_t arrayLength) +static bool +IsUniformSetterTypeValid(GLenum setterType, GLenum uniformType) { - if (IsContextLost()) - return false; - if (!ValidateUniformLocation(name, location_object)) - return false; - location = location_object->Location(); - uint32_t uniformElemSize = location_object->ElementSize(); - if (expectedElemSize != uniformElemSize) { - ErrorInvalidOperation("%s: this function expected a uniform of element size %d," - " got a uniform of element size %d", name, - expectedElemSize, - uniformElemSize); + switch (uniformType) { + case LOCAL_GL_BOOL: + case LOCAL_GL_BOOL_VEC2: + case LOCAL_GL_BOOL_VEC3: + case LOCAL_GL_BOOL_VEC4: + return true; // GLfloat(0.0) sets a bool to false. + + case LOCAL_GL_INT: + case LOCAL_GL_SAMPLER_2D: + case LOCAL_GL_SAMPLER_CUBE: + case LOCAL_GL_INT_VEC2: + case LOCAL_GL_INT_VEC3: + case LOCAL_GL_INT_VEC4: + return setterType == LOCAL_GL_INT; + + case LOCAL_GL_FLOAT: + case LOCAL_GL_FLOAT_VEC2: + case LOCAL_GL_FLOAT_VEC3: + case LOCAL_GL_FLOAT_VEC4: + case LOCAL_GL_FLOAT_MAT2: + case LOCAL_GL_FLOAT_MAT3: + case LOCAL_GL_FLOAT_MAT4: + return setterType == LOCAL_GL_FLOAT; + + default: + MOZ_ASSERT(false); // should never get here return false; } - if (arrayLength == 0 || - arrayLength % expectedElemSize) +} + +static bool +CheckUniformSizeAndType(WebGLContext& webgl, WebGLUniformLocation* loc, + uint8_t setterElemSize, GLenum setterType, + const char* info) +{ + if (setterElemSize != loc->ElementSize()) { + webgl.ErrorInvalidOperation("%s: Bad uniform size: %i", info, + loc->ElementSize()); + return false; + } + + if (!IsUniformSetterTypeValid(setterType, loc->Info().type)) { + webgl.ErrorInvalidOperation("%s: Bad uniform type: %i", info, + loc->Info().type); + return false; + } + + return true; +} + +static bool +CheckUniformArrayLength(WebGLContext& webgl, WebGLUniformLocation* loc, + uint8_t setterElemSize, size_t setterArraySize, + const char* info) +{ + if (setterArraySize == 0 || + setterArraySize % setterElemSize) { - ErrorInvalidValue("%s: expected an array of length a multiple" - " of %d, got an array of length %d", name, - expectedElemSize, - arrayLength); + webgl.ErrorInvalidValue("%s: expected an array of length a multiple of" + " %d, got an array of length %d.", info, + setterElemSize, setterArraySize); return false; } - const WebGLUniformInfo& info = location_object->Info(); - if (!info.isArray && - arrayLength != expectedElemSize) { - ErrorInvalidOperation("%s: expected an array of length exactly" - " %d (since this uniform is not an array" - " uniform), got an array of length %d", name, - expectedElemSize, - arrayLength); - return false; - } - numElementsToUpload = - std::min(info.arraySize, arrayLength / expectedElemSize); - return true; -} -bool -WebGLContext::ValidateUniformMatrixArraySetter(const char* name, int dim, WebGLUniformLocation *location_object, - GLint& location, uint32_t& numElementsToUpload, uint32_t arrayLength, - WebGLboolean aTranspose) -{ - uint32_t expectedElemSize = (dim)*(dim); - if (IsContextLost()) - return false; - if (!ValidateUniformLocation(name, location_object)) - return false; - location = location_object->Location(); - uint32_t uniformElemSize = location_object->ElementSize(); - if (expectedElemSize != uniformElemSize) { - ErrorInvalidOperation("%s: this function expected a uniform of element size %d," - " got a uniform of element size %d", name, - expectedElemSize, - uniformElemSize); - return false; - } - if (arrayLength == 0 || - arrayLength % expectedElemSize) + if (!loc->Info().isArray && + setterArraySize != setterElemSize) { - ErrorInvalidValue("%s: expected an array of length a multiple" - " of %d, got an array of length %d", name, - expectedElemSize, - arrayLength); + webgl.ErrorInvalidOperation("%s: expected an array of length exactly %d" + " (since this uniform is not an array" + " uniform), got an array of length %d.", + info, setterElemSize, setterArraySize); return false; } - const WebGLUniformInfo& info = location_object->Info(); - if (!info.isArray && - arrayLength != expectedElemSize) { - ErrorInvalidOperation("%s: expected an array of length exactly" - " %d (since this uniform is not an array" - " uniform), got an array of length %d", name, - expectedElemSize, - arrayLength); - return false; - } - if (aTranspose) { - ErrorInvalidValue("%s: transpose must be FALSE as per the " - "OpenGL ES 2.0 spec", name); - return false; - } - numElementsToUpload = - std::min(info.arraySize, arrayLength / (expectedElemSize)); + return true; } bool -WebGLContext::ValidateUniformSetter(const char* name, WebGLUniformLocation *location_object, GLint& location) +WebGLContext::ValidateUniformSetter(WebGLUniformLocation* loc, + uint8_t setterElemSize, GLenum setterType, + const char* info, GLuint* out_rawLoc) { if (IsContextLost()) return false; - if (!ValidateUniformLocation(name, location_object)) + + if (!ValidateUniformLocation(info, loc)) return false; - location = location_object->Location(); + + if (!CheckUniformSizeAndType(*this, loc, setterElemSize, setterType, info)) + return false; + + *out_rawLoc = loc->Location(); return true; } -bool WebGLContext::ValidateAttribIndex(GLuint index, const char *info) +bool +WebGLContext::ValidateUniformArraySetter(WebGLUniformLocation* loc, + uint8_t setterElemSize, GLenum setterType, + size_t setterArraySize, + const char* info, GLuint* out_rawLoc, + GLsizei* out_numElementsToUpload) { - return mBoundVertexArray->EnsureAttrib(index, info); + if (IsContextLost()) + return false; + + if (!ValidateUniformLocation(info, loc)) + return false; + + if (!CheckUniformSizeAndType(*this, loc, setterElemSize, setterType, info)) + return false; + + if (!CheckUniformArrayLength(*this, loc, setterElemSize, setterArraySize, + info)) + { + return false; + } + + *out_rawLoc = loc->Location(); + *out_numElementsToUpload = std::min((size_t)loc->Info().arraySize, + setterArraySize / setterElemSize); + return true; +} + +bool +WebGLContext::ValidateUniformMatrixArraySetter(WebGLUniformLocation* loc, + uint8_t setterDims, + GLenum setterType, + size_t setterArraySize, + bool setterTranspose, + const char* info, + GLuint* out_rawLoc, + GLsizei* out_numElementsToUpload) +{ + uint8_t setterElemSize = setterDims * setterDims; + + if (IsContextLost()) + return false; + + if (!ValidateUniformLocation(info, loc)) + return false; + + if (!CheckUniformSizeAndType(*this, loc, setterElemSize, setterType, info)) + return false; + + if (!CheckUniformArrayLength(*this, loc, setterElemSize, setterArraySize, + info)) + { + return false; + } + + if (setterTranspose) { + ErrorInvalidValue("%s: `transpose` must be false.", info); + return false; + } + + *out_rawLoc = loc->Location(); + *out_numElementsToUpload = std::min((size_t)loc->Info().arraySize, + setterArraySize / setterElemSize); + return true; } bool WebGLContext::ValidateStencilParamsForDrawCall() diff --git a/dom/canvas/WebGLContextVertices.cpp b/dom/canvas/WebGLContextVertices.cpp index 582433538c42..201b7573583a 100644 --- a/dom/canvas/WebGLContextVertices.cpp +++ b/dom/canvas/WebGLContextVertices.cpp @@ -20,12 +20,36 @@ using namespace mozilla; using namespace dom; +static bool +CheckAttribIndex(WebGLContext& webgl, GLuint index, const char* info) +{ + if (index >= webgl.MaxVertexAttribs()) { + if (index == GLuint(-1)) { + webgl.ErrorInvalidValue("%s: -1 is not a valid `index`. This value" + " probably comes from a getAttribLocation()" + " call, where this return value -1 means" + " that the passed name didn't correspond to" + " an active attribute in the specified" + " program.", info); + } else { + webgl.ErrorInvalidValue("%s: `index` must be less than" + " MAX_VERTEX_ATTRIBS.", info); + } + return false; + } + + return true; +} + void WebGLContext::VertexAttrib1f(GLuint index, GLfloat x0) { if (IsContextLost()) return; + if (!CheckAttribIndex(*this, index, "vertexAttrib1f")) + return; + MakeContextCurrent(); if (index) { @@ -46,6 +70,9 @@ WebGLContext::VertexAttrib2f(GLuint index, GLfloat x0, GLfloat x1) if (IsContextLost()) return; + if (!CheckAttribIndex(*this, index, "vertexAttrib2f")) + return; + MakeContextCurrent(); if (index) { @@ -66,6 +93,9 @@ WebGLContext::VertexAttrib3f(GLuint index, GLfloat x0, GLfloat x1, GLfloat x2) if (IsContextLost()) return; + if (!CheckAttribIndex(*this, index, "vertexAttrib3f")) + return; + MakeContextCurrent(); if (index) { @@ -87,6 +117,9 @@ WebGLContext::VertexAttrib4f(GLuint index, GLfloat x0, GLfloat x1, if (IsContextLost()) return; + if (!CheckAttribIndex(*this, index, "vertexAttrib4f")) + return; + MakeContextCurrent(); if (index) { @@ -103,82 +136,94 @@ WebGLContext::VertexAttrib4f(GLuint index, GLfloat x0, GLfloat x1, void -WebGLContext::VertexAttrib1fv_base(GLuint idx, uint32_t arrayLength, +WebGLContext::VertexAttrib1fv_base(GLuint index, uint32_t arrayLength, const GLfloat* ptr) { if (!ValidateAttribArraySetter("VertexAttrib1fv", 1, arrayLength)) return; + if (!CheckAttribIndex(*this, index, "vertexAttrib1fv")) + return; + MakeContextCurrent(); - if (idx) { - gl->fVertexAttrib1fv(idx, ptr); + if (index) { + gl->fVertexAttrib1fv(index, ptr); } else { mVertexAttrib0Vector[0] = ptr[0]; mVertexAttrib0Vector[1] = GLfloat(0); mVertexAttrib0Vector[2] = GLfloat(0); mVertexAttrib0Vector[3] = GLfloat(1); if (gl->IsGLES()) - gl->fVertexAttrib1fv(idx, ptr); + gl->fVertexAttrib1fv(index, ptr); } } void -WebGLContext::VertexAttrib2fv_base(GLuint idx, uint32_t arrayLength, +WebGLContext::VertexAttrib2fv_base(GLuint index, uint32_t arrayLength, const GLfloat* ptr) { if (!ValidateAttribArraySetter("VertexAttrib2fv", 2, arrayLength)) return; + if (!CheckAttribIndex(*this, index, "vertexAttrib2fv")) + return; + MakeContextCurrent(); - if (idx) { - gl->fVertexAttrib2fv(idx, ptr); + if (index) { + gl->fVertexAttrib2fv(index, ptr); } else { mVertexAttrib0Vector[0] = ptr[0]; mVertexAttrib0Vector[1] = ptr[1]; mVertexAttrib0Vector[2] = GLfloat(0); mVertexAttrib0Vector[3] = GLfloat(1); if (gl->IsGLES()) - gl->fVertexAttrib2fv(idx, ptr); + gl->fVertexAttrib2fv(index, ptr); } } void -WebGLContext::VertexAttrib3fv_base(GLuint idx, uint32_t arrayLength, +WebGLContext::VertexAttrib3fv_base(GLuint index, uint32_t arrayLength, const GLfloat* ptr) { if (!ValidateAttribArraySetter("VertexAttrib3fv", 3, arrayLength)) return; + if (!CheckAttribIndex(*this, index, "vertexAttrib3fv")) + return; + MakeContextCurrent(); - if (idx) { - gl->fVertexAttrib3fv(idx, ptr); + if (index) { + gl->fVertexAttrib3fv(index, ptr); } else { mVertexAttrib0Vector[0] = ptr[0]; mVertexAttrib0Vector[1] = ptr[1]; mVertexAttrib0Vector[2] = ptr[2]; mVertexAttrib0Vector[3] = GLfloat(1); if (gl->IsGLES()) - gl->fVertexAttrib3fv(idx, ptr); + gl->fVertexAttrib3fv(index, ptr); } } void -WebGLContext::VertexAttrib4fv_base(GLuint idx, uint32_t arrayLength, +WebGLContext::VertexAttrib4fv_base(GLuint index, uint32_t arrayLength, const GLfloat* ptr) { if (!ValidateAttribArraySetter("VertexAttrib4fv", 4, arrayLength)) return; + if (!CheckAttribIndex(*this, index, "vertexAttrib4fv")) + return; + MakeContextCurrent(); - if (idx) { - gl->fVertexAttrib4fv(idx, ptr); + if (index) { + gl->fVertexAttrib4fv(index, ptr); } else { mVertexAttrib0Vector[0] = ptr[0]; mVertexAttrib0Vector[1] = ptr[1]; mVertexAttrib0Vector[2] = ptr[2]; mVertexAttrib0Vector[3] = ptr[3]; if (gl->IsGLES()) - gl->fVertexAttrib4fv(idx, ptr); + gl->fVertexAttrib4fv(index, ptr); } } @@ -188,14 +233,16 @@ WebGLContext::EnableVertexAttribArray(GLuint index) if (IsContextLost()) return; - if (!ValidateAttribIndex(index, "enableVertexAttribArray")) + if (!CheckAttribIndex(*this, index, "enableVertexAttribArray")) return; MakeContextCurrent(); InvalidateBufferFetching(); gl->fEnableVertexAttribArray(index); - MOZ_ASSERT(mBoundVertexArray->HasAttrib(index)); // should have been validated earlier + + MOZ_ASSERT(mBoundVertexArray); + mBoundVertexArray->EnsureAttrib(index); mBoundVertexArray->mAttribs[index].enabled = true; } @@ -205,7 +252,7 @@ WebGLContext::DisableVertexAttribArray(GLuint index) if (IsContextLost()) return; - if (!ValidateAttribIndex(index, "disableVertexAttribArray")) + if (!CheckAttribIndex(*this, index, "disableVertexAttribArray")) return; MakeContextCurrent(); @@ -214,11 +261,11 @@ WebGLContext::DisableVertexAttribArray(GLuint index) if (index || gl->IsGLES()) gl->fDisableVertexAttribArray(index); - MOZ_ASSERT(mBoundVertexArray->HasAttrib(index)); // should have been validated earlier + MOZ_ASSERT(mBoundVertexArray); + mBoundVertexArray->EnsureAttrib(index); mBoundVertexArray->mAttribs[index].enabled = false; } - JS::Value WebGLContext::GetVertexAttrib(JSContext* cx, GLuint index, GLenum pname, ErrorResult& rv) @@ -226,9 +273,12 @@ WebGLContext::GetVertexAttrib(JSContext* cx, GLuint index, GLenum pname, if (IsContextLost()) return JS::NullValue(); - if (!ValidateAttribIndex(index, "getVertexAttrib")) + if (!CheckAttribIndex(*this, index, "getVertexAttrib")) return JS::NullValue(); + MOZ_ASSERT(mBoundVertexArray); + mBoundVertexArray->EnsureAttrib(index); + MakeContextCurrent(); switch (pname) { @@ -300,7 +350,6 @@ WebGLContext::GetVertexAttrib(JSContext* cx, GLuint index, GLenum pname, } ErrorInvalidEnumInfo("getVertexAttrib: parameter", pname); - return JS::NullValue(); } @@ -310,7 +359,7 @@ WebGLContext::GetVertexAttribOffset(GLuint index, GLenum pname) if (IsContextLost()) return 0; - if (!ValidateAttribIndex(index, "getVertexAttribOffset")) + if (!CheckAttribIndex(*this, index, "getVertexAttribOffset")) return 0; if (pname != LOCAL_GL_VERTEX_ATTRIB_ARRAY_POINTER) { @@ -318,6 +367,8 @@ WebGLContext::GetVertexAttribOffset(GLuint index, GLenum pname) return 0; } + MOZ_ASSERT(mBoundVertexArray); + mBoundVertexArray->EnsureAttrib(index); return mBoundVertexArray->mAttribs[index].byteOffset; } @@ -329,6 +380,9 @@ WebGLContext::VertexAttribPointer(GLuint index, GLint size, GLenum type, if (IsContextLost()) return; + if (!CheckAttribIndex(*this, index, "vertexAttribPointer")) + return; + if (mBoundArrayBuffer == nullptr) return ErrorInvalidOperation("vertexAttribPointer: must have valid GL_ARRAY_BUFFER binding"); @@ -353,9 +407,8 @@ WebGLContext::VertexAttribPointer(GLuint index, GLint size, GLenum type, // requiredAlignment should always be a power of two. GLsizei requiredAlignmentMask = requiredAlignment - 1; - if (!ValidateAttribIndex(index, "vertexAttribPointer")) { - return; - } + MOZ_ASSERT(mBoundVertexArray); + mBoundVertexArray->EnsureAttrib(index); if (size < 1 || size > 4) return ErrorInvalidValue("vertexAttribPointer: invalid element size"); @@ -406,9 +459,11 @@ WebGLContext::VertexAttribDivisor(GLuint index, GLuint divisor) if (IsContextLost()) return; - if (!ValidateAttribIndex(index, "vertexAttribDivisor")) { + if (!CheckAttribIndex(*this, index, "vertexAttribDivisor")) return; - } + + MOZ_ASSERT(mBoundVertexArray); + mBoundVertexArray->EnsureAttrib(index); WebGLVertexAttribData& vd = mBoundVertexArray->mAttribs[index]; vd.divisor = divisor; diff --git a/dom/canvas/WebGLVertexArray.cpp b/dom/canvas/WebGLVertexArray.cpp index 93d519f0eacf..470ff93669ba 100644 --- a/dom/canvas/WebGLVertexArray.cpp +++ b/dom/canvas/WebGLVertexArray.cpp @@ -49,24 +49,14 @@ WebGLVertexArray::Delete() mAttribs.Clear(); } -bool -WebGLVertexArray::EnsureAttrib(GLuint index, const char *info) +void +WebGLVertexArray::EnsureAttrib(GLuint index) { - if (index >= GLuint(mContext->mGLMaxVertexAttribs)) { - if (index == GLuint(-1)) { - mContext->ErrorInvalidValue("%s: index -1 is invalid. That probably comes from a getAttribLocation() call, " - "where this return value -1 means that the passed name didn't correspond to an active attribute in " - "the specified program.", info); - } else { - mContext->ErrorInvalidValue("%s: index %d is out of range", info, index); - } - return false; - } - else if (index >= mAttribs.Length()) { + MOZ_ASSERT(index < GLuint(mContext->mGLMaxVertexAttribs)); + + if (index >= mAttribs.Length()) { mAttribs.SetLength(index + 1); } - - return true; } NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLVertexArray, diff --git a/dom/canvas/WebGLVertexArray.h b/dom/canvas/WebGLVertexArray.h index 5d242f1e095c..a66d1c3725c5 100644 --- a/dom/canvas/WebGLVertexArray.h +++ b/dom/canvas/WebGLVertexArray.h @@ -61,7 +61,7 @@ public: // ------------------------------------------------------------------------- // MEMBER FUNCTIONS - bool EnsureAttrib(GLuint index, const char *info); + void EnsureAttrib(GLuint index); bool HasAttrib(GLuint index) { return index < mAttribs.Length(); }