// // Created by BZLZHH on 2025/5/1. // // TODO: Add more gl error check for vertex array state manager. #include "VertexArrayState.h" VertexArrayState::VertexArrayState() { vaos_[0]; } GLenum VertexArrayState::Create(GLuint* array) { if (array == nullptr) return GL_INVALID_VALUE; GLuint id = freeId_.empty() ? lastId_++ : freeId_.back(); if (!freeId_.empty()) { freeId_.pop_back(); } *array = id; vaos_[id] = { .generated = false }; return GL_NO_ERROR; } GLenum VertexArrayState::CreateN(GLsizei n, GLuint* arrays) { if (n <= 0 || arrays == nullptr) { return GL_INVALID_VALUE; } for (GLsizei i = 0; i < n; ++i) { if (GLenum error = Create(&arrays[i]); error != GL_NO_ERROR) { return error; } } return GL_NO_ERROR; } GLenum VertexArrayState::Bind(GLuint array) { if (array != 0 && vaos_.find(array) == vaos_.end()) return GL_INVALID_OPERATION; currentVao_ = array; GetCurrentVAO()->generated = true; return GL_NO_ERROR; } GLenum VertexArrayState::EnableAttrib(GLuint index) { if (currentVao_ == 0) 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); return GL_NO_ERROR; } GLenum VertexArrayState::DisableAttrib(GLuint index) { if (currentVao_ == 0) 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); return GL_NO_ERROR; } 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 (index >= GL_MAX_VERTEX_ATTRIBS) return GL_INVALID_VALUE; VertexAttribState state; state.size = size; state.type = type; state.normalized = normalized; state.stride = stride; state.pointer = pointer; state.buffer = currentArrayBuffer; state.isInteger = isInteger; if (vaos_[currentVao_].attribs.count(index) && vaos_[currentVao_].attribs[index].enabled) state.enabled = true; vaos_[currentVao_].attribs[index] = state; return GL_NO_ERROR; } GLuint VertexArrayState::GetBoundElementBuffer() { auto it = vaos_.find(currentVao_); return (it != vaos_.end()) ? it->second.elementBuffer : 0; } VertexArrayObject* VertexArrayState::GetCurrentVAO() { auto it = vaos_.find(currentVao_); if (it != vaos_.end()) return &it->second; else { MG_Util::Debug::LogD("%s: VAO not found, currentVao_ = %u !", __func__, currentVao_); return nullptr; } }