diff --git a/CMakeLists.txt b/CMakeLists.txt index daa37a36..42afb407 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,8 +59,12 @@ add_library(${CMAKE_PROJECT_NAME} SHARED MG/MG_GL/State/Core/GLState.cpp MG/MG_GL/State/Common/CommonState.cpp - + MG/MG_GL/State/Texture/TextureState.cpp + + MG/MG_GL/State/VertexArray/VertexArrayState.cpp + + MG/MG_GL/State/Buffer/BufferState.cpp # MG_GL/BackendLoader MG/MG_GL/BackendLoader/GLES/Loader.cpp diff --git a/MG/Constants.h b/MG/Constants.h index f184497f..d7caed3f 100644 --- a/MG/Constants.h +++ b/MG/Constants.h @@ -22,6 +22,22 @@ namespace MG_Constants { inline const int LOG_LEVEL_INFO = 0x0013; inline const int LOG_LEVEL_FATAL = 0x0014; } + + namespace Buffer { + static const std::unordered_set VALID_PARAM_NAMES = { + GL_BUFFER_ACCESS, GL_BUFFER_MAPPED, GL_BUFFER_SIZE, GL_BUFFER_USAGE + }; // OpenGL 3 + + static const std::unordered_set VALID_TARGETS = { + GL_ARRAY_BUFFER, GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, GL_ELEMENT_ARRAY_BUFFER, + GL_PIXEL_PACK_BUFFER, GL_PIXEL_UNPACK_BUFFER, GL_TEXTURE_BUFFER, + GL_TRANSFORM_FEEDBACK_BUFFER, GL_UNIFORM_BUFFER + }; // OpenGL 3 + + static const std::unordered_set VALID_ACCESS = { + GL_READ_ONLY, GL_WRITE_ONLY, GL_READ_WRITE + }; // OpenGL 3 + } namespace PixelStore { static const std::unordered_map DEFAULT_VALUES_MAP = { diff --git a/MG/Includes.h b/MG/Includes.h index 91a18517..5ca8453b 100644 --- a/MG/Includes.h +++ b/MG/Includes.h @@ -44,6 +44,12 @@ #ifndef MOBILEGL_TEXTURESTATE_H #include "MG_GL/State/Texture/TextureState.h" #endif +#ifndef MOBILEGL_VERTEXARRAYSTATE_H +#include "MG_GL/State/VertexArray/VertexArrayState.h" +#endif +#ifndef MOBILEGL_BUFFERSTATE_H +#include "MG_GL/State/Buffer/BufferState.h" +#endif #ifndef MOBILEGL_LOOKUP_H #include "MG_GL/Implementations/GLX/LookUp/LookUp.h" #endif diff --git a/MG/MG_GL/Implementations/GL/Buffer/GL_Buffer.cpp b/MG/MG_GL/Implementations/GL/Buffer/GL_Buffer.cpp index 4a2214c6..f6d567d9 100644 --- a/MG/MG_GL/Implementations/GL/Buffer/GL_Buffer.cpp +++ b/MG/MG_GL/Implementations/GL/Buffer/GL_Buffer.cpp @@ -5,5 +5,104 @@ #include "GL_Buffer.h" namespace MG_GL::GL { + void* MapBuffer(GLenum target, GLenum access) { + MG_Util::Debug::LogD("glMapBuffer(target=0x%x, access=0x%x)", target, access); + + void* mappedPtr = nullptr; + GLenum err = MG_State::AcquireBufferMemory(target, access, &mappedPtr); + + if (err != GL_NO_ERROR) { + MG_State::SetError(err); + MG_Util::Debug::LogE("glMapBuffer failed: %s", + MG_Util::Debug::GLEnumToString(err)); + return nullptr; + } + + MG_Util::Debug::LogD("glMapBuffer returns %p", mappedPtr); + return mappedPtr; + } + GLboolean UnmapBuffer(GLenum target) { + MG_Util::Debug::LogD("glUnmapBuffer(target=0x%x)", target); + + GLenum err = MG_State::ReleaseBufferMemory(target); + if (err != GL_NO_ERROR) { + MG_State::SetError(err); + MG_Util::Debug::LogE("glUnmapBuffer failed: %s", + MG_Util::Debug::GLEnumToString(err)); + return GL_FALSE; + } + + MG_Util::Debug::LogD("glUnmapBuffer succeeded"); + return GL_TRUE; + } + + void BindBuffer(GLenum target, GLuint buffer) { + MG_Util::Debug::LogD("glBindBuffer, target: %d, buffer: %d", target, buffer); + if (buffer != 0 && !MG_State::ValidateBufferHandle(buffer)) { + MG_State::SetError(GL_INVALID_VALUE); + MG_Util::Debug::LogE("Invalid buffer handle: %u", buffer); + return; + } + GLenum result = MG_State::BindBuffer(target, buffer); + if (result == GL_NO_ERROR) + return; + MG_State::SetError(result); + MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result)); + } + + void BufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage) { + MG_Util::Debug::LogD("glBufferData, target: %d, size: %zd, data: %p, usage: %d", + target, size, data, usage); + GLenum result = MG_State::CommitBufferStorage(target, size, data, usage); + if (result == GL_NO_ERROR) + return; + MG_State::SetError(result); + MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result)); + } + + void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params) { + MG_Util::Debug::LogD("glGetBufferParameteriv, target: %d, pname: %d, params: %p", + target, pname, params); + GLenum result = MG_State::QueryBufferPropertyIntVector(target, pname, params); + if (result == GL_NO_ERROR) + return; + MG_State::SetError(result); + MG_Util::Debug::LogE("GetBufferParameteriv not implemented"); + } + + void GenBuffers(GLsizei n, GLuint* buffers) { + MG_Util::Debug::LogD("glGenBuffers, n: %d, buffers: %p", n, buffers); + + if (n < 0) { + MG_State::SetError(GL_INVALID_VALUE); + MG_Util::Debug::LogE("Invalid buffer count: %d", n); + return; + } + + GLenum result = MG_State::CreateBuffers(n, buffers); + if (result == GL_NO_ERROR) { + MG_Util::Debug::LogD("Generated buffers:"); + for (GLsizei i = 0; i < n; ++i) { + MG_Util::Debug::LogD(" Buffer[%d] = %u", i, buffers[i]); + } + return; + } + + MG_State::SetError(result); + MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result)); + } + + GLboolean IsBuffer(GLuint buffer) { + MG_Util::Debug::LogD("glIsBuffer, buffer: %u", buffer); + + if (buffer == 0) { + return GL_FALSE; + } + + bool isValid = MG_State::ValidateBufferHandle(buffer); + // Should we report gl error here or in MG_State? + MG_Util::Debug::LogD("Buffer %u is %s", buffer, isValid ? "valid" : "invalid"); + return isValid ? GL_TRUE : GL_FALSE; + } } \ No newline at end of file diff --git a/MG/MG_GL/Implementations/GL/Buffer/GL_Buffer.h b/MG/MG_GL/Implementations/GL/Buffer/GL_Buffer.h index 01870b9e..4ac655eb 100644 --- a/MG/MG_GL/Implementations/GL/Buffer/GL_Buffer.h +++ b/MG/MG_GL/Implementations/GL/Buffer/GL_Buffer.h @@ -8,7 +8,13 @@ #include "../../../../Includes.h" namespace MG_GL::GL { - + void* MapBuffer(GLenum target, GLenum access); + GLboolean UnmapBuffer(GLenum target); + void BindBuffer(GLenum target, GLuint buffer); + void BufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage); + void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params); + void GenBuffers(GLsizei n, GLuint* buffers); + GLboolean IsBuffer(GLuint buffer); } #endif //MOBILEGL_GL_BUFFER_H diff --git a/MG/MG_GL/Implementations/GL/GLFuncsDefinitions/GLFuncsDefinitions.cpp b/MG/MG_GL/Implementations/GL/GLFuncsDefinitions/GLFuncsDefinitions.cpp index d77e1535..eaf8c198 100644 --- a/MG/MG_GL/Implementations/GL/GLFuncsDefinitions/GLFuncsDefinitions.cpp +++ b/MG/MG_GL/Implementations/GL/GLFuncsDefinitions/GLFuncsDefinitions.cpp @@ -9,7 +9,7 @@ MG_EXPORT type gl##name(__VA_ARGS__) { #define DECLARE_GL_FUNCTION_STUB_END(type,name,...) \ MG_Util::Debug::LogW("Stub function: %s(...)", __FUNCTION__); \ - return (type)0; \ + return (type)1; \ } #define DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(type,name,...) \ @@ -31,12 +31,12 @@ MG_EXPORT type gl##name(__VA_ARGS__) { DECLARE_GL_FUNCTION_HEAD(const GLubyte*, GetStringi, GLenum name, GLuint index) DECLARE_GL_FUNCTION_END(const GLubyte*, GetStringi, name, index) DECLARE_GL_FUNCTION_HEAD(const GLubyte*, GetString, GLenum name) DECLARE_GL_FUNCTION_END(const GLubyte*, GetString, name) -DECLARE_GL_FUNCTION_STUB_HEAD(void*, MapBuffer, GLenum target, GLenum access) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void*, MapBuffer, target, access) +DECLARE_GL_FUNCTION_HEAD(void*, MapBuffer, GLenum target, GLenum access) DECLARE_GL_FUNCTION_END(void*, MapBuffer, target, access) DECLARE_GL_FUNCTION_HEAD(void, ClearDepth, GLclampd depth) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ClearDepth, depth) DECLARE_GL_FUNCTION_HEAD(void, ActiveTexture, GLenum texture) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ActiveTexture, texture) DECLARE_GL_FUNCTION_STUB_HEAD(void, AttachShader, GLuint program, GLuint shader) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, AttachShader, program,shader) DECLARE_GL_FUNCTION_STUB_HEAD(void, BindAttribLocation, GLuint program, GLuint index, const GLchar *name) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BindAttribLocation, program,index,name) -DECLARE_GL_FUNCTION_STUB_HEAD(void, BindBuffer, GLenum target, GLuint buffer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BindBuffer, target,buffer) +DECLARE_GL_FUNCTION_HEAD(void, BindBuffer, GLenum target, GLuint buffer) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BindBuffer, target,buffer) DECLARE_GL_FUNCTION_STUB_HEAD(void, BindFramebuffer, GLenum target, GLuint framebuffer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BindFramebuffer, target,framebuffer) DECLARE_GL_FUNCTION_STUB_HEAD(void, BindRenderbuffer, GLenum target, GLuint renderbuffer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BindRenderbuffer, target,renderbuffer) DECLARE_GL_FUNCTION_HEAD(void, BindTexture, GLenum target, GLuint texture) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BindTexture, target,texture) @@ -45,7 +45,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendEquation, GLenum mode) DECLARE_GL_FUNCT DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendEquationSeparate, GLenum modeRGB, GLenum modeAlpha) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendEquationSeparate, modeRGB,modeAlpha) DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendFunc, GLenum sfactor, GLenum dfactor) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendFunc, sfactor,dfactor) DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendFuncSeparate, GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendFuncSeparate, sfactorRGB,dfactorRGB,sfactorAlpha,dfactorAlpha) -DECLARE_GL_FUNCTION_STUB_HEAD(void, BufferData, GLenum target, GLsizeiptr size, const void *data, GLenum usage) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BufferData, target,size,data,usage) +DECLARE_GL_FUNCTION_HEAD(void, BufferData, GLenum target, GLsizeiptr size, const void *data, GLenum usage) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BufferData, target,size,data,usage) DECLARE_GL_FUNCTION_STUB_HEAD(void, BufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, const void *data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BufferSubData, target,offset,size,data) DECLARE_GL_FUNCTION_HEAD(GLenum, CheckFramebufferStatus, GLenum target) DECLARE_GL_FUNCTION_END(GLenum, CheckFramebufferStatus, target) DECLARE_GL_FUNCTION_HEAD(void, Clear, GLbitfield mask) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Clear, mask) @@ -76,13 +76,13 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, DisableVertexAttribArray, GLuint index) DECL DECLARE_GL_FUNCTION_HEAD(void, DrawArrays, GLenum mode, GLint first, GLsizei count) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DrawArrays, mode,first,count) DECLARE_GL_FUNCTION_HEAD(void, DrawElements, GLenum mode, GLsizei count, GLenum type, const void *indices) DECLARE_GL_FUNCTION_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) DECLARE_GL_FUNCTION_STUB_HEAD(void, FramebufferTexture2D, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, FramebufferTexture2D, target,attachment,textarget,texture,level) DECLARE_GL_FUNCTION_STUB_HEAD(void, FrontFace, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, FrontFace, mode) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GenBuffers, GLsizei n, GLuint *buffers) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GenBuffers, n,buffers) +DECLARE_GL_FUNCTION_HEAD(void, GenBuffers, GLsizei n, GLuint *buffers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GenBuffers, n,buffers) DECLARE_GL_FUNCTION_STUB_HEAD(void, GenerateMipmap, GLenum target) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GenerateMipmap, target) DECLARE_GL_FUNCTION_STUB_HEAD(void, GenFramebuffers, GLsizei n, GLuint *framebuffers) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GenFramebuffers, n,framebuffers) DECLARE_GL_FUNCTION_STUB_HEAD(void, GenRenderbuffers, GLsizei n, GLuint *renderbuffers) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GenRenderbuffers, n,renderbuffers) @@ -92,7 +92,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, GetActiveUniform, GLuint program, GLuint ind DECLARE_GL_FUNCTION_STUB_HEAD(void, GetAttachedShaders, GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetAttachedShaders, program,maxCount,count,shaders) DECLARE_GL_FUNCTION_STUB_HEAD(GLint, GetAttribLocation, GLuint program, const GLchar *name) DECLARE_GL_FUNCTION_STUB_END(GLint, GetAttribLocation, program,name) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetBooleanv, GLenum pname, GLboolean *data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetBooleanv, pname,data) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetBufferParameteriv, GLenum target, GLenum pname, GLint *params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetBufferParameteriv, target,pname,params) +DECLARE_GL_FUNCTION_HEAD(void, GetBufferParameteriv, GLenum target, GLenum pname, GLint *params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetBufferParameteriv, target,pname,params) DECLARE_GL_FUNCTION_HEAD(GLenum, GetError) DECLARE_GL_FUNCTION_END(GLenum, GetError) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetFloatv, GLenum pname, GLfloat *data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetFloatv, pname,data) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetFramebufferAttachmentParameteriv, GLenum target, GLenum attachment, GLenum pname, GLint *params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetFramebufferAttachmentParameteriv, target,attachment,pname,params) @@ -113,7 +113,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) @@ -172,7 +172,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) @@ -188,7 +188,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, BeginQuery, GLenum target, GLuint id) DECLAR DECLARE_GL_FUNCTION_STUB_HEAD(void, EndQuery, GLenum target) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, EndQuery, target) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetQueryiv, GLenum target, GLenum pname, GLint *params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetQueryiv, target,pname,params) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetQueryObjectuiv, GLuint id, GLenum pname, GLuint *params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetQueryObjectuiv, id,pname,params) -DECLARE_GL_FUNCTION_STUB_HEAD(GLboolean, UnmapBuffer, GLenum target) DECLARE_GL_FUNCTION_STUB_END(GLboolean, UnmapBuffer, target) +DECLARE_GL_FUNCTION_HEAD(GLboolean, UnmapBuffer, GLenum target) DECLARE_GL_FUNCTION_END(GLboolean, UnmapBuffer, target) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetBufferPointerv, GLenum target, GLenum pname, void **params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetBufferPointerv, target,pname,params) DECLARE_GL_FUNCTION_STUB_HEAD(void, DrawBuffers, GLsizei n, const GLenum *bufs) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DrawBuffers, n,bufs) DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix2x3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix2x3fv, location,count,transpose,value) @@ -201,9 +201,9 @@ 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_STUB_HEAD(void, FlushMappedBufferRange, GLenum target, GLintptr offset, GLsizeiptr length) DECLARE_GL_FUNCTION_STUB_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_HEAD(void, BindVertexArray, GLuint array) DECLARE_GL_FUNCTION_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_HEAD(void, GenVertexArrays, GLsizei n, GLuint *arrays) DECLARE_GL_FUNCTION_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_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) @@ -212,7 +212,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) diff --git a/MG/MG_GL/Implementations/GL/VertexArray/GL_VertexArray.cpp b/MG/MG_GL/Implementations/GL/VertexArray/GL_VertexArray.cpp index dcc5f5f6..04918d3b 100644 --- a/MG/MG_GL/Implementations/GL/VertexArray/GL_VertexArray.cpp +++ b/MG/MG_GL/Implementations/GL/VertexArray/GL_VertexArray.cpp @@ -5,5 +5,49 @@ #include "GL_VertexArray.h" 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); + if (result == GL_NO_ERROR) return; + MG_State::SetError(result); + MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result)); + } + + void BindVertexArray(GLuint array) { + MG_Util::Debug::LogD("glBindVertexArray, array: %u", array); + GLenum result = MG_State::BindVertexArray(array); + if (result == GL_NO_ERROR) return; + MG_State::SetError(result); + MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result)); + } + + void EnableVertexAttribArray(GLuint index) { + MG_Util::Debug::LogD("glEnableVertexAttribArray, index: %u", index); + GLenum result = MG_State::EnableVertexAttribArray(index); + if (result == GL_NO_ERROR) return; + MG_State::SetError(result); + MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result)); + } + + void VertexAttribPointer(GLuint index, GLint size, GLenum type, + GLboolean normalized, GLsizei stride, const void* pointer) { + MG_Util::Debug::LogD("glVertexAttribPointer, index: %u, size: %d, type: %s, norm: %d, stride: %d, ptr: %p", + index, size, MG_Util::Debug::GLEnumToString(type), normalized, stride, pointer); + + GLenum result = MG_State::SetVertexAttributeLayout(index, size, type, normalized, stride, pointer); + if (result == GL_NO_ERROR) return; + MG_State::SetError(result); + MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result)); + } + + void VertexAttribIPointer(GLuint index, GLint size, GLenum type, + GLsizei stride, const void* pointer) { + MG_Util::Debug::LogD("glVertexAttribIPointer, index: %u, size: %d, type: %s, stride: %d, ptr: %p", + index, size, MG_Util::Debug::GLEnumToString(type), stride, pointer); + + GLenum result = MG_State::SetVertexAttributeLayoutInt(index, size, type, stride, pointer); + if (result == GL_NO_ERROR) return; + MG_State::SetError(result); + MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result)); + } } \ No newline at end of file diff --git a/MG/MG_GL/Implementations/GL/VertexArray/GL_VertexArray.h b/MG/MG_GL/Implementations/GL/VertexArray/GL_VertexArray.h index 61f3433c..4fbbe634 100644 --- a/MG/MG_GL/Implementations/GL/VertexArray/GL_VertexArray.h +++ b/MG/MG_GL/Implementations/GL/VertexArray/GL_VertexArray.h @@ -8,7 +8,11 @@ #include "../../../../Includes.h" namespace MG_GL::GL { - + void GenVertexArrays(GLsizei n, GLuint* arrays); + void BindVertexArray(GLuint array); + void EnableVertexAttribArray(GLuint index); + void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer); + void VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer); } #endif //MOBILEGL_GL_VERTEXARRAY_H diff --git a/MG/MG_GL/State/Buffer/BufferState.cpp b/MG/MG_GL/State/Buffer/BufferState.cpp new file mode 100644 index 00000000..4dde0d53 --- /dev/null +++ b/MG/MG_GL/State/Buffer/BufferState.cpp @@ -0,0 +1,196 @@ +// +// Created by BZLZHH on 2025/5/1. +// + +// TODO: Add more gl error check for buffer state manager. + +#include "BufferState.h" + +GLenum BufferState::Create(GLuint* buffer) { + MG_Util::Debug::LogD("MG_State: Buffer: Create called"); + if (!buffer) return GL_INVALID_VALUE; + + GLuint id = 0; + if (!freeIds_.empty()) { + id = *freeIds_.begin(); + freeIds_.erase(freeIds_.begin()); + } else { + id = ++lastId_; + } + *buffer = id; + BufferObject& obj = buffers_[id]; + MG_Util::Debug::LogD("MG_State: Buffer: Create created buffer %d", id); + obj.generated = true; + + return GL_NO_ERROR; +} + +GLenum BufferState::CreateN(GLsizei n, GLuint* buffers) { + MG_Util::Debug::LogD("MG_State: Buffer: CreateN called with n=%d", n); + if (n < 0) return GL_INVALID_VALUE; + + for (GLsizei i = 0; i < n; ++i) { + GLenum result = Create(&buffers[i]); + if (result != GL_NO_ERROR) { + MG_Util::Debug::LogE("MG_State: Buffer: CreateN create buffer failed with error 0x%x", result); + return result; + } + } + MG_Util::Debug::LogD("MG_State: Buffer: CreateN created buffers successfully"); + return GL_NO_ERROR; +} + +GLenum BufferState::Bind(GLenum target, GLuint buffer) { + if (!IsValidTarget_(target)) return GL_INVALID_ENUM; + MG_Util::Debug::LogD("MG_State: Buffer: Bind called with target=0x%x, buffer=%u", target, buffer); + + if (buffer != 0) { + auto it = buffers_.find(buffer); + if (it == buffers_.end()) { + buffers_[buffer]; + } else { + BufferObject& obj = it->second; + if (obj.target != 0 && obj.target != target) { + MG_Util::Debug::LogE("MG_State: Buffer: Bind can not bind a buffer to different target 0x%x, current bind target is 0x%x", target, obj.target); + return GL_INVALID_OPERATION; + } + } + buffers_[buffer].target = target; + } + + currentBindings_[target] = buffer; + MG_Util::Debug::LogD("MG_State: Buffer: Bind succeed bind buffer %u to target 0x%x", buffer, target); + return GL_NO_ERROR; +} + +GLenum BufferState::CommitStorage(GLenum target, GLsizeiptr size, const void* data, GLenum usage) { + MG_Util::Debug::LogD("MG_State: Buffer: CommitStorage called on target 0x%x",target); + auto it = currentBindings_.find(target); + if (it == currentBindings_.end() || it->second == 0) + return GL_INVALID_OPERATION; + + BufferObject& obj = buffers_[it->second]; + MG_Util::Debug::LogD("MG_State: Buffer: CommitStorage get buffer object %u at target 0x%x",it->second,target); + obj.usage = usage; + obj.data.resize(size); + if (data) memcpy(obj.data.data(), data, size); + MG_Util::Debug::LogD("MG_State: Buffer: CommitStorage buffer at target 0x%x committed storage, size = %zu, usage=0x%x", target, size, usage); + + return GL_NO_ERROR; +} + +GLenum BufferState::AcquireBufferMemory(GLenum target, GLenum access, void** mappedPointer) { + if (!IsValidTarget_(target)) return GL_INVALID_ENUM; + if (MG_Constants::Buffer::VALID_ACCESS.find(access) == MG_Constants::Buffer::VALID_ACCESS.end()) { + return GL_INVALID_ENUM; + MG_Util::Debug::LogD("MG_State: Buffer: AcquireBufferMemory buffer at target 0x%x acquired mapped memory, access mode = 0x%x", target, access); + } + + auto it = currentBindings_.find(target); + if (it == currentBindings_.end() || it->second == 0) + return GL_INVALID_OPERATION; + + BufferObject& obj = buffers_[it->second]; + if (obj.isMapped) return GL_INVALID_OPERATION; + + obj.isMapped = true; + *mappedPointer = obj.data.data(); + obj.isMapped = true; + obj.accessMode = access; + + return GL_NO_ERROR; +} + +GLenum BufferState::ReleaseBufferMemory(GLenum target) { + MG_Util::Debug::LogD("MG_State: Buffer: ReleaseBufferMemory called on target 0x%x",target); + if (!IsValidTarget_(target)) return GL_INVALID_ENUM; + + + auto it = currentBindings_.find(target); + if (it == currentBindings_.end() || it->second == 0) + return GL_INVALID_OPERATION; + + BufferObject& obj = buffers_[it->second]; + if (!obj.isMapped) return GL_INVALID_OPERATION; + + obj.isMapped = false; + obj.accessMode = GL_READ_WRITE; + MG_Util::Debug::LogD("MG_State: Buffer: ReleaseBufferMemory buffer at target 0x%x released mapped memory", target); + return GL_NO_ERROR; +} + +bool BufferState::ValidateHandle(GLuint buffer) { + bool isvalid = buffers_.count(buffer) > 0; + MG_Util::Debug::LogD("MG_State: Buffer: ValidateHandle called on buffer %u returns %d", buffer, isvalid); + return isvalid; +} + +void BufferState::Delete(GLuint buffer) { + if (buffers_.erase(buffer)) { + freeIds_.insert(buffer); + for (auto& [target, id] : currentBindings_) { + if (id == buffer) id = 0; + } + } + MG_Util::Debug::LogD("MG_State: Buffer: Delete buffer %u", buffer); +} + +bool BufferState::IsValidTarget_(GLenum target) { + MG_Util::Debug::LogD("MG_State: Buffer: IsValidTarget_ called with target=0x%x,result=%d", target, !(MG_Constants::Buffer::VALID_TARGETS.find(target) == MG_Constants::Buffer::VALID_TARGETS.end())); + return !(MG_Constants::Buffer::VALID_TARGETS.find(target) == MG_Constants::Buffer::VALID_TARGETS.end()); +} + +GLenum BufferState::QueryPropertyIntVector(GLenum target, GLenum pname, GLint* params) const { + MG_Util::Debug::LogD("MG_State: Buffer: QueryPropertyIntVector called at target 0x%x,param name = 0x%x",target,pname); + static const std::set validTargets = { + GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER, + GL_PIXEL_PACK_BUFFER, GL_PIXEL_UNPACK_BUFFER + }; + if (validTargets.find(target) == validTargets.end()) { + return GL_INVALID_ENUM; + } + + if (MG_Constants::Buffer::VALID_PARAM_NAMES.find(pname) == MG_Constants::Buffer::VALID_PARAM_NAMES.end()) { + return GL_INVALID_ENUM; + } + + auto bindingIt = currentBindings_.find(target); + if (bindingIt == currentBindings_.end() || bindingIt->second == 0) { + return GL_INVALID_OPERATION; + } + GLuint bufferId = bindingIt->second; + auto bufferIt = buffers_.find(bufferId); + if (bufferIt == buffers_.end()) { + return GL_INVALID_OPERATION; + } + + const BufferObject& buffer = bufferIt->second; + + switch (pname) { + case GL_BUFFER_ACCESS: + *params = static_cast(buffer.accessMode); + break; + case GL_BUFFER_MAPPED: + *params = buffer.isMapped ? GL_TRUE : GL_FALSE; + break; + case GL_BUFFER_SIZE: + *params = static_cast(buffer.data.size()); + break; + case GL_BUFFER_USAGE: + *params = static_cast(buffer.usage); + break; + MG_Util::Debug::LogD("MG_State: Buffer: QueryPropertyIntVector Query info about buffer %u succeed",buffer.target); + default: + return GL_INVALID_ENUM; + } + return GL_NO_ERROR; +} + + +GLuint BufferState::GetCurrentBinding(GLenum target) const { + auto it = currentBindings_.find(target); + if (it != currentBindings_.end()) { + return it->second; + } + return 0; +} \ No newline at end of file diff --git a/MG/MG_GL/State/Buffer/BufferState.h b/MG/MG_GL/State/Buffer/BufferState.h new file mode 100644 index 00000000..28db6c1f --- /dev/null +++ b/MG/MG_GL/State/Buffer/BufferState.h @@ -0,0 +1,44 @@ +// +// Created by BZLZHH on 2025/5/1. +// + +#ifndef MOBILEGL_BUFFERSTATE_H +#define MOBILEGL_BUFFERSTATE_H +#define MOBILEGL_GLSTATE_H + +#include "../../../Includes.h" + +class BufferState { +public: + struct BufferObject { + GLenum target = 0; + GLenum usage = GL_STATIC_DRAW; + std::vector data; + bool isMapped = false; + bool generated = false; + GLenum accessMode = GL_READ_WRITE; + }; + + // Return: the validity of the operation, according to OpenGL 3 standard + GLenum Create(GLuint* buffer); + GLenum CreateN(GLsizei n, GLuint* buffers); + GLenum Bind(GLenum target, GLuint buffer); + GLenum CommitStorage(GLenum target, GLsizeiptr size, const void* data, GLenum usage); + GLenum AcquireBufferMemory(GLenum target, GLenum access, void** mappedPointer); + GLenum ReleaseBufferMemory(GLenum target); + GLenum QueryPropertyIntVector(GLenum target, GLenum pname, GLint* params) const; + + bool ValidateHandle(GLuint buffer); + void Delete(GLuint buffer); + GLuint GetCurrentBinding(GLenum target) const; + +private: + std::unordered_map buffers_; + std::set freeIds_; + GLuint lastId_ = 0; + std::unordered_map currentBindings_; + + static bool IsValidTarget_(GLenum target); +}; + +#endif //MOBILEGL_BUFFERSTATE_H diff --git a/MG/MG_GL/State/Common/CommonState.h b/MG/MG_GL/State/Common/CommonState.h index efa74859..a2b58a61 100644 --- a/MG/MG_GL/State/Common/CommonState.h +++ b/MG/MG_GL/State/Common/CommonState.h @@ -13,7 +13,9 @@ private: std::unordered_map pixelStoreParams; public: + // Return: the validity of the operation, according to OpenGL 3 standard GLenum SetPixelStoreInt(GLenum pname, GLint param); + GLint GetPixelStoreInt(GLenum pname); }; diff --git a/MG/MG_GL/State/Core/GLState.cpp b/MG/MG_GL/State/Core/GLState.cpp index 60096e58..bcd4d433 100644 --- a/MG/MG_GL/State/Core/GLState.cpp +++ b/MG/MG_GL/State/Core/GLState.cpp @@ -7,16 +7,22 @@ std::queue MG_State_T::glErrorQueue; TextureState* MG_State_T::textureState = nullptr; CommonState* MG_State_T::commonState = nullptr; +BufferState* MG_State_T::bufferState = nullptr; +VertexArrayState* MG_State_T::vertexArrayState = nullptr; namespace MG_State { void Init() { MG_State_T::textureState = new TextureState(); MG_State_T::commonState = new CommonState(); + MG_State_T::bufferState = new BufferState(); + MG_State_T::vertexArrayState = new VertexArrayState(); } void Destroy() { delete MG_State_T::textureState; delete MG_State_T::commonState; + delete MG_State_T::bufferState; + delete MG_State_T::vertexArrayState; } void SetError(GLenum error) { @@ -34,7 +40,9 @@ namespace MG_State { MG_State_T::glErrorQueue.pop(); return error; } - + +// TODO: Take these functions apart into multiple files. + // Texture GLenum BindTextureUnit(GLenum textureUnit) { return MG_State_T::textureState->BindUnit(textureUnit); @@ -83,7 +91,8 @@ namespace MG_State { GLenum GetTextureLevelPropertyIntVector(GLenum target, GLint level, GLenum pname, GLint* params) { return MG_State_T::textureState->GetLevelPropertyIntVector(target, level, pname, params); } - + + // Common GLenum MG_State::SetPixelStoreInt(GLenum pname, GLint param) { return MG_State_T::commonState->SetPixelStoreInt(pname, param); } @@ -91,5 +100,84 @@ namespace MG_State { GLint MG_State::GetPixelStoreInt(GLenum pname) { return MG_State_T::commonState->GetPixelStoreInt(pname); } + + // Buffer + GLenum AcquireBufferMemory(GLenum target, GLenum access, void** mappedPtr) { + return MG_State_T::bufferState->AcquireBufferMemory(target, access, mappedPtr); + } + GLenum ReleaseBufferMemory(GLenum target) { + return MG_State_T::bufferState->ReleaseBufferMemory(target); + } + + GLenum CreateBuffer(GLuint* buffer) { + return MG_State_T::bufferState->Create(buffer); + } + + GLenum CreateBuffers(GLsizei n, GLuint* buffers) { + return MG_State_T::bufferState->CreateN(n, buffers); + } + + GLenum BindBuffer(GLenum target, GLuint buffer) { + if (target == GL_ELEMENT_ARRAY_BUFFER) { + auto* vao = MG_State_T::vertexArrayState->GetCurrentVAO(); + if (!vao) return GL_INVALID_OPERATION; + vao->elementBuffer = (GLuint)buffer; + } + return MG_State_T::bufferState->Bind(target, buffer); + } + + GLenum CommitBufferStorage(GLenum target, GLsizeiptr size, const void* data, GLenum usage) { + return MG_State_T::bufferState->CommitStorage(target, size, data, usage); + } + + bool ValidateBufferHandle(GLuint buffer) { + return MG_State_T::bufferState->ValidateHandle(buffer); + } + + void DeleteBuffer(GLuint buffer) { + return MG_State_T::bufferState->Delete(buffer); + } + + GLenum QueryBufferPropertyIntVector(GLenum target, GLenum pname, GLint* params) { + return MG_State_T::bufferState->QueryPropertyIntVector(target, pname, params); + } + + // VertexArray + GLenum BindVertexArray(GLuint array) { + return MG_State_T::vertexArrayState->Bind(array); + } + + GLenum CreateVertexArray(GLuint* array) { + return MG_State_T::vertexArrayState->Create(array); + } + + GLenum CreateVertexArrays(GLsizei n, GLuint* arrays) { + return MG_State_T::vertexArrayState->CreateN(n, arrays); + } + + GLenum EnableVertexAttribArray(GLuint index) { + return MG_State_T::vertexArrayState->EnableAttrib(index); + } + + GLenum DisableVertexAttribArray(GLuint index) { + return MG_State_T::vertexArrayState->DisableAttrib(index); + } + + GLenum SetVertexAttributeLayout(GLuint index, GLint size, GLenum type, + GLboolean normalized, GLsizei stride, + const void* pointer) { + GLuint currentBuffer = MG_State_T::bufferState->GetCurrentBinding(GL_ARRAY_BUFFER); + return MG_State_T::vertexArrayState->SetAttribPointer( + index, size, type, normalized, stride, pointer, false, currentBuffer + ); + } + + GLenum SetVertexAttributeLayoutInt(GLuint index, GLint size, GLenum type, + GLsizei stride, const void* pointer) { + GLuint currentBuffer = MG_State_T::bufferState->GetCurrentBinding(GL_ARRAY_BUFFER); + return MG_State_T::vertexArrayState->SetAttribPointer( + index, size, type, GL_FALSE, stride, pointer, true, currentBuffer + ); + } } \ No newline at end of file diff --git a/MG/MG_GL/State/Core/GLState.h b/MG/MG_GL/State/Core/GLState.h index 7d60c791..25cdda1e 100644 --- a/MG/MG_GL/State/Core/GLState.h +++ b/MG/MG_GL/State/Core/GLState.h @@ -11,6 +11,8 @@ struct MG_State_T { static std::queue glErrorQueue; static TextureState* textureState; static CommonState* commonState; + static BufferState* bufferState; + static VertexArrayState* vertexArrayState; }; namespace MG_State { @@ -35,9 +37,34 @@ namespace MG_State { GLenum DeleteTexture(GLuint texture); GLenum DeleteTextures(GLsizei n, const GLuint* textures); GLenum GetTextureLevelPropertyIntVector(GLenum target, GLint level, GLenum pname, GLint* params); + + // Common GLenum SetPixelStoreInt(GLenum pname, GLint param); - GLint GetPixelStoreInt(GLenum pname); + + // Buffer + GLenum AcquireBufferMemory(GLenum target, GLenum access, void** mappedPtr); + GLenum ReleaseBufferMemory(GLenum target); + GLenum CreateBuffer(GLuint* buffer); + GLenum CreateBuffers(GLsizei n, GLuint* buffers); + GLenum BindBuffer(GLenum target, GLuint buffer); + GLenum CommitBufferStorage(GLenum target, GLsizeiptr size, const void* data, GLenum usage); + bool ValidateBufferHandle(GLuint buffer); + void DeleteBuffer(GLuint buffer); + GLenum QueryBufferPropertyIntVector(GLenum target, GLenum pname, GLint* params); + + // VertexArray + + GLenum CreateVertexArray(GLuint* array); + GLenum CreateVertexArrays(GLsizei n, GLuint* arrays); + GLenum BindVertexArray(GLuint array); + GLenum EnableVertexAttribArray(GLuint index); + GLenum DisableVertexAttribArray(GLuint index); + GLenum SetVertexAttributeLayout(GLuint index, GLint size, GLenum type, + GLboolean normalized, GLsizei stride, + const void* pointer); + GLenum SetVertexAttributeLayoutInt(GLuint index, GLint size, GLenum type, + GLsizei stride, const void* pointer); } diff --git a/MG/MG_GL/State/Texture/TextureState.h b/MG/MG_GL/State/Texture/TextureState.h index 6bdbfbd4..ccc1a96b 100644 --- a/MG/MG_GL/State/Texture/TextureState.h +++ b/MG/MG_GL/State/Texture/TextureState.h @@ -98,10 +98,9 @@ private: static void ReverseBitOrder_(const GLubyte* src, GLubyte* dst, size_t size); static GLubyte ReverseBits_(GLubyte b); void SwapPixelBytes_(GLenum format, GLenum type, const GLubyte* src, GLubyte* dst); - GLenum CheckUploadingTexture2DValidity_(GLenum target, GLint level, GLint internalFormat, - GLsizei width, GLsizei height, GLint border, GLenum format, - GLenum type, const void* data); + GLsizei width, GLsizei height, GLint border, GLenum format, + GLenum type, const void* data); GLenum CheckUpdatingTextureRegion2DValidity_(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* data); diff --git a/MG/MG_GL/State/VertexArray/VertexArrayState.cpp b/MG/MG_GL/State/VertexArray/VertexArrayState.cpp new file mode 100644 index 00000000..6995604f --- /dev/null +++ b/MG/MG_GL/State/VertexArray/VertexArrayState.cpp @@ -0,0 +1,91 @@ +// +// Created by BZLZHH on 2025/5/1. +// + +// TODO: Add more gl error check for buffer state manager. + +#include "VertexArrayState.h" + +VertexArrayState::VertexArrayState() { + vaos_[0]; +} + +GLenum VertexArrayState::Create(GLuint* array) { + if (array == nullptr) return GL_INVALID_VALUE; + + GLuint id = freeIds_.empty() ? ++lastId_ : *freeIds_.begin(); + if (!freeIds_.empty()) { + freeIds_.erase(freeIds_.begin()); + } + + *array = id; + vaos_[id].generated = true; + return GL_NO_ERROR; +} + +GLenum VertexArrayState::CreateN(GLsizei n, GLuint* arrays) { + if (n < 0) { + return GL_INVALID_VALUE; + } + + 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_.count(array)) return GL_INVALID_OPERATION; + currentVao_ = array; + 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; + vaos_[currentVao_].attribs[index].enabled = true; + 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; + vaos_[currentVao_].attribs[index].enabled = false; + 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; + + 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_); + return (it != vaos_.end()) ? &it->second : &vaos_.at(0); +} \ No newline at end of file diff --git a/MG/MG_GL/State/VertexArray/VertexArrayState.h b/MG/MG_GL/State/VertexArray/VertexArrayState.h new file mode 100644 index 00000000..8b02e9b9 --- /dev/null +++ b/MG/MG_GL/State/VertexArray/VertexArrayState.h @@ -0,0 +1,53 @@ +// +// Created by BZLZHH on 2025/5/1. +// + +#ifndef MOBILEGL_VERTEXARRAYSTATE_H +#define MOBILEGL_VERTEXARRAYSTATE_H +#define MOBILEGL_GLSTATE_H + +#include "../../../Includes.h" + +struct VertexAttribState { + bool enabled = false; + GLint size = 4; + GLenum type = GL_FLOAT; + GLboolean normalized = GL_FALSE; + GLsizei stride = 0; + const GLvoid* pointer = nullptr; + GLuint buffer = 0; + bool isInteger = false; +}; + +struct VertexArrayObject { + bool generated = false; + GLuint elementBuffer = 0; + std::unordered_map attribs; +}; + +class VertexArrayState { +public: + VertexArrayState(); + + // Return: the validity of the operation, according to OpenGL 3 standard + GLenum Create(GLuint* array); + GLenum CreateN(GLsizei n, GLuint* arrays); + GLenum Bind(GLuint array); + GLenum EnableAttrib(GLuint index); + GLenum DisableAttrib(GLuint index); + GLenum SetAttribPointer(GLuint index, GLint size, GLenum type, + GLboolean normalized, GLsizei stride, + const void* pointer, bool isInteger, + GLuint currentArrayBuffer); + + GLuint GetBoundElementBuffer(); + VertexArrayObject* GetCurrentVAO(); + +private: + std::unordered_map vaos_; + std::set freeIds_; + GLuint lastId_ = 0; + GLuint currentVao_ = 0; +}; + +#endif //MOBILEGL_VERTEXARRAYSTATE_H