diff --git a/MobileGL/MG_Impl/GLImpl/Buffer/GL_Buffer.cpp b/MobileGL/MG_Impl/GLImpl/Buffer/GL_Buffer.cpp index e9f0136a..15f28580 100644 --- a/MobileGL/MG_Impl/GLImpl/Buffer/GL_Buffer.cpp +++ b/MobileGL/MG_Impl/GLImpl/Buffer/GL_Buffer.cpp @@ -38,6 +38,7 @@ namespace MobileGL::MG_Impl::GLImpl { GetNamedBufferParameteriv, GetNamedBufferParameteri64v, GetNamedBufferPointerv, + GetNamedBufferSubData, }; const char* GetBufferOpName(BufferOp op) { @@ -76,6 +77,8 @@ namespace MobileGL::MG_Impl::GLImpl { return "UnmapNamedBuffer"; case BufferOp::FlushMappedNamedBufferRange: return "FlushMappedNamedBufferRange"; + case BufferOp::GetNamedBufferSubData: + return "GetNamedBufferSubData"; case BufferOp::GetNamedBufferParameteriv: return "GetNamedBufferParameteriv"; case BufferOp::GetNamedBufferParameteri64v: @@ -891,6 +894,44 @@ namespace MobileGL::MG_Impl::GLImpl { bufferObject->DownloadSubData(data, static_cast(offset), static_cast(size)); } + void GetNamedBufferSubData_State(GLuint buffer, GLintptr offset, GLsizeiptr size, void* data) { + if (!data) { + // Match GetBufferSubData_State: a null pointer is a caller bug, not a GL-specified error. + return; + } + + if (size < 0 || offset < 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", "GetNamedBufferSubData_State", + "Offset and size must be non-negative.")); + return; + } + + auto bufferObject = GetNamedBufferObject(buffer, BufferOp::GetNamedBufferSubData); + if (!bufferObject) return; + + if (static_cast(offset) + static_cast(size) > bufferObject->GetSize()) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", "GetNamedBufferSubData_State", + "Offset and size exceed buffer size.")); + return; + } + + if (bufferObject->IsMapped() && + !(bufferObject->GetMappingAccess() & BufferMappingAccessBit::Persistent)) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", "GetNamedBufferSubData_State", + "Cannot read from a buffer object mapped without GL_MAP_PERSISTENT_BIT.")); + return; + } + + bufferObject->SyncGpuWrites(); + bufferObject->DownloadSubData(data, static_cast(offset), static_cast(size)); + } + void BufferData_State(GLenum target, GLsizeiptr size, const void* data, GLenum usage) { MGLOG_D("%s: %s, size = %d, data = %p, usage = %s", __func__, MG_Util::ConvertGLEnumToString(target).c_str(), size, data, MG_Util::ConvertGLEnumToString(usage).c_str()); @@ -1553,6 +1594,10 @@ namespace MobileGL::MG_Impl::GLImpl { BufferSubData_State(target, offset, size, data); } + void GetNamedBufferSubData(GLuint buffer, GLintptr offset, GLsizeiptr size, void* data) { + GetNamedBufferSubData_State(buffer, offset, size, data); + } + void GetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, void* data) { GetBufferSubData_State(target, offset, size, data); } diff --git a/MobileGL/MG_Impl/GLImpl/Buffer/GL_Buffer.h b/MobileGL/MG_Impl/GLImpl/Buffer/GL_Buffer.h index a408189c..3a24dfc2 100644 --- a/MobileGL/MG_Impl/GLImpl/Buffer/GL_Buffer.h +++ b/MobileGL/MG_Impl/GLImpl/Buffer/GL_Buffer.h @@ -41,6 +41,7 @@ namespace MobileGL::MG_Impl::GLImpl { GLsizeiptr size); void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void* data); void GetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, void* data); + void GetNamedBufferSubData(GLuint buffer, GLintptr offset, GLsizeiptr size, void* data); void BufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage); void BindBuffer(GLenum target, GLuint buffer); void GenBuffers(GLsizei n, GLuint* buffers); diff --git a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp index f8c36028..97798a54 100644 --- a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp +++ b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp @@ -1025,7 +1025,7 @@ DECLARE_GL_FUNCTION_HEAD(void, FlushMappedNamedBufferRange, GLuint buffer, GLint DECLARE_GL_FUNCTION_HEAD(void, GetNamedBufferParameteriv, GLuint buffer, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetNamedBufferParameteriv, buffer, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetNamedBufferParameteri64v, GLuint buffer, GLenum pname, GLint64* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetNamedBufferParameteri64v, buffer, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetNamedBufferPointerv, GLuint buffer, GLenum pname, void** params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetNamedBufferPointerv, buffer, pname, params) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetNamedBufferSubData, GLuint buffer, GLintptr offset, GLsizeiptr size, void* data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetNamedBufferSubData, buffer, offset, size, data) +DECLARE_GL_FUNCTION_HEAD(void, GetNamedBufferSubData, GLuint buffer, GLintptr offset, GLsizeiptr size, void* data) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetNamedBufferSubData, buffer, offset, size, data) DECLARE_GL_FUNCTION_HEAD(void, CreateFramebuffers, GLsizei n, GLuint* framebuffers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CreateFramebuffers, n, framebuffers) DECLARE_GL_FUNCTION_HEAD(void, NamedFramebufferRenderbuffer, GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) DECLARE_GL_FUNCTION_END_NO_RETURN(void, NamedFramebufferRenderbuffer, framebuffer, attachment, renderbuffertarget, renderbuffer) DECLARE_GL_FUNCTION_STUB_HEAD(void, NamedFramebufferParameteri, GLuint framebuffer, GLenum pname, GLint param) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, NamedFramebufferParameteri, framebuffer, pname, param)