[Feat] (All): Continue building the basic structure.

Feat: implement MG_Impl/VertexArray
Feat: add tests about MG_Impl/VertexArray
Feat: add several converters
Feat: implement IsBuffer
This commit is contained in:
BZLZHH
2025-07-25 21:36:14 +08:00
parent e7a21423da
commit 47f7039720
18 changed files with 672 additions and 12 deletions
+5
View File
@@ -20,12 +20,15 @@ add_library(${CMAKE_PROJECT_NAME} SHARED
MobileGL/MG_Util/Debug/Log.cpp
MobileGL/MG_Util/Converters/GLToStr/GLEnumConverter.cpp
MobileGL/MG_Util/Converters/MGToStr/DataTypeConverter.cpp
MobileGL/MG_Util/Converters/MGToStr/GLExtensionConverter.cpp
MobileGL/MG_Util/Converters/MGToStr/BufferEnumConverter.cpp
MobileGL/MG_Util/Converters/GLToGlslang/GLShaderLangConverter.cpp
MobileGL/MG_Util/Converters/MGToGL/ErrorCodeConverter.cpp
MobileGL/MG_Util/Converters/MGToGL/BufferEnumConverter.cpp
MobileGL/MG_Util/Converters/MGToGL/DataTypeConverter.cpp
MobileGL/MG_Util/Converters/GLToMG/BufferEnumConverter.cpp
MobileGL/MG_Util/Converters/GLToMG/DataTypeConverter.cpp
MobileGL/MG_Impl/GLXImpl/Exporting/Definitions.cpp
MobileGL/MG_Impl/GLXImpl/LookUp/LookUp.cpp
@@ -34,6 +37,8 @@ add_library(${CMAKE_PROJECT_NAME} SHARED
MobileGL/MG_Impl/EGLImpl/Temporary/TemporaryEGLImpl.cpp
# @INSERTION_POINT:SOURCE_FILE_GLIMPL@ #
MobileGL/MG_Impl/GLImpl/VertexArray/Validators.cpp
MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.cpp
MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp
MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.cpp
MobileGL/MG_Impl/GLImpl/Buffer/GL_Buffer.cpp
+7 -2
View File
@@ -113,16 +113,21 @@ inline int __android_log_print(int prio, const char* tag, const char* fmt, ...)
#include "MG_State/GLState/VertexArrayState/VertexArrayState.h"
/* @INSERTION_POINT:HEADER_FILE_GLIMPL@ */
#include "MG_Impl/GLImpl/VertexArray/Validators.h"
#include "MG_Impl/GLImpl/VertexArray/GL_VertexArray.h"
#include "MG_Impl/GLImpl/Getter/GL_Getter.h"
#include "MG_Impl/GLImpl/Buffer/GL_Buffer.h"
#include "MG_Impl/GLImpl/Buffer/Validators.h"
#include "MG_State/GLState/Core.h"
#include "MG_Util/Converters/GLToMG/BufferEnumConverter.h"
#include "MG_Util/Converters/MGToGL/BufferEnumConverter.h"
#include "MG_Util/Converters/MGToGL/ErrorCodeConverter.h"
#include "MG_Util/Converters/GLToStr/GLEnumConverter.h"
#include "MG_Util/Converters/MGToGL/DataTypeConverter.h"
#include "MG_Util/Converters/MGToStr/DataTypeConverter.h"
#include "MG_Util/Converters/MGToStr/BufferEnumConverter.h"
#include "MG_Util/Converters/MGToStr/GLExtensionConverter.h"
#include "MG_Util/Converters/GLToMG/BufferEnumConverter.h"
#include "MG_Util/Converters/GLToMG/DataTypeConverter.h"
#include "MG_Util/Converters/GLToStr/GLEnumConverter.h"
#include "MG_Util/Converters/GLToGlslang/GLShaderLangConverter.h"
@@ -384,6 +384,13 @@ namespace MobileGL {
auto& bindingSlot = MG_State::pGLContext->GetBufferBindingSlot(bufferTarget);
bindingSlot.Bind(bufferObject);
if (bufferTarget == BufferTarget::Index) {
auto currentVAO = MG_State::pGLContext->GetBoundVertexArray();
if (currentVAO) {
currentVAO->BindElementBuffer(bufferObject);
}
}
}
void GenBuffers_State(GLsizei n, GLuint* buffers) {
@@ -396,7 +403,23 @@ namespace MobileGL {
Copy(bufferNames.data(), buffers, bufferNames.size());
}
GLboolean IsBuffer_State(GLuint buffer) {
if (buffer == 0) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "IsBuffer_State",
"Buffer name 0 is not a valid buffer object."));
return GL_FALSE;
}
if (!BufferImpl::ValidateBufferName(buffer)) return GL_FALSE;
return MG_State::pGLContext->ValidateBufferObject(buffer) ? GL_TRUE : GL_FALSE;
}
/* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */
GLboolean IsBuffer(GLuint buffer) {
return IsBuffer_State(buffer);
}
void DeleteBuffers(GLsizei n, const GLuint* buffers) {
DeleteBuffers_State(n, buffers);
}
@@ -3,6 +3,7 @@
namespace MobileGL {
namespace MG_Impl::GLImpl {
/* @INSERTION_POINT:FUNCTION_DECLARATION@ */
GLboolean IsBuffer(GLuint buffer);
void DeleteBuffers(GLsizei n, const GLuint* buffers);
void FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length);
GLboolean UnmapBuffer(GLenum target);
@@ -68,11 +68,11 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, DepthMask, GLboolean flag) DECLARE_GL_FUNCTI
DECLARE_GL_FUNCTION_STUB_HEAD(void, DepthRangef, GLfloat n, GLfloat f) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DepthRangef, n, f)
DECLARE_GL_FUNCTION_STUB_HEAD(void, DetachShader, GLuint program, GLuint shader) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DetachShader, program, shader)
DECLARE_GL_FUNCTION_STUB_HEAD(void, Disable, GLenum cap) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Disable, cap)
DECLARE_GL_FUNCTION_STUB_HEAD(void, DisableVertexAttribArray, GLuint index) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DisableVertexAttribArray, index)
DECLARE_GL_FUNCTION_HEAD(void, DisableVertexAttribArray, GLuint index) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DisableVertexAttribArray, index)
DECLARE_GL_FUNCTION_STUB_HEAD(void, DrawArrays, GLenum mode, GLint first, GLsizei count) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DrawArrays, mode, first, count)
DECLARE_GL_FUNCTION_STUB_HEAD(void, DrawElements, GLenum mode, GLsizei count, GLenum type, const void* indices) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DrawElements, mode, count, type, indices)
DECLARE_GL_FUNCTION_STUB_HEAD(void, Enable, GLenum cap) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Enable, cap)
DECLARE_GL_FUNCTION_STUB_HEAD(void, EnableVertexAttribArray, GLuint index) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, EnableVertexAttribArray, index)
DECLARE_GL_FUNCTION_HEAD(void, EnableVertexAttribArray, GLuint index) DECLARE_GL_FUNCTION_END_NO_RETURN(void, EnableVertexAttribArray, index)
DECLARE_GL_FUNCTION_STUB_HEAD(void, Finish) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Finish)
DECLARE_GL_FUNCTION_STUB_HEAD(void, Flush) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Flush)
DECLARE_GL_FUNCTION_STUB_HEAD(void, FramebufferRenderbuffer, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, FramebufferRenderbuffer, target, attachment, renderbuffertarget, renderbuffer)
@@ -109,7 +109,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, GetVertexAttribfv, GLuint index, GLenum pnam
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetVertexAttribiv, GLuint index, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetVertexAttribiv, index, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetVertexAttribPointerv, GLuint index, GLenum pname, void** pointer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetVertexAttribPointerv, index, pname, pointer)
DECLARE_GL_FUNCTION_STUB_HEAD(void, Hint, GLenum target, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Hint, target, mode)
DECLARE_GL_FUNCTION_STUB_HEAD(GLboolean, IsBuffer, GLuint buffer) DECLARE_GL_FUNCTION_STUB_END(GLboolean, IsBuffer, buffer)
DECLARE_GL_FUNCTION_HEAD(GLboolean, IsBuffer, GLuint buffer) DECLARE_GL_FUNCTION_END(GLboolean, IsBuffer, buffer)
DECLARE_GL_FUNCTION_STUB_HEAD(GLboolean, IsEnabled, GLenum cap) DECLARE_GL_FUNCTION_STUB_END(GLboolean, IsEnabled, cap)
DECLARE_GL_FUNCTION_STUB_HEAD(GLboolean, IsFramebuffer, GLuint framebuffer) DECLARE_GL_FUNCTION_STUB_END(GLboolean, IsFramebuffer, framebuffer)
DECLARE_GL_FUNCTION_STUB_HEAD(GLboolean, IsProgram, GLuint program) DECLARE_GL_FUNCTION_STUB_END(GLboolean, IsProgram, program)
@@ -168,7 +168,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib3f, GLuint index, GLfloat x, GLf
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib3fv, GLuint index, const GLfloat* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib3fv, index, v)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4f, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4f, index, x, y, z, w)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4fv, GLuint index, const GLfloat* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4fv, index, v)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribPointer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribPointer, index, size, type, normalized, stride, pointer)
DECLARE_GL_FUNCTION_HEAD(void, VertexAttribPointer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribPointer, index, size, type, normalized, stride, pointer)
DECLARE_GL_FUNCTION_STUB_HEAD(void, Viewport, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Viewport, x, y, width, height)
DECLARE_GL_FUNCTION_STUB_HEAD(void, ReadBuffer, GLenum src) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ReadBuffer, src)
DECLARE_GL_FUNCTION_STUB_HEAD(void, DrawRangeElements, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DrawRangeElements, mode, start, end, count, type, indices)
@@ -198,10 +198,10 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, BlitFramebuffer, GLint srcX0, GLint srcY0, G
DECLARE_GL_FUNCTION_STUB_HEAD(void, RenderbufferStorageMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, RenderbufferStorageMultisample, target, samples, internalformat, width, height)
DECLARE_GL_FUNCTION_STUB_HEAD(void, FramebufferTextureLayer, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, FramebufferTextureLayer, target, attachment, texture, level, layer)
DECLARE_GL_FUNCTION_HEAD(void, FlushMappedBufferRange, GLenum target, GLintptr offset, GLsizeiptr length) DECLARE_GL_FUNCTION_END_NO_RETURN(void, FlushMappedBufferRange, target, offset, length)
DECLARE_GL_FUNCTION_STUB_HEAD(void, BindVertexArray, GLuint array) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BindVertexArray, array)
DECLARE_GL_FUNCTION_STUB_HEAD(void, DeleteVertexArrays, GLsizei n, const GLuint* arrays) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DeleteVertexArrays, n, arrays)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GenVertexArrays, GLsizei n, GLuint* arrays) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GenVertexArrays, n, arrays)
DECLARE_GL_FUNCTION_STUB_HEAD(GLboolean, IsVertexArray, GLuint array) DECLARE_GL_FUNCTION_STUB_END(GLboolean, IsVertexArray, array)
DECLARE_GL_FUNCTION_HEAD(void, BindVertexArray, GLuint array) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BindVertexArray, array)
DECLARE_GL_FUNCTION_HEAD(void, DeleteVertexArrays, GLsizei n, const GLuint* arrays) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DeleteVertexArrays, n, arrays)
DECLARE_GL_FUNCTION_HEAD(void, GenVertexArrays, GLsizei n, GLuint* arrays) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GenVertexArrays, n, arrays)
DECLARE_GL_FUNCTION_HEAD(GLboolean, IsVertexArray, GLuint array) DECLARE_GL_FUNCTION_END(GLboolean, IsVertexArray, array)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetIntegeri_v, GLenum target, GLuint index, GLint* data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetIntegeri_v, target, index, data)
DECLARE_GL_FUNCTION_STUB_HEAD(void, BeginTransformFeedback, GLenum primitiveMode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BeginTransformFeedback, primitiveMode)
DECLARE_GL_FUNCTION_STUB_HEAD(void, EndTransformFeedback) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, EndTransformFeedback)
@@ -209,7 +209,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, BindBufferRange, GLenum target, GLuint index
DECLARE_GL_FUNCTION_STUB_HEAD(void, BindBufferBase, GLenum target, GLuint index, GLuint buffer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BindBufferBase, target, index, buffer)
DECLARE_GL_FUNCTION_STUB_HEAD(void, TransformFeedbackVaryings, GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TransformFeedbackVaryings, program, count, varyings, bufferMode)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTransformFeedbackVarying, GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTransformFeedbackVarying, program, index, bufSize, length, size, type, name)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribIPointer, GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribIPointer, index, size, type, stride, pointer)
DECLARE_GL_FUNCTION_HEAD(void, VertexAttribIPointer, GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribIPointer, index, size, type, stride, pointer)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetVertexAttribIiv, GLuint index, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetVertexAttribIiv, index, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetVertexAttribIuiv, GLuint index, GLenum pname, GLuint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetVertexAttribIuiv, index, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribI4i, GLuint index, GLint x, GLint y, GLint z, GLint w) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribI4i, index, x, y, z, w)
@@ -0,0 +1,194 @@
#include "../../../Includes.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;
}
/* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */
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);
}
}
}
@@ -0,0 +1,15 @@
#pragma once
namespace MobileGL {
namespace MG_Impl::GLImpl {
/* @INSERTION_POINT:FUNCTION_DECLARATION@ */
GLboolean IsVertexArray(GLuint array);
void DisableVertexAttribArray(GLuint index);
void EnableVertexAttribArray(GLuint index);
void VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer);
void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer);
void BindVertexArray(GLuint array);
void DeleteVertexArrays(GLsizei n, const GLuint* arrays);
void GenVertexArrays(GLsizei n, GLuint* arrays);
}
}
@@ -0,0 +1,69 @@
#include "../../../Includes.h"
namespace MobileGL::MG_Impl::GLImpl {
namespace VertexArrayImpl {
bool ValidateVertexArrayName(Uint index) {
if (index == 0) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateVertexArrayName",
"Vertex array name 0 is not supported."));
return false;
}
bool isValid = MG_State::pGLContext->ValidateVertexArrayName(index);
if (!isValid) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateVertexArrayName",
std::format("Vertex array name {} is not valid.", index)));
}
return true;
}
bool ValidateVertexArrayObject(Uint index) {
if (!MG_State::pGLContext->ValidateVertexArrayObject(index)) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateVertexArrayObject",
std::format("Vertex array object {} does not exist.", index)));
return false;
}
return true;
}
bool ValidateVertexAttributeIndex(Uint index) {
if (index >= MG_State::GLState::VertexArrayObject::MAX_VERTEX_ATTRIBS) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateVertexAttributeIndex",
std::format("Attribute index {} exceeds maximum of {}.",
index, MG_State::GLState::VertexArrayObject::MAX_VERTEX_ATTRIBS - 1)));
return false;
}
return true;
}
bool ValidateVertexAttribPointerParams(Uint index, SizeT size, DataType type, Int stride) {
if (size < 1 || size > 4) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateVertexAttribPointerParams",
std::format("Invalid size {} for attribute {}. Must be 1-4.", size, index)));
return false;
}
if (type == DataType::Unknown) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateVertexAttribPointerParams",
std::format("Invalid type {} for attribute {}.", MG_Util::ConvertDataTypeToString(type).c_str(), index)));
return false;
}
if (stride < 0) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateVertexAttribPointerParams",
std::format("Negative stride {} is not allowed for attribute {}.", stride, index)));
return false;
}
return true;
}
}
}
@@ -0,0 +1,10 @@
#pragma once
namespace MobileGL::MG_Impl::GLImpl {
namespace VertexArrayImpl {
bool ValidateVertexArrayName(Uint index);
bool ValidateVertexArrayObject(Uint index);
bool ValidateVertexAttributeIndex(Uint index);
bool ValidateVertexAttribPointerParams(Uint index, SizeT size, DataType type, Int stride);
}
}
@@ -13,13 +13,17 @@ add_executable(
${MGL_ROOT}/MobileGL/MG_Impl/GLImpl/Buffer/GL_Buffer.cpp
${MGL_ROOT}/MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.cpp
${MGL_ROOT}/MobileGL/MG_Impl/GLImpl/Buffer/Validators.cpp
${MGL_ROOT}/MobileGL/MG_Impl/GLImpl/VertexArray/Validators.cpp
${MGL_ROOT}/MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.cpp
${MGL_ROOT}/MobileGL/MG_Util/Converters/GLToStr/GLEnumConverter.cpp
${MGL_ROOT}/MobileGL/MG_Util/Converters/MGToStr/GLExtensionConverter.cpp
${MGL_ROOT}/MobileGL/MG_Util/Converters/MGToStr/BufferEnumConverter.cpp
${MGL_ROOT}/MobileGL/MG_Util/Converters/GLToGlslang/GLShaderLangConverter.cpp
${MGL_ROOT}/MobileGL/MG_Util/Converters/MGToGL/ErrorCodeConverter.cpp
${MGL_ROOT}/MobileGL/MG_Util/Converters/MGToGL/BufferEnumConverter.cpp
${MGL_ROOT}/MobileGL/MG_Util/Converters/MGToGL/DataTypeConverter.cpp
${MGL_ROOT}/MobileGL/MG_Util/Converters/GLToMG/BufferEnumConverter.cpp
${MGL_ROOT}/MobileGL/MG_Util/Converters/GLToMG/DataTypeConverter.cpp
${MGL_ROOT}/MobileGL/MG_Backend/Init.cpp
${MGL_ROOT}/MobileGL/MG_Util/Debug/Log.cpp
)
@@ -197,3 +197,251 @@ TEST_F(VertexArrayTest, BoundVAOPreservesState) {
ASSERT_FALSE(vao2->IsAttributeEnabled(0));
}
using namespace MobileGL::MG_Impl::GLImpl;
class GeneralVertexArrayTest : public ::testing::Test {
protected:
void SetUp() override {
MG_State::pGLContext = new MG_State::GLState::GLContext();
}
void TearDown() override {
delete MG_State::pGLContext;
MG_State::pGLContext = nullptr;
}
GLuint CreateVAO() {
GLuint vao;
GenVertexArrays(1, &vao);
BindVertexArray(vao);
return vao;
}
GLuint CreateVBO(GLenum target, GLsizeiptr size, const void* data = nullptr) {
GLuint vbo;
GenBuffers(1, &vbo);
BindBuffer(target, vbo);
BufferData(target, size, data, GL_STATIC_DRAW);
return vbo;
}
};
TEST_F(GeneralVertexArrayTest, General_VAOLifecycle) {
GLuint vaos[3];
GenVertexArrays(3, vaos);
EXPECT_NE(vaos[0], 0);
EXPECT_NE(vaos[1], 0);
EXPECT_NE(vaos[2], 0);
EXPECT_NE(vaos[0], vaos[1]);
BindVertexArray(vaos[0]);
EXPECT_EQ(IsVertexArray(vaos[0]), GL_TRUE);
GLuint deleteVao = vaos[1];
DeleteVertexArrays(1, &deleteVao);
BindVertexArray(deleteVao);
EXPECT_EQ(GetError(), GL_INVALID_OPERATION);
DeleteVertexArrays(1, &vaos[0]);
DeleteVertexArrays(1, &vaos[2]);
EXPECT_EQ(GetError(), GL_NO_ERROR);
}
TEST_F(GeneralVertexArrayTest, General_VertexAttributeConfiguration) {
GLuint vao = CreateVAO();
GLuint vbo = CreateVBO(GL_ARRAY_BUFFER, 128);
VertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
EnableVertexAttribArray(0);
VertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
EnableVertexAttribArray(1);
auto vaoObj = MG_State::pGLContext->GetVertexArrayObject(vao);
ASSERT_NE(vaoObj, nullptr);
const auto& attr0 = vaoObj->GetAttribute(0);
EXPECT_TRUE(attr0.Enabled);
EXPECT_EQ(attr0.Size, 3);
EXPECT_EQ(attr0.Type, DataType::Float32);
EXPECT_EQ(attr0.Offset, 0);
const auto& attr1 = vaoObj->GetAttribute(1);
EXPECT_TRUE(attr1.Enabled);
EXPECT_EQ(attr1.Offset, 3 * sizeof(float));
DisableVertexAttribArray(1);
EXPECT_FALSE(vaoObj->GetAttribute(1).Enabled);
EXPECT_EQ(GetError(), GL_NO_ERROR);
}
TEST_F(GeneralVertexArrayTest, General_ElementBufferBinding) {
GLuint vao = CreateVAO();
GLuint ebo = CreateVBO(GL_ELEMENT_ARRAY_BUFFER, 256);
auto vaoObj = MG_State::pGLContext->GetVertexArrayObject(vao);
ASSERT_NE(vaoObj, nullptr);
ASSERT_NE(vaoObj->GetElementBuffer(), nullptr);
GLuint newEbo;
GenBuffers(1, &newEbo);
BindBuffer(GL_ELEMENT_ARRAY_BUFFER, newEbo);
EXPECT_EQ(vaoObj->GetElementBuffer(), MG_State::pGLContext->GetBufferObject(newEbo));
GLuint vao2 = CreateVAO();
GLuint ebo2 = CreateVBO(GL_ELEMENT_ARRAY_BUFFER, 128);
auto vaoObj2 = MG_State::pGLContext->GetVertexArrayObject(vao2);
EXPECT_NE(vaoObj->GetElementBuffer(), vaoObj2->GetElementBuffer());
EXPECT_EQ(GetError(), GL_NO_ERROR);
}
TEST_F(GeneralVertexArrayTest, General_IntegerAttributes) {
GLuint vao = CreateVAO();
GLuint vbo = CreateVBO(GL_ARRAY_BUFFER, 128);
VertexAttribIPointer(2, 4, GL_UNSIGNED_INT, sizeof(GLuint) * 8, (void*)(sizeof(GLuint) * 4));
EnableVertexAttribArray(2);
auto vaoObj = MG_State::pGLContext->GetVertexArrayObject(vao);
const auto& attr = vaoObj->GetAttribute(2);
EXPECT_TRUE(attr.Enabled);
EXPECT_EQ(attr.Size, 4);
EXPECT_EQ(attr.Type, DataType::Uint32);
EXPECT_EQ(attr.Offset, sizeof(GLuint) * 4);
EXPECT_TRUE(attr.IsInteger);
EXPECT_FALSE(attr.Normalized);
EXPECT_EQ(GetError(), GL_NO_ERROR);
}
TEST_F(GeneralVertexArrayTest, General_StatePreservation) {
GLuint vao1 = CreateVAO();
GLuint vbo1 = CreateVBO(GL_ARRAY_BUFFER, 64);
VertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
EnableVertexAttribArray(0);
GLuint vao2;
GenVertexArrays(1, &vao2);
BindVertexArray(vao2);
GLuint vbo2 = CreateVBO(GL_ARRAY_BUFFER, 128);
VertexAttribPointer(1, 3, GL_FLOAT, GL_TRUE, 0, nullptr);
EnableVertexAttribArray(1);
BindVertexArray(vao1);
auto vaoObj1 = MG_State::pGLContext->GetVertexArrayObject(vao1);
EXPECT_TRUE(vaoObj1->IsAttributeEnabled(0));
EXPECT_FALSE(vaoObj1->IsAttributeEnabled(1));
auto vaoObj2 = MG_State::pGLContext->GetVertexArrayObject(vao2);
EXPECT_TRUE(vaoObj2->IsAttributeEnabled(1));
EXPECT_FALSE(vaoObj2->IsAttributeEnabled(0));
EXPECT_EQ(GetError(), GL_NO_ERROR);
}
TEST_F(GeneralVertexArrayTest, General_ErrorConditions) {
VertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
EXPECT_EQ(GetError(), GL_INVALID_OPERATION);
GLuint vao = CreateVAO();
EnableVertexAttribArray(MG_State::GLState::VertexArrayObject::MAX_VERTEX_ATTRIBS);
EXPECT_EQ(GetError(), GL_INVALID_VALUE);
VertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
EXPECT_EQ(GetError(), GL_INVALID_OPERATION);
GLuint vbo = CreateVBO(GL_ARRAY_BUFFER, 64);
VertexAttribPointer(0, 3, 0xFFFFFFFF, GL_FALSE, 0, nullptr);
EXPECT_EQ(GetError(), GL_INVALID_ENUM);
VertexAttribPointer(0, 5, GL_FLOAT, GL_FALSE, 0, nullptr);
EXPECT_EQ(GetError(), GL_INVALID_VALUE);
EXPECT_EQ(GetError(), GL_NO_ERROR);
}
TEST_F(GeneralVertexArrayTest, General_ComplexUsage) {
GLuint vao1 = CreateVAO();
GLuint vboPos = CreateVBO(GL_ARRAY_BUFFER, 256);
GLuint vboColor = CreateVBO(GL_ARRAY_BUFFER, 128);
GLuint ebo1 = CreateVBO(GL_ELEMENT_ARRAY_BUFFER, 64);
VertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
EnableVertexAttribArray(0);
BindBuffer(GL_ARRAY_BUFFER, vboColor);
VertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
EnableVertexAttribArray(1);
GLuint vao2;
GenVertexArrays(1, &vao2);
BindVertexArray(vao2);
GLuint vboNormal = CreateVBO(GL_ARRAY_BUFFER, 192);
GLuint ebo2 = CreateVBO(GL_ELEMENT_ARRAY_BUFFER, 96);
VertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
EnableVertexAttribArray(2);
BindVertexArray(vao1);
auto vaoObj1 = MG_State::pGLContext->GetVertexArrayObject(vao1);
EXPECT_TRUE(vaoObj1->IsAttributeEnabled(0));
EXPECT_TRUE(vaoObj1->IsAttributeEnabled(1));
EXPECT_FALSE(vaoObj1->IsAttributeEnabled(2));
EXPECT_NE(vaoObj1->GetElementBuffer(), nullptr);
auto vaoObj2 = MG_State::pGLContext->GetVertexArrayObject(vao2);
EXPECT_TRUE(vaoObj2->IsAttributeEnabled(2));
EXPECT_FALSE(vaoObj2->IsAttributeEnabled(0));
EXPECT_NE(vaoObj2->GetElementBuffer(), nullptr);
DeleteVertexArrays(1, &vao1);
DeleteVertexArrays(1, &vao2);
GLuint buffers[] = { vboPos, vboColor, ebo1, vboNormal, ebo2 };
DeleteBuffers(5, buffers);
EXPECT_EQ(GetError(), GL_NO_ERROR);
}
TEST_F(GeneralVertexArrayTest, General_BindWithoutCreation) {
GLuint vao = 1;
BindVertexArray(vao);
EXPECT_EQ(GetError(), GL_NO_ERROR);
EXPECT_NE(MG_State::pGLContext->GetVertexArrayObject(vao), nullptr);
GLuint vbo = CreateVBO(GL_ARRAY_BUFFER, 64);
VertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
EXPECT_EQ(GetError(), GL_NO_ERROR);
EXPECT_EQ(GetError(), GL_NO_ERROR);
}
TEST_F(GeneralVertexArrayTest, General_DeleteBoundVAO) {
GLuint vao = CreateVAO();
GLuint vbo = CreateVBO(GL_ARRAY_BUFFER, 64);
VertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
EnableVertexAttribArray(0);
DeleteVertexArrays(1, &vao);
EXPECT_EQ(MG_State::pGLContext->GetBoundVertexArray(), nullptr);
EXPECT_EQ(MG_State::pGLContext->GetVertexArrayObject(vao), nullptr);
VertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
EXPECT_EQ(GetError(), GL_INVALID_OPERATION);
EXPECT_EQ(GetError(), GL_NO_ERROR);
}
@@ -0,0 +1,21 @@
#include "../../../Includes.h"
namespace MobileGL {
namespace MG_Util {
DataType ConvertGLEnumToDataType(GLenum type) {
switch (type) {
case GL_BYTE: return DataType::Int8;
case GL_UNSIGNED_BYTE: return DataType::Uint8;
case GL_SHORT: return DataType::Int16;
case GL_UNSIGNED_SHORT: return DataType::Uint16;
case GL_INT: return DataType::Int32;
case GL_UNSIGNED_INT: return DataType::Uint32;
case GL_HALF_FLOAT: return DataType::Float16;
case GL_FLOAT: return DataType::Float32;
case GL_DOUBLE: return DataType::Float64;
default:
return DataType::Unknown;
}
}
}
}
@@ -0,0 +1,7 @@
#pragma once
namespace MobileGL {
namespace MG_Util {
DataType ConvertGLEnumToDataType(GLenum type);
}
}
@@ -0,0 +1,21 @@
#include "../../../Includes.h"
namespace MobileGL {
namespace MG_Util {
GLenum ConvertDataTypeToGLEnum(DataType type) {
switch (type) {
case DataType::Int8: return GL_BYTE;
case DataType::Uint8: return GL_UNSIGNED_BYTE;
case DataType::Int16: return GL_SHORT;
case DataType::Uint16: return GL_UNSIGNED_SHORT;
case DataType::Int32: return GL_INT;
case DataType::Uint32: return GL_UNSIGNED_INT;
case DataType::Float16: return GL_HALF_FLOAT;
case DataType::Float32: return GL_FLOAT;
case DataType::Float64: return GL_DOUBLE;
default:
return GL_UNKNOWN_MGL;
}
}
}
}
@@ -0,0 +1,7 @@
#pragma once
namespace MobileGL {
namespace MG_Util {
GLenum ConvertDataTypeToGLEnum(DataType type);
}
}
@@ -0,0 +1,22 @@
#include "../../../Includes.h"
namespace MobileGL {
namespace MG_Util {
String ConvertDataTypeToString(DataType type) {
switch (type) {
case DataType::Int8: return "Int8";
case DataType::Uint8: return "Uint8";
case DataType::Int16: return "Int16";
case DataType::Uint16: return "Uint16";
case DataType::Int32: return "Int32";
case DataType::Uint32: return "Uint32";
case DataType::Float16: return "Float16";
case DataType::Float32: return "Float32";
case DataType::Float64: return "Float64";
case DataType::Fixed32: return "Fixed32";
case DataType::Unknown:
default: return "Unknown";
}
}
}
}
@@ -0,0 +1,7 @@
#pragma once
namespace MobileGL {
namespace MG_Util {
String ConvertDataTypeToString(DataType type);
}
}
+2 -1
View File
@@ -74,7 +74,8 @@ namespace MobileGL {
Float16,
Float32,
Float64,
Fixed32
Fixed32,
Unknown = -1
};
// represents a range of [start, end)