summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladimir Agafonkin <agafonkin@gmail.com>2018-02-07 17:09:12 +0200
committerVladimir Agafonkin <agafonkin@gmail.com>2018-02-07 17:09:12 +0200
commit186c04e8bd3785b4a3a28efccb9896d3209c6bb8 (patch)
tree082eb618c6261c0669a0f1f1f3714310574a94ca
parent62d2b755086db3c48f0d16155d75adfc2f8be123 (diff)
downloadqtlocation-mapboxgl-186c04e8bd3785b4a3a28efccb9896d3209c6bb8.tar.gz
use half-float texture for heatmap if possible
Co-Authored-By: Konstantin Käfer <mail@kkaefer.com>
-rw-r--r--src/mbgl/gl/context.cpp29
-rw-r--r--src/mbgl/gl/context.hpp23
-rw-r--r--src/mbgl/gl/types.hpp9
-rw-r--r--src/mbgl/renderer/layers/render_heatmap_layer.cpp8
-rw-r--r--src/mbgl/util/offscreen_texture.cpp22
-rw-r--r--src/mbgl/util/offscreen_texture.hpp6
6 files changed, 73 insertions, 24 deletions
diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp
index b6244d58c7..f810857968 100644
--- a/src/mbgl/gl/context.cpp
+++ b/src/mbgl/gl/context.cpp
@@ -60,6 +60,14 @@ static_assert(std::is_same<std::underlying_type_t<TextureFormat>, GLenum>::value
static_assert(underlying_type(TextureFormat::RGBA) == GL_RGBA, "OpenGL type mismatch");
static_assert(underlying_type(TextureFormat::Alpha) == GL_ALPHA, "OpenGL type mismatch");
+static_assert(std::is_same<std::underlying_type_t<TextureType>, GLenum>::value, "OpenGL type mismatch");
+static_assert(underlying_type(TextureType::UnsignedByte) == GL_UNSIGNED_BYTE, "OpenGL type mismatch");
+#if MBGL_USE_GLES2
+static_assert(underlying_type(TextureType::HalfFloat) == GL_HALF_FLOAT_OES, "OpenGL type mismatch");
+#else
+static_assert(underlying_type(TextureType::HalfFloat) == GL_HALF_FLOAT_ARB, "OpenGL type mismatch");
+#endif
+
static_assert(underlying_type(UniformDataType::Float) == GL_FLOAT, "OpenGL type mismatch");
static_assert(underlying_type(UniformDataType::FloatVec2) == GL_FLOAT_VEC2, "OpenGL type mismatch");
static_assert(underlying_type(UniformDataType::FloatVec3) == GL_FLOAT_VEC3, "OpenGL type mismatch");
@@ -116,6 +124,15 @@ void Context::initializeExtensions(const std::function<gl::ProcAddress(const cha
programBinary = std::make_unique<extension::ProgramBinary>(fn);
#endif
+#if MBGL_USE_GLES2
+ constexpr const char* halfFloatExtensionName = "OES_texture_half_float";
+#else
+ constexpr const char* halfFloatExtensionName = "ARB_half_float_pixel";
+#endif
+ if (strstr(extensions, halfFloatExtensionName) != nullptr) {
+ halfFloat = true;
+ }
+
if (!supportsVertexArrays()) {
Log::Warning(Event::OpenGL, "Not using Vertex Array Objects");
}
@@ -271,6 +288,10 @@ bool Context::supportsVertexArrays() const {
vertexArray->deleteVertexArrays;
}
+bool Context::supportsHalfFloatTextures() const {
+ return halfFloat;
+}
+
#if MBGL_HAS_BINARY_PROGRAMS
bool Context::supportsProgramBinaries() const {
if (!programBinary || !programBinary->programBinary || !programBinary->getProgramBinary) {
@@ -491,10 +512,10 @@ Context::createFramebuffer(const Texture& color,
}
UniqueTexture
-Context::createTexture(const Size size, const void* data, TextureFormat format, TextureUnit unit) {
+Context::createTexture(const Size size, const void* data, TextureFormat format, TextureUnit unit, TextureType type) {
auto obj = createTexture();
pixelStoreUnpack = { 1 };
- updateTexture(obj, size, data, format, unit);
+ updateTexture(obj, size, data, format, unit, type);
// We are using clamp to edge here since OpenGL ES doesn't allow GL_REPEAT on NPOT textures.
// We use those when the pixelRatio isn't a power of two, e.g. on iPhone 6 Plus.
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
@@ -505,11 +526,11 @@ Context::createTexture(const Size size, const void* data, TextureFormat format,
}
void Context::updateTexture(
- TextureID id, const Size size, const void* data, TextureFormat format, TextureUnit unit) {
+ TextureID id, const Size size, const void* data, TextureFormat format, TextureUnit unit, TextureType type) {
activeTextureUnit = unit;
texture[unit] = id;
MBGL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, static_cast<GLenum>(format), size.width,
- size.height, 0, static_cast<GLenum>(format), GL_UNSIGNED_BYTE,
+ size.height, 0, static_cast<GLenum>(format), static_cast<GLenum>(type),
data));
}
diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp
index bdf78b0f4e..9116aa7d93 100644
--- a/src/mbgl/gl/context.hpp
+++ b/src/mbgl/gl/context.hpp
@@ -53,6 +53,8 @@ public:
UniqueTexture createTexture();
VertexArray createVertexArray();
+ bool supportsHalfFloatTextures() const;
+
#if MBGL_HAS_BINARY_PROGRAMS
bool supportsProgramBinaries() const;
#else
@@ -125,15 +127,20 @@ public:
// Create a texture from an image with data.
template <typename Image>
- Texture createTexture(const Image& image, TextureUnit unit = 0) {
+ Texture createTexture(const Image& image,
+ TextureUnit unit = 0,
+ TextureType type = TextureType::UnsignedByte) {
auto format = image.channels == 4 ? TextureFormat::RGBA : TextureFormat::Alpha;
- return { image.size, createTexture(image.size, image.data.get(), format, unit) };
+ return { image.size, createTexture(image.size, image.data.get(), format, unit, type) };
}
template <typename Image>
- void updateTexture(Texture& obj, const Image& image, TextureUnit unit = 0) {
+ void updateTexture(Texture& obj,
+ const Image& image,
+ TextureUnit unit = 0,
+ TextureType type = TextureType::UnsignedByte) {
auto format = image.channels == 4 ? TextureFormat::RGBA : TextureFormat::Alpha;
- updateTexture(obj.texture.get(), image.size, image.data.get(), format, unit);
+ updateTexture(obj.texture.get(), image.size, image.data.get(), format, unit, type);
obj.size = image.size;
}
@@ -141,8 +148,9 @@ public:
Texture createTexture(const Size size,
TextureFormat format = TextureFormat::RGBA,
TextureUnit unit = 0,
+ TextureType type = TextureType::UnsignedByte,
const void* data = nullptr) {
- return { size, createTexture(size, data, format, unit) };
+ return { size, createTexture(size, data, format, unit, type) };
}
void bindTexture(Texture&,
@@ -210,6 +218,7 @@ private:
#if MBGL_HAS_BINARY_PROGRAMS
std::unique_ptr<extension::ProgramBinary> programBinary;
#endif
+ bool halfFloat = false;
public:
State<value::ActiveTextureUnit> activeTextureUnit;
@@ -260,8 +269,8 @@ private:
void updateVertexBuffer(UniqueBuffer& buffer, const void* data, std::size_t size);
UniqueBuffer createIndexBuffer(const void* data, std::size_t size, const BufferUsage usage);
void updateIndexBuffer(UniqueBuffer& buffer, const void* data, std::size_t size);
- UniqueTexture createTexture(Size size, const void* data, TextureFormat, TextureUnit);
- void updateTexture(TextureID, Size size, const void* data, TextureFormat, TextureUnit);
+ UniqueTexture createTexture(Size size, const void* data, TextureFormat, TextureUnit, TextureType);
+ void updateTexture(TextureID, Size size, const void* data, TextureFormat, TextureUnit, TextureType);
UniqueFramebuffer createFramebuffer();
UniqueRenderbuffer createRenderbuffer(RenderbufferType, Size size);
std::unique_ptr<uint8_t[]> readFramebuffer(Size, TextureFormat, bool flip);
diff --git a/src/mbgl/gl/types.hpp b/src/mbgl/gl/types.hpp
index da08195e58..376a784a0c 100644
--- a/src/mbgl/gl/types.hpp
+++ b/src/mbgl/gl/types.hpp
@@ -64,6 +64,15 @@ enum class TextureFormat : uint32_t {
#endif // MBGL_USE_GLES2
};
+enum class TextureType : uint32_t {
+ UnsignedByte = 0x1401,
+#if MBGL_USE_GLES2
+ HalfFloat = 0x8D61,
+#else
+ HalfFloat = 0x140B,
+#endif // MBGL_USE_GLES2
+};
+
enum class PrimitiveType {
Points = 0x0000,
Lines = 0x0001,
diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.cpp b/src/mbgl/renderer/layers/render_heatmap_layer.cpp
index f39c6c3efc..9daa4e0a5d 100644
--- a/src/mbgl/renderer/layers/render_heatmap_layer.cpp
+++ b/src/mbgl/renderer/layers/render_heatmap_layer.cpp
@@ -55,12 +55,16 @@ void RenderHeatmapLayer::render(PaintParameters& parameters, RenderSource*) {
const auto size = Size{viewportSize.width / 4, viewportSize.height / 4};
if (!renderTexture || renderTexture->getSize() != size) {
- renderTexture = OffscreenTexture(parameters.context, size);
+ const auto type = parameters.context.supportsHalfFloatTextures() ?
+ gl::TextureType::HalfFloat : gl::TextureType::UnsignedByte;
+
+ renderTexture = OffscreenTexture(parameters.context, size, type);
}
if (!colorRampTexture) {
const auto colorRampSize = Size{256, 1};
- colorRampTexture = parameters.context.createTexture(colorRampSize, gl::TextureFormat::RGBA, 1, colorRamp.data());
+ colorRampTexture = parameters.context.createTexture(colorRampSize, gl::TextureFormat::RGBA, 1,
+ gl::TextureType::UnsignedByte, colorRamp.data());
}
renderTexture->bind();
diff --git a/src/mbgl/util/offscreen_texture.cpp b/src/mbgl/util/offscreen_texture.cpp
index 339e74b250..03f555eae0 100644
--- a/src/mbgl/util/offscreen_texture.cpp
+++ b/src/mbgl/util/offscreen_texture.cpp
@@ -11,20 +11,21 @@ OffscreenTexture& OffscreenTexture::operator=(OffscreenTexture&&) = default;
class OffscreenTexture::Impl {
public:
- Impl(gl::Context& context_, const Size size_)
- : context(context_), size(std::move(size_)) {
+ Impl(gl::Context& context_, const Size size_, const gl::TextureType type_)
+ : context(context_), size(std::move(size_)), type(type_) {
assert(!size.isEmpty());
}
Impl(gl::Context& context_,
const Size size_,
- gl::Renderbuffer<gl::RenderbufferType::DepthComponent>& depth_)
- : context(context_), size(std::move(size_)), depth(&depth_) {
+ gl::Renderbuffer<gl::RenderbufferType::DepthComponent>& depth_,
+ const gl::TextureType type_)
+ : context(context_), size(std::move(size_)), depth(&depth_), type(type_) {
assert(!size.isEmpty());
}
void bind() {
if (!framebuffer) {
- texture = context.createTexture(size, gl::TextureFormat::RGBA);
+ texture = context.createTexture(size, gl::TextureFormat::RGBA, 0, type);
if (depth) {
framebuffer = context.createFramebuffer(*texture, *depth);
} else {
@@ -58,18 +59,21 @@ private:
optional<gl::Framebuffer> framebuffer;
optional<gl::Texture> texture;
gl::Renderbuffer<gl::RenderbufferType::DepthComponent>* depth = nullptr;
+ const gl::TextureType type;
};
OffscreenTexture::OffscreenTexture(gl::Context& context,
- const Size size)
- : impl(std::make_unique<Impl>(context, std::move(size))) {
+ const Size size,
+ const gl::TextureType type)
+ : impl(std::make_unique<Impl>(context, std::move(size), type)) {
assert(!size.isEmpty());
}
OffscreenTexture::OffscreenTexture(gl::Context& context,
const Size size,
- gl::Renderbuffer<gl::RenderbufferType::DepthComponent>& renderbuffer)
- : impl(std::make_unique<Impl>(context, std::move(size), renderbuffer)) {
+ gl::Renderbuffer<gl::RenderbufferType::DepthComponent>& renderbuffer,
+ const gl::TextureType type)
+ : impl(std::make_unique<Impl>(context, std::move(size), renderbuffer, type)) {
assert(!size.isEmpty());
}
diff --git a/src/mbgl/util/offscreen_texture.hpp b/src/mbgl/util/offscreen_texture.hpp
index 7f7e0f0338..36f24f16d3 100644
--- a/src/mbgl/util/offscreen_texture.hpp
+++ b/src/mbgl/util/offscreen_texture.hpp
@@ -12,10 +12,12 @@ class Texture;
class OffscreenTexture {
public:
OffscreenTexture(gl::Context&,
- Size size = { 256, 256 });
+ Size size = { 256, 256 },
+ gl::TextureType type = gl::TextureType::UnsignedByte);
OffscreenTexture(gl::Context&,
Size size,
- gl::Renderbuffer<gl::RenderbufferType::DepthComponent>&);
+ gl::Renderbuffer<gl::RenderbufferType::DepthComponent>&,
+ gl::TextureType type = gl::TextureType::UnsignedByte);
~OffscreenTexture();
OffscreenTexture(OffscreenTexture&&);
OffscreenTexture& operator=(OffscreenTexture&&);