mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[Fix] (GL): raise INVALID_OPERATION from glTextureParameter* for sampler state on a multisample texture
This commit is contained in:
@@ -100,6 +100,26 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
return true;
|
||||
}
|
||||
|
||||
// GL 4.6 core 8.10 gives the multisample-target sampler-state rejection a different error
|
||||
// per entry point: glTexParameter* raises INVALID_ENUM, glTextureParameter* INVALID_OPERATION.
|
||||
// The by-name setters share the bound-target code (directly or through
|
||||
// WithTemporarilyBoundNamedTexture), so they mark the call for its duration instead of
|
||||
// threading a flag through every TexParameter*_State signature.
|
||||
thread_local Bool g_inNamedTextureParameterCall = false;
|
||||
|
||||
class ScopedNamedTextureParameterCall {
|
||||
public:
|
||||
ScopedNamedTextureParameterCall() : m_previous(g_inNamedTextureParameterCall) {
|
||||
g_inNamedTextureParameterCall = true;
|
||||
}
|
||||
~ScopedNamedTextureParameterCall() { g_inNamedTextureParameterCall = m_previous; }
|
||||
ScopedNamedTextureParameterCall(const ScopedNamedTextureParameterCall&) = delete;
|
||||
ScopedNamedTextureParameterCall& operator=(const ScopedNamedTextureParameterCall&) = delete;
|
||||
|
||||
private:
|
||||
Bool m_previous;
|
||||
};
|
||||
|
||||
Bool ValidateMaxAnisotropy(Float maxAnisotropy, const char* caller) {
|
||||
if (maxAnisotropy >= 1.0f) return true;
|
||||
|
||||
@@ -1223,12 +1243,12 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
pname == GL_TEXTURE_MAX_LOD || pname == GL_TEXTURE_LOD_BIAS || pname == GL_TEXTURE_COMPARE_MODE ||
|
||||
pname == GL_TEXTURE_COMPARE_FUNC || pname == GL_TEXTURE_BORDER_COLOR ||
|
||||
pname == GL_TEXTURE_MAX_ANISOTROPY_EXT)) {
|
||||
// GL 4.6 core 8.10: a multisample target simply does not ACCEPT these pnames, which is
|
||||
// an INVALID_ENUM - not the INVALID_OPERATION the two BASE_LEVEL gates above report.
|
||||
// Those really are operation errors (the pname is accepted, the value is not), which is
|
||||
// presumably how the wrong class got copied down here.
|
||||
// GL 4.6 core 8.10: through glTexParameter* a multisample target simply does not ACCEPT
|
||||
// these pnames, which is an INVALID_ENUM. The by-name glTextureParameter* spelling of
|
||||
// the same rejection is an INVALID_OPERATION instead (the texture object, not the enum,
|
||||
// is what is wrong there).
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidEnum,
|
||||
g_inNamedTextureParameterCall ? ErrorCode::InvalidOperation : ErrorCode::InvalidEnum,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", caller,
|
||||
"Multisample textures do not accept sampler-state pnames."));
|
||||
return false;
|
||||
@@ -6376,12 +6396,14 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
|
||||
void TextureParameteri(GLuint texture, GLenum pname, GLint param) {
|
||||
ScopedNamedTextureParameterCall namedCall;
|
||||
auto textureObject = GetTextureObjectByName(texture, __func__);
|
||||
if (!ValidateNamedTextureParameterTarget(textureObject, __func__)) return;
|
||||
TextureParameterObject_State(textureObject, pname, param, __func__);
|
||||
}
|
||||
|
||||
void TextureParameterf(GLuint texture, GLenum pname, GLfloat param) {
|
||||
ScopedNamedTextureParameterCall namedCall;
|
||||
auto textureObject = GetTextureObjectByName(texture, __func__);
|
||||
if (!ValidateNamedTextureParameterTarget(textureObject, __func__)) return;
|
||||
TextureParameterObjectf_State(textureObject, pname, param, __func__);
|
||||
@@ -6389,18 +6411,21 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
|
||||
void TextureParameterfv(GLuint texture, GLenum pname, const GLfloat* params) {
|
||||
if (!params) return;
|
||||
ScopedNamedTextureParameterCall namedCall;
|
||||
auto textureObject = GetTextureObjectByName(texture, __func__);
|
||||
WithTemporarilyBoundNamedTexture(textureObject, [&](GLenum target) { TexParameterfv_State(target, pname, params); });
|
||||
}
|
||||
|
||||
void TextureParameteriv(GLuint texture, GLenum pname, const GLint* params) {
|
||||
if (!params) return;
|
||||
ScopedNamedTextureParameterCall namedCall;
|
||||
auto textureObject = GetTextureObjectByName(texture, __func__);
|
||||
WithTemporarilyBoundNamedTexture(textureObject, [&](GLenum target) { TexParameteriv_State(target, pname, params); });
|
||||
}
|
||||
|
||||
void TextureParameterIiv(GLuint texture, GLenum pname, const GLint* params) {
|
||||
if (!params) return;
|
||||
ScopedNamedTextureParameterCall namedCall;
|
||||
auto textureObject = GetTextureObjectByName(texture, __func__);
|
||||
WithTemporarilyBoundNamedTexture(textureObject, [&](GLenum target) {
|
||||
TexParameterIiv_State(target, pname, params);
|
||||
@@ -6409,6 +6434,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
|
||||
void TextureParameterIuiv(GLuint texture, GLenum pname, const GLuint* params) {
|
||||
if (!params) return;
|
||||
ScopedNamedTextureParameterCall namedCall;
|
||||
auto textureObject = GetTextureObjectByName(texture, __func__);
|
||||
WithTemporarilyBoundNamedTexture(textureObject, [&](GLenum target) {
|
||||
TexParameterIuiv_State(target, pname, params);
|
||||
|
||||
@@ -945,6 +945,41 @@ TEST_F(TextureTest, MultisampleSamplerStateIsInvalidEnumWhileNonZeroBaseLevelIsI
|
||||
DrainPendingGlErrors();
|
||||
}
|
||||
|
||||
// The by-name spelling of the same rejection is INVALID_OPERATION (GL 4.6 core 8.10), for every
|
||||
// glTextureParameter* form - including the vector ones that re-enter the bound-target code - while the
|
||||
// bound-target spelling right after it stays INVALID_ENUM.
|
||||
TEST_F(TextureTest, NamedMultisampleSamplerStateIsInvalidOperation) {
|
||||
GLuint texture = 0;
|
||||
MG_Impl::GLImpl::CreateTextures(GL_TEXTURE_2D_MULTISAMPLE, 1, &texture);
|
||||
ASSERT_NE(texture, 0u);
|
||||
ASSERT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
|
||||
MG_Impl::GLImpl::TextureParameterf(texture, GL_TEXTURE_LOD_BIAS, 1.0f);
|
||||
ExpectSingleGlError(GL_INVALID_OPERATION);
|
||||
MG_Impl::GLImpl::TextureParameteri(texture, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
ExpectSingleGlError(GL_INVALID_OPERATION);
|
||||
const GLfloat lodBias = 1.0f;
|
||||
MG_Impl::GLImpl::TextureParameterfv(texture, GL_TEXTURE_LOD_BIAS, &lodBias);
|
||||
ExpectSingleGlError(GL_INVALID_OPERATION);
|
||||
const GLint wrap = GL_REPEAT;
|
||||
MG_Impl::GLImpl::TextureParameteriv(texture, GL_TEXTURE_WRAP_S, &wrap);
|
||||
ExpectSingleGlError(GL_INVALID_OPERATION);
|
||||
MG_Impl::GLImpl::TextureParameterIiv(texture, GL_TEXTURE_WRAP_T, &wrap);
|
||||
ExpectSingleGlError(GL_INVALID_OPERATION);
|
||||
const GLuint borderColor[4] = {0u, 0u, 0u, 0u};
|
||||
MG_Impl::GLImpl::TextureParameterIuiv(texture, GL_TEXTURE_BORDER_COLOR, borderColor);
|
||||
ExpectSingleGlError(GL_INVALID_OPERATION);
|
||||
|
||||
// The flag must not outlive the by-name call.
|
||||
MG_Impl::GLImpl::BindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
|
||||
MG_Impl::GLImpl::TexParameterf(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_LOD_BIAS, 1.0f);
|
||||
ExpectSingleGlError(GL_INVALID_ENUM);
|
||||
|
||||
MG_Impl::GLImpl::BindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
|
||||
MG_Impl::GLImpl::DeleteTextures(1, &texture);
|
||||
DrainPendingGlErrors();
|
||||
}
|
||||
|
||||
// The whole (pname x entry-point) matrix, because the sampler getters funnel three spellings through
|
||||
// one void* function and used to write a FIXED destination type per pname regardless of which
|
||||
// spelling called. That returned the other type's bit pattern: 10497 punned into a GLfloat reads
|
||||
|
||||
Reference in New Issue
Block a user