From 49630d43d4f5f8f1d0e74f9fc2b1b78a2a9764a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 24 Feb 2021 11:15:36 +0100 Subject: [PATCH] GL: add a type trait for checking if a type is an extension. Similar to what Vulkan has. Will be used mainly for guarding implicit conversion to the Extension class. --- src/Magnum/GL/Context.h | 29 +++++++++++++------ src/Magnum/GL/Test/ContextTest.cpp | 45 +++++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/src/Magnum/GL/Context.h b/src/Magnum/GL/Context.h index 54c2e7f5e..45bb43794 100644 --- a/src/Magnum/GL/Context.h +++ b/src/Magnum/GL/Context.h @@ -57,6 +57,14 @@ namespace GL { namespace Implementation { struct ContextState; struct State; + + template class IsExtension; + template<> class IsExtension<> { public: enum: bool { value = true }; }; + CORRADE_HAS_TYPE(IsExtension, decltype(T::Index)); + template class IsExtension { + /** @todo C++17: use &&... instead of all this */ + public: enum: bool { value = IsExtension::value && IsExtension::value }; + }; } /** @@ -650,8 +658,8 @@ class MAGNUM_GL_EXPORT Context { * @ref MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(), * @ref isExtensionDisabled() */ - template bool isExtensionSupported() const { - return isExtensionSupported(version()); + template bool isExtensionSupported() const { + return isExtensionSupported(version()); } /** @@ -664,8 +672,9 @@ class MAGNUM_GL_EXPORT Context { * * @snippet MagnumGL.cpp Context-isExtensionSupported-version */ - template bool isExtensionSupported(Version version) const { - return _extensionRequiredVersion[T::Index] <= version && _extensionStatus[T::Index]; + template bool isExtensionSupported(Version version) const { + static_assert(Implementation::IsExtension::value, "expected an OpenGL extension"); + return _extensionRequiredVersion[E::Index] <= version && _extensionStatus[E::Index]; } /** @@ -688,8 +697,8 @@ class MAGNUM_GL_EXPORT Context { * extensions return `false` in @ref isExtensionSupported() even if * they are advertised as being supported by the driver. */ - template bool isExtensionDisabled() const { - return isExtensionDisabled(version()); + template bool isExtensionDisabled() const { + return isExtensionDisabled(version()); } /** @@ -698,9 +707,11 @@ class MAGNUM_GL_EXPORT Context { * Similar to above, but can also check for extensions which are * disabled only for particular versions. */ - template bool isExtensionDisabled(Version version) const { - /* The extension is advertised, but the minimal version has been increased */ - return T::requiredVersion() <= version && _extensionRequiredVersion[T::Index] > version; + template bool isExtensionDisabled(Version version) const { + static_assert(Implementation::IsExtension::value, "expected an OpenGL extension"); + /* The extension is advertised, but the minimal version has been + increased */ + return E::requiredVersion() <= version && _extensionRequiredVersion[E::Index] > version; } /** diff --git a/src/Magnum/GL/Test/ContextTest.cpp b/src/Magnum/GL/Test/ContextTest.cpp index 12e626180..c393e1048 100644 --- a/src/Magnum/GL/Test/ContextTest.cpp +++ b/src/Magnum/GL/Test/ContextTest.cpp @@ -37,6 +37,8 @@ namespace Magnum { namespace GL { namespace Test { namespace { struct ContextTest: TestSuite::Tester { explicit ContextTest(); + void isExtension(); + void constructNoCreate(); void constructCopyMove(); @@ -52,7 +54,9 @@ struct ContextTest: TestSuite::Tester { }; ContextTest::ContextTest() { - addTests({&ContextTest::constructNoCreate, + addTests({&ContextTest::isExtension, + + &ContextTest::constructNoCreate, &ContextTest::constructCopyMove, &ContextTest::makeCurrentNoOp, @@ -66,6 +70,45 @@ ContextTest::ContextTest() { &ContextTest::debugDetectedDrivers}); } +void ContextTest::isExtension() { + CORRADE_VERIFY(Implementation::IsExtension::value); + CORRADE_VERIFY(!Implementation::IsExtension::value); + CORRADE_VERIFY(!Implementation::IsExtension::value); + + { + /* Not really a problem right now, but once people hit this we might + want to guard against this (especially because the Index might be + out of bounds) */ + struct ALExtension { + enum: std::size_t { Index }; + }; + CORRADE_EXPECT_FAIL("AL/Vk extensions are not rejected right now."); + CORRADE_VERIFY(!Implementation::IsExtension::value); + } + + /* Variadic check (used in variadic addEnabledExtensions()), check that it + properly fails for each occurence of a non-extension */ + CORRADE_VERIFY((Implementation::IsExtension< + Extensions::KHR::debug, + Extensions::EXT::texture_filter_anisotropic, + Extensions::KHR::texture_compression_astc_hdr>::value)); + CORRADE_VERIFY(!(Implementation::IsExtension< + Extension, + Extensions::KHR::debug, + Extensions::EXT::texture_filter_anisotropic>::value)); + CORRADE_VERIFY(!(Implementation::IsExtension< + Extensions::KHR::debug, + Extension, + Extensions::EXT::texture_filter_anisotropic>::value)); + CORRADE_VERIFY(!(Implementation::IsExtension< + Extensions::KHR::debug, + Extensions::EXT::texture_filter_anisotropic, + Extension>::value)); + + /* Empty variadic list should return true */ + CORRADE_VERIFY(Implementation::IsExtension<>::value); +} + void ContextTest::constructNoCreate() { { /* Shouldn't crash during construction, shouldn't attempt to access GL,