diff options
Diffstat (limited to 'src/mbgl/gl')
-rw-r--r-- | src/mbgl/gl/context.cpp | 71 | ||||
-rw-r--r-- | src/mbgl/gl/context.hpp | 5 | ||||
-rw-r--r-- | src/mbgl/gl/texture.hpp | 1 | ||||
-rw-r--r-- | src/mbgl/gl/texture_filter_anisotropic_extension.hpp | 34 | ||||
-rw-r--r-- | src/mbgl/gl/types.hpp | 38 |
5 files changed, 133 insertions, 16 deletions
diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index 565fe33771..749098bb35 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -4,6 +4,7 @@ #include <mbgl/gl/debugging_extension.hpp> #include <mbgl/gl/vertex_array_extension.hpp> #include <mbgl/gl/program_binary_extension.hpp> +#include <mbgl/gl/texture_filter_anisotropic_extension.hpp> #include <mbgl/util/traits.hpp> #include <mbgl/util/std.hpp> #include <mbgl/util/logging.hpp> @@ -38,6 +39,42 @@ static_assert(underlying_type(TextureFormat::Alpha) == GL_ALPHA, "OpenGL type mi static_assert(std::is_same<BinaryProgramFormat, GLenum>::value, "OpenGL type mismatch"); +struct ExtensionLoader { +public: + ExtensionLoader(const std::function<ProcAddress(const char*)>& getProcAddress_) + : getProcAddress(getProcAddress_), + extensions(reinterpret_cast<const char*>(MBGL_CHECK_ERROR(glGetString(GL_EXTENSIONS)))) { + } + + operator bool() const { + return getProcAddress && extensions; + } + + ProcAddress operator()(std::initializer_list<std::pair<const char*, const char*>> probes) const { + for (auto probe : probes) { + if (strstr(extensions, probe.first) != nullptr) { + if (ProcAddress ptr = getProcAddress(probe.second)) { + return ptr; + } + } + } + return nullptr; + } + + bool operator()(std::initializer_list<const char*> probes) const { + for (auto probe : probes) { + if (strstr(extensions, probe) != nullptr) { + return true; + } + } + return false; + } + +private: + const std::function<ProcAddress(const char*)>& getProcAddress; + const char* extensions; +}; + Context::Context() = default; Context::~Context() { @@ -45,21 +82,7 @@ Context::~Context() { } void Context::initializeExtensions(const std::function<gl::ProcAddress(const char*)>& getProcAddress) { - if (const char* extensions = - reinterpret_cast<const char*>(MBGL_CHECK_ERROR(glGetString(GL_EXTENSIONS)))) { - - auto fn = [&]( - std::initializer_list<std::pair<const char*, const char*>> probes) -> ProcAddress { - for (auto probe : probes) { - if (strstr(extensions, probe.first) != nullptr) { - if (ProcAddress ptr = getProcAddress(probe.second)) { - return ptr; - } - } - } - return nullptr; - }; - + if (ExtensionLoader fn{ getProcAddress }) { debugging = std::make_unique<extension::Debugging>(fn); if (!disableVAOExtension) { vertexArray = std::make_unique<extension::VertexArray>(fn); @@ -67,6 +90,7 @@ void Context::initializeExtensions(const std::function<gl::ProcAddress(const cha #if MBGL_HAS_BINARY_PROGRAMS programBinary = std::make_unique<extension::ProgramBinary>(fn); #endif + textureFilterAnisotropic = std::make_unique<extension::TextureFilterAnisotropic>(fn); if (!supportsVertexArrays()) { Log::Warning(Event::OpenGL, "Not using Vertex Array Objects"); @@ -229,6 +253,10 @@ optional<std::pair<BinaryProgramFormat, std::string>> Context::getBinaryProgram( } #endif +bool Context::supportsAnisotropicTextureFiltering() const { + return textureFilterAnisotropic && textureFilterAnisotropic->available; +} + UniqueVertexArray Context::createVertexArray() { assert(supportsVertexArrays()); VertexArrayID id = 0; @@ -410,9 +438,11 @@ void Context::bindTexture(Texture& obj, TextureUnit unit, TextureFilter filter, TextureMipMap mipmap, + TextureAnisotropic anisotropic, TextureWrap wrapX, TextureWrap wrapY) { - if (filter != obj.filter || mipmap != obj.mipmap || wrapX != obj.wrapX || wrapY != obj.wrapY) { + if (filter != obj.filter || mipmap != obj.mipmap || obj.anisotropic != anisotropic || + wrapX != obj.wrapX || wrapY != obj.wrapY) { activeTexture = unit; texture[unit] = obj.texture; @@ -428,6 +458,15 @@ void Context::bindTexture(Texture& obj, obj.filter = filter; obj.mipmap = mipmap; } + if (anisotropic != obj.anisotropic) { + if (supportsAnisotropicTextureFiltering()) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, + *(anisotropic == TextureAnisotropic::Max + ? textureFilterAnisotropic->maximum + : anisotropic)); + } + obj.anisotropic = anisotropic; + } if (wrapX != obj.wrapX) { MBGL_CHECK_ERROR( diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index 14af299baa..20821f530f 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -36,6 +36,7 @@ namespace extension { class VertexArray; class Debugging; class ProgramBinary; +class TextureFilterAnisotropic; } // namespace extension class Context : private util::noncopyable { @@ -64,6 +65,8 @@ public: #endif optional<std::pair<BinaryProgramFormat, std::string>> getBinaryProgram(ProgramID) const; + bool supportsAnisotropicTextureFiltering() const; + template <class Vertex, class DrawMode> VertexBuffer<Vertex, DrawMode> createVertexBuffer(VertexVector<Vertex, DrawMode>&& v) { return VertexBuffer<Vertex, DrawMode> { @@ -135,6 +138,7 @@ public: TextureUnit = 0, TextureFilter = TextureFilter::Nearest, TextureMipMap = TextureMipMap::No, + TextureAnisotropic = TextureAnisotropic::Default, TextureWrap wrapX = TextureWrap::Clamp, TextureWrap wrapY = TextureWrap::Clamp); @@ -190,6 +194,7 @@ private: #if MBGL_HAS_BINARY_PROGRAMS std::unique_ptr<extension::ProgramBinary> programBinary; #endif + std::unique_ptr<extension::TextureFilterAnisotropic> textureFilterAnisotropic; public: State<value::ActiveTexture> activeTexture; diff --git a/src/mbgl/gl/texture.hpp b/src/mbgl/gl/texture.hpp index 5330689ac2..7757b919da 100644 --- a/src/mbgl/gl/texture.hpp +++ b/src/mbgl/gl/texture.hpp @@ -12,6 +12,7 @@ public: UniqueTexture texture; TextureFilter filter = TextureFilter::Nearest; TextureMipMap mipmap = TextureMipMap::No; + TextureAnisotropic anisotropic = TextureAnisotropic::Default; TextureWrap wrapX = TextureWrap::Clamp; TextureWrap wrapY = TextureWrap::Clamp; }; diff --git a/src/mbgl/gl/texture_filter_anisotropic_extension.hpp b/src/mbgl/gl/texture_filter_anisotropic_extension.hpp new file mode 100644 index 0000000000..041820ecaa --- /dev/null +++ b/src/mbgl/gl/texture_filter_anisotropic_extension.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include <mbgl/gl/features.hpp> +#include <mbgl/gl/extension.hpp> +#include <mbgl/gl/gl.hpp> + +#define GL_TEXTURE_MAX_ANISOTROPY 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY 0x84FF + +namespace mbgl { +namespace gl { +namespace extension { + +class TextureFilterAnisotropic { +public: + template <typename Fn> + TextureFilterAnisotropic(const Fn& loadExtension) + : available(loadExtension({ "GL_EXT_texture_filter_anisotropic" })), + maximum([this] { + float value = 1.0f; + if (available) { + MBGL_CHECK_ERROR(glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY, &value)); + } + return value; + }()) { + } + + const bool available; + const TextureAnisotropic maximum; +}; + +} // namespace extension +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/types.hpp b/src/mbgl/gl/types.hpp index 7d436693c9..7ea41ef1ed 100644 --- a/src/mbgl/gl/types.hpp +++ b/src/mbgl/gl/types.hpp @@ -41,6 +41,44 @@ enum class RenderbufferType : uint32_t { enum class TextureMipMap : bool { No = false, Yes = true }; enum class TextureFilter : bool { Nearest = false, Linear = true }; + +class TextureAnisotropic { +public: + using Type = float; + static constexpr const Type Default = 1.0f; + // Values below 1.0 are not allowed, so we treat all values below 1.0 as the + // implementation-defined maximum. + static constexpr const Type Max = 0.0f; + + TextureAnisotropic(float v) { + operator=(v); + } + + float operator*() const { + return value; + } + + bool operator==(const TextureAnisotropic& rhs) const { + return value == rhs.value; + } + + bool operator!=(const TextureAnisotropic& rhs) const { + return value != rhs.value; + } + + TextureAnisotropic& operator=(float v) { + if (v < Default) { + value = Max; + } else { + value = v; + } + return *this; + } + +private: + Type value = Default; +}; + enum class TextureWrap : bool { Clamp, Repeat }; enum class TextureFormat : uint32_t { RGBA = 0x1908, |