Bug 1088345 - Don't run GL commands that may cause non-OOM errors. - r=kamidphish

This commit is contained in:
Jeff Gilbert 2014-10-23 15:10:57 -07:00
parent a25184ab43
commit e15b3b3c98
6 changed files with 580 additions and 378 deletions

View File

@ -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<GLint>& arr) {
Uniform1iv_base(location, arr.Length(), arr.Elements());
void Uniform1iv(WebGLUniformLocation* loc,
const dom::Sequence<GLint>& 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<GLint>& arr) {
Uniform2iv_base(location, arr.Length(), arr.Elements());
void Uniform2iv(WebGLUniformLocation* loc,
const dom::Sequence<GLint>& 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<GLint>& arr) {
Uniform3iv_base(location, arr.Length(), arr.Elements());
void Uniform3iv(WebGLUniformLocation* loc,
const dom::Sequence<GLint>& 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<GLint>& arr) {
Uniform4iv_base(location, arr.Length(), arr.Elements());
void Uniform4iv(WebGLUniformLocation* loc,
const dom::Sequence<GLint>& 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<GLfloat>& arr) {
Uniform1fv_base(location, arr.Length(), arr.Elements());
void Uniform1fv(WebGLUniformLocation* loc,
const dom::Sequence<GLfloat>& 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<GLfloat>& arr) {
Uniform2fv_base(location, arr.Length(), arr.Elements());
void Uniform2fv(WebGLUniformLocation* loc,
const dom::Sequence<GLfloat>& 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<GLfloat>& arr) {
Uniform3fv_base(location, arr.Length(), arr.Elements());
void Uniform3fv(WebGLUniformLocation* loc,
const dom::Sequence<GLfloat>& 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<GLfloat>& arr) {
Uniform4fv_base(location, arr.Length(), arr.Elements());
void Uniform4fv(WebGLUniformLocation* loc,
const dom::Sequence<GLfloat>& 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<float> &value) {
UniformMatrix2fv_base(location, transpose, value.Length(),
void UniformMatrix2fv(WebGLUniformLocation* loc, WebGLboolean transpose,
const dom::Sequence<float>& 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<float> &value) {
UniformMatrix3fv_base(location, transpose, value.Length(),
value.Elements());
void UniformMatrix3fv(WebGLUniformLocation* loc, WebGLboolean transpose,
const dom::Sequence<float>& 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<float> &value) {
UniformMatrix4fv_base(location, transpose, value.Length(),
void UniformMatrix4fv(WebGLUniformLocation* loc, WebGLboolean transpose,
const dom::Sequence<float>& 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);

View File

@ -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<WebGLBuffer>* 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);
}

View File

@ -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()

View File

@ -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;

View File

@ -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,

View File

@ -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();
}