Files
MobileGL/MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.cpp
T

234 lines
10 KiB
C++

// MobileGL - MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.cpp
// Copyright (c) 2025-2026 MobileGL-Dev
// Licensed under the GNU Lesser General Public License v3.0:
// https://www.gnu.org/licenses/gpl-3.0.txt
// https://www.gnu.org/licenses/lgpl-3.0.txt
// SPDX-License-Identifier: LGPL-3.0-only
// End of Source File Header
#include "GL_VertexArray.h"
#include "Validators.h"
#include <MG_State/GLState/Core.h>
#include <MG_State/GLState/ErrorState/Error.h>
#include <MG_Util/Converters/GLToMG/DataTypeConverter.h>
namespace MobileGL {
namespace MG_Impl::GLImpl {
void DisableVertexAttribArray_State(GLuint index) {
if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return;
auto vao = MG_State::pGLContext->GetBoundVertexArray();
if (!vao) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl",
"EnableVertexAttribArray_State",
"No vertex array object is bound."));
return;
}
vao->DisableAttribute(index);
}
void EnableVertexAttribArray_State(GLuint index) {
if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return;
auto vao = MG_State::pGLContext->GetBoundVertexArray();
if (!vao) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl",
"EnableVertexAttribArray_State",
"No vertex array object is bound."));
return;
}
vao->EnableAttribute(index);
}
// TODO: implement GL_BGRA support
void VertexAttribIPointer_State(GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer) {
if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return;
DataType dataType = MG_Util::ConvertGLEnumToDataType(type);
if (!VertexArrayImpl::ValidateVertexAttribPointerParams(index, size, dataType, stride)) return;
auto vao = MG_State::pGLContext->GetBoundVertexArray();
if (!vao) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl",
"VertexAttribPointer_State",
"No vertex array object is bound."));
return;
}
auto& vboSlot = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::Vertex);
auto vbo = vboSlot.GetBoundObject();
if (!vbo) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "VertexAttribPointer_State",
"No buffer is bound to GL_ARRAY_BUFFER."));
return;
}
SizeT offset = reinterpret_cast<SizeT>(pointer);
vao->SetAttributeFormat(index, size, dataType, false, stride, offset, true);
vao->BindAttributeBuffer(index, vbo);
}
// TODO: implement GL_BGRA support
void VertexAttribPointer_State(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride,
const void* pointer) {
if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return;
DataType dataType = MG_Util::ConvertGLEnumToDataType(type);
if (!VertexArrayImpl::ValidateVertexAttribPointerParams(index, size, dataType, stride)) return;
auto vao = MG_State::pGLContext->GetBoundVertexArray();
if (!vao) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl",
"VertexAttribPointer_State",
"No vertex array object is bound."));
return;
}
auto& vboSlot = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::Vertex);
auto vbo = vboSlot.GetBoundObject();
if (!vbo) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "VertexAttribPointer_State",
"No buffer is bound to GL_ARRAY_BUFFER."));
return;
}
SizeT offset = reinterpret_cast<SizeT>(pointer);
vao->SetAttributeFormat(index, size, dataType, normalized, stride, offset, false);
vao->BindAttributeBuffer(index, vbo);
}
void BindVertexArray_State(GLuint array) {
if (array == 0) {
MG_State::pGLContext->BindVertexArray(0);
return;
}
if (!VertexArrayImpl::ValidateVertexArrayName(array)) return;
if (!MG_State::pGLContext->ValidateVertexArrayObject(array)) {
MG_State::pGLContext->CreateVertexArrayObject(array);
}
MG_State::pGLContext->BindVertexArray(array);
}
void DeleteVertexArrays_State(GLsizei n, const GLuint* arrays) {
if (n < 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "DeleteVertexArrays_State",
"n must be non-negative."));
return;
}
for (GLsizei i = 0; i < n; ++i) {
GLuint vao = arrays[i];
if (vao == 0) continue;
if (!VertexArrayImpl::ValidateVertexArrayName(vao)) continue;
if (MG_State::pGLContext->GetBoundVertexArray() &&
MG_State::pGLContext->GetBoundVertexArray() == MG_State::pGLContext->GetVertexArrayObject(vao)) {
MG_State::pGLContext->BindVertexArray(0);
}
MG_State::pGLContext->MarkVertexArrayForDeletion(vao);
}
}
void GenVertexArrays_State(GLsizei n, GLuint* arrays) {
if (n < 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GenVertexArrays_State", "n must be non-negative."));
return;
}
auto vaoNames = MG_State::pGLContext->GenVertexArrayNames(n);
Copy(vaoNames.data(), arrays, vaoNames.size());
}
GLboolean IsVertexArray_State(GLuint array) {
if (array == 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "IsVertexArray_State",
"Vertex array name 0 is not supported."));
return GL_FALSE;
}
if (!VertexArrayImpl::ValidateVertexArrayName(array)) return GL_FALSE;
if (!MG_State::pGLContext->ValidateVertexArrayObject(array)) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "IsVertexArray_State",
std::format("Vertex array object {} does not exist.", array)));
return GL_FALSE;
}
return GL_TRUE;
}
void VertexAttribDivisor_State(GLuint index, GLuint divisor) {
if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return;
auto vao = MG_State::pGLContext->GetBoundVertexArray();
if (!vao) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl",
"VertexAttribDivisor_State",
"No vertex array object is bound."));
return;
}
vao->SetAttributeDivisor(index, divisor);
}
/* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */
void VertexAttribDivisor(GLuint index, GLuint divisor) {
VertexAttribDivisor_State(index, divisor);
}
GLboolean IsVertexArray(GLuint array) {
return IsVertexArray_State(array);
}
void DisableVertexAttribArray(GLuint index) {
DisableVertexAttribArray_State(index);
}
void EnableVertexAttribArray(GLuint index) {
EnableVertexAttribArray_State(index);
}
void VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer) {
VertexAttribIPointer_State(index, size, type, stride, pointer);
}
void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride,
const void* pointer) {
VertexAttribPointer_State(index, size, type, normalized, stride, pointer);
}
void BindVertexArray(GLuint array) {
BindVertexArray_State(array);
}
void DeleteVertexArrays(GLsizei n, const GLuint* arrays) {
DeleteVertexArrays_State(n, arrays);
}
void GenVertexArrays(GLsizei n, GLuint* arrays) {
GenVertexArrays_State(n, arrays);
}
} // namespace MG_Impl::GLImpl
} // namespace MobileGL