summaryrefslogtreecommitdiff
path: root/src/mbgl/geometry
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2016-09-15 17:03:13 -0700
committerJohn Firebaugh <john.firebaugh@gmail.com>2016-09-19 09:40:43 -0700
commitdc1861f6d5391707126a20dbb0272f5bd3522de8 (patch)
tree961a3612706b9466d9ff0ef278ae1206b821aa88 /src/mbgl/geometry
parent940124ff713a960d7f70071779dd37d07010fa80 (diff)
downloadqtlocation-mapboxgl-dc1861f6d5391707126a20dbb0272f5bd3522de8.tar.gz
[core] Merge GlyphStore and GlyphAtlas
Diffstat (limited to 'src/mbgl/geometry')
-rw-r--r--src/mbgl/geometry/glyph_atlas.cpp201
-rw-r--r--src/mbgl/geometry/glyph_atlas.hpp64
2 files changed, 0 insertions, 265 deletions
diff --git a/src/mbgl/geometry/glyph_atlas.cpp b/src/mbgl/geometry/glyph_atlas.cpp
deleted file mode 100644
index ff62c5b897..0000000000
--- a/src/mbgl/geometry/glyph_atlas.cpp
+++ /dev/null
@@ -1,201 +0,0 @@
-#include <mbgl/geometry/glyph_atlas.hpp>
-
-#include <mbgl/gl/gl.hpp>
-#include <mbgl/gl/object_store.hpp>
-#include <mbgl/gl/gl_config.hpp>
-#include <mbgl/platform/log.hpp>
-#include <mbgl/platform/platform.hpp>
-
-#include <cassert>
-#include <algorithm>
-
-
-namespace mbgl {
-
-GlyphAtlas::GlyphAtlas(uint16_t width_, uint16_t height_)
- : width(width_),
- height(height_),
- bin(width_, height_),
- data(std::make_unique<uint8_t[]>(width_ * height_)),
- dirty(true) {
-}
-
-GlyphAtlas::~GlyphAtlas() = default;
-
-void GlyphAtlas::addGlyphs(uintptr_t tileUID,
- const std::u32string& text,
- const FontStack& fontStack,
- const GlyphSet& glyphSet,
- GlyphPositions& face)
-{
- std::lock_guard<std::mutex> lock(mtx);
-
- const std::map<uint32_t, SDFGlyph>& sdfs = glyphSet.getSDFs();
-
- for (uint32_t chr : text)
- {
- auto sdf_it = sdfs.find(chr);
- if (sdf_it == sdfs.end()) {
- continue;
- }
-
- const SDFGlyph& sdf = sdf_it->second;
- Rect<uint16_t> rect = addGlyph(tileUID, fontStack, sdf);
- face.emplace(chr, Glyph{rect, sdf.metrics});
- }
-}
-
-Rect<uint16_t> GlyphAtlas::addGlyph(uintptr_t tileUID,
- const FontStack& fontStack,
- const SDFGlyph& glyph)
-{
- // Use constant value for now.
- const uint8_t buffer = 3;
-
- std::map<uint32_t, GlyphValue>& face = index[fontStack];
- auto it = face.find(glyph.id);
-
- // The glyph is already in this texture.
- if (it != face.end()) {
- GlyphValue& value = it->second;
- value.ids.insert(tileUID);
- return value.rect;
- }
-
- // The glyph bitmap has zero width.
- if (glyph.bitmap.empty()) {
- return Rect<uint16_t>{ 0, 0, 0, 0 };
- }
-
- uint16_t buffered_width = glyph.metrics.width + buffer * 2;
- uint16_t buffered_height = glyph.metrics.height + buffer * 2;
-
- // Add a 1px border around every image.
- const uint16_t padding = 1;
- uint16_t pack_width = buffered_width + 2 * padding;
- uint16_t pack_height = buffered_height + 2 * padding;
-
- // Increase to next number divisible by 4, but at least 1.
- // This is so we can scale down the texture coordinates and pack them
- // into 2 bytes rather than 4 bytes.
- pack_width += (4 - pack_width % 4);
- pack_height += (4 - pack_height % 4);
-
- Rect<uint16_t> rect = bin.allocate(pack_width, pack_height);
- if (rect.w == 0) {
- Log::Error(Event::OpenGL, "glyph bitmap overflow");
- return rect;
- }
-
- assert(rect.x + rect.w <= width);
- assert(rect.y + rect.h <= height);
-
- face.emplace(glyph.id, GlyphValue { rect, tileUID });
-
- // Copy the bitmap
- const uint8_t* source = reinterpret_cast<const uint8_t*>(glyph.bitmap.data());
- for (uint32_t y = 0; y < buffered_height; y++) {
- uint32_t y1 = width * (rect.y + y + padding) + rect.x + padding;
- uint32_t y2 = buffered_width * y;
- for (uint32_t x = 0; x < buffered_width; x++) {
- data[y1 + x] = source[y2 + x];
- }
- }
-
- dirty = true;
-
- return rect;
-}
-
-void GlyphAtlas::removeGlyphs(uintptr_t tileUID) {
- std::lock_guard<std::mutex> lock(mtx);
-
- for (auto& faces : index) {
- std::map<uint32_t, GlyphValue>& face = faces.second;
- for (auto it = face.begin(); it != face.end(); /* we advance in the body */) {
- GlyphValue& value = it->second;
- value.ids.erase(tileUID);
-
- if (value.ids.empty()) {
- const Rect<uint16_t>& rect = value.rect;
-
- // Clear out the bitmap.
- uint8_t *target = data.get();
- for (uint32_t y = 0; y < rect.h; y++) {
- uint32_t y1 = width * (rect.y + y) + rect.x;
- for (uint32_t x = 0; x < rect.w; x++) {
- target[y1 + x] = 0;
- }
- }
-
- bin.release(rect);
-
- // Make sure to post-increment the iterator: This will return the
- // current iterator, but will go to the next position before we
- // erase the element from the map. That way, the iterator stays
- // valid.
- face.erase(it++);
- } else {
- ++it;
- }
- }
- }
-}
-
-void GlyphAtlas::upload(gl::ObjectStore& store, gl::Config& config, uint32_t unit) {
- if (dirty) {
- const bool first = !texture;
- bind(store, config, unit);
-
- std::lock_guard<std::mutex> lock(mtx);
-
- config.activeTexture = unit;
- if (first) {
- MBGL_CHECK_ERROR(glTexImage2D(
- GL_TEXTURE_2D, // GLenum target
- 0, // GLint level
- GL_ALPHA, // GLint internalformat
- width, // GLsizei width
- height, // GLsizei height
- 0, // GLint border
- GL_ALPHA, // GLenum format
- GL_UNSIGNED_BYTE, // GLenum type
- data.get() // const GLvoid* data
- ));
- } else {
- MBGL_CHECK_ERROR(glTexSubImage2D(
- GL_TEXTURE_2D, // GLenum target
- 0, // GLint level
- 0, // GLint xoffset
- 0, // GLint yoffset
- width, // GLsizei width
- height, // GLsizei height
- GL_ALPHA, // GLenum format
- GL_UNSIGNED_BYTE, // GLenum type
- data.get() // const GLvoid* data
- ));
- }
-
- dirty = false;
- }
-}
-
-void GlyphAtlas::bind(gl::ObjectStore& store, gl::Config& config, uint32_t unit) {
- if (!texture) {
- texture = store.createTexture();
- config.activeTexture = unit;
- config.texture[unit] = *texture;
-#ifndef GL_ES_VERSION_2_0
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0));
-#endif
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
- } else if (config.texture[unit] != *texture) {
- config.activeTexture = unit;
- config.texture[unit] = *texture;
- }
-}
-
-} // namespace mbgl
diff --git a/src/mbgl/geometry/glyph_atlas.hpp b/src/mbgl/geometry/glyph_atlas.hpp
deleted file mode 100644
index b9170c1caf..0000000000
--- a/src/mbgl/geometry/glyph_atlas.hpp
+++ /dev/null
@@ -1,64 +0,0 @@
-#pragma once
-
-#include <mbgl/geometry/binpack.hpp>
-#include <mbgl/text/glyph_store.hpp>
-#include <mbgl/util/noncopyable.hpp>
-#include <mbgl/util/optional.hpp>
-#include <mbgl/gl/gl.hpp>
-#include <mbgl/gl/object_store.hpp>
-
-#include <atomic>
-#include <string>
-#include <set>
-#include <unordered_map>
-#include <mutex>
-
-namespace mbgl {
-
-namespace gl {
-class Config;
-} // namespace gl
-
-class GlyphAtlas : public util::noncopyable {
-public:
- GlyphAtlas(uint16_t width, uint16_t height);
- ~GlyphAtlas();
-
- void addGlyphs(uintptr_t tileUID,
- const std::u32string& text,
- const FontStack&,
- const GlyphSet&,
- GlyphPositions&);
- void removeGlyphs(uintptr_t tileUID);
-
- // Binds the atlas texture to the GPU, and uploads data if it is out of date.
- void bind(gl::ObjectStore&, gl::Config&, uint32_t unit);
-
- // Uploads the texture to the GPU to be available when we need it. This is a lazy operation;
- // the texture is only bound when the data is out of date (=dirty).
- void upload(gl::ObjectStore&, gl::Config&, uint32_t unit);
-
- const GLsizei width;
- const GLsizei height;
-
-private:
- struct GlyphValue {
- GlyphValue(Rect<uint16_t> rect_, uintptr_t id)
- : rect(std::move(rect_)), ids({ id }) {}
- Rect<uint16_t> rect;
- std::set<uintptr_t> ids;
- };
-
- Rect<uint16_t> addGlyph(uintptr_t tileID,
- const FontStack&,
- const SDFGlyph&);
-
- std::mutex mtx;
- BinPack<uint16_t> bin;
- std::unordered_map<FontStack, std::map<uint32_t, GlyphValue>, FontStackHash> index;
- const std::unique_ptr<uint8_t[]> data;
- std::atomic<bool> dirty;
- mbgl::optional<gl::UniqueTexture> texture;
-};
-
-} // namespace mbgl