diff options
Diffstat (limited to 'src/mbgl')
159 files changed, 1672 insertions, 1638 deletions
diff --git a/src/mbgl/annotation/annotation_manager.cpp b/src/mbgl/annotation/annotation_manager.cpp index 52f8b08ad3..5f5feb456a 100644 --- a/src/mbgl/annotation/annotation_manager.cpp +++ b/src/mbgl/annotation/annotation_manager.cpp @@ -48,6 +48,16 @@ AnnotationManager::addShapeAnnotations(const std::vector<ShapeAnnotation>& shape return annotationIDs; } +void AnnotationManager::updatePointAnnotation(const AnnotationID& id, const PointAnnotation& point, const uint8_t) { + auto foundAnnotation = pointAnnotations.find(id); + if (foundAnnotation != pointAnnotations.end()) { + auto updatedAnnotation = std::make_shared<PointAnnotationImpl>(id, point); + pointTree.remove(foundAnnotation->second); + pointTree.insert(updatedAnnotation); + foundAnnotation->second = updatedAnnotation; + } +} + void AnnotationManager::removeAnnotations(const AnnotationIDs& ids) { for (const auto& id : ids) { if (pointAnnotations.find(id) != pointAnnotations.end()) { diff --git a/src/mbgl/annotation/annotation_manager.hpp b/src/mbgl/annotation/annotation_manager.hpp index 163c7129c7..11860047c2 100644 --- a/src/mbgl/annotation/annotation_manager.hpp +++ b/src/mbgl/annotation/annotation_manager.hpp @@ -28,6 +28,7 @@ public: AnnotationIDs addPointAnnotations(const std::vector<PointAnnotation>&, const uint8_t maxZoom); AnnotationIDs addShapeAnnotations(const std::vector<ShapeAnnotation>&, const uint8_t maxZoom); + void updatePointAnnotation(const AnnotationID&, const PointAnnotation&, const uint8_t maxZoom); void removeAnnotations(const AnnotationIDs&); AnnotationIDs getPointAnnotationsInBounds(const LatLngBounds&) const; diff --git a/src/mbgl/annotation/annotation_tile.cpp b/src/mbgl/annotation/annotation_tile.cpp index a4590ffe30..3a038cc6eb 100644 --- a/src/mbgl/annotation/annotation_tile.cpp +++ b/src/mbgl/annotation/annotation_tile.cpp @@ -10,7 +10,7 @@ AnnotationTileFeature::AnnotationTileFeature(FeatureType type_, GeometryCollecti std::unordered_map<std::string, std::string> properties_) : type(type_), properties(std::move(properties_)), - geometries(geometries_) {} + geometries(std::move(geometries_)) {} optional<Value> AnnotationTileFeature::getValue(const std::string& key) const { auto it = properties.find(key); diff --git a/src/mbgl/annotation/annotation_tile.hpp b/src/mbgl/annotation/annotation_tile.hpp index 742a4114a8..b2d98c6a3b 100644 --- a/src/mbgl/annotation/annotation_tile.hpp +++ b/src/mbgl/annotation/annotation_tile.hpp @@ -1,7 +1,7 @@ #ifndef MBGL_ANNOTATION_TILE #define MBGL_ANNOTATION_TILE -#include <mbgl/map/geometry_tile.hpp> +#include <mbgl/tile/geometry_tile.hpp> #include <mbgl/map/tile_id.hpp> #include <map> diff --git a/src/mbgl/geometry/buffer.hpp b/src/mbgl/geometry/buffer.hpp index c7278a1036..143597ed0a 100644 --- a/src/mbgl/geometry/buffer.hpp +++ b/src/mbgl/geometry/buffer.hpp @@ -1,12 +1,13 @@ #ifndef MBGL_GEOMETRY_BUFFER #define MBGL_GEOMETRY_BUFFER -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> +#include <mbgl/gl/gl_object_store.hpp> #include <mbgl/platform/log.hpp> -#include <mbgl/util/gl_object_store.hpp> #include <mbgl/util/noncopyable.hpp> #include <mbgl/util/thread_context.hpp> +#include <memory> #include <cstdlib> #include <cassert> #include <stdexcept> @@ -23,10 +24,6 @@ class Buffer : private util::noncopyable { public: ~Buffer() { cleanup(); - if (buffer != 0) { - util::ThreadContext::getGLObjectStore()->abandonBuffer(buffer); - buffer = 0; - } } // Returns the number of elements in this buffer. This is not the number of @@ -40,12 +37,12 @@ public: } // Transfers this buffer to the GPU and binds the buffer to the GL context. - void bind() { + void bind(gl::GLObjectStore& glObjectStore) { if (buffer) { - MBGL_CHECK_ERROR(glBindBuffer(bufferType, buffer)); + MBGL_CHECK_ERROR(glBindBuffer(bufferType, getID())); } else { - MBGL_CHECK_ERROR(glGenBuffers(1, &buffer)); - MBGL_CHECK_ERROR(glBindBuffer(bufferType, buffer)); + buffer.create(glObjectStore); + MBGL_CHECK_ERROR(glBindBuffer(bufferType, getID())); if (array == nullptr) { Log::Debug(Event::OpenGL, "Buffer doesn't contain elements"); pos = 0; @@ -64,21 +61,21 @@ public: } } - inline GLuint getID() const { - return buffer; + GLuint getID() const { + return buffer.getID(); } // Uploads the buffer to the GPU to be available when we need it. - inline void upload() { + inline void upload(gl::GLObjectStore& glObjectStore) { if (!buffer) { - bind(); + bind(glObjectStore); } } protected: // increase the buffer size by at least /required/ bytes. inline void *addElement() { - if (buffer != 0) { + if (buffer) { throw std::runtime_error("Can't add elements after buffer was bound to GPU"); } if (length < pos + itemSize) { @@ -118,8 +115,8 @@ private: // Number of bytes that are valid in this buffer. size_t length = 0; - // GL buffer ID - GLuint buffer = 0; + // GL buffer object handle. + gl::BufferHolder buffer; }; } // namespace mbgl diff --git a/src/mbgl/geometry/circle_buffer.cpp b/src/mbgl/geometry/circle_buffer.cpp index f4b0cddec3..74ccfa8267 100644 --- a/src/mbgl/geometry/circle_buffer.cpp +++ b/src/mbgl/geometry/circle_buffer.cpp @@ -1,6 +1,6 @@ #include <mbgl/geometry/circle_buffer.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <climits> diff --git a/src/mbgl/geometry/collision_box_buffer.cpp b/src/mbgl/geometry/collision_box_buffer.cpp index f4f8075e10..a47267d566 100644 --- a/src/mbgl/geometry/collision_box_buffer.cpp +++ b/src/mbgl/geometry/collision_box_buffer.cpp @@ -1,5 +1,5 @@ #include <mbgl/geometry/collision_box_buffer.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <mbgl/util/math.hpp> #include <cmath> diff --git a/src/mbgl/geometry/debug_font_buffer.cpp b/src/mbgl/geometry/debug_font_buffer.cpp index e4af707660..5df67accd6 100644 --- a/src/mbgl/geometry/debug_font_buffer.cpp +++ b/src/mbgl/geometry/debug_font_buffer.cpp @@ -1,7 +1,7 @@ #include <mbgl/geometry/debug_font_buffer.hpp> #include <mbgl/geometry/debug_font_data.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <cmath> #include <cstring> diff --git a/src/mbgl/geometry/fill_buffer.cpp b/src/mbgl/geometry/fill_buffer.cpp index 3392699431..ee70dfc53b 100644 --- a/src/mbgl/geometry/fill_buffer.cpp +++ b/src/mbgl/geometry/fill_buffer.cpp @@ -1,6 +1,6 @@ #include <mbgl/geometry/fill_buffer.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <climits> diff --git a/src/mbgl/geometry/glyph_atlas.cpp b/src/mbgl/geometry/glyph_atlas.cpp index b90444e582..24c1b8c8db 100644 --- a/src/mbgl/geometry/glyph_atlas.cpp +++ b/src/mbgl/geometry/glyph_atlas.cpp @@ -2,10 +2,10 @@ #include <mbgl/text/font_stack.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> +#include <mbgl/gl/gl_object_store.hpp> #include <mbgl/platform/log.hpp> #include <mbgl/platform/platform.hpp> -#include <mbgl/util/gl_object_store.hpp> #include <mbgl/util/thread_context.hpp> #include <cassert> @@ -24,11 +24,6 @@ GlyphAtlas::GlyphAtlas(uint16_t width_, uint16_t height_) GlyphAtlas::~GlyphAtlas() { assert(util::ThreadContext::currentlyOn(util::ThreadType::Map)); - - if (texture) { - mbgl::util::ThreadContext::getGLObjectStore()->abandonTexture(texture); - texture = 0; - } } void GlyphAtlas::addGlyphs(uintptr_t tileUID, @@ -151,10 +146,10 @@ void GlyphAtlas::removeGlyphs(uintptr_t tileUID) { } } -void GlyphAtlas::upload() { +void GlyphAtlas::upload(gl::GLObjectStore& glObjectStore) { if (dirty) { const bool first = !texture; - bind(); + bind(glObjectStore); std::lock_guard<std::mutex> lock(mtx); @@ -192,10 +187,10 @@ void GlyphAtlas::upload() { } } -void GlyphAtlas::bind() { +void GlyphAtlas::bind(gl::GLObjectStore& glObjectStore) { if (!texture) { - MBGL_CHECK_ERROR(glGenTextures(1, &texture)); - MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture)); + texture.create(glObjectStore); + MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture.getID())); #ifndef GL_ES_VERSION_2_0 MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0)); #endif @@ -204,6 +199,6 @@ void GlyphAtlas::bind() { 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 { - MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture)); + MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture.getID())); } }; diff --git a/src/mbgl/geometry/glyph_atlas.hpp b/src/mbgl/geometry/glyph_atlas.hpp index 5b4ae1fc6b..2758ac7cee 100644 --- a/src/mbgl/geometry/glyph_atlas.hpp +++ b/src/mbgl/geometry/glyph_atlas.hpp @@ -4,7 +4,8 @@ #include <mbgl/geometry/binpack.hpp> #include <mbgl/text/glyph_store.hpp> #include <mbgl/util/noncopyable.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> +#include <mbgl/gl/gl_object_store.hpp> #include <string> #include <set> @@ -27,11 +28,11 @@ public: void removeGlyphs(uintptr_t tileUID); // Binds the atlas texture to the GPU, and uploads data if it is out of date. - void bind(); + void bind(gl::GLObjectStore&); // 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(); + void upload(gl::GLObjectStore&); const GLsizei width; const GLsizei height; @@ -53,7 +54,7 @@ private: std::map<std::string, std::map<uint32_t, GlyphValue>> index; const std::unique_ptr<uint8_t[]> data; std::atomic<bool> dirty; - GLuint texture = 0; + gl::TextureHolder texture; }; } // namespace mbgl diff --git a/src/mbgl/geometry/icon_buffer.cpp b/src/mbgl/geometry/icon_buffer.cpp index 4e6a1c52e7..101132ddbc 100644 --- a/src/mbgl/geometry/icon_buffer.cpp +++ b/src/mbgl/geometry/icon_buffer.cpp @@ -1,5 +1,5 @@ #include <mbgl/geometry/icon_buffer.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <mbgl/util/math.hpp> #include <cmath> diff --git a/src/mbgl/geometry/line_atlas.cpp b/src/mbgl/geometry/line_atlas.cpp index bbda2dce6f..9b133319dc 100644 --- a/src/mbgl/geometry/line_atlas.cpp +++ b/src/mbgl/geometry/line_atlas.cpp @@ -1,8 +1,8 @@ #include <mbgl/geometry/line_atlas.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> +#include <mbgl/gl/gl_object_store.hpp> #include <mbgl/platform/log.hpp> #include <mbgl/platform/platform.hpp> -#include <mbgl/util/gl_object_store.hpp> #include <mbgl/util/thread_context.hpp> #include <boost/functional/hash.hpp> @@ -21,14 +21,9 @@ LineAtlas::LineAtlas(GLsizei w, GLsizei h) LineAtlas::~LineAtlas() { assert(util::ThreadContext::currentlyOn(util::ThreadType::Map)); - - if (texture) { - mbgl::util::ThreadContext::getGLObjectStore()->abandonTexture(texture); - texture = 0; - } } -LinePatternPos LineAtlas::getDashPosition(const std::vector<float> &dasharray, bool round) { +LinePatternPos LineAtlas::getDashPosition(const std::vector<float> &dasharray, bool round, gl::GLObjectStore& glObjectStore) { assert(util::ThreadContext::currentlyOn(util::ThreadType::Map)); size_t key = round ? std::numeric_limits<size_t>::min() : std::numeric_limits<size_t>::max(); @@ -39,7 +34,7 @@ LinePatternPos LineAtlas::getDashPosition(const std::vector<float> &dasharray, b // Note: We're not handling hash collisions here. const auto it = positions.find(key); if (it == positions.end()) { - auto inserted = positions.emplace(key, addDash(dasharray, round)); + auto inserted = positions.emplace(key, addDash(dasharray, round, glObjectStore)); assert(inserted.second); return inserted.first->second; } else { @@ -47,7 +42,7 @@ LinePatternPos LineAtlas::getDashPosition(const std::vector<float> &dasharray, b } } -LinePatternPos LineAtlas::addDash(const std::vector<float> &dasharray, bool round) { +LinePatternPos LineAtlas::addDash(const std::vector<float> &dasharray, bool round, gl::GLObjectStore& glObjectStore) { int n = round ? 7 : 0; int dashheight = 2 * n + 1; @@ -125,31 +120,31 @@ LinePatternPos LineAtlas::addDash(const std::vector<float> &dasharray, bool roun nextRow += dashheight; dirty = true; - bind(); + bind(glObjectStore); return position; }; -void LineAtlas::upload() { +void LineAtlas::upload(gl::GLObjectStore& glObjectStore) { if (dirty) { - bind(); + bind(glObjectStore); } } -void LineAtlas::bind() { +void LineAtlas::bind(gl::GLObjectStore& glObjectStore) { assert(util::ThreadContext::currentlyOn(util::ThreadType::Map)); bool first = false; if (!texture) { - MBGL_CHECK_ERROR(glGenTextures(1, &texture)); - MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture)); + texture.create(glObjectStore); + MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture.getID())); 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_REPEAT)); MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); first = true; } else { - MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture)); + MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture.getID())); } if (dirty) { diff --git a/src/mbgl/geometry/line_atlas.hpp b/src/mbgl/geometry/line_atlas.hpp index e76a91b61d..e94b399457 100644 --- a/src/mbgl/geometry/line_atlas.hpp +++ b/src/mbgl/geometry/line_atlas.hpp @@ -1,11 +1,11 @@ #ifndef MBGL_GEOMETRY_LINE_ATLAS #define MBGL_GEOMETRY_LINE_ATLAS -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> +#include <mbgl/gl/gl_object_store.hpp> #include <vector> #include <map> -#include <memory> namespace mbgl { @@ -21,14 +21,14 @@ public: ~LineAtlas(); // Binds the atlas texture to the GPU, and uploads data if it is out of date. - void bind(); + void bind(gl::GLObjectStore&); // 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(); + void upload(gl::GLObjectStore&); - LinePatternPos getDashPosition(const std::vector<float>&, bool); - LinePatternPos addDash(const std::vector<float> &dasharray, bool round); + LinePatternPos getDashPosition(const std::vector<float>&, bool, gl::GLObjectStore&); + LinePatternPos addDash(const std::vector<float> &dasharray, bool round, gl::GLObjectStore&); const GLsizei width; const GLsizei height; @@ -36,7 +36,7 @@ public: private: const std::unique_ptr<GLbyte[]> data; bool dirty; - GLuint texture = 0; + gl::TextureHolder texture; int nextRow = 0; std::map<size_t, LinePatternPos> positions; }; diff --git a/src/mbgl/geometry/line_buffer.cpp b/src/mbgl/geometry/line_buffer.cpp index f775a4589f..b35d3e8f47 100644 --- a/src/mbgl/geometry/line_buffer.cpp +++ b/src/mbgl/geometry/line_buffer.cpp @@ -1,5 +1,5 @@ #include <mbgl/geometry/line_buffer.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <cmath> diff --git a/src/mbgl/geometry/static_vertex_buffer.cpp b/src/mbgl/geometry/static_vertex_buffer.cpp index e8dad0ba9b..254b01b6b6 100644 --- a/src/mbgl/geometry/static_vertex_buffer.cpp +++ b/src/mbgl/geometry/static_vertex_buffer.cpp @@ -1,5 +1,5 @@ #include <mbgl/geometry/static_vertex_buffer.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> namespace mbgl { diff --git a/src/mbgl/geometry/text_buffer.cpp b/src/mbgl/geometry/text_buffer.cpp index 530048a6dd..1aa65146a4 100644 --- a/src/mbgl/geometry/text_buffer.cpp +++ b/src/mbgl/geometry/text_buffer.cpp @@ -1,5 +1,5 @@ #include <mbgl/geometry/text_buffer.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <mbgl/util/math.hpp> #include <cmath> diff --git a/src/mbgl/geometry/vao.cpp b/src/mbgl/geometry/vao.cpp index d3ad16e64f..8239604264 100644 --- a/src/mbgl/geometry/vao.cpp +++ b/src/mbgl/geometry/vao.cpp @@ -1,59 +1,23 @@ #include <mbgl/geometry/vao.hpp> #include <mbgl/platform/log.hpp> -#include <mbgl/util/gl_object_store.hpp> +#include <mbgl/gl/gl_object_store.hpp> #include <mbgl/util/string.hpp> -#include <mbgl/util/thread_context.hpp> namespace mbgl { -static gl::ExtensionFunction< - void (GLuint array)> - BindVertexArray({ - {"GL_ARB_vertex_array_object", "glBindVertexArray"}, - {"GL_OES_vertex_array_object", "glBindVertexArrayOES"}, - {"GL_APPLE_vertex_array_object", "glBindVertexArrayAPPLE"} - }); - -static gl::ExtensionFunction< - void (GLsizei n, - const GLuint* arrays)> - DeleteVertexArrays({ - {"GL_ARB_vertex_array_object", "glDeleteVertexArrays"}, - {"GL_OES_vertex_array_object", "glDeleteVertexArraysOES"}, - {"GL_APPLE_vertex_array_object", "glDeleteVertexArraysAPPLE"} - }); - -static gl::ExtensionFunction< - void (GLsizei n, - GLuint* arrays)> - GenVertexArrays({ - {"GL_ARB_vertex_array_object", "glGenVertexArrays"}, - {"GL_OES_vertex_array_object", "glGenVertexArraysOES"}, - {"GL_APPLE_vertex_array_object", "glGenVertexArraysAPPLE"} - }); - void VertexArrayObject::Unbind() { - if (!BindVertexArray) return; - MBGL_CHECK_ERROR(BindVertexArray(0)); -} - -void VertexArrayObject::Delete(GLsizei n, const GLuint* arrays) { - MBGL_CHECK_ERROR(DeleteVertexArrays(n, arrays)); + if (!gl::BindVertexArray) return; + MBGL_CHECK_ERROR(gl::BindVertexArray(0)); } VertexArrayObject::VertexArrayObject() { } VertexArrayObject::~VertexArrayObject() { - if (!DeleteVertexArrays) return; - - if (vao) { - util::ThreadContext::getGLObjectStore()->abandonVAO(vao); - } } -void VertexArrayObject::bindVertexArrayObject() { - if (!GenVertexArrays || !BindVertexArray) { +void VertexArrayObject::bindVertexArrayObject(gl::GLObjectStore& glObjectStore) { + if (!gl::GenVertexArrays || !gl::BindVertexArray) { static bool reported = false; if (!reported) { Log::Warning(Event::OpenGL, "Not using Vertex Array Objects"); @@ -62,10 +26,8 @@ void VertexArrayObject::bindVertexArrayObject() { return; } - if (!vao) { - MBGL_CHECK_ERROR(GenVertexArrays(1, &vao)); - } - MBGL_CHECK_ERROR(BindVertexArray(vao)); + if (!vao) vao.create(glObjectStore); + MBGL_CHECK_ERROR(gl::BindVertexArray(vao.getID())); } void VertexArrayObject::verifyBinding(Shader &shader, GLuint vertexBuffer, GLuint elementsBuffer, diff --git a/src/mbgl/geometry/vao.hpp b/src/mbgl/geometry/vao.hpp index 2dcc02c76b..dcb66dd41d 100644 --- a/src/mbgl/geometry/vao.hpp +++ b/src/mbgl/geometry/vao.hpp @@ -2,26 +2,28 @@ #define MBGL_GEOMETRY_VAO #include <mbgl/shader/shader.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> +#include <mbgl/gl/gl_object_store.hpp> #include <mbgl/util/noncopyable.hpp> #include <stdexcept> namespace mbgl { +class Shader; + class VertexArrayObject : public util::noncopyable { public: static void Unbind(); - static void Delete(GLsizei n, const GLuint* arrays); VertexArrayObject(); ~VertexArrayObject(); template <typename Shader, typename VertexBuffer> - inline void bind(Shader& shader, VertexBuffer &vertexBuffer, GLbyte *offset) { - bindVertexArrayObject(); + inline void bind(Shader& shader, VertexBuffer &vertexBuffer, GLbyte *offset, gl::GLObjectStore& glObjectStore) { + bindVertexArrayObject(glObjectStore); if (bound_shader == 0) { - vertexBuffer.bind(); + vertexBuffer.bind(glObjectStore); shader.bind(offset); if (vao) { storeBinding(shader, vertexBuffer.getID(), 0, offset); @@ -32,11 +34,11 @@ public: } template <typename Shader, typename VertexBuffer, typename ElementsBuffer> - inline void bind(Shader& shader, VertexBuffer &vertexBuffer, ElementsBuffer &elementsBuffer, GLbyte *offset) { - bindVertexArrayObject(); + inline void bind(Shader& shader, VertexBuffer &vertexBuffer, ElementsBuffer &elementsBuffer, GLbyte *offset, gl::GLObjectStore& glObjectStore) { + bindVertexArrayObject(glObjectStore); if (bound_shader == 0) { - vertexBuffer.bind(); - elementsBuffer.bind(); + vertexBuffer.bind(glObjectStore); + elementsBuffer.bind(glObjectStore); shader.bind(offset); if (vao) { storeBinding(shader, vertexBuffer.getID(), elementsBuffer.getID(), offset); @@ -46,16 +48,16 @@ public: } } - inline GLuint getID() const { - return vao; + GLuint getID() const { + return vao.getID(); } private: - void bindVertexArrayObject(); + void bindVertexArrayObject(gl::GLObjectStore&); void storeBinding(Shader &shader, GLuint vertexBuffer, GLuint elementsBuffer, GLbyte *offset); void verifyBinding(Shader &shader, GLuint vertexBuffer, GLuint elementsBuffer, GLbyte *offset); - GLuint vao = 0; + gl::VAOHolder vao; // For debug reasons, we're storing the bind information so that we can // detect errors and report diff --git a/src/mbgl/gl/debugging.cpp b/src/mbgl/gl/debugging.cpp index fb9e037714..e61de42bc3 100644 --- a/src/mbgl/gl/debugging.cpp +++ b/src/mbgl/gl/debugging.cpp @@ -1,5 +1,5 @@ #include <mbgl/gl/debugging.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <mbgl/platform/event.hpp> #include <mbgl/platform/log.hpp> diff --git a/src/mbgl/platform/gl.cpp b/src/mbgl/gl/gl.cpp index e5495c80dc..c57717aa87 100644 --- a/src/mbgl/platform/gl.cpp +++ b/src/mbgl/gl/gl.cpp @@ -1,4 +1,4 @@ -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <mbgl/util/string.hpp> #include <mbgl/platform/log.hpp> diff --git a/src/mbgl/renderer/gl_config.cpp b/src/mbgl/gl/gl_config.cpp index 4160ae100e..4160ae100e 100644 --- a/src/mbgl/renderer/gl_config.cpp +++ b/src/mbgl/gl/gl_config.cpp diff --git a/src/mbgl/gl/gl_config.hpp b/src/mbgl/gl/gl_config.hpp new file mode 100644 index 0000000000..af373fc3f8 --- /dev/null +++ b/src/mbgl/gl/gl_config.hpp @@ -0,0 +1,100 @@ +#ifndef MBGL_GL_GL_CONFIG +#define MBGL_GL_GL_CONFIG + +#include <cstdint> +#include <tuple> +#include <array> + +#include <mbgl/gl/gl_values.hpp> + +namespace mbgl { +namespace gl { + +template <typename T> +class Value { +public: + inline void operator=(const typename T::Type& value) { + if (dirty || current != value) { + dirty = false; + current = value; + T::Set(current); + } + } + + inline void reset() { + dirty = true; + current = T::Default; + T::Set(current); + } + + inline void setDirty() { + dirty = true; + } + +private: + typename T::Type current = T::Default; + bool dirty = false; +}; + +class Config { +public: + void reset() { + stencilFunc.reset(); + stencilMask.reset(); + stencilTest.reset(); + stencilOp.reset(); + depthRange.reset(); + depthMask.reset(); + depthTest.reset(); + depthFunc.reset(); + blend.reset(); + blendFunc.reset(); + colorMask.reset(); + clearDepth.reset(); + clearColor.reset(); + clearStencil.reset(); + program.reset(); + lineWidth.reset(); + } + + void setDirty() { + stencilFunc.setDirty(); + stencilMask.setDirty(); + stencilTest.setDirty(); + stencilOp.setDirty(); + depthRange.setDirty(); + depthMask.setDirty(); + depthTest.setDirty(); + depthFunc.setDirty(); + blend.setDirty(); + blendFunc.setDirty(); + colorMask.setDirty(); + clearDepth.setDirty(); + clearColor.setDirty(); + clearStencil.setDirty(); + program.setDirty(); + lineWidth.setDirty(); + } + + Value<StencilFunc> stencilFunc; + Value<StencilMask> stencilMask; + Value<StencilTest> stencilTest; + Value<StencilOp> stencilOp; + Value<DepthRange> depthRange; + Value<DepthMask> depthMask; + Value<DepthTest> depthTest; + Value<DepthFunc> depthFunc; + Value<Blend> blend; + Value<BlendFunc> blendFunc; + Value<ColorMask> colorMask; + Value<ClearDepth> clearDepth; + Value<ClearColor> clearColor; + Value<ClearStencil> clearStencil; + Value<Program> program; + Value<LineWidth> lineWidth; +}; + +} // namespace gl +} // namespace mbgl + +#endif // MBGL_RENDERER_GL_CONFIG diff --git a/src/mbgl/gl/gl_object_store.cpp b/src/mbgl/gl/gl_object_store.cpp new file mode 100644 index 0000000000..4948e20694 --- /dev/null +++ b/src/mbgl/gl/gl_object_store.cpp @@ -0,0 +1,120 @@ +#include <mbgl/gl/gl_object_store.hpp> + +#include <cassert> + +namespace mbgl { +namespace gl { + +void ProgramHolder::create(GLObjectStore& objectStore_) { + if (id) return; + objectStore = &objectStore_; + id = MBGL_CHECK_ERROR(glCreateProgram()); +} + +void ProgramHolder::reset() { + if (!id) return; + objectStore->abandonedPrograms.push_back(id); + id = 0; +} + +void ShaderHolder::create(GLObjectStore& objectStore_) { + if (id) return; + objectStore = &objectStore_; + id = MBGL_CHECK_ERROR(glCreateShader(type)); +} + +void ShaderHolder::reset() { + if (!id) return; + objectStore->abandonedShaders.push_back(id); + id = 0; +} + +void BufferHolder::create(GLObjectStore& objectStore_) { + if (id) return; + objectStore = &objectStore_; + MBGL_CHECK_ERROR(glGenBuffers(1, &id)); +} + +void BufferHolder::reset() { + if (!id) return; + objectStore->abandonedBuffers.push_back(id); + id = 0; +} + +void TextureHolder::create(GLObjectStore& objectStore_) { + if (id) return; + objectStore = &objectStore_; + MBGL_CHECK_ERROR(glGenTextures(1, &id)); +} + +void TextureHolder::reset() { + if (!id) return; + objectStore->abandonedTextures.push_back(id); + id = 0; +} + +void TexturePoolHolder::create(GLObjectStore& objectStore_) { + if (bool()) return; + objectStore = &objectStore_; + MBGL_CHECK_ERROR(glGenTextures(TextureMax, ids.data())); +} + +void TexturePoolHolder::reset() { + if (!bool()) return; + for (GLuint id : ids) { + if (id) { + objectStore->abandonedTextures.push_back(id); + } + } + ids.fill(0); +} + +void VAOHolder::create(GLObjectStore& objectStore_) { + if (id) return; + objectStore = &objectStore_; + MBGL_CHECK_ERROR(gl::GenVertexArrays(1, &id)); +} + +void VAOHolder::reset() { + if (!id) return; + objectStore->abandonedVAOs.push_back(id); + id = 0; +} + +GLObjectStore::~GLObjectStore() { + assert(abandonedPrograms.empty()); + assert(abandonedShaders.empty()); + assert(abandonedBuffers.empty()); + assert(abandonedTextures.empty()); + assert(abandonedVAOs.empty()); +} + +void GLObjectStore::performCleanup() { + for (GLuint id : abandonedPrograms) { + MBGL_CHECK_ERROR(glDeleteProgram(id)); + } + abandonedPrograms.clear(); + + for (GLuint id : abandonedShaders) { + MBGL_CHECK_ERROR(glDeleteShader(id)); + } + abandonedShaders.clear(); + + if (!abandonedBuffers.empty()) { + MBGL_CHECK_ERROR(glDeleteBuffers(int(abandonedBuffers.size()), abandonedBuffers.data())); + abandonedBuffers.clear(); + } + + if (!abandonedTextures.empty()) { + MBGL_CHECK_ERROR(glDeleteTextures(int(abandonedTextures.size()), abandonedTextures.data())); + abandonedTextures.clear(); + } + + if (!abandonedVAOs.empty()) { + MBGL_CHECK_ERROR(gl::DeleteVertexArrays(int(abandonedVAOs.size()), abandonedVAOs.data())); + abandonedVAOs.clear(); + } +} + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/gl_object_store.hpp b/src/mbgl/gl/gl_object_store.hpp new file mode 100644 index 0000000000..832f1d09b3 --- /dev/null +++ b/src/mbgl/gl/gl_object_store.hpp @@ -0,0 +1,141 @@ +#ifndef MBGL_MAP_UTIL_GL_OBJECT_STORE +#define MBGL_MAP_UTIL_GL_OBJECT_STORE + +#include <mbgl/gl/gl.hpp> +#include <mbgl/util/noncopyable.hpp> + +#include <array> +#include <algorithm> +#include <memory> +#include <vector> + +namespace mbgl { +namespace gl { + +class GLObjectStore : private util::noncopyable { +public: + ~GLObjectStore(); + + // Actually remove the objects we marked as abandoned with the above methods. + // Only call this while the OpenGL context is exclusive to this thread. + void performCleanup(); + +private: + friend class ProgramHolder; + friend class ShaderHolder; + friend class BufferHolder; + friend class TextureHolder; + friend class TexturePoolHolder; + friend class VAOHolder; + + std::vector<GLuint> abandonedPrograms; + std::vector<GLuint> abandonedShaders; + std::vector<GLuint> abandonedBuffers; + std::vector<GLuint> abandonedTextures; + std::vector<GLuint> abandonedVAOs; +}; + +class GLHolder : private util::noncopyable { +public: + GLHolder() {} + + GLHolder(GLHolder&& o) noexcept : id(o.id) { o.id = 0; } + GLHolder& operator=(GLHolder&& o) noexcept { id = o.id; o.id = 0; return *this; } + + explicit operator bool() const { return id; } + GLuint getID() const { return id; } + +protected: + GLuint id = 0; + GLObjectStore* objectStore = nullptr; +}; + +class ProgramHolder : public GLHolder { +public: + ProgramHolder() = default; + ~ProgramHolder() { reset(); } + + ProgramHolder(ProgramHolder&& o) noexcept : GLHolder(std::move(o)) {} + ProgramHolder& operator=(ProgramHolder&& o) noexcept { GLHolder::operator=(std::move(o)); return *this; } + + void create(GLObjectStore&); + void reset(); +}; + +class ShaderHolder : public GLHolder { +public: + ShaderHolder(GLenum type_) : type(type_) {} + ~ShaderHolder() { reset(); } + + ShaderHolder(ShaderHolder&& o) noexcept : GLHolder(std::move(o)), type(o.type) {} + ShaderHolder& operator=(ShaderHolder&& o) noexcept { GLHolder::operator=(std::move(o)); type = o.type; return *this; } + + void create(GLObjectStore&); + void reset(); + +private: + GLenum type = 0; +}; + +class BufferHolder : public GLHolder { +public: + BufferHolder() = default; + ~BufferHolder() { reset(); } + + BufferHolder(BufferHolder&& o) noexcept : GLHolder(std::move(o)) {} + BufferHolder& operator=(BufferHolder&& o) noexcept { GLHolder::operator=(std::move(o)); return *this; } + + void create(GLObjectStore&); + void reset(); +}; + +class TextureHolder : public GLHolder { +public: + TextureHolder() = default; + ~TextureHolder() { reset(); } + + TextureHolder(TextureHolder&& o) noexcept : GLHolder(std::move(o)) {} + TextureHolder& operator=(TextureHolder&& o) noexcept { GLHolder::operator=(std::move(o)); return *this; } + + void create(GLObjectStore&); + void reset(); +}; + +class TexturePoolHolder : private util::noncopyable { +public: + static const GLsizei TextureMax = 64; + + TexturePoolHolder() { ids.fill(0); } + ~TexturePoolHolder() { reset(); } + + TexturePoolHolder(TexturePoolHolder&& o) noexcept : ids(std::move(o.ids)) {} + TexturePoolHolder& operator=(TexturePoolHolder&& o) noexcept { ids = std::move(o.ids); return *this; } + + explicit operator bool() { return std::none_of(ids.begin(), ids.end(), [](int id) { return id == 0; }); } + const std::array<GLuint, TextureMax>& getIDs() const { return ids; } + const GLuint& operator[](size_t pos) { return ids[pos]; } + + void create(GLObjectStore&); + void reset(); + +private: + std::array<GLuint, TextureMax> ids; + GLObjectStore* objectStore = nullptr; +}; + +class VAOHolder : public GLHolder { +public: + VAOHolder() = default; + ~VAOHolder() { reset(); } + + VAOHolder(VAOHolder&& o) noexcept : GLHolder(std::move(o)) {} + VAOHolder& operator=(VAOHolder&& o) noexcept { GLHolder::operator=(std::move(o)); return *this; } + + void create(GLObjectStore&); + void reset(); +}; + +} // namespace gl +} // namespace mbgl + +#endif diff --git a/src/mbgl/gl/texture_pool.cpp b/src/mbgl/gl/texture_pool.cpp new file mode 100644 index 0000000000..a875f4d579 --- /dev/null +++ b/src/mbgl/gl/texture_pool.cpp @@ -0,0 +1,41 @@ +#include <mbgl/gl/texture_pool.hpp> +#include <mbgl/gl/gl_object_store.hpp> + +#include <vector> + +namespace mbgl { +namespace gl { + +GLuint TexturePool::getTextureID(gl::GLObjectStore& glObjectStore) { + for (auto& impl : pools) { + if (impl.ids.empty()) continue; + auto it = impl.ids.begin(); + GLuint id = *it; + impl.ids.erase(it); + return id; + } + + // All texture IDs are in use. + pools.emplace_back(Impl(glObjectStore)); + auto it = pools.back().ids.begin(); + GLuint id = *it; + pools.back().ids.erase(it); + return id; +} + +void TexturePool::releaseTextureID(GLuint id) { + for (auto it = pools.begin(); it != pools.end(); ++it) { + for (GLsizei i = 0; i < gl::TexturePoolHolder::TextureMax; ++i) { + if (it->pool[i] == id) { + it->ids.push_back(id); + if (GLsizei(it->ids.size()) == gl::TexturePoolHolder::TextureMax) { + pools.erase(it); + } + return; + } + } + } +} + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/texture_pool.hpp b/src/mbgl/gl/texture_pool.hpp new file mode 100644 index 0000000000..10f63bfac9 --- /dev/null +++ b/src/mbgl/gl/texture_pool.hpp @@ -0,0 +1,41 @@ +#ifndef MBGL_UTIL_TEXTUREPOOL +#define MBGL_UTIL_TEXTUREPOOL + +#include <mbgl/util/noncopyable.hpp> +#include <mbgl/gl/gl.hpp> +#include <mbgl/gl/gl_object_store.hpp> + +#include <algorithm> +#include <memory> +#include <vector> + +namespace mbgl { +namespace gl { + +class TexturePool : private util::noncopyable { +public: + GLuint getTextureID(gl::GLObjectStore&); + void releaseTextureID(GLuint); + +private: + class Impl : private util::noncopyable { + public: + Impl(gl::GLObjectStore& glObjectStore) : ids(gl::TexturePoolHolder::TextureMax) { + pool.create(glObjectStore); + std::copy(pool.getIDs().begin(), pool.getIDs().end(), ids.begin()); + } + + Impl(Impl&& o) : pool(std::move(o.pool)), ids(std::move(o.ids)) {} + Impl& operator=(Impl&& o) { pool = std::move(o.pool); ids = std::move(o.ids); return *this; } + + gl::TexturePoolHolder pool; + std::vector<GLuint> ids; + }; + + std::vector<Impl> pools; +}; + +} // namespace gl +} // namespace mbgl + +#endif diff --git a/src/mbgl/layer/background_layer.hpp b/src/mbgl/layer/background_layer.hpp index 063331fade..118bb19053 100644 --- a/src/mbgl/layer/background_layer.hpp +++ b/src/mbgl/layer/background_layer.hpp @@ -15,6 +15,7 @@ public: class BackgroundLayer : public StyleLayer { public: + BackgroundLayer() : StyleLayer(Type::Background) {} std::unique_ptr<StyleLayer> clone() const override; void parseLayout(const JSValue&) override {}; @@ -28,6 +29,11 @@ public: BackgroundPaintProperties paint; }; +template <> +inline bool StyleLayer::is<BackgroundLayer>() const { + return type == Type::Background; +} + } // namespace mbgl #endif diff --git a/src/mbgl/layer/circle_layer.hpp b/src/mbgl/layer/circle_layer.hpp index 03169ca065..036bf79991 100644 --- a/src/mbgl/layer/circle_layer.hpp +++ b/src/mbgl/layer/circle_layer.hpp @@ -22,6 +22,7 @@ public: class CircleLayer : public StyleLayer { public: + CircleLayer() : StyleLayer(Type::Circle) {} std::unique_ptr<StyleLayer> clone() const override; void parseLayout(const JSValue&) override {}; @@ -35,6 +36,11 @@ public: CirclePaintProperties paint; }; +template <> +inline bool StyleLayer::is<CircleLayer>() const { + return type == Type::Circle; +} + } // namespace mbgl #endif diff --git a/src/mbgl/layer/custom_layer.cpp b/src/mbgl/layer/custom_layer.cpp index 39742ecad8..0b6de51e67 100644 --- a/src/mbgl/layer/custom_layer.cpp +++ b/src/mbgl/layer/custom_layer.cpp @@ -8,7 +8,8 @@ CustomLayer::CustomLayer(const std::string& id_, CustomLayerInitializeFunction initializeFn_, CustomLayerRenderFunction renderFn_, CustomLayerDeinitializeFunction deinitializeFn_, - void * context_) { + void* context_) + : StyleLayer(Type::Custom) { id = id_; initializeFn = initializeFn_; renderFn = renderFn_; diff --git a/src/mbgl/layer/custom_layer.hpp b/src/mbgl/layer/custom_layer.hpp index 315d158802..b54ac7481e 100644 --- a/src/mbgl/layer/custom_layer.hpp +++ b/src/mbgl/layer/custom_layer.hpp @@ -38,6 +38,11 @@ private: void* context = nullptr; }; +template <> +inline bool StyleLayer::is<CustomLayer>() const { + return type == Type::Custom; +} + } // namespace mbgl #endif diff --git a/src/mbgl/layer/fill_layer.hpp b/src/mbgl/layer/fill_layer.hpp index ee079a5c8a..3b1c5a84fe 100644 --- a/src/mbgl/layer/fill_layer.hpp +++ b/src/mbgl/layer/fill_layer.hpp @@ -19,6 +19,7 @@ public: class FillLayer : public StyleLayer { public: + FillLayer() : StyleLayer(Type::Fill) {} std::unique_ptr<StyleLayer> clone() const override; void parseLayout(const JSValue&) override {}; @@ -32,6 +33,11 @@ public: FillPaintProperties paint; }; +template <> +inline bool StyleLayer::is<FillLayer>() const { + return type == Type::Fill; +} + } // namespace mbgl #endif diff --git a/src/mbgl/layer/line_layer.cpp b/src/mbgl/layer/line_layer.cpp index 8454eb2664..edf128fd35 100644 --- a/src/mbgl/layer/line_layer.cpp +++ b/src/mbgl/layer/line_layer.cpp @@ -69,7 +69,7 @@ bool LineLayer::recalculate(const StyleCalculationParameters& parameters) { } std::unique_ptr<Bucket> LineLayer::createBucket(StyleBucketParameters& parameters) const { - auto bucket = std::make_unique<LineBucket>(); + auto bucket = std::make_unique<LineBucket>(parameters.tileID.overscaling); bucket->layout = layout; diff --git a/src/mbgl/layer/line_layer.hpp b/src/mbgl/layer/line_layer.hpp index 027f7a9c06..200541c620 100644 --- a/src/mbgl/layer/line_layer.hpp +++ b/src/mbgl/layer/line_layer.hpp @@ -38,6 +38,7 @@ public: class LineLayer : public StyleLayer { public: + LineLayer() : StyleLayer(Type::Line) {} std::unique_ptr<StyleLayer> clone() const override; void parseLayout(const JSValue&) override; @@ -52,6 +53,11 @@ public: LinePaintProperties paint; }; +template <> +inline bool StyleLayer::is<LineLayer>() const { + return type == Type::Line; +} + } // namespace mbgl #endif diff --git a/src/mbgl/layer/raster_layer.hpp b/src/mbgl/layer/raster_layer.hpp index bf912bad4a..52c0f0a7ae 100644 --- a/src/mbgl/layer/raster_layer.hpp +++ b/src/mbgl/layer/raster_layer.hpp @@ -19,6 +19,7 @@ public: class RasterLayer : public StyleLayer { public: + RasterLayer() : StyleLayer(Type::Raster) {} std::unique_ptr<StyleLayer> clone() const override; void parseLayout(const JSValue&) override {}; @@ -32,6 +33,11 @@ public: RasterPaintProperties paint; }; +template <> +inline bool StyleLayer::is<RasterLayer>() const { + return type == Type::Raster; +} + } // namespace mbgl #endif diff --git a/src/mbgl/layer/symbol_layer.hpp b/src/mbgl/layer/symbol_layer.hpp index 730bd2ad4a..a2b3b0acf9 100644 --- a/src/mbgl/layer/symbol_layer.hpp +++ b/src/mbgl/layer/symbol_layer.hpp @@ -84,6 +84,7 @@ public: class SymbolLayer : public StyleLayer { public: + SymbolLayer() : StyleLayer(Type::Symbol) {} std::unique_ptr<StyleLayer> clone() const override; void parseLayout(const JSValue&) override; @@ -97,9 +98,14 @@ public: SymbolLayoutProperties layout; SymbolPaintProperties paint; - SpriteAtlas* spriteAtlas; + SpriteAtlas* spriteAtlas = nullptr; }; +template <> +inline bool StyleLayer::is<SymbolLayer>() const { + return type == Type::Symbol; +} + } // namespace mbgl #endif diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 7e0fdd29fe..c3123fb3be 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -462,6 +462,11 @@ AnnotationIDs Map::addShapeAnnotations(const std::vector<ShapeAnnotation>& annot return result; } +void Map::updatePointAnnotation(AnnotationID annotationId, const PointAnnotation& annotation) { + data->getAnnotationManager()->updatePointAnnotation(annotationId, annotation, getMaxZoom()); + update(Update::Annotations); +} + void Map::removeAnnotation(AnnotationID annotation) { removeAnnotations({ annotation }); } diff --git a/src/mbgl/map/map_context.cpp b/src/mbgl/map/map_context.cpp index 03da5ee321..f9397d4f78 100644 --- a/src/mbgl/map/map_context.cpp +++ b/src/mbgl/map/map_context.cpp @@ -16,9 +16,10 @@ #include <mbgl/sprite/sprite_atlas.hpp> #include <mbgl/sprite/sprite_store.hpp> -#include <mbgl/util/gl_object_store.hpp> +#include <mbgl/gl/gl_object_store.hpp> +#include <mbgl/gl/texture_pool.hpp> + #include <mbgl/util/worker.hpp> -#include <mbgl/util/texture_pool.hpp> #include <mbgl/util/exception.hpp> #include <mbgl/util/string.hpp> #include <mbgl/util/mapbox.hpp> @@ -27,18 +28,16 @@ namespace mbgl { -MapContext::MapContext(View& view_, FileSource& fileSource, MapMode mode_, GLContextMode contextMode_, const float pixelRatio_) +MapContext::MapContext(View& view_, FileSource& fileSource_, MapMode mode_, GLContextMode contextMode_, const float pixelRatio_) : view(view_), + fileSource(fileSource_), dataPtr(std::make_unique<MapData>(mode_, contextMode_, pixelRatio_)), data(*dataPtr), asyncUpdate([this] { update(); }), asyncInvalidate([&view_] { view_.invalidate(); }), - texturePool(std::make_unique<TexturePool>()) { + texturePool(std::make_unique<gl::TexturePool>()) { assert(util::ThreadContext::currentlyOn(util::ThreadType::Map)); - util::ThreadContext::setFileSource(&fileSource); - util::ThreadContext::setGLObjectStore(&glObjectStore); - view.activate(); } @@ -95,7 +94,7 @@ void MapContext::setStyleURL(const std::string& url) { styleURL = url; styleJSON.clear(); - style = std::make_unique<Style>(data); + style = std::make_unique<Style>(data, fileSource); const size_t pos = styleURL.rfind('/'); std::string base = ""; @@ -103,8 +102,7 @@ void MapContext::setStyleURL(const std::string& url) { base = styleURL.substr(0, pos + 1); } - FileSource* fs = util::ThreadContext::getFileSource(); - styleRequest = fs->request(Resource::style(styleURL), [this, base](Response res) { + styleRequest = fileSource.request(Resource::style(styleURL), [this, base](Response res) { if (res.error) { if (res.error->reason == Response::Error::Reason::NotFound && util::mapbox::isMapboxURL(styleURL)) { @@ -113,14 +111,11 @@ void MapContext::setStyleURL(const std::string& url) { Log::Error(Event::Setup, "loading style failed: %s", res.error->message.c_str()); data.loading = false; } + } else if (res.notModified || res.noContent) { return; + } else { + loadStyleJSON(*res.data, base); } - - if (res.notModified) { - return; - } - - loadStyleJSON(*res.data, base); }); } @@ -132,7 +127,7 @@ void MapContext::setStyleJSON(const std::string& json, const std::string& base) styleURL.clear(); styleJSON.clear(); - style = std::make_unique<Style>(data); + style = std::make_unique<Style>(data, fileSource); loadStyleJSON(json, base); } @@ -241,7 +236,7 @@ bool MapContext::renderSync(const TransformState& state, const FrameData& frame) // Cleanup OpenGL objects that we abandoned since the last render call. glObjectStore.performCleanup(); - if (!painter) painter = std::make_unique<Painter>(data, transformState); + if (!painter) painter = std::make_unique<Painter>(data, transformState, glObjectStore); painter->render(*style, frame, data.getAnnotationManager()->getSpriteAtlas()); if (data.mode == MapMode::Still) { diff --git a/src/mbgl/map/map_context.hpp b/src/mbgl/map/map_context.hpp index dd0c2de465..83ab71c86e 100644 --- a/src/mbgl/map/map_context.hpp +++ b/src/mbgl/map/map_context.hpp @@ -8,9 +8,9 @@ #include <mbgl/map/map_data.hpp> #include <mbgl/style/style.hpp> #include <mbgl/util/async_task.hpp> -#include <mbgl/util/gl_object_store.hpp> #include <mbgl/util/ptr.hpp> #include <mbgl/util/optional.hpp> +#include <mbgl/gl/gl_object_store.hpp> #include <vector> @@ -18,11 +18,12 @@ namespace mbgl { class View; class MapData; -class TexturePool; class Painter; class SpriteImage; class FileRequest; +namespace gl { class TexturePool; } + struct FrameData { std::array<uint16_t, 2> framebufferSize; }; @@ -77,16 +78,17 @@ private: void loadStyleJSON(const std::string& json, const std::string& base); View& view; + FileSource& fileSource; std::unique_ptr<MapData> dataPtr; MapData& data; - util::GLObjectStore glObjectStore; + gl::GLObjectStore glObjectStore; Update updateFlags = Update::Nothing; util::AsyncTask asyncUpdate; util::AsyncTask asyncInvalidate; - std::unique_ptr<TexturePool> texturePool; + std::unique_ptr<gl::TexturePool> texturePool; std::unique_ptr<Painter> painter; std::unique_ptr<Style> style; diff --git a/src/mbgl/map/raster_tile_data.cpp b/src/mbgl/map/raster_tile_data.cpp deleted file mode 100644 index f9f5480197..0000000000 --- a/src/mbgl/map/raster_tile_data.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#include <mbgl/map/raster_tile_data.hpp> -#include <mbgl/map/source.hpp> -#include <mbgl/storage/resource.hpp> -#include <mbgl/storage/response.hpp> -#include <mbgl/storage/file_source.hpp> -#include <mbgl/util/worker.hpp> -#include <mbgl/util/work_request.hpp> - -using namespace mbgl; - -RasterTileData::RasterTileData(const TileID& id_, - float pixelRatio, - const std::string& urlTemplate, - TexturePool &texturePool_, - Worker& worker_, - const std::function<void(std::exception_ptr)>& callback) - : TileData(id_), - texturePool(texturePool_), - worker(worker_) { - state = State::loading; - - const Resource resource = Resource::tile(urlTemplate, pixelRatio, id.x, id.y, id.sourceZ); - req = util::ThreadContext::getFileSource()->request(resource, [callback, this](Response res) { - if (res.error) { - std::exception_ptr error; - if (res.error->reason == Response::Error::Reason::NotFound) { - // This is a 404 response. We're treating these as empty tiles. - workRequest.reset(); - state = State::parsed; - bucket.reset(); - } else { - // This is a different error, e.g. a connection or server error. - error = std::make_exception_ptr(std::runtime_error(res.error->message)); - } - callback(error); - return; - } - - modified = res.modified; - expires = res.expires; - - if (res.notModified) { - // We got the same data again. Abort early. - return; - } - - if (state == State::loading) { - // Only overwrite the state when we didn't have a previous tile. - state = State::loaded; - } - - workRequest.reset(); - workRequest = worker.parseRasterTile(std::make_unique<RasterBucket>(texturePool), res.data, [this, callback] (RasterTileParseResult result) { - workRequest.reset(); - if (state != State::loaded) { - return; - } - - std::exception_ptr error; - if (result.is<std::unique_ptr<Bucket>>()) { - state = State::parsed; - bucket = std::move(result.get<std::unique_ptr<Bucket>>()); - } else { - error = result.get<std::exception_ptr>(); - state = State::obsolete; - bucket.reset(); - } - - callback(error); - }); - }); -} - -RasterTileData::~RasterTileData() { - cancel(); -} - -Bucket* RasterTileData::getBucket(StyleLayer const&) { - return bucket.get(); -} - -void RasterTileData::cancel() { - if (state != State::obsolete) { - state = State::obsolete; - } - req = nullptr; - workRequest.reset(); -} diff --git a/src/mbgl/map/tile.cpp b/src/mbgl/map/tile.cpp deleted file mode 100644 index 408cdfaec5..0000000000 --- a/src/mbgl/map/tile.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include <mbgl/map/tile.hpp> - -using namespace mbgl; diff --git a/src/mbgl/map/tile_id.hpp b/src/mbgl/map/tile_id.hpp index dddbce3bb7..a193b63392 100644 --- a/src/mbgl/map/tile_id.hpp +++ b/src/mbgl/map/tile_id.hpp @@ -6,6 +6,7 @@ #include <string> #include <functional> #include <forward_list> +#include <limits> namespace mbgl { @@ -25,12 +26,6 @@ public: return ((std::pow(2, z) * y + x) * 32) + z; } - struct Hash { - std::size_t operator()(const TileID& id) const { - return std::hash<uint64_t>()(id.to_uint64()); - } - }; - inline bool operator==(const TileID& rhs) const { return w == rhs.w && z == rhs.z && x == rhs.x && y == rhs.y; } @@ -48,12 +43,24 @@ public: TileID parent(int8_t z, int8_t sourceMaxZoom) const; TileID normalized() const; - std::forward_list<TileID> children(int8_t sourceMaxZoom) const; + std::forward_list<TileID> + children(int8_t sourceMaxZoom = std::numeric_limits<int8_t>::max()) const; bool isChildOf(const TileID&) const; operator std::string() const; - }; } // namespace mbgl +namespace std { +template <> +struct hash<mbgl::TileID> { + typedef mbgl::TileID argument_type; + typedef std::size_t result_type; + + result_type operator()(const mbgl::TileID& id) const { + return std::hash<uint64_t>()(id.to_uint64()); + } +}; +} // namespace std + #endif diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp index 009534fc8b..087defabda 100644 --- a/src/mbgl/map/transform_state.cpp +++ b/src/mbgl/map/transform_state.cpp @@ -1,7 +1,6 @@ #include <mbgl/map/transform_state.hpp> #include <mbgl/map/tile_id.hpp> #include <mbgl/util/constants.hpp> -#include <mbgl/util/box.hpp> #include <mbgl/util/tile_coordinate.hpp> #include <mbgl/util/interpolate.hpp> #include <mbgl/util/math.hpp> @@ -54,18 +53,6 @@ void TransformState::getProjMatrix(mat4& projMatrix) const { pixel_y() - getHeight() / 2.0f, 0); } -box TransformState::cornersToBox(uint32_t z) const { - double w = width; - double h = height; - box b( - pointToCoordinate({ 0, 0 }).zoomTo(z), - pointToCoordinate({ w, 0 }).zoomTo(z), - pointToCoordinate({ w, h }).zoomTo(z), - pointToCoordinate({ 0, h }).zoomTo(z)); - return b; -} - - #pragma mark - Dimensions uint16_t TransformState::getWidth() const { diff --git a/src/mbgl/map/transform_state.hpp b/src/mbgl/map/transform_state.hpp index dfcc1ed1a0..0fb1f2304b 100644 --- a/src/mbgl/map/transform_state.hpp +++ b/src/mbgl/map/transform_state.hpp @@ -15,8 +15,7 @@ namespace mbgl { class TileID; -struct box; -struct TileCoordinate; +class TileCoordinate; class TransformState { friend class Transform; @@ -27,7 +26,6 @@ public: // Matrix void matrixFor(mat4& matrix, const TileID& id, const int8_t z) const; void getProjMatrix(mat4& matrix) const; - box cornersToBox(uint32_t z) const; // Dimensions uint16_t getWidth() const; diff --git a/src/mbgl/renderer/bucket.hpp b/src/mbgl/renderer/bucket.hpp index b7cbfdf0fe..85f97688dd 100644 --- a/src/mbgl/renderer/bucket.hpp +++ b/src/mbgl/renderer/bucket.hpp @@ -1,7 +1,7 @@ #ifndef MBGL_RENDERER_BUCKET #define MBGL_RENDERER_BUCKET -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <mbgl/renderer/render_pass.hpp> #include <mbgl/util/noncopyable.hpp> #include <mbgl/util/mat4.hpp> @@ -18,13 +18,17 @@ class StyleLayer; class TileID; class CollisionTile; +namespace gl { +class GLObjectStore; +} + class Bucket : private util::noncopyable { public: Bucket() : uploaded(false) {} // As long as this bucket has a Prepare render pass, this function is getting called. Typically, // this only happens once when the bucket is being rendered for the first time. - virtual void upload() = 0; + virtual void upload(gl::GLObjectStore&) = 0; // Every time this bucket is getting rendered, this function is called. This happens either // once or twice (for Opaque and Transparent render passes). diff --git a/src/mbgl/renderer/circle_bucket.cpp b/src/mbgl/renderer/circle_bucket.cpp index 1ebe8ffaf3..fcead38c33 100644 --- a/src/mbgl/renderer/circle_bucket.cpp +++ b/src/mbgl/renderer/circle_bucket.cpp @@ -14,9 +14,9 @@ CircleBucket::~CircleBucket() { // Do not remove. header file only contains forward definitions to unique pointers. } -void CircleBucket::upload() { - vertexBuffer_.upload(); - elementsBuffer_.upload(); +void CircleBucket::upload(gl::GLObjectStore& glObjectStore) { + vertexBuffer_.upload(glObjectStore); + elementsBuffer_.upload(glObjectStore); uploaded = true; } @@ -73,7 +73,7 @@ void CircleBucket::addGeometry(const GeometryCollection& geometryCollection) { } } -void CircleBucket::drawCircles(CircleShader& shader) { +void CircleBucket::drawCircles(CircleShader& shader, gl::GLObjectStore& glObjectStore) { GLbyte* vertexIndex = BUFFER_OFFSET(0); GLbyte* elementsIndex = BUFFER_OFFSET(0); @@ -82,7 +82,7 @@ void CircleBucket::drawCircles(CircleShader& shader) { if (!group->elements_length) continue; - group->array[0].bind(shader, vertexBuffer_, elementsBuffer_, vertexIndex); + group->array[0].bind(shader, vertexBuffer_, elementsBuffer_, vertexIndex, glObjectStore); MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT, elementsIndex)); diff --git a/src/mbgl/renderer/circle_bucket.hpp b/src/mbgl/renderer/circle_bucket.hpp index f85c9267d3..875e5bb4a9 100644 --- a/src/mbgl/renderer/circle_bucket.hpp +++ b/src/mbgl/renderer/circle_bucket.hpp @@ -3,7 +3,7 @@ #include <mbgl/renderer/bucket.hpp> -#include <mbgl/map/geometry_tile.hpp> +#include <mbgl/tile/geometry_tile.hpp> #include <mbgl/geometry/elements_buffer.hpp> #include <mbgl/geometry/circle_buffer.hpp> @@ -20,13 +20,13 @@ public: CircleBucket(); ~CircleBucket() override; - void upload() override; + void upload(gl::GLObjectStore&) override; void render(Painter&, const StyleLayer&, const TileID&, const mat4&) override; bool hasData() const override; void addGeometry(const GeometryCollection&); - void drawCircles(CircleShader& shader); + void drawCircles(CircleShader&, gl::GLObjectStore&); private: CircleVertexBuffer vertexBuffer_; diff --git a/src/mbgl/renderer/debug_bucket.cpp b/src/mbgl/renderer/debug_bucket.cpp index 2d0590c56b..947783ddb8 100644 --- a/src/mbgl/renderer/debug_bucket.cpp +++ b/src/mbgl/renderer/debug_bucket.cpp @@ -2,7 +2,7 @@ #include <mbgl/renderer/painter.hpp> #include <mbgl/shader/plain_shader.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <cassert> #include <string> @@ -11,8 +11,8 @@ using namespace mbgl; DebugBucket::DebugBucket(const TileID id, const TileData::State state_, optional<SystemTimePoint> modified_, optional<SystemTimePoint> expires_, MapDebugOptions debugMode_) : state(state_), - modified(modified_), - expires(expires_), + modified(std::move(modified_)), + expires(std::move(expires_)), debugMode(debugMode_) { double baseline = 200; if (debugMode & MapDebugOptions::ParseStatus) { @@ -30,12 +30,12 @@ DebugBucket::DebugBucket(const TileID id, const TileData::State state_, optional } } -void DebugBucket::drawLines(PlainShader& shader) { - array.bind(shader, fontBuffer, BUFFER_OFFSET_0); +void DebugBucket::drawLines(PlainShader& shader, gl::GLObjectStore& glObjectStore) { + array.bind(shader, fontBuffer, BUFFER_OFFSET_0, glObjectStore); MBGL_CHECK_ERROR(glDrawArrays(GL_LINES, 0, (GLsizei)(fontBuffer.index()))); } -void DebugBucket::drawPoints(PlainShader& shader) { - array.bind(shader, fontBuffer, BUFFER_OFFSET_0); +void DebugBucket::drawPoints(PlainShader& shader, gl::GLObjectStore& glObjectStore) { + array.bind(shader, fontBuffer, BUFFER_OFFSET_0, glObjectStore); MBGL_CHECK_ERROR(glDrawArrays(GL_POINTS, 0, (GLsizei)(fontBuffer.index()))); } diff --git a/src/mbgl/renderer/debug_bucket.hpp b/src/mbgl/renderer/debug_bucket.hpp index 5c7511ce87..f12452751c 100644 --- a/src/mbgl/renderer/debug_bucket.hpp +++ b/src/mbgl/renderer/debug_bucket.hpp @@ -1,7 +1,7 @@ #ifndef MBGL_RENDERER_DEBUGBUCKET #define MBGL_RENDERER_DEBUGBUCKET -#include <mbgl/map/tile_data.hpp> +#include <mbgl/tile/tile_data.hpp> #include <mbgl/map/mode.hpp> #include <mbgl/geometry/debug_font_buffer.hpp> #include <mbgl/geometry/vao.hpp> @@ -11,6 +11,10 @@ namespace mbgl { class PlainShader; +namespace util { +class GLObjectStore; +} + class DebugBucket : private util::noncopyable { public: DebugBucket(TileID id, TileData::State, @@ -18,8 +22,8 @@ public: optional<SystemTimePoint> expires, MapDebugOptions); - void drawLines(PlainShader& shader); - void drawPoints(PlainShader& shader); + void drawLines(PlainShader&, gl::GLObjectStore&); + void drawPoints(PlainShader&, gl::GLObjectStore&); const TileData::State state; const optional<SystemTimePoint> modified; diff --git a/src/mbgl/renderer/fill_bucket.cpp b/src/mbgl/renderer/fill_bucket.cpp index ff976c2450..d3a4bc2b57 100644 --- a/src/mbgl/renderer/fill_bucket.cpp +++ b/src/mbgl/renderer/fill_bucket.cpp @@ -6,7 +6,7 @@ #include <mbgl/shader/plain_shader.hpp> #include <mbgl/shader/pattern_shader.hpp> #include <mbgl/shader/outline_shader.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <mbgl/platform/log.hpp> #include <cassert> @@ -186,10 +186,10 @@ void FillBucket::tessellate() { lineGroup.vertex_length += total_vertex_count; } -void FillBucket::upload() { - vertexBuffer.upload(); - triangleElementsBuffer.upload(); - lineElementsBuffer.upload(); +void FillBucket::upload(gl::GLObjectStore& glObjectStore) { + vertexBuffer.upload(glObjectStore); + triangleElementsBuffer.upload(glObjectStore); + lineElementsBuffer.upload(glObjectStore); // From now on, we're going to render during the opaque and translucent pass. uploaded = true; @@ -206,36 +206,36 @@ bool FillBucket::hasData() const { return !triangleGroups.empty() || !lineGroups.empty(); } -void FillBucket::drawElements(PlainShader& shader) { +void FillBucket::drawElements(PlainShader& shader, gl::GLObjectStore& glObjectStore) { GLbyte* vertex_index = BUFFER_OFFSET(0); GLbyte* elements_index = BUFFER_OFFSET(0); for (auto& group : triangleGroups) { assert(group); - group->array[0].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index); + group->array[0].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, glObjectStore); MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT, elements_index)); vertex_index += group->vertex_length * vertexBuffer.itemSize; elements_index += group->elements_length * triangleElementsBuffer.itemSize; } } -void FillBucket::drawElements(PatternShader& shader) { +void FillBucket::drawElements(PatternShader& shader, gl::GLObjectStore& glObjectStore) { GLbyte* vertex_index = BUFFER_OFFSET(0); GLbyte* elements_index = BUFFER_OFFSET(0); for (auto& group : triangleGroups) { assert(group); - group->array[1].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index); + group->array[1].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, glObjectStore); MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT, elements_index)); vertex_index += group->vertex_length * vertexBuffer.itemSize; elements_index += group->elements_length * triangleElementsBuffer.itemSize; } } -void FillBucket::drawVertices(OutlineShader& shader) { +void FillBucket::drawVertices(OutlineShader& shader, gl::GLObjectStore& glObjectStore) { GLbyte* vertex_index = BUFFER_OFFSET(0); GLbyte* elements_index = BUFFER_OFFSET(0); for (auto& group : lineGroups) { assert(group); - group->array[0].bind(shader, vertexBuffer, lineElementsBuffer, vertex_index); + group->array[0].bind(shader, vertexBuffer, lineElementsBuffer, vertex_index, glObjectStore); MBGL_CHECK_ERROR(glDrawElements(GL_LINES, group->elements_length * 2, GL_UNSIGNED_SHORT, elements_index)); vertex_index += group->vertex_length * vertexBuffer.itemSize; elements_index += group->elements_length * lineElementsBuffer.itemSize; diff --git a/src/mbgl/renderer/fill_bucket.hpp b/src/mbgl/renderer/fill_bucket.hpp index 674c41f7d1..b3b46f030b 100644 --- a/src/mbgl/renderer/fill_bucket.hpp +++ b/src/mbgl/renderer/fill_bucket.hpp @@ -2,7 +2,7 @@ #define MBGL_RENDERER_FILLBUCKET #include <mbgl/renderer/bucket.hpp> -#include <mbgl/map/geometry_tile.hpp> +#include <mbgl/tile/geometry_tile.hpp> #include <mbgl/geometry/elements_buffer.hpp> #include <mbgl/geometry/fill_buffer.hpp> @@ -32,16 +32,16 @@ public: FillBucket(); ~FillBucket() override; - void upload() override; + void upload(gl::GLObjectStore&) override; void render(Painter&, const StyleLayer&, const TileID&, const mat4&) override; bool hasData() const override; void addGeometry(const GeometryCollection&); void tessellate(); - void drawElements(PlainShader& shader); - void drawElements(PatternShader& shader); - void drawVertices(OutlineShader& shader); + void drawElements(PlainShader&, gl::GLObjectStore&); + void drawElements(PatternShader&, gl::GLObjectStore&); + void drawVertices(OutlineShader&, gl::GLObjectStore&); private: TESSalloc *allocator; diff --git a/src/mbgl/renderer/gl_config.hpp b/src/mbgl/renderer/gl_config.hpp deleted file mode 100644 index 2f21b35fe3..0000000000 --- a/src/mbgl/renderer/gl_config.hpp +++ /dev/null @@ -1,330 +0,0 @@ -#ifndef MBGL_RENDERER_GL_CONFIG -#define MBGL_RENDERER_GL_CONFIG - -#include <cstdint> -#include <tuple> -#include <array> - -#include <mbgl/platform/gl.hpp> - -namespace mbgl { -namespace gl { - -template <typename T> -class Value { -public: - inline void operator=(const typename T::Type& value) { - if (dirty || current != value) { - dirty = false; - current = value; - T::Set(current); - } - } - - inline void reset() { - dirty = true; - current = T::Default; - T::Set(current); - } - - inline void setDirty() { - dirty = true; - } - -private: - typename T::Type current = T::Default; - bool dirty = false; -}; - -struct ClearDepth { - using Type = GLfloat; - static const Type Default; - inline static void Set(const Type& value) { - MBGL_CHECK_ERROR(glClearDepth(value)); - } - inline static Type Get() { - Type clearDepth; - MBGL_CHECK_ERROR(glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepth)); - return clearDepth; - } -}; - -struct ClearColor { - struct Type { GLfloat r, g, b, a; }; - static const Type Default; - inline static void Set(const Type& value) { - MBGL_CHECK_ERROR(glClearColor(value.r, value.g, value.b, value.a)); - } - inline static Type Get() { - GLfloat floats[4]; - MBGL_CHECK_ERROR(glGetFloatv(GL_COLOR_CLEAR_VALUE, floats)); - return { floats[0], floats[1], floats[2], floats[3] }; - } -}; - -inline bool operator!=(const ClearColor::Type& a, const ClearColor::Type& b) { - return a.r != b.r || a.g != b.g || a.b != b.b || a.a != b.a; -} - -struct ClearStencil { - using Type = GLint; - static const Type Default; - inline static void Set(const Type& value) { - MBGL_CHECK_ERROR(glClearStencil(value)); - } - inline static Type Get() { - Type clearStencil; - MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &clearStencil)); - return clearStencil; - } -}; - -struct StencilMask { - using Type = GLuint; - static const Type Default; - inline static void Set(const Type& value) { - MBGL_CHECK_ERROR(glStencilMask(value)); - } - inline static Type Get() { - GLint stencilMask; - MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_WRITEMASK, &stencilMask)); - return stencilMask; - } -}; - -struct DepthMask { - using Type = GLboolean; - static const Type Default; - inline static void Set(const Type& value) { - MBGL_CHECK_ERROR(glDepthMask(value)); - } - inline static Type Get() { - Type depthMask; - MBGL_CHECK_ERROR(glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask)); - return depthMask; - } -}; - -struct ColorMask { - struct Type { bool r, g, b, a; }; - static const Type Default; - inline static void Set(const Type& value) { - MBGL_CHECK_ERROR(glColorMask(value.r, value.g, value.b, value.a)); - } - inline static Type Get() { - GLboolean bools[4]; - MBGL_CHECK_ERROR(glGetBooleanv(GL_COLOR_WRITEMASK, bools)); - return { static_cast<bool>(bools[0]), static_cast<bool>(bools[1]), - static_cast<bool>(bools[2]), static_cast<bool>(bools[3]) }; - } -}; - -inline bool operator!=(const ColorMask::Type& a, const ColorMask::Type& b) { - return a.r != b.r || a.g != b.g || a.b != b.b || a.a != b.a; -} - -struct StencilFunc { - struct Type { GLenum func; GLint ref; GLuint mask; }; - static const Type Default; - inline static void Set(const Type& value) { - MBGL_CHECK_ERROR(glStencilFunc(value.func, value.ref, value.mask)); - } - inline static Type Get() { - GLint func, ref, mask; - MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_FUNC, &func)); - MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_REF, &ref)); - MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_VALUE_MASK, &mask)); - return { static_cast<GLenum>(func), ref, static_cast<GLuint>(mask) }; - } -}; - -inline bool operator!=(const StencilFunc::Type& a, const StencilFunc::Type& b) { - return a.func != b.func || a.ref != b.ref || a.mask != b.mask; -} - -struct StencilTest { - using Type = bool; - static const Type Default; - inline static void Set(const Type& value) { - MBGL_CHECK_ERROR(value ? glEnable(GL_STENCIL_TEST) : glDisable(GL_STENCIL_TEST)); - } - inline static Type Get() { - Type stencilTest; - MBGL_CHECK_ERROR(stencilTest = glIsEnabled(GL_STENCIL_TEST)); - return stencilTest; - } -}; - -struct StencilOp { - struct Type { GLenum sfail, dpfail, dppass; }; - static const Type Default; - inline static void Set(const Type& value) { - MBGL_CHECK_ERROR(glStencilOp(value.sfail, value.dpfail, value.dppass)); - } - inline static Type Get() { - GLint sfail, dpfail, dppass; - MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_FAIL, &sfail)); - MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &dpfail)); - MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &dppass)); - return { static_cast<GLenum>(sfail), static_cast<GLenum>(dpfail), static_cast<GLuint>(dppass) }; - } -}; - -struct DepthRange { - struct Type { GLfloat near, far; }; - static const Type Default; - inline static void Set(const Type& value) { - MBGL_CHECK_ERROR(glDepthRange(value.near, value.far)); - } - inline static Type Get() { - GLfloat floats[2]; - MBGL_CHECK_ERROR(glGetFloatv(GL_DEPTH_RANGE, floats)); - return { floats[0], floats[1] }; - } -}; - -inline bool operator!=(const DepthRange::Type& a, const DepthRange::Type& b) { - return a.near != b.near || a.far != b.far; -} - -struct DepthTest { - using Type = bool; - static const Type Default; - inline static void Set(const Type& value) { - MBGL_CHECK_ERROR(value ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST)); - } - inline static Type Get() { - Type depthTest; - MBGL_CHECK_ERROR(depthTest = glIsEnabled(GL_DEPTH_TEST)); - return depthTest; - } -}; - -struct DepthFunc { - using Type = GLenum; - static const Type Default; - inline static void Set(const Type& value) { - MBGL_CHECK_ERROR(glDepthFunc(value)); - } - inline static Type Get() { - GLint depthFunc; - MBGL_CHECK_ERROR(glGetIntegerv(GL_DEPTH_FUNC, &depthFunc)); - return depthFunc; - } -}; - -struct Blend { - using Type = bool; - static const Type Default; - inline static void Set(const Type& value) { - MBGL_CHECK_ERROR(value ? glEnable(GL_BLEND) : glDisable(GL_BLEND)); - } - inline static Type Get() { - Type blend; - MBGL_CHECK_ERROR(blend = glIsEnabled(GL_BLEND)); - return blend; - } -}; - -struct BlendFunc { - struct Type { GLenum sfactor, dfactor; }; - static const Type Default; - inline static void Set(const Type& value) { - MBGL_CHECK_ERROR(glBlendFunc(value.sfactor, value.dfactor)); - } - inline static Type Get() { - GLint sfactor, dfactor; - MBGL_CHECK_ERROR(glGetIntegerv(GL_BLEND_SRC_ALPHA, &sfactor)); - MBGL_CHECK_ERROR(glGetIntegerv(GL_BLEND_DST_ALPHA, &dfactor)); - return { static_cast<GLenum>(sfactor), static_cast<GLenum>(dfactor) }; - } -}; - -struct Program { - using Type = GLuint; - static const Type Default; - inline static void Set(const Type& value) { - MBGL_CHECK_ERROR(glUseProgram(value)); - } - inline static Type Get() { - GLint program; - MBGL_CHECK_ERROR(glGetIntegerv(GL_CURRENT_PROGRAM, &program)); - return program; - } -}; - -struct LineWidth { - using Type = GLfloat; - static const Type Default; - inline static void Set(const Type& value) { - MBGL_CHECK_ERROR(glLineWidth(value)); - } - inline static Type Get() { - Type lineWidth; - MBGL_CHECK_ERROR(glGetFloatv(GL_LINE_WIDTH, &lineWidth)); - return lineWidth; - } -}; - -class Config { -public: - void reset() { - stencilFunc.reset(); - stencilMask.reset(); - stencilTest.reset(); - stencilOp.reset(); - depthRange.reset(); - depthMask.reset(); - depthTest.reset(); - depthFunc.reset(); - blend.reset(); - blendFunc.reset(); - colorMask.reset(); - clearDepth.reset(); - clearColor.reset(); - clearStencil.reset(); - program.reset(); - lineWidth.reset(); - } - - void setDirty() { - stencilFunc.setDirty(); - stencilMask.setDirty(); - stencilTest.setDirty(); - stencilOp.setDirty(); - depthRange.setDirty(); - depthMask.setDirty(); - depthTest.setDirty(); - depthFunc.setDirty(); - blend.setDirty(); - blendFunc.setDirty(); - colorMask.setDirty(); - clearDepth.setDirty(); - clearColor.setDirty(); - clearStencil.setDirty(); - program.setDirty(); - lineWidth.setDirty(); - } - - Value<StencilFunc> stencilFunc; - Value<StencilMask> stencilMask; - Value<StencilTest> stencilTest; - Value<StencilOp> stencilOp; - Value<DepthRange> depthRange; - Value<DepthMask> depthMask; - Value<DepthTest> depthTest; - Value<DepthFunc> depthFunc; - Value<Blend> blend; - Value<BlendFunc> blendFunc; - Value<ColorMask> colorMask; - Value<ClearDepth> clearDepth; - Value<ClearColor> clearColor; - Value<ClearStencil> clearStencil; - Value<Program> program; - Value<LineWidth> lineWidth; -}; - -} // namespace gl -} // namespace mbgl - -#endif // MBGL_RENDERER_GL_CONFIG diff --git a/src/mbgl/renderer/line_bucket.cpp b/src/mbgl/renderer/line_bucket.cpp index 83c5b43776..ba50e6b1f0 100644 --- a/src/mbgl/renderer/line_bucket.cpp +++ b/src/mbgl/renderer/line_bucket.cpp @@ -6,13 +6,14 @@ #include <mbgl/shader/linesdf_shader.hpp> #include <mbgl/shader/linepattern_shader.hpp> #include <mbgl/util/math.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/util/constants.hpp> +#include <mbgl/gl/gl.hpp> #include <cassert> using namespace mbgl; -LineBucket::LineBucket() { +LineBucket::LineBucket(float overscaling_) : overscaling(overscaling_) { } LineBucket::~LineBucket() { @@ -25,6 +26,21 @@ void LineBucket::addGeometry(const GeometryCollection& geometryCollection) { } } + +/* + * Sharp corners cause dashed lines to tilt because the distance along the line + * is the same at both the inner and outer corners. To improve the appearance of + * dashed lines we add extra points near sharp corners so that a smaller part + * of the line is tilted. + * + * COS_HALF_SHARP_CORNER controls how sharp a corner has to be for us to add an + * extra vertex. The default is 75 degrees. + * + * The newly created vertices are placed SHARP_CORNER_OFFSET pixels from the corner. + */ +const float COS_HALF_SHARP_CORNER = std::cos(75.0 / 2.0 * (M_PI / 180.0)); +const float SHARP_CORNER_OFFSET = 15.0f; + void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) { const GLsizei len = [&vertices] { GLsizei l = static_cast<GLsizei>(vertices.size()); @@ -42,6 +58,8 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) { const float miterLimit = layout.join == JoinType::Bevel ? 1.05f : float(layout.miterLimit); + const double sharpCornerOffset = SHARP_CORNER_OFFSET * (util::EXTENT / (512.0 * overscaling)); + const Coordinate firstVertex = vertices.front(); const Coordinate lastVertex = vertices[len - 1]; const bool closed = firstVertex == lastVertex; @@ -98,10 +116,6 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) { currentVertex = vertices[i]; - // Calculate how far along the line the currentVertex is - if (prevVertex) - distance += util::dist<double>(currentVertex, prevVertex); - // Calculate the normal towards the next vertex in this line. In case // there is no next vertex, pretend that the line is continuing straight, // meaning that we are just using the previous normal. @@ -134,6 +148,18 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) { const float cosHalfAngle = joinNormal.x * nextNormal.x + joinNormal.y * nextNormal.y; const float miterLength = cosHalfAngle != 0 ? 1 / cosHalfAngle: 1; + const bool isSharpCorner = cosHalfAngle < COS_HALF_SHARP_CORNER && prevVertex && nextVertex; + + if (isSharpCorner && i > 0) { + const double prevSegmentLength = util::dist<double>(currentVertex, prevVertex); + if (prevSegmentLength > 2.0 * sharpCornerOffset) { + Coordinate newPrevVertex = currentVertex - (util::round(vec2<double>(currentVertex - prevVertex) * (sharpCornerOffset / prevSegmentLength))); + distance += util::dist<double>(newPrevVertex, prevVertex); + addCurrentVertex(newPrevVertex, flip, distance, prevNormal, 0, 0, false, startVertex, triangleStore); + prevVertex = newPrevVertex; + } + } + // The join if a middle vertex, otherwise the cap const bool middleVertex = prevVertex && nextVertex; JoinType currentJoin = layout.join; @@ -167,6 +193,10 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) { } } + // Calculate how far along the line the currentVertex is + if (prevVertex) + distance += util::dist<double>(currentVertex, prevVertex); + if (middleVertex && currentJoin == JoinType::Miter) { joinNormal = joinNormal * miterLength; addCurrentVertex(currentVertex, flip, distance, joinNormal, 0, 0, false, startVertex, @@ -295,6 +325,16 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) { } } + if (isSharpCorner && i < len - 1) { + const double nextSegmentLength = util::dist<double>(currentVertex, nextVertex); + if (nextSegmentLength > 2 * sharpCornerOffset) { + Coordinate newCurrentVertex = currentVertex + util::round(vec2<double>(nextVertex - currentVertex) * (sharpCornerOffset / nextSegmentLength)); + distance += util::dist<double>(newCurrentVertex, currentVertex); + addCurrentVertex(newCurrentVertex, flip, distance, nextNormal, 0, 0, false, startVertex, triangleStore); + currentVertex = newCurrentVertex; + } + } + startOfLine = false; } @@ -378,9 +418,9 @@ void LineBucket::addPieSliceVertex(const Coordinate& currentVertex, } } -void LineBucket::upload() { - vertexBuffer.upload(); - triangleElementsBuffer.upload(); +void LineBucket::upload(gl::GLObjectStore& glObjectStore) { + vertexBuffer.upload(glObjectStore); + triangleElementsBuffer.upload(glObjectStore); // From now on, we're only going to render during the translucent pass. uploaded = true; @@ -397,7 +437,7 @@ bool LineBucket::hasData() const { return !triangleGroups.empty(); } -void LineBucket::drawLines(LineShader& shader) { +void LineBucket::drawLines(LineShader& shader, gl::GLObjectStore& glObjectStore) { GLbyte* vertex_index = BUFFER_OFFSET(0); GLbyte* elements_index = BUFFER_OFFSET(0); for (auto& group : triangleGroups) { @@ -405,7 +445,7 @@ void LineBucket::drawLines(LineShader& shader) { if (!group->elements_length) { continue; } - group->array[0].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index); + group->array[0].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, glObjectStore); MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT, elements_index)); vertex_index += group->vertex_length * vertexBuffer.itemSize; @@ -413,7 +453,7 @@ void LineBucket::drawLines(LineShader& shader) { } } -void LineBucket::drawLineSDF(LineSDFShader& shader) { +void LineBucket::drawLineSDF(LineSDFShader& shader, gl::GLObjectStore& glObjectStore) { GLbyte* vertex_index = BUFFER_OFFSET(0); GLbyte* elements_index = BUFFER_OFFSET(0); for (auto& group : triangleGroups) { @@ -421,7 +461,7 @@ void LineBucket::drawLineSDF(LineSDFShader& shader) { if (!group->elements_length) { continue; } - group->array[2].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index); + group->array[2].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, glObjectStore); MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT, elements_index)); vertex_index += group->vertex_length * vertexBuffer.itemSize; @@ -429,7 +469,7 @@ void LineBucket::drawLineSDF(LineSDFShader& shader) { } } -void LineBucket::drawLinePatterns(LinepatternShader& shader) { +void LineBucket::drawLinePatterns(LinepatternShader& shader, gl::GLObjectStore& glObjectStore) { GLbyte* vertex_index = BUFFER_OFFSET(0); GLbyte* elements_index = BUFFER_OFFSET(0); for (auto& group : triangleGroups) { @@ -437,7 +477,7 @@ void LineBucket::drawLinePatterns(LinepatternShader& shader) { if (!group->elements_length) { continue; } - group->array[1].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index); + group->array[1].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, glObjectStore); MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT, elements_index)); vertex_index += group->vertex_length * vertexBuffer.itemSize; diff --git a/src/mbgl/renderer/line_bucket.hpp b/src/mbgl/renderer/line_bucket.hpp index 7d662aac02..dd0ce4ff29 100644 --- a/src/mbgl/renderer/line_bucket.hpp +++ b/src/mbgl/renderer/line_bucket.hpp @@ -2,7 +2,7 @@ #define MBGL_RENDERER_LINEBUCKET #include <mbgl/renderer/bucket.hpp> -#include <mbgl/map/geometry_tile.hpp> +#include <mbgl/tile/geometry_tile.hpp> #include <mbgl/geometry/vao.hpp> #include <mbgl/geometry/elements_buffer.hpp> #include <mbgl/geometry/line_buffer.hpp> @@ -24,19 +24,19 @@ class LineBucket : public Bucket { using TriangleGroup = ElementGroup<3>; public: - LineBucket(); + LineBucket(float overscaling); ~LineBucket() override; - void upload() override; + void upload(gl::GLObjectStore&) override; void render(Painter&, const StyleLayer&, const TileID&, const mat4&) override; bool hasData() const override; void addGeometry(const GeometryCollection&); void addGeometry(const std::vector<Coordinate>& line); - void drawLines(LineShader& shader); - void drawLineSDF(LineSDFShader& shader); - void drawLinePatterns(LinepatternShader& shader); + void drawLines(LineShader&, gl::GLObjectStore&); + void drawLineSDF(LineSDFShader&, gl::GLObjectStore&); + void drawLinePatterns(LinepatternShader&, gl::GLObjectStore&); private: struct TriangleElement { @@ -62,6 +62,8 @@ private: GLint e3; std::vector<std::unique_ptr<TriangleGroup>> triangleGroups; + + const float overscaling; }; } // namespace mbgl diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index 0fd76314dc..da3551aa74 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -1,7 +1,7 @@ #include <mbgl/renderer/painter.hpp> -#include <mbgl/map/source.hpp> -#include <mbgl/map/tile.hpp> +#include <mbgl/source/source.hpp> +#include <mbgl/tile/tile.hpp> #include <mbgl/map/map_context.hpp> #include <mbgl/map/map_data.hpp> @@ -46,23 +46,25 @@ using namespace mbgl; -Painter::Painter(MapData& data_, TransformState& state_) - : data(data_), state(state_) { +Painter::Painter(MapData& data_, TransformState& state_, gl::GLObjectStore& glObjectStore_) + : data(data_), + state(state_), + glObjectStore(glObjectStore_) { gl::debugging::enable(); - plainShader = std::make_unique<PlainShader>(); - outlineShader = std::make_unique<OutlineShader>(); - lineShader = std::make_unique<LineShader>(); - linesdfShader = std::make_unique<LineSDFShader>(); - linepatternShader = std::make_unique<LinepatternShader>(); - patternShader = std::make_unique<PatternShader>(); - iconShader = std::make_unique<IconShader>(); - rasterShader = std::make_unique<RasterShader>(); - sdfGlyphShader = std::make_unique<SDFGlyphShader>(); - sdfIconShader = std::make_unique<SDFIconShader>(); - dotShader = std::make_unique<DotShader>(); - collisionBoxShader = std::make_unique<CollisionBoxShader>(); - circleShader = std::make_unique<CircleShader>(); + plainShader = std::make_unique<PlainShader>(glObjectStore); + outlineShader = std::make_unique<OutlineShader>(glObjectStore); + lineShader = std::make_unique<LineShader>(glObjectStore); + linesdfShader = std::make_unique<LineSDFShader>(glObjectStore); + linepatternShader = std::make_unique<LinepatternShader>(glObjectStore); + patternShader = std::make_unique<PatternShader>(glObjectStore); + iconShader = std::make_unique<IconShader>(glObjectStore); + rasterShader = std::make_unique<RasterShader>(glObjectStore); + sdfGlyphShader = std::make_unique<SDFGlyphShader>(glObjectStore); + sdfIconShader = std::make_unique<SDFIconShader>(glObjectStore); + dotShader = std::make_unique<DotShader>(glObjectStore); + collisionBoxShader = std::make_unique<CollisionBoxShader>(glObjectStore); + circleShader = std::make_unique<CircleShader>(glObjectStore); // Reset GL values config.reset(); @@ -108,16 +110,16 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a { MBGL_DEBUG_GROUP("upload"); - tileStencilBuffer.upload(); - tileBorderBuffer.upload(); - spriteAtlas->upload(); - lineAtlas->upload(); - glyphAtlas->upload(); - annotationSpriteAtlas.upload(); + tileStencilBuffer.upload(glObjectStore); + tileBorderBuffer.upload(glObjectStore); + spriteAtlas->upload(glObjectStore); + lineAtlas->upload(glObjectStore); + glyphAtlas->upload(glObjectStore); + annotationSpriteAtlas.upload(glObjectStore); for (const auto& item : order) { if (item.bucket && item.bucket->needsUpload()) { - item.bucket->upload(); + item.bucket->upload(glObjectStore); } } } @@ -151,7 +153,7 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a source->updateMatrices(projMatrix, state); } - drawClippingMasks(sources); + drawClippingMasks(generator.getStencils()); } frameHistory.record(data.getAnimationTime(), state.getZoom()); @@ -270,7 +272,7 @@ void Painter::renderBackground(const BackgroundLayer& layer) { float zoomFraction = state.getZoomFraction(); - config.program = patternShader->program; + config.program = patternShader->getID(); patternShader->u_matrix = identityMatrix; patternShader->u_pattern_tl_a = (*imagePosA).tl; patternShader->u_pattern_br_a = (*imagePosA).br; @@ -315,9 +317,9 @@ void Painter::renderBackground(const BackgroundLayer& layer) { patternShader->u_patternmatrix_b = matrixB; VertexArrayObject::Unbind(); - backgroundBuffer.bind(); + backgroundBuffer.bind(glObjectStore); patternShader->bind(0); - spriteAtlas->bind(true); + spriteAtlas->bind(true, glObjectStore); } else { Color color = properties.color; color[0] *= properties.opacity; @@ -325,10 +327,10 @@ void Painter::renderBackground(const BackgroundLayer& layer) { color[2] *= properties.opacity; color[3] *= properties.opacity; - config.program = plainShader->program; + config.program = plainShader->getID(); plainShader->u_matrix = identityMatrix; plainShader->u_color = color; - backgroundArray.bind(*plainShader, backgroundBuffer, BUFFER_OFFSET(0)); + backgroundArray.bind(*plainShader, backgroundBuffer, BUFFER_OFFSET(0), glObjectStore); } config.stencilTest = GL_FALSE; diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp index 092c164033..83d051359b 100644 --- a/src/mbgl/renderer/painter.hpp +++ b/src/mbgl/renderer/painter.hpp @@ -10,11 +10,11 @@ #include <mbgl/geometry/vao.hpp> #include <mbgl/geometry/static_vertex_buffer.hpp> -#include <mbgl/renderer/gl_config.hpp> +#include <mbgl/gl/gl_config.hpp> #include <mbgl/style/types.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <mbgl/util/noncopyable.hpp> #include <mbgl/util/chrono.hpp> @@ -66,9 +66,13 @@ class CollisionBoxShader; struct ClipID; +namespace util { +class GLObjectStore; +} + class Painter : private util::noncopyable { public: - Painter(MapData&, TransformState&); + Painter(MapData&, TransformState&, gl::GLObjectStore&); ~Painter(); void render(const Style& style, @@ -93,8 +97,7 @@ public: float contrastFactor(float contrast); std::array<float, 3> spinWeights(float spin_value); - void drawClippingMasks(const std::set<Source*>&); - void drawClippingMask(const mat4& matrix, const ClipID& clip); + void drawClippingMasks(const std::map<TileID, ClipID>&); bool needsAnimation() const; @@ -119,7 +122,7 @@ private: float scaleDivisor, std::array<float, 2> texsize, SDFShader& sdfShader, - void (SymbolBucket::*drawSDF)(SDFShader&)); + void (SymbolBucket::*drawSDF)(SDFShader&, gl::GLObjectStore&)); void setDepthSublayer(int n); @@ -143,6 +146,8 @@ private: MapData& data; TransformState& state; + gl::GLObjectStore& glObjectStore; + FrameData frame; int indent = 0; diff --git a/src/mbgl/renderer/painter_circle.cpp b/src/mbgl/renderer/painter_circle.cpp index 9518cf9e39..4ae562d674 100644 --- a/src/mbgl/renderer/painter_circle.cpp +++ b/src/mbgl/renderer/painter_circle.cpp @@ -38,7 +38,7 @@ void Painter::renderCircle(CircleBucket& bucket, // are inversely related. float antialiasing = 1 / data.pixelRatio / properties.radius; - config.program = circleShader->program; + config.program = circleShader->getID(); circleShader->u_matrix = vtxMatrix; circleShader->u_exmatrix = extrudeMatrix; @@ -46,5 +46,5 @@ void Painter::renderCircle(CircleBucket& bucket, circleShader->u_blur = std::max<float>(properties.blur, antialiasing); circleShader->u_size = properties.radius; - bucket.drawCircles(*circleShader); + bucket.drawCircles(*circleShader, glObjectStore); } diff --git a/src/mbgl/renderer/painter_clipping.cpp b/src/mbgl/renderer/painter_clipping.cpp index 6994650412..aed4c45869 100644 --- a/src/mbgl/renderer/painter_clipping.cpp +++ b/src/mbgl/renderer/painter_clipping.cpp @@ -1,36 +1,39 @@ #include <mbgl/renderer/painter.hpp> -#include <mbgl/map/source.hpp> +#include <mbgl/source/source.hpp> #include <mbgl/shader/plain_shader.hpp> #include <mbgl/util/clip_id.hpp> #include <mbgl/gl/debugging.hpp> using namespace mbgl; -void Painter::drawClippingMasks(const std::set<Source*>& sources) { + +void Painter::drawClippingMasks(const std::map<TileID, ClipID>& stencils) { MBGL_DEBUG_GROUP("clipping masks"); - config.program = plainShader->program; + mat4 matrix; + const GLuint mask = 0b11111111; + + config.program = plainShader->getID(); config.stencilOp.reset(); config.stencilTest = GL_TRUE; - config.depthFunc.reset(); - config.depthTest = GL_TRUE; + config.depthTest = GL_FALSE; config.depthMask = GL_FALSE; config.colorMask = { GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE }; - config.depthRange = { 1.0f, 1.0f }; + config.stencilMask = mask; - coveringPlainArray.bind(*plainShader, tileStencilBuffer, BUFFER_OFFSET_0); + coveringPlainArray.bind(*plainShader, tileStencilBuffer, BUFFER_OFFSET_0, glObjectStore); - for (const auto& source : sources) { - source->drawClippingMasks(*this); - } -} + for (const auto& stencil : stencils) { + const auto& id = stencil.first; + const auto& clip = stencil.second; -void Painter::drawClippingMask(const mat4& matrix, const ClipID &clip) { - plainShader->u_matrix = matrix; + MBGL_DEBUG_GROUP(std::string{ "mask: " } + std::string(id)); + state.matrixFor(matrix, id, id.z); + matrix::multiply(matrix, projMatrix, matrix); + plainShader->u_matrix = matrix; - const GLint ref = (GLint)(clip.reference.to_ulong()); - const GLuint mask = (GLuint)(clip.mask.to_ulong()); - config.stencilFunc = { GL_ALWAYS, ref, mask }; - config.stencilMask = mask; - MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLES, 0, (GLsizei)tileStencilBuffer.index())); + const GLint ref = (GLint)(clip.reference.to_ulong()); + config.stencilFunc = { GL_ALWAYS, ref, mask }; + MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLES, 0, (GLsizei)tileStencilBuffer.index())); + } } diff --git a/src/mbgl/renderer/painter_debug.cpp b/src/mbgl/renderer/painter_debug.cpp index d6b1aec73c..575bffe53f 100644 --- a/src/mbgl/renderer/painter_debug.cpp +++ b/src/mbgl/renderer/painter_debug.cpp @@ -1,7 +1,7 @@ #include <mbgl/renderer/painter.hpp> #include <mbgl/renderer/debug_bucket.hpp> -#include <mbgl/map/tile.hpp> -#include <mbgl/map/tile_data.hpp> +#include <mbgl/tile/tile.hpp> +#include <mbgl/tile/tile_data.hpp> #include <mbgl/map/map_data.hpp> #include <mbgl/shader/plain_shader.hpp> #include <mbgl/util/string.hpp> @@ -15,7 +15,9 @@ void Painter::renderTileDebug(const Tile& tile) { if (data.getDebug() != MapDebugOptions::NoDebug) { prepareTile(tile); renderDebugText(*tile.data, tile.matrix); - renderDebugFrame(tile.matrix); + if (data.getDebug() & MapDebugOptions::TileBorders) { + renderDebugFrame(tile.matrix); + } } } @@ -31,24 +33,24 @@ void Painter::renderDebugText(TileData& tileData, const mat4 &matrix) { tileData.debugBucket = std::make_unique<DebugBucket>(tileData.id, tileData.getState(), tileData.modified, tileData.expires, data.getDebug()); } - config.program = plainShader->program; + config.program = plainShader->getID(); plainShader->u_matrix = matrix; // Draw white outline plainShader->u_color = {{ 1.0f, 1.0f, 1.0f, 1.0f }}; config.lineWidth = 4.0f * data.pixelRatio; - tileData.debugBucket->drawLines(*plainShader); + tileData.debugBucket->drawLines(*plainShader, glObjectStore); #ifndef GL_ES_VERSION_2_0 // Draw line "end caps" MBGL_CHECK_ERROR(glPointSize(2)); - tileData.debugBucket->drawPoints(*plainShader); + tileData.debugBucket->drawPoints(*plainShader, glObjectStore); #endif // Draw black text. plainShader->u_color = {{ 0.0f, 0.0f, 0.0f, 1.0f }}; config.lineWidth = 2.0f * data.pixelRatio; - tileData.debugBucket->drawLines(*plainShader); + tileData.debugBucket->drawLines(*plainShader, glObjectStore); config.depthFunc.reset(); config.depthTest = GL_TRUE; @@ -64,11 +66,11 @@ void Painter::renderDebugFrame(const mat4 &matrix) { config.stencilOp.reset(); config.stencilTest = GL_TRUE; - config.program = plainShader->program; + config.program = plainShader->getID(); plainShader->u_matrix = matrix; // draw tile outline - tileBorderArray.bind(*plainShader, tileBorderBuffer, BUFFER_OFFSET_0); + tileBorderArray.bind(*plainShader, tileBorderBuffer, BUFFER_OFFSET_0, glObjectStore); plainShader->u_color = {{ 1.0f, 0.0f, 0.0f, 1.0f }}; config.lineWidth = 4.0f * data.pixelRatio; MBGL_CHECK_ERROR(glDrawArrays(GL_LINE_STRIP, 0, (GLsizei)tileBorderBuffer.index())); diff --git a/src/mbgl/renderer/painter_fill.cpp b/src/mbgl/renderer/painter_fill.cpp index 44ae1919a0..cd54645c2b 100644 --- a/src/mbgl/renderer/painter_fill.cpp +++ b/src/mbgl/renderer/painter_fill.cpp @@ -44,7 +44,7 @@ void Painter::renderFill(FillBucket& bucket, const FillLayer& layer, const TileI // Because we're drawing top-to-bottom, and we update the stencil mask // befrom, we have to draw the outline first (!) if (outline && pass == RenderPass::Translucent) { - config.program = outlineShader->program; + config.program = outlineShader->getID(); outlineShader->u_matrix = vtxMatrix; config.lineWidth = 2.0f; // This is always fixed and does not depend on the pixelRatio! @@ -56,7 +56,7 @@ void Painter::renderFill(FillBucket& bucket, const FillLayer& layer, const TileI static_cast<float>(frame.framebufferSize[1]) }}; setDepthSublayer(0); - bucket.drawVertices(*outlineShader); + bucket.drawVertices(*outlineShader, glObjectStore); } if (pattern) { @@ -78,7 +78,7 @@ void Painter::renderFill(FillBucket& bucket, const FillLayer& layer, const TileI 1.0f / ((*posB).size[0] * factor * properties.pattern.value.toScale), 1.0f / ((*posB).size[1] * factor * properties.pattern.value.toScale)); - config.program = patternShader->program; + config.program = patternShader->getID(); patternShader->u_matrix = vtxMatrix; patternShader->u_pattern_tl_a = (*posA).tl; patternShader->u_pattern_br_a = (*posA).br; @@ -111,11 +111,11 @@ void Painter::renderFill(FillBucket& bucket, const FillLayer& layer, const TileI patternShader->u_offset_b = std::array<float, 2>{{offsetBx, offsetBy}}; MBGL_CHECK_ERROR(glActiveTexture(GL_TEXTURE0)); - spriteAtlas->bind(true); + spriteAtlas->bind(true, glObjectStore); // Draw the actual triangles into the color & stencil buffer. setDepthSublayer(0); - bucket.drawElements(*patternShader); + bucket.drawElements(*patternShader, glObjectStore); } } else { @@ -125,20 +125,20 @@ void Painter::renderFill(FillBucket& bucket, const FillLayer& layer, const TileI // fragments or when it's translucent and we're drawing translucent // fragments // Draw filling rectangle. - config.program = plainShader->program; + config.program = plainShader->getID(); plainShader->u_matrix = vtxMatrix; plainShader->u_color = fill_color; // Draw the actual triangles into the color & stencil buffer. setDepthSublayer(1); - bucket.drawElements(*plainShader); + bucket.drawElements(*plainShader, glObjectStore); } } // Because we're drawing top-to-bottom, and we update the stencil mask // below, we have to draw the outline first (!) if (fringeline && pass == RenderPass::Translucent) { - config.program = outlineShader->program; + config.program = outlineShader->getID(); outlineShader->u_matrix = vtxMatrix; config.lineWidth = 2.0f; // This is always fixed and does not depend on the pixelRatio! @@ -151,6 +151,6 @@ void Painter::renderFill(FillBucket& bucket, const FillLayer& layer, const TileI }}; setDepthSublayer(2); - bucket.drawVertices(*outlineShader); + bucket.drawVertices(*outlineShader, glObjectStore); } } diff --git a/src/mbgl/renderer/painter_line.cpp b/src/mbgl/renderer/painter_line.cpp index dd2833b117..5fc5ee0221 100644 --- a/src/mbgl/renderer/painter_line.cpp +++ b/src/mbgl/renderer/painter_line.cpp @@ -70,7 +70,7 @@ void Painter::renderLine(LineBucket& bucket, const LineLayer& layer, const TileI if (!properties.dasharray.value.from.empty()) { - config.program = linesdfShader->program; + config.program = linesdfShader->getID(); linesdfShader->u_matrix = vtxMatrix; linesdfShader->u_exmatrix = extrudeMatrix; @@ -79,9 +79,9 @@ void Painter::renderLine(LineBucket& bucket, const LineLayer& layer, const TileI linesdfShader->u_blur = blur; linesdfShader->u_color = color; - LinePatternPos posA = lineAtlas->getDashPosition(properties.dasharray.value.from, layout.cap == CapType::Round); - LinePatternPos posB = lineAtlas->getDashPosition(properties.dasharray.value.to, layout.cap == CapType::Round); - lineAtlas->bind(); + LinePatternPos posA = lineAtlas->getDashPosition(properties.dasharray.value.from, layout.cap == CapType::Round, glObjectStore); + LinePatternPos posB = lineAtlas->getDashPosition(properties.dasharray.value.to, layout.cap == CapType::Round, glObjectStore); + lineAtlas->bind(glObjectStore); const float widthA = posA.width * properties.dasharray.value.fromScale; const float widthB = posB.width * properties.dasharray.value.toScale; @@ -102,7 +102,7 @@ void Painter::renderLine(LineBucket& bucket, const LineLayer& layer, const TileI linesdfShader->u_offset = -properties.offset; linesdfShader->u_antialiasingmatrix = antialiasingMatrix; - bucket.drawLineSDF(*linesdfShader); + bucket.drawLineSDF(*linesdfShader, glObjectStore); } else if (!properties.pattern.value.from.empty()) { optional<SpriteAtlasPosition> imagePosA = spriteAtlas->getPosition(properties.pattern.value.from, true); @@ -113,7 +113,7 @@ void Painter::renderLine(LineBucket& bucket, const LineLayer& layer, const TileI float factor = util::EXTENT / (512 * id.overscaling) / std::pow(2, state.getIntegerZoom() - id.z); - config.program = linepatternShader->program; + config.program = linepatternShader->getID(); linepatternShader->u_matrix = vtxMatrix; linepatternShader->u_exmatrix = extrudeMatrix; @@ -134,12 +134,12 @@ void Painter::renderLine(LineBucket& bucket, const LineLayer& layer, const TileI linepatternShader->u_antialiasingmatrix = antialiasingMatrix; MBGL_CHECK_ERROR(glActiveTexture(GL_TEXTURE0)); - spriteAtlas->bind(true); + spriteAtlas->bind(true, glObjectStore); - bucket.drawLinePatterns(*linepatternShader); + bucket.drawLinePatterns(*linepatternShader, glObjectStore); } else { - config.program = lineShader->program; + config.program = lineShader->getID(); lineShader->u_matrix = vtxMatrix; lineShader->u_exmatrix = extrudeMatrix; @@ -152,6 +152,6 @@ void Painter::renderLine(LineBucket& bucket, const LineLayer& layer, const TileI lineShader->u_color = color; - bucket.drawLines(*lineShader); + bucket.drawLines(*lineShader, glObjectStore); } } diff --git a/src/mbgl/renderer/painter_raster.cpp b/src/mbgl/renderer/painter_raster.cpp index 3fd953fcd6..377b2c005c 100644 --- a/src/mbgl/renderer/painter_raster.cpp +++ b/src/mbgl/renderer/painter_raster.cpp @@ -1,5 +1,5 @@ #include <mbgl/renderer/painter.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <mbgl/renderer/raster_bucket.hpp> #include <mbgl/layer/raster_layer.hpp> #include <mbgl/shader/raster_shader.hpp> @@ -12,7 +12,7 @@ void Painter::renderRaster(RasterBucket& bucket, const RasterLayer& layer, const const RasterPaintProperties& properties = layer.paint; if (bucket.hasData()) { - config.program = rasterShader->program; + config.program = rasterShader->getID(); rasterShader->u_matrix = matrix; rasterShader->u_buffer = 0; rasterShader->u_opacity = properties.opacity; @@ -28,7 +28,7 @@ void Painter::renderRaster(RasterBucket& bucket, const RasterLayer& layer, const config.depthTest = GL_TRUE; config.depthMask = GL_FALSE; setDepthSublayer(0); - bucket.drawRaster(*rasterShader, tileStencilBuffer, coveringRasterArray); + bucket.drawRaster(*rasterShader, tileStencilBuffer, coveringRasterArray, glObjectStore); } } diff --git a/src/mbgl/renderer/painter_symbol.cpp b/src/mbgl/renderer/painter_symbol.cpp index 0538485824..5f59d6a8a6 100644 --- a/src/mbgl/renderer/painter_symbol.cpp +++ b/src/mbgl/renderer/painter_symbol.cpp @@ -23,7 +23,7 @@ void Painter::renderSDF(SymbolBucket &bucket, float sdfFontSize, std::array<float, 2> texsize, SDFShader& sdfShader, - void (SymbolBucket::*drawSDF)(SDFShader&)) + void (SymbolBucket::*drawSDF)(SDFShader&, gl::GLObjectStore&)) { mat4 vtxMatrix = translatedMatrix(matrix, styleProperties.translate, id, styleProperties.translateAnchor); @@ -49,7 +49,7 @@ void Painter::renderSDF(SymbolBucket &bucket, float fontScale = fontSize / sdfFontSize; matrix::scale(exMatrix, exMatrix, fontScale, fontScale, 1.0f); - config.program = sdfShader.program; + config.program = sdfShader.getID(); sdfShader.u_matrix = vtxMatrix; sdfShader.u_exmatrix = exMatrix; sdfShader.u_texsize = texsize; @@ -101,7 +101,7 @@ void Painter::renderSDF(SymbolBucket &bucket, sdfShader.u_buffer = (haloOffset - styleProperties.haloWidth / fontScale) / sdfPx; setDepthSublayer(0); - (bucket.*drawSDF)(sdfShader); + (bucket.*drawSDF)(sdfShader, glObjectStore); } // Then, we draw the text/icon over the halo @@ -122,7 +122,7 @@ void Painter::renderSDF(SymbolBucket &bucket, sdfShader.u_buffer = (256.0f - 64.0f) / 256.0f; setDepthSublayer(1); - (bucket.*drawSDF)(sdfShader); + (bucket.*drawSDF)(sdfShader, glObjectStore); } } @@ -137,22 +137,6 @@ void Painter::renderSymbol(SymbolBucket& bucket, const SymbolLayer& layer, const config.depthMask = GL_FALSE; - if (bucket.hasCollisionBoxData()) { - config.stencilOp.reset(); - config.stencilTest = GL_TRUE; - - config.program = collisionBoxShader->program; - collisionBoxShader->u_matrix = matrix; - collisionBoxShader->u_scale = std::pow(2, state.getZoom() - id.z); - collisionBoxShader->u_zoom = state.getZoom() * 10; - collisionBoxShader->u_maxzoom = (id.z + 1) * 10; - config.lineWidth = 1.0f; - - setDepthSublayer(0); - bucket.drawCollisionBoxes(*collisionBoxShader); - - } - // TODO remove the `true ||` when #1673 is implemented const bool drawAcrossEdges = (data.mode == MapMode::Continuous) && (true || !(layout.text.allowOverlap || layout.icon.allowOverlap || layout.text.ignorePlacement || layout.icon.ignorePlacement)); @@ -190,7 +174,7 @@ void Painter::renderSymbol(SymbolBucket& bucket, const SymbolLayer& layer, const SpriteAtlas* activeSpriteAtlas = layer.spriteAtlas; const bool iconScaled = fontScale != 1 || data.pixelRatio != activeSpriteAtlas->getPixelRatio() || bucket.iconsNeedLinear; const bool iconTransformed = layout.icon.rotationAlignment == RotationAlignmentType::Map || angleOffset != 0 || state.getPitch() != 0; - activeSpriteAtlas->bind(sdf || state.isChanging() || iconScaled || iconTransformed); + activeSpriteAtlas->bind(sdf || state.isChanging() || iconScaled || iconTransformed, glObjectStore); if (sdf) { renderSDF(bucket, @@ -227,7 +211,7 @@ void Painter::renderSymbol(SymbolBucket& bucket, const SymbolLayer& layer, const float x = state.getHeight() / 2.0f * std::tan(state.getPitch()); float extra = (topedgelength + x) / topedgelength - 1; - config.program = iconShader->program; + config.program = iconShader->getID(); iconShader->u_matrix = vtxMatrix; iconShader->u_exmatrix = exMatrix; iconShader->u_texsize = {{ float(activeSpriteAtlas->getWidth()) / 4.0f, float(activeSpriteAtlas->getHeight()) / 4.0f }}; @@ -246,7 +230,7 @@ void Painter::renderSymbol(SymbolBucket& bucket, const SymbolLayer& layer, const iconShader->u_opacity = properties.icon.opacity; setDepthSublayer(0); - bucket.drawIcons(*iconShader); + bucket.drawIcons(*iconShader, glObjectStore); } } @@ -258,7 +242,7 @@ void Painter::renderSymbol(SymbolBucket& bucket, const SymbolLayer& layer, const config.depthTest = GL_FALSE; } - glyphAtlas->bind(); + glyphAtlas->bind(glObjectStore); renderSDF(bucket, id, @@ -271,4 +255,20 @@ void Painter::renderSymbol(SymbolBucket& bucket, const SymbolLayer& layer, const &SymbolBucket::drawGlyphs); } + if (bucket.hasCollisionBoxData()) { + config.stencilOp.reset(); + config.stencilTest = GL_TRUE; + + config.program = collisionBoxShader->getID(); + collisionBoxShader->u_matrix = matrix; + collisionBoxShader->u_scale = std::pow(2, state.getZoom() - id.z); + collisionBoxShader->u_zoom = state.getZoom() * 10; + collisionBoxShader->u_maxzoom = (id.z + 1) * 10; + config.lineWidth = 1.0f; + + setDepthSublayer(0); + bucket.drawCollisionBoxes(*collisionBoxShader, glObjectStore); + + } + } diff --git a/src/mbgl/renderer/raster_bucket.cpp b/src/mbgl/renderer/raster_bucket.cpp index 4dbbf18697..137574b731 100644 --- a/src/mbgl/renderer/raster_bucket.cpp +++ b/src/mbgl/renderer/raster_bucket.cpp @@ -5,13 +5,13 @@ using namespace mbgl; -RasterBucket::RasterBucket(TexturePool& texturePool) +RasterBucket::RasterBucket(gl::TexturePool& texturePool) : raster(texturePool) { } -void RasterBucket::upload() { +void RasterBucket::upload(gl::GLObjectStore& glObjectStore) { if (hasData()) { - raster.upload(); + raster.upload(glObjectStore); uploaded = true; } } @@ -27,10 +27,10 @@ void RasterBucket::setImage(PremultipliedImage image) { raster.load(std::move(image)); } -void RasterBucket::drawRaster(RasterShader& shader, StaticVertexBuffer &vertices, VertexArrayObject &array) { - raster.bind(true); +void RasterBucket::drawRaster(RasterShader& shader, StaticVertexBuffer &vertices, VertexArrayObject &array, gl::GLObjectStore& glObjectStore) { + raster.bind(true, glObjectStore); shader.u_image = 0; - array.bind(shader, vertices, BUFFER_OFFSET_0); + array.bind(shader, vertices, BUFFER_OFFSET_0, glObjectStore); MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLES, 0, (GLsizei)vertices.index())); } diff --git a/src/mbgl/renderer/raster_bucket.hpp b/src/mbgl/renderer/raster_bucket.hpp index 0f6237969a..466a7602ed 100644 --- a/src/mbgl/renderer/raster_bucket.hpp +++ b/src/mbgl/renderer/raster_bucket.hpp @@ -12,15 +12,15 @@ class VertexArrayObject; class RasterBucket : public Bucket { public: - RasterBucket(TexturePool&); + RasterBucket(gl::TexturePool&); - void upload() override; + void upload(gl::GLObjectStore&) override; void render(Painter&, const StyleLayer&, const TileID&, const mat4&) override; bool hasData() const override; void setImage(PremultipliedImage); - void drawRaster(RasterShader& shader, StaticVertexBuffer &vertices, VertexArrayObject &array); + void drawRaster(RasterShader&, StaticVertexBuffer&, VertexArrayObject&, gl::GLObjectStore&); Raster raster; }; diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp index e4fccc22e9..683a6f4b11 100644 --- a/src/mbgl/renderer/symbol_bucket.cpp +++ b/src/mbgl/renderer/symbol_bucket.cpp @@ -1,6 +1,6 @@ #include <mbgl/renderer/symbol_bucket.hpp> #include <mbgl/layer/symbol_layer.hpp> -#include <mbgl/map/geometry_tile.hpp> +#include <mbgl/tile/geometry_tile.hpp> #include <mbgl/sprite/sprite_image.hpp> #include <mbgl/sprite/sprite_store.hpp> #include <mbgl/sprite/sprite_atlas.hpp> @@ -64,14 +64,14 @@ SymbolBucket::~SymbolBucket() { // Do not remove. header file only contains forward definitions to unique pointers. } -void SymbolBucket::upload() { +void SymbolBucket::upload(gl::GLObjectStore& glObjectStore) { if (hasTextData()) { - renderData->text.vertices.upload(); - renderData->text.triangles.upload(); + renderData->text.vertices.upload(glObjectStore); + renderData->text.triangles.upload(glObjectStore); } if (hasIconData()) { - renderData->icon.vertices.upload(); - renderData->icon.triangles.upload(); + renderData->icon.vertices.upload(glObjectStore); + renderData->icon.triangles.upload(glObjectStore); } uploaded = true; @@ -572,50 +572,50 @@ void SymbolBucket::swapRenderData() { } } -void SymbolBucket::drawGlyphs(SDFShader &shader) { +void SymbolBucket::drawGlyphs(SDFShader& shader, gl::GLObjectStore& glObjectStore) { GLbyte *vertex_index = BUFFER_OFFSET_0; GLbyte *elements_index = BUFFER_OFFSET_0; auto& text = renderData->text; for (auto &group : text.groups) { assert(group); - group->array[0].bind(shader, text.vertices, text.triangles, vertex_index); + group->array[0].bind(shader, text.vertices, text.triangles, vertex_index, glObjectStore); MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT, elements_index)); vertex_index += group->vertex_length * text.vertices.itemSize; elements_index += group->elements_length * text.triangles.itemSize; } } -void SymbolBucket::drawIcons(SDFShader &shader) { +void SymbolBucket::drawIcons(SDFShader& shader, gl::GLObjectStore& glObjectStore) { GLbyte *vertex_index = BUFFER_OFFSET_0; GLbyte *elements_index = BUFFER_OFFSET_0; auto& icon = renderData->icon; for (auto &group : icon.groups) { assert(group); - group->array[0].bind(shader, icon.vertices, icon.triangles, vertex_index); + group->array[0].bind(shader, icon.vertices, icon.triangles, vertex_index, glObjectStore); MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT, elements_index)); vertex_index += group->vertex_length * icon.vertices.itemSize; elements_index += group->elements_length * icon.triangles.itemSize; } } -void SymbolBucket::drawIcons(IconShader &shader) { +void SymbolBucket::drawIcons(IconShader& shader, gl::GLObjectStore& glObjectStore) { GLbyte *vertex_index = BUFFER_OFFSET_0; GLbyte *elements_index = BUFFER_OFFSET_0; auto& icon = renderData->icon; for (auto &group : icon.groups) { assert(group); - group->array[1].bind(shader, icon.vertices, icon.triangles, vertex_index); + group->array[1].bind(shader, icon.vertices, icon.triangles, vertex_index, glObjectStore); MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT, elements_index)); vertex_index += group->vertex_length * icon.vertices.itemSize; elements_index += group->elements_length * icon.triangles.itemSize; } } -void SymbolBucket::drawCollisionBoxes(CollisionBoxShader &shader) { +void SymbolBucket::drawCollisionBoxes(CollisionBoxShader& shader, gl::GLObjectStore& glObjectStore) { GLbyte *vertex_index = BUFFER_OFFSET_0; auto& collisionBox = renderData->collisionBox; for (auto &group : collisionBox.groups) { - group->array[0].bind(shader, collisionBox.vertices, vertex_index); + group->array[0].bind(shader, collisionBox.vertices, vertex_index, glObjectStore); MBGL_CHECK_ERROR(glDrawArrays(GL_LINES, 0, group->vertex_length)); } } diff --git a/src/mbgl/renderer/symbol_bucket.hpp b/src/mbgl/renderer/symbol_bucket.hpp index 5728cfa28c..cebb7e5dbe 100644 --- a/src/mbgl/renderer/symbol_bucket.hpp +++ b/src/mbgl/renderer/symbol_bucket.hpp @@ -2,7 +2,7 @@ #define MBGL_RENDERER_SYMBOLBUCKET #include <mbgl/renderer/bucket.hpp> -#include <mbgl/map/geometry_tile.hpp> +#include <mbgl/tile/geometry_tile.hpp> #include <mbgl/map/mode.hpp> #include <mbgl/geometry/vao.hpp> #include <mbgl/geometry/elements_buffer.hpp> @@ -70,7 +70,7 @@ public: SymbolBucket(float overscaling, float zoom, const MapMode); ~SymbolBucket() override; - void upload() override; + void upload(gl::GLObjectStore&) override; void render(Painter&, const StyleLayer&, const TileID&, const mat4&) override; bool hasData() const override; bool hasTextData() const; @@ -82,10 +82,10 @@ public: GlyphAtlas&, GlyphStore&); - void drawGlyphs(SDFShader& shader); - void drawIcons(SDFShader& shader); - void drawIcons(IconShader& shader); - void drawCollisionBoxes(CollisionBoxShader& shader); + void drawGlyphs(SDFShader&, gl::GLObjectStore&); + void drawIcons(SDFShader&, gl::GLObjectStore&); + void drawIcons(IconShader&, gl::GLObjectStore&); + void drawCollisionBoxes(CollisionBoxShader&, gl::GLObjectStore&); void parseFeatures(const GeometryTileLayer&, const FilterExpression&); diff --git a/src/mbgl/shader/box_shader.cpp b/src/mbgl/shader/box_shader.cpp index d9845ec36f..63f800ea69 100644 --- a/src/mbgl/shader/box_shader.cpp +++ b/src/mbgl/shader/box_shader.cpp @@ -1,16 +1,16 @@ #include <mbgl/shader/box_shader.hpp> #include <mbgl/shader/box.vertex.hpp> #include <mbgl/shader/box.fragment.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <cstdio> using namespace mbgl; -CollisionBoxShader::CollisionBoxShader() - : Shader("collisionbox", shaders::box::vertex, shaders::box::fragment) { - a_extrude = MBGL_CHECK_ERROR(glGetAttribLocation(program, "a_extrude")); - a_data = MBGL_CHECK_ERROR(glGetAttribLocation(program, "a_data")); +CollisionBoxShader::CollisionBoxShader(gl::GLObjectStore& glObjectStore) + : Shader("collisionbox", shaders::box::vertex, shaders::box::fragment, glObjectStore) { + a_extrude = MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_extrude")); + a_data = MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_data")); } void CollisionBoxShader::bind(GLbyte *offset) { diff --git a/src/mbgl/shader/box_shader.hpp b/src/mbgl/shader/box_shader.hpp index 19df2ca825..f3015b73a7 100644 --- a/src/mbgl/shader/box_shader.hpp +++ b/src/mbgl/shader/box_shader.hpp @@ -3,13 +3,13 @@ #include <mbgl/shader/shader.hpp> #include <mbgl/shader/uniform.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> namespace mbgl { class CollisionBoxShader : public Shader { public: - CollisionBoxShader(); + CollisionBoxShader(gl::GLObjectStore&); void bind(GLbyte *offset) final; diff --git a/src/mbgl/shader/circle_shader.cpp b/src/mbgl/shader/circle_shader.cpp index 0af5bcf604..3ec822747f 100644 --- a/src/mbgl/shader/circle_shader.cpp +++ b/src/mbgl/shader/circle_shader.cpp @@ -1,14 +1,14 @@ #include <mbgl/shader/circle_shader.hpp> #include <mbgl/shader/circle.vertex.hpp> #include <mbgl/shader/circle.fragment.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <cstdio> using namespace mbgl; -CircleShader::CircleShader() - : Shader("circle", shaders::circle::vertex, shaders::circle::fragment) { +CircleShader::CircleShader(gl::GLObjectStore& glObjectStore) + : Shader("circle", shaders::circle::vertex, shaders::circle::fragment, glObjectStore) { } void CircleShader::bind(GLbyte* offset) { diff --git a/src/mbgl/shader/circle_shader.hpp b/src/mbgl/shader/circle_shader.hpp index 7c1212c275..a28bf3c6ae 100644 --- a/src/mbgl/shader/circle_shader.hpp +++ b/src/mbgl/shader/circle_shader.hpp @@ -8,7 +8,7 @@ namespace mbgl { class CircleShader : public Shader { public: - CircleShader(); + CircleShader(gl::GLObjectStore&); void bind(GLbyte *offset) final; diff --git a/src/mbgl/shader/dot_shader.cpp b/src/mbgl/shader/dot_shader.cpp index 2eba489b66..9d60306da2 100644 --- a/src/mbgl/shader/dot_shader.cpp +++ b/src/mbgl/shader/dot_shader.cpp @@ -1,13 +1,14 @@ #include <mbgl/shader/dot_shader.hpp> #include <mbgl/shader/dot.vertex.hpp> #include <mbgl/shader/dot.fragment.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <cstdio> using namespace mbgl; -DotShader::DotShader() : Shader("dot", shaders::dot::vertex, shaders::dot::fragment) { +DotShader::DotShader(gl::GLObjectStore& glObjectStore) + : Shader("dot", shaders::dot::vertex, shaders::dot::fragment, glObjectStore) { } void DotShader::bind(GLbyte* offset) { diff --git a/src/mbgl/shader/dot_shader.hpp b/src/mbgl/shader/dot_shader.hpp index 606764c2d6..a015310a62 100644 --- a/src/mbgl/shader/dot_shader.hpp +++ b/src/mbgl/shader/dot_shader.hpp @@ -8,7 +8,7 @@ namespace mbgl { class DotShader : public Shader { public: - DotShader(); + DotShader(gl::GLObjectStore&); void bind(GLbyte *offset) final; diff --git a/src/mbgl/shader/icon_shader.cpp b/src/mbgl/shader/icon_shader.cpp index bb43cb3e4a..2ff653a87c 100644 --- a/src/mbgl/shader/icon_shader.cpp +++ b/src/mbgl/shader/icon_shader.cpp @@ -1,16 +1,17 @@ #include <mbgl/shader/icon_shader.hpp> #include <mbgl/shader/icon.vertex.hpp> #include <mbgl/shader/icon.fragment.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <cstdio> using namespace mbgl; -IconShader::IconShader() : Shader("icon", shaders::icon::vertex, shaders::icon::fragment) { - a_offset = MBGL_CHECK_ERROR(glGetAttribLocation(program, "a_offset")); - a_data1 = MBGL_CHECK_ERROR(glGetAttribLocation(program, "a_data1")); - a_data2 = MBGL_CHECK_ERROR(glGetAttribLocation(program, "a_data2")); +IconShader::IconShader(gl::GLObjectStore& glObjectStore) + : Shader("icon", shaders::icon::vertex, shaders::icon::fragment, glObjectStore) { + a_offset = MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_offset")); + a_data1 = MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_data1")); + a_data2 = MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_data2")); } void IconShader::bind(GLbyte* offset) { diff --git a/src/mbgl/shader/icon_shader.hpp b/src/mbgl/shader/icon_shader.hpp index 8a25b635fe..ec6311ea80 100644 --- a/src/mbgl/shader/icon_shader.hpp +++ b/src/mbgl/shader/icon_shader.hpp @@ -8,7 +8,7 @@ namespace mbgl { class IconShader : public Shader { public: - IconShader(); + IconShader(gl::GLObjectStore&); void bind(GLbyte *offset) final; diff --git a/src/mbgl/shader/line_shader.cpp b/src/mbgl/shader/line_shader.cpp index 54bc6c1148..e4df0531d8 100644 --- a/src/mbgl/shader/line_shader.cpp +++ b/src/mbgl/shader/line_shader.cpp @@ -1,14 +1,15 @@ #include <mbgl/shader/line_shader.hpp> #include <mbgl/shader/line.vertex.hpp> #include <mbgl/shader/line.fragment.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <cstdio> using namespace mbgl; -LineShader::LineShader() : Shader("line", shaders::line::vertex, shaders::line::fragment) { - a_data = MBGL_CHECK_ERROR(glGetAttribLocation(program, "a_data")); +LineShader::LineShader(gl::GLObjectStore& glObjectStore) + : Shader("line", shaders::line::vertex, shaders::line::fragment, glObjectStore) { + a_data = MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_data")); } void LineShader::bind(GLbyte* offset) { diff --git a/src/mbgl/shader/line_shader.hpp b/src/mbgl/shader/line_shader.hpp index 14e03c2eaf..1a9598f925 100644 --- a/src/mbgl/shader/line_shader.hpp +++ b/src/mbgl/shader/line_shader.hpp @@ -8,7 +8,7 @@ namespace mbgl { class LineShader : public Shader { public: - LineShader(); + LineShader(gl::GLObjectStore&); void bind(GLbyte *offset) final; diff --git a/src/mbgl/shader/linepattern_shader.cpp b/src/mbgl/shader/linepattern_shader.cpp index 9e71d0a9d9..7acd42f727 100644 --- a/src/mbgl/shader/linepattern_shader.cpp +++ b/src/mbgl/shader/linepattern_shader.cpp @@ -1,15 +1,15 @@ #include <mbgl/shader/linepattern_shader.hpp> #include <mbgl/shader/linepattern.vertex.hpp> #include <mbgl/shader/linepattern.fragment.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <cstdio> using namespace mbgl; -LinepatternShader::LinepatternShader() - : Shader("linepattern", shaders::linepattern::vertex, shaders::linepattern::fragment) { - a_data = MBGL_CHECK_ERROR(glGetAttribLocation(program, "a_data")); +LinepatternShader::LinepatternShader(gl::GLObjectStore& glObjectStore) + : Shader("linepattern", shaders::linepattern::vertex, shaders::linepattern::fragment, glObjectStore) { + a_data = MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_data")); } void LinepatternShader::bind(GLbyte* offset) { diff --git a/src/mbgl/shader/linepattern_shader.hpp b/src/mbgl/shader/linepattern_shader.hpp index 6c83cb0cc3..0d3e98c834 100644 --- a/src/mbgl/shader/linepattern_shader.hpp +++ b/src/mbgl/shader/linepattern_shader.hpp @@ -8,7 +8,7 @@ namespace mbgl { class LinepatternShader : public Shader { public: - LinepatternShader(); + LinepatternShader(gl::GLObjectStore&); void bind(GLbyte *offset) final; diff --git a/src/mbgl/shader/linesdf_shader.cpp b/src/mbgl/shader/linesdf_shader.cpp index df988bb337..00adaf0c86 100644 --- a/src/mbgl/shader/linesdf_shader.cpp +++ b/src/mbgl/shader/linesdf_shader.cpp @@ -1,15 +1,15 @@ #include <mbgl/shader/linesdf_shader.hpp> #include <mbgl/shader/linesdf.vertex.hpp> #include <mbgl/shader/linesdf.fragment.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <cstdio> using namespace mbgl; -LineSDFShader::LineSDFShader() - : Shader("line", shaders::linesdf::vertex, shaders::linesdf::fragment) { - a_data = MBGL_CHECK_ERROR(glGetAttribLocation(program, "a_data")); +LineSDFShader::LineSDFShader(gl::GLObjectStore& glObjectStore) + : Shader("line", shaders::linesdf::vertex, shaders::linesdf::fragment, glObjectStore) { + a_data = MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_data")); } void LineSDFShader::bind(GLbyte* offset) { diff --git a/src/mbgl/shader/linesdf_shader.hpp b/src/mbgl/shader/linesdf_shader.hpp index 2a8bdc6629..8ac0aa5793 100644 --- a/src/mbgl/shader/linesdf_shader.hpp +++ b/src/mbgl/shader/linesdf_shader.hpp @@ -8,7 +8,7 @@ namespace mbgl { class LineSDFShader : public Shader { public: - LineSDFShader(); + LineSDFShader(gl::GLObjectStore&); void bind(GLbyte *offset) final; diff --git a/src/mbgl/shader/outline_shader.cpp b/src/mbgl/shader/outline_shader.cpp index 9cda1a1108..8c7458327f 100644 --- a/src/mbgl/shader/outline_shader.cpp +++ b/src/mbgl/shader/outline_shader.cpp @@ -1,14 +1,14 @@ #include <mbgl/shader/outline_shader.hpp> #include <mbgl/shader/outline.vertex.hpp> #include <mbgl/shader/outline.fragment.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <cstdio> using namespace mbgl; -OutlineShader::OutlineShader() - : Shader("outline", shaders::outline::vertex, shaders::outline::fragment) { +OutlineShader::OutlineShader(gl::GLObjectStore& glObjectStore) + : Shader("outline", shaders::outline::vertex, shaders::outline::fragment, glObjectStore) { } void OutlineShader::bind(GLbyte* offset) { diff --git a/src/mbgl/shader/outline_shader.hpp b/src/mbgl/shader/outline_shader.hpp index 3af9b8349f..800461bf06 100644 --- a/src/mbgl/shader/outline_shader.hpp +++ b/src/mbgl/shader/outline_shader.hpp @@ -8,7 +8,7 @@ namespace mbgl { class OutlineShader : public Shader { public: - OutlineShader(); + OutlineShader(gl::GLObjectStore&); void bind(GLbyte *offset) final; diff --git a/src/mbgl/shader/pattern_shader.cpp b/src/mbgl/shader/pattern_shader.cpp index ef3f35c356..4f52df59fb 100644 --- a/src/mbgl/shader/pattern_shader.cpp +++ b/src/mbgl/shader/pattern_shader.cpp @@ -1,16 +1,17 @@ #include <mbgl/shader/pattern_shader.hpp> #include <mbgl/shader/pattern.vertex.hpp> #include <mbgl/shader/pattern.fragment.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <cstdio> using namespace mbgl; -PatternShader::PatternShader() +PatternShader::PatternShader(gl::GLObjectStore& glObjectStore) : Shader( "pattern", - shaders::pattern::vertex, shaders::pattern::fragment + shaders::pattern::vertex, shaders::pattern::fragment, + glObjectStore ) { } diff --git a/src/mbgl/shader/pattern_shader.hpp b/src/mbgl/shader/pattern_shader.hpp index db7901c578..8692f6ed39 100644 --- a/src/mbgl/shader/pattern_shader.hpp +++ b/src/mbgl/shader/pattern_shader.hpp @@ -8,7 +8,7 @@ namespace mbgl { class PatternShader : public Shader { public: - PatternShader(); + PatternShader(gl::GLObjectStore&); void bind(GLbyte *offset) final; diff --git a/src/mbgl/shader/plain_shader.cpp b/src/mbgl/shader/plain_shader.cpp index 1817ffbc3d..1b5a7819b3 100644 --- a/src/mbgl/shader/plain_shader.cpp +++ b/src/mbgl/shader/plain_shader.cpp @@ -1,13 +1,14 @@ #include <mbgl/shader/plain_shader.hpp> #include <mbgl/shader/plain.vertex.hpp> #include <mbgl/shader/plain.fragment.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <cstdio> using namespace mbgl; -PlainShader::PlainShader() : Shader("plain", shaders::plain::vertex, shaders::plain::fragment) { +PlainShader::PlainShader(gl::GLObjectStore& glObjectStore) + : Shader("plain", shaders::plain::vertex, shaders::plain::fragment, glObjectStore) { } void PlainShader::bind(GLbyte* offset) { diff --git a/src/mbgl/shader/plain_shader.hpp b/src/mbgl/shader/plain_shader.hpp index f9b8c41a63..34ee4dcdf7 100644 --- a/src/mbgl/shader/plain_shader.hpp +++ b/src/mbgl/shader/plain_shader.hpp @@ -8,7 +8,7 @@ namespace mbgl { class PlainShader : public Shader { public: - PlainShader(); + PlainShader(gl::GLObjectStore&); void bind(GLbyte *offset) final; diff --git a/src/mbgl/shader/raster_shader.cpp b/src/mbgl/shader/raster_shader.cpp index aaf0bfd2a5..77bcf40008 100644 --- a/src/mbgl/shader/raster_shader.cpp +++ b/src/mbgl/shader/raster_shader.cpp @@ -1,14 +1,14 @@ #include <mbgl/shader/raster_shader.hpp> #include <mbgl/shader/raster.vertex.hpp> #include <mbgl/shader/raster.fragment.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <cstdio> using namespace mbgl; -RasterShader::RasterShader() - : Shader("raster", shaders::raster::vertex, shaders::raster::fragment) { +RasterShader::RasterShader(gl::GLObjectStore& glObjectStore) + : Shader("raster", shaders::raster::vertex, shaders::raster::fragment, glObjectStore) { } void RasterShader::bind(GLbyte* offset) { diff --git a/src/mbgl/shader/raster_shader.hpp b/src/mbgl/shader/raster_shader.hpp index 60b283fc2a..6a2e2ecf3e 100644 --- a/src/mbgl/shader/raster_shader.hpp +++ b/src/mbgl/shader/raster_shader.hpp @@ -8,7 +8,7 @@ namespace mbgl { class RasterShader : public Shader { public: - RasterShader(); + RasterShader(gl::GLObjectStore&); void bind(GLbyte *offset) final; diff --git a/src/mbgl/shader/sdf_shader.cpp b/src/mbgl/shader/sdf_shader.cpp index 97297a7baf..a972849d3d 100644 --- a/src/mbgl/shader/sdf_shader.cpp +++ b/src/mbgl/shader/sdf_shader.cpp @@ -1,16 +1,17 @@ #include <mbgl/shader/sdf_shader.hpp> #include <mbgl/shader/sdf.vertex.hpp> #include <mbgl/shader/sdf.fragment.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <cstdio> using namespace mbgl; -SDFShader::SDFShader() : Shader("sdf", shaders::sdf::vertex, shaders::sdf::fragment) { - a_offset = MBGL_CHECK_ERROR(glGetAttribLocation(program, "a_offset")); - a_data1 = MBGL_CHECK_ERROR(glGetAttribLocation(program, "a_data1")); - a_data2 = MBGL_CHECK_ERROR(glGetAttribLocation(program, "a_data2")); +SDFShader::SDFShader(gl::GLObjectStore& glObjectStore) + : Shader("sdf", shaders::sdf::vertex, shaders::sdf::fragment, glObjectStore) { + a_offset = MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_offset")); + a_data1 = MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_data1")); + a_data2 = MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_data2")); } void SDFGlyphShader::bind(GLbyte* offset) { diff --git a/src/mbgl/shader/sdf_shader.hpp b/src/mbgl/shader/sdf_shader.hpp index 29dbfea047..402168de0c 100644 --- a/src/mbgl/shader/sdf_shader.hpp +++ b/src/mbgl/shader/sdf_shader.hpp @@ -8,7 +8,7 @@ namespace mbgl { class SDFShader : public Shader { public: - SDFShader(); + SDFShader(gl::GLObjectStore&); UniformMatrix<4> u_matrix = {"u_matrix", *this}; UniformMatrix<4> u_exmatrix = {"u_exmatrix", *this}; @@ -32,11 +32,13 @@ protected: class SDFGlyphShader : public SDFShader { public: + SDFGlyphShader(gl::GLObjectStore& glObjectStore) : SDFShader(glObjectStore) {} void bind(GLbyte *offset) final; }; class SDFIconShader : public SDFShader { public: + SDFIconShader(gl::GLObjectStore& glObjectStore) : SDFShader(glObjectStore) {} void bind(GLbyte *offset) final; }; diff --git a/src/mbgl/shader/shader.cpp b/src/mbgl/shader/shader.cpp index e8deefc8ff..8216de5b4d 100644 --- a/src/mbgl/shader/shader.cpp +++ b/src/mbgl/shader/shader.cpp @@ -1,5 +1,5 @@ #include <mbgl/shader/shader.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <mbgl/util/stopwatch.hpp> #include <mbgl/util/exception.hpp> #include <mbgl/platform/log.hpp> @@ -11,94 +11,74 @@ #include <fstream> #include <cstdio> -using namespace mbgl; +namespace mbgl { -Shader::Shader(const char *name_, const GLchar *vertSource, const GLchar *fragSource) +Shader::Shader(const char *name_, const GLchar *vertSource, const GLchar *fragSource, gl::GLObjectStore& glObjectStore) : name(name_) - , program(0) { util::stopwatch stopwatch("shader compilation", Event::Shader); - program = MBGL_CHECK_ERROR(glCreateProgram()); - - if (!compileShader(&vertShader, GL_VERTEX_SHADER, &vertSource)) { + program.create(glObjectStore); + vertexShader.create(glObjectStore); + if (!compileShader(vertexShader, &vertSource)) { Log::Error(Event::Shader, "Vertex shader %s failed to compile: %s", name, vertSource); - MBGL_CHECK_ERROR(glDeleteProgram(program)); - program = 0; throw util::ShaderException(std::string { "Vertex shader " } + name + " failed to compile"); } - if (!compileShader(&fragShader, GL_FRAGMENT_SHADER, &fragSource)) { + fragmentShader.create(glObjectStore); + if (!compileShader(fragmentShader, &fragSource)) { Log::Error(Event::Shader, "Fragment shader %s failed to compile: %s", name, fragSource); - MBGL_CHECK_ERROR(glDeleteShader(vertShader)); - vertShader = 0; - MBGL_CHECK_ERROR(glDeleteProgram(program)); - program = 0; throw util::ShaderException(std::string { "Fragment shader " } + name + " failed to compile"); } // Attach shaders - MBGL_CHECK_ERROR(glAttachShader(program, vertShader)); - MBGL_CHECK_ERROR(glAttachShader(program, fragShader)); + MBGL_CHECK_ERROR(glAttachShader(program.getID(), vertexShader.getID())); + MBGL_CHECK_ERROR(glAttachShader(program.getID(), fragmentShader.getID())); { // Link program GLint status; - MBGL_CHECK_ERROR(glLinkProgram(program)); + MBGL_CHECK_ERROR(glLinkProgram(program.getID())); - MBGL_CHECK_ERROR(glGetProgramiv(program, GL_LINK_STATUS, &status)); + MBGL_CHECK_ERROR(glGetProgramiv(program.getID(), GL_LINK_STATUS, &status)); if (status == 0) { GLint logLength; - MBGL_CHECK_ERROR(glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength)); + MBGL_CHECK_ERROR(glGetProgramiv(program.getID(), GL_INFO_LOG_LENGTH, &logLength)); const auto log = std::make_unique<GLchar[]>(logLength); if (logLength > 0) { - MBGL_CHECK_ERROR(glGetProgramInfoLog(program, logLength, &logLength, log.get())); + MBGL_CHECK_ERROR(glGetProgramInfoLog(program.getID(), logLength, &logLength, log.get())); Log::Error(Event::Shader, "Program failed to link: %s", log.get()); } - - MBGL_CHECK_ERROR(glDeleteShader(vertShader)); - vertShader = 0; - MBGL_CHECK_ERROR(glDeleteShader(fragShader)); - fragShader = 0; - MBGL_CHECK_ERROR(glDeleteProgram(program)); - program = 0; throw util::ShaderException(std::string { "Program " } + name + " failed to link: " + log.get()); } } - a_pos = MBGL_CHECK_ERROR(glGetAttribLocation(program, "a_pos")); + a_pos = MBGL_CHECK_ERROR(glGetAttribLocation(program.getID(), "a_pos")); } +bool Shader::compileShader(gl::ShaderHolder& shader, const GLchar *source[]) { + GLint status = 0; -bool Shader::compileShader(GLuint *shader, GLenum type, const GLchar *source[]) { - GLint status; - - *shader = MBGL_CHECK_ERROR(glCreateShader(type)); const GLsizei lengths = static_cast<GLsizei>(std::strlen(*source)); - MBGL_CHECK_ERROR(glShaderSource(*shader, 1, source, &lengths)); + MBGL_CHECK_ERROR(glShaderSource(shader.getID(), 1, source, &lengths)); - MBGL_CHECK_ERROR(glCompileShader(*shader)); + MBGL_CHECK_ERROR(glCompileShader(shader.getID())); - MBGL_CHECK_ERROR(glGetShaderiv(*shader, GL_COMPILE_STATUS, &status)); + MBGL_CHECK_ERROR(glGetShaderiv(shader.getID(), GL_COMPILE_STATUS, &status)); if (status == 0) { GLint logLength; - MBGL_CHECK_ERROR(glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength)); + MBGL_CHECK_ERROR(glGetShaderiv(shader.getID(), GL_INFO_LOG_LENGTH, &logLength)); if (logLength > 0) { const auto log = std::make_unique<GLchar[]>(logLength); - MBGL_CHECK_ERROR(glGetShaderInfoLog(*shader, logLength, &logLength, log.get())); + MBGL_CHECK_ERROR(glGetShaderInfoLog(shader.getID(), logLength, &logLength, log.get())); Log::Error(Event::Shader, "Shader failed to compile: %s", log.get()); } - - MBGL_CHECK_ERROR(glDeleteShader(*shader)); - *shader = 0; return false; } - MBGL_CHECK_ERROR(glGetShaderiv(*shader, GL_COMPILE_STATUS, &status)); + MBGL_CHECK_ERROR(glGetShaderiv(shader.getID(), GL_COMPILE_STATUS, &status)); if (status == GL_FALSE) { Log::Error(Event::Shader, "Shader %s failed to compile.", name); - MBGL_CHECK_ERROR(glDeleteShader(*shader)); - *shader = 0; return false; } @@ -107,13 +87,9 @@ bool Shader::compileShader(GLuint *shader, GLenum type, const GLchar *source[]) Shader::~Shader() { if (program) { - MBGL_CHECK_ERROR(glDetachShader(program, vertShader)); - MBGL_CHECK_ERROR(glDetachShader(program, fragShader)); - MBGL_CHECK_ERROR(glDeleteProgram(program)); - program = 0; - MBGL_CHECK_ERROR(glDeleteShader(vertShader)); - vertShader = 0; - MBGL_CHECK_ERROR(glDeleteShader(fragShader)); - fragShader = 0; + MBGL_CHECK_ERROR(glDetachShader(program.getID(), vertexShader.getID())); + MBGL_CHECK_ERROR(glDetachShader(program.getID(), fragmentShader.getID())); } } + +} // namespace mbgl diff --git a/src/mbgl/shader/shader.hpp b/src/mbgl/shader/shader.hpp index 927fdf0b0b..b543f73a6f 100644 --- a/src/mbgl/shader/shader.hpp +++ b/src/mbgl/shader/shader.hpp @@ -1,25 +1,21 @@ #ifndef MBGL_RENDERER_SHADER #define MBGL_RENDERER_SHADER -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> +#include <mbgl/gl/gl_object_store.hpp> #include <mbgl/util/noncopyable.hpp> -#include <cstdint> -#include <array> -#include <string> - namespace mbgl { class Shader : private util::noncopyable { public: - Shader(const GLchar *name, const GLchar *vertex, const GLchar *fragment); + Shader(const GLchar *name, const GLchar *vertex, const GLchar *fragment, gl::GLObjectStore&); ~Shader(); const GLchar *name; - GLuint program; - inline GLuint getID() const { - return program; + GLuint getID() const { + return program.getID(); } virtual void bind(GLbyte *offset) = 0; @@ -28,10 +24,11 @@ protected: GLint a_pos = -1; private: - bool compileShader(GLuint *shader, GLenum type, const GLchar *source[]); + bool compileShader(gl::ShaderHolder&, const GLchar *source[]); - GLuint vertShader = 0; - GLuint fragShader = 0; + gl::ProgramHolder program; + gl::ShaderHolder vertexShader = { GL_VERTEX_SHADER }; + gl::ShaderHolder fragmentShader = { GL_FRAGMENT_SHADER }; }; } // namespace mbgl diff --git a/src/mbgl/shader/uniform.hpp b/src/mbgl/shader/uniform.hpp index 0b6d574d09..5c4a2b14c4 100644 --- a/src/mbgl/shader/uniform.hpp +++ b/src/mbgl/shader/uniform.hpp @@ -2,7 +2,9 @@ #define MBGL_SHADER_UNIFORM #include <mbgl/shader/shader.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> + +#include <array> namespace mbgl { @@ -10,7 +12,7 @@ template <typename T> class Uniform { public: Uniform(const GLchar* name, const Shader& shader) : current() { - location = MBGL_CHECK_ERROR(glGetUniformLocation(shader.program, name)); + location = MBGL_CHECK_ERROR(glGetUniformLocation(shader.getID(), name)); } void operator=(const T& t) { @@ -33,7 +35,7 @@ public: typedef std::array<float, C*R> T; UniformMatrix(const GLchar* name, const Shader& shader) : current() { - location = MBGL_CHECK_ERROR(glGetUniformLocation(shader.program, name)); + location = MBGL_CHECK_ERROR(glGetUniformLocation(shader.getID(), name)); } void operator=(const std::array<double, C*R>& t) { diff --git a/src/mbgl/map/source.cpp b/src/mbgl/source/source.cpp index 7f9b47440b..8947e4f988 100644 --- a/src/mbgl/map/source.cpp +++ b/src/mbgl/source/source.cpp @@ -1,8 +1,8 @@ -#include <mbgl/map/source.hpp> +#include <mbgl/source/source.hpp> #include <mbgl/map/map_data.hpp> #include <mbgl/map/transform.hpp> -#include <mbgl/map/tile.hpp> -#include <mbgl/map/vector_tile.hpp> +#include <mbgl/tile/tile.hpp> +#include <mbgl/tile/vector_tile.hpp> #include <mbgl/annotation/annotation_tile.hpp> #include <mbgl/tile/geojson_tile.hpp> #include <mbgl/renderer/painter.hpp> @@ -11,8 +11,6 @@ #include <mbgl/storage/resource.hpp> #include <mbgl/storage/response.hpp> #include <mbgl/util/math.hpp> -#include <mbgl/util/box.hpp> -#include <mbgl/util/tile_coordinate.hpp> #include <mbgl/storage/file_source.hpp> #include <mbgl/style/style_layer.hpp> #include <mbgl/style/style_update_parameters.hpp> @@ -22,8 +20,8 @@ #include <mbgl/util/string.hpp> #include <mbgl/util/tile_cover.hpp> -#include <mbgl/map/vector_tile_data.hpp> -#include <mbgl/map/raster_tile_data.hpp> +#include <mbgl/tile/vector_tile_data.hpp> +#include <mbgl/tile/raster_tile_data.hpp> #include <mbgl/style/style.hpp> #include <mbgl/style/style_parser.hpp> #include <mbgl/gl/debugging.hpp> @@ -70,10 +68,7 @@ bool Source::isLoading() const { return !loaded && req.operator bool(); } -// Note: This is a separate function that must be called exactly once after creation -// The reason this isn't part of the constructor is that calling shared_from_this() in -// the constructor fails. -void Source::load() { +void Source::load(FileSource& fileSource) { if (url.empty()) { // In case there is no URL set, we assume that we already have all of the data because the // TileJSON was specified inline in the stylesheet. @@ -88,80 +83,77 @@ void Source::load() { } // URL may either be a TileJSON file, or a GeoJSON file. - FileSource* fs = util::ThreadContext::getFileSource(); - req = fs->request(Resource::source(url), [this](Response res) { + req = fileSource.request(Resource::source(url), [this](Response res) { if (res.error) { observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error(res.error->message))); + } else if (res.notModified) { return; - } + } else if (res.noContent) { + observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error("unexpectedly empty source"))); + } else { + bool reloadTiles = false; + + if (type == SourceType::Vector || type == SourceType::Raster) { + std::unique_ptr<SourceInfo> newInfo; + + // Create a new copy of the SourceInfo object that holds the base values we've parsed + // from the stylesheet. Then merge in the values parsed from the TileJSON we retrieved + // via the URL. + try { + newInfo = StyleParser::parseTileJSON(*res.data, url, type, tileSize); + } catch (...) { + observer->onSourceError(*this, std::current_exception()); + return; + } - if (res.notModified) { - // We got the same data back as last time. Abort early. - return; - } + // Check whether previous information specifies different tile + if (info && info->tiles != newInfo->tiles) { + reloadTiles = true; - bool reloadTiles = false; + // Tile size changed: We need to recalculate the tiles we need to load because we + // might have to load tiles for a different zoom level + // This is done automatically when we trigger the onSourceLoaded observer below. - if (type == SourceType::Vector || type == SourceType::Raster) { - std::unique_ptr<SourceInfo> newInfo; + // Min/Max zoom changed: We need to recalculate what tiles to load, if we have tiles + // loaded that are outside the new zoom range + // This is done automatically when we trigger the onSourceLoaded observer below. - // Create a new copy of the SourceInfo object that holds the base values we've parsed - // from the stylesheet. Then merge in the values parsed from the TileJSON we retrieved - // via the URL. - try { - newInfo = StyleParser::parseTileJSON(*res.data, url, type); - } catch (...) { - observer->onSourceError(*this, std::current_exception()); - return; - } + // Attribution changed: We need to notify the embedding application that this + // changed. See https://github.com/mapbox/mapbox-gl-native/issues/2723 + // This is not yet implemented. - // Check whether previous information specifies different tile - if (info && info->tiles != newInfo->tiles) { - reloadTiles = true; + // Center/bounds changed: We're not using these values currently + } - // Tile size changed: We need to recalculate the tiles we need to load because we - // might have to load tiles for a different zoom level - // This is done automatically when we trigger the onSourceLoaded observer below. + info = std::move(newInfo); + } else if (type == SourceType::GeoJSON) { + info = std::make_unique<SourceInfo>(); - // Min/Max zoom changed: We need to recalculate what tiles to load, if we have tiles - // loaded that are outside the new zoom range - // This is done automatically when we trigger the onSourceLoaded observer below. + rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> d; + d.Parse<0>(res.data->c_str()); - // Attribution changed: We need to notify the embedding application that this - // changed. See https://github.com/mapbox/mapbox-gl-native/issues/2723 - // This is not yet implemented. + if (d.HasParseError()) { + std::stringstream message; + message << d.GetErrorOffset() << " - " << rapidjson::GetParseError_En(d.GetParseError()); + observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error(message.str()))); + return; + } - // Center/bounds changed: We're not using these values currently + geojsonvt = StyleParser::parseGeoJSON(d); + reloadTiles = true; } - info = std::move(newInfo); - } else if (type == SourceType::GeoJSON) { - info = std::make_unique<SourceInfo>(); - - rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> d; - d.Parse<0>(res.data->c_str()); - - if (d.HasParseError()) { - std::stringstream message; - message << d.GetErrorOffset() << " - " << rapidjson::GetParseError_En(d.GetParseError()); - observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error(message.str()))); - return; + if (reloadTiles) { + // Tile information changed because we got new GeoJSON data, or a new tile URL. + tilePtrs.clear(); + tileDataMap.clear(); + tiles.clear(); + cache.clear(); } - geojsonvt = StyleParser::parseGeoJSON(d); - reloadTiles = true; - } - - if (reloadTiles) { - // Tile information changed because we got new GeoJSON data, or a new tile URL. - tilePtrs.clear(); - tileDataMap.clear(); - tiles.clear(); - cache.clear(); + loaded = true; + observer->onSourceLoaded(*this); } - - loaded = true; - observer->onSourceLoaded(*this); }); } @@ -173,14 +165,6 @@ void Source::updateMatrices(const mat4 &projMatrix, const TransformState &transf } } -void Source::drawClippingMasks(Painter &painter) { - for (const auto& pair : tiles) { - Tile &tile = *pair.second; - MBGL_DEBUG_GROUP(std::string { "mask: " } + std::string(tile.id)); - painter.drawClippingMask(tile.matrix, tile.clip); - } -} - void Source::finishRender(Painter &painter) { for (const auto& pair : tiles) { Tile &tile = *pair.second; @@ -271,12 +255,13 @@ TileData::State Source::addTile(const TileID& tileID, const StyleUpdateParameter info->tiles.at(0), parameters.texturePool, parameters.worker, + parameters.fileSource, callback); } else { std::unique_ptr<GeometryTileMonitor> monitor; if (type == SourceType::Vector) { - monitor = std::make_unique<VectorTileMonitor>(normalizedID, parameters.pixelRatio, info->tiles.at(0)); + monitor = std::make_unique<VectorTileMonitor>(normalizedID, parameters.pixelRatio, info->tiles.at(0), parameters.fileSource); } else if (type == SourceType::Annotations) { monitor = std::make_unique<AnnotationTileMonitor>(normalizedID, parameters.data); } else if (type == SourceType::GeoJSON) { @@ -302,47 +287,6 @@ TileData::State Source::addTile(const TileID& tileID, const StyleUpdateParameter return newState; } -double Source::getZoom(const TransformState& state) const { - double offset = std::log(util::tileSize / tileSize) / std::log(2); - return state.getZoom() + offset; -} - -int32_t Source::coveringZoomLevel(const TransformState& state) const { - double zoom = getZoom(state); - if (type == SourceType::Raster || type == SourceType::Video) { - zoom = ::round(zoom); - } else { - zoom = std::floor(zoom); - } - return util::clamp(zoom, state.getMinZoom(), state.getMaxZoom()); -} - -std::forward_list<TileID> Source::coveringTiles(const TransformState& state) const { - int32_t z = coveringZoomLevel(state); - - auto actualZ = z; - const bool reparseOverscaled = - type == SourceType::Vector || - type == SourceType::Annotations; - - if (z < info->minZoom) return {{}}; - if (z > info->maxZoom) z = info->maxZoom; - - // Map four viewport corners to pixel coordinates - box points = state.cornersToBox(z); - const TileCoordinate center = state.pointToCoordinate({ state.getWidth() / 2.0f, state.getHeight()/ 2.0f }).zoomTo(z); - - std::forward_list<TileID> covering_tiles = tileCover(z, points, reparseOverscaled ? actualZ : z); - - covering_tiles.sort([¢er](const TileID& a, const TileID& b) { - // Sorts by distance from the box center - return std::fabs(a.x - center.column) + std::fabs(a.y - center.row) < - std::fabs(b.x - center.column) + std::fabs(b.y - center.row); - }); - - return covering_tiles; -} - /** * Recursively find children of the given tile that are already loaded. * @@ -352,14 +296,14 @@ std::forward_list<TileID> Source::coveringTiles(const TransformState& state) con * * @return boolean Whether the children found completely cover the tile. */ -bool Source::findLoadedChildren(const TileID& tileID, int32_t maxCoveringZoom, std::forward_list<TileID>& retain) { +bool Source::findLoadedChildren(const TileID& tileID, int32_t maxCoveringZoom, std::vector<TileID>& retain) { bool complete = true; int32_t z = tileID.z; auto ids = tileID.children(info->maxZoom); for (const auto& child_id : ids) { const TileData::State state = hasTile(child_id); if (TileData::isReadyState(state)) { - retain.emplace_front(child_id); + retain.emplace_back(child_id); } if (state != TileData::State::parsed) { complete = false; @@ -381,12 +325,12 @@ bool Source::findLoadedChildren(const TileID& tileID, int32_t maxCoveringZoom, s * * @return boolean Whether a parent was found. */ -void Source::findLoadedParent(const TileID& tileID, int32_t minCoveringZoom, std::forward_list<TileID>& retain) { +void Source::findLoadedParent(const TileID& tileID, int32_t minCoveringZoom, std::vector<TileID>& retain) { for (int32_t z = tileID.z - 1; z >= minCoveringZoom; --z) { const TileID parent_id = tileID.parent(z, info->maxZoom); const TileData::State state = hasTile(parent_id); if (TileData::isReadyState(state)) { - retain.emplace_front(parent_id); + retain.emplace_back(parent_id); if (state == TileData::State::parsed) { return; } @@ -401,17 +345,29 @@ bool Source::update(const StyleUpdateParameters& parameters) { return allTilesUpdated; } - double zoom = coveringZoomLevel(parameters.transformState); - std::forward_list<TileID> required = coveringTiles(parameters.transformState); - - // Determine the overzooming/underzooming amounts. + // Determine the overzooming/underzooming amounts and required tiles. + std::vector<TileID> required; + int32_t zoom = coveringZoomLevel(parameters.transformState.getZoom(), type, tileSize); int32_t minCoveringZoom = util::clamp<int32_t>(zoom - 10, info->minZoom, info->maxZoom); int32_t maxCoveringZoom = util::clamp<int32_t>(zoom + 1, info->minZoom, info->maxZoom); + if (zoom >= info->minZoom) { + const bool reparseOverscaled = + type == SourceType::Vector || + type == SourceType::Annotations; + + const auto actualZ = zoom; + if (zoom > info->maxZoom) { + zoom = info->maxZoom; + } + + required = tileCover(parameters.transformState, zoom, reparseOverscaled ? actualZ : zoom); + } + // Retain is a list of tiles that we shouldn't delete, even if they are not // the most ideal tile for the current viewport. This may include tiles like // parent or child tiles that are *already* loaded. - std::forward_list<TileID> retain(required); + std::vector<TileID> retain(required); // Add existing child/parent tiles if the actual tile is not yet loaded for (const auto& tileID : required) { diff --git a/src/mbgl/map/source.hpp b/src/mbgl/source/source.hpp index d9146c1fdb..52c7d76baf 100644 --- a/src/mbgl/map/source.hpp +++ b/src/mbgl/source/source.hpp @@ -1,13 +1,15 @@ #ifndef MBGL_MAP_SOURCE #define MBGL_MAP_SOURCE -#include <mbgl/map/tile_cache.hpp> -#include <mbgl/map/source_info.hpp> +#include <mbgl/tile/tile_data.hpp> +#include <mbgl/tile/tile_cache.hpp> +#include <mbgl/source/source_info.hpp> #include <mbgl/util/mat4.hpp> #include <mbgl/util/rapidjson.hpp> #include <forward_list> +#include <vector> #include <map> namespace mapbox { @@ -20,6 +22,7 @@ namespace mbgl { class StyleUpdateParameters; class Painter; +class FileSource; class FileRequest; class TransformState; class Tile; @@ -49,10 +52,12 @@ public: ~Source(); bool loaded = false; - void load(); + void load(FileSource&); bool isLoading() const; bool isLoaded() const; + const SourceInfo* getInfo() const { return info.get(); } + // Request or parse all the tiles relevant for the "TransformState". This method // will return true if all the tiles were scheduled for updating of false if // they were not. shouldReparsePartialTiles must be set to "true" if there is @@ -60,7 +65,6 @@ public: bool update(const StyleUpdateParameters&); void updateMatrices(const mat4 &projMatrix, const TransformState &transform); - void drawClippingMasks(Painter &painter); void finishRender(Painter &painter); std::forward_list<Tile *> getLoadedTiles() const; @@ -83,17 +87,13 @@ private: std::exception_ptr, bool isNewTile); bool handlePartialTile(const TileID&); - bool findLoadedChildren(const TileID&, int32_t maxCoveringZoom, std::forward_list<TileID>& retain); - void findLoadedParent(const TileID&, int32_t minCoveringZoom, std::forward_list<TileID>& retain); - int32_t coveringZoomLevel(const TransformState&) const; - std::forward_list<TileID> coveringTiles(const TransformState&) const; + bool findLoadedChildren(const TileID&, int32_t maxCoveringZoom, std::vector<TileID>& retain); + void findLoadedParent(const TileID&, int32_t minCoveringZoom, std::vector<TileID>& retain); TileData::State addTile(const TileID&, const StyleUpdateParameters&); TileData::State hasTile(const TileID&); void updateTilePtrs(); - double getZoom(const TransformState &state) const; - private: std::unique_ptr<const SourceInfo> info; diff --git a/src/mbgl/map/source_info.hpp b/src/mbgl/source/source_info.hpp index 2fb5c2466d..2fb5c2466d 100644 --- a/src/mbgl/map/source_info.hpp +++ b/src/mbgl/source/source_info.hpp diff --git a/src/mbgl/sprite/sprite_atlas.cpp b/src/mbgl/sprite/sprite_atlas.cpp index be5c59c74c..12d12a53cb 100644 --- a/src/mbgl/sprite/sprite_atlas.cpp +++ b/src/mbgl/sprite/sprite_atlas.cpp @@ -1,9 +1,8 @@ #include <mbgl/sprite/sprite_atlas.hpp> #include <mbgl/sprite/sprite_store.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <mbgl/platform/log.hpp> #include <mbgl/platform/platform.hpp> -#include <mbgl/util/gl_object_store.hpp> #include <mbgl/util/math.hpp> #include <mbgl/util/std.hpp> #include <mbgl/util/constants.hpp> @@ -144,9 +143,9 @@ void SpriteAtlas::copy(const Holder& holder, const bool wrap) { dirty = true; } -void SpriteAtlas::upload() { +void SpriteAtlas::upload(gl::GLObjectStore& glObjectStore) { if (dirty) { - bind(); + bind(false, glObjectStore); } } @@ -181,14 +180,14 @@ void SpriteAtlas::updateDirty() { } } -void SpriteAtlas::bind(bool linear) { +void SpriteAtlas::bind(bool linear, gl::GLObjectStore& glObjectStore) { if (!data) { return; // Empty atlas } if (!texture) { - MBGL_CHECK_ERROR(glGenTextures(1, &texture)); - MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture)); + texture.create(glObjectStore); + MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture.getID())); #ifndef GL_ES_VERSION_2_0 MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0)); #endif @@ -198,7 +197,7 @@ void SpriteAtlas::bind(bool linear) { MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); fullUploadRequired = true; } else { - MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture)); + MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture.getID())); } GLuint filter_val = linear ? GL_LINEAR : GL_NEAREST; @@ -247,13 +246,7 @@ void SpriteAtlas::bind(bool linear) { } }; -SpriteAtlas::~SpriteAtlas() { - std::lock_guard<std::recursive_mutex> lock(mtx); - if (texture) { - mbgl::util::ThreadContext::getGLObjectStore()->abandonTexture(texture); - texture = 0; - } -} +SpriteAtlas::~SpriteAtlas() = default; SpriteAtlas::Holder::Holder(const std::shared_ptr<const SpriteImage>& spriteImage_, const Rect<dimension>& pos_) diff --git a/src/mbgl/sprite/sprite_atlas.hpp b/src/mbgl/sprite/sprite_atlas.hpp index 73b3037ec6..ba592c5acb 100644 --- a/src/mbgl/sprite/sprite_atlas.hpp +++ b/src/mbgl/sprite/sprite_atlas.hpp @@ -2,7 +2,8 @@ #define MBGL_SPRITE_ATLAS #include <mbgl/geometry/binpack.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> +#include <mbgl/gl/gl_object_store.hpp> #include <mbgl/util/noncopyable.hpp> #include <mbgl/util/ptr.hpp> #include <mbgl/util/optional.hpp> @@ -51,14 +52,14 @@ public: optional<SpriteAtlasPosition> getPosition(const std::string& name, bool repeating = false); // Binds the atlas texture to the GPU, and uploads data if it is out of date. - void bind(bool linear = false); + void bind(bool linear, gl::GLObjectStore&); // Updates sprites in the atlas texture that may have changed in the source SpriteStore object. void updateDirty(); // 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(); + void upload(gl::GLObjectStore&); inline dimension getWidth() const { return width; } inline dimension getHeight() const { return height; } @@ -94,7 +95,7 @@ private: std::unique_ptr<uint32_t[]> data; std::atomic<bool> dirty; bool fullUploadRequired = true; - GLuint texture = 0; + gl::TextureHolder texture; uint32_t filter = 0; static const int buffer = 1; }; diff --git a/src/mbgl/sprite/sprite_store.cpp b/src/mbgl/sprite/sprite_store.cpp index 15a345cc4d..869abab39f 100644 --- a/src/mbgl/sprite/sprite_store.cpp +++ b/src/mbgl/sprite/sprite_store.cpp @@ -5,7 +5,6 @@ #include <mbgl/storage/resource.hpp> #include <mbgl/storage/response.hpp> #include <mbgl/util/exception.hpp> -#include <mbgl/util/thread_context.hpp> #include <cassert> #include <string> @@ -25,7 +24,7 @@ SpriteStore::SpriteStore(float pixelRatio_) SpriteStore::~SpriteStore() = default; -void SpriteStore::setURL(const std::string& url) { +void SpriteStore::load(const std::string& url, FileSource& fileSource) { if (url.empty()) { // Treat a non-existent sprite as a successfully loaded empty sprite. loaded = true; @@ -34,37 +33,30 @@ void SpriteStore::setURL(const std::string& url) { loader = std::make_unique<Loader>(); - FileSource* fs = util::ThreadContext::getFileSource(); - loader->jsonRequest = fs->request(Resource::spriteJSON(url, pixelRatio), [this](Response res) { + loader->jsonRequest = fileSource.request(Resource::spriteJSON(url, pixelRatio), [this](Response res) { if (res.error) { observer->onSpriteError(std::make_exception_ptr(std::runtime_error(res.error->message))); + } else if (res.notModified) { return; - } - - if (res.notModified) { - // We got the same data back as last time. Abort early. - return; - } - - if (!loader->json || *loader->json != *res.data) { + } else if (res.noContent) { + loader->json = std::make_shared<const std::string>(); + emitSpriteLoadedIfComplete(); + } else { // Only trigger a sprite loaded event we got new data. loader->json = res.data; emitSpriteLoadedIfComplete(); } }); - loader->spriteRequest = fs->request(Resource::spriteImage(url, pixelRatio), [this](Response res) { + loader->spriteRequest = fileSource.request(Resource::spriteImage(url, pixelRatio), [this](Response res) { if (res.error) { observer->onSpriteError(std::make_exception_ptr(std::runtime_error(res.error->message))); + } else if (res.notModified) { return; - } - - if (res.notModified) { - // We got the same data back as last time. Abort early. - return; - } - - if (!loader->image || *loader->image != *res.data) { + } else if (res.noContent) { + loader->image = std::make_shared<const std::string>(); + emitSpriteLoadedIfComplete(); + } else { loader->image = res.data; emitSpriteLoadedIfComplete(); } diff --git a/src/mbgl/sprite/sprite_store.hpp b/src/mbgl/sprite/sprite_store.hpp index 7c5fe71802..995cb81900 100644 --- a/src/mbgl/sprite/sprite_store.hpp +++ b/src/mbgl/sprite/sprite_store.hpp @@ -10,6 +10,8 @@ namespace mbgl { +class FileSource; + class SpriteStore : private util::noncopyable { public: using Sprites = std::map<std::string, std::shared_ptr<const SpriteImage>>; @@ -25,7 +27,7 @@ public: SpriteStore(float pixelRatio); ~SpriteStore(); - void setURL(const std::string&); + void load(const std::string& url, FileSource&); bool isLoaded() const { return loaded; diff --git a/src/mbgl/storage/http_context_base.hpp b/src/mbgl/storage/http_context_base.hpp index b50bf11ec7..6615ea00cf 100644 --- a/src/mbgl/storage/http_context_base.hpp +++ b/src/mbgl/storage/http_context_base.hpp @@ -11,6 +11,7 @@ namespace mbgl { class HTTPContextBase { public: static std::unique_ptr<HTTPContextBase> createContext(); + static uint32_t maximumConcurrentRequests(); virtual ~HTTPContextBase() = default; virtual HTTPRequestBase* createRequest(const Resource&, HTTPRequestBase::Callback) = 0; diff --git a/src/mbgl/storage/resource.cpp b/src/mbgl/storage/resource.cpp index 6f727a6027..d5b88d9292 100644 --- a/src/mbgl/storage/resource.cpp +++ b/src/mbgl/storage/resource.cpp @@ -49,6 +49,7 @@ Resource Resource::glyphs(const std::string& urlTemplate, const std::string& fon } Resource Resource::tile(const std::string& urlTemplate, float pixelRatio, int32_t x, int32_t y, int8_t z) { + bool supportsRatio = urlTemplate.find("{ratio}") != std::string::npos; return Resource { Resource::Kind::Tile, util::replaceTokens(urlTemplate, [&](const std::string& token) { @@ -71,7 +72,7 @@ Resource Resource::tile(const std::string& urlTemplate, float pixelRatio, int32_ }), Resource::TileData { urlTemplate, - uint8_t(pixelRatio > 1.0 ? 2 : 1), + uint8_t(supportsRatio && pixelRatio > 1.0 ? 2 : 1), x, y, z diff --git a/src/mbgl/storage/response.cpp b/src/mbgl/storage/response.cpp index 22263d2ebb..644d73d286 100644 --- a/src/mbgl/storage/response.cpp +++ b/src/mbgl/storage/response.cpp @@ -1,6 +1,9 @@ #include <mbgl/storage/response.hpp> #include <mbgl/util/chrono.hpp> +#include <iostream> +#include <cassert> + namespace mbgl { Response::Response(const Response& res) { @@ -9,6 +12,7 @@ Response::Response(const Response& res) { Response& Response::operator=(const Response& res) { error = res.error ? std::make_unique<Error>(*res.error) : nullptr; + noContent = res.noContent; notModified = res.notModified; data = res.data; modified = res.modified; @@ -21,4 +25,23 @@ Response::Error::Error(Reason reason_, const std::string& message_) : reason(reason_), message(message_) { } +std::ostream& operator<<(std::ostream& os, Response::Error::Reason r) { + switch (r) { + case Response::Error::Reason::Success: + return os << "Response::Error::Reason::NotFound"; + case Response::Error::Reason::NotFound: + return os << "Response::Error::Reason::NotFound"; + case Response::Error::Reason::Server: + return os << "Response::Error::Reason::Server"; + case Response::Error::Reason::Connection: + return os << "Response::Error::Reason::Connection"; + case Response::Error::Reason::Other: + return os << "Response::Error::Reason::Other"; + } + + // The above switch is exhaustive, but placate GCC nonetheless: + assert(false); + return os; +} + } // namespace mbgl diff --git a/src/mbgl/storage/sqlite_cache.hpp b/src/mbgl/storage/sqlite_cache.hpp deleted file mode 100644 index b5a7cbcc07..0000000000 --- a/src/mbgl/storage/sqlite_cache.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef MBGL_STORAGE_DEFAULT_SQLITE_CACHE -#define MBGL_STORAGE_DEFAULT_SQLITE_CACHE - -#include <mbgl/util/noncopyable.hpp> -#include <mbgl/util/chrono.hpp> - -#include <functional> -#include <memory> -#include <string> - -namespace mbgl { - -class Resource; -class Response; -class WorkRequest; - -namespace util { -template <typename T> class Thread; -} // namespace util - -class SQLiteCache : private util::noncopyable { -public: - static std::shared_ptr<SQLiteCache> getShared(const std::string &path = ":memory:"); - - SQLiteCache(const std::string &path = ":memory:"); - ~SQLiteCache(); - - void setMaximumCacheSize(uint64_t size); - void setMaximumCacheEntrySize(uint64_t size); - - using Callback = std::function<void(std::unique_ptr<Response>)>; - - std::unique_ptr<WorkRequest> get(const Resource&, Callback); - void put(const Resource&, const Response&); - - class Impl; - -private: - const std::unique_ptr<util::Thread<Impl>> thread; -}; - -} // namespace mbgl - -#endif diff --git a/src/mbgl/style/filter_expression.cpp b/src/mbgl/style/filter_expression.cpp index e8231b82e0..660c978f0d 100644 --- a/src/mbgl/style/filter_expression.cpp +++ b/src/mbgl/style/filter_expression.cpp @@ -1,5 +1,5 @@ #include <mbgl/style/filter_expression.hpp> -#include <mbgl/map/geometry_tile.hpp> +#include <mbgl/tile/geometry_tile.hpp> #include <mbgl/platform/log.hpp> namespace mbgl { diff --git a/src/mbgl/style/function.hpp b/src/mbgl/style/function.hpp index 4d2e4fcbd7..160f5be390 100644 --- a/src/mbgl/style/function.hpp +++ b/src/mbgl/style/function.hpp @@ -27,6 +27,9 @@ public: T evaluate(const StyleCalculationParameters&) const; + float getBase() const { return base; } + const std::vector<std::pair<float, T>>& getStops() const { return stops; } + private: float base = 1; std::vector<std::pair<float, T>> stops; diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index 1ffd75bf69..e5ba08e57f 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -1,7 +1,7 @@ #include <mbgl/style/style.hpp> #include <mbgl/map/map_data.hpp> -#include <mbgl/map/source.hpp> -#include <mbgl/map/tile.hpp> +#include <mbgl/source/source.hpp> +#include <mbgl/tile/tile.hpp> #include <mbgl/map/transform_state.hpp> #include <mbgl/layer/symbol_layer.hpp> #include <mbgl/layer/custom_layer.hpp> @@ -27,9 +27,10 @@ namespace mbgl { -Style::Style(MapData& data_) +Style::Style(MapData& data_, FileSource& fileSource_) : data(data_), - glyphStore(std::make_unique<GlyphStore>()), + fileSource(fileSource_), + glyphStore(std::make_unique<GlyphStore>(fileSource)), glyphAtlas(std::make_unique<GlyphAtlas>(1024, 1024)), spriteStore(std::make_unique<SpriteStore>(data.pixelRatio)), spriteAtlas(std::make_unique<SpriteAtlas>(1024, 1024, data.pixelRatio, *spriteStore)), @@ -55,7 +56,7 @@ void Style::setJSON(const std::string& json, const std::string&) { } glyphStore->setURL(parser.glyphURL); - spriteStore->setURL(parser.spriteURL); + spriteStore->load(parser.spriteURL, fileSource); loaded = true; } @@ -116,13 +117,14 @@ void Style::removeLayer(const std::string& id) { } void Style::update(const TransformState& transform, - TexturePool& texturePool) { + gl::TexturePool& texturePool) { bool allTilesUpdated = true; StyleUpdateParameters parameters(data.pixelRatio, data.getDebug(), data.getAnimationTime(), transform, workers, + fileSource, texturePool, shouldReparsePartialTiles, data.mode, @@ -180,7 +182,9 @@ void Style::recalculate(float z) { Source* source = getSource(layer->source); if (source && layer->needsRendering()) { source->enabled = true; - if (!source->loaded && !source->isLoading()) source->load(); + if (!source->loaded && !source->isLoading()) { + source->load(fileSource); + } } } } diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp index 7bd98a7552..82c048b195 100644 --- a/src/mbgl/style/style.hpp +++ b/src/mbgl/style/style.hpp @@ -3,7 +3,7 @@ #include <mbgl/style/zoom_history.hpp> -#include <mbgl/map/source.hpp> +#include <mbgl/source/source.hpp> #include <mbgl/text/glyph_store.hpp> #include <mbgl/sprite/sprite_store.hpp> @@ -19,6 +19,7 @@ namespace mbgl { class MapData; +class FileSource; class GlyphAtlas; class GlyphStore; class SpriteStore; @@ -26,11 +27,11 @@ class SpriteAtlas; class LineAtlas; class StyleLayer; class TransformState; -class TexturePool; - class Tile; class Bucket; +namespace gl { class TexturePool; } + struct RenderItem { inline RenderItem(const StyleLayer& layer_, const Tile* tile_ = nullptr, @@ -54,7 +55,7 @@ class Style : public GlyphStore::Observer, public Source::Observer, public util::noncopyable { public: - Style(MapData&); + Style(MapData&, FileSource&); ~Style(); class Observer : public GlyphStore::Observer, @@ -79,7 +80,7 @@ public: // Fetch the tiles needed by the current viewport and emit a signal when // a tile is ready so observers can render the tile. - void update(const TransformState&, TexturePool&); + void update(const TransformState&, gl::TexturePool&); void cascade(); void recalculate(float z); @@ -107,6 +108,7 @@ public: void dumpDebugLogs() const; MapData& data; + FileSource& fileSource; std::unique_ptr<GlyphStore> glyphStore; std::unique_ptr<GlyphAtlas> glyphAtlas; std::unique_ptr<SpriteStore> spriteStore; diff --git a/src/mbgl/style/style_bucket_parameters.cpp b/src/mbgl/style/style_bucket_parameters.cpp index e8303e3d8f..7bde1fd80e 100644 --- a/src/mbgl/style/style_bucket_parameters.cpp +++ b/src/mbgl/style/style_bucket_parameters.cpp @@ -1,5 +1,5 @@ #include <mbgl/style/style_bucket_parameters.hpp> -#include <mbgl/map/geometry_tile.hpp> +#include <mbgl/tile/geometry_tile.hpp> namespace mbgl { diff --git a/src/mbgl/style/style_bucket_parameters.hpp b/src/mbgl/style/style_bucket_parameters.hpp index 3329cac032..134850066d 100644 --- a/src/mbgl/style/style_bucket_parameters.hpp +++ b/src/mbgl/style/style_bucket_parameters.hpp @@ -3,7 +3,7 @@ #include <mbgl/map/mode.hpp> #include <mbgl/style/filter_expression.hpp> -#include <mbgl/map/tile_data.hpp> +#include <mbgl/tile/tile_data.hpp> #include <functional> diff --git a/src/mbgl/style/style_layer.hpp b/src/mbgl/style/style_layer.hpp index 764906576f..fa09ee2e82 100644 --- a/src/mbgl/style/style_layer.hpp +++ b/src/mbgl/style/style_layer.hpp @@ -23,11 +23,18 @@ public: virtual ~StyleLayer() = default; // Check whether this layer is of the given subtype. - template <class T> bool is() const { return dynamic_cast<const T*>(this); } + template <class T> + bool is() const; // Dynamically cast this layer to the given subtype. - template <class T> T* as() { return dynamic_cast< T*>(this); } - template <class T> const T* as() const { return dynamic_cast<const T*>(this); } + template <class T> + T* as() { + return is<T>() ? reinterpret_cast<T*>(this) : nullptr; + } + template <class T> + const T* as() const { + return is<T>() ? reinterpret_cast<const T*>(this) : nullptr; + } // Create a copy of this layer. virtual std::unique_ptr<StyleLayer> clone() const = 0; @@ -64,10 +71,22 @@ public: VisibilityType visibility = VisibilityType::Visible; protected: - StyleLayer() = default; + enum class Type { + Fill, + Line, + Circle, + Symbol, + Raster, + Background, + Custom, + }; + + StyleLayer(Type type_) : type(type_) {} StyleLayer(const StyleLayer&) = default; StyleLayer& operator=(const StyleLayer&) = delete; + const Type type; + // Stores what render passes this layer is currently enabled for. This depends on the // evaluated StyleProperties object and is updated accordingly. RenderPass passes = RenderPass::None; diff --git a/src/mbgl/style/style_parser.cpp b/src/mbgl/style/style_parser.cpp index 7d53d603e5..7c2a94b206 100644 --- a/src/mbgl/style/style_parser.cpp +++ b/src/mbgl/style/style_parser.cpp @@ -18,6 +18,7 @@ #include <algorithm> #include <sstream> +#include <set> namespace mbgl { @@ -255,7 +256,7 @@ std::unique_ptr<mapbox::geojsonvt::GeoJSONVT> StyleParser::parseGeoJSON(const JS } } -std::unique_ptr<SourceInfo> StyleParser::parseTileJSON(const std::string& json, const std::string& sourceURL, SourceType type) { +std::unique_ptr<SourceInfo> StyleParser::parseTileJSON(const std::string& json, const std::string& sourceURL, SourceType type, uint16_t tileSize) { rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> document; document.Parse<0>(json.c_str()); @@ -268,11 +269,10 @@ std::unique_ptr<SourceInfo> StyleParser::parseTileJSON(const std::string& json, std::unique_ptr<SourceInfo> result = StyleParser::parseTileJSON(document); // TODO: Remove this hack by delivering proper URLs in the TileJSON to begin with. - if (type == SourceType::Raster && util::mapbox::isMapboxURL(sourceURL)) { - std::transform(result->tiles.begin(), - result->tiles.end(), - result->tiles.begin(), - util::mapbox::normalizeRasterTileURL); + if (util::mapbox::isMapboxURL(sourceURL)) { + for (auto& url : result->tiles) { + url = util::mapbox::canonicalizeTileURL(url, type, tileSize); + } } return result; @@ -484,4 +484,23 @@ void StyleParser::parseVisibility(StyleLayer& layer, const JSValue& value) { layer.visibility = VisibilityTypeClass({ value["visibility"].GetString(), value["visibility"].GetStringLength() }); } +std::vector<std::string> StyleParser::fontStacks() const { + std::set<std::string> result; + + for (const auto& layer : layers) { + if (layer->is<SymbolLayer>()) { + LayoutProperty<std::string> property = layer->as<SymbolLayer>()->layout.text.font; + if (property.parsedValue) { + for (const auto& stop : property.parsedValue->getStops()) { + result.insert(stop.second); + } + } else { + result.insert(property.value); + } + } + } + + return std::vector<std::string>(result.begin(), result.end()); +} + } // namespace mbgl diff --git a/src/mbgl/style/style_parser.hpp b/src/mbgl/style/style_parser.hpp index 69bd8a3bf9..280cda530b 100644 --- a/src/mbgl/style/style_parser.hpp +++ b/src/mbgl/style/style_parser.hpp @@ -2,7 +2,7 @@ #define MBGL_STYLE_STYLE_PARSER #include <mbgl/style/style_layer.hpp> -#include <mbgl/map/source.hpp> +#include <mbgl/source/source.hpp> #include <mbgl/util/rapidjson.hpp> #include <vector> @@ -28,7 +28,10 @@ public: std::vector<std::unique_ptr<Source>> sources; std::vector<std::unique_ptr<StyleLayer>> layers; - static std::unique_ptr<SourceInfo> parseTileJSON(const std::string& json, const std::string& sourceURL, SourceType); + // Statically evaluate layer properties to determine what font stacks are used. + std::vector<std::string> fontStacks() const; + + static std::unique_ptr<SourceInfo> parseTileJSON(const std::string& json, const std::string& sourceURL, SourceType, uint16_t tileSize); static std::unique_ptr<SourceInfo> parseTileJSON(const JSValue&); static std::unique_ptr<mapbox::geojsonvt::GeoJSONVT> parseGeoJSON(const JSValue&); diff --git a/src/mbgl/style/style_update_parameters.hpp b/src/mbgl/style/style_update_parameters.hpp index 0a646219f0..9ea7e112eb 100644 --- a/src/mbgl/style/style_update_parameters.hpp +++ b/src/mbgl/style/style_update_parameters.hpp @@ -7,9 +7,10 @@ namespace mbgl { class TransformState; class Worker; -class TexturePool; +class FileSource; class MapData; class Style; +namespace gl { class TexturePool; } class StyleUpdateParameters { public: @@ -18,7 +19,8 @@ public: TimePoint animationTime_, const TransformState& transformState_, Worker& worker_, - TexturePool& texturePool_, + FileSource& fileSource_, + gl::TexturePool& texturePool_, bool shouldReparsePartialTiles_, const MapMode mode_, MapData& data_, @@ -28,6 +30,7 @@ public: animationTime(animationTime_), transformState(transformState_), worker(worker_), + fileSource(fileSource_), texturePool(texturePool_), shouldReparsePartialTiles(shouldReparsePartialTiles_), mode(mode_), @@ -39,7 +42,8 @@ public: TimePoint animationTime; const TransformState& transformState; Worker& worker; - TexturePool& texturePool; + FileSource& fileSource; + gl::TexturePool& texturePool; bool shouldReparsePartialTiles; const MapMode mode; diff --git a/src/mbgl/text/get_anchors.cpp b/src/mbgl/text/get_anchors.cpp index 1a2142bfb2..7a129d692c 100644 --- a/src/mbgl/text/get_anchors.cpp +++ b/src/mbgl/text/get_anchors.cpp @@ -10,14 +10,19 @@ namespace mbgl { Anchors resample(const std::vector<Coordinate> &line, const float offset, const float spacing, const float angleWindowSize, const float maxAngle, const float labelLength, const bool continuedLine, const bool placeAtMiddle) { + const float halfLabelLength = labelLength / 2.0f; + float lineLength = 0; + for (auto it = line.begin(), end = line.end() - 1; it != end; it++) { + lineLength += util::dist<float>(*(it), *(it + 1)); + } + float distance = 0; float markedDistance = offset - spacing; Anchors anchors; - auto end = line.end() - 1; int i = 0; - for (auto it = line.begin(); it != end; it++, i++) { + for (auto it = line.begin(), end = line.end() - 1; it != end; it++, i++) { const Coordinate &a = *(it); const Coordinate &b = *(it + 1); @@ -31,7 +36,12 @@ Anchors resample(const std::vector<Coordinate> &line, const float offset, const x = util::interpolate(float(a.x), float(b.x), t), y = util::interpolate(float(a.y), float(b.y), t); - if (x >= 0 && x < util::EXTENT && y >= 0 && y < util::EXTENT) { + // Check that the point is within the tile boundaries and that + // the label would fit before the beginning and end of the line + // if placed at this point. + if (x >= 0 && x < util::EXTENT && y >= 0 && y < util::EXTENT && + markedDistance - halfLabelLength >= 0.0f && + markedDistance + halfLabelLength <= lineLength) { Anchor anchor(::round(x), ::round(y), angle, 0.5f, i); if (!angleWindowSize || checkMaxAngle(line, anchor, labelLength, angleWindowSize, maxAngle)) { diff --git a/src/mbgl/text/glyph_pbf.cpp b/src/mbgl/text/glyph_pbf.cpp index 0dfed6b430..c9466e8652 100644 --- a/src/mbgl/text/glyph_pbf.cpp +++ b/src/mbgl/text/glyph_pbf.cpp @@ -8,7 +8,6 @@ #include <mbgl/util/exception.hpp> #include <mbgl/util/pbf.hpp> #include <mbgl/util/string.hpp> -#include <mbgl/util/thread_context.hpp> #include <mbgl/util/token.hpp> #include <mbgl/util/url.hpp> @@ -64,29 +63,29 @@ namespace mbgl { GlyphPBF::GlyphPBF(GlyphStore* store, const std::string& fontStack, const GlyphRange& glyphRange, - GlyphStore::Observer* observer_) + GlyphStore::Observer* observer_, + FileSource& fileSource) : parsed(false), observer(observer_) { - FileSource* fs = util::ThreadContext::getFileSource(); - req = fs->request(Resource::glyphs(store->getURL(), fontStack, glyphRange), [this, store, fontStack, glyphRange](Response res) { + req = fileSource.request(Resource::glyphs(store->getURL(), fontStack, glyphRange), [this, store, fontStack, glyphRange](Response res) { if (res.error) { observer->onGlyphsError(fontStack, glyphRange, std::make_exception_ptr(std::runtime_error(res.error->message))); + } else if (res.notModified) { return; - } - - if (res.notModified) { - return; - } + } else if (res.noContent) { + parsed = true; + observer->onGlyphsLoaded(fontStack, glyphRange); + } else { + try { + parseGlyphPBF(**store->getFontStack(fontStack), *res.data); + } catch (...) { + observer->onGlyphsError(fontStack, glyphRange, std::current_exception()); + return; + } - try { - parseGlyphPBF(**store->getFontStack(fontStack), *res.data); - } catch (...) { - observer->onGlyphsError(fontStack, glyphRange, std::current_exception()); - return; + parsed = true; + observer->onGlyphsLoaded(fontStack, glyphRange); } - - parsed = true; - observer->onGlyphsLoaded(fontStack, glyphRange); }); } diff --git a/src/mbgl/text/glyph_pbf.hpp b/src/mbgl/text/glyph_pbf.hpp index 9e2ee4eacf..016792aae8 100644 --- a/src/mbgl/text/glyph_pbf.hpp +++ b/src/mbgl/text/glyph_pbf.hpp @@ -14,13 +14,15 @@ namespace mbgl { class FontStack; class FileRequest; +class FileSource; class GlyphPBF : private util::noncopyable { public: GlyphPBF(GlyphStore* store, const std::string& fontStack, const GlyphRange&, - GlyphStore::Observer*); + GlyphStore::Observer*, + FileSource&); ~GlyphPBF(); bool isParsed() const { diff --git a/src/mbgl/text/glyph_store.cpp b/src/mbgl/text/glyph_store.cpp index a3d1530e3d..1c75f7191e 100644 --- a/src/mbgl/text/glyph_store.cpp +++ b/src/mbgl/text/glyph_store.cpp @@ -7,7 +7,10 @@ namespace mbgl { -GlyphStore::GlyphStore() = default; +GlyphStore::GlyphStore(FileSource& fileSource_) + : fileSource(fileSource_) { +} + GlyphStore::~GlyphStore() = default; void GlyphStore::requestGlyphRange(const std::string& fontStackName, const GlyphRange& range) { @@ -22,7 +25,7 @@ void GlyphStore::requestGlyphRange(const std::string& fontStackName, const Glyph } rangeSets.emplace(range, - std::make_unique<GlyphPBF>(this, fontStackName, range, observer)); + std::make_unique<GlyphPBF>(this, fontStackName, range, observer, fileSource)); } diff --git a/src/mbgl/text/glyph_store.hpp b/src/mbgl/text/glyph_store.hpp index 2236bce38c..6829397851 100644 --- a/src/mbgl/text/glyph_store.hpp +++ b/src/mbgl/text/glyph_store.hpp @@ -14,6 +14,7 @@ namespace mbgl { +class FileSource; class GlyphPBF; // The GlyphStore manages the loading and storage of Glyphs @@ -29,7 +30,7 @@ public: virtual void onGlyphsError(const std::string& /* fontStack */, const GlyphRange&, std::exception_ptr) {}; }; - GlyphStore(); + GlyphStore(FileSource&); ~GlyphStore(); util::exclusive<FontStack> getFontStack(const std::string& fontStack); @@ -54,6 +55,7 @@ public: private: void requestGlyphRange(const std::string& fontStackName, const GlyphRange& range); + FileSource& fileSource; std::string glyphURL; std::unordered_map<std::string, std::map<GlyphRange, std::unique_ptr<GlyphPBF>>> ranges; diff --git a/src/mbgl/tile/geojson_tile.hpp b/src/mbgl/tile/geojson_tile.hpp index fd27fa5917..6f3cbc10d1 100644 --- a/src/mbgl/tile/geojson_tile.hpp +++ b/src/mbgl/tile/geojson_tile.hpp @@ -1,7 +1,7 @@ #ifndef MBGL_ANNOTATION_GEOJSON_VT_TILE #define MBGL_ANNOTATION_GEOJSON_VT_TILE -#include <mbgl/map/geometry_tile.hpp> +#include <mbgl/tile/geometry_tile.hpp> #include <mbgl/map/tile_id.hpp> #include <unordered_map> diff --git a/src/mbgl/map/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index 82affc689f..fa41481d4d 100644 --- a/src/mbgl/map/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -1,4 +1,4 @@ -#include <mbgl/map/geometry_tile.hpp> +#include <mbgl/tile/geometry_tile.hpp> #include <mbgl/style/filter_expression.hpp> #include <mbgl/style/filter_expression_private.hpp> diff --git a/src/mbgl/map/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp index 5cb2f96fdc..5cb2f96fdc 100644 --- a/src/mbgl/map/geometry_tile.hpp +++ b/src/mbgl/tile/geometry_tile.hpp diff --git a/src/mbgl/tile/raster_tile_data.cpp b/src/mbgl/tile/raster_tile_data.cpp new file mode 100644 index 0000000000..3f26bbdfdd --- /dev/null +++ b/src/mbgl/tile/raster_tile_data.cpp @@ -0,0 +1,83 @@ +#include <mbgl/tile/raster_tile_data.hpp> +#include <mbgl/source/source.hpp> +#include <mbgl/storage/resource.hpp> +#include <mbgl/storage/response.hpp> +#include <mbgl/storage/file_source.hpp> +#include <mbgl/util/worker.hpp> +#include <mbgl/util/work_request.hpp> + +using namespace mbgl; + +RasterTileData::RasterTileData(const TileID& id_, + float pixelRatio, + const std::string& urlTemplate, + gl::TexturePool &texturePool_, + Worker& worker_, + FileSource& fileSource, + const std::function<void(std::exception_ptr)>& callback) + : TileData(id_), + texturePool(texturePool_), + worker(worker_) { + state = State::loading; + + const Resource resource = Resource::tile(urlTemplate, pixelRatio, id.x, id.y, id.sourceZ); + req = fileSource.request(resource, [callback, this](Response res) { + if (res.error) { + callback(std::make_exception_ptr(std::runtime_error(res.error->message))); + } else if (res.notModified) { + modified = res.modified; + expires = res.expires; + } else if (res.noContent) { + state = State::parsed; + modified = res.modified; + expires = res.expires; + workRequest.reset(); + bucket.reset(); + callback(nullptr); + } else { + modified = res.modified; + expires = res.expires; + + // Only overwrite the state when we didn't have a previous tile. + if (state == State::loading) { + state = State::loaded; + } + + workRequest.reset(); + workRequest = worker.parseRasterTile(std::make_unique<RasterBucket>(texturePool), res.data, [this, callback] (RasterTileParseResult result) { + workRequest.reset(); + if (state != State::loaded) { + return; + } + + std::exception_ptr error; + if (result.is<std::unique_ptr<Bucket>>()) { + state = State::parsed; + bucket = std::move(result.get<std::unique_ptr<Bucket>>()); + } else { + error = result.get<std::exception_ptr>(); + state = State::obsolete; + bucket.reset(); + } + + callback(error); + }); + } + }); +} + +RasterTileData::~RasterTileData() { + cancel(); +} + +Bucket* RasterTileData::getBucket(StyleLayer const&) { + return bucket.get(); +} + +void RasterTileData::cancel() { + if (state != State::obsolete) { + state = State::obsolete; + } + req = nullptr; + workRequest.reset(); +} diff --git a/src/mbgl/map/raster_tile_data.hpp b/src/mbgl/tile/raster_tile_data.hpp index e68fbc94c5..59eee88496 100644 --- a/src/mbgl/map/raster_tile_data.hpp +++ b/src/mbgl/tile/raster_tile_data.hpp @@ -1,23 +1,25 @@ #ifndef MBGL_MAP_RASTER_TILE_DATA #define MBGL_MAP_RASTER_TILE_DATA -#include <mbgl/map/tile_data.hpp> +#include <mbgl/tile/tile_data.hpp> #include <mbgl/renderer/raster_bucket.hpp> namespace mbgl { +class FileSource; class FileRequest; class StyleLayer; -class TexturePool; class WorkRequest; +namespace gl { class TexturePool; } class RasterTileData : public TileData { public: RasterTileData(const TileID&, float pixelRatio, const std::string& urlTemplate, - TexturePool&, + gl::TexturePool&, Worker&, + FileSource&, const std::function<void(std::exception_ptr)>& callback); ~RasterTileData(); @@ -25,7 +27,7 @@ public: Bucket* getBucket(StyleLayer const &layer_desc) override; private: - TexturePool& texturePool; + gl::TexturePool& texturePool; Worker& worker; std::unique_ptr<FileRequest> req; std::unique_ptr<Bucket> bucket; diff --git a/src/mbgl/tile/tile.cpp b/src/mbgl/tile/tile.cpp new file mode 100644 index 0000000000..a1d36421a4 --- /dev/null +++ b/src/mbgl/tile/tile.cpp @@ -0,0 +1,3 @@ +#include <mbgl/tile/tile.hpp> + +using namespace mbgl; diff --git a/src/mbgl/map/tile.hpp b/src/mbgl/tile/tile.hpp index 8b9030f1bd..8b9030f1bd 100644 --- a/src/mbgl/map/tile.hpp +++ b/src/mbgl/tile/tile.hpp diff --git a/src/mbgl/map/tile_cache.cpp b/src/mbgl/tile/tile_cache.cpp index 2d1a0da96c..423b355827 100644 --- a/src/mbgl/map/tile_cache.cpp +++ b/src/mbgl/tile/tile_cache.cpp @@ -1,4 +1,5 @@ -#include <mbgl/map/tile_cache.hpp> +#include <mbgl/tile/tile_cache.hpp> +#include <mbgl/tile/tile_data.hpp> #include <cassert> diff --git a/src/mbgl/map/tile_cache.hpp b/src/mbgl/tile/tile_cache.hpp index e39db0ffae..4d0b42242a 100644 --- a/src/mbgl/map/tile_cache.hpp +++ b/src/mbgl/tile/tile_cache.hpp @@ -1,13 +1,14 @@ #ifndef MBGL_MAP_TILE_CACHE #define MBGL_MAP_TILE_CACHE -#include <mbgl/map/tile_data.hpp> - #include <list> +#include <memory> #include <unordered_map> namespace mbgl { +class TileData; + class TileCache { public: TileCache(size_t size_ = 0) : size(size_) {} @@ -18,6 +19,7 @@ public: std::shared_ptr<TileData> get(uint64_t key); bool has(uint64_t key); void clear(); + private: std::unordered_map<uint64_t, std::shared_ptr<TileData>> tiles; std::list<uint64_t> orderedKeys; diff --git a/src/mbgl/map/tile_data.cpp b/src/mbgl/tile/tile_data.cpp index edfe4d7ada..46ce64771c 100644 --- a/src/mbgl/map/tile_data.cpp +++ b/src/mbgl/tile/tile_data.cpp @@ -1,4 +1,4 @@ -#include <mbgl/map/tile_data.hpp> +#include <mbgl/tile/tile_data.hpp> #include <mbgl/renderer/debug_bucket.hpp> #include <mbgl/util/string.hpp> diff --git a/src/mbgl/map/tile_data.hpp b/src/mbgl/tile/tile_data.hpp index 90196f8a42..90196f8a42 100644 --- a/src/mbgl/map/tile_data.hpp +++ b/src/mbgl/tile/tile_data.hpp diff --git a/src/mbgl/map/tile_worker.cpp b/src/mbgl/tile/tile_worker.cpp index edbd392057..917b61fde9 100644 --- a/src/mbgl/map/tile_worker.cpp +++ b/src/mbgl/tile/tile_worker.cpp @@ -1,6 +1,6 @@ #include <mbgl/text/collision_tile.hpp> -#include <mbgl/map/tile_worker.hpp> -#include <mbgl/map/geometry_tile.hpp> +#include <mbgl/tile/tile_worker.hpp> +#include <mbgl/tile/geometry_tile.hpp> #include <mbgl/style/style_layer.hpp> #include <mbgl/style/style_bucket_parameters.hpp> #include <mbgl/layer/background_layer.hpp> diff --git a/src/mbgl/map/tile_worker.hpp b/src/mbgl/tile/tile_worker.hpp index bcd8e59bf9..08048c134b 100644 --- a/src/mbgl/map/tile_worker.hpp +++ b/src/mbgl/tile/tile_worker.hpp @@ -4,7 +4,7 @@ #include <mapbox/variant.hpp> #include <mbgl/map/mode.hpp> -#include <mbgl/map/tile_data.hpp> +#include <mbgl/tile/tile_data.hpp> #include <mbgl/util/noncopyable.hpp> #include <mbgl/util/ptr.hpp> #include <mbgl/text/placement_config.hpp> diff --git a/src/mbgl/map/vector_tile.cpp b/src/mbgl/tile/vector_tile.cpp index 17746a26a1..9e35debbff 100644 --- a/src/mbgl/map/vector_tile.cpp +++ b/src/mbgl/tile/vector_tile.cpp @@ -1,9 +1,8 @@ -#include <mbgl/map/vector_tile.hpp> -#include <mbgl/map/source.hpp> +#include <mbgl/tile/vector_tile.hpp> +#include <mbgl/source/source.hpp> #include <mbgl/storage/resource.hpp> #include <mbgl/storage/response.hpp> #include <mbgl/storage/file_source.hpp> -#include <mbgl/util/thread_context.hpp> #include <mbgl/util/url.hpp> #include <utility> @@ -182,31 +181,25 @@ util::ptr<const GeometryTileFeature> VectorTileLayer::getFeature(std::size_t i) return std::make_shared<VectorTileFeature>(features.at(i), *this); } -VectorTileMonitor::VectorTileMonitor(const TileID& tileID_, float pixelRatio_, const std::string& urlTemplate_) +VectorTileMonitor::VectorTileMonitor(const TileID& tileID_, float pixelRatio_, const std::string& urlTemplate_, FileSource& fileSource_) : tileID(tileID_), pixelRatio(pixelRatio_), - urlTemplate(urlTemplate_) { + urlTemplate(urlTemplate_), + fileSource(fileSource_) { } std::unique_ptr<FileRequest> VectorTileMonitor::monitorTile(const GeometryTileMonitor::Callback& callback) { const Resource resource = Resource::tile(urlTemplate, pixelRatio, tileID.x, tileID.y, tileID.sourceZ); - return util::ThreadContext::getFileSource()->request(resource, [callback, this](Response res) { - if (res.notModified) { - // We got the same data again. Abort early. - return; - } - + return fileSource.request(resource, [callback, this](Response res) { if (res.error) { - if (res.error->reason == Response::Error::Reason::NotFound) { - callback(nullptr, nullptr, res.modified, res.expires); - return; - } else { - callback(std::make_exception_ptr(std::runtime_error(res.error->message)), nullptr, res.modified, res.expires); - return; - } + callback(std::make_exception_ptr(std::runtime_error(res.error->message)), nullptr, res.modified, res.expires); + } else if (res.notModified) { + return; + } else if (res.noContent) { + callback(nullptr, nullptr, res.modified, res.expires); + } else { + callback(nullptr, std::make_unique<VectorTile>(res.data), res.modified, res.expires); } - - callback(nullptr, std::make_unique<VectorTile>(res.data), res.modified, res.expires); }); } diff --git a/src/mbgl/map/vector_tile.hpp b/src/mbgl/tile/vector_tile.hpp index 8550b1c55a..48e501cbd7 100644 --- a/src/mbgl/map/vector_tile.hpp +++ b/src/mbgl/tile/vector_tile.hpp @@ -1,7 +1,7 @@ #ifndef MBGL_MAP_VECTOR_TILE #define MBGL_MAP_VECTOR_TILE -#include <mbgl/map/geometry_tile.hpp> +#include <mbgl/tile/geometry_tile.hpp> #include <mbgl/map/tile_id.hpp> #include <mbgl/util/pbf.hpp> @@ -59,10 +59,11 @@ private: }; class TileID; +class FileSource; class VectorTileMonitor : public GeometryTileMonitor { public: - VectorTileMonitor(const TileID&, float pixelRatio, const std::string& urlTemplate); + VectorTileMonitor(const TileID&, float pixelRatio, const std::string& urlTemplate, FileSource&); std::unique_ptr<FileRequest> monitorTile(const GeometryTileMonitor::Callback&) override; @@ -70,6 +71,7 @@ private: TileID tileID; float pixelRatio; std::string urlTemplate; + FileSource& fileSource; }; } // namespace mbgl diff --git a/src/mbgl/map/vector_tile_data.cpp b/src/mbgl/tile/vector_tile_data.cpp index 27172a3e63..d2eecab975 100644 --- a/src/mbgl/map/vector_tile_data.cpp +++ b/src/mbgl/tile/vector_tile_data.cpp @@ -1,5 +1,5 @@ -#include <mbgl/map/vector_tile_data.hpp> -#include <mbgl/map/geometry_tile.hpp> +#include <mbgl/tile/vector_tile_data.hpp> +#include <mbgl/tile/geometry_tile.hpp> #include <mbgl/style/style_layer.hpp> #include <mbgl/util/worker.hpp> #include <mbgl/util/work_request.hpp> diff --git a/src/mbgl/map/vector_tile_data.hpp b/src/mbgl/tile/vector_tile_data.hpp index b61b2a25a0..d0b599c4cf 100644 --- a/src/mbgl/map/vector_tile_data.hpp +++ b/src/mbgl/tile/vector_tile_data.hpp @@ -1,8 +1,8 @@ #ifndef MBGL_MAP_VECTOR_TILE_DATA #define MBGL_MAP_VECTOR_TILE_DATA -#include <mbgl/map/tile_data.hpp> -#include <mbgl/map/tile_worker.hpp> +#include <mbgl/tile/tile_data.hpp> +#include <mbgl/tile/tile_worker.hpp> #include <mbgl/text/placement_config.hpp> #include <atomic> diff --git a/src/mbgl/util/box.hpp b/src/mbgl/util/box.hpp deleted file mode 100644 index 2806fb95fc..0000000000 --- a/src/mbgl/util/box.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef MBGL_UTIL_BOX -#define MBGL_UTIL_BOX - -#include <mbgl/util/tile_coordinate.hpp> - -namespace mbgl { - -struct box { - box(TileCoordinate tl_, TileCoordinate tr_, TileCoordinate br_, TileCoordinate bl_) : - tl(tl_), tr(tr_), br(br_), bl(bl_) {} - TileCoordinate tl, tr, br, bl; -}; - -} // namespace mbgl - -#endif diff --git a/src/mbgl/util/clip_id.cpp b/src/mbgl/util/clip_id.cpp index b89315d97b..47a5877bb6 100644 --- a/src/mbgl/util/clip_id.cpp +++ b/src/mbgl/util/clip_id.cpp @@ -2,7 +2,8 @@ #include <mbgl/platform/log.hpp> #include <mbgl/util/math.hpp> -#include <mbgl/map/tile.hpp> +#include <mbgl/util/std.hpp> +#include <mbgl/tile/tile.hpp> #include <list> #include <vector> @@ -10,13 +11,14 @@ #include <cassert> #include <iostream> #include <algorithm> +#include <iterator> namespace mbgl { -ClipIDGenerator::Leaf::Leaf(Tile &tile_) : tile(tile_) {} +ClipIDGenerator::Leaf::Leaf(TileID id_, ClipID& clip_) : id(id_), clip(clip_) {} void ClipIDGenerator::Leaf::add(const TileID &p) { - if (p.isChildOf(tile.id)) { + if (p.isChildOf(id)) { // Ensure that no already present child is a parent of the new p. for (const auto& child : children) { if (p.isChildOf(child)) @@ -27,27 +29,16 @@ void ClipIDGenerator::Leaf::add(const TileID &p) { } bool ClipIDGenerator::Leaf::operator==(const Leaf &other) const { - return tile.id == other.tile.id && children == other.children; -} - -bool ClipIDGenerator::reuseExisting(Leaf &leaf) { - for (const auto& pool : pools) { - auto existing = std::find(pool.begin(), pool.end(), leaf); - if (existing != pool.end()) { - leaf.tile.clip = existing->tile.clip; - return true; - } - } - return false; + return id == other.id && children == other.children; } void ClipIDGenerator::update(std::forward_list<Tile *> tiles) { - Pool pool; - tiles.sort([](const Tile *a, const Tile *b) { return a->id < b->id; }); + std::size_t size = 0; + const auto end = tiles.end(); for (auto it = tiles.begin(); it != end; it++) { if (!*it) { @@ -56,37 +47,49 @@ void ClipIDGenerator::update(std::forward_list<Tile *> tiles) { } Tile &tile = **it; - Leaf clip { tile }; + // Use the actual zoom level for computing the clipping mask. + Leaf leaf{ TileID{ tile.id.sourceZ, tile.id.x, tile.id.y, tile.id.sourceZ }, tile.clip }; // Try to add all remaining ids as children. We sorted the tile list // by z earlier, so all preceding items cannot be children of the current // tile. for (auto child_it = std::next(it); child_it != end; child_it++) { - clip.add((*child_it)->id); + // Use the actual zoom level for computing the clipping mask. + const auto& childID = (*child_it)->id; + leaf.add(TileID { childID.sourceZ, childID.x, childID.y, childID.sourceZ }); } - clip.children.sort(); + leaf.children.sort(); // Loop through all existing pools and try to find a matching ClipID. - if (!reuseExisting(clip)) { + auto existing = std::find(pool.begin(), pool.end(), leaf); + if (existing != pool.end()) { + leaf.clip = existing->clip; + } else { // We haven't found an existing clip ID - pool.push_back(std::move(clip)); + leaf.clip = {}; + size++; } + + pool.emplace_back(std::move(leaf)); } - if (!pool.empty()) { - const uint32_t bit_count = util::ceil_log2(pool.size() + 1); + if (size > 0) { + const uint32_t bit_count = util::ceil_log2(size + 1); const std::bitset<8> mask = uint64_t(((1ul << bit_count) - 1) << bit_offset); // We are starting our count with 1 since we need at least 1 bit set to distinguish between // areas without any tiles whatsoever and the current area. uint8_t count = 1; - for (auto& leaf : pool) { - leaf.tile.clip.mask = mask; - leaf.tile.clip.reference = uint32_t(count++) << bit_offset; + for (auto& tile : tiles) { + tile->clip.mask |= mask; + + // Assign only to clip IDs that have no value yet. + if (tile->clip.reference.none()) { + tile->clip.reference = uint32_t(count++) << bit_offset; + } } bit_offset += bit_count; - pools.push_front(std::move(pool)); } if (bit_offset > 8) { @@ -94,4 +97,58 @@ void ClipIDGenerator::update(std::forward_list<Tile *> tiles) { } } +template <typename Container> +bool coveredByChildren(const TileID& id, const Container& container) { + for (const auto& child : id.children()) { + const auto lower = container.lower_bound(child); + if (lower == container.end() || + (lower->first != child && !coveredByChildren(child, container))) { + return false; + } + } + + // We looked at all four immediate children and verified that they're covered. + return true; +} + +std::map<TileID, ClipID> ClipIDGenerator::getStencils() const { + std::map<TileID, ClipID> stencils; + + // Merge everything. + for (auto& leaf : pool) { + auto res = stencils.emplace(leaf.id, leaf.clip); + if (!res.second) { + // Merge with the existing ClipID when there was already an element with the + // same tile ID. + res.first->second |= leaf.clip; + } + } + + for (auto it = stencils.begin(); it != stencils.end(); ++it) { + auto& childId = it->first; + auto& childClip = it->second; + + // Loop through all preceding stencils, and find all parents. + + for (auto parentIt = std::reverse_iterator<std::map<TileID, ClipID>::iterator>(it); + parentIt != stencils.rend(); ++parentIt) { + auto& parentId = parentIt->first; + if (childId.isChildOf(parentId)) { + // Once we have a parent, we add the bits that this ID hasn't set yet. + const auto& parentClip = parentIt->second; + const auto mask = ~(childClip.mask & parentClip.mask); + childClip.reference |= mask & parentClip.reference; + childClip.mask |= parentClip.mask; + } + } + } + + // Remove tiles that are entirely covered by children. + util::erase_if(stencils, [&] (const auto& stencil) { + return coveredByChildren(stencil.first, stencils); + }); + + return stencils; +} + } // namespace mbgl diff --git a/src/mbgl/util/clip_id.hpp b/src/mbgl/util/clip_id.hpp index 71a07708c9..2c128d2643 100644 --- a/src/mbgl/util/clip_id.hpp +++ b/src/mbgl/util/clip_id.hpp @@ -14,7 +14,6 @@ namespace mbgl { class Tile; -class TileID; struct ClipID { inline ClipID() {} @@ -26,28 +25,33 @@ struct ClipID { inline bool operator==(const ClipID &other) const { return mask == other.mask && reference == other.reference; } + + inline ClipID& operator|=(const ClipID &other) { + mask |= other.mask; + reference |= other.reference; + return *this; + } }; class ClipIDGenerator { private: struct Leaf { - Leaf(Tile &tile); + Leaf(TileID, ClipID&); void add(const TileID &p); bool operator==(const Leaf &other) const; - Tile &tile; + const TileID id; std::forward_list<TileID> children; + ClipID& clip; }; - typedef std::vector<Leaf> Pool; - std::forward_list<Pool> pools; uint8_t bit_offset = 0; - -private: - bool reuseExisting(Leaf &leaf); + std::vector<Leaf> pool; public: void update(std::forward_list<Tile *> tiles); + + std::map<TileID, ClipID> getStencils() const; }; diff --git a/src/mbgl/util/clip_lines.cpp b/src/mbgl/util/clip_lines.cpp index 3a909d674a..071e9d09bd 100644 --- a/src/mbgl/util/clip_lines.cpp +++ b/src/mbgl/util/clip_lines.cpp @@ -21,33 +21,33 @@ std::vector<std::vector<Coordinate>> clipLines(const std::vector<std::vector<Coo if (p0.x < x1 && p1.x < x1) { continue; } else if (p0.x < x1) { - p0 = { x1, static_cast<int16_t>(p0.y + (p1.y - p0.y) * ((float)(x1 - p0.x) / (p1.x - p0.x))) }; + p0 = { x1, static_cast<int16_t>(::round(p0.y + (p1.y - p0.y) * ((float)(x1 - p0.x) / (p1.x - p0.x)))) }; } else if (p1.x < x1) { - p1 = { x1, static_cast<int16_t>(p0.y + (p1.y - p0.y) * ((float)(x1 - p0.x) / (p1.x - p0.x))) }; + p1 = { x1, static_cast<int16_t>(::round(p0.y + (p1.y - p0.y) * ((float)(x1 - p0.x) / (p1.x - p0.x)))) }; } if (p0.y < y1 && p1.y < y1) { continue; } else if (p0.y < y1) { - p0 = { static_cast<int16_t>(p0.x + (p1.x - p0.x) * ((float)(y1 - p0.y) / (p1.y - p0.y))), y1 }; + p0 = { static_cast<int16_t>(::round(p0.x + (p1.x - p0.x) * ((float)(y1 - p0.y) / (p1.y - p0.y)))), y1 }; } else if (p1.y < y1) { - p1 = { static_cast<int16_t>(p0.x + (p1.x - p0.x) * ((float)(y1 - p0.y) / (p1.y - p0.y))), y1 }; + p1 = { static_cast<int16_t>(::round(p0.x + (p1.x - p0.x) * ((float)(y1 - p0.y) / (p1.y - p0.y)))), y1 }; } if (p0.x >= x2 && p1.x >= x2) { continue; } else if (p0.x >= x2) { - p0 = { x2, static_cast<int16_t>(p0.y + (p1.y - p0.y) * ((float)(x2 - p0.x) / (p1.x - p0.x))) }; + p0 = { x2, static_cast<int16_t>(::round(p0.y + (p1.y - p0.y) * ((float)(x2 - p0.x) / (p1.x - p0.x)))) }; } else if (p1.x >= x2) { - p1 = { x2, static_cast<int16_t>(p0.y + (p1.y - p0.y) * ((float)(x2 - p0.x) / (p1.x - p0.x))) }; + p1 = { x2, static_cast<int16_t>(::round(p0.y + (p1.y - p0.y) * ((float)(x2 - p0.x) / (p1.x - p0.x)))) }; } if (p0.y >= y2 && p1.y >= y2) { continue; } else if (p0.y >= y2) { - p0 = { static_cast<int16_t>(p0.x + (p1.x - p0.x) * ((float)(y2 - p0.y) / (p1.y - p0.y))), y2 }; + p0 = { static_cast<int16_t>(::round(p0.x + (p1.x - p0.x) * ((float)(y2 - p0.y) / (p1.y - p0.y)))), y2 }; } else if (p1.y >= y2) { - p1 = { static_cast<int16_t>(p0.x + (p1.x - p0.x) * ((float)(y2 - p0.y) / (p1.y - p0.y))), y2 }; + p1 = { static_cast<int16_t>(::round(p0.x + (p1.x - p0.x) * ((float)(y2 - p0.y) / (p1.y - p0.y)))), y2 }; } if (clippedLines.empty() || (!clippedLines.back().empty() && !(p0 == clippedLines.back().back()))) { diff --git a/src/mbgl/util/constants.cpp b/src/mbgl/util/constants.cpp index 0452dd19e5..90a4d28c2f 100644 --- a/src/mbgl/util/constants.cpp +++ b/src/mbgl/util/constants.cpp @@ -1,6 +1,12 @@ #include <mbgl/util/constants.hpp> -const float mbgl::util::tileSize = 512.0f; +#include <limits> + +namespace mbgl { + +namespace util { + +const float tileSize = 512.0f; /* * The maximum extent of a feature that can be safely stored in the buffer. @@ -12,37 +18,47 @@ const float mbgl::util::tileSize = 512.0f; * One bit is lost to support features extending past the extent on the right edge of the tile. * This leaves us with 2^13 = 8192 */ -const int32_t mbgl::util::EXTENT = 8192; +const int32_t EXTENT = 8192; + +const double DEG2RAD = M_PI / 180.0; +const double RAD2DEG = 180.0 / M_PI; +const double M2PI = 2 * M_PI; +const double EARTH_RADIUS_M = 6378137; +const double LATITUDE_MAX = 85.05112878; +const double PITCH_MAX = M_PI / 3; +const double MIN_ZOOM = 0.0; +const double MAX_ZOOM = 25.5; -const double mbgl::util::DEG2RAD = M_PI / 180.0; -const double mbgl::util::RAD2DEG = 180.0 / M_PI; -const double mbgl::util::M2PI = 2 * M_PI; -const double mbgl::util::EARTH_RADIUS_M = 6378137; -const double mbgl::util::LATITUDE_MAX = 85.05112878; -const double mbgl::util::PITCH_MAX = M_PI / 3; -const double mbgl::util::MIN_ZOOM = 0.0; -const double mbgl::util::MAX_ZOOM = 25.5; +const uint64_t DEFAULT_MAX_CACHE_SIZE = 50 * 1024 * 1024; + +} // namespace util + +namespace debug { #if defined(DEBUG) -const bool mbgl::debug::tileParseWarnings = false; -const bool mbgl::debug::styleParseWarnings = false; -const bool mbgl::debug::spriteWarnings = false; -const bool mbgl::debug::renderWarnings = false; -const bool mbgl::debug::renderTree = false; -const bool mbgl::debug::labelTextMissingWarning = true; -const bool mbgl::debug::missingFontStackWarning = true; -const bool mbgl::debug::missingFontFaceWarning = true; -const bool mbgl::debug::glyphWarning = true; -const bool mbgl::debug::shapingWarning = true; +const bool tileParseWarnings = false; +const bool styleParseWarnings = false; +const bool spriteWarnings = false; +const bool renderWarnings = false; +const bool renderTree = false; +const bool labelTextMissingWarning = true; +const bool missingFontStackWarning = true; +const bool missingFontFaceWarning = true; +const bool glyphWarning = true; +const bool shapingWarning = true; #else -const bool mbgl::debug::tileParseWarnings = false; -const bool mbgl::debug::styleParseWarnings = false; -const bool mbgl::debug::spriteWarnings = false; -const bool mbgl::debug::renderWarnings = false; -const bool mbgl::debug::renderTree = false; -const bool mbgl::debug::labelTextMissingWarning = false; -const bool mbgl::debug::missingFontStackWarning = false; -const bool mbgl::debug::missingFontFaceWarning = false; -const bool mbgl::debug::glyphWarning = false; -const bool mbgl::debug::shapingWarning = false; +const bool tileParseWarnings = false; +const bool styleParseWarnings = false; +const bool spriteWarnings = false; +const bool renderWarnings = false; +const bool renderTree = false; +const bool labelTextMissingWarning = false; +const bool missingFontStackWarning = false; +const bool missingFontFaceWarning = false; +const bool glyphWarning = false; +const bool shapingWarning = false; #endif + +} // namespace debug + +} // namespace mbgl diff --git a/src/mbgl/util/get_geometries.cpp b/src/mbgl/util/get_geometries.cpp index 4d4d02c5ff..5961af2150 100644 --- a/src/mbgl/util/get_geometries.cpp +++ b/src/mbgl/util/get_geometries.cpp @@ -1,6 +1,8 @@ #include <mbgl/util/get_geometries.hpp> #include <mbgl/util/constants.hpp> +#include <cmath> + namespace mbgl { GeometryCollection getGeometries(const GeometryTileFeature& feature) { @@ -8,8 +10,8 @@ GeometryCollection getGeometries(const GeometryTileFeature& feature) { GeometryCollection geometryCollection = feature.getGeometries(); for (auto& line : geometryCollection) { for (auto& point : line) { - point.x = std::round(point.x * scale); - point.y = std::round(point.y * scale); + point.x = ::round(point.x * scale); + point.y = ::round(point.y * scale); } } return geometryCollection; diff --git a/src/mbgl/util/get_geometries.hpp b/src/mbgl/util/get_geometries.hpp index 32dd389507..013a7e5b9f 100644 --- a/src/mbgl/util/get_geometries.hpp +++ b/src/mbgl/util/get_geometries.hpp @@ -1,7 +1,7 @@ #ifndef MBGL_UTIL_GET_GEOMETRIES #define MBGL_UTIL_GET_GEOMETRIES -#include <mbgl/map/geometry_tile.hpp> +#include <mbgl/tile/geometry_tile.hpp> namespace mbgl { diff --git a/src/mbgl/util/gl_object_store.cpp b/src/mbgl/util/gl_object_store.cpp deleted file mode 100644 index 78d6700237..0000000000 --- a/src/mbgl/util/gl_object_store.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include <mbgl/util/gl_object_store.hpp> - -#include <mbgl/util/thread.hpp> -#include <mbgl/geometry/vao.hpp> -#include <mbgl/platform/gl.hpp> - -#include <cassert> - -namespace mbgl { -namespace util { - -void GLObjectStore::abandonVAO(GLuint vao) { - assert(ThreadContext::currentlyOn(ThreadType::Map)); - abandonedVAOs.emplace_back(vao); -} - -void GLObjectStore::abandonBuffer(GLuint buffer) { - assert(ThreadContext::currentlyOn(ThreadType::Map)); - abandonedBuffers.emplace_back(buffer); -} - -void GLObjectStore::abandonTexture(GLuint texture) { - assert(ThreadContext::currentlyOn(ThreadType::Map)); - abandonedTextures.emplace_back(texture); -} - -void GLObjectStore::performCleanup() { - assert(ThreadContext::currentlyOn(ThreadType::Map)); - - if (!abandonedVAOs.empty()) { - MBGL_CHECK_ERROR(VertexArrayObject::Delete(static_cast<GLsizei>(abandonedVAOs.size()), - abandonedVAOs.data())); - abandonedVAOs.clear(); - } - - if (!abandonedTextures.empty()) { - MBGL_CHECK_ERROR(glDeleteTextures(static_cast<GLsizei>(abandonedTextures.size()), - abandonedTextures.data())); - abandonedTextures.clear(); - } - - if (!abandonedBuffers.empty()) { - MBGL_CHECK_ERROR(glDeleteBuffers(static_cast<GLsizei>(abandonedBuffers.size()), - abandonedBuffers.data())); - abandonedBuffers.clear(); - } -} - -} // namespace util -} // namespace mbgl diff --git a/src/mbgl/util/gl_object_store.hpp b/src/mbgl/util/gl_object_store.hpp deleted file mode 100644 index 775d4d1d01..0000000000 --- a/src/mbgl/util/gl_object_store.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef MBGL_MAP_UTIL_GL_OBJECT_STORE -#define MBGL_MAP_UTIL_GL_OBJECT_STORE - -#include <mbgl/platform/gl.hpp> -#include <mbgl/util/noncopyable.hpp> - -#include <cstdint> -#include <vector> - -namespace mbgl { -namespace util { - -class GLObjectStore : private util::noncopyable { -public: - GLObjectStore() = default; - - // Mark OpenGL objects for deletion - void abandonVAO(GLuint vao); - void abandonBuffer(GLuint buffer); - void abandonTexture(GLuint texture); - - // Actually remove the objects we marked as abandoned with the above methods. - // Only call this while the OpenGL context is exclusive to this thread. - void performCleanup(); - -private: - std::vector<GLuint> abandonedVAOs; - std::vector<GLuint> abandonedBuffers; - std::vector<GLuint> abandonedTextures; -}; - -} // namespace util -} // namespace mbgl - -#endif diff --git a/src/mbgl/util/mapbox.cpp b/src/mbgl/util/mapbox.cpp index d94a9a5f7d..7ee0f279b6 100644 --- a/src/mbgl/util/mapbox.cpp +++ b/src/mbgl/util/mapbox.cpp @@ -111,83 +111,62 @@ std::string normalizeGlyphsURL(const std::string& url, const std::string& access return baseURL + "fonts/v1/" + user + "/" + fontstack + "/" + range + "?access_token=" + accessToken; } -std::string normalizeRasterTileURL(const std::string& url) { - std::string::size_type queryIdx = url.rfind("?"); - // Trim off the right end but never touch anything before the extension dot. - std::string urlSansParams((queryIdx == std::string::npos) ? url : url.substr(0, queryIdx)); - - while (!urlSansParams.empty() && isdigit(urlSansParams.back())) { - urlSansParams.pop_back(); - } - - std::string::size_type basenameIdx = url.rfind("/", queryIdx); - std::string::size_type extensionIdx = url.rfind(".", queryIdx); - if (basenameIdx == std::string::npos || extensionIdx == std::string::npos || - basenameIdx > extensionIdx) { - // No file extension: probably not a file name we can tack a ratio onto. +std::string normalizeTileURL(const std::string& url, const std::string& accessToken) { + if (!isMapboxURL(url)) { return url; } - std::string normalizedURL(url); -#if !defined(__ANDROID__) && !defined(__APPLE__) - // Replace PNG with WebP. - if (normalizedURL.compare(extensionIdx + 1, 3, "png") == 0) { - normalizedURL.replace(extensionIdx + 1, 3, "webp"); - } -#endif // !defined(__ANDROID__) && !defined(__APPLE__) - normalizedURL.insert(extensionIdx, "{ratio}"); - return normalizedURL; + return baseURL + "v4/" + url.substr(sizeof("mapbox://tiles/") - 1) + "?access_token=" + accessToken; } - -std::string removeAccessTokenFromURL(const std::string &url) { - const size_t token_start = url.find("access_token="); - // Ensure that token exists, isn't at the front and is preceded by either & or ?. - if (token_start == std::string::npos || token_start == 0 || !(url[token_start - 1] == '&' || url[token_start - 1] == '?')) { +std::string canonicalizeTileURL(const std::string& url, SourceType type, uint16_t tileSize) { + auto tilesetStartIdx = url.find("/v4/"); + if (tilesetStartIdx == std::string::npos) { return url; } - const size_t token_end = url.find_first_of('&', token_start); - if (token_end == std::string::npos) { - // The token is the last query argument. We slice away the "&access_token=..." part - return url.substr(0, token_start - 1); - } else { - // We slice away the "access_token=...&" part. - return url.substr(0, token_start) + url.substr(token_end + 1); - } -} - -namespace { + tilesetStartIdx += sizeof("/v4/") - 1; -std::string convertMapboxDomainsToProtocol(const std::string &url) { - const size_t protocol_separator = url.find("://"); - if (protocol_separator == std::string::npos) { + auto tilesetEndIdx = url.find("/", tilesetStartIdx); + if (tilesetEndIdx == std::string::npos) { return url; } - const std::string protocol = url.substr(0, protocol_separator); - if (!(protocol == "http" || protocol == "https")) { - return url; + auto queryIdx = url.rfind("?"); + if (queryIdx == std::string::npos) { + queryIdx = url.length(); } - const size_t domain_begin = protocol_separator + 3; - const size_t path_separator = url.find("/", domain_begin); - if (path_separator == std::string::npos) { - return url; + auto basenameIdx = url.rfind("/", queryIdx); + if (basenameIdx == std::string::npos || basenameIdx == queryIdx - 1) { + basenameIdx = url.length(); + } else { + basenameIdx += 1; } - const std::string domain = url.substr(domain_begin, path_separator - domain_begin); - if (domain == "api.mapbox.com" || domain.find(".tiles.mapbox.com") != std::string::npos) { - return std::string{ "mapbox://" } + url.substr(path_separator + 1); - } else { + auto extensionIdx = url.find(".", basenameIdx); + if (extensionIdx == std::string::npos || extensionIdx == queryIdx - 1) { return url; } -} -} // end namespace + auto tileset = url.substr(tilesetStartIdx, tilesetEndIdx - tilesetStartIdx); + auto extension = url.substr(extensionIdx + 1, queryIdx - extensionIdx - 1); + +#if !defined(__ANDROID__) && !defined(__APPLE__) + // Replace PNG with WebP. + if (extension == "png") { + extension = "webp"; + } +#endif // !defined(__ANDROID__) && !defined(__APPLE__) + + std::string result = "mapbox://tiles/" + tileset + "/{z}/{x}/{y}"; + + if (type == SourceType::Raster) { + result += tileSize == 512 ? "@2x" : "{ratio}"; + } -std::string canonicalURL(const std::string &url) { - return removeAccessTokenFromURL(convertMapboxDomainsToProtocol(url)); + result += "." + extension; + return result; } } // end namespace mapbox diff --git a/src/mbgl/util/mapbox.hpp b/src/mbgl/util/mapbox.hpp index 3c44d704c7..bb0536cfa2 100644 --- a/src/mbgl/util/mapbox.hpp +++ b/src/mbgl/util/mapbox.hpp @@ -14,13 +14,10 @@ std::string normalizeSourceURL(const std::string& url, const std::string& access std::string normalizeStyleURL(const std::string& url, const std::string& accessToken); std::string normalizeSpriteURL(const std::string& url, const std::string& accessToken); std::string normalizeGlyphsURL(const std::string& url, const std::string& accessToken); -std::string normalizeRasterTileURL(const std::string& url); +std::string normalizeTileURL(const std::string& url, const std::string& accessToken); -// Canonicalizes Mapbox URLs by removing [a-d] subdomain prefixes, access tokens, and protocol. -// Note that this is close, but not exactly the reverse operation as above, as this retains certain -// information, such as the API version. It is used to cache resources retrieved from the URL, that -// sometimes have multiple valid URLs. -std::string canonicalURL(const std::string &url); +// Return a "mapbox://tiles/..." URL (suitable for normalizeTileURL) for the given Mapbox tile URL. +std::string canonicalizeTileURL(const std::string& url, SourceType, uint16_t tileSize); } // namespace mapbox } // namespace util diff --git a/src/mbgl/util/raster.cpp b/src/mbgl/util/raster.cpp index 704d05e1eb..a74b73a016 100644 --- a/src/mbgl/util/raster.cpp +++ b/src/mbgl/util/raster.cpp @@ -1,5 +1,5 @@ #include <mbgl/platform/platform.hpp> -#include <mbgl/platform/gl.hpp> +#include <mbgl/gl/gl.hpp> #include <mbgl/platform/log.hpp> #include <mbgl/util/raster.hpp> @@ -9,13 +9,14 @@ using namespace mbgl; -Raster::Raster(TexturePool& texturePool_) +Raster::Raster(gl::TexturePool& texturePool_) : texturePool(texturePool_) {} Raster::~Raster() { if (textured) { - texturePool.removeTextureID(texture); + texturePool.releaseTextureID(textureID); + textureID = 0; } } @@ -36,16 +37,16 @@ void Raster::load(PremultipliedImage image) { } -void Raster::bind(bool linear) { +void Raster::bind(bool linear, gl::GLObjectStore& glObjectStore) { if (!width || !height) { Log::Error(Event::OpenGL, "trying to bind texture without dimension"); return; } if (img.data && !textured) { - upload(); + upload(glObjectStore); } else if (textured) { - MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture)); + MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, textureID)); } GLint new_filter = linear ? GL_LINEAR : GL_NEAREST; @@ -56,10 +57,10 @@ void Raster::bind(bool linear) { } } -void Raster::upload() { +void Raster::upload(gl::GLObjectStore& glObjectStore) { if (img.data && !textured) { - texture = texturePool.getTextureID(); - MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture)); + textureID = texturePool.getTextureID(glObjectStore); + MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, textureID)); #ifndef GL_ES_VERSION_2_0 MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0)); #endif diff --git a/src/mbgl/util/raster.hpp b/src/mbgl/util/raster.hpp index 02d6615a9f..0a275a197c 100644 --- a/src/mbgl/util/raster.hpp +++ b/src/mbgl/util/raster.hpp @@ -1,8 +1,8 @@ #ifndef MBGL_UTIL_RASTER #define MBGL_UTIL_RASTER -#include <mbgl/platform/gl.hpp> -#include <mbgl/util/texture_pool.hpp> +#include <mbgl/gl/gl.hpp> +#include <mbgl/gl/texture_pool.hpp> #include <mbgl/util/image.hpp> #include <mbgl/util/ptr.hpp> #include <mbgl/util/chrono.hpp> @@ -14,17 +14,17 @@ namespace mbgl { class Raster : public std::enable_shared_from_this<Raster> { public: - Raster(TexturePool&); + Raster(gl::TexturePool&); ~Raster(); // load image data void load(PremultipliedImage); // bind current texture - void bind(bool linear = false); + void bind(bool linear, gl::GLObjectStore&); // uploads the texture if it hasn't been uploaded yet. - void upload(); + void upload(gl::GLObjectStore&); // loaded status bool isLoaded() const; @@ -38,7 +38,7 @@ public: bool textured = false; // the uploaded texture - GLuint texture = 0; + GLuint textureID = 0; // texture opacity double opacity = 0; @@ -50,7 +50,7 @@ private: bool loaded = false; // shared texture pool - TexturePool& texturePool; + gl::TexturePool& texturePool; // min/mag filter GLint filter = 0; diff --git a/src/mbgl/util/texture_pool.cpp b/src/mbgl/util/texture_pool.cpp deleted file mode 100644 index d4afb1f868..0000000000 --- a/src/mbgl/util/texture_pool.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include <mbgl/util/texture_pool.hpp> - -#include <mbgl/util/gl_object_store.hpp> -#include <mbgl/util/thread_context.hpp> - -#include <vector> - -const GLsizei TextureMax = 64; - -using namespace mbgl; - -GLuint TexturePool::getTextureID() { - if (texture_ids.empty()) { - GLuint new_texture_ids[TextureMax]; - MBGL_CHECK_ERROR(glGenTextures(TextureMax, new_texture_ids)); - for (GLuint id = 0; id < TextureMax; id++) { - texture_ids.insert(new_texture_ids[id]); - } - } - - GLuint id = 0; - - if (!texture_ids.empty()) { - std::set<GLuint>::iterator id_iterator = texture_ids.begin(); - id = *id_iterator; - texture_ids.erase(id_iterator); - } - - return id; -} - -void TexturePool::removeTextureID(GLuint texture_id) { - bool needs_clear = false; - - texture_ids.insert(texture_id); - - if (texture_ids.size() > TextureMax) { - needs_clear = true; - } - - if (needs_clear) { - // TODO: We need to find a better way to deal with texture pool cleanup -// clearTextureIDs(); - } -} - -void TexturePool::clearTextureIDs() { - auto getGLObjectStore = util::ThreadContext::getGLObjectStore(); - for (auto texture : texture_ids) { - getGLObjectStore->abandonTexture(texture); - } - texture_ids.clear(); -} diff --git a/src/mbgl/util/texture_pool.hpp b/src/mbgl/util/texture_pool.hpp deleted file mode 100644 index a980584c13..0000000000 --- a/src/mbgl/util/texture_pool.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef MBGL_UTIL_TEXTUREPOOL -#define MBGL_UTIL_TEXTUREPOOL - -#include <mbgl/util/noncopyable.hpp> -#include <mbgl/platform/gl.hpp> - -#include <set> -#include <mutex> - -namespace mbgl { - -class TexturePool : private util::noncopyable { - -public: - GLuint getTextureID(); - void removeTextureID(GLuint texture_id); - void clearTextureIDs(); - -private: - std::set<GLuint> texture_ids; -}; - -} // namespace mbgl - -#endif diff --git a/src/mbgl/util/thread_context.cpp b/src/mbgl/util/thread_context.cpp index b611b3d023..d6ddda2e8e 100644 --- a/src/mbgl/util/thread_context.cpp +++ b/src/mbgl/util/thread_context.cpp @@ -44,38 +44,6 @@ ThreadPriority ThreadContext::getPriority() { } } -FileSource* ThreadContext::getFileSource() { - if (current.get() != nullptr) { - return current.get()->fileSource; - } else { - return nullptr; - } -} - -void ThreadContext::setFileSource(FileSource* fileSource) { - if (current.get() != nullptr) { - current.get()->fileSource = fileSource; - } else { - throw std::runtime_error("Current thread has no current ThreadContext."); - } -} - -GLObjectStore* ThreadContext::getGLObjectStore() { - if (current.get() != nullptr) { - return current.get()->glObjectStore; - } else { - return nullptr; - } -} - -void ThreadContext::setGLObjectStore(GLObjectStore* glObjectStore) { - if (current.get() != nullptr) { - current.get()->glObjectStore = glObjectStore; - } else { - throw std::runtime_error("Current thread has no current ThreadContext."); - } -} - class MainThreadContextRegistrar { public: MainThreadContextRegistrar() : context("Main", ThreadType::Main, ThreadPriority::Regular) { diff --git a/src/mbgl/util/thread_context.hpp b/src/mbgl/util/thread_context.hpp index 2b22b2faf4..dea98fe3fa 100644 --- a/src/mbgl/util/thread_context.hpp +++ b/src/mbgl/util/thread_context.hpp @@ -6,13 +6,8 @@ #include <thread> namespace mbgl { - -class FileSource; - namespace util { -class GLObjectStore; - enum class ThreadPriority : bool { Regular, Low, @@ -35,17 +30,9 @@ public: static std::string getName(); static ThreadPriority getPriority(); - static FileSource* getFileSource(); - static void setFileSource(FileSource* fileSource); - static GLObjectStore* getGLObjectStore(); - static void setGLObjectStore(GLObjectStore* glObjectStore); - std::string name; ThreadType type; ThreadPriority priority; - - FileSource* fileSource = nullptr; - GLObjectStore* glObjectStore = nullptr; }; } // namespace util diff --git a/src/mbgl/util/tile_coordinate.hpp b/src/mbgl/util/tile_coordinate.hpp index 4710e08d0a..a989bef0c9 100644 --- a/src/mbgl/util/tile_coordinate.hpp +++ b/src/mbgl/util/tile_coordinate.hpp @@ -5,23 +5,11 @@ namespace mbgl { -struct TileCoordinate { +class TileCoordinate { +public: double column; double row; double zoom; - - TileCoordinate(double column_, double row_, double zoom_) : - column(column_), row(row_), zoom(zoom_) {} - - TileCoordinate zoomTo(double targetZoom) { - double scale = std::pow(2, targetZoom - zoom); - return { column * scale, row * scale, targetZoom }; - } - - TileCoordinate operator-(TileCoordinate c) { - c = c.zoomTo(zoom); - return { column - c.column, row - c.row, zoom }; - }; }; } // namespace mbgl diff --git a/src/mbgl/util/tile_cover.cpp b/src/mbgl/util/tile_cover.cpp index 803aa53eee..e77ea469a7 100644 --- a/src/mbgl/util/tile_cover.cpp +++ b/src/mbgl/util/tile_cover.cpp @@ -1,7 +1,8 @@ #include <mbgl/util/tile_cover.hpp> #include <mbgl/util/vec.hpp> -#include <mbgl/util/box.hpp> #include <mbgl/util/tile_coordinate.hpp> +#include <mbgl/util/constants.hpp> +#include <mbgl/map/transform_state.hpp> namespace mbgl { @@ -66,7 +67,27 @@ static void scanTriangle(const mbgl::vec2<double> a, const mbgl::vec2<double> b, if (bc.dy) scanSpans(ca, bc, ymin, ymax, scanLine); } -std::forward_list<TileID> tileCover(int8_t z, const mbgl::box &bounds, int8_t actualZ) { +int32_t coveringZoomLevel(double zoom, SourceType type, uint16_t tileSize) { + zoom += std::log(util::tileSize / tileSize) / std::log(2); + if (type == SourceType::Raster || type == SourceType::Video) { + return ::round(zoom); + } else { + return std::floor(zoom); + } +} + +static mbgl::vec2<double> zoomTo(const TileCoordinate& c, double z) { + double scale = std::pow(2, z - c.zoom); + return { c.column * scale, c.row * scale }; +} + +std::vector<TileID> tileCover(const TileCoordinate& tl_, + const TileCoordinate& tr_, + const TileCoordinate& br_, + const TileCoordinate& bl_, + const TileCoordinate& center, + int32_t z, + int32_t actualZ) { int32_t tiles = 1 << z; std::forward_list<mbgl::TileID> t; @@ -79,10 +100,11 @@ std::forward_list<TileID> tileCover(int8_t z, const mbgl::box &bounds, int8_t ac } }; - mbgl::vec2<double> tl = { bounds.tl.column, bounds.tl.row }; - mbgl::vec2<double> tr = { bounds.tr.column, bounds.tr.row }; - mbgl::vec2<double> br = { bounds.br.column, bounds.br.row }; - mbgl::vec2<double> bl = { bounds.bl.column, bounds.bl.row }; + mbgl::vec2<double> tl = zoomTo(tl_, z); + mbgl::vec2<double> tr = zoomTo(tr_, z); + mbgl::vec2<double> br = zoomTo(br_, z); + mbgl::vec2<double> bl = zoomTo(bl_, z); + mbgl::vec2<double> c = zoomTo(center, z); // Divide the screen up in two triangles and scan each of them: // \---+ @@ -94,7 +116,46 @@ std::forward_list<TileID> tileCover(int8_t z, const mbgl::box &bounds, int8_t ac t.sort(); t.unique(); - return t; + t.sort([&](const TileID& a, const TileID& b) { + // Sorts by distance from the box center + return std::fabs(a.x - c.x) + std::fabs(a.y - c.y) < + std::fabs(b.x - c.x) + std::fabs(b.y - c.y); + }); + + return std::vector<TileID>(t.begin(), t.end()); +} + +std::vector<TileID> tileCover(const LatLngBounds& bounds_, int32_t z, int32_t actualZ) { + if (bounds_.isEmpty() || + bounds_.south() > util::LATITUDE_MAX || + bounds_.north() < -util::LATITUDE_MAX) { + return {}; + } + + LatLngBounds bounds = LatLngBounds::hull( + { std::max(bounds_.south(), -util::LATITUDE_MAX), bounds_.west() }, + { std::min(bounds_.north(), util::LATITUDE_MAX), bounds_.east() }); + + const TransformState state; + return tileCover( + state.latLngToCoordinate(bounds.northwest()), + state.latLngToCoordinate(bounds.northeast()), + state.latLngToCoordinate(bounds.southeast()), + state.latLngToCoordinate(bounds.southwest()), + state.latLngToCoordinate(bounds.center()), + z, actualZ); +} + +std::vector<TileID> tileCover(const TransformState& state, int32_t z, int32_t actualZ) { + const double w = state.getWidth(); + const double h = state.getHeight(); + return tileCover( + state.pointToCoordinate({ 0, 0 }), + state.pointToCoordinate({ w, 0 }), + state.pointToCoordinate({ w, h }), + state.pointToCoordinate({ 0, h }), + state.pointToCoordinate({ w/2, h/2 }), + z, actualZ); } } // namespace mbgl diff --git a/src/mbgl/util/tile_cover.hpp b/src/mbgl/util/tile_cover.hpp index 0514c36b62..a489964abf 100644 --- a/src/mbgl/util/tile_cover.hpp +++ b/src/mbgl/util/tile_cover.hpp @@ -2,13 +2,19 @@ #define MBGL_UTIL_TILE_COVER #include <mbgl/map/tile_id.hpp> -#include <mbgl/util/box.hpp> +#include <mbgl/style/types.hpp> -#include <forward_list> +#include <vector> namespace mbgl { -std::forward_list<TileID> tileCover(int8_t z, const box& bounds, int8_t actualZ); +class TransformState; +class LatLngBounds; + +int32_t coveringZoomLevel(double z, SourceType type, uint16_t tileSize); + +std::vector<TileID> tileCover(const TransformState&, int32_t z, int32_t actualZ); +std::vector<TileID> tileCover(const LatLngBounds&, int32_t z, int32_t actualZ); } // namespace mbgl diff --git a/src/mbgl/util/worker.cpp b/src/mbgl/util/worker.cpp index fe8ee81779..bc6e4be3db 100644 --- a/src/mbgl/util/worker.cpp +++ b/src/mbgl/util/worker.cpp @@ -3,7 +3,7 @@ #include <mbgl/util/work_request.hpp> #include <mbgl/platform/platform.hpp> #include <mbgl/renderer/raster_bucket.hpp> -#include <mbgl/map/geometry_tile.hpp> +#include <mbgl/tile/geometry_tile.hpp> #include <mbgl/style/style_layer.hpp> #include <cassert> diff --git a/src/mbgl/util/worker.hpp b/src/mbgl/util/worker.hpp index d72438bc75..96a7b27885 100644 --- a/src/mbgl/util/worker.hpp +++ b/src/mbgl/util/worker.hpp @@ -3,7 +3,7 @@ #include <mbgl/util/noncopyable.hpp> #include <mbgl/util/thread.hpp> -#include <mbgl/map/tile_worker.hpp> +#include <mbgl/tile/tile_worker.hpp> #include <functional> #include <memory> |