From b54ba138c6759b4705a3a24f9762a51eb3512709 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Wed, 12 Apr 2017 14:41:47 +0200 Subject: [core] add anisotropic filtering to raster tiles --- src/mbgl/geometry/line_atlas.cpp | 3 +- src/mbgl/gl/context.cpp | 71 +++++++++++++++++----- src/mbgl/gl/context.hpp | 5 ++ src/mbgl/gl/texture.hpp | 1 + .../gl/texture_filter_anisotropic_extension.hpp | 34 +++++++++++ src/mbgl/gl/types.hpp | 38 ++++++++++++ src/mbgl/renderer/painter_raster.cpp | 6 +- 7 files changed, 139 insertions(+), 19 deletions(-) create mode 100644 src/mbgl/gl/texture_filter_anisotropic_extension.hpp diff --git a/src/mbgl/geometry/line_atlas.cpp b/src/mbgl/geometry/line_atlas.cpp index 71a855b943..566d488385 100644 --- a/src/mbgl/geometry/line_atlas.cpp +++ b/src/mbgl/geometry/line_atlas.cpp @@ -134,7 +134,8 @@ void LineAtlas::upload(gl::Context& context, gl::TextureUnit unit) { void LineAtlas::bind(gl::Context& context, gl::TextureUnit unit) { upload(context, unit); context.bindTexture(*texture, unit, gl::TextureFilter::Linear, gl::TextureMipMap::No, - gl::TextureWrap::Repeat, gl::TextureWrap::Clamp); + gl::TextureAnisotropic::Default, gl::TextureWrap::Repeat, + gl::TextureWrap::Clamp); } } // namespace mbgl 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 #include #include +#include #include #include #include @@ -38,6 +39,42 @@ static_assert(underlying_type(TextureFormat::Alpha) == GL_ALPHA, "OpenGL type mi static_assert(std::is_same::value, "OpenGL type mismatch"); +struct ExtensionLoader { +public: + ExtensionLoader(const std::function& getProcAddress_) + : getProcAddress(getProcAddress_), + extensions(reinterpret_cast(MBGL_CHECK_ERROR(glGetString(GL_EXTENSIONS)))) { + } + + operator bool() const { + return getProcAddress && extensions; + } + + ProcAddress operator()(std::initializer_list> 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 probes) const { + for (auto probe : probes) { + if (strstr(extensions, probe) != nullptr) { + return true; + } + } + return false; + } + +private: + const std::function& getProcAddress; + const char* extensions; +}; + Context::Context() = default; Context::~Context() { @@ -45,21 +82,7 @@ Context::~Context() { } void Context::initializeExtensions(const std::function& getProcAddress) { - if (const char* extensions = - reinterpret_cast(MBGL_CHECK_ERROR(glGetString(GL_EXTENSIONS)))) { - - auto fn = [&]( - std::initializer_list> 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(fn); if (!disableVAOExtension) { vertexArray = std::make_unique(fn); @@ -67,6 +90,7 @@ void Context::initializeExtensions(const std::function(fn); #endif + textureFilterAnisotropic = std::make_unique(fn); if (!supportsVertexArrays()) { Log::Warning(Event::OpenGL, "Not using Vertex Array Objects"); @@ -229,6 +253,10 @@ optional> 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> getBinaryProgram(ProgramID) const; + bool supportsAnisotropicTextureFiltering() const; + template VertexBuffer createVertexBuffer(VertexVector&& v) { return VertexBuffer { @@ -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 programBinary; #endif + std::unique_ptr textureFilterAnisotropic; public: State 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 +#include +#include + +#define GL_TEXTURE_MAX_ANISOTROPY 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY 0x84FF + +namespace mbgl { +namespace gl { +namespace extension { + +class TextureFilterAnisotropic { +public: + template + 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, diff --git a/src/mbgl/renderer/painter_raster.cpp b/src/mbgl/renderer/painter_raster.cpp index c216955db8..a7419bf89b 100644 --- a/src/mbgl/renderer/painter_raster.cpp +++ b/src/mbgl/renderer/painter_raster.cpp @@ -52,8 +52,10 @@ void Painter::renderRaster(PaintParameters& parameters, const RasterProgram::PaintPropertyBinders paintAttributeData(properties, 0); assert(bucket.texture); - context.bindTexture(*bucket.texture, 0, gl::TextureFilter::Linear); - context.bindTexture(*bucket.texture, 1, gl::TextureFilter::Linear); + context.bindTexture(*bucket.texture, 0, gl::TextureFilter::Linear, gl::TextureMipMap::No, + gl::TextureAnisotropic::Max); + context.bindTexture(*bucket.texture, 1, gl::TextureFilter::Linear, gl::TextureMipMap::No, + gl::TextureAnisotropic::Max); parameters.programs.raster.draw( context, -- cgit v1.2.1