mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-07 18:04:46 +00:00
Bug 1325301 (flattened) - Validate attribute base types match data base types. - r=bz,daoshengmu
Flattened with: * Clean up generic vertex attribs. - r=bz,daoshengmu * Remove EnsureAttrib() and friends. - r=daoshengmu * Simplify EnumName behavior and usage and add ErrorInvalidEnumArg(). - r=daoshengmu
This commit is contained in:
parent
59ad1b29d3
commit
0b065a7b71
@ -243,8 +243,10 @@ public:
|
||||
////////////////
|
||||
|
||||
// GL 3.0 & ES 3.0
|
||||
void VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w);
|
||||
void VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
|
||||
void VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w,
|
||||
const char* funcName = nullptr);
|
||||
void VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w,
|
||||
const char* funcName = nullptr);
|
||||
|
||||
void VertexAttribI4iv(GLuint index, const Int32ListU& list) {
|
||||
const auto& arr = Int32Arr::From(list);
|
||||
|
@ -325,9 +325,11 @@ WebGL2Context::ReadBuffer(GLenum mode)
|
||||
if (mode != LOCAL_GL_NONE &&
|
||||
mode != LOCAL_GL_BACK)
|
||||
{
|
||||
nsCString enumName;
|
||||
EnumName(mode, &enumName);
|
||||
ErrorInvalidOperation("%s: If READ_FRAMEBUFFER is null, `mode` must be BACK or"
|
||||
" NONE. Was %s",
|
||||
funcName, EnumName(mode));
|
||||
" NONE. Was %s.",
|
||||
funcName, enumName.BeginReading());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -139,7 +139,7 @@ WebGL2Context::GetSamplerParameter(JSContext*, const WebGLSampler& sampler, GLen
|
||||
return;
|
||||
|
||||
default:
|
||||
ErrorInvalidEnum("%s: invalid pname: %s", funcName, EnumName(pname));
|
||||
ErrorInvalidEnumArg(funcName, "pname", pname);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ ValidateUniformEnum(WebGLContext* webgl, GLenum pname, const char* info)
|
||||
return true;
|
||||
|
||||
default:
|
||||
webgl->ErrorInvalidEnum("%s: invalid pname: %s", info, webgl->EnumName(pname));
|
||||
webgl->ErrorInvalidEnumArg(info, "pname", pname);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -76,7 +76,6 @@ WebGL2Context::VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsiz
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mBoundVertexArray);
|
||||
mBoundVertexArray->EnsureAttrib(index);
|
||||
|
||||
InvalidateBufferFetching();
|
||||
|
||||
@ -90,56 +89,4 @@ WebGL2Context::VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsiz
|
||||
offset);
|
||||
}
|
||||
|
||||
void
|
||||
WebGL2Context::VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
|
||||
{
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
if (!ValidateAttribIndex(index, "vertexAttribI4i"))
|
||||
return;
|
||||
|
||||
mVertexAttribType[index] = LOCAL_GL_INT;
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (index) {
|
||||
gl->fVertexAttribI4i(index, x, y, z, w);
|
||||
} else {
|
||||
mVertexAttrib0Vector[0] = BitwiseCast<GLfloat>(x);
|
||||
mVertexAttrib0Vector[1] = BitwiseCast<GLfloat>(y);
|
||||
mVertexAttrib0Vector[2] = BitwiseCast<GLfloat>(z);
|
||||
mVertexAttrib0Vector[3] = BitwiseCast<GLfloat>(w);
|
||||
if (gl->IsGLES()) {
|
||||
gl->fVertexAttribI4i(index, x, y, z, w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGL2Context::VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
|
||||
{
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
if (!ValidateAttribIndex(index, "vertexAttribI4ui"))
|
||||
return;
|
||||
|
||||
mVertexAttribType[index] = LOCAL_GL_UNSIGNED_INT;
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (index) {
|
||||
gl->fVertexAttribI4ui(index, x, y, z, w);
|
||||
} else {
|
||||
mVertexAttrib0Vector[0] = BitwiseCast<GLfloat>(x);
|
||||
mVertexAttrib0Vector[1] = BitwiseCast<GLfloat>(y);
|
||||
mVertexAttrib0Vector[2] = BitwiseCast<GLfloat>(z);
|
||||
mVertexAttrib0Vector[3] = BitwiseCast<GLfloat>(w);
|
||||
if (gl->IsGLES()) {
|
||||
gl->fVertexAttribI4ui(index, x, y, z, w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -143,18 +143,6 @@ WebGLContext::WebGLContext()
|
||||
|
||||
mActiveTexture = 0;
|
||||
|
||||
mVertexAttrib0Vector[0] = 0;
|
||||
mVertexAttrib0Vector[1] = 0;
|
||||
mVertexAttrib0Vector[2] = 0;
|
||||
mVertexAttrib0Vector[3] = 1;
|
||||
mFakeVertexAttrib0BufferObjectVector[0] = 0;
|
||||
mFakeVertexAttrib0BufferObjectVector[1] = 0;
|
||||
mFakeVertexAttrib0BufferObjectVector[2] = 0;
|
||||
mFakeVertexAttrib0BufferObjectVector[3] = 1;
|
||||
mFakeVertexAttrib0BufferObjectSize = 0;
|
||||
mFakeVertexAttrib0BufferObject = 0;
|
||||
mFakeVertexAttrib0BufferStatus = WebGLVertexAttrib0Status::Default;
|
||||
|
||||
mStencilRefFront = 0;
|
||||
mStencilRefBack = 0;
|
||||
mStencilValueMaskFront = 0;
|
||||
|
@ -408,17 +408,17 @@ public:
|
||||
void ErrorOutOfMemory(const char* fmt = 0, ...);
|
||||
void ErrorImplementationBug(const char* fmt = 0, ...);
|
||||
|
||||
void ErrorInvalidEnumArg(const char* funcName, const char* argName, GLenum val);
|
||||
|
||||
const char* ErrorName(GLenum error);
|
||||
|
||||
/**
|
||||
* Return displayable name for GLenum.
|
||||
* This version is like gl::GLenumToStr but with out the GL_ prefix to
|
||||
* keep consistency with how errors are reported from WebGL.
|
||||
* Returns hex formatted version of glenum if glenum is unknown.
|
||||
*/
|
||||
// Returns nullptr if glenum is unknown.
|
||||
static const char* EnumName(GLenum glenum);
|
||||
// Returns hex formatted version of glenum if glenum is unknown.
|
||||
static void EnumName(GLenum glenum, nsACString* out_name);
|
||||
static void EnumName(GLenum val, nsCString* out_name);
|
||||
|
||||
void DummyReadFramebufferOperation(const char* funcName);
|
||||
|
||||
@ -1286,44 +1286,65 @@ public:
|
||||
|
||||
WebGLsizeiptr GetVertexAttribOffset(GLuint index, GLenum pname);
|
||||
|
||||
void VertexAttrib1f(GLuint index, GLfloat x0);
|
||||
void VertexAttrib2f(GLuint index, GLfloat x0, GLfloat x1);
|
||||
void VertexAttrib3f(GLuint index, GLfloat x0, GLfloat x1, GLfloat x2);
|
||||
void VertexAttrib4f(GLuint index, GLfloat x0, GLfloat x1, GLfloat x2,
|
||||
GLfloat x3);
|
||||
////
|
||||
|
||||
void VertexAttrib1fv(GLuint idx, const dom::Float32Array& arr) {
|
||||
arr.ComputeLengthAndData();
|
||||
VertexAttrib1fv_base(idx, arr.LengthAllowShared(), arr.DataAllowShared());
|
||||
void VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w,
|
||||
const char* funcName = nullptr);
|
||||
|
||||
////
|
||||
|
||||
void VertexAttrib1f(GLuint index, GLfloat x) {
|
||||
VertexAttrib4f(index, x, 0, 0, 1, "vertexAttrib1f");
|
||||
}
|
||||
void VertexAttrib1fv(GLuint idx, const dom::Sequence<GLfloat>& arr) {
|
||||
VertexAttrib1fv_base(idx, arr.Length(), arr.Elements());
|
||||
void VertexAttrib2f(GLuint index, GLfloat x, GLfloat y) {
|
||||
VertexAttrib4f(index, x, y, 0, 1, "vertexAttrib2f");
|
||||
}
|
||||
void VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) {
|
||||
VertexAttrib4f(index, x, y, z, 1, "vertexAttrib3f");
|
||||
}
|
||||
|
||||
void VertexAttrib2fv(GLuint idx, const dom::Float32Array& arr) {
|
||||
arr.ComputeLengthAndData();
|
||||
VertexAttrib2fv_base(idx, arr.LengthAllowShared(), arr.DataAllowShared());
|
||||
}
|
||||
void VertexAttrib2fv(GLuint idx, const dom::Sequence<GLfloat>& arr) {
|
||||
VertexAttrib2fv_base(idx, arr.Length(), arr.Elements());
|
||||
////
|
||||
|
||||
void VertexAttrib1fv(GLuint index, const Float32ListU& list) {
|
||||
const char funcName[] = "vertexAttrib1fv";
|
||||
const auto& arr = Float32Arr::From(list);
|
||||
if (!ValidateAttribArraySetter(funcName, 1, arr.elemCount))
|
||||
return;
|
||||
|
||||
VertexAttrib4f(index, arr.elemBytes[0], 0, 0, 1, funcName);
|
||||
}
|
||||
|
||||
void VertexAttrib3fv(GLuint idx, const dom::Float32Array& arr) {
|
||||
arr.ComputeLengthAndData();
|
||||
VertexAttrib3fv_base(idx, arr.LengthAllowShared(), arr.DataAllowShared());
|
||||
}
|
||||
void VertexAttrib3fv(GLuint idx, const dom::Sequence<GLfloat>& arr) {
|
||||
VertexAttrib3fv_base(idx, arr.Length(), arr.Elements());
|
||||
void VertexAttrib2fv(GLuint index, const Float32ListU& list) {
|
||||
const char funcName[] = "vertexAttrib2fv";
|
||||
const auto& arr = Float32Arr::From(list);
|
||||
if (!ValidateAttribArraySetter(funcName, 2, arr.elemCount))
|
||||
return;
|
||||
|
||||
VertexAttrib4f(index, arr.elemBytes[0], arr.elemBytes[1], 0, 1, funcName);
|
||||
}
|
||||
|
||||
void VertexAttrib4fv(GLuint idx, const dom::Float32Array& arr) {
|
||||
arr.ComputeLengthAndData();
|
||||
VertexAttrib4fv_base(idx, arr.LengthAllowShared(), arr.DataAllowShared());
|
||||
void VertexAttrib3fv(GLuint index, const Float32ListU& list) {
|
||||
const char funcName[] = "vertexAttrib3fv";
|
||||
const auto& arr = Float32Arr::From(list);
|
||||
if (!ValidateAttribArraySetter(funcName, 3, arr.elemCount))
|
||||
return;
|
||||
|
||||
VertexAttrib4f(index, arr.elemBytes[0], arr.elemBytes[1], arr.elemBytes[2], 1,
|
||||
funcName);
|
||||
}
|
||||
void VertexAttrib4fv(GLuint idx, const dom::Sequence<GLfloat>& arr) {
|
||||
VertexAttrib4fv_base(idx, arr.Length(), arr.Elements());
|
||||
|
||||
void VertexAttrib4fv(GLuint index, const Float32ListU& list) {
|
||||
const char funcName[] = "vertexAttrib4fv";
|
||||
const auto& arr = Float32Arr::From(list);
|
||||
if (!ValidateAttribArraySetter(funcName, 4, arr.elemCount))
|
||||
return;
|
||||
|
||||
VertexAttrib4f(index, arr.elemBytes[0], arr.elemBytes[1], arr.elemBytes[2],
|
||||
arr.elemBytes[3], funcName);
|
||||
}
|
||||
|
||||
////
|
||||
|
||||
void VertexAttribPointer(GLuint index, GLint size, GLenum type,
|
||||
WebGLboolean normalized, GLsizei stride,
|
||||
WebGLintptr byteOffset);
|
||||
@ -1361,8 +1382,8 @@ private:
|
||||
// -----------------------------------------------------------------------------
|
||||
// PROTECTED
|
||||
protected:
|
||||
WebGLVertexAttrib0Status WhatDoesVertexAttrib0Need();
|
||||
bool DoFakeVertexAttrib0(GLuint vertexCount);
|
||||
WebGLVertexAttrib0Status WhatDoesVertexAttrib0Need() const;
|
||||
bool DoFakeVertexAttrib0(const char* funcName, GLuint vertexCount);
|
||||
void UndoFakeVertexAttrib0();
|
||||
|
||||
inline void InvalidateBufferFetching()
|
||||
@ -1409,7 +1430,7 @@ protected:
|
||||
webgl::ShaderValidator* CreateShaderValidator(GLenum shaderType) const;
|
||||
|
||||
// some GL constants
|
||||
int32_t mGLMaxVertexAttribs;
|
||||
uint32_t mGLMaxVertexAttribs;
|
||||
int32_t mGLMaxTextureUnits;
|
||||
int32_t mGLMaxTextureImageUnits;
|
||||
int32_t mGLMaxVertexTextureImageUnits;
|
||||
@ -1873,16 +1894,17 @@ public:
|
||||
|
||||
protected:
|
||||
// Generic Vertex Attributes
|
||||
UniquePtr<GLenum[]> mVertexAttribType;
|
||||
GLfloat mVertexAttrib0Vector[4];
|
||||
GLfloat mFakeVertexAttrib0BufferObjectVector[4];
|
||||
size_t mFakeVertexAttrib0BufferObjectSize;
|
||||
GLuint mFakeVertexAttrib0BufferObject;
|
||||
WebGLVertexAttrib0Status mFakeVertexAttrib0BufferStatus;
|
||||
// Though CURRENT_VERTEX_ATTRIB is listed under "Vertex Shader State" in the spec
|
||||
// state tables, this isn't vertex shader /object/ state. This array is merely state
|
||||
// useful to vertex shaders, but is global state.
|
||||
UniquePtr<GLenum[]> mGenericVertexAttribTypes;
|
||||
uint8_t mGenericVertexAttrib0Data[sizeof(float) * 4];
|
||||
|
||||
GLuint mFakeVertexAttrib0BufferObject;
|
||||
size_t mFakeVertexAttrib0BufferObjectSize;
|
||||
bool mFakeVertexAttrib0DataDefined;
|
||||
uint8_t mFakeVertexAttrib0Data[sizeof(float) * 4];
|
||||
|
||||
void GetVertexAttribFloat(GLuint index, GLfloat* out_result);
|
||||
void GetVertexAttribInt(GLuint index, GLint* out_result);
|
||||
void GetVertexAttribUint(GLuint index, GLuint* out_result);
|
||||
JSObject* GetVertexAttribFloat32Array(JSContext* cx, GLuint index);
|
||||
JSObject* GetVertexAttribInt32Array(JSContext* cx, GLuint index);
|
||||
JSObject* GetVertexAttribUint32Array(JSContext* cx, GLuint index);
|
||||
|
@ -506,10 +506,8 @@ WebGLContext::DeleteBuffer(WebGLBuffer* buffer)
|
||||
}
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < mGLMaxVertexAttribs; i++) {
|
||||
if (mBoundVertexArray->HasAttrib(i)) {
|
||||
fnClearIfBuffer(mBoundVertexArray->mAttribs[i].mBuf);
|
||||
}
|
||||
for (auto& cur : mBoundVertexArray->mAttribs) {
|
||||
fnClearIfBuffer(cur.mBuf);
|
||||
}
|
||||
|
||||
////
|
||||
|
@ -346,7 +346,7 @@ public:
|
||||
////
|
||||
|
||||
const size_t requiredVerts = firstVertex + vertCount;
|
||||
if (!mWebGL->DoFakeVertexAttrib0(requiredVerts)) {
|
||||
if (!mWebGL->DoFakeVertexAttrib0(funcName, requiredVerts)) {
|
||||
*out_error = true;
|
||||
return;
|
||||
}
|
||||
@ -394,6 +394,33 @@ public:
|
||||
|
||||
////
|
||||
|
||||
for (const auto& progAttrib : mWebGL->mActiveProgramLinkInfo->attribs) {
|
||||
const auto& loc = progAttrib.mLoc;
|
||||
|
||||
const auto& attribData = mWebGL->mBoundVertexArray->mAttribs[loc];
|
||||
|
||||
GLenum attribDataBaseType;
|
||||
if (attribData.mEnabled) {
|
||||
attribDataBaseType = attribData.BaseType();
|
||||
} else {
|
||||
attribDataBaseType = mWebGL->mGenericVertexAttribTypes[loc];
|
||||
}
|
||||
|
||||
if (attribDataBaseType != progAttrib.mBaseType) {
|
||||
nsCString progType, dataType;
|
||||
WebGLContext::EnumName(progAttrib.mBaseType, &progType);
|
||||
WebGLContext::EnumName(attribDataBaseType, &dataType);
|
||||
mWebGL->ErrorInvalidOperation("%s: Vertex attrib %u requires data of type"
|
||||
" %s, but is being supplied with type %s.",
|
||||
funcName, loc, progType.BeginReading(),
|
||||
dataType.BeginReading());
|
||||
*out_error = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
////
|
||||
|
||||
mWebGL->RunContextLossTimer();
|
||||
}
|
||||
|
||||
@ -686,9 +713,11 @@ WebGLContext::DrawElements_check(const char* funcName, GLenum mode, GLsizei vert
|
||||
|
||||
// Bug 1008310 - Check if buffer has been used with a different previous type
|
||||
if (elemArrayBuffer.IsElementArrayUsedWithMultipleTypes()) {
|
||||
nsCString typeName;
|
||||
WebGLContext::EnumName(type, &typeName);
|
||||
GenerateWarning("%s: bound element array buffer previously used with a type other than "
|
||||
"%s, this will affect performance.",
|
||||
funcName, WebGLContext::EnumName(type));
|
||||
funcName, typeName.BeginReading());
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -957,23 +986,25 @@ WebGLContext::ValidateBufferFetching(const char* info)
|
||||
}
|
||||
|
||||
WebGLVertexAttrib0Status
|
||||
WebGLContext::WhatDoesVertexAttrib0Need()
|
||||
WebGLContext::WhatDoesVertexAttrib0Need() const
|
||||
{
|
||||
MOZ_ASSERT(mCurrentProgram);
|
||||
MOZ_ASSERT(mActiveProgramLinkInfo);
|
||||
|
||||
const auto& isAttribArray0Enabled = mBoundVertexArray->mAttribs[0].mEnabled;
|
||||
|
||||
// work around Mac OSX crash, see bug 631420
|
||||
#ifdef XP_MACOSX
|
||||
if (gl->WorkAroundDriverBugs() &&
|
||||
mBoundVertexArray->IsAttribArrayEnabled(0) &&
|
||||
isAttribArray0Enabled &&
|
||||
!mBufferFetch_IsAttrib0Active)
|
||||
{
|
||||
return WebGLVertexAttrib0Status::EmulatedUninitializedArray;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (MOZ_LIKELY(gl->IsGLES() ||
|
||||
mBoundVertexArray->IsAttribArrayEnabled(0)))
|
||||
if (MOZ_LIKELY(!gl->IsCompatibilityProfile() ||
|
||||
isAttribArray0Enabled))
|
||||
{
|
||||
return WebGLVertexAttrib0Status::Default;
|
||||
}
|
||||
@ -984,10 +1015,13 @@ WebGLContext::WhatDoesVertexAttrib0Need()
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLContext::DoFakeVertexAttrib0(GLuint vertexCount)
|
||||
WebGLContext::DoFakeVertexAttrib0(const char* funcName, GLuint vertexCount)
|
||||
{
|
||||
WebGLVertexAttrib0Status whatDoesAttrib0Need = WhatDoesVertexAttrib0Need();
|
||||
if (!vertexCount) {
|
||||
vertexCount = 1;
|
||||
}
|
||||
|
||||
const auto whatDoesAttrib0Need = WhatDoesVertexAttrib0Need();
|
||||
if (MOZ_LIKELY(whatDoesAttrib0Need == WebGLVertexAttrib0Status::Default))
|
||||
return true;
|
||||
|
||||
@ -1000,88 +1034,101 @@ WebGLContext::DoFakeVertexAttrib0(GLuint vertexCount)
|
||||
mAlreadyWarnedAboutFakeVertexAttrib0 = true;
|
||||
}
|
||||
|
||||
CheckedUint32 checked_dataSize = CheckedUint32(vertexCount) * 4 * sizeof(GLfloat);
|
||||
if (!mFakeVertexAttrib0BufferObject) {
|
||||
gl->fGenBuffers(1, &mFakeVertexAttrib0BufferObject);
|
||||
mFakeVertexAttrib0BufferObjectSize = 0;
|
||||
}
|
||||
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mFakeVertexAttrib0BufferObject);
|
||||
|
||||
////
|
||||
|
||||
switch (mGenericVertexAttribTypes[0]) {
|
||||
case LOCAL_GL_FLOAT:
|
||||
gl->fVertexAttribPointer(0, 4, LOCAL_GL_FLOAT, false, 0, 0);
|
||||
break;
|
||||
|
||||
case LOCAL_GL_INT:
|
||||
gl->fVertexAttribIPointer(0, 4, LOCAL_GL_INT, 0, 0);
|
||||
break;
|
||||
|
||||
case LOCAL_GL_UNSIGNED_INT:
|
||||
gl->fVertexAttribIPointer(0, 4, LOCAL_GL_UNSIGNED_INT, 0, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
////
|
||||
|
||||
const auto bytesPerVert = sizeof(mFakeVertexAttrib0Data);
|
||||
const auto checked_dataSize = CheckedUint32(vertexCount) * bytesPerVert;
|
||||
if (!checked_dataSize.isValid()) {
|
||||
ErrorOutOfMemory("Integer overflow trying to construct a fake vertex attrib 0 array for a draw-operation "
|
||||
"with %d vertices. Try reducing the number of vertices.", vertexCount);
|
||||
return false;
|
||||
}
|
||||
const auto dataSize = checked_dataSize.value();
|
||||
|
||||
GLuint dataSize = checked_dataSize.value();
|
||||
|
||||
if (!mFakeVertexAttrib0BufferObject) {
|
||||
gl->fGenBuffers(1, &mFakeVertexAttrib0BufferObject);
|
||||
if (mFakeVertexAttrib0BufferObjectSize < dataSize) {
|
||||
gl->fBufferData(LOCAL_GL_ARRAY_BUFFER, dataSize, nullptr, LOCAL_GL_DYNAMIC_DRAW);
|
||||
mFakeVertexAttrib0BufferObjectSize = dataSize;
|
||||
mFakeVertexAttrib0DataDefined = false;
|
||||
}
|
||||
|
||||
// if the VBO status is already exactly what we need, or if the only difference is that it's initialized and
|
||||
// we don't need it to be, then consider it OK
|
||||
bool vertexAttrib0BufferStatusOK =
|
||||
mFakeVertexAttrib0BufferStatus == whatDoesAttrib0Need ||
|
||||
(mFakeVertexAttrib0BufferStatus == WebGLVertexAttrib0Status::EmulatedInitializedArray &&
|
||||
whatDoesAttrib0Need == WebGLVertexAttrib0Status::EmulatedUninitializedArray);
|
||||
if (whatDoesAttrib0Need == WebGLVertexAttrib0Status::EmulatedUninitializedArray)
|
||||
return true;
|
||||
|
||||
if (!vertexAttrib0BufferStatusOK ||
|
||||
mFakeVertexAttrib0BufferObjectSize < dataSize ||
|
||||
mFakeVertexAttrib0BufferObjectVector[0] != mVertexAttrib0Vector[0] ||
|
||||
mFakeVertexAttrib0BufferObjectVector[1] != mVertexAttrib0Vector[1] ||
|
||||
mFakeVertexAttrib0BufferObjectVector[2] != mVertexAttrib0Vector[2] ||
|
||||
mFakeVertexAttrib0BufferObjectVector[3] != mVertexAttrib0Vector[3])
|
||||
////
|
||||
|
||||
if (mFakeVertexAttrib0DataDefined &&
|
||||
memcmp(mFakeVertexAttrib0Data, mGenericVertexAttrib0Data, bytesPerVert) == 0)
|
||||
{
|
||||
mFakeVertexAttrib0BufferStatus = whatDoesAttrib0Need;
|
||||
mFakeVertexAttrib0BufferObjectSize = dataSize;
|
||||
mFakeVertexAttrib0BufferObjectVector[0] = mVertexAttrib0Vector[0];
|
||||
mFakeVertexAttrib0BufferObjectVector[1] = mVertexAttrib0Vector[1];
|
||||
mFakeVertexAttrib0BufferObjectVector[2] = mVertexAttrib0Vector[2];
|
||||
mFakeVertexAttrib0BufferObjectVector[3] = mVertexAttrib0Vector[3];
|
||||
return true;
|
||||
}
|
||||
|
||||
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mFakeVertexAttrib0BufferObject);
|
||||
////
|
||||
|
||||
GetAndFlushUnderlyingGLErrors();
|
||||
const UniqueBuffer data(malloc(dataSize));
|
||||
if (!data) {
|
||||
ErrorOutOfMemory("%s: Failed to allocate fake vertex attrib 0 array.",
|
||||
funcName);
|
||||
return false;
|
||||
}
|
||||
auto itr = (uint8_t*)data.get();
|
||||
const auto itrEnd = itr + dataSize;
|
||||
while (itr != itrEnd) {
|
||||
memcpy(itr, mGenericVertexAttrib0Data, bytesPerVert);
|
||||
itr += bytesPerVert;
|
||||
}
|
||||
|
||||
if (mFakeVertexAttrib0BufferStatus == WebGLVertexAttrib0Status::EmulatedInitializedArray) {
|
||||
auto array = MakeUniqueFallible<GLfloat[]>(4 * vertexCount);
|
||||
if (!array) {
|
||||
ErrorOutOfMemory("Fake attrib0 array.");
|
||||
return false;
|
||||
}
|
||||
for(size_t i = 0; i < vertexCount; ++i) {
|
||||
array[4 * i + 0] = mVertexAttrib0Vector[0];
|
||||
array[4 * i + 1] = mVertexAttrib0Vector[1];
|
||||
array[4 * i + 2] = mVertexAttrib0Vector[2];
|
||||
array[4 * i + 3] = mVertexAttrib0Vector[3];
|
||||
}
|
||||
gl->fBufferData(LOCAL_GL_ARRAY_BUFFER, dataSize, array.get(), LOCAL_GL_DYNAMIC_DRAW);
|
||||
} else {
|
||||
gl->fBufferData(LOCAL_GL_ARRAY_BUFFER, dataSize, nullptr, LOCAL_GL_DYNAMIC_DRAW);
|
||||
}
|
||||
GLenum error = GetAndFlushUnderlyingGLErrors();
|
||||
{
|
||||
gl::GLContext::LocalErrorScope errorScope(*gl);
|
||||
|
||||
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundArrayBuffer ? mBoundArrayBuffer->mGLName : 0);
|
||||
gl->fBufferSubData(LOCAL_GL_ARRAY_BUFFER, 0, dataSize, data.get());
|
||||
|
||||
// note that we do this error checking and early return AFTER having restored the buffer binding above
|
||||
if (error) {
|
||||
ErrorOutOfMemory("Ran out of memory trying to construct a fake vertex attrib 0 array for a draw-operation "
|
||||
"with %d vertices. Try reducing the number of vertices.", vertexCount);
|
||||
const auto err = errorScope.GetError();
|
||||
if (err) {
|
||||
ErrorOutOfMemory("%s: Failed to upload fake vertex attrib 0 data.", funcName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mFakeVertexAttrib0BufferObject);
|
||||
gl->fVertexAttribPointer(0, 4, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, 0);
|
||||
////
|
||||
|
||||
memcpy(mFakeVertexAttrib0Data, mGenericVertexAttrib0Data, bytesPerVert);
|
||||
mFakeVertexAttrib0DataDefined = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::UndoFakeVertexAttrib0()
|
||||
{
|
||||
WebGLVertexAttrib0Status whatDoesAttrib0Need = WhatDoesVertexAttrib0Need();
|
||||
|
||||
const auto whatDoesAttrib0Need = WhatDoesVertexAttrib0Need();
|
||||
if (MOZ_LIKELY(whatDoesAttrib0Need == WebGLVertexAttrib0Status::Default))
|
||||
return;
|
||||
|
||||
if (mBoundVertexArray->HasAttrib(0) && mBoundVertexArray->mAttribs[0].mBuf) {
|
||||
if (mBoundVertexArray->mAttribs[0].mBuf) {
|
||||
const WebGLVertexAttribData& attrib0 = mBoundVertexArray->mAttribs[0];
|
||||
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, attrib0.mBuf->mGLName);
|
||||
attrib0.DoVertexAttribPointer(gl, 0);
|
||||
|
@ -246,12 +246,13 @@ WebGLContext::ErrorName(GLenum error)
|
||||
}
|
||||
}
|
||||
|
||||
// This version is 'fallible' and will return NULL if glenum is not recognized.
|
||||
const char*
|
||||
WebGLContext::EnumName(GLenum glenum)
|
||||
// This version is fallible and will return nullptr if unrecognized.
|
||||
static const char*
|
||||
GetEnumName(GLenum val)
|
||||
{
|
||||
switch (glenum) {
|
||||
switch (val) {
|
||||
#define XX(x) case LOCAL_GL_##x: return #x
|
||||
XX(NONE);
|
||||
XX(ALPHA);
|
||||
XX(ATC_RGB);
|
||||
XX(ATC_RGBA_EXPLICIT_ALPHA);
|
||||
@ -273,6 +274,7 @@ WebGLContext::EnumName(GLenum glenum)
|
||||
XX(DRAW_FRAMEBUFFER);
|
||||
XX(ETC1_RGB8_OES);
|
||||
XX(FLOAT);
|
||||
XX(INT);
|
||||
XX(FRAMEBUFFER);
|
||||
XX(HALF_FLOAT);
|
||||
XX(LUMINANCE);
|
||||
@ -574,16 +576,24 @@ WebGLContext::EnumName(GLenum glenum)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::EnumName(GLenum glenum, nsACString* out_name)
|
||||
/*static*/ void
|
||||
WebGLContext::EnumName(GLenum val, nsCString* out_name)
|
||||
{
|
||||
const char* name = EnumName(glenum);
|
||||
const char* name = GetEnumName(val);
|
||||
if (name) {
|
||||
*out_name = nsDependentCString(name);
|
||||
} else {
|
||||
nsPrintfCString enumAsHex("<enum 0x%04x>", glenum);
|
||||
*out_name = enumAsHex;
|
||||
*out_name = name;
|
||||
return;
|
||||
}
|
||||
|
||||
*out_name = nsPrintfCString("<enum 0x%04x>", val);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::ErrorInvalidEnumArg(const char* funcName, const char* argName, GLenum val)
|
||||
{
|
||||
nsCString enumName;
|
||||
EnumName(val, &enumName);
|
||||
ErrorInvalidEnum("%s: Bad `%s`: %s", funcName, argName, enumName.BeginReading());
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -543,7 +543,7 @@ WebGLContext::InitAndValidateGL(FailureReason* const out_failReason)
|
||||
if (MinCapabilityMode())
|
||||
mGLMaxVertexAttribs = MINVALUE_GL_MAX_VERTEX_ATTRIBS;
|
||||
else
|
||||
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, &mGLMaxVertexAttribs);
|
||||
gl->GetUIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, &mGLMaxVertexAttribs);
|
||||
|
||||
if (mGLMaxVertexAttribs < 8) {
|
||||
const nsPrintfCString reason("GL_MAX_VERTEX_ATTRIBS: %d is < 8!",
|
||||
@ -740,13 +740,6 @@ WebGLContext::InitAndValidateGL(FailureReason* const out_failReason)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Default value for all disabled vertex attributes is [0, 0, 0, 1]
|
||||
mVertexAttribType = MakeUnique<GLenum[]>(mGLMaxVertexAttribs);
|
||||
for (int32_t index = 0; index < mGLMaxVertexAttribs; ++index) {
|
||||
mVertexAttribType[index] = LOCAL_GL_FLOAT;
|
||||
VertexAttrib4f(index, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
mDefaultVertexArray = WebGLVertexArray::Create(this);
|
||||
mDefaultVertexArray->mAttribs.SetLength(mGLMaxVertexAttribs);
|
||||
mBoundVertexArray = mDefaultVertexArray;
|
||||
@ -783,6 +776,15 @@ WebGLContext::InitAndValidateGL(FailureReason* const out_failReason)
|
||||
|
||||
mPrimRestartTypeBytes = 0;
|
||||
|
||||
mGenericVertexAttribTypes.reset(new GLenum[mGLMaxVertexAttribs]);
|
||||
std::fill_n(mGenericVertexAttribTypes.get(), mGLMaxVertexAttribs, LOCAL_GL_FLOAT);
|
||||
|
||||
static const float kDefaultGenericVertexAttribData[4] = { 0, 0, 0, 1 };
|
||||
memcpy(mGenericVertexAttrib0Data, kDefaultGenericVertexAttribData,
|
||||
sizeof(mGenericVertexAttrib0Data));
|
||||
|
||||
mFakeVertexAttrib0BufferObject = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -809,8 +811,7 @@ WebGLContext::ValidateFramebufferTarget(GLenum target,
|
||||
return true;
|
||||
}
|
||||
|
||||
ErrorInvalidEnum("%s: Invalid target: %s (0x%04x).", info, EnumName(target),
|
||||
target);
|
||||
ErrorInvalidEnumArg(info, "target", target);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -20,50 +20,15 @@
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
void
|
||||
WebGLContext::GetVertexAttribFloat(GLuint index, GLfloat* out_result)
|
||||
{
|
||||
if (index) {
|
||||
gl->fGetVertexAttribfv(index, LOCAL_GL_CURRENT_VERTEX_ATTRIB, out_result);
|
||||
} else {
|
||||
out_result[0] = mVertexAttrib0Vector[0];
|
||||
out_result[1] = mVertexAttrib0Vector[1];
|
||||
out_result[2] = mVertexAttrib0Vector[2];
|
||||
out_result[3] = mVertexAttrib0Vector[3];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::GetVertexAttribInt(GLuint index, GLint* out_result)
|
||||
{
|
||||
if (index) {
|
||||
gl->fGetVertexAttribIiv(index, LOCAL_GL_CURRENT_VERTEX_ATTRIB, out_result);
|
||||
} else {
|
||||
out_result[0] = BitwiseCast<GLint>(mVertexAttrib0Vector[0]);
|
||||
out_result[1] = BitwiseCast<GLint>(mVertexAttrib0Vector[1]);
|
||||
out_result[2] = BitwiseCast<GLint>(mVertexAttrib0Vector[2]);
|
||||
out_result[3] = BitwiseCast<GLint>(mVertexAttrib0Vector[3]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::GetVertexAttribUint(GLuint index, GLuint* out_result)
|
||||
{
|
||||
if (index) {
|
||||
gl->fGetVertexAttribIuiv(index, LOCAL_GL_CURRENT_VERTEX_ATTRIB, out_result);
|
||||
} else {
|
||||
out_result[0] = BitwiseCast<GLuint>(mVertexAttrib0Vector[0]);
|
||||
out_result[1] = BitwiseCast<GLuint>(mVertexAttrib0Vector[1]);
|
||||
out_result[2] = BitwiseCast<GLuint>(mVertexAttrib0Vector[2]);
|
||||
out_result[3] = BitwiseCast<GLuint>(mVertexAttrib0Vector[3]);
|
||||
}
|
||||
}
|
||||
|
||||
JSObject*
|
||||
WebGLContext::GetVertexAttribFloat32Array(JSContext* cx, GLuint index)
|
||||
{
|
||||
GLfloat attrib[4];
|
||||
GetVertexAttribFloat(index, &attrib[0]);
|
||||
if (index) {
|
||||
gl->fGetVertexAttribfv(index, LOCAL_GL_CURRENT_VERTEX_ATTRIB, attrib);
|
||||
} else {
|
||||
memcpy(attrib, mGenericVertexAttrib0Data, sizeof(mGenericVertexAttrib0Data));
|
||||
}
|
||||
return dom::Float32Array::Create(cx, this, 4, attrib);
|
||||
}
|
||||
|
||||
@ -71,218 +36,122 @@ JSObject*
|
||||
WebGLContext::GetVertexAttribInt32Array(JSContext* cx, GLuint index)
|
||||
{
|
||||
GLint attrib[4];
|
||||
GetVertexAttribInt(index, &attrib[0]);
|
||||
if (index) {
|
||||
gl->fGetVertexAttribIiv(index, LOCAL_GL_CURRENT_VERTEX_ATTRIB, attrib);
|
||||
} else {
|
||||
memcpy(attrib, mGenericVertexAttrib0Data, sizeof(mGenericVertexAttrib0Data));
|
||||
}
|
||||
return dom::Int32Array::Create(cx, this, 4, attrib);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
WebGLContext::GetVertexAttribUint32Array(JSContext* cx, GLuint index) {
|
||||
WebGLContext::GetVertexAttribUint32Array(JSContext* cx, GLuint index)
|
||||
{
|
||||
GLuint attrib[4];
|
||||
GetVertexAttribUint(index, &attrib[0]);
|
||||
if (index) {
|
||||
gl->fGetVertexAttribIuiv(index, LOCAL_GL_CURRENT_VERTEX_ATTRIB, attrib);
|
||||
} else {
|
||||
memcpy(attrib, mGenericVertexAttrib0Data, sizeof(mGenericVertexAttrib0Data));
|
||||
}
|
||||
return dom::Uint32Array::Create(cx, this, 4, attrib);
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
void
|
||||
WebGLContext::VertexAttrib1f(GLuint index, GLfloat x0)
|
||||
WebGLContext::VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w,
|
||||
const char* funcName)
|
||||
{
|
||||
if (!funcName) {
|
||||
funcName = "vertexAttrib4f";
|
||||
}
|
||||
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
if (!ValidateAttribIndex(index, "vertexAttrib1f"))
|
||||
if (!ValidateAttribIndex(index, funcName))
|
||||
return;
|
||||
|
||||
mVertexAttribType[index] = LOCAL_GL_FLOAT;
|
||||
////
|
||||
|
||||
MakeContextCurrent();
|
||||
gl->MakeCurrent();
|
||||
if (index || !gl->IsCompatibilityProfile()) {
|
||||
gl->fVertexAttrib4f(index, x, y, z, w);
|
||||
}
|
||||
|
||||
if (index) {
|
||||
gl->fVertexAttrib1f(index, x0);
|
||||
} else {
|
||||
mVertexAttrib0Vector[0] = x0;
|
||||
mVertexAttrib0Vector[1] = 0;
|
||||
mVertexAttrib0Vector[2] = 0;
|
||||
mVertexAttrib0Vector[3] = 1;
|
||||
if (gl->IsGLES())
|
||||
gl->fVertexAttrib1f(index, x0);
|
||||
////
|
||||
|
||||
mGenericVertexAttribTypes[index] = LOCAL_GL_FLOAT;
|
||||
|
||||
if (!index) {
|
||||
const float data[4] = { x, y, z, w };
|
||||
memcpy(mGenericVertexAttrib0Data, data, sizeof(data));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::VertexAttrib2f(GLuint index, GLfloat x0, GLfloat x1)
|
||||
WebGL2Context::VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w,
|
||||
const char* funcName)
|
||||
{
|
||||
if (!funcName) {
|
||||
funcName = "vertexAttribI4i";
|
||||
}
|
||||
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
if (!ValidateAttribIndex(index, "vertexAttrib2f"))
|
||||
if (!ValidateAttribIndex(index, funcName))
|
||||
return;
|
||||
|
||||
mVertexAttribType[index] = LOCAL_GL_FLOAT;
|
||||
////
|
||||
|
||||
MakeContextCurrent();
|
||||
gl->MakeCurrent();
|
||||
if (index || !gl->IsCompatibilityProfile()) {
|
||||
gl->fVertexAttribI4i(index, x, y, z, w);
|
||||
}
|
||||
|
||||
if (index) {
|
||||
gl->fVertexAttrib2f(index, x0, x1);
|
||||
} else {
|
||||
mVertexAttrib0Vector[0] = x0;
|
||||
mVertexAttrib0Vector[1] = x1;
|
||||
mVertexAttrib0Vector[2] = 0;
|
||||
mVertexAttrib0Vector[3] = 1;
|
||||
if (gl->IsGLES())
|
||||
gl->fVertexAttrib2f(index, x0, x1);
|
||||
////
|
||||
|
||||
mGenericVertexAttribTypes[index] = LOCAL_GL_INT;
|
||||
|
||||
if (!index) {
|
||||
const int32_t data[4] = { x, y, z, w };
|
||||
memcpy(mGenericVertexAttrib0Data, data, sizeof(data));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::VertexAttrib3f(GLuint index, GLfloat x0, GLfloat x1, GLfloat x2)
|
||||
WebGL2Context::VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w,
|
||||
const char* funcName)
|
||||
{
|
||||
if (!funcName) {
|
||||
funcName = "vertexAttribI4ui";
|
||||
}
|
||||
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
if (!ValidateAttribIndex(index, "vertexAttrib3f"))
|
||||
if (!ValidateAttribIndex(index, funcName))
|
||||
return;
|
||||
|
||||
mVertexAttribType[index] = LOCAL_GL_FLOAT;
|
||||
////
|
||||
|
||||
MakeContextCurrent();
|
||||
gl->MakeCurrent();
|
||||
if (index || !gl->IsCompatibilityProfile()) {
|
||||
gl->fVertexAttribI4ui(index, x, y, z, w);
|
||||
}
|
||||
|
||||
if (index) {
|
||||
gl->fVertexAttrib3f(index, x0, x1, x2);
|
||||
} else {
|
||||
mVertexAttrib0Vector[0] = x0;
|
||||
mVertexAttrib0Vector[1] = x1;
|
||||
mVertexAttrib0Vector[2] = x2;
|
||||
mVertexAttrib0Vector[3] = 1;
|
||||
if (gl->IsGLES())
|
||||
gl->fVertexAttrib3f(index, x0, x1, x2);
|
||||
////
|
||||
|
||||
mGenericVertexAttribTypes[index] = LOCAL_GL_UNSIGNED_INT;
|
||||
|
||||
if (!index) {
|
||||
const uint32_t data[4] = { x, y, z, w };
|
||||
memcpy(mGenericVertexAttrib0Data, data, sizeof(data));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::VertexAttrib4f(GLuint index, GLfloat x0, GLfloat x1,
|
||||
GLfloat x2, GLfloat x3)
|
||||
{
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
if (!ValidateAttribIndex(index, "vertexAttrib4f"))
|
||||
return;
|
||||
|
||||
mVertexAttribType[index] = LOCAL_GL_FLOAT;
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (index) {
|
||||
gl->fVertexAttrib4f(index, x0, x1, x2, x3);
|
||||
} else {
|
||||
mVertexAttrib0Vector[0] = x0;
|
||||
mVertexAttrib0Vector[1] = x1;
|
||||
mVertexAttrib0Vector[2] = x2;
|
||||
mVertexAttrib0Vector[3] = x3;
|
||||
if (gl->IsGLES())
|
||||
gl->fVertexAttrib4f(index, x0, x1, x2, x3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WebGLContext::VertexAttrib1fv_base(GLuint index, uint32_t arrayLength,
|
||||
const GLfloat* ptr)
|
||||
{
|
||||
if (!ValidateAttribArraySetter("VertexAttrib1fv", 1, arrayLength))
|
||||
return;
|
||||
|
||||
if (!ValidateAttribIndex(index, "vertexAttrib1fv"))
|
||||
return;
|
||||
|
||||
mVertexAttribType[index] = LOCAL_GL_FLOAT;
|
||||
|
||||
MakeContextCurrent();
|
||||
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(index, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::VertexAttrib2fv_base(GLuint index, uint32_t arrayLength,
|
||||
const GLfloat* ptr)
|
||||
{
|
||||
if (!ValidateAttribArraySetter("VertexAttrib2fv", 2, arrayLength))
|
||||
return;
|
||||
|
||||
if (!ValidateAttribIndex(index, "vertexAttrib2fv"))
|
||||
return;
|
||||
|
||||
mVertexAttribType[index] = LOCAL_GL_FLOAT;
|
||||
|
||||
MakeContextCurrent();
|
||||
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(index, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::VertexAttrib3fv_base(GLuint index, uint32_t arrayLength,
|
||||
const GLfloat* ptr)
|
||||
{
|
||||
if (!ValidateAttribArraySetter("VertexAttrib3fv", 3, arrayLength))
|
||||
return;
|
||||
|
||||
if (!ValidateAttribIndex(index, "vertexAttrib3fv"))
|
||||
return;
|
||||
|
||||
mVertexAttribType[index] = LOCAL_GL_FLOAT;
|
||||
|
||||
MakeContextCurrent();
|
||||
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(index, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::VertexAttrib4fv_base(GLuint index, uint32_t arrayLength,
|
||||
const GLfloat* ptr)
|
||||
{
|
||||
if (!ValidateAttribArraySetter("VertexAttrib4fv", 4, arrayLength))
|
||||
return;
|
||||
|
||||
if (!ValidateAttribIndex(index, "vertexAttrib4fv"))
|
||||
return;
|
||||
|
||||
mVertexAttribType[index] = LOCAL_GL_FLOAT;
|
||||
|
||||
MakeContextCurrent();
|
||||
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(index, ptr);
|
||||
}
|
||||
}
|
||||
////////////////////////////////////////
|
||||
|
||||
void
|
||||
WebGLContext::EnableVertexAttribArray(GLuint index)
|
||||
@ -299,7 +168,6 @@ WebGLContext::EnableVertexAttribArray(GLuint index)
|
||||
gl->fEnableVertexAttribArray(index);
|
||||
|
||||
MOZ_ASSERT(mBoundVertexArray);
|
||||
mBoundVertexArray->EnsureAttrib(index);
|
||||
mBoundVertexArray->mAttribs[index].mEnabled = true;
|
||||
}
|
||||
|
||||
@ -315,12 +183,11 @@ WebGLContext::DisableVertexAttribArray(GLuint index)
|
||||
MakeContextCurrent();
|
||||
InvalidateBufferFetching();
|
||||
|
||||
if (index || gl->IsGLES()) {
|
||||
if (index || !gl->IsCompatibilityProfile()) {
|
||||
gl->fDisableVertexAttribArray(index);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mBoundVertexArray);
|
||||
mBoundVertexArray->EnsureAttrib(index);
|
||||
mBoundVertexArray->mAttribs[index].mEnabled = false;
|
||||
}
|
||||
|
||||
@ -328,14 +195,14 @@ JS::Value
|
||||
WebGLContext::GetVertexAttrib(JSContext* cx, GLuint index, GLenum pname,
|
||||
ErrorResult& rv)
|
||||
{
|
||||
const char funcName[] = "getVertexAttrib";
|
||||
if (IsContextLost())
|
||||
return JS::NullValue();
|
||||
|
||||
if (!ValidateAttribIndex(index, "getVertexAttrib"))
|
||||
if (!ValidateAttribIndex(index, funcName))
|
||||
return JS::NullValue();
|
||||
|
||||
MOZ_ASSERT(mBoundVertexArray);
|
||||
mBoundVertexArray->EnsureAttrib(index);
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
@ -369,7 +236,7 @@ WebGLContext::GetVertexAttrib(JSContext* cx, GLuint index, GLenum pname,
|
||||
case LOCAL_GL_CURRENT_VERTEX_ATTRIB:
|
||||
{
|
||||
JS::RootedObject obj(cx);
|
||||
switch (mVertexAttribType[index]) {
|
||||
switch (mGenericVertexAttribTypes[index]) {
|
||||
case LOCAL_GL_FLOAT:
|
||||
obj = GetVertexAttribFloat32Array(cx, index);
|
||||
break;
|
||||
@ -417,7 +284,6 @@ WebGLContext::GetVertexAttribOffset(GLuint index, GLenum pname)
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mBoundVertexArray);
|
||||
mBoundVertexArray->EnsureAttrib(index);
|
||||
return mBoundVertexArray->mAttribs[index].ByteOffset();
|
||||
}
|
||||
|
||||
@ -436,7 +302,6 @@ WebGLContext::VertexAttribPointer(GLuint index, GLint size, GLenum type,
|
||||
return;
|
||||
|
||||
MOZ_ASSERT(mBoundVertexArray);
|
||||
mBoundVertexArray->EnsureAttrib(index);
|
||||
|
||||
InvalidateBufferFetching();
|
||||
|
||||
@ -465,7 +330,6 @@ WebGLContext::VertexAttribDivisor(GLuint index, GLuint divisor)
|
||||
return;
|
||||
|
||||
MOZ_ASSERT(mBoundVertexArray);
|
||||
mBoundVertexArray->EnsureAttrib(index);
|
||||
|
||||
WebGLVertexAttribData& vd = mBoundVertexArray->mAttribs[index];
|
||||
vd.mDivisor = divisor;
|
||||
|
@ -423,13 +423,14 @@ WebGLFBAttachPoint::GetParameter(const char* funcName, WebGLContext* webgl, JSCo
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
nsCString attachmentName;
|
||||
WebGLContext::EnumName(attachment, &attachmentName);
|
||||
if (webgl->IsWebGL2()) {
|
||||
webgl->ErrorInvalidOperation("%s: No attachment at %s.", funcName,
|
||||
webgl->EnumName(attachment));
|
||||
attachmentName.BeginReading());
|
||||
} else {
|
||||
webgl->ErrorInvalidEnum("%s: No attachment at %s.", funcName,
|
||||
webgl->EnumName(attachment));
|
||||
attachmentName.BeginReading());
|
||||
}
|
||||
return JS::NullValue();
|
||||
}
|
||||
|
@ -83,7 +83,49 @@ AssembleName(const nsCString& baseName, bool isArray, size_t arrayIndex,
|
||||
}
|
||||
}
|
||||
|
||||
//////////
|
||||
////
|
||||
|
||||
static GLenum
|
||||
AttribBaseType(GLenum attribType)
|
||||
{
|
||||
switch (attribType) {
|
||||
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_MAT2x3:
|
||||
case LOCAL_GL_FLOAT_MAT2x4:
|
||||
|
||||
case LOCAL_GL_FLOAT_MAT3x2:
|
||||
case LOCAL_GL_FLOAT_MAT3:
|
||||
case LOCAL_GL_FLOAT_MAT3x4:
|
||||
|
||||
case LOCAL_GL_FLOAT_MAT4x2:
|
||||
case LOCAL_GL_FLOAT_MAT4x3:
|
||||
case LOCAL_GL_FLOAT_MAT4:
|
||||
return LOCAL_GL_FLOAT;
|
||||
|
||||
case LOCAL_GL_INT:
|
||||
case LOCAL_GL_INT_VEC2:
|
||||
case LOCAL_GL_INT_VEC3:
|
||||
case LOCAL_GL_INT_VEC4:
|
||||
return LOCAL_GL_INT;
|
||||
|
||||
case LOCAL_GL_UNSIGNED_INT:
|
||||
case LOCAL_GL_UNSIGNED_INT_VEC2:
|
||||
case LOCAL_GL_UNSIGNED_INT_VEC3:
|
||||
case LOCAL_GL_UNSIGNED_INT_VEC4:
|
||||
return LOCAL_GL_UNSIGNED_INT;
|
||||
|
||||
default:
|
||||
MOZ_ASSERT(false, "unexpected attrib elemType");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
////
|
||||
|
||||
/*static*/ const webgl::UniformInfo::TexListT*
|
||||
webgl::UniformInfo::GetTexList(WebGLActiveInfo* activeInfo)
|
||||
@ -225,7 +267,8 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
|
||||
elemType, isArray,
|
||||
userName,
|
||||
mappedName);
|
||||
const webgl::AttribInfo attrib = {activeInfo, uint32_t(loc)};
|
||||
const GLenum baseType = AttribBaseType(elemType);
|
||||
const webgl::AttribInfo attrib = {activeInfo, uint32_t(loc), baseType};
|
||||
info->attribs.push_back(attrib);
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,8 @@ namespace webgl {
|
||||
struct AttribInfo final
|
||||
{
|
||||
const RefPtr<WebGLActiveInfo> mActiveInfo;
|
||||
uint32_t mLoc;
|
||||
const uint32_t mLoc;
|
||||
const GLenum mBaseType;
|
||||
};
|
||||
|
||||
struct UniformInfo final
|
||||
@ -122,6 +123,7 @@ class WebGLProgram final
|
||||
, public LinkedListElement<WebGLProgram>
|
||||
{
|
||||
friend class WebGLTransformFeedback;
|
||||
friend struct webgl::LinkedProgramInfo;
|
||||
|
||||
public:
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLProgram)
|
||||
|
@ -136,8 +136,7 @@ WebGLQuery::GetQueryParameter(GLenum pname, JS::MutableHandleValue retval) const
|
||||
break;
|
||||
|
||||
default:
|
||||
mContext->ErrorInvalidEnum("%s: Invalid pname: %s", funcName,
|
||||
mContext->EnumName(pname));
|
||||
mContext->ErrorInvalidEnumArg(funcName, "pname", pname);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -133,12 +133,11 @@ ValidateSamplerParameterParams(WebGLContext* webgl, const char* funcName, GLenum
|
||||
break;
|
||||
|
||||
default:
|
||||
webgl->ErrorInvalidEnum("%s: invalid pname: %s", funcName,
|
||||
webgl->EnumName(pname));
|
||||
webgl->ErrorInvalidEnumArg(funcName, "pname", pname);
|
||||
return false;
|
||||
}
|
||||
|
||||
webgl->ErrorInvalidEnum("%s: invalid param: %s", funcName, webgl->EnumName(paramInt));
|
||||
webgl->ErrorInvalidEnumArg(funcName, "param", paramInt);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -89,6 +89,7 @@ public:
|
||||
public:
|
||||
const GLuint mGLName;
|
||||
const GLenum mType;
|
||||
|
||||
protected:
|
||||
nsString mSource;
|
||||
nsCString mCleanSource;
|
||||
|
@ -24,6 +24,7 @@ WebGLVertexArray::WebGLVertexArray(WebGLContext* webgl)
|
||||
: WebGLRefCountedObject(webgl)
|
||||
, mGLName(0)
|
||||
{
|
||||
mAttribs.SetLength(mContext->mGLMaxVertexAttribs);
|
||||
mContext->mVertexArrays.insertBack(this);
|
||||
}
|
||||
|
||||
@ -55,16 +56,6 @@ WebGLVertexArray::IsVertexArray() const
|
||||
return IsVertexArrayImpl();
|
||||
}
|
||||
|
||||
void
|
||||
WebGLVertexArray::EnsureAttrib(GLuint index)
|
||||
{
|
||||
MOZ_ASSERT(index < GLuint(mContext->mGLMaxVertexAttribs));
|
||||
|
||||
if (index >= mAttribs.Length()) {
|
||||
mAttribs.SetLength(index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLVertexArray,
|
||||
mAttribs,
|
||||
mElementArrayBuffer)
|
||||
|
@ -33,14 +33,6 @@ public:
|
||||
BindVertexArrayImpl();
|
||||
};
|
||||
|
||||
void EnsureAttrib(GLuint index);
|
||||
bool HasAttrib(GLuint index) const {
|
||||
return index < mAttribs.Length();
|
||||
}
|
||||
bool IsAttribArrayEnabled(GLuint index) const {
|
||||
return HasAttrib(index) && mAttribs[index].mEnabled;
|
||||
}
|
||||
|
||||
// Implement parent classes:
|
||||
void Delete();
|
||||
bool IsVertexArray() const;
|
||||
@ -72,6 +64,7 @@ protected:
|
||||
nsTArray<WebGLVertexAttribData> mAttribs;
|
||||
WebGLRefPtr<WebGLBuffer> mElementArrayBuffer;
|
||||
|
||||
friend class ScopedDrawHelper;
|
||||
friend class WebGLContext;
|
||||
friend class WebGLVertexArrayFake;
|
||||
friend class WebGL2Context;
|
||||
|
@ -43,6 +43,28 @@ CalcBytesPerVertex(GLenum type, uint8_t size)
|
||||
return bytesPerType * size;
|
||||
}
|
||||
|
||||
static GLenum
|
||||
AttribPointerBaseType(bool integerFunc, GLenum type)
|
||||
{
|
||||
if (!integerFunc)
|
||||
return LOCAL_GL_FLOAT;
|
||||
|
||||
switch (type) {
|
||||
case LOCAL_GL_BYTE:
|
||||
case LOCAL_GL_SHORT:
|
||||
case LOCAL_GL_INT:
|
||||
return LOCAL_GL_INT;
|
||||
|
||||
case LOCAL_GL_UNSIGNED_BYTE:
|
||||
case LOCAL_GL_UNSIGNED_SHORT:
|
||||
case LOCAL_GL_UNSIGNED_INT:
|
||||
return LOCAL_GL_UNSIGNED_INT;
|
||||
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLVertexAttribData::VertexAttribPointer(bool integerFunc, WebGLBuffer* buf,
|
||||
uint8_t size, GLenum type, bool normalized,
|
||||
@ -51,6 +73,7 @@ WebGLVertexAttribData::VertexAttribPointer(bool integerFunc, WebGLBuffer* buf,
|
||||
mIntegerFunc = integerFunc;
|
||||
mBuf = buf;
|
||||
mType = type;
|
||||
mBaseType = AttribPointerBaseType(integerFunc, type);
|
||||
mSize = size;
|
||||
mBytesPerVertex = CalcBytesPerVertex(mType, mSize);
|
||||
mNormalized = normalized;
|
||||
|
@ -25,6 +25,7 @@ public:
|
||||
WebGLRefPtr<WebGLBuffer> mBuf;
|
||||
private:
|
||||
GLenum mType;
|
||||
GLenum mBaseType;
|
||||
uint8_t mSize; // num of mType vals per vert
|
||||
uint8_t mBytesPerVertex;
|
||||
bool mNormalized;
|
||||
@ -38,6 +39,7 @@ public:
|
||||
|
||||
GETTER(IntegerFunc)
|
||||
GETTER(Type)
|
||||
GETTER(BaseType)
|
||||
GETTER(Size)
|
||||
GETTER(BytesPerVertex)
|
||||
GETTER(Normalized)
|
||||
|
@ -40,6 +40,14 @@ void main()
|
||||
gl_Position = vec4(p.x + a.x + a.y + a.z + a.w, p.y, 0.0, 10.0);
|
||||
}
|
||||
</script>
|
||||
<script id='vshader_unsigned' type='x-shader/x-vertex'>#version 300 es
|
||||
layout(location=0) in ivec2 p;
|
||||
layout(location=1) in uvec4 a;
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(p.x + int(a.x + a.y + a.z + a.w), p.y, 0.0, 10.0);
|
||||
}
|
||||
</script>
|
||||
<script id='fshader' type='x-shader/x-fragment'>#version 300 es
|
||||
precision mediump float;
|
||||
layout(location=0) out vec4 oColor;
|
||||
@ -69,7 +77,8 @@ function runTest() {
|
||||
testFailed('could not create context');
|
||||
return;
|
||||
}
|
||||
var program = wtu.setupProgram(gl, ['vshader', 'fshader'])
|
||||
var program = wtu.setupProgram(gl, ['vshader', 'fshader']);
|
||||
var program_unsigned = wtu.setupProgram(gl, ['vshader_unsigned', 'fshader']);
|
||||
|
||||
gl.enableVertexAttribArray(0);
|
||||
var pos = gl.createBuffer();
|
||||
@ -83,6 +92,11 @@ function runTest() {
|
||||
var tests = ['vertexAttribI4i', 'vertexAttribI4ui', 'vertexAttribI4iv', 'vertexAttribI4uiv'];
|
||||
|
||||
for (var ii = 0; ii < 4; ++ii) {
|
||||
if (ii % 2 == 0) {
|
||||
gl.useProgram(program);
|
||||
} else {
|
||||
gl.useProgram(program_unsigned);
|
||||
}
|
||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||
if (ii < 2) {
|
||||
gl[tests[ii]](1, vals[ii][0], vals[ii][1], vals[ii][2], vals[ii][3]);
|
||||
|
@ -51,6 +51,17 @@ void main()
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="vshader_unsigned" type="x-shader/x-vertex">#version 300 es
|
||||
layout(location=0) in uvec4 aPosition;
|
||||
layout(location=1) in vec4 aColor;
|
||||
out vec4 vColor;
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(aPosition);
|
||||
vColor = aColor;
|
||||
}
|
||||
|
||||
</script>
|
||||
<script id="fshader" type="x-shader/x-fragment">#version 300 es
|
||||
precision mediump float;
|
||||
in vec4 vColor;
|
||||
@ -70,6 +81,7 @@ function init()
|
||||
var wtu = WebGLTestUtils;
|
||||
var gl = wtu.create3DContext("example", undefined, 2);
|
||||
var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition"]);
|
||||
var program_unsigned = wtu.setupProgram(gl, ["vshader_unsigned", "fshader"], ["vPosition"]);
|
||||
|
||||
var tests = [
|
||||
{ data: new Int32Array([ 0, 1, 0, 1, 0, 0, 0, 0, 0 ]),
|
||||
@ -116,6 +128,11 @@ function init()
|
||||
var stride = test.componentSize * kNumComponents + test.componentSize * ss;
|
||||
debug("");
|
||||
debug("check with " + wtu.glEnumToString(gl, test.type) + " at offset: " + offset + " with stride:" + stride);
|
||||
if (test.type == gl.INT || test.type == gl.SHORT || test.type == gl.BYTE) {
|
||||
gl.useProgram(program);
|
||||
} else {
|
||||
gl.useProgram(program_unsigned);
|
||||
}
|
||||
gl.vertexAttrib4fv(1, color);
|
||||
var data = new Uint8Array(test.componentSize * kNumVerts * kNumComponents + stride * (kNumVerts - 1));
|
||||
var view = new Uint8Array(test.data.buffer);
|
||||
|
@ -5928,7 +5928,6 @@ fail-if = (os == 'android')
|
||||
[generated/test_conformance__attribs__gl-enable-vertex-attrib.html]
|
||||
[generated/test_conformance__attribs__gl-matrix-attributes.html]
|
||||
[generated/test_conformance__attribs__gl-vertex-attrib-render.html]
|
||||
fail-if = (os == 'linux')
|
||||
[generated/test_conformance__attribs__gl-vertex-attrib-zero-issues.html]
|
||||
[generated/test_conformance__attribs__gl-vertex-attrib.html]
|
||||
[generated/test_conformance__attribs__gl-vertexattribpointer-offsets.html]
|
||||
|
@ -475,8 +475,6 @@ fail-if = (os == 'b2g')
|
||||
########################################################################
|
||||
########################################################################
|
||||
# Linux
|
||||
[generated/test_conformance__attribs__gl-vertex-attrib-render.html]
|
||||
fail-if = (os == 'linux')
|
||||
[generated/test_conformance__glsl__constructors__glsl-construct-vec-mat-corner-cases.html]
|
||||
# mozalloc_abort in libglsl.so
|
||||
skip-if = (os == 'linux')
|
||||
|
@ -693,17 +693,13 @@ interface WebGLRenderingContextBase {
|
||||
void validateProgram(WebGLProgram program);
|
||||
|
||||
void vertexAttrib1f(GLuint indx, GLfloat x);
|
||||
void vertexAttrib1fv(GLuint indx, Float32Array values);
|
||||
void vertexAttrib1fv(GLuint indx, sequence<GLfloat> values);
|
||||
void vertexAttrib1fv(GLuint indx, Float32List values);
|
||||
void vertexAttrib2f(GLuint indx, GLfloat x, GLfloat y);
|
||||
void vertexAttrib2fv(GLuint indx, Float32Array values);
|
||||
void vertexAttrib2fv(GLuint indx, sequence<GLfloat> values);
|
||||
void vertexAttrib2fv(GLuint indx, Float32List values);
|
||||
void vertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z);
|
||||
void vertexAttrib3fv(GLuint indx, Float32Array values);
|
||||
void vertexAttrib3fv(GLuint indx, sequence<GLfloat> values);
|
||||
void vertexAttrib3fv(GLuint indx, Float32List values);
|
||||
void vertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
|
||||
void vertexAttrib4fv(GLuint indx, Float32Array values);
|
||||
void vertexAttrib4fv(GLuint indx, sequence<GLfloat> values);
|
||||
void vertexAttrib4fv(GLuint indx, Float32List values);
|
||||
void vertexAttribPointer(GLuint indx, GLint size, GLenum type,
|
||||
GLboolean normalized, GLsizei stride, GLintptr offset);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user