diff --git a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp index 9cd6f11a..2f11f3fc 100644 --- a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp +++ b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp @@ -362,8 +362,8 @@ DECLARE_GL_FUNCTION_HEAD(void, BindImageTexture, GLuint unit, GLuint texture, GL DECLARE_GL_FUNCTION_HEAD(void, GetBooleani_v, GLenum target, GLuint index, GLboolean* data) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetBooleani_v, target, index, data) DECLARE_GL_FUNCTION_HEAD(void, MemoryBarrier, GLbitfield barriers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, MemoryBarrier, barriers) DECLARE_GL_FUNCTION_HEAD(void, MemoryBarrierByRegion, GLbitfield barriers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, MemoryBarrierByRegion, barriers) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TexStorage2DMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexStorage2DMultisample, target, samples, internalformat, width, height, fixedsamplelocations) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetMultisamplefv, GLenum pname, GLuint index, GLfloat* val) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetMultisamplefv, pname, index, val) +DECLARE_GL_FUNCTION_HEAD(void, TexStorage2DMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexStorage2DMultisample, target, samples, internalformat, width, height, fixedsamplelocations) +DECLARE_GL_FUNCTION_HEAD(void, GetMultisamplefv, GLenum pname, GLuint index, GLfloat* val) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetMultisamplefv, pname, index, val) DECLARE_GL_FUNCTION_HEAD(void, SampleMaski, GLuint maskNumber, GLbitfield mask) DECLARE_GL_FUNCTION_END_NO_RETURN(void, SampleMaski, maskNumber, mask) DECLARE_GL_FUNCTION_HEAD(void, GetTexLevelParameteriv, GLenum target, GLint level, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTexLevelParameteriv, target, level, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetTexLevelParameterfv, GLenum target, GLint level, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTexLevelParameterfv, target, level, pname, params) @@ -419,7 +419,7 @@ DECLARE_GL_FUNCTION_HEAD(void, GetSamplerParameterIiv, GLuint sampler, GLenum pn DECLARE_GL_FUNCTION_HEAD(void, GetSamplerParameterIuiv, GLuint sampler, GLenum pname, GLuint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetSamplerParameterIuiv, sampler, pname, params) DECLARE_GL_FUNCTION_HEAD(void, TexBuffer, GLenum target, GLenum internalformat, GLuint buffer) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexBuffer, target, internalformat, buffer) DECLARE_GL_FUNCTION_STUB_HEAD(void, TexBufferRange, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexBufferRange, target, internalformat, buffer, offset, size) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TexStorage3DMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexStorage3DMultisample, target, samples, internalformat, width, height, depth, fixedsamplelocations) +DECLARE_GL_FUNCTION_HEAD(void, TexStorage3DMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexStorage3DMultisample, target, samples, internalformat, width, height, depth, fixedsamplelocations) DECLARE_GL_FUNCTION_HEAD(void*, MapBufferRange, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) DECLARE_GL_FUNCTION_END(void*, MapBufferRange, target, offset, length, access) DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearIndex, GLfloat c) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearIndex, c) DECLARE_GL_FUNCTION_STUB_HEAD(void, IndexMask, GLuint mask) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, IndexMask, mask) @@ -1030,7 +1030,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, GetNamedFramebufferParameteriv, GLuint frame DECLARE_GL_FUNCTION_HEAD(void, GetNamedFramebufferAttachmentParameteriv, GLuint framebuffer, GLenum attachment, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetNamedFramebufferAttachmentParameteriv, framebuffer, attachment, pname, params) DECLARE_GL_FUNCTION_HEAD(void, CreateRenderbuffers, GLsizei n, GLuint* renderbuffers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CreateRenderbuffers, n, renderbuffers) DECLARE_GL_FUNCTION_HEAD(void, NamedRenderbufferStorage, GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, NamedRenderbufferStorage, renderbuffer, internalformat, width, height) -DECLARE_GL_FUNCTION_STUB_HEAD(void, NamedRenderbufferStorageMultisample, GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, NamedRenderbufferStorageMultisample, renderbuffer, samples, internalformat, width, height) +DECLARE_GL_FUNCTION_HEAD(void, NamedRenderbufferStorageMultisample, GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, NamedRenderbufferStorageMultisample, renderbuffer, samples, internalformat, width, height) DECLARE_GL_FUNCTION_HEAD(void, GetNamedRenderbufferParameteriv, GLuint renderbuffer, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetNamedRenderbufferParameteriv, renderbuffer, pname, params) DECLARE_GL_FUNCTION_HEAD(void, CreateTextures, GLenum target, GLsizei n, GLuint* textures) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CreateTextures, target, n, textures) DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureBuffer, GLuint texture, GLenum internalformat, GLuint buffer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureBuffer, texture, internalformat, buffer) @@ -1038,8 +1038,8 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureBufferRange, GLuint texture, GLenum i DECLARE_GL_FUNCTION_HEAD(void, TextureStorage1D, GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage1D, texture, levels, internalformat, width) DECLARE_GL_FUNCTION_HEAD(void, TextureStorage2D, GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage2D, texture, levels, internalformat, width, height) DECLARE_GL_FUNCTION_HEAD(void, TextureStorage3D, GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage3D, texture, levels, internalformat, width, height, depth) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureStorage2DMultisample, GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureStorage2DMultisample, texture, samples, internalformat, width, height, fixedsamplelocations) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureStorage3DMultisample, GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureStorage3DMultisample, texture, samples, internalformat, width, height, depth, fixedsamplelocations) +DECLARE_GL_FUNCTION_HEAD(void, TextureStorage2DMultisample, GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage2DMultisample, texture, samples, internalformat, width, height, fixedsamplelocations) +DECLARE_GL_FUNCTION_HEAD(void, TextureStorage3DMultisample, GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage3DMultisample, texture, samples, internalformat, width, height, depth, fixedsamplelocations) DECLARE_GL_FUNCTION_HEAD(void, TextureSubImage1D, GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureSubImage1D, texture, level, xoffset, width, format, type, pixels) DECLARE_GL_FUNCTION_HEAD(void, TextureSubImage2D, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureSubImage2D, texture, level, xoffset, yoffset, width, height, format, type, pixels) DECLARE_GL_FUNCTION_HEAD(void, TextureSubImage3D, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureSubImage3D, texture, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels) @@ -1887,7 +1887,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, GetNamedProgramivEXT, GLuint program, GLenum DECLARE_GL_FUNCTION_STUB_HEAD(void, GetNamedProgramStringEXT, GLuint program, GLenum target, GLenum pname, void* string) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetNamedProgramStringEXT, program, target, pname, string) DECLARE_GL_FUNCTION_HEAD(void, NamedRenderbufferStorageEXT, GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, NamedRenderbufferStorage, renderbuffer, internalformat, width, height) DECLARE_GL_FUNCTION_HEAD(void, GetNamedRenderbufferParameterivEXT, GLuint renderbuffer, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetNamedRenderbufferParameteriv, renderbuffer, pname, params) -DECLARE_GL_FUNCTION_STUB_HEAD(void, NamedRenderbufferStorageMultisampleEXT, GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, NamedRenderbufferStorageMultisampleEXT, renderbuffer, samples, internalformat, width, height) +DECLARE_GL_FUNCTION_HEAD(void, NamedRenderbufferStorageMultisampleEXT, GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, NamedRenderbufferStorageMultisample, renderbuffer, samples, internalformat, width, height) DECLARE_GL_FUNCTION_STUB_HEAD(void, NamedRenderbufferStorageMultisampleCoverageEXT, GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, NamedRenderbufferStorageMultisampleCoverageEXT, renderbuffer, coverageSamples, colorSamples, internalformat, width, height) DECLARE_GL_FUNCTION_STUB_HEAD(GLenum, CheckNamedFramebufferStatusEXT, GLuint framebuffer, GLenum target) DECLARE_GL_FUNCTION_STUB_END(GLenum, CheckNamedFramebufferStatusEXT, framebuffer, target) DECLARE_GL_FUNCTION_STUB_HEAD(void, NamedFramebufferTexture1DEXT, GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, NamedFramebufferTexture1DEXT, framebuffer, attachment, textarget, texture, level) @@ -1952,8 +1952,8 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureBufferRangeEXT, GLuint texture, GLenu DECLARE_GL_FUNCTION_HEAD(void, TextureStorage1DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage1D, texture, levels, internalformat, width) DECLARE_GL_FUNCTION_HEAD(void, TextureStorage2DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage2D, texture, levels, internalformat, width, height) DECLARE_GL_FUNCTION_HEAD(void, TextureStorage3DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage3D, texture, levels, internalformat, width, height, depth) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureStorage2DMultisampleEXT, GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureStorage2DMultisampleEXT, texture, target, samples, internalformat, width, height, fixedsamplelocations) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureStorage3DMultisampleEXT, GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureStorage3DMultisampleEXT, texture, target, samples, internalformat, width, height, depth, fixedsamplelocations) +DECLARE_GL_FUNCTION_HEAD(void, TextureStorage2DMultisampleEXT, GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage2DMultisample, texture, samples, internalformat, width, height, fixedsamplelocations) +DECLARE_GL_FUNCTION_HEAD(void, TextureStorage3DMultisampleEXT, GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage3DMultisample, texture, samples, internalformat, width, height, depth, fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexArrayBindVertexBufferEXT, GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexArrayBindVertexBufferEXT, vaobj, bindingindex, buffer, offset, stride) DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexArrayVertexAttribFormatEXT, GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexArrayVertexAttribFormatEXT, vaobj, attribindex, size, type, normalized, relativeoffset) DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexArrayVertexAttribIFormatEXT, GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexArrayVertexAttribIFormatEXT, vaobj, attribindex, size, type, relativeoffset) @@ -2298,7 +2298,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, GetMapParameterfvNV, GLenum target, GLenum p DECLARE_GL_FUNCTION_STUB_HEAD(void, GetMapAttribParameterivNV, GLenum target, GLuint index, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetMapAttribParameterivNV, target, index, pname, params) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetMapAttribParameterfvNV, GLenum target, GLuint index, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetMapAttribParameterfvNV, target, index, pname, params) DECLARE_GL_FUNCTION_STUB_HEAD(void, EvalMapsNV, GLenum target, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, EvalMapsNV, target, mode) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetMultisamplefvNV, GLenum pname, GLuint index, GLfloat* val) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetMultisamplefvNV, pname, index, val) +DECLARE_GL_FUNCTION_HEAD(void, GetMultisamplefvNV, GLenum pname, GLuint index, GLfloat* val) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetMultisamplefv, pname, index, val) DECLARE_GL_FUNCTION_STUB_HEAD(void, SampleMaskIndexedNV, GLuint index, GLbitfield mask) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, SampleMaskIndexedNV, index, mask) DECLARE_GL_FUNCTION_STUB_HEAD(void, TexRenderbufferNV, GLenum target, GLuint renderbuffer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexRenderbufferNV, target, renderbuffer) DECLARE_GL_FUNCTION_STUB_HEAD(void, DeleteFencesNV, GLsizei n, const GLuint* fences) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DeleteFencesNV, n, fences) diff --git a/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp b/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp index 0ade8d32..13b17e0e 100644 --- a/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp +++ b/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp @@ -438,6 +438,34 @@ namespace MobileGL::MG_Impl::GLImpl { "NamedRenderbufferStorage_State"); } + void NamedRenderbufferStorageMultisample_State(GLuint renderbuffer, GLsizei samples, GLenum internalformat, + GLsizei width, GLsizei height) { + auto renderbufferObject = + GetNamedRenderbufferObject_State(renderbuffer, "NamedRenderbufferStorageMultisample_State"); + if (!renderbufferObject) return; + + TextureInternalFormat format = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat); + if (!TextureImpl::ValidateTextureInternalFormat(format)) return; + if (samples < 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", "NamedRenderbufferStorageMultisample_State", + "Sample count must be non-negative.")); + return; + } + if (width < 0 || height < 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", "NamedRenderbufferStorageMultisample_State", + "Width and height must be non-negative.")); + return; + } + + renderbufferObject->AllocateStorage({width, height}); + renderbufferObject->SetInternalFormat(format); + renderbufferObject->SetSamples(samples); + } + void GenFramebuffers_State(GLsizei n, GLuint* framebuffers) { if (n < 0) { MG_State::pGLContext->RecordError( @@ -1499,6 +1527,11 @@ namespace MobileGL::MG_Impl::GLImpl { NamedRenderbufferStorage_State(renderbuffer, internalformat, width, height); } + void NamedRenderbufferStorageMultisample(GLuint renderbuffer, GLsizei samples, GLenum internalformat, + GLsizei width, GLsizei height) { + NamedRenderbufferStorageMultisample_State(renderbuffer, samples, internalformat, width, height); + } + void GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname, GLint* params) { GetNamedRenderbufferParameteriv_State(renderbuffer, pname, params); } diff --git a/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h b/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h index 6e1e551a..f7ecb37a 100644 --- a/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h +++ b/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h @@ -26,6 +26,8 @@ namespace MobileGL::MG_Impl::GLImpl { void GenRenderbuffers(GLsizei n, GLuint* renderbuffers); void CreateRenderbuffers(GLsizei n, GLuint* renderbuffers); void NamedRenderbufferStorage(GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height); + void NamedRenderbufferStorageMultisample(GLuint renderbuffer, GLsizei samples, GLenum internalformat, + GLsizei width, GLsizei height); void GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname, GLint* params); void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); void NamedFramebufferRenderbuffer(GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, diff --git a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp index 4f31724e..613ea72a 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp +++ b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp @@ -85,6 +85,102 @@ namespace MobileGL::MG_Impl::GLImpl { MG_Util::GetInternalBytesPerPixel(textureInternalFormat, MG_Util::ConvertGLEnumToTexturePixelDataType(realType)); } + + Bool IsMultisampleTextureTarget(TextureTarget target) { + return target == TextureTarget::Texture2DMultisample || + target == TextureTarget::Texture2DMultisampleArray; + } + + Int GetMaxSupportedTextureSamples(TextureInternalFormat textureInternalFormat) { + if (MG_Backend::pActiveBackendObject == nullptr) { + return std::numeric_limits::max(); + } + + const auto& dynamicParameters = MG_Backend::pActiveBackendObject->GetDynamicParameters(); + if (MG_Util::IsDepthFormatInternalFormat(textureInternalFormat) || + MG_Util::IsStencilFormatInternalFormat(textureInternalFormat)) { + return std::max(dynamicParameters.MaxDepthTextureSamples, 1); + } + + GLenum normalizedInternalFormat = MG_Util::ConvertTextureInternalFormatToGLEnum(textureInternalFormat); + GLenum normalizedFormat = GL_RGBA; + GLenum normalizedType = GL_UNSIGNED_BYTE; + MG_Util::TextureFormatProcessor::NormalizePixelFormat( + normalizedInternalFormat, PixelFormatNormalizeOptionBit::None, &normalizedInternalFormat, + &normalizedFormat, &normalizedType); + const Bool isIntegerFormat = normalizedFormat == GL_RED_INTEGER || normalizedFormat == GL_RG_INTEGER || + normalizedFormat == GL_RGB_INTEGER || normalizedFormat == GL_RGBA_INTEGER; + return std::max(isIntegerFormat ? dynamicParameters.MaxIntegerSamples + : dynamicParameters.MaxColorTextureSamples, + 1); + } + + Bool ValidateTextureMultisampleStorage(TextureTarget textureTarget, GLsizei samples, GLsizei width, + GLsizei height, GLsizei depth, TextureInternalFormat textureInternalFormat, + const char* caller) { + if (!IsMultisampleTextureTarget(textureTarget)) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, + MakeUnique("MG_Impl/GLImpl", caller, + "Target is not a multisample texture target.")); + return false; + } + if (samples <= 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", caller, "Sample count must be positive.")); + return false; + } + if (width < 0 || height < 0 || depth < 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", caller, "Texture size must be non-negative.")); + return false; + } + if (textureTarget == TextureTarget::Texture2DMultisample && depth != 1) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", caller, + "2D multisample textures must use depth 1.")); + return false; + } + if (textureTarget == TextureTarget::Texture2DMultisampleArray && depth == 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", caller, + "2D multisample array textures must have at least one layer.")); + return false; + } + + const Int maxSamples = GetMaxSupportedTextureSamples(textureInternalFormat); + if (samples > maxSamples) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique( + "MG_Impl/GLImpl", caller, + std::format("Sample count {} exceeds the supported maximum {} for this texture format.", + samples, maxSamples))); + return false; + } + return true; + } + + void AllocateMultisampleTextureStorage(const SharedPtr& textureObject, + TextureUploadTarget textureUploadTarget, + TextureInternalFormat textureInternalFormat, GLsizei samples, + GLsizei width, GLsizei height, GLsizei depth, + GLboolean fixedsamplelocations) { + MOBILEGL_ASSERT(textureObject != nullptr, "AllocateMultisampleTextureStorage requires a texture object"); + MOBILEGL_ASSERT(textureObject->GetStorageType() == TextureStorageType::Mipmap, + "AllocateMultisampleTextureStorage requires mipmap-backed storage"); + + auto* textureMipmapObject = static_cast(textureObject.get()); + textureObject->SetInternalFormat(textureInternalFormat); + textureObject->SetSamples(samples); + textureObject->SetFixedSampleLocations(fixedsamplelocations == GL_TRUE); + textureMipmapObject->AllocateStorage(textureUploadTarget, 0, {{width, height, depth}, 0}); + textureMipmapObject->MarkStorageDirty(textureUploadTarget, 0, false); + } } // namespace const SharedPtr& GetTextureObjectByName(GLuint texture, const char* caller) { @@ -814,12 +910,84 @@ namespace MobileGL::MG_Impl::GLImpl { void TexImage3DMultisample_State(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) { - // TODO: implement + TextureUploadTarget textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); + TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); + TextureInternalFormat textureInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat); + + if (!TextureImpl::ValidateTextureTarget(textureTarget)) return; + if (!TextureImpl::ValidateTextureUploadTarget(textureUploadTarget)) return; + if (textureTarget != TextureTarget::Texture2DMultisampleArray) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, + MakeUnique("MG_Impl/GLImpl", __func__, + "Target must be GL_TEXTURE_2D_MULTISAMPLE_ARRAY or its proxy.")); + return; + } + + textureInternalFormat = MG_Util::ConvertInternalFormatToSized(textureInternalFormat, TextureInputFormat::RGBA, + TexturePixelDataType::UnsignedByte); + if (!TextureImpl::ValidateTextureInternalFormat(textureInternalFormat)) return; + if (!ValidateTextureMultisampleStorage(textureTarget, samples, width, height, depth, textureInternalFormat, + __func__)) + return; + + auto& activeUnit = MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit()); + auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget); + const Bool isProxy = TextureImpl::IsProxyTextureTarget(textureUploadTarget); + auto& textureObject = + isProxy ? TextureImpl::pProxyTextureManager->CreateOrReplaceProxyTextureObject(textureUploadTarget) + : bindingSlot.GetBoundObject(); + if (!TextureImpl::ValidateTextureObject(textureObject)) return; + if (textureObject->GetStorageType() != TextureStorageType::Mipmap) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, "Texture storage is not mipmap-backed.")); + return; + } + + AllocateMultisampleTextureStorage(textureObject, textureUploadTarget, textureInternalFormat, samples, width, + height, depth, fixedsamplelocations); } void TexImage2DMultisample_State(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) { - // TODO: implement + TextureUploadTarget textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); + TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); + TextureInternalFormat textureInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat); + + if (!TextureImpl::ValidateTextureTarget(textureTarget)) return; + if (!TextureImpl::ValidateTextureUploadTarget(textureUploadTarget)) return; + if (textureTarget != TextureTarget::Texture2DMultisample) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, + MakeUnique("MG_Impl/GLImpl", __func__, + "Target must be GL_TEXTURE_2D_MULTISAMPLE or its proxy.")); + return; + } + + textureInternalFormat = MG_Util::ConvertInternalFormatToSized(textureInternalFormat, TextureInputFormat::RGBA, + TexturePixelDataType::UnsignedByte); + if (!TextureImpl::ValidateTextureInternalFormat(textureInternalFormat)) return; + if (!ValidateTextureMultisampleStorage(textureTarget, samples, width, height, 1, textureInternalFormat, + __func__)) + return; + + auto& activeUnit = MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit()); + auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget); + const Bool isProxy = TextureImpl::IsProxyTextureTarget(textureUploadTarget); + auto& textureObject = + isProxy ? TextureImpl::pProxyTextureManager->CreateOrReplaceProxyTextureObject(textureUploadTarget) + : bindingSlot.GetBoundObject(); + if (!TextureImpl::ValidateTextureObject(textureObject)) return; + if (textureObject->GetStorageType() != TextureStorageType::Mipmap) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, "Texture storage is not mipmap-backed.")); + return; + } + + AllocateMultisampleTextureStorage(textureObject, textureUploadTarget, textureInternalFormat, samples, width, + height, 1, fixedsamplelocations); } void TexImage3D_State(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, @@ -1505,6 +1673,16 @@ namespace MobileGL::MG_Impl::GLImpl { *params = (GLint)MG_Util::ConvertTextureInternalFormatToGLEnum(textureObject->GetFormat()); } break; + case GL_TEXTURE_SAMPLES: + if (params) { + *params = textureObject->GetSamples(); + } + break; + case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS: + if (params) { + *params = textureObject->HasFixedSampleLocations() ? GL_TRUE : GL_FALSE; + } + break; case GL_TEXTURE_RED_TYPE: case GL_TEXTURE_GREEN_TYPE: case GL_TEXTURE_BLUE_TYPE: @@ -1595,6 +1773,16 @@ namespace MobileGL::MG_Impl::GLImpl { *params = (GLfloat)MG_Util::ConvertTextureInternalFormatToGLEnum(textureObject->GetFormat()); } break; + case GL_TEXTURE_SAMPLES: + if (params) { + *params = static_cast(textureObject->GetSamples()); + } + break; + case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS: + if (params) { + *params = textureObject->HasFixedSampleLocations() ? 1.0f : 0.0f; + } + break; case GL_TEXTURE_RED_TYPE: case GL_TEXTURE_GREEN_TYPE: case GL_TEXTURE_BLUE_TYPE: @@ -2157,6 +2345,22 @@ namespace MobileGL::MG_Impl::GLImpl { } } + void TextureStorage2DMultisample(GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, + GLsizei height, GLboolean fixedsamplelocations) { + auto textureObject = GetTextureObjectByName(texture, __func__); + WithTemporarilyBoundNamedTexture(textureObject, [&](GLenum target) { + TexStorage2DMultisample(target, samples, internalformat, width, height, fixedsamplelocations); + }); + } + + void TextureStorage3DMultisample(GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, + GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) { + auto textureObject = GetTextureObjectByName(texture, __func__); + WithTemporarilyBoundNamedTexture(textureObject, [&](GLenum target) { + TexStorage3DMultisample(target, samples, internalformat, width, height, depth, fixedsamplelocations); + }); + } + void TexStorage1D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width) { const auto textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); const auto textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); @@ -2200,6 +2404,16 @@ namespace MobileGL::MG_Impl::GLImpl { TextureStorage3D(textureObject->GetExternalIndex(), levels, internalformat, width, height, depth); } + void TexStorage2DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, + GLsizei height, GLboolean fixedsamplelocations) { + TexImage2DMultisample_State(target, samples, internalformat, width, height, fixedsamplelocations); + } + + void TexStorage3DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, + GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) { + TexImage3DMultisample_State(target, samples, internalformat, width, height, depth, fixedsamplelocations); + } + void TextureSubImage1D(GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels) { auto textureObject = GetTextureObjectByName(texture, __func__); @@ -2613,6 +2827,30 @@ namespace MobileGL::MG_Impl::GLImpl { } } + void GetMultisamplefv(GLenum pname, GLuint index, GLfloat* val) { + if (val == nullptr) return; + if (pname != GL_SAMPLE_POSITION) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, + MakeUnique("MG_Impl/GLImpl", __func__, "Only GL_SAMPLE_POSITION is supported.")); + return; + } + + const Int maxSamples = MG_Backend::pActiveBackendObject != nullptr + ? std::max(MG_Backend::pActiveBackendObject->GetDynamicParameters().MaxSamples, 1) + : 1; + if (static_cast(index) >= maxSamples) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", __func__, "Sample index is out of range.")); + return; + } + + // Keep sample positions deterministic even before the backend exposes vendor-specific patterns. + val[0] = 0.5f; + val[1] = 0.5f; + } + void TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels) { TexSubImage3D_State(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); diff --git a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.h b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.h index c5d214ea..febf458b 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.h +++ b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.h @@ -20,6 +20,10 @@ namespace MobileGL::MG_Impl::GLImpl { void TextureStorage2D(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); void TextureStorage3D(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + void TextureStorage2DMultisample(GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, + GLsizei height, GLboolean fixedsamplelocations); + void TextureStorage3DMultisample(GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, + GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); void TextureSubImage1D(GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels); void TextureSubImage2D(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, @@ -47,6 +51,10 @@ namespace MobileGL::MG_Impl::GLImpl { void TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); void TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + void TexStorage2DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, + GLsizei height, GLboolean fixedsamplelocations); + void TexStorage3DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, + GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); void TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels); void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, @@ -78,6 +86,7 @@ namespace MobileGL::MG_Impl::GLImpl { void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params); void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params); void GetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat* params); + void GetMultisamplefv(GLenum pname, GLuint index, GLfloat* val); void GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params); void GetCompressedTexImage(GLenum target, GLint level, void* img); void GenTextures(GLsizei n, GLuint* textures); diff --git a/MobileGL/MG_Impl/GLImpl/Texture/Validators.cpp b/MobileGL/MG_Impl/GLImpl/Texture/Validators.cpp index d6d36ef3..98e36501 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/Validators.cpp +++ b/MobileGL/MG_Impl/GLImpl/Texture/Validators.cpp @@ -230,6 +230,18 @@ namespace MobileGL::MG_Impl::GLImpl::TextureImpl { return false; } } + if (target == TextureUploadTarget::Texture2DMultisample || + target == TextureUploadTarget::ProxyTexture2DMultisample || + target == TextureUploadTarget::Texture2DMultisampleArray || + target == TextureUploadTarget::ProxyTexture2DMultisampleArray) { + if (level != 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", "ValidateTextureLevelWithUploadTarget", + "Level must be zero for multisample textures")); + return false; + } + } return true; } diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObject.cpp b/MobileGL/MG_State/GLState/TextureState/TextureObject.cpp index 076d7647..58fb9bb1 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObject.cpp +++ b/MobileGL/MG_State/GLState/TextureState/TextureObject.cpp @@ -139,6 +139,22 @@ namespace MobileGL { return m_textureParamsVersion; } + Int TextureObjectBase::GetSamples() const { + return m_samples; + } + + void TextureObjectBase::SetSamples(Int samples) { + m_samples = samples; + } + + Bool TextureObjectBase::HasFixedSampleLocations() const { + return m_fixedSampleLocations; + } + + void TextureObjectBase::SetFixedSampleLocations(Bool fixedSampleLocations) { + m_fixedSampleLocations = fixedSampleLocations; + } + Uint TextureObjectWithOneMipmap::GetMipmapLevelCount() const { return m_textureStorage.GetLevelCount(); } diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObject.h b/MobileGL/MG_State/GLState/TextureState/TextureObject.h index bdda99dc..b1947e54 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObject.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureObject.h @@ -40,6 +40,10 @@ namespace MobileGL::MG_State::GLState { virtual void SetBaseLevel(Uint baseLevel) = 0; virtual void SetMaxLevel(Uint maxLevel) = 0; virtual Uint16 GetTextureParamsVersion() const = 0; + virtual Int GetSamples() const = 0; + virtual void SetSamples(Int samples) = 0; + virtual Bool HasFixedSampleLocations() const = 0; + virtual void SetFixedSampleLocations(Bool fixedSampleLocations) = 0; protected: virtual Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const = 0; @@ -67,6 +71,10 @@ namespace MobileGL::MG_State::GLState { void SetBaseLevel(Uint baseLevel) override; void SetMaxLevel(Uint maxLevel) override; Uint16 GetTextureParamsVersion() const override; + Int GetSamples() const override; + void SetSamples(Int samples) override; + Bool HasFixedSampleLocations() const override; + void SetFixedSampleLocations(Bool fixedSampleLocations) override; protected: const Uint m_externalIndex; @@ -78,6 +86,8 @@ namespace MobileGL::MG_State::GLState { TextureSwizzleParam::Blue, TextureSwizzleParam::Alpha}; UintVec2 m_levelRange = {0, 1000}; Uint16 m_textureParamsVersion = 0; + Int m_samples = 0; + Bool m_fixedSampleLocations = true; }; class TextureObjectMipmap : public TextureObjectBase { diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObjectStubs.h b/MobileGL/MG_State/GLState/TextureState/TextureObjectStubs.h index a143c3eb..b29d6764 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObjectStubs.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureObjectStubs.h @@ -15,12 +15,11 @@ namespace MobileGL { namespace GLState { /* These texture types are not yet implemented: * TextureRectangle, - * Texture2DMultisample, * TextureBuffer, * Texture1DArray, * Texture2DArray, * TextureCubeMapArray, - * Texture2DMultisampleArray + * Texture2DMultisampleArray layered attachment behavior */ #define STUB_TEXTURE_OBJECT_CLASS_DEFINITION(className, texTarget, uploadTargets) \ class className : public TextureObjectWithOneMipmap { \ @@ -58,4 +57,4 @@ namespace MobileGL { } // namespace GLState } // namespace MG_State -} // namespace MobileGL \ No newline at end of file +} // namespace MobileGL diff --git a/MobileGL/MG_State/GLState/TextureState/TextureState.cpp b/MobileGL/MG_State/GLState/TextureState/TextureState.cpp index 439abe95..d58727e1 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureState.cpp +++ b/MobileGL/MG_State/GLState/TextureState/TextureState.cpp @@ -57,7 +57,7 @@ namespace MobileGL::MG_State::GLState { textureObject = MakeShared(index); break; - // These texture types are stubbed: + // These texture types are still stubbed: case TextureTarget::TextureRectangle: textureObject = MakeShared(index); break; diff --git a/MobileGL/MG_Test/Texture/TextureTest.cpp b/MobileGL/MG_Test/Texture/TextureTest.cpp index dc51bfd7..9ec245d7 100644 --- a/MobileGL/MG_Test/Texture/TextureTest.cpp +++ b/MobileGL/MG_Test/Texture/TextureTest.cpp @@ -123,6 +123,33 @@ TEST_F(TextureTest, BoundTexStorage2DAllocatesRedTextureForSubImageUpdates) { EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR); } +TEST_F(TextureTest, TextureStorage2DMultisampleTracksNamedObjectState) { + GLuint texture = 0; + MG_Impl::GLImpl::CreateTextures(GL_TEXTURE_2D_MULTISAMPLE, 1, &texture); + + MG_Impl::GLImpl::TextureStorage2DMultisample(texture, 4, GL_RGBA8, 8, 6, GL_TRUE); + + const auto textureObject = MG_State::pGLContext->GetTextureObject(texture); + ASSERT_NE(textureObject, nullptr); + EXPECT_EQ(textureObject->GetTarget(), TextureTarget::Texture2DMultisample); + EXPECT_EQ(textureObject->GetSamples(), 4); + EXPECT_TRUE(textureObject->HasFixedSampleLocations()); + + auto* textureMipmapObject = static_cast(textureObject.get()); + ASSERT_NE(textureMipmapObject, nullptr); + EXPECT_EQ(textureMipmapObject->GetMipmapLevelCount(), 1u); + EXPECT_EQ(textureMipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture2DMultisample, 0), IntVec3(8, 6, 1)); + EXPECT_FALSE(textureMipmapObject->IsStorageDirty(TextureUploadTarget::Texture2DMultisample, 0)); + + GLint samples = 0; + GLint fixed = 0; + MG_Impl::GLImpl::GetTextureLevelParameteriv(texture, 0, GL_TEXTURE_SAMPLES, &samples); + MG_Impl::GLImpl::GetTextureLevelParameteriv(texture, 0, GL_TEXTURE_FIXED_SAMPLE_LOCATIONS, &fixed); + EXPECT_EQ(samples, 4); + EXPECT_EQ(fixed, GL_TRUE); + EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR); +} + TEST_F(TextureTest, GetTextureImageReadsNamedObjectWithoutBinding) { GLuint texture = 0; MG_Impl::GLImpl::CreateTextures(GL_TEXTURE_2D, 1, &texture);