diff --git a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp index df6f5c9f..4e111de5 100644 --- a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp +++ b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp @@ -1092,9 +1092,9 @@ DECLARE_GL_FUNCTION_HEAD(void, VertexArrayAttribFormat, GLuint vaobj, GLuint att DECLARE_GL_FUNCTION_HEAD(void, VertexArrayAttribIFormat, GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexArrayAttribIFormat, vaobj, attribindex, size, type, relativeoffset) DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexArrayAttribLFormat, GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexArrayAttribLFormat, vaobj, attribindex, size, type, relativeoffset) DECLARE_GL_FUNCTION_HEAD(void, VertexArrayBindingDivisor, GLuint vaobj, GLuint bindingindex, GLuint divisor) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexArrayBindingDivisor, vaobj, bindingindex, divisor) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetVertexArrayiv, GLuint vaobj, GLenum pname, GLint* param) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetVertexArrayiv, vaobj, pname, param) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetVertexArrayIndexediv, GLuint vaobj, GLuint index, GLenum pname, GLint* param) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetVertexArrayIndexediv, vaobj, index, pname, param) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetVertexArrayIndexed64iv, GLuint vaobj, GLuint index, GLenum pname, GLint64* param) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetVertexArrayIndexed64iv, vaobj, index, pname, param) +DECLARE_GL_FUNCTION_HEAD(void, GetVertexArrayiv, GLuint vaobj, GLenum pname, GLint* param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetVertexArrayiv, vaobj, pname, param) +DECLARE_GL_FUNCTION_HEAD(void, GetVertexArrayIndexediv, GLuint vaobj, GLuint index, GLenum pname, GLint* param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetVertexArrayIndexediv, vaobj, index, pname, param) +DECLARE_GL_FUNCTION_HEAD(void, GetVertexArrayIndexed64iv, GLuint vaobj, GLuint index, GLenum pname, GLint64* param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetVertexArrayIndexed64iv, vaobj, index, pname, param) DECLARE_GL_FUNCTION_HEAD(void, CreateSamplers, GLsizei n, GLuint* samplers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CreateSamplers, n, samplers) DECLARE_GL_FUNCTION_STUB_HEAD(void, CreateProgramPipelines, GLsizei n, GLuint* pipelines) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CreateProgramPipelines, n, pipelines) DECLARE_GL_FUNCTION_HEAD(void, CreateQueries, GLenum target, GLsizei n, GLuint* ids) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CreateQueries, target, n, ids) diff --git a/MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.cpp b/MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.cpp index d7405a45..70035562 100644 --- a/MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.cpp +++ b/MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.cpp @@ -1044,6 +1044,83 @@ namespace MobileGL::MG_Impl::GLImpl { VertexArrayVertexBuffer_State(vaobj, bindingindex, buffer, offset, stride); } + // glGetVertexArrayiv reports exactly one thing (GL 4.6 core table 23.4): which buffer the + // named vertex array takes its indices from. Everything else about a vertex array is + // per-attribute and belongs to the indexed queries below. + void GetVertexArrayiv(GLuint vaobj, GLenum pname, GLint* param) { + auto vao = GetNamedVertexArrayObject_State(vaobj, __func__); + if (!vao || !param) return; + if (pname != GL_ELEMENT_ARRAY_BUFFER_BINDING) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, + MakeUnique("MG_Impl/GLImpl", __func__, + "pname must be GL_ELEMENT_ARRAY_BUFFER_BINDING.")); + return; + } + const auto& indexBuffer = vao->GetIndexBufferBindingSlot().GetBoundObject(); + *param = indexBuffer ? static_cast(indexBuffer->GetExternalIndex()) : 0; + } + + void GetVertexArrayIndexediv(GLuint vaobj, GLuint index, GLenum pname, GLint* param) { + auto vao = GetNamedVertexArrayObject_State(vaobj, __func__); + if (!vao || !param) return; + if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return; + const auto& attr = vao->GetAttribute(index); + switch (pname) { + case GL_VERTEX_ATTRIB_ARRAY_ENABLED: + *param = attr.Enabled ? GL_TRUE : GL_FALSE; + return; + case GL_VERTEX_ATTRIB_ARRAY_SIZE: + *param = static_cast(attr.Size); + return; + case GL_VERTEX_ATTRIB_ARRAY_STRIDE: + *param = static_cast(attr.Stride); + return; + case GL_VERTEX_ATTRIB_ARRAY_TYPE: + *param = static_cast(MG_Util::ConvertDataTypeToGLEnum(attr.Type)); + return; + case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: + *param = attr.Normalized ? GL_TRUE : GL_FALSE; + return; + case GL_VERTEX_ATTRIB_ARRAY_INTEGER: + *param = attr.IsInteger ? GL_TRUE : GL_FALSE; + return; + case GL_VERTEX_ATTRIB_ARRAY_LONG: + // 64-bit attributes are not supported, so no attribute is ever a long one. + *param = GL_FALSE; + return; + case GL_VERTEX_ATTRIB_ARRAY_DIVISOR: + *param = static_cast(attr.Divisor); + return; + case GL_VERTEX_ATTRIB_RELATIVE_OFFSET: + *param = static_cast(vao->GetAttributeRelativeOffset(index)); + return; + default: + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, + MakeUnique("MG_Impl/GLImpl", __func__, + "pname is not an accepted indexed vertex array query.")); + return; + } + } + + // Only GL_VERTEX_BINDING_OFFSET needs 64 bits. Its `index` names a vertex buffer binding + // point directly (GL 4.6 core 10.3.1), not an attribute - unlike every pname the 32-bit + // indexed query above accepts, which is why this one does not go through an attribute's + // binding index. + void GetVertexArrayIndexed64iv(GLuint vaobj, GLuint index, GLenum pname, GLint64* param) { + auto vao = GetNamedVertexArrayObject_State(vaobj, __func__); + if (!vao || !param) return; + if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return; + if (pname != GL_VERTEX_BINDING_OFFSET) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, + MakeUnique("MG_Impl/GLImpl", __func__, "pname must be GL_VERTEX_BINDING_OFFSET.")); + return; + } + *param = static_cast(vao->GetBindingPoint(index).Offset); + } + void VertexArrayAttribFormat(GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) { VertexArrayAttribFormat_State(vaobj, attribindex, size, type, normalized, relativeoffset); diff --git a/MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.h b/MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.h index 14fbb4dd..55376749 100644 --- a/MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.h +++ b/MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.h @@ -92,6 +92,9 @@ namespace MobileGL::MG_Impl::GLImpl { void EnableVertexArrayAttrib(GLuint vaobj, GLuint index); void VertexArrayElementBuffer(GLuint vaobj, GLuint buffer); void VertexArrayVertexBuffer(GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); + void GetVertexArrayiv(GLuint vaobj, GLenum pname, GLint* param); + void GetVertexArrayIndexediv(GLuint vaobj, GLuint index, GLenum pname, GLint* param); + void GetVertexArrayIndexed64iv(GLuint vaobj, GLuint index, GLenum pname, GLint64* param); void VertexArrayAttribFormat(GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); void VertexArrayAttribIFormat(GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); diff --git a/MobileGL/MG_State/GLState/VertexArrayState/VertexArrayObject.h b/MobileGL/MG_State/GLState/VertexArrayState/VertexArrayObject.h index 6d945103..15c8c03f 100644 --- a/MobileGL/MG_State/GLState/VertexArrayState/VertexArrayObject.h +++ b/MobileGL/MG_State/GLState/VertexArrayState/VertexArrayObject.h @@ -84,6 +84,21 @@ namespace MobileGL { void SetAttributeFormatSeparate(Uint attribIndex, int size, DataType type, Bool normalized, Bool isInteger, Uint relativeOffset); + // The binding-point view the attributes were resolved from. Kept queryable + // because glGetVertexArrayIndexed[64]iv reports it verbatim, and the resolved + // flat attribute cannot always be inverted back into it. + Uint GetAttributeRelativeOffset(Uint attribIndex) const { + return attribIndex < m_attributeRelativeOffset.size() ? m_attributeRelativeOffset[attribIndex] : 0; + } + Uint GetAttributeBindingIndex(Uint attribIndex) const { + return attribIndex < m_attributeBindingIndex.size() ? m_attributeBindingIndex[attribIndex] + : attribIndex; + } + const VertexBufferBindingPoint& GetBindingPoint(Uint bindingIndex) const { + static const VertexBufferBindingPoint kEmpty{}; + return bindingIndex < m_bindingPoints.size() ? m_bindingPoints[bindingIndex] : kEmpty; + } + const VertexAttributeVersion& GetAttributeVersion(Uint index) const; const Array& GetAllAttributeVersions() const;