diff --git a/MG/MG_GL/Implementations/GL/VertexArray/GL_VertexArray.cpp b/MG/MG_GL/Implementations/GL/VertexArray/GL_VertexArray.cpp index 04918d3b..94b8d0b8 100644 --- a/MG/MG_GL/Implementations/GL/VertexArray/GL_VertexArray.cpp +++ b/MG/MG_GL/Implementations/GL/VertexArray/GL_VertexArray.cpp @@ -7,7 +7,7 @@ namespace MG_GL::GL { void GenVertexArrays(GLsizei n, GLuint* arrays) { MG_Util::Debug::LogD("glGenVertexArrays, n: %d, arrays: %p", n, arrays); - GLenum result = MG_State::CreateVertexArrays(n, arrays); + GLenum result = MG_State::GenVertexArraysNames(n, arrays); if (result == GL_NO_ERROR) return; MG_State::SetError(result); MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result)); diff --git a/MG/MG_GL/State/Core/GLState.cpp b/MG/MG_GL/State/Core/GLState.cpp index 8638d52b..fc1f466b 100644 --- a/MG/MG_GL/State/Core/GLState.cpp +++ b/MG/MG_GL/State/Core/GLState.cpp @@ -214,6 +214,10 @@ namespace MG_State { return MG_State_T::vertexArrayState->CreateN(n, arrays); } + GLenum GenVertexArraysNames(GLsizei n, GLuint* arrays) { + return MG_State_T::vertexArrayState->GenNameN(n, arrays); + } + GLenum EnableVertexAttribArray(GLuint index) { return MG_State_T::vertexArrayState->EnableAttrib(index); } diff --git a/MG/MG_GL/State/Core/GLState.h b/MG/MG_GL/State/Core/GLState.h index 5b667071..c702dc6f 100644 --- a/MG/MG_GL/State/Core/GLState.h +++ b/MG/MG_GL/State/Core/GLState.h @@ -71,6 +71,7 @@ namespace MG_State { // VertexArray GLenum CreateVertexArray(GLuint* array); GLenum CreateVertexArrays(GLsizei n, GLuint* arrays); + GLenum GenVertexArraysNames(GLsizei n, GLuint* arrays); GLenum BindVertexArray(GLuint array); GLenum EnableVertexAttribArray(GLuint index); GLenum DisableVertexAttribArray(GLuint index); diff --git a/MG/MG_GL/State/VertexArray/VertexArrayState.cpp b/MG/MG_GL/State/VertexArray/VertexArrayState.cpp index f6626b75..159e5160 100644 --- a/MG/MG_GL/State/VertexArray/VertexArrayState.cpp +++ b/MG/MG_GL/State/VertexArray/VertexArrayState.cpp @@ -10,6 +10,37 @@ VertexArrayState::VertexArrayState() { vaos_[0]; } +GLenum VertexArrayState::GenName(GLuint *array) { + MG_Util::Debug::LogD("MG_State: VAO: GenName"); + if (!array) + return GL_INVALID_VALUE; + GLuint id; + if (freeIds_.empty()) { + id = ++lastId_; + } else { + id = *freeIds_.begin(); + freeIds_.erase(freeIds_.begin()); + } + *array = id; + MG_Util::Debug::LogD("MG_State: VAO: Generated new name %d", id); + return GL_NO_ERROR; +} + +GLenum VertexArrayState::GenNameN(GLsizei n, GLuint* arrays) { + MG_Util::Debug::LogD("MG_State: VAO: GenNameN called with n=%d", n); + if (n < 0) + return GL_INVALID_VALUE; + for (GLsizei i = 0; i < n; ++i) { + GLenum result = GenName(&arrays[i]); + if (result != GL_NO_ERROR) { + MG_Util::Debug::LogE("MG_State: VAO: GenNameN failed at index %d with error 0x%x", i, result); + return result; + } + } + MG_Util::Debug::LogD("MG_State: VAO: GenNameN created %d names", n); + return GL_NO_ERROR; +} + GLenum VertexArrayState::Create(GLuint* array) { if (array == nullptr) return GL_INVALID_VALUE; @@ -41,13 +72,41 @@ GLenum VertexArrayState::CreateN(GLsizei n, GLuint* arrays) { } GLenum VertexArrayState::Bind(GLuint array) { - if (array != 0 && !vaos_.count(array)) return GL_INVALID_OPERATION; + MG_Util::Debug::LogD("MG_State: VAO: Bind called for %u", array); + if (array != 0) { + if (!ValidateGeneratedName(array)) { + MG_Util::Debug::LogE("MG_State: VAO: Bind invalid name %u", array); + return GL_INVALID_OPERATION; + } + auto& vao = vaos_[array]; + if (!vao.generated) { + MG_Util::Debug::LogD("MG_State: VAO: Creating VAO %u during bind", array); + vao.generated = true; + } + } currentVao_ = array; + MG_Util::Debug::LogD("MG_State: VAO: Bound to %u", array); return GL_NO_ERROR; } +bool VertexArrayState::ValidateGeneratedName(GLuint array) { + if (array == 0) + return true; + bool inFreeList = freeIds_.count(array) > 0; + bool valid = (array <= lastId_) && !inFreeList; + MG_Util::Debug::LogD("MG_State: VAO: ValidateGeneratedName %u: %d", array, valid); + return valid; +} + +bool VertexArrayState::ValidateAllocatedHandle(GLuint array) { + bool exists = vaos_.count(array) && vaos_[array].generated; + MG_Util::Debug::LogD("MG_State: VAO: ValidateAllocatedHandle %u: %d", array, exists); + return exists; +} + GLenum VertexArrayState::EnableAttrib(GLuint index) { - if (currentVao_ == 0) return GL_INVALID_OPERATION; + if (!ValidateAllocatedHandle(currentVao_)) + return GL_INVALID_OPERATION; if (index >= GL_MAX_VERTEX_ATTRIBS) return GL_INVALID_VALUE; GetCurrentVAO()->attribs[index].enabled = true; MG_Util::Debug::LogD("Attrib vaos_[%u].attribs[%u].enabled = %d", currentVao_, index, vaos_[currentVao_].attribs[index].enabled); @@ -55,7 +114,8 @@ GLenum VertexArrayState::EnableAttrib(GLuint index) { } GLenum VertexArrayState::DisableAttrib(GLuint index) { - if (currentVao_ == 0) return GL_INVALID_OPERATION; + if (!ValidateAllocatedHandle(currentVao_)) + return GL_INVALID_OPERATION; if (index >= GL_MAX_VERTEX_ATTRIBS) return GL_INVALID_VALUE; GetCurrentVAO()->attribs[index].enabled = false; MG_Util::Debug::LogD("Attrib vaos_[%u].attribs[%u].enabled = %d", currentVao_, index, vaos_[currentVao_].attribs[index].enabled); @@ -66,7 +126,8 @@ GLenum VertexArrayState::SetAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer, bool isInteger, GLuint currentArrayBuffer) { - if (currentVao_ == 0) return GL_INVALID_OPERATION; + if (!ValidateAllocatedHandle(currentVao_)) + return GL_INVALID_OPERATION; if (index >= GL_MAX_VERTEX_ATTRIBS) return GL_INVALID_VALUE; VertexAttribState state; diff --git a/MG/MG_GL/State/VertexArray/VertexArrayState.h b/MG/MG_GL/State/VertexArray/VertexArrayState.h index ac19561c..7253f428 100644 --- a/MG/MG_GL/State/VertexArray/VertexArrayState.h +++ b/MG/MG_GL/State/VertexArray/VertexArrayState.h @@ -30,6 +30,8 @@ public: VertexArrayState(); // Return: the validity of the operation, according to OpenGL 3 standard + GLenum GenName(GLuint* array); + GLenum GenNameN(GLsizei n, GLuint* arrays); GLenum Create(GLuint* array); GLenum CreateN(GLsizei n, GLuint* arrays); GLenum Bind(GLuint array); @@ -42,6 +44,8 @@ public: GLuint GetBoundElementBuffer(); VertexArrayObject* GetCurrentVAO(); + bool ValidateGeneratedName(GLuint array); + bool ValidateAllocatedHandle(GLuint array); GLuint currentVao_ = 0; std::unordered_map vaos_;