summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2017-04-12 14:41:47 +0200
committerKonstantin Käfer <mail@kkaefer.com>2017-04-12 14:43:10 +0200
commitb54ba138c6759b4705a3a24f9762a51eb3512709 (patch)
tree55bb7c1cca90fd6f4ba03da3de008b4a6754cf01
parent12b6fdbe3b1caad95089150d5c3ab69af31fb725 (diff)
downloadqtlocation-mapboxgl-upstream/8688-anisotropic-filtering.tar.gz
[core] add anisotropic filtering to raster tilesupstream/8688-anisotropic-filtering
-rw-r--r--src/mbgl/geometry/line_atlas.cpp3
-rw-r--r--src/mbgl/gl/context.cpp71
-rw-r--r--src/mbgl/gl/context.hpp5
-rw-r--r--src/mbgl/gl/texture.hpp1
-rw-r--r--src/mbgl/gl/texture_filter_anisotropic_extension.hpp34
-rw-r--r--src/mbgl/gl/types.hpp38
-rw-r--r--src/mbgl/renderer/painter_raster.cpp6
7 files changed, 139 insertions, 19 deletions
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 <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,
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,