mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-07 19:58:32 +09:00
[Fix] (MG_Impl/Texture): support anisotropic sampler parameters
This commit is contained in:
@@ -2159,6 +2159,16 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
g_GLESFuncs.glTexParameterf(target, GL_TEXTURE_MAX_LOD, samplerParams.maxLod);
|
||||
m_cacheSamplerParameters.maxLod = samplerParams.maxLod;
|
||||
}
|
||||
if (m_cacheSamplerParameters.maxAnisotropy != samplerParams.maxAnisotropy) {
|
||||
if (g_GLESCapabilities.SupportsTextureFilterAnisotropy) {
|
||||
g_GLESFuncs.glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT,
|
||||
samplerParams.maxAnisotropy);
|
||||
}
|
||||
// Unsupported GLES backends intentionally treat anisotropy as a
|
||||
// frontend-only no-op; remember the observed value so the cache
|
||||
// remains coherent without issuing an illegal enum every sync.
|
||||
m_cacheSamplerParameters.maxAnisotropy = samplerParams.maxAnisotropy;
|
||||
}
|
||||
DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
|
||||
MGLOG_D("%s(%s:%d) ES error %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str());
|
||||
});
|
||||
@@ -3040,6 +3050,13 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
g_GLESFuncs.glSamplerParameterf(m_backendSamplerId, GL_TEXTURE_MAX_LOD, samplerParams.maxLod);
|
||||
m_cacheSamplerParameters.maxLod = samplerParams.maxLod;
|
||||
}
|
||||
if (m_cacheSamplerParameters.maxAnisotropy != samplerParams.maxAnisotropy) {
|
||||
if (g_GLESCapabilities.SupportsTextureFilterAnisotropy) {
|
||||
g_GLESFuncs.glSamplerParameterf(m_backendSamplerId, GL_TEXTURE_MAX_ANISOTROPY_EXT,
|
||||
samplerParams.maxAnisotropy);
|
||||
}
|
||||
m_cacheSamplerParameters.maxAnisotropy = samplerParams.maxAnisotropy;
|
||||
}
|
||||
#undef SYNC_SAMPLER_PARAM_IF_CHANGED
|
||||
m_isInitialized = true;
|
||||
}
|
||||
|
||||
@@ -99,6 +99,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
XXHASH_VERIFY(XXH64_update(m_hashState, &maxLod, sizeof(maxLod)));
|
||||
const auto lodBias = sampler.GetLodBias();
|
||||
XXHASH_VERIFY(XXH64_update(m_hashState, &lodBias, sizeof(lodBias)));
|
||||
// Anisotropy is currently an accepted frontend-only state on DirectVulkan.
|
||||
// Keep it out of the key so changing this no-op does not manufacture duplicate
|
||||
// VkSamplers while sampler versioning still exposes the new frontend value.
|
||||
const auto compareMode = sampler.GetCompareMode();
|
||||
XXHASH_VERIFY(XXH64_update(m_hashState, &compareMode, sizeof(compareMode)));
|
||||
const auto compareFunc = ResolveCompareFunc(sampler, texture);
|
||||
@@ -125,6 +128,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
samplerInfo.addressModeV = ToVkAddressMode(sampler.GetWrapT());
|
||||
samplerInfo.addressModeW = ToVkAddressMode(sampler.GetWrapR());
|
||||
samplerInfo.mipLodBias = sampler.GetLodBias();
|
||||
// DirectVulkan does not yet plumb samplerAnisotropy feature/limit discovery;
|
||||
// preserve the accepted frontend state without requesting an unsupported feature.
|
||||
samplerInfo.anisotropyEnable = VK_FALSE;
|
||||
samplerInfo.maxAnisotropy = 1.0f;
|
||||
samplerInfo.compareEnable = sampler.GetCompareMode() == SamplerCompareMode::CompareToTexture ? VK_TRUE : VK_FALSE;
|
||||
|
||||
@@ -14,7 +14,13 @@
|
||||
|
||||
namespace MobileGL::MG_Impl::GLImpl {
|
||||
namespace {
|
||||
Bool ValidateSamplerParameterValue(GLenum pname, const void* param, Bool isFloat, Bool isInteger) {
|
||||
Float ReadSamplerScalar(const void* param, Bool isFloat, Bool isUnsignedInteger) {
|
||||
if (isFloat) return *(const GLfloat*)param;
|
||||
if (isUnsignedInteger) return static_cast<Float>(*(const GLuint*)param);
|
||||
return static_cast<Float>(*(const GLint*)param);
|
||||
}
|
||||
|
||||
Bool ValidateSamplerParameterValue(GLenum pname, const void* param, Bool isFloat, Bool isUnsignedInteger) {
|
||||
if (param == nullptr) return false;
|
||||
|
||||
switch (pname) {
|
||||
@@ -22,6 +28,13 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
case GL_TEXTURE_MAX_LOD:
|
||||
case GL_TEXTURE_LOD_BIAS:
|
||||
return true;
|
||||
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
|
||||
if (ReadSamplerScalar(param, isFloat, isUnsignedInteger) >= 1.0f) return true;
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidValue,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "SetSamplerParam_State",
|
||||
"GL_TEXTURE_MAX_ANISOTROPY_EXT must be at least 1.0."));
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -29,14 +42,15 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
if (isFloat) {
|
||||
return SamplerImpl::ValidateSamplerFloatParam(pname, *(const GLfloat*)param);
|
||||
}
|
||||
if (isInteger) {
|
||||
if (isUnsignedInteger) {
|
||||
return SamplerImpl::ValidateSamplerIntParam(pname, static_cast<GLint>(*(const GLuint*)param));
|
||||
}
|
||||
return SamplerImpl::ValidateSamplerIntParam(pname, *(const GLint*)param);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void SetSamplerParam_State(GLuint sampler, GLenum pname, const void* param, bool isFloat, bool isInteger) {
|
||||
void SetSamplerParam_State(GLuint sampler, GLenum pname, const void* param, bool isFloat,
|
||||
bool isUnsignedInteger) {
|
||||
if (param == nullptr) return;
|
||||
if (!SamplerImpl::ValidateSamplerName(sampler)) return;
|
||||
|
||||
@@ -47,7 +61,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
auto& samplerObj = MG_State::pGLContext->GetSamplerObject(sampler);
|
||||
if (!SamplerImpl::ValidateSamplerObject(sampler)) return;
|
||||
if (!ValidateSamplerParameterValue(pname, param, isFloat, isInteger)) return;
|
||||
if (!ValidateSamplerParameterValue(pname, param, isFloat, isUnsignedInteger)) return;
|
||||
|
||||
using namespace MG_Util;
|
||||
switch (pname) {
|
||||
@@ -76,6 +90,9 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
case GL_TEXTURE_LOD_BIAS:
|
||||
samplerObj->SetLodBias(*(const GLfloat*)param);
|
||||
break;
|
||||
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
|
||||
samplerObj->SetMaxAnisotropy(ReadSamplerScalar(param, isFloat, isUnsignedInteger));
|
||||
break;
|
||||
case GL_TEXTURE_COMPARE_MODE:
|
||||
samplerObj->SetCompareMode(MG_Util::ConvertGLEnumToSamplerCompareMode(*(const GLint*)param));
|
||||
break;
|
||||
@@ -89,7 +106,8 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
}
|
||||
|
||||
void GetSamplerParam_State(GLuint sampler, GLenum pname, void* params, bool isFloat, bool isInteger) {
|
||||
void GetSamplerParam_State(GLuint sampler, GLenum pname, void* params, bool isFloat,
|
||||
bool isUnsignedInteger) {
|
||||
if (params == nullptr) return;
|
||||
if (!SamplerImpl::ValidateSamplerName(sampler)) return;
|
||||
|
||||
@@ -129,6 +147,15 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
case GL_TEXTURE_LOD_BIAS:
|
||||
*(GLfloat*)params = samplerObj->GetLodBias();
|
||||
break;
|
||||
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
|
||||
if (isFloat) {
|
||||
*(GLfloat*)params = samplerObj->GetMaxAnisotropy();
|
||||
} else if (isUnsignedInteger) {
|
||||
*(GLuint*)params = static_cast<GLuint>(samplerObj->GetMaxAnisotropy());
|
||||
} else {
|
||||
*(GLint*)params = static_cast<GLint>(samplerObj->GetMaxAnisotropy());
|
||||
}
|
||||
break;
|
||||
case GL_TEXTURE_COMPARE_MODE:
|
||||
*(GLuint*)params = MG_Util::ConvertSamplerCompareModeToGLEnum(samplerObj->GetCompareMode());
|
||||
break;
|
||||
@@ -240,7 +267,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
|
||||
void SamplerParameterIiv(GLuint sampler, GLenum pname, const GLint* param) {
|
||||
SetSamplerParam_State(sampler, pname, param, false, true);
|
||||
SetSamplerParam_State(sampler, pname, param, false, false);
|
||||
}
|
||||
|
||||
void SamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param) {
|
||||
@@ -268,7 +295,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
|
||||
void GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint* params) {
|
||||
GetSamplerParam_State(sampler, pname, params, false, true);
|
||||
GetSamplerParam_State(sampler, pname, params, false, false);
|
||||
}
|
||||
|
||||
void GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params) {
|
||||
|
||||
@@ -99,6 +99,16 @@ namespace MobileGL::MG_Impl::GLImpl::SamplerImpl {
|
||||
case GL_TEXTURE_LOD_BIAS:
|
||||
return true;
|
||||
|
||||
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
|
||||
if (!(param >= 1.0f)) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidValue,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateSamplerFloatParam",
|
||||
"GL_TEXTURE_MAX_ANISOTROPY_EXT must be at least 1.0."));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
case GL_TEXTURE_BORDER_COLOR:
|
||||
if (param < 0.0f || param > 1.0f) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
@@ -125,6 +135,16 @@ namespace MobileGL::MG_Impl::GLImpl::SamplerImpl {
|
||||
}
|
||||
return true;
|
||||
|
||||
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
|
||||
if (param < 1) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidValue,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateSamplerIntParam",
|
||||
"GL_TEXTURE_MAX_ANISOTROPY_EXT must be at least 1."));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
return ValidateSamplerParam(pname, static_cast<GLenum>(param));
|
||||
}
|
||||
|
||||
@@ -74,6 +74,16 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
return true;
|
||||
}
|
||||
|
||||
Bool ValidateMaxAnisotropy(Float maxAnisotropy, const char* caller) {
|
||||
if (maxAnisotropy >= 1.0f) return true;
|
||||
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidValue,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", caller,
|
||||
"GL_TEXTURE_MAX_ANISOTROPY_EXT must be at least 1.0."));
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Fn>
|
||||
void WithTemporarilyBoundNamedTexture(const SharedPtr<MG_State::GLState::ITextureObject>& textureObject,
|
||||
Fn&& fn) {
|
||||
@@ -466,6 +476,9 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
Bool ValidateTextureParameterForTarget(const SharedPtr<MG_State::GLState::ITextureObject>& textureObject,
|
||||
GLenum pname, GLint param, const char* caller) {
|
||||
const auto target = textureObject->GetTarget();
|
||||
if (pname == GL_TEXTURE_MAX_ANISOTROPY_EXT && !ValidateMaxAnisotropy(param, caller)) {
|
||||
return false;
|
||||
}
|
||||
if ((pname == GL_TEXTURE_BASE_LEVEL || pname == GL_TEXTURE_MAX_LEVEL) && param < 0) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidValue,
|
||||
@@ -495,7 +508,8 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
(pname == GL_TEXTURE_WRAP_S || pname == GL_TEXTURE_WRAP_T || pname == GL_TEXTURE_WRAP_R ||
|
||||
pname == GL_TEXTURE_MIN_FILTER || pname == GL_TEXTURE_MAG_FILTER || pname == GL_TEXTURE_MIN_LOD ||
|
||||
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_COMPARE_FUNC || pname == GL_TEXTURE_BORDER_COLOR ||
|
||||
pname == GL_TEXTURE_MAX_ANISOTROPY_EXT)) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", caller,
|
||||
@@ -586,6 +600,9 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
case GL_TEXTURE_LOD_BIAS:
|
||||
textureObject->GetSamplerObject()->SetLodBias((GLfloat)param);
|
||||
break;
|
||||
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
|
||||
textureObject->GetSamplerObject()->SetMaxAnisotropy(static_cast<GLfloat>(param));
|
||||
break;
|
||||
case GL_GENERATE_MIPMAP:
|
||||
g_autoGenerateMipmapByTextureId[textureObject->GetExternalIndex()] = (param != GL_FALSE);
|
||||
break;
|
||||
@@ -602,7 +619,10 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
void TextureParameterObjectf_State(const SharedPtr<MG_State::GLState::ITextureObject>& textureObject, GLenum pname,
|
||||
GLfloat param, const char* caller) {
|
||||
if (!textureObject) return;
|
||||
if (!ValidateTextureParameterForTarget(textureObject, pname, static_cast<GLint>(param), caller)) return;
|
||||
if (pname == GL_TEXTURE_MAX_ANISOTROPY_EXT && !ValidateMaxAnisotropy(param, caller)) return;
|
||||
const GLint validationParam =
|
||||
pname == GL_TEXTURE_MAX_ANISOTROPY_EXT ? 1 : static_cast<GLint>(param);
|
||||
if (!ValidateTextureParameterForTarget(textureObject, pname, validationParam, caller)) return;
|
||||
|
||||
switch (pname) {
|
||||
case GL_TEXTURE_MAG_FILTER:
|
||||
@@ -648,6 +668,9 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
case GL_TEXTURE_LOD_BIAS:
|
||||
textureObject->GetSamplerObject()->SetLodBias(param);
|
||||
break;
|
||||
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
|
||||
textureObject->GetSamplerObject()->SetMaxAnisotropy(param);
|
||||
break;
|
||||
case GL_GENERATE_MIPMAP:
|
||||
g_autoGenerateMipmapByTextureId[textureObject->GetExternalIndex()] = (param != 0.0f);
|
||||
break;
|
||||
@@ -717,6 +740,9 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
*params = (GLint)MG_Util::ConvertSamplerCompareFuncToGLEnum(
|
||||
textureObject->GetSamplerObject()->GetSamplerCompareFunc());
|
||||
break;
|
||||
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
|
||||
*params = static_cast<GLint>(textureObject->GetSamplerObject()->GetMaxAnisotropy());
|
||||
break;
|
||||
default:
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidEnum,
|
||||
@@ -1105,6 +1131,10 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
case GL_TEXTURE_LOD_BIAS:
|
||||
textureObject->GetSamplerObject()->SetLodBias(param);
|
||||
break;
|
||||
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
|
||||
if (!ValidateMaxAnisotropy(param, __func__)) return;
|
||||
textureObject->GetSamplerObject()->SetMaxAnisotropy(param);
|
||||
break;
|
||||
case GL_GENERATE_MIPMAP:
|
||||
g_autoGenerateMipmapByTextureId[textureObject->GetExternalIndex()] = (param != 0.0f);
|
||||
break;
|
||||
@@ -1912,6 +1942,11 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
textureObject->GetSamplerObject()->GetSamplerCompareFunc());
|
||||
}
|
||||
break;
|
||||
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
|
||||
if (params) {
|
||||
*params = static_cast<GLint>(textureObject->GetSamplerObject()->GetMaxAnisotropy());
|
||||
}
|
||||
break;
|
||||
case GL_IMAGE_FORMAT_COMPATIBILITY_TYPE:
|
||||
if (params) {
|
||||
*params = GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE;
|
||||
@@ -2058,6 +2093,11 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
textureObject->GetSamplerObject()->GetSamplerCompareFunc());
|
||||
}
|
||||
break;
|
||||
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
|
||||
if (params) {
|
||||
*params = textureObject->GetSamplerObject()->GetMaxAnisotropy();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MG_State::pGLContext->RecordError(ErrorCode::InvalidEnum,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexParameterfv_State",
|
||||
|
||||
@@ -78,6 +78,13 @@ namespace MobileGL {
|
||||
++m_version;
|
||||
}
|
||||
|
||||
void SamplerObject::SetMaxAnisotropy(Float maxAnisotropy) {
|
||||
if (maxAnisotropy == m_samplerParameters.maxAnisotropy) return;
|
||||
|
||||
m_samplerParameters.maxAnisotropy = maxAnisotropy;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
void SamplerObject::SetSamplerCompareFunc(SamplerCompareFunc func) {
|
||||
if (func == m_samplerParameters.compareFunc) return;
|
||||
|
||||
@@ -128,6 +135,10 @@ namespace MobileGL {
|
||||
return m_samplerParameters.lodBias;
|
||||
}
|
||||
|
||||
Float SamplerObject::GetMaxAnisotropy() const {
|
||||
return m_samplerParameters.maxAnisotropy;
|
||||
}
|
||||
|
||||
SamplerCompareMode SamplerObject::GetCompareMode() const {
|
||||
return m_samplerParameters.compareMode;
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ namespace MobileGL {
|
||||
Float minLod = -1000.0f;
|
||||
Float maxLod = 1000.0f;
|
||||
Float lodBias = 0.0f;
|
||||
Float maxAnisotropy = 1.0f;
|
||||
SamplerCompareFunc compareFunc = SamplerCompareFunc::Always;
|
||||
SamplerCompareMode compareMode = SamplerCompareMode::None;
|
||||
};
|
||||
@@ -83,6 +84,7 @@ namespace MobileGL {
|
||||
void SetMipmapMode(SamplerMipmapMode mode);
|
||||
void SetLodRange(Float minLod, Float maxLod);
|
||||
void SetLodBias(Float bias);
|
||||
void SetMaxAnisotropy(Float maxAnisotropy);
|
||||
void SetSamplerCompareFunc(SamplerCompareFunc func);
|
||||
void SetCompareMode(SamplerCompareMode mode);
|
||||
|
||||
@@ -95,6 +97,7 @@ namespace MobileGL {
|
||||
Float GetMinLod() const;
|
||||
Float GetMaxLod() const;
|
||||
Float GetLodBias() const;
|
||||
Float GetMaxAnisotropy() const;
|
||||
SamplerCompareMode GetCompareMode() const;
|
||||
SamplerCompareFunc GetSamplerCompareFunc() const;
|
||||
Uint GetExternalIndex() const;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <MG_Util/BackendLoaders/OpenGL/Loader.h>
|
||||
@@ -28,6 +29,7 @@ namespace {
|
||||
GLenum errorRaisedByDraw = GL_NO_ERROR;
|
||||
|
||||
GLenum pendingError = GL_NO_ERROR;
|
||||
std::vector<std::string> extensions;
|
||||
|
||||
GLuint nextBufferId = 1;
|
||||
GLuint nextShaderId = 1;
|
||||
@@ -86,7 +88,7 @@ namespace {
|
||||
*data = 1;
|
||||
break;
|
||||
case GL_NUM_EXTENSIONS:
|
||||
*data = 0;
|
||||
*data = static_cast<GLint>(g_fake.extensions.size());
|
||||
break;
|
||||
default:
|
||||
// Leave the caller's defaults for every other capability query.
|
||||
@@ -114,9 +116,10 @@ namespace {
|
||||
return reinterpret_cast<const GLubyte*>("");
|
||||
}
|
||||
};
|
||||
// GL_NUM_EXTENSIONS reports 0 above, so this is never reached; it exists so the
|
||||
// table stays complete if the extension loop ever runs.
|
||||
funcs.glGetStringi = [](GLenum, GLuint) -> const GLubyte* { return nullptr; };
|
||||
funcs.glGetStringi = [](GLenum name, GLuint index) -> const GLubyte* {
|
||||
if (name != GL_EXTENSIONS || index >= g_fake.extensions.size()) return nullptr;
|
||||
return reinterpret_cast<const GLubyte*>(g_fake.extensions[index].c_str());
|
||||
};
|
||||
funcs.glGetFloatv = [](GLenum pname, GLfloat* data) {
|
||||
switch (pname) {
|
||||
// Two-component range queries.
|
||||
@@ -400,3 +403,20 @@ TEST(IndirectInstanceIdProbe, FillInCapabilitiesWiresProbeResult) {
|
||||
EXPECT_FALSE(conformingCaps.IndirectDrawInstanceIdIncludesBaseInstance);
|
||||
ExpectProbeReleasedAllObjects();
|
||||
}
|
||||
|
||||
TEST(TextureAnisotropyCapabilities, ExtensionPresenceIsDetectedExactly) {
|
||||
ResetFakeDriver();
|
||||
g_fake.maxVertexSsboBlocks = 0;
|
||||
const auto funcs = MakeFakeGLESFunctions();
|
||||
|
||||
MobileGL::MG_External::GLESCapabilities absentCaps;
|
||||
ASSERT_TRUE(MobileGL::MG_Util::BackendLoader::FillInGLESCapabilities(absentCaps, funcs));
|
||||
EXPECT_FALSE(absentCaps.SupportsTextureFilterAnisotropy);
|
||||
|
||||
ResetFakeDriver();
|
||||
g_fake.maxVertexSsboBlocks = 0;
|
||||
g_fake.extensions.emplace_back("GL_EXT_texture_filter_anisotropic");
|
||||
MobileGL::MG_External::GLESCapabilities presentCaps;
|
||||
ASSERT_TRUE(MobileGL::MG_Util::BackendLoader::FillInGLESCapabilities(presentCaps, funcs));
|
||||
EXPECT_TRUE(presentCaps.SupportsTextureFilterAnisotropy);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <MG_Backend/DirectGLES/Managers.h>
|
||||
#include <MG_Impl/GLImpl/Getter/GL_Getter.h>
|
||||
#include <MG_Impl/GLImpl/RenderState/GL_RenderState.h>
|
||||
#include <MG_Impl/GLImpl/Sampler/GL_Sampler.h>
|
||||
#include <MG_Impl/GLImpl/Texture/GL_Texture.h>
|
||||
#include <MG_State/GLState/Core.h>
|
||||
#include <MG_State/GLState/TextureState/TextureObject.h>
|
||||
@@ -136,6 +137,127 @@ TEST_F(TextureTest, CreateTexturesCreatesObjectsWithoutBinding) {
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
}
|
||||
|
||||
TEST_F(TextureTest, TextureMaxAnisotropyDefaultsToOneAndRoundTripsWithoutRedundantVersionBumps) {
|
||||
GLuint texture = 0;
|
||||
MG_Impl::GLImpl::GenTextures(1, &texture);
|
||||
MG_Impl::GLImpl::BindTexture(GL_TEXTURE_2D, texture);
|
||||
ASSERT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
|
||||
const auto textureObject = MG_State::pGLContext->GetTextureObject(texture);
|
||||
ASSERT_NE(textureObject, nullptr);
|
||||
const auto& samplerObject = textureObject->GetSamplerObject();
|
||||
ASSERT_NE(samplerObject, nullptr);
|
||||
|
||||
GLfloat floatValue = 0.0f;
|
||||
MG_Impl::GLImpl::GetTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &floatValue);
|
||||
EXPECT_FLOAT_EQ(floatValue, 1.0f);
|
||||
EXPECT_FLOAT_EQ(samplerObject->GetMaxAnisotropy(), 1.0f);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
|
||||
const Uint16 initialVersion = samplerObject->GetVersion();
|
||||
MG_Impl::GLImpl::TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 4.0f);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
EXPECT_FLOAT_EQ(samplerObject->GetMaxAnisotropy(), 4.0f);
|
||||
EXPECT_EQ(samplerObject->GetVersion(), static_cast<Uint16>(initialVersion + 1));
|
||||
|
||||
GLint integerValue = 0;
|
||||
MG_Impl::GLImpl::GetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &integerValue);
|
||||
EXPECT_EQ(integerValue, 4);
|
||||
MG_Impl::GLImpl::GetTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &floatValue);
|
||||
EXPECT_FLOAT_EQ(floatValue, 4.0f);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
|
||||
const Uint16 setVersion = samplerObject->GetVersion();
|
||||
MG_Impl::GLImpl::TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 4.0f);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
EXPECT_EQ(samplerObject->GetVersion(), setVersion);
|
||||
|
||||
MG_Impl::GLImpl::TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
EXPECT_FLOAT_EQ(samplerObject->GetMaxAnisotropy(), 8.0f);
|
||||
EXPECT_EQ(samplerObject->GetVersion(), static_cast<Uint16>(setVersion + 1));
|
||||
}
|
||||
|
||||
TEST_F(TextureTest, TextureMaxAnisotropyBelowOneIsInvalidValueAndPreservesState) {
|
||||
GLuint texture = 0;
|
||||
MG_Impl::GLImpl::GenTextures(1, &texture);
|
||||
MG_Impl::GLImpl::BindTexture(GL_TEXTURE_2D, texture);
|
||||
ASSERT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
|
||||
const auto textureObject = MG_State::pGLContext->GetTextureObject(texture);
|
||||
ASSERT_NE(textureObject, nullptr);
|
||||
const auto& samplerObject = textureObject->GetSamplerObject();
|
||||
ASSERT_NE(samplerObject, nullptr);
|
||||
const Uint16 initialVersion = samplerObject->GetVersion();
|
||||
|
||||
MG_Impl::GLImpl::TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0.5f);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_INVALID_VALUE);
|
||||
EXPECT_FLOAT_EQ(samplerObject->GetMaxAnisotropy(), 1.0f);
|
||||
EXPECT_EQ(samplerObject->GetVersion(), initialVersion);
|
||||
|
||||
MG_Impl::GLImpl::TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_INVALID_VALUE);
|
||||
EXPECT_FLOAT_EQ(samplerObject->GetMaxAnisotropy(), 1.0f);
|
||||
EXPECT_EQ(samplerObject->GetVersion(), initialVersion);
|
||||
}
|
||||
|
||||
TEST_F(TextureTest, SamplerMaxAnisotropyUsesTheSameStateAndValidationSemantics) {
|
||||
GLuint sampler = 0;
|
||||
MG_Impl::GLImpl::GenSamplers(1, &sampler);
|
||||
ASSERT_NE(sampler, 0u);
|
||||
|
||||
GLfloat floatValue = 0.0f;
|
||||
MG_Impl::GLImpl::GetSamplerParameterfv(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, &floatValue);
|
||||
ASSERT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
EXPECT_FLOAT_EQ(floatValue, 1.0f);
|
||||
|
||||
const auto& samplerObject = MG_State::pGLContext->GetSamplerObject(sampler);
|
||||
ASSERT_NE(samplerObject, nullptr);
|
||||
const Uint16 initialVersion = samplerObject->GetVersion();
|
||||
|
||||
MG_Impl::GLImpl::SamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, 6.0f);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
EXPECT_FLOAT_EQ(samplerObject->GetMaxAnisotropy(), 6.0f);
|
||||
EXPECT_EQ(samplerObject->GetVersion(), static_cast<Uint16>(initialVersion + 1));
|
||||
|
||||
GLint integerValue = 0;
|
||||
MG_Impl::GLImpl::GetSamplerParameteriv(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, &integerValue);
|
||||
EXPECT_EQ(integerValue, 6);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
|
||||
const Uint16 setVersion = samplerObject->GetVersion();
|
||||
MG_Impl::GLImpl::SamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, 6.0f);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
EXPECT_EQ(samplerObject->GetVersion(), setVersion);
|
||||
|
||||
MG_Impl::GLImpl::SamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0.25f);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_INVALID_VALUE);
|
||||
EXPECT_FLOAT_EQ(samplerObject->GetMaxAnisotropy(), 6.0f);
|
||||
EXPECT_EQ(samplerObject->GetVersion(), setVersion);
|
||||
|
||||
MG_Impl::GLImpl::SamplerParameteri(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_INVALID_VALUE);
|
||||
EXPECT_FLOAT_EQ(samplerObject->GetMaxAnisotropy(), 6.0f);
|
||||
EXPECT_EQ(samplerObject->GetVersion(), setVersion);
|
||||
|
||||
const GLint signedInvalidValue = -1;
|
||||
MG_Impl::GLImpl::SamplerParameterIiv(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, &signedInvalidValue);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_INVALID_VALUE);
|
||||
EXPECT_FLOAT_EQ(samplerObject->GetMaxAnisotropy(), 6.0f);
|
||||
EXPECT_EQ(samplerObject->GetVersion(), setVersion);
|
||||
|
||||
const GLuint unsignedValue = 10;
|
||||
MG_Impl::GLImpl::SamplerParameterIuiv(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, &unsignedValue);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
EXPECT_FLOAT_EQ(samplerObject->GetMaxAnisotropy(), 10.0f);
|
||||
EXPECT_EQ(samplerObject->GetVersion(), static_cast<Uint16>(setVersion + 1));
|
||||
|
||||
GLuint queriedUnsignedValue = 0;
|
||||
MG_Impl::GLImpl::GetSamplerParameterIuiv(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, &queriedUnsignedValue);
|
||||
EXPECT_EQ(queriedUnsignedValue, unsignedValue);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
}
|
||||
|
||||
TEST_F(TextureTest, GenThenBindCreatesObjectForUnsizedPackedBgraSubImageUpload) {
|
||||
GLuint texture = 0;
|
||||
MG_Impl::GLImpl::GenTextures(1, &texture);
|
||||
|
||||
@@ -799,6 +799,9 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
if (std::strcmp(extension, "GL_EXT_texture_norm16") == 0) {
|
||||
caps.SupportsNorm16Texture = true;
|
||||
}
|
||||
if (std::strcmp(extension, "GL_EXT_texture_filter_anisotropic") == 0) {
|
||||
caps.SupportsTextureFilterAnisotropy = true;
|
||||
}
|
||||
if (std::strcmp(extension, "GL_EXT_base_instance") == 0) {
|
||||
caps.SupportsBaseInstance = true;
|
||||
}
|
||||
|
||||
@@ -1031,6 +1031,9 @@ namespace MobileGL {
|
||||
String GLESShadingLanguageVersionString;
|
||||
Bool SupportsPersistentMapping = false;
|
||||
Bool SupportsNorm16Texture = false;
|
||||
// GL_EXT_texture_filter_anisotropic is present, so sampler/texture
|
||||
// anisotropy may be forwarded without raising GL_INVALID_ENUM in GLES.
|
||||
Bool SupportsTextureFilterAnisotropy = false;
|
||||
Bool SupportsBaseInstance = false;
|
||||
// GL_EXT_disjoint_timer_query is present in the extension string.
|
||||
Bool SupportsDisjointTimerQuery = false;
|
||||
|
||||
Reference in New Issue
Block a user