mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 04:08:32 +09:00
234 lines
10 KiB
C++
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
|